PostgreSQL Source Code  git master
jsonfuncs.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * jsonfuncs.c
4  * Functions to process JSON data types.
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/jsonfuncs.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include <limits.h>
18 
19 #include "access/htup_details.h"
20 #include "catalog/pg_type.h"
21 #include "common/jsonapi.h"
22 #include "common/string.h"
23 #include "fmgr.h"
24 #include "funcapi.h"
25 #include "lib/stringinfo.h"
26 #include "mb/pg_wchar.h"
27 #include "miscadmin.h"
28 #include "nodes/miscnodes.h"
29 #include "utils/array.h"
30 #include "utils/builtins.h"
31 #include "utils/fmgroids.h"
32 #include "utils/hsearch.h"
33 #include "utils/json.h"
34 #include "utils/jsonb.h"
35 #include "utils/jsonfuncs.h"
36 #include "utils/lsyscache.h"
37 #include "utils/memutils.h"
38 #include "utils/syscache.h"
39 #include "utils/typcache.h"
40 
41 /* Operations available for setPath */
42 #define JB_PATH_CREATE 0x0001
43 #define JB_PATH_DELETE 0x0002
44 #define JB_PATH_REPLACE 0x0004
45 #define JB_PATH_INSERT_BEFORE 0x0008
46 #define JB_PATH_INSERT_AFTER 0x0010
47 #define JB_PATH_CREATE_OR_INSERT \
48  (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
49 #define JB_PATH_FILL_GAPS 0x0020
50 #define JB_PATH_CONSISTENT_POSITION 0x0040
51 
52 /* state for json_object_keys */
53 typedef struct OkeysState
54 {
56  char **result;
61 
62 /* state for iterate_json_values function */
64 {
66  JsonIterateStringValuesAction action; /* an action that will be applied
67  * to each json value */
68  void *action_state; /* any necessary context for iteration */
69  uint32 flags; /* what kind of elements from a json we want
70  * to iterate */
72 
73 /* state for transform_json_string_values function */
75 {
77  StringInfo strval; /* resulting json */
78  JsonTransformStringValuesAction action; /* an action that will be applied
79  * to each json value */
80  void *action_state; /* any necessary context for transformation */
82 
83 /* state for json_get* functions */
84 typedef struct GetState
85 {
88  char *result_start;
91  int npath; /* length of each path-related array */
92  char **path_names; /* field name(s) being sought */
93  int *path_indexes; /* array index(es) being sought */
94  bool *pathok; /* is path matched to current depth? */
95  int *array_cur_index; /* current element index at each path
96  * level */
98 
99 /* state for json_array_length */
100 typedef struct AlenState
101 {
103  int count;
105 
106 /* state for json_each */
107 typedef struct EachState
108 {
118 
119 /* state for json_array_elements */
120 typedef struct ElementsState
121 {
123  const char *function_name;
132 
133 /* state for get_json_object_as_hash */
134 typedef struct JHashState
135 {
137  const char *function_name;
143 
144 /* hashtable element */
145 typedef struct JsonHashEntry
146 {
147  char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
148  char *val;
151 
152 /* structure to cache type I/O metadata needed for populate_scalar() */
153 typedef struct ScalarIOData
154 {
158 
159 /* these two structures are used recursively */
160 typedef struct ColumnIOData ColumnIOData;
161 typedef struct RecordIOData RecordIOData;
162 
163 /* structure to cache metadata needed for populate_array() */
164 typedef struct ArrayIOData
165 {
166  ColumnIOData *element_info; /* metadata cache */
167  Oid element_type; /* array element type id */
168  int32 element_typmod; /* array element type modifier */
170 
171 /* structure to cache metadata needed for populate_composite() */
172 typedef struct CompositeIOData
173 {
174  /*
175  * We use pointer to a RecordIOData here because variable-length struct
176  * RecordIOData can't be used directly in ColumnIOData.io union
177  */
178  RecordIOData *record_io; /* metadata cache for populate_record() */
179  TupleDesc tupdesc; /* cached tuple descriptor */
180  /* these fields differ from target type only if domain over composite: */
181  Oid base_typid; /* base type id */
182  int32 base_typmod; /* base type modifier */
183  /* this field is used only if target type is domain over composite: */
184  void *domain_info; /* opaque cache for domain checks */
186 
187 /* structure to cache metadata needed for populate_domain() */
188 typedef struct DomainIOData
189 {
190  ColumnIOData *base_io; /* metadata cache */
191  Oid base_typid; /* base type id */
192  int32 base_typmod; /* base type modifier */
193  void *domain_info; /* opaque cache for domain checks */
195 
196 /* enumeration type categories */
197 typedef enum TypeCat
198 {
203  TYPECAT_DOMAIN = 'd'
205 
206 /* these two are stolen from hstore / record_out, used in populate_record* */
207 
208 /* structure to cache record metadata needed for populate_record_field() */
209 struct ColumnIOData
210 {
211  Oid typid; /* column type id */
212  int32 typmod; /* column type modifier */
213  TypeCat typcat; /* column type category */
214  ScalarIOData scalar_io; /* metadata cache for direct conversion
215  * through input function */
216  union
217  {
221  } io; /* metadata cache for various column type
222  * categories */
223 };
224 
225 /* structure to cache record metadata needed for populate_record() */
226 struct RecordIOData
227 {
230  int ncolumns;
232 };
233 
234 /* per-query cache for populate_record_worker and populate_recordset_worker */
235 typedef struct PopulateRecordCache
236 {
237  Oid argtype; /* declared type of the record argument */
238  ColumnIOData c; /* metadata cache for populate_composite() */
239  MemoryContext fn_mcxt; /* where this is stored */
241 
242 /* per-call state for populate_recordset */
244 {
246  const char *function_name;
255 
256 /* common data for populate_array_json() and populate_array_dim_jsonb() */
257 typedef struct PopulateArrayContext
258 {
259  ArrayBuildState *astate; /* array build state */
260  ArrayIOData *aio; /* metadata cache */
261  MemoryContext acxt; /* array build memory context */
262  MemoryContext mcxt; /* cache memory context */
263  const char *colname; /* for diagnostics only */
264  int *dims; /* dimensions */
265  int *sizes; /* current dimension counters */
266  int ndims; /* number of dimensions */
268 
269 /* state for populate_array_json() */
270 typedef struct PopulateArrayState
271 {
272  JsonLexContext *lex; /* json lexer */
273  PopulateArrayContext *ctx; /* context */
274  char *element_start; /* start of the current array element */
275  char *element_scalar; /* current array element token if it is a
276  * scalar */
277  JsonTokenType element_type; /* current array element type */
279 
280 /* state for json_strip_nulls */
281 typedef struct StripnullState
282 {
287 
288 /* structure for generalized json/jsonb value passing */
289 typedef struct JsValue
290 {
291  bool is_json; /* json/jsonb */
292  union
293  {
294  struct
295  {
296  char *str; /* json string */
297  int len; /* json string length or -1 if null-terminated */
298  JsonTokenType type; /* json type */
299  } json; /* json value */
300 
301  JsonbValue *jsonb; /* jsonb value */
302  } val;
304 
305 typedef struct JsObject
306 {
307  bool is_json; /* json/jsonb */
308  union
309  {
312  } val;
314 
315 /* useful macros for testing JsValue properties */
316 #define JsValueIsNull(jsv) \
317  ((jsv)->is_json ? \
318  (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
319  (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
320 
321 #define JsValueIsString(jsv) \
322  ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
323  : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
324 
325 #define JsObjectIsEmpty(jso) \
326  ((jso)->is_json \
327  ? hash_get_num_entries((jso)->val.json_hash) == 0 \
328  : ((jso)->val.jsonb_cont == NULL || \
329  JsonContainerSize((jso)->val.jsonb_cont) == 0))
330 
331 #define JsObjectFree(jso) \
332  do { \
333  if ((jso)->is_json) \
334  hash_destroy((jso)->val.json_hash); \
335  } while (0)
336 
337 static int report_json_context(JsonLexContext *lex);
338 
339 /* semantic action functions for json_object_keys */
340 static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull);
342 static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype);
343 
344 /* semantic action functions for json_get* functions */
347 static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull);
348 static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull);
351 static JsonParseErrorType get_array_element_start(void *state, bool isnull);
352 static JsonParseErrorType get_array_element_end(void *state, bool isnull);
353 static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype);
354 
355 /* common worker function for json getter functions */
356 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
357 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
358  bool normalize_results);
359 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
360 static text *JsonbValueAsText(JsonbValue *v);
361 
362 /* semantic action functions for json_array_length */
364 static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype);
365 static JsonParseErrorType alen_array_element_start(void *state, bool isnull);
366 
367 /* common workers for json{b}_each* functions */
368 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
369 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
370  bool as_text);
371 
372 /* semantic action functions for json_each */
373 static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull);
374 static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull);
376 static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype);
377 
378 /* common workers for json{b}_array_elements_* functions */
379 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
380  bool as_text);
381 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
382  bool as_text);
383 
384 /* semantic action functions for json_array_elements */
386 static JsonParseErrorType elements_array_element_start(void *state, bool isnull);
387 static JsonParseErrorType elements_array_element_end(void *state, bool isnull);
388 static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype);
389 
390 /* turn a json object into a hash table */
391 static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname);
392 
393 /* semantic actions for populate_array_json */
395 static JsonParseErrorType populate_array_array_end(void *_state);
396 static JsonParseErrorType populate_array_element_start(void *_state, bool isnull);
397 static JsonParseErrorType populate_array_element_end(void *_state, bool isnull);
398 static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
399 
400 /* semantic action functions for get_json_object_as_hash */
401 static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull);
402 static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull);
404 static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype);
405 
406 /* semantic action functions for populate_recordset */
407 static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull);
408 static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull);
409 static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
414 
415 /* semantic action functions for json_strip_nulls */
420 static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull);
421 static JsonParseErrorType sn_array_element_start(void *state, bool isnull);
422 static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype);
423 
424 /* worker functions for populate_record, to_record, populate_recordset and to_recordset */
425 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
426  bool is_json, bool have_record_arg);
427 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
428  bool is_json, bool have_record_arg);
429 
430 /* helper functions for populate_record[set] */
431 static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p,
432  HeapTupleHeader defaultval, MemoryContext mcxt,
433  JsObject *obj);
435  const char *funcname,
436  PopulateRecordCache *cache);
438  const char *funcname,
439  PopulateRecordCache *cache);
440 static void JsValueToJsObject(JsValue *jsv, JsObject *jso);
441 static Datum populate_composite(CompositeIOData *io, Oid typid,
442  const char *colname, MemoryContext mcxt,
443  HeapTupleHeader defaultval, JsValue *jsv, bool isnull);
444 static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv);
445 static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod,
446  MemoryContext mcxt, bool need_scalar);
447 static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod,
448  const char *colname, MemoryContext mcxt, Datum defaultval,
449  JsValue *jsv, bool *isnull);
450 static RecordIOData *allocate_record_info(MemoryContext mcxt, int ncolumns);
451 static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv);
453 static void populate_array_json(PopulateArrayContext *ctx, char *json, int len);
455  int ndim);
457 static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims);
458 static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim);
459 static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv);
460 static Datum populate_array(ArrayIOData *aio, const char *colname,
461  MemoryContext mcxt, JsValue *jsv);
462 static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname,
463  MemoryContext mcxt, JsValue *jsv, bool isnull);
464 
465 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
468 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
469  bool *path_nulls, int path_len,
470  JsonbParseState **st, int level, JsonbValue *newval,
471  int op_type);
472 static void setPathObject(JsonbIterator **it, Datum *path_elems,
473  bool *path_nulls, int path_len, JsonbParseState **st,
474  int level,
475  JsonbValue *newval, uint32 npairs, int op_type);
476 static void setPathArray(JsonbIterator **it, Datum *path_elems,
477  bool *path_nulls, int path_len, JsonbParseState **st,
478  int level,
479  JsonbValue *newval, uint32 nelems, int op_type);
480 
481 /* function supporting iterate_json_values */
482 static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
483 static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull);
484 
485 /* functions supporting transform_json_string_values */
490 static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull);
492 static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
493 
494 
495 /*
496  * pg_parse_json_or_errsave
497  *
498  * This function is like pg_parse_json, except that it does not return a
499  * JsonParseErrorType. Instead, in case of any failure, this function will
500  * save error data into *escontext if that's an ErrorSaveContext, otherwise
501  * ereport(ERROR).
502  *
503  * Returns a boolean indicating success or failure (failure will only be
504  * returned when escontext is an ErrorSaveContext).
505  */
506 bool
508  Node *escontext)
509 {
510  JsonParseErrorType result;
511 
512  result = pg_parse_json(lex, sem);
513  if (result != JSON_SUCCESS)
514  {
515  json_errsave_error(result, lex, escontext);
516  return false;
517  }
518  return true;
519 }
520 
521 /*
522  * makeJsonLexContext
523  *
524  * This is like makeJsonLexContextCstringLen, but it accepts a text value
525  * directly.
526  */
528 makeJsonLexContext(text *json, bool need_escapes)
529 {
530  /*
531  * Most callers pass a detoasted datum, but it's not clear that they all
532  * do. pg_detoast_datum_packed() is cheap insurance.
533  */
534  json = pg_detoast_datum_packed(json);
535 
537  VARSIZE_ANY_EXHDR(json),
539  need_escapes);
540 }
541 
542 /*
543  * SQL function json_object_keys
544  *
545  * Returns the set of keys for the object argument.
546  *
547  * This SRF operates in value-per-call mode. It processes the
548  * object during the first call, and the keys are simply stashed
549  * in an array, whose size is expanded as necessary. This is probably
550  * safe enough for a list of keys of a single object, since they are
551  * limited in size to NAMEDATALEN and the number of keys is unlikely to
552  * be so huge that it has major memory implications.
553  */
554 Datum
556 {
557  FuncCallContext *funcctx;
558  OkeysState *state;
559 
560  if (SRF_IS_FIRSTCALL())
561  {
562  MemoryContext oldcontext;
563  Jsonb *jb = PG_GETARG_JSONB_P(0);
564  bool skipNested = false;
565  JsonbIterator *it;
566  JsonbValue v;
568 
569  if (JB_ROOT_IS_SCALAR(jb))
570  ereport(ERROR,
571  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
572  errmsg("cannot call %s on a scalar",
573  "jsonb_object_keys")));
574  else if (JB_ROOT_IS_ARRAY(jb))
575  ereport(ERROR,
576  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
577  errmsg("cannot call %s on an array",
578  "jsonb_object_keys")));
579 
580  funcctx = SRF_FIRSTCALL_INIT();
581  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
582 
583  state = palloc(sizeof(OkeysState));
584 
585  state->result_size = JB_ROOT_COUNT(jb);
586  state->result_count = 0;
587  state->sent_count = 0;
588  state->result = palloc(state->result_size * sizeof(char *));
589 
590  it = JsonbIteratorInit(&jb->root);
591 
592  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
593  {
594  skipNested = true;
595 
596  if (r == WJB_KEY)
597  {
598  char *cstr;
599 
600  cstr = palloc(v.val.string.len + 1 * sizeof(char));
601  memcpy(cstr, v.val.string.val, v.val.string.len);
602  cstr[v.val.string.len] = '\0';
603  state->result[state->result_count++] = cstr;
604  }
605  }
606 
607  MemoryContextSwitchTo(oldcontext);
608  funcctx->user_fctx = (void *) state;
609  }
610 
611  funcctx = SRF_PERCALL_SETUP();
612  state = (OkeysState *) funcctx->user_fctx;
613 
614  if (state->sent_count < state->result_count)
615  {
616  char *nxt = state->result[state->sent_count++];
617 
618  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
619  }
620 
621  SRF_RETURN_DONE(funcctx);
622 }
623 
624 /*
625  * Report a JSON error.
626  */
627 void
629  Node *escontext)
630 {
634  errsave(escontext,
635  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
636  errmsg("unsupported Unicode escape sequence"),
638  report_json_context(lex)));
639  else if (error == JSON_SEM_ACTION_FAILED)
640  {
641  /* semantic action function had better have reported something */
642  if (!SOFT_ERROR_OCCURRED(escontext))
643  elog(ERROR, "JSON semantic action function did not provide error information");
644  }
645  else
646  errsave(escontext,
647  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
648  errmsg("invalid input syntax for type %s", "json"),
650  report_json_context(lex)));
651 }
652 
653 /*
654  * Report a CONTEXT line for bogus JSON input.
655  *
656  * lex->token_terminator must be set to identify the spot where we detected
657  * the error. Note that lex->token_start might be NULL, in case we recognized
658  * error at EOF.
659  *
660  * The return value isn't meaningful, but we make it non-void so that this
661  * can be invoked inside ereport().
662  */
663 static int
665 {
666  const char *context_start;
667  const char *context_end;
668  const char *line_start;
669  char *ctxt;
670  int ctxtlen;
671  const char *prefix;
672  const char *suffix;
673 
674  /* Choose boundaries for the part of the input we will display */
675  line_start = lex->line_start;
676  context_start = line_start;
677  context_end = lex->token_terminator;
678 
679  /* Advance until we are close enough to context_end */
680  while (context_end - context_start >= 50)
681  {
682  /* Advance to next multibyte character */
683  if (IS_HIGHBIT_SET(*context_start))
684  context_start += pg_mblen(context_start);
685  else
686  context_start++;
687  }
688 
689  /*
690  * We add "..." to indicate that the excerpt doesn't start at the
691  * beginning of the line ... but if we're within 3 characters of the
692  * beginning of the line, we might as well just show the whole line.
693  */
694  if (context_start - line_start <= 3)
695  context_start = line_start;
696 
697  /* Get a null-terminated copy of the data to present */
698  ctxtlen = context_end - context_start;
699  ctxt = palloc(ctxtlen + 1);
700  memcpy(ctxt, context_start, ctxtlen);
701  ctxt[ctxtlen] = '\0';
702 
703  /*
704  * Show the context, prefixing "..." if not starting at start of line, and
705  * suffixing "..." if not ending at end of line.
706  */
707  prefix = (context_start > line_start) ? "..." : "";
708  suffix = (lex->token_type != JSON_TOKEN_END &&
709  context_end - lex->input < lex->input_length &&
710  *context_end != '\n' && *context_end != '\r') ? "..." : "";
711 
712  return errcontext("JSON data, line %d: %s%s%s",
713  lex->line_number, prefix, ctxt, suffix);
714 }
715 
716 
717 Datum
719 {
720  FuncCallContext *funcctx;
721  OkeysState *state;
722 
723  if (SRF_IS_FIRSTCALL())
724  {
725  text *json = PG_GETARG_TEXT_PP(0);
726  JsonLexContext *lex = makeJsonLexContext(json, true);
727  JsonSemAction *sem;
728  MemoryContext oldcontext;
729 
730  funcctx = SRF_FIRSTCALL_INIT();
731  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
732 
733  state = palloc(sizeof(OkeysState));
734  sem = palloc0(sizeof(JsonSemAction));
735 
736  state->lex = lex;
737  state->result_size = 256;
738  state->result_count = 0;
739  state->sent_count = 0;
740  state->result = palloc(256 * sizeof(char *));
741 
742  sem->semstate = (void *) state;
744  sem->scalar = okeys_scalar;
746  /* remainder are all NULL, courtesy of palloc0 above */
747 
748  pg_parse_json_or_ereport(lex, sem);
749  /* keys are now in state->result */
750 
751  pfree(lex->strval->data);
752  pfree(lex->strval);
753  pfree(lex);
754  pfree(sem);
755 
756  MemoryContextSwitchTo(oldcontext);
757  funcctx->user_fctx = (void *) state;
758  }
759 
760  funcctx = SRF_PERCALL_SETUP();
761  state = (OkeysState *) funcctx->user_fctx;
762 
763  if (state->sent_count < state->result_count)
764  {
765  char *nxt = state->result[state->sent_count++];
766 
767  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
768  }
769 
770  SRF_RETURN_DONE(funcctx);
771 }
772 
773 static JsonParseErrorType
774 okeys_object_field_start(void *state, char *fname, bool isnull)
775 {
776  OkeysState *_state = (OkeysState *) state;
777 
778  /* only collecting keys for the top level object */
779  if (_state->lex->lex_level != 1)
780  return JSON_SUCCESS;
781 
782  /* enlarge result array if necessary */
783  if (_state->result_count >= _state->result_size)
784  {
785  _state->result_size *= 2;
786  _state->result = (char **)
787  repalloc(_state->result, sizeof(char *) * _state->result_size);
788  }
789 
790  /* save a copy of the field name */
791  _state->result[_state->result_count++] = pstrdup(fname);
792 
793  return JSON_SUCCESS;
794 }
795 
796 static JsonParseErrorType
798 {
799  OkeysState *_state = (OkeysState *) state;
800 
801  /* top level must be a json object */
802  if (_state->lex->lex_level == 0)
803  ereport(ERROR,
804  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
805  errmsg("cannot call %s on an array",
806  "json_object_keys")));
807 
808  return JSON_SUCCESS;
809 }
810 
811 static JsonParseErrorType
812 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
813 {
814  OkeysState *_state = (OkeysState *) state;
815 
816  /* top level must be a json object */
817  if (_state->lex->lex_level == 0)
818  ereport(ERROR,
819  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
820  errmsg("cannot call %s on a scalar",
821  "json_object_keys")));
822 
823  return JSON_SUCCESS;
824 }
825 
826 /*
827  * json and jsonb getter functions
828  * these implement the -> ->> #> and #>> operators
829  * and the json{b?}_extract_path*(json, text, ...) functions
830  */
831 
832 
833 Datum
835 {
836  text *json = PG_GETARG_TEXT_PP(0);
837  text *fname = PG_GETARG_TEXT_PP(1);
838  char *fnamestr = text_to_cstring(fname);
839  text *result;
840 
841  result = get_worker(json, &fnamestr, NULL, 1, false);
842 
843  if (result != NULL)
844  PG_RETURN_TEXT_P(result);
845  else
846  PG_RETURN_NULL();
847 }
848 
849 Datum
851 {
852  Jsonb *jb = PG_GETARG_JSONB_P(0);
853  text *key = PG_GETARG_TEXT_PP(1);
854  JsonbValue *v;
855  JsonbValue vbuf;
856 
857  if (!JB_ROOT_IS_OBJECT(jb))
858  PG_RETURN_NULL();
859 
861  VARDATA_ANY(key),
863  &vbuf);
864 
865  if (v != NULL)
867 
868  PG_RETURN_NULL();
869 }
870 
871 Datum
873 {
874  text *json = PG_GETARG_TEXT_PP(0);
875  text *fname = PG_GETARG_TEXT_PP(1);
876  char *fnamestr = text_to_cstring(fname);
877  text *result;
878 
879  result = get_worker(json, &fnamestr, NULL, 1, true);
880 
881  if (result != NULL)
882  PG_RETURN_TEXT_P(result);
883  else
884  PG_RETURN_NULL();
885 }
886 
887 Datum
889 {
890  Jsonb *jb = PG_GETARG_JSONB_P(0);
891  text *key = PG_GETARG_TEXT_PP(1);
892  JsonbValue *v;
893  JsonbValue vbuf;
894 
895  if (!JB_ROOT_IS_OBJECT(jb))
896  PG_RETURN_NULL();
897 
899  VARDATA_ANY(key),
901  &vbuf);
902 
903  if (v != NULL && v->type != jbvNull)
905 
906  PG_RETURN_NULL();
907 }
908 
909 Datum
911 {
912  text *json = PG_GETARG_TEXT_PP(0);
913  int element = PG_GETARG_INT32(1);
914  text *result;
915 
916  result = get_worker(json, NULL, &element, 1, false);
917 
918  if (result != NULL)
919  PG_RETURN_TEXT_P(result);
920  else
921  PG_RETURN_NULL();
922 }
923 
924 Datum
926 {
927  Jsonb *jb = PG_GETARG_JSONB_P(0);
928  int element = PG_GETARG_INT32(1);
929  JsonbValue *v;
930 
931  if (!JB_ROOT_IS_ARRAY(jb))
932  PG_RETURN_NULL();
933 
934  /* Handle negative subscript */
935  if (element < 0)
936  {
937  uint32 nelements = JB_ROOT_COUNT(jb);
938 
939  if (-element > nelements)
940  PG_RETURN_NULL();
941  else
942  element += nelements;
943  }
944 
946  if (v != NULL)
948 
949  PG_RETURN_NULL();
950 }
951 
952 Datum
954 {
955  text *json = PG_GETARG_TEXT_PP(0);
956  int element = PG_GETARG_INT32(1);
957  text *result;
958 
959  result = get_worker(json, NULL, &element, 1, true);
960 
961  if (result != NULL)
962  PG_RETURN_TEXT_P(result);
963  else
964  PG_RETURN_NULL();
965 }
966 
967 Datum
969 {
970  Jsonb *jb = PG_GETARG_JSONB_P(0);
971  int element = PG_GETARG_INT32(1);
972  JsonbValue *v;
973 
974  if (!JB_ROOT_IS_ARRAY(jb))
975  PG_RETURN_NULL();
976 
977  /* Handle negative subscript */
978  if (element < 0)
979  {
980  uint32 nelements = JB_ROOT_COUNT(jb);
981 
982  if (-element > nelements)
983  PG_RETURN_NULL();
984  else
985  element += nelements;
986  }
987 
989 
990  if (v != NULL && v->type != jbvNull)
992 
993  PG_RETURN_NULL();
994 }
995 
996 Datum
998 {
999  return get_path_all(fcinfo, false);
1000 }
1001 
1002 Datum
1004 {
1005  return get_path_all(fcinfo, true);
1006 }
1007 
1008 /*
1009  * common routine for extract_path functions
1010  */
1011 static Datum
1012 get_path_all(FunctionCallInfo fcinfo, bool as_text)
1013 {
1014  text *json = PG_GETARG_TEXT_PP(0);
1015  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1016  text *result;
1017  Datum *pathtext;
1018  bool *pathnulls;
1019  int npath;
1020  char **tpath;
1021  int *ipath;
1022  int i;
1023 
1024  /*
1025  * If the array contains any null elements, return NULL, on the grounds
1026  * that you'd have gotten NULL if any RHS value were NULL in a nested
1027  * series of applications of the -> operator. (Note: because we also
1028  * return NULL for error cases such as no-such-field, this is true
1029  * regardless of the contents of the rest of the array.)
1030  */
1031  if (array_contains_nulls(path))
1032  PG_RETURN_NULL();
1033 
1034  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1035 
1036  tpath = palloc(npath * sizeof(char *));
1037  ipath = palloc(npath * sizeof(int));
1038 
1039  for (i = 0; i < npath; i++)
1040  {
1041  Assert(!pathnulls[i]);
1042  tpath[i] = TextDatumGetCString(pathtext[i]);
1043 
1044  /*
1045  * we have no idea at this stage what structure the document is so
1046  * just convert anything in the path that we can to an integer and set
1047  * all the other integers to INT_MIN which will never match.
1048  */
1049  if (*tpath[i] != '\0')
1050  {
1051  int ind;
1052  char *endptr;
1053 
1054  errno = 0;
1055  ind = strtoint(tpath[i], &endptr, 10);
1056  if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1057  ipath[i] = INT_MIN;
1058  else
1059  ipath[i] = ind;
1060  }
1061  else
1062  ipath[i] = INT_MIN;
1063  }
1064 
1065  result = get_worker(json, tpath, ipath, npath, as_text);
1066 
1067  if (result != NULL)
1068  PG_RETURN_TEXT_P(result);
1069  else
1070  PG_RETURN_NULL();
1071 }
1072 
1073 /*
1074  * get_worker
1075  *
1076  * common worker for all the json getter functions
1077  *
1078  * json: JSON object (in text form)
1079  * tpath[]: field name(s) to extract
1080  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
1081  * npath: length of tpath[] and/or ipath[]
1082  * normalize_results: true to de-escape string and null scalars
1083  *
1084  * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
1085  * field is not to be matched at that nesting level. Similarly, ipath can
1086  * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
1087  * not to be matched at that nesting level (a json datum should never be
1088  * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
1089  */
1090 static text *
1092  char **tpath,
1093  int *ipath,
1094  int npath,
1095  bool normalize_results)
1096 {
1097  JsonLexContext *lex = makeJsonLexContext(json, true);
1098  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1099  GetState *state = palloc0(sizeof(GetState));
1100 
1101  Assert(npath >= 0);
1102 
1103  state->lex = lex;
1104  /* is it "_as_text" variant? */
1105  state->normalize_results = normalize_results;
1106  state->npath = npath;
1107  state->path_names = tpath;
1108  state->path_indexes = ipath;
1109  state->pathok = palloc0(sizeof(bool) * npath);
1110  state->array_cur_index = palloc(sizeof(int) * npath);
1111 
1112  if (npath > 0)
1113  state->pathok[0] = true;
1114 
1115  sem->semstate = (void *) state;
1116 
1117  /*
1118  * Not all variants need all the semantic routines. Only set the ones that
1119  * are actually needed for maximum efficiency.
1120  */
1121  sem->scalar = get_scalar;
1122  if (npath == 0)
1123  {
1125  sem->object_end = get_object_end;
1127  sem->array_end = get_array_end;
1128  }
1129  if (tpath != NULL)
1130  {
1133  }
1134  if (ipath != NULL)
1135  {
1139  }
1140 
1141  pg_parse_json_or_ereport(lex, sem);
1142 
1143  return state->tresult;
1144 }
1145 
1146 static JsonParseErrorType
1148 {
1149  GetState *_state = (GetState *) state;
1150  int lex_level = _state->lex->lex_level;
1151 
1152  if (lex_level == 0 && _state->npath == 0)
1153  {
1154  /*
1155  * Special case: we should match the entire object. We only need this
1156  * at outermost level because at nested levels the match will have
1157  * been started by the outer field or array element callback.
1158  */
1159  _state->result_start = _state->lex->token_start;
1160  }
1161 
1162  return JSON_SUCCESS;
1163 }
1164 
1165 static JsonParseErrorType
1167 {
1168  GetState *_state = (GetState *) state;
1169  int lex_level = _state->lex->lex_level;
1170 
1171  if (lex_level == 0 && _state->npath == 0)
1172  {
1173  /* Special case: return the entire object */
1174  char *start = _state->result_start;
1175  int len = _state->lex->prev_token_terminator - start;
1176 
1177  _state->tresult = cstring_to_text_with_len(start, len);
1178  }
1179 
1180  return JSON_SUCCESS;
1181 }
1182 
1183 static JsonParseErrorType
1184 get_object_field_start(void *state, char *fname, bool isnull)
1185 {
1186  GetState *_state = (GetState *) state;
1187  bool get_next = false;
1188  int lex_level = _state->lex->lex_level;
1189 
1190  if (lex_level <= _state->npath &&
1191  _state->pathok[lex_level - 1] &&
1192  _state->path_names != NULL &&
1193  _state->path_names[lex_level - 1] != NULL &&
1194  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1195  {
1196  if (lex_level < _state->npath)
1197  {
1198  /* if not at end of path just mark path ok */
1199  _state->pathok[lex_level] = true;
1200  }
1201  else
1202  {
1203  /* end of path, so we want this value */
1204  get_next = true;
1205  }
1206  }
1207 
1208  if (get_next)
1209  {
1210  /* this object overrides any previous matching object */
1211  _state->tresult = NULL;
1212  _state->result_start = NULL;
1213 
1214  if (_state->normalize_results &&
1215  _state->lex->token_type == JSON_TOKEN_STRING)
1216  {
1217  /* for as_text variants, tell get_scalar to set it for us */
1218  _state->next_scalar = true;
1219  }
1220  else
1221  {
1222  /* for non-as_text variants, just note the json starting point */
1223  _state->result_start = _state->lex->token_start;
1224  }
1225  }
1226 
1227  return JSON_SUCCESS;
1228 }
1229 
1230 static JsonParseErrorType
1231 get_object_field_end(void *state, char *fname, bool isnull)
1232 {
1233  GetState *_state = (GetState *) state;
1234  bool get_last = false;
1235  int lex_level = _state->lex->lex_level;
1236 
1237  /* same tests as in get_object_field_start */
1238  if (lex_level <= _state->npath &&
1239  _state->pathok[lex_level - 1] &&
1240  _state->path_names != NULL &&
1241  _state->path_names[lex_level - 1] != NULL &&
1242  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1243  {
1244  if (lex_level < _state->npath)
1245  {
1246  /* done with this field so reset pathok */
1247  _state->pathok[lex_level] = false;
1248  }
1249  else
1250  {
1251  /* end of path, so we want this value */
1252  get_last = true;
1253  }
1254  }
1255 
1256  /* for as_text scalar case, our work is already done */
1257  if (get_last && _state->result_start != NULL)
1258  {
1259  /*
1260  * make a text object from the string from the previously noted json
1261  * start up to the end of the previous token (the lexer is by now
1262  * ahead of us on whatever came after what we're interested in).
1263  */
1264  if (isnull && _state->normalize_results)
1265  _state->tresult = (text *) NULL;
1266  else
1267  {
1268  char *start = _state->result_start;
1269  int len = _state->lex->prev_token_terminator - start;
1270 
1271  _state->tresult = cstring_to_text_with_len(start, len);
1272  }
1273 
1274  /* this should be unnecessary but let's do it for cleanliness: */
1275  _state->result_start = NULL;
1276  }
1277 
1278  return JSON_SUCCESS;
1279 }
1280 
1281 static JsonParseErrorType
1283 {
1284  GetState *_state = (GetState *) state;
1285  int lex_level = _state->lex->lex_level;
1286 
1287  if (lex_level < _state->npath)
1288  {
1289  /* Initialize counting of elements in this array */
1290  _state->array_cur_index[lex_level] = -1;
1291 
1292  /* INT_MIN value is reserved to represent invalid subscript */
1293  if (_state->path_indexes[lex_level] < 0 &&
1294  _state->path_indexes[lex_level] != INT_MIN)
1295  {
1296  /* Negative subscript -- convert to positive-wise subscript */
1298  int nelements;
1299 
1300  error = json_count_array_elements(_state->lex, &nelements);
1301  if (error != JSON_SUCCESS)
1302  json_errsave_error(error, _state->lex, NULL);
1303 
1304  if (-_state->path_indexes[lex_level] <= nelements)
1305  _state->path_indexes[lex_level] += nelements;
1306  }
1307  }
1308  else if (lex_level == 0 && _state->npath == 0)
1309  {
1310  /*
1311  * Special case: we should match the entire array. We only need this
1312  * at the outermost level because at nested levels the match will have
1313  * been started by the outer field or array element callback.
1314  */
1315  _state->result_start = _state->lex->token_start;
1316  }
1317 
1318  return JSON_SUCCESS;
1319 }
1320 
1321 static JsonParseErrorType
1323 {
1324  GetState *_state = (GetState *) state;
1325  int lex_level = _state->lex->lex_level;
1326 
1327  if (lex_level == 0 && _state->npath == 0)
1328  {
1329  /* Special case: return the entire array */
1330  char *start = _state->result_start;
1331  int len = _state->lex->prev_token_terminator - start;
1332 
1333  _state->tresult = cstring_to_text_with_len(start, len);
1334  }
1335 
1336  return JSON_SUCCESS;
1337 }
1338 
1339 static JsonParseErrorType
1340 get_array_element_start(void *state, bool isnull)
1341 {
1342  GetState *_state = (GetState *) state;
1343  bool get_next = false;
1344  int lex_level = _state->lex->lex_level;
1345 
1346  /* Update array element counter */
1347  if (lex_level <= _state->npath)
1348  _state->array_cur_index[lex_level - 1]++;
1349 
1350  if (lex_level <= _state->npath &&
1351  _state->pathok[lex_level - 1] &&
1352  _state->path_indexes != NULL &&
1353  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1354  {
1355  if (lex_level < _state->npath)
1356  {
1357  /* if not at end of path just mark path ok */
1358  _state->pathok[lex_level] = true;
1359  }
1360  else
1361  {
1362  /* end of path, so we want this value */
1363  get_next = true;
1364  }
1365  }
1366 
1367  /* same logic as for objects */
1368  if (get_next)
1369  {
1370  _state->tresult = NULL;
1371  _state->result_start = NULL;
1372 
1373  if (_state->normalize_results &&
1374  _state->lex->token_type == JSON_TOKEN_STRING)
1375  {
1376  _state->next_scalar = true;
1377  }
1378  else
1379  {
1380  _state->result_start = _state->lex->token_start;
1381  }
1382  }
1383 
1384  return JSON_SUCCESS;
1385 }
1386 
1387 static JsonParseErrorType
1388 get_array_element_end(void *state, bool isnull)
1389 {
1390  GetState *_state = (GetState *) state;
1391  bool get_last = false;
1392  int lex_level = _state->lex->lex_level;
1393 
1394  /* same tests as in get_array_element_start */
1395  if (lex_level <= _state->npath &&
1396  _state->pathok[lex_level - 1] &&
1397  _state->path_indexes != NULL &&
1398  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1399  {
1400  if (lex_level < _state->npath)
1401  {
1402  /* done with this element so reset pathok */
1403  _state->pathok[lex_level] = false;
1404  }
1405  else
1406  {
1407  /* end of path, so we want this value */
1408  get_last = true;
1409  }
1410  }
1411 
1412  /* same logic as for objects */
1413  if (get_last && _state->result_start != NULL)
1414  {
1415  if (isnull && _state->normalize_results)
1416  _state->tresult = (text *) NULL;
1417  else
1418  {
1419  char *start = _state->result_start;
1420  int len = _state->lex->prev_token_terminator - start;
1421 
1422  _state->tresult = cstring_to_text_with_len(start, len);
1423  }
1424 
1425  _state->result_start = NULL;
1426  }
1427 
1428  return JSON_SUCCESS;
1429 }
1430 
1431 static JsonParseErrorType
1432 get_scalar(void *state, char *token, JsonTokenType tokentype)
1433 {
1434  GetState *_state = (GetState *) state;
1435  int lex_level = _state->lex->lex_level;
1436 
1437  /* Check for whole-object match */
1438  if (lex_level == 0 && _state->npath == 0)
1439  {
1440  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1441  {
1442  /* we want the de-escaped string */
1443  _state->next_scalar = true;
1444  }
1445  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1446  {
1447  _state->tresult = (text *) NULL;
1448  }
1449  else
1450  {
1451  /*
1452  * This is a bit hokey: we will suppress whitespace after the
1453  * scalar token, but not whitespace before it. Probably not worth
1454  * doing our own space-skipping to avoid that.
1455  */
1456  char *start = _state->lex->input;
1457  int len = _state->lex->prev_token_terminator - start;
1458 
1459  _state->tresult = cstring_to_text_with_len(start, len);
1460  }
1461  }
1462 
1463  if (_state->next_scalar)
1464  {
1465  /* a de-escaped text value is wanted, so supply it */
1466  _state->tresult = cstring_to_text(token);
1467  /* make sure the next call to get_scalar doesn't overwrite it */
1468  _state->next_scalar = false;
1469  }
1470 
1471  return JSON_SUCCESS;
1472 }
1473 
1474 Datum
1476 {
1477  return get_jsonb_path_all(fcinfo, false);
1478 }
1479 
1480 Datum
1482 {
1483  return get_jsonb_path_all(fcinfo, true);
1484 }
1485 
1486 static Datum
1488 {
1489  Jsonb *jb = PG_GETARG_JSONB_P(0);
1490  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1491  Datum *pathtext;
1492  bool *pathnulls;
1493  bool isnull;
1494  int npath;
1495  Datum res;
1496 
1497  /*
1498  * If the array contains any null elements, return NULL, on the grounds
1499  * that you'd have gotten NULL if any RHS value were NULL in a nested
1500  * series of applications of the -> operator. (Note: because we also
1501  * return NULL for error cases such as no-such-field, this is true
1502  * regardless of the contents of the rest of the array.)
1503  */
1504  if (array_contains_nulls(path))
1505  PG_RETURN_NULL();
1506 
1507  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1508 
1509  res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
1510 
1511  if (isnull)
1512  PG_RETURN_NULL();
1513  else
1515 }
1516 
1517 Datum
1518 jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
1519 {
1520  JsonbContainer *container = &jb->root;
1521  JsonbValue *jbvp = NULL;
1522  int i;
1523  bool have_object = false,
1524  have_array = false;
1525 
1526  *isnull = false;
1527 
1528  /* Identify whether we have object, array, or scalar at top-level */
1529  if (JB_ROOT_IS_OBJECT(jb))
1530  have_object = true;
1531  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1532  have_array = true;
1533  else
1534  {
1536  /* Extract the scalar value, if it is what we'll return */
1537  if (npath <= 0)
1538  jbvp = getIthJsonbValueFromContainer(container, 0);
1539  }
1540 
1541  /*
1542  * If the array is empty, return the entire LHS object, on the grounds
1543  * that we should do zero field or element extractions. For the
1544  * non-scalar case we can just hand back the object without much work. For
1545  * the scalar case, fall through and deal with the value below the loop.
1546  * (This inconsistency arises because there's no easy way to generate a
1547  * JsonbValue directly for root-level containers.)
1548  */
1549  if (npath <= 0 && jbvp == NULL)
1550  {
1551  if (as_text)
1552  {
1554  container,
1555  VARSIZE(jb))));
1556  }
1557  else
1558  {
1559  /* not text mode - just hand back the jsonb */
1560  PG_RETURN_JSONB_P(jb);
1561  }
1562  }
1563 
1564  for (i = 0; i < npath; i++)
1565  {
1566  if (have_object)
1567  {
1568  text *subscr = DatumGetTextPP(path[i]);
1569 
1570  jbvp = getKeyJsonValueFromContainer(container,
1571  VARDATA_ANY(subscr),
1572  VARSIZE_ANY_EXHDR(subscr),
1573  NULL);
1574  }
1575  else if (have_array)
1576  {
1577  int lindex;
1578  uint32 index;
1579  char *indextext = TextDatumGetCString(path[i]);
1580  char *endptr;
1581 
1582  errno = 0;
1583  lindex = strtoint(indextext, &endptr, 10);
1584  if (endptr == indextext || *endptr != '\0' || errno != 0)
1585  {
1586  *isnull = true;
1587  return PointerGetDatum(NULL);
1588  }
1589 
1590  if (lindex >= 0)
1591  {
1592  index = (uint32) lindex;
1593  }
1594  else
1595  {
1596  /* Handle negative subscript */
1597  uint32 nelements;
1598 
1599  /* Container must be array, but make sure */
1600  if (!JsonContainerIsArray(container))
1601  elog(ERROR, "not a jsonb array");
1602 
1603  nelements = JsonContainerSize(container);
1604 
1605  if (lindex == INT_MIN || -lindex > nelements)
1606  {
1607  *isnull = true;
1608  return PointerGetDatum(NULL);
1609  }
1610  else
1611  index = nelements + lindex;
1612  }
1613 
1614  jbvp = getIthJsonbValueFromContainer(container, index);
1615  }
1616  else
1617  {
1618  /* scalar, extraction yields a null */
1619  *isnull = true;
1620  return PointerGetDatum(NULL);
1621  }
1622 
1623  if (jbvp == NULL)
1624  {
1625  *isnull = true;
1626  return PointerGetDatum(NULL);
1627  }
1628  else if (i == npath - 1)
1629  break;
1630 
1631  if (jbvp->type == jbvBinary)
1632  {
1633  container = jbvp->val.binary.data;
1634  have_object = JsonContainerIsObject(container);
1635  have_array = JsonContainerIsArray(container);
1636  Assert(!JsonContainerIsScalar(container));
1637  }
1638  else
1639  {
1640  Assert(IsAJsonbScalar(jbvp));
1641  have_object = false;
1642  have_array = false;
1643  }
1644  }
1645 
1646  if (as_text)
1647  {
1648  if (jbvp->type == jbvNull)
1649  {
1650  *isnull = true;
1651  return PointerGetDatum(NULL);
1652  }
1653 
1654  return PointerGetDatum(JsonbValueAsText(jbvp));
1655  }
1656  else
1657  {
1658  Jsonb *res = JsonbValueToJsonb(jbvp);
1659 
1660  /* not text mode - just hand back the jsonb */
1662  }
1663 }
1664 
1665 Datum
1666 jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
1667  JsonbValue *newval)
1668 {
1669  JsonbValue *res;
1670  JsonbParseState *state = NULL;
1671  JsonbIterator *it;
1672  bool *path_nulls = palloc0(path_len * sizeof(bool));
1673 
1674  if (newval->type == jbvArray && newval->val.array.rawScalar)
1675  *newval = newval->val.array.elems[0];
1676 
1677  it = JsonbIteratorInit(&jb->root);
1678 
1679  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1682 
1683  pfree(path_nulls);
1684 
1686 }
1687 
1688 static void
1690 {
1691  JsonbValue null;
1692 
1693  null.type = jbvNull;
1694 
1695  while (num-- > 0)
1696  pushJsonbValue(ps, WJB_ELEM, &null);
1697 }
1698 
1699 /*
1700  * Prepare a new structure containing nested empty objects and arrays
1701  * corresponding to the specified path, and assign a new value at the end of
1702  * this path. E.g. the path [a][0][b] with the new value 1 will produce the
1703  * structure {a: [{b: 1}]}.
1704  *
1705  * Caller is responsible to make sure such path does not exist yet.
1706  */
1707 static void
1708 push_path(JsonbParseState **st, int level, Datum *path_elems,
1709  bool *path_nulls, int path_len, JsonbValue *newval)
1710 {
1711  /*
1712  * tpath contains expected type of an empty jsonb created at each level
1713  * higher or equal than the current one, either jbvObject or jbvArray.
1714  * Since it contains only information about path slice from level to the
1715  * end, the access index must be normalized by level.
1716  */
1717  enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
1718  JsonbValue newkey;
1719 
1720  /*
1721  * Create first part of the chain with beginning tokens. For the current
1722  * level WJB_BEGIN_OBJECT/WJB_BEGIN_ARRAY was already created, so start
1723  * with the next one.
1724  */
1725  for (int i = level + 1; i < path_len; i++)
1726  {
1727  char *c,
1728  *badp;
1729  int lindex;
1730 
1731  if (path_nulls[i])
1732  break;
1733 
1734  /*
1735  * Try to convert to an integer to find out the expected type, object
1736  * or array.
1737  */
1738  c = TextDatumGetCString(path_elems[i]);
1739  errno = 0;
1740  lindex = strtoint(c, &badp, 10);
1741  if (badp == c || *badp != '\0' || errno != 0)
1742  {
1743  /* text, an object is expected */
1744  newkey.type = jbvString;
1745  newkey.val.string.val = c;
1746  newkey.val.string.len = strlen(c);
1747 
1748  (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL);
1749  (void) pushJsonbValue(st, WJB_KEY, &newkey);
1750 
1751  tpath[i - level] = jbvObject;
1752  }
1753  else
1754  {
1755  /* integer, an array is expected */
1756  (void) pushJsonbValue(st, WJB_BEGIN_ARRAY, NULL);
1757 
1758  push_null_elements(st, lindex);
1759 
1760  tpath[i - level] = jbvArray;
1761  }
1762  }
1763 
1764  /* Insert an actual value for either an object or array */
1765  if (tpath[(path_len - level) - 1] == jbvArray)
1766  {
1767  (void) pushJsonbValue(st, WJB_ELEM, newval);
1768  }
1769  else
1770  (void) pushJsonbValue(st, WJB_VALUE, newval);
1771 
1772  /*
1773  * Close everything up to the last but one level. The last one will be
1774  * closed outside of this function.
1775  */
1776  for (int i = path_len - 1; i > level; i--)
1777  {
1778  if (path_nulls[i])
1779  break;
1780 
1781  if (tpath[i - level] == jbvObject)
1782  (void) pushJsonbValue(st, WJB_END_OBJECT, NULL);
1783  else
1784  (void) pushJsonbValue(st, WJB_END_ARRAY, NULL);
1785  }
1786 }
1787 
1788 /*
1789  * Return the text representation of the given JsonbValue.
1790  */
1791 static text *
1793 {
1794  switch (v->type)
1795  {
1796  case jbvNull:
1797  return NULL;
1798 
1799  case jbvBool:
1800  return v->val.boolean ?
1801  cstring_to_text_with_len("true", 4) :
1802  cstring_to_text_with_len("false", 5);
1803 
1804  case jbvString:
1805  return cstring_to_text_with_len(v->val.string.val,
1806  v->val.string.len);
1807 
1808  case jbvNumeric:
1809  {
1810  Datum cstr;
1811 
1813  PointerGetDatum(v->val.numeric));
1814 
1815  return cstring_to_text(DatumGetCString(cstr));
1816  }
1817 
1818  case jbvBinary:
1819  {
1820  StringInfoData jtext;
1821 
1822  initStringInfo(&jtext);
1823  (void) JsonbToCString(&jtext, v->val.binary.data,
1824  v->val.binary.len);
1825 
1826  return cstring_to_text_with_len(jtext.data, jtext.len);
1827  }
1828 
1829  default:
1830  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1831  return NULL;
1832  }
1833 }
1834 
1835 /*
1836  * SQL function json_array_length(json) -> int
1837  */
1838 Datum
1840 {
1841  text *json = PG_GETARG_TEXT_PP(0);
1842  AlenState *state;
1843  JsonLexContext *lex;
1844  JsonSemAction *sem;
1845 
1846  lex = makeJsonLexContext(json, false);
1847  state = palloc0(sizeof(AlenState));
1848  sem = palloc0(sizeof(JsonSemAction));
1849 
1850  /* palloc0 does this for us */
1851 #if 0
1852  state->count = 0;
1853 #endif
1854  state->lex = lex;
1855 
1856  sem->semstate = (void *) state;
1858  sem->scalar = alen_scalar;
1860 
1861  pg_parse_json_or_ereport(lex, sem);
1862 
1863  PG_RETURN_INT32(state->count);
1864 }
1865 
1866 Datum
1868 {
1869  Jsonb *jb = PG_GETARG_JSONB_P(0);
1870 
1871  if (JB_ROOT_IS_SCALAR(jb))
1872  ereport(ERROR,
1873  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1874  errmsg("cannot get array length of a scalar")));
1875  else if (!JB_ROOT_IS_ARRAY(jb))
1876  ereport(ERROR,
1877  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1878  errmsg("cannot get array length of a non-array")));
1879 
1881 }
1882 
1883 /*
1884  * These next two checks ensure that the json is an array (since it can't be
1885  * a scalar or an object).
1886  */
1887 
1888 static JsonParseErrorType
1890 {
1891  AlenState *_state = (AlenState *) state;
1892 
1893  /* json structure check */
1894  if (_state->lex->lex_level == 0)
1895  ereport(ERROR,
1896  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1897  errmsg("cannot get array length of a non-array")));
1898 
1899  return JSON_SUCCESS;
1900 }
1901 
1902 static JsonParseErrorType
1903 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1904 {
1905  AlenState *_state = (AlenState *) state;
1906 
1907  /* json structure check */
1908  if (_state->lex->lex_level == 0)
1909  ereport(ERROR,
1910  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1911  errmsg("cannot get array length of a scalar")));
1912 
1913  return JSON_SUCCESS;
1914 }
1915 
1916 static JsonParseErrorType
1917 alen_array_element_start(void *state, bool isnull)
1918 {
1919  AlenState *_state = (AlenState *) state;
1920 
1921  /* just count up all the level 1 elements */
1922  if (_state->lex->lex_level == 1)
1923  _state->count++;
1924 
1925  return JSON_SUCCESS;
1926 }
1927 
1928 /*
1929  * SQL function json_each and json_each_text
1930  *
1931  * decompose a json object into key value pairs.
1932  *
1933  * Unlike json_object_keys() these SRFs operate in materialize mode,
1934  * stashing results into a Tuplestore object as they go.
1935  * The construction of tuples is done using a temporary memory context
1936  * that is cleared out after each tuple is built.
1937  */
1938 Datum
1940 {
1941  return each_worker(fcinfo, false);
1942 }
1943 
1944 Datum
1946 {
1947  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1948 }
1949 
1950 Datum
1952 {
1953  return each_worker(fcinfo, true);
1954 }
1955 
1956 Datum
1958 {
1959  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1960 }
1961 
1962 static Datum
1963 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1964 {
1965  Jsonb *jb = PG_GETARG_JSONB_P(0);
1966  ReturnSetInfo *rsi;
1967  MemoryContext old_cxt,
1968  tmp_cxt;
1969  bool skipNested = false;
1970  JsonbIterator *it;
1971  JsonbValue v;
1973 
1974  if (!JB_ROOT_IS_OBJECT(jb))
1975  ereport(ERROR,
1976  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1977  errmsg("cannot call %s on a non-object",
1978  funcname)));
1979 
1980  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1982 
1984  "jsonb_each temporary cxt",
1986 
1987  it = JsonbIteratorInit(&jb->root);
1988 
1989  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1990  {
1991  skipNested = true;
1992 
1993  if (r == WJB_KEY)
1994  {
1995  text *key;
1996  Datum values[2];
1997  bool nulls[2] = {false, false};
1998 
1999  /* Use the tmp context so we can clean up after each tuple is done */
2000  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2001 
2002  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2003 
2004  /*
2005  * The next thing the iterator fetches should be the value, no
2006  * matter what shape it is.
2007  */
2008  r = JsonbIteratorNext(&it, &v, skipNested);
2009  Assert(r != WJB_DONE);
2010 
2011  values[0] = PointerGetDatum(key);
2012 
2013  if (as_text)
2014  {
2015  if (v.type == jbvNull)
2016  {
2017  /* a json null is an sql null in text mode */
2018  nulls[1] = true;
2019  values[1] = (Datum) NULL;
2020  }
2021  else
2023  }
2024  else
2025  {
2026  /* Not in text mode, just return the Jsonb */
2027  Jsonb *val = JsonbValueToJsonb(&v);
2028 
2029  values[1] = PointerGetDatum(val);
2030  }
2031 
2032  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2033 
2034  /* clean up and switch back */
2035  MemoryContextSwitchTo(old_cxt);
2036  MemoryContextReset(tmp_cxt);
2037  }
2038  }
2039 
2040  MemoryContextDelete(tmp_cxt);
2041 
2042  PG_RETURN_NULL();
2043 }
2044 
2045 
2046 static Datum
2047 each_worker(FunctionCallInfo fcinfo, bool as_text)
2048 {
2049  text *json = PG_GETARG_TEXT_PP(0);
2050  JsonLexContext *lex;
2051  JsonSemAction *sem;
2052  ReturnSetInfo *rsi;
2053  EachState *state;
2054 
2055  lex = makeJsonLexContext(json, true);
2056  state = palloc0(sizeof(EachState));
2057  sem = palloc0(sizeof(JsonSemAction));
2058 
2059  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2060 
2062  state->tuple_store = rsi->setResult;
2063  state->ret_tdesc = rsi->setDesc;
2064 
2065  sem->semstate = (void *) state;
2067  sem->scalar = each_scalar;
2070 
2071  state->normalize_results = as_text;
2072  state->next_scalar = false;
2073  state->lex = lex;
2075  "json_each temporary cxt",
2077 
2078  pg_parse_json_or_ereport(lex, sem);
2079 
2080  MemoryContextDelete(state->tmp_cxt);
2081 
2082  PG_RETURN_NULL();
2083 }
2084 
2085 
2086 static JsonParseErrorType
2087 each_object_field_start(void *state, char *fname, bool isnull)
2088 {
2089  EachState *_state = (EachState *) state;
2090 
2091  /* save a pointer to where the value starts */
2092  if (_state->lex->lex_level == 1)
2093  {
2094  /*
2095  * next_scalar will be reset in the object_field_end handler, and
2096  * since we know the value is a scalar there is no danger of it being
2097  * on while recursing down the tree.
2098  */
2099  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2100  _state->next_scalar = true;
2101  else
2102  _state->result_start = _state->lex->token_start;
2103  }
2104 
2105  return JSON_SUCCESS;
2106 }
2107 
2108 static JsonParseErrorType
2109 each_object_field_end(void *state, char *fname, bool isnull)
2110 {
2111  EachState *_state = (EachState *) state;
2112  MemoryContext old_cxt;
2113  int len;
2114  text *val;
2115  HeapTuple tuple;
2116  Datum values[2];
2117  bool nulls[2] = {false, false};
2118 
2119  /* skip over nested objects */
2120  if (_state->lex->lex_level != 1)
2121  return JSON_SUCCESS;
2122 
2123  /* use the tmp context so we can clean up after each tuple is done */
2124  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2125 
2126  values[0] = CStringGetTextDatum(fname);
2127 
2128  if (isnull && _state->normalize_results)
2129  {
2130  nulls[1] = true;
2131  values[1] = (Datum) 0;
2132  }
2133  else if (_state->next_scalar)
2134  {
2136  _state->next_scalar = false;
2137  }
2138  else
2139  {
2140  len = _state->lex->prev_token_terminator - _state->result_start;
2142  values[1] = PointerGetDatum(val);
2143  }
2144 
2145  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2146 
2147  tuplestore_puttuple(_state->tuple_store, tuple);
2148 
2149  /* clean up and switch back */
2150  MemoryContextSwitchTo(old_cxt);
2151  MemoryContextReset(_state->tmp_cxt);
2152 
2153  return JSON_SUCCESS;
2154 }
2155 
2156 static JsonParseErrorType
2158 {
2159  EachState *_state = (EachState *) state;
2160 
2161  /* json structure check */
2162  if (_state->lex->lex_level == 0)
2163  ereport(ERROR,
2164  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2165  errmsg("cannot deconstruct an array as an object")));
2166 
2167  return JSON_SUCCESS;
2168 }
2169 
2170 static JsonParseErrorType
2171 each_scalar(void *state, char *token, JsonTokenType tokentype)
2172 {
2173  EachState *_state = (EachState *) state;
2174 
2175  /* json structure check */
2176  if (_state->lex->lex_level == 0)
2177  ereport(ERROR,
2178  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2179  errmsg("cannot deconstruct a scalar")));
2180 
2181  /* supply de-escaped value if required */
2182  if (_state->next_scalar)
2183  _state->normalized_scalar = token;
2184 
2185  return JSON_SUCCESS;
2186 }
2187 
2188 /*
2189  * SQL functions json_array_elements and json_array_elements_text
2190  *
2191  * get the elements from a json array
2192  *
2193  * a lot of this processing is similar to the json_each* functions
2194  */
2195 
2196 Datum
2198 {
2199  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2200 }
2201 
2202 Datum
2204 {
2205  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2206 }
2207 
2208 static Datum
2209 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
2210  bool as_text)
2211 {
2212  Jsonb *jb = PG_GETARG_JSONB_P(0);
2213  ReturnSetInfo *rsi;
2214  MemoryContext old_cxt,
2215  tmp_cxt;
2216  bool skipNested = false;
2217  JsonbIterator *it;
2218  JsonbValue v;
2220 
2221  if (JB_ROOT_IS_SCALAR(jb))
2222  ereport(ERROR,
2223  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2224  errmsg("cannot extract elements from a scalar")));
2225  else if (!JB_ROOT_IS_ARRAY(jb))
2226  ereport(ERROR,
2227  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2228  errmsg("cannot extract elements from an object")));
2229 
2230  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2231 
2233 
2235  "jsonb_array_elements temporary cxt",
2237 
2238  it = JsonbIteratorInit(&jb->root);
2239 
2240  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2241  {
2242  skipNested = true;
2243 
2244  if (r == WJB_ELEM)
2245  {
2246  Datum values[1];
2247  bool nulls[1] = {false};
2248 
2249  /* use the tmp context so we can clean up after each tuple is done */
2250  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2251 
2252  if (as_text)
2253  {
2254  if (v.type == jbvNull)
2255  {
2256  /* a json null is an sql null in text mode */
2257  nulls[0] = true;
2258  values[0] = (Datum) NULL;
2259  }
2260  else
2262  }
2263  else
2264  {
2265  /* Not in text mode, just return the Jsonb */
2266  Jsonb *val = JsonbValueToJsonb(&v);
2267 
2268  values[0] = PointerGetDatum(val);
2269  }
2270 
2271  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2272 
2273  /* clean up and switch back */
2274  MemoryContextSwitchTo(old_cxt);
2275  MemoryContextReset(tmp_cxt);
2276  }
2277  }
2278 
2279  MemoryContextDelete(tmp_cxt);
2280 
2281  PG_RETURN_NULL();
2282 }
2283 
2284 Datum
2286 {
2287  return elements_worker(fcinfo, "json_array_elements", false);
2288 }
2289 
2290 Datum
2292 {
2293  return elements_worker(fcinfo, "json_array_elements_text", true);
2294 }
2295 
2296 static Datum
2297 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
2298 {
2299  text *json = PG_GETARG_TEXT_PP(0);
2300 
2301  /* elements only needs escaped strings when as_text */
2302  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2303  JsonSemAction *sem;
2304  ReturnSetInfo *rsi;
2306 
2307  state = palloc0(sizeof(ElementsState));
2308  sem = palloc0(sizeof(JsonSemAction));
2309 
2311  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2312  state->tuple_store = rsi->setResult;
2313  state->ret_tdesc = rsi->setDesc;
2314 
2315  sem->semstate = (void *) state;
2317  sem->scalar = elements_scalar;
2320 
2321  state->function_name = funcname;
2322  state->normalize_results = as_text;
2323  state->next_scalar = false;
2324  state->lex = lex;
2326  "json_array_elements temporary cxt",
2328 
2329  pg_parse_json_or_ereport(lex, sem);
2330 
2331  MemoryContextDelete(state->tmp_cxt);
2332 
2333  PG_RETURN_NULL();
2334 }
2335 
2336 static JsonParseErrorType
2338 {
2339  ElementsState *_state = (ElementsState *) state;
2340 
2341  /* save a pointer to where the value starts */
2342  if (_state->lex->lex_level == 1)
2343  {
2344  /*
2345  * next_scalar will be reset in the array_element_end handler, and
2346  * since we know the value is a scalar there is no danger of it being
2347  * on while recursing down the tree.
2348  */
2349  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2350  _state->next_scalar = true;
2351  else
2352  _state->result_start = _state->lex->token_start;
2353  }
2354 
2355  return JSON_SUCCESS;
2356 }
2357 
2358 static JsonParseErrorType
2360 {
2361  ElementsState *_state = (ElementsState *) state;
2362  MemoryContext old_cxt;
2363  int len;
2364  text *val;
2365  HeapTuple tuple;
2366  Datum values[1];
2367  bool nulls[1] = {false};
2368 
2369  /* skip over nested objects */
2370  if (_state->lex->lex_level != 1)
2371  return JSON_SUCCESS;
2372 
2373  /* use the tmp context so we can clean up after each tuple is done */
2374  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2375 
2376  if (isnull && _state->normalize_results)
2377  {
2378  nulls[0] = true;
2379  values[0] = (Datum) NULL;
2380  }
2381  else if (_state->next_scalar)
2382  {
2384  _state->next_scalar = false;
2385  }
2386  else
2387  {
2388  len = _state->lex->prev_token_terminator - _state->result_start;
2390  values[0] = PointerGetDatum(val);
2391  }
2392 
2393  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2394 
2395  tuplestore_puttuple(_state->tuple_store, tuple);
2396 
2397  /* clean up and switch back */
2398  MemoryContextSwitchTo(old_cxt);
2399  MemoryContextReset(_state->tmp_cxt);
2400 
2401  return JSON_SUCCESS;
2402 }
2403 
2404 static JsonParseErrorType
2406 {
2407  ElementsState *_state = (ElementsState *) state;
2408 
2409  /* json structure check */
2410  if (_state->lex->lex_level == 0)
2411  ereport(ERROR,
2412  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2413  errmsg("cannot call %s on a non-array",
2414  _state->function_name)));
2415 
2416  return JSON_SUCCESS;
2417 }
2418 
2419 static JsonParseErrorType
2420 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2421 {
2422  ElementsState *_state = (ElementsState *) state;
2423 
2424  /* json structure check */
2425  if (_state->lex->lex_level == 0)
2426  ereport(ERROR,
2427  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2428  errmsg("cannot call %s on a scalar",
2429  _state->function_name)));
2430 
2431  /* supply de-escaped value if required */
2432  if (_state->next_scalar)
2433  _state->normalized_scalar = token;
2434 
2435  return JSON_SUCCESS;
2436 }
2437 
2438 /*
2439  * SQL function json_populate_record
2440  *
2441  * set fields in a record from the argument json
2442  *
2443  * Code adapted shamelessly from hstore's populate_record
2444  * which is in turn partly adapted from record_out.
2445  *
2446  * The json is decomposed into a hash table, in which each
2447  * field in the record is then looked up by name. For jsonb
2448  * we fetch the values direct from the object.
2449  */
2450 Datum
2452 {
2453  return populate_record_worker(fcinfo, "jsonb_populate_record",
2454  false, true);
2455 }
2456 
2457 Datum
2459 {
2460  return populate_record_worker(fcinfo, "jsonb_to_record",
2461  false, false);
2462 }
2463 
2464 Datum
2466 {
2467  return populate_record_worker(fcinfo, "json_populate_record",
2468  true, true);
2469 }
2470 
2471 Datum
2473 {
2474  return populate_record_worker(fcinfo, "json_to_record",
2475  true, false);
2476 }
2477 
2478 /* helper function for diagnostics */
2479 static void
2481 {
2482  if (ndim <= 0)
2483  {
2484  if (ctx->colname)
2485  ereport(ERROR,
2486  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2487  errmsg("expected JSON array"),
2488  errhint("See the value of key \"%s\".", ctx->colname)));
2489  else
2490  ereport(ERROR,
2491  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2492  errmsg("expected JSON array")));
2493  }
2494  else
2495  {
2496  StringInfoData indices;
2497  int i;
2498 
2499  initStringInfo(&indices);
2500 
2501  Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2502 
2503  for (i = 0; i < ndim; i++)
2504  appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2505 
2506  if (ctx->colname)
2507  ereport(ERROR,
2508  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2509  errmsg("expected JSON array"),
2510  errhint("See the array element %s of key \"%s\".",
2511  indices.data, ctx->colname)));
2512  else
2513  ereport(ERROR,
2514  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2515  errmsg("expected JSON array"),
2516  errhint("See the array element %s.",
2517  indices.data)));
2518  }
2519 }
2520 
2521 /* set the number of dimensions of the populated array when it becomes known */
2522 static void
2524 {
2525  int i;
2526 
2527  Assert(ctx->ndims <= 0);
2528 
2529  if (ndims <= 0)
2531 
2532  ctx->ndims = ndims;
2533  ctx->dims = palloc(sizeof(int) * ndims);
2534  ctx->sizes = palloc0(sizeof(int) * ndims);
2535 
2536  for (i = 0; i < ndims; i++)
2537  ctx->dims[i] = -1; /* dimensions are unknown yet */
2538 }
2539 
2540 /* check the populated subarray dimension */
2541 static void
2543 {
2544  int dim = ctx->sizes[ndim]; /* current dimension counter */
2545 
2546  if (ctx->dims[ndim] == -1)
2547  ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2548  else if (ctx->dims[ndim] != dim)
2549  ereport(ERROR,
2550  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2551  errmsg("malformed JSON array"),
2552  errdetail("Multidimensional arrays must have "
2553  "sub-arrays with matching dimensions.")));
2554 
2555  /* reset the current array dimension size counter */
2556  ctx->sizes[ndim] = 0;
2557 
2558  /* increment the parent dimension counter if it is a nested sub-array */
2559  if (ndim > 0)
2560  ctx->sizes[ndim - 1]++;
2561 }
2562 
2563 static void
2565 {
2566  Datum element;
2567  bool element_isnull;
2568 
2569  /* populate the array element */
2571  ctx->aio->element_type,
2572  ctx->aio->element_typmod,
2573  NULL, ctx->mcxt, PointerGetDatum(NULL),
2574  jsv, &element_isnull);
2575 
2576  accumArrayResult(ctx->astate, element, element_isnull,
2577  ctx->aio->element_type, ctx->acxt);
2578 
2579  Assert(ndim > 0);
2580  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2581 }
2582 
2583 /* json object start handler for populate_array_json() */
2584 static JsonParseErrorType
2586 {
2588  int ndim = state->lex->lex_level;
2589 
2590  if (state->ctx->ndims <= 0)
2591  populate_array_assign_ndims(state->ctx, ndim);
2592  else if (ndim < state->ctx->ndims)
2594 
2595  return JSON_SUCCESS;
2596 }
2597 
2598 /* json array end handler for populate_array_json() */
2599 static JsonParseErrorType
2601 {
2603  PopulateArrayContext *ctx = state->ctx;
2604  int ndim = state->lex->lex_level;
2605 
2606  if (ctx->ndims <= 0)
2607  populate_array_assign_ndims(ctx, ndim + 1);
2608 
2609  if (ndim < ctx->ndims)
2610  populate_array_check_dimension(ctx, ndim);
2611 
2612  return JSON_SUCCESS;
2613 }
2614 
2615 /* json array element start handler for populate_array_json() */
2616 static JsonParseErrorType
2617 populate_array_element_start(void *_state, bool isnull)
2618 {
2620  int ndim = state->lex->lex_level;
2621 
2622  if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2623  {
2624  /* remember current array element start */
2625  state->element_start = state->lex->token_start;
2626  state->element_type = state->lex->token_type;
2627  state->element_scalar = NULL;
2628  }
2629 
2630  return JSON_SUCCESS;
2631 }
2632 
2633 /* json array element end handler for populate_array_json() */
2634 static JsonParseErrorType
2635 populate_array_element_end(void *_state, bool isnull)
2636 {
2638  PopulateArrayContext *ctx = state->ctx;
2639  int ndim = state->lex->lex_level;
2640 
2641  Assert(ctx->ndims > 0);
2642 
2643  if (ndim == ctx->ndims)
2644  {
2645  JsValue jsv;
2646 
2647  jsv.is_json = true;
2648  jsv.val.json.type = state->element_type;
2649 
2650  if (isnull)
2651  {
2652  Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2653  jsv.val.json.str = NULL;
2654  jsv.val.json.len = 0;
2655  }
2656  else if (state->element_scalar)
2657  {
2658  jsv.val.json.str = state->element_scalar;
2659  jsv.val.json.len = -1; /* null-terminated */
2660  }
2661  else
2662  {
2663  jsv.val.json.str = state->element_start;
2664  jsv.val.json.len = (state->lex->prev_token_terminator -
2665  state->element_start) * sizeof(char);
2666  }
2667 
2668  populate_array_element(ctx, ndim, &jsv);
2669  }
2670 
2671  return JSON_SUCCESS;
2672 }
2673 
2674 /* json scalar handler for populate_array_json() */
2675 static JsonParseErrorType
2676 populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
2677 {
2679  PopulateArrayContext *ctx = state->ctx;
2680  int ndim = state->lex->lex_level;
2681 
2682  if (ctx->ndims <= 0)
2683  populate_array_assign_ndims(ctx, ndim);
2684  else if (ndim < ctx->ndims)
2686 
2687  if (ndim == ctx->ndims)
2688  {
2689  /* remember the scalar element token */
2690  state->element_scalar = token;
2691  /* element_type must already be set in populate_array_element_start() */
2692  Assert(state->element_type == tokentype);
2693  }
2694 
2695  return JSON_SUCCESS;
2696 }
2697 
2698 /* parse a json array and populate array */
2699 static void
2701 {
2703  JsonSemAction sem;
2704 
2706  state.ctx = ctx;
2707 
2708  memset(&sem, 0, sizeof(sem));
2709  sem.semstate = (void *) &state;
2715 
2716  pg_parse_json_or_ereport(state.lex, &sem);
2717 
2718  /* number of dimensions should be already known */
2719  Assert(ctx->ndims > 0 && ctx->dims);
2720 
2721  pfree(state.lex);
2722 }
2723 
2724 /*
2725  * populate_array_dim_jsonb() -- Iterate recursively through jsonb sub-array
2726  * elements and accumulate result using given ArrayBuildState.
2727  */
2728 static void
2730  JsonbValue *jbv, /* jsonb sub-array */
2731  int ndim) /* current dimension */
2732 {
2733  JsonbContainer *jbc = jbv->val.binary.data;
2734  JsonbIterator *it;
2735  JsonbIteratorToken tok;
2736  JsonbValue val;
2737  JsValue jsv;
2738 
2740 
2741  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
2742  populate_array_report_expected_array(ctx, ndim - 1);
2743 
2745 
2746  it = JsonbIteratorInit(jbc);
2747 
2748  tok = JsonbIteratorNext(&it, &val, true);
2749  Assert(tok == WJB_BEGIN_ARRAY);
2750 
2751  tok = JsonbIteratorNext(&it, &val, true);
2752 
2753  /*
2754  * If the number of dimensions is not yet known and we have found end of
2755  * the array, or the first child element is not an array, then assign the
2756  * number of dimensions now.
2757  */
2758  if (ctx->ndims <= 0 &&
2759  (tok == WJB_END_ARRAY ||
2760  (tok == WJB_ELEM &&
2761  (val.type != jbvBinary ||
2762  !JsonContainerIsArray(val.val.binary.data)))))
2763  populate_array_assign_ndims(ctx, ndim);
2764 
2765  jsv.is_json = false;
2766  jsv.val.jsonb = &val;
2767 
2768  /* process all the array elements */
2769  while (tok == WJB_ELEM)
2770  {
2771  /*
2772  * Recurse only if the dimensions of dimensions is still unknown or if
2773  * it is not the innermost dimension.
2774  */
2775  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2776  populate_array_element(ctx, ndim, &jsv);
2777  else
2778  {
2779  /* populate child sub-array */
2780  populate_array_dim_jsonb(ctx, &val, ndim + 1);
2781 
2782  /* number of dimensions should be already known */
2783  Assert(ctx->ndims > 0 && ctx->dims);
2784 
2785  populate_array_check_dimension(ctx, ndim);
2786  }
2787 
2788  tok = JsonbIteratorNext(&it, &val, true);
2789  }
2790 
2791  Assert(tok == WJB_END_ARRAY);
2792 
2793  /* free iterator, iterating until WJB_DONE */
2794  tok = JsonbIteratorNext(&it, &val, true);
2795  Assert(tok == WJB_DONE && !it);
2796 }
2797 
2798 /* recursively populate an array from json/jsonb */
2799 static Datum
2801  const char *colname,
2802  MemoryContext mcxt,
2803  JsValue *jsv)
2804 {
2806  Datum result;
2807  int *lbs;
2808  int i;
2809 
2810  ctx.aio = aio;
2811  ctx.mcxt = mcxt;
2812  ctx.acxt = CurrentMemoryContext;
2813  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2814  ctx.colname = colname;
2815  ctx.ndims = 0; /* unknown yet */
2816  ctx.dims = NULL;
2817  ctx.sizes = NULL;
2818 
2819  if (jsv->is_json)
2820  populate_array_json(&ctx, jsv->val.json.str,
2821  jsv->val.json.len >= 0 ? jsv->val.json.len
2822  : strlen(jsv->val.json.str));
2823  else
2824  {
2825  populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
2826  ctx.dims[0] = ctx.sizes[0];
2827  }
2828 
2829  Assert(ctx.ndims > 0);
2830 
2831  lbs = palloc(sizeof(int) * ctx.ndims);
2832 
2833  for (i = 0; i < ctx.ndims; i++)
2834  lbs[i] = 1;
2835 
2836  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2837  ctx.acxt, true);
2838 
2839  pfree(ctx.dims);
2840  pfree(ctx.sizes);
2841  pfree(lbs);
2842 
2843  return result;
2844 }
2845 
2846 static void
2848 {
2849  jso->is_json = jsv->is_json;
2850 
2851  if (jsv->is_json)
2852  {
2853  /* convert plain-text json into a hash table */
2854  jso->val.json_hash =
2855  get_json_object_as_hash(jsv->val.json.str,
2856  jsv->val.json.len >= 0
2857  ? jsv->val.json.len
2858  : strlen(jsv->val.json.str),
2859  "populate_composite");
2860  }
2861  else
2862  {
2863  JsonbValue *jbv = jsv->val.jsonb;
2864 
2865  if (jbv->type == jbvBinary &&
2866  JsonContainerIsObject(jbv->val.binary.data))
2867  {
2868  jso->val.jsonb_cont = jbv->val.binary.data;
2869  }
2870  else
2871  {
2872  bool is_scalar;
2873 
2874  is_scalar = IsAJsonbScalar(jbv) ||
2875  (jbv->type == jbvBinary &&
2876  JsonContainerIsScalar(jbv->val.binary.data));
2877  ereport(ERROR,
2878  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2879  is_scalar
2880  ? errmsg("cannot call %s on a scalar",
2881  "populate_composite")
2882  : errmsg("cannot call %s on an array",
2883  "populate_composite")));
2884  }
2885  }
2886 }
2887 
2888 /* acquire or update cached tuple descriptor for a composite type */
2889 static void
2891 {
2892  if (!io->tupdesc ||
2893  io->tupdesc->tdtypeid != io->base_typid ||
2894  io->tupdesc->tdtypmod != io->base_typmod)
2895  {
2897  io->base_typmod);
2898  MemoryContext oldcxt;
2899 
2900  if (io->tupdesc)
2901  FreeTupleDesc(io->tupdesc);
2902 
2903  /* copy tuple desc without constraints into cache memory context */
2904  oldcxt = MemoryContextSwitchTo(mcxt);
2905  io->tupdesc = CreateTupleDescCopy(tupdesc);
2906  MemoryContextSwitchTo(oldcxt);
2907 
2908  ReleaseTupleDesc(tupdesc);
2909  }
2910 }
2911 
2912 /* recursively populate a composite (row type) value from json/jsonb */
2913 static Datum
2915  Oid typid,
2916  const char *colname,
2917  MemoryContext mcxt,
2918  HeapTupleHeader defaultval,
2919  JsValue *jsv,
2920  bool isnull)
2921 {
2922  Datum result;
2923 
2924  /* acquire/update cached tuple descriptor */
2925  update_cached_tupdesc(io, mcxt);
2926 
2927  if (isnull)
2928  result = (Datum) 0;
2929  else
2930  {
2931  HeapTupleHeader tuple;
2932  JsObject jso;
2933 
2934  /* prepare input value */
2935  JsValueToJsObject(jsv, &jso);
2936 
2937  /* populate resulting record tuple */
2938  tuple = populate_record(io->tupdesc, &io->record_io,
2939  defaultval, mcxt, &jso);
2940  result = HeapTupleHeaderGetDatum(tuple);
2941 
2942  JsObjectFree(&jso);
2943  }
2944 
2945  /*
2946  * If it's domain over composite, check domain constraints. (This should
2947  * probably get refactored so that we can see the TYPECAT value, but for
2948  * now, we can tell by comparing typid to base_typid.)
2949  */
2950  if (typid != io->base_typid && typid != RECORDOID)
2951  domain_check(result, isnull, typid, &io->domain_info, mcxt);
2952 
2953  return result;
2954 }
2955 
2956 /* populate non-null scalar value from json/jsonb value */
2957 static Datum
2958 populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
2959 {
2960  Datum res;
2961  char *str = NULL;
2962  char *json = NULL;
2963 
2964  if (jsv->is_json)
2965  {
2966  int len = jsv->val.json.len;
2967 
2968  json = jsv->val.json.str;
2969  Assert(json);
2970  if (len >= 0)
2971  {
2972  /* Need to copy non-null-terminated string */
2973  str = palloc(len + 1 * sizeof(char));
2974  memcpy(str, json, len);
2975  str[len] = '\0';
2976  }
2977  else
2978  str = json; /* string is already null-terminated */
2979 
2980  /* If converting to json/jsonb, make string into valid JSON literal */
2981  if ((typid == JSONOID || typid == JSONBOID) &&
2982  jsv->val.json.type == JSON_TOKEN_STRING)
2983  {
2985 
2986  initStringInfo(&buf);
2987  escape_json(&buf, str);
2988  /* free temporary buffer */
2989  if (str != json)
2990  pfree(str);
2991  str = buf.data;
2992  }
2993  }
2994  else
2995  {
2996  JsonbValue *jbv = jsv->val.jsonb;
2997 
2998  if (typid == JSONBOID)
2999  {
3000  Jsonb *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
3001 
3002  return JsonbPGetDatum(jsonb);
3003  }
3004  /* convert jsonb to string for typio call */
3005  else if (typid == JSONOID && jbv->type != jbvBinary)
3006  {
3007  /*
3008  * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
3009  * to json string, preserving quotes around top-level strings.
3010  */
3011  Jsonb *jsonb = JsonbValueToJsonb(jbv);
3012 
3013  str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
3014  }
3015  else if (jbv->type == jbvString) /* quotes are stripped */
3016  str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
3017  else if (jbv->type == jbvBool)
3018  str = pstrdup(jbv->val.boolean ? "true" : "false");
3019  else if (jbv->type == jbvNumeric)
3021  PointerGetDatum(jbv->val.numeric)));
3022  else if (jbv->type == jbvBinary)
3023  str = JsonbToCString(NULL, jbv->val.binary.data,
3024  jbv->val.binary.len);
3025  else
3026  elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
3027  }
3028 
3029  res = InputFunctionCall(&io->typiofunc, str, io->typioparam, typmod);
3030 
3031  /* free temporary buffer */
3032  if (str != json)
3033  pfree(str);
3034 
3035  return res;
3036 }
3037 
3038 static Datum
3040  Oid typid,
3041  const char *colname,
3042  MemoryContext mcxt,
3043  JsValue *jsv,
3044  bool isnull)
3045 {
3046  Datum res;
3047 
3048  if (isnull)
3049  res = (Datum) 0;
3050  else
3051  {
3053  io->base_typid, io->base_typmod,
3054  colname, mcxt, PointerGetDatum(NULL),
3055  jsv, &isnull);
3056  Assert(!isnull);
3057  }
3058 
3059  domain_check(res, isnull, typid, &io->domain_info, mcxt);
3060 
3061  return res;
3062 }
3063 
3064 /* prepare column metadata cache for the given type */
3065 static void
3067  Oid typid,
3068  int32 typmod,
3069  MemoryContext mcxt,
3070  bool need_scalar)
3071 {
3072  HeapTuple tup;
3074 
3075  column->typid = typid;
3076  column->typmod = typmod;
3077 
3078  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3079  if (!HeapTupleIsValid(tup))
3080  elog(ERROR, "cache lookup failed for type %u", typid);
3081 
3082  type = (Form_pg_type) GETSTRUCT(tup);
3083 
3084  if (type->typtype == TYPTYPE_DOMAIN)
3085  {
3086  /*
3087  * We can move directly to the bottom base type; domain_check() will
3088  * take care of checking all constraints for a stack of domains.
3089  */
3090  Oid base_typid;
3091  int32 base_typmod = typmod;
3092 
3093  base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
3094  if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
3095  {
3096  /* domain over composite has its own code path */
3097  column->typcat = TYPECAT_COMPOSITE_DOMAIN;
3098  column->io.composite.record_io = NULL;
3099  column->io.composite.tupdesc = NULL;
3100  column->io.composite.base_typid = base_typid;
3101  column->io.composite.base_typmod = base_typmod;
3102  column->io.composite.domain_info = NULL;
3103  }
3104  else
3105  {
3106  /* domain over anything else */
3107  column->typcat = TYPECAT_DOMAIN;
3108  column->io.domain.base_typid = base_typid;
3109  column->io.domain.base_typmod = base_typmod;
3110  column->io.domain.base_io =
3111  MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3112  column->io.domain.domain_info = NULL;
3113  }
3114  }
3115  else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3116  {
3117  column->typcat = TYPECAT_COMPOSITE;
3118  column->io.composite.record_io = NULL;
3119  column->io.composite.tupdesc = NULL;
3120  column->io.composite.base_typid = typid;
3121  column->io.composite.base_typmod = typmod;
3122  column->io.composite.domain_info = NULL;
3123  }
3124  else if (IsTrueArrayType(type))
3125  {
3126  column->typcat = TYPECAT_ARRAY;
3128  sizeof(ColumnIOData));
3129  column->io.array.element_type = type->typelem;
3130  /* array element typemod stored in attribute's typmod */
3131  column->io.array.element_typmod = typmod;
3132  }
3133  else
3134  {
3135  column->typcat = TYPECAT_SCALAR;
3136  need_scalar = true;
3137  }
3138 
3139  /* caller can force us to look up scalar_io info even for non-scalars */
3140  if (need_scalar)
3141  {
3142  Oid typioproc;
3143 
3144  getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
3145  fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
3146  }
3147 
3148  ReleaseSysCache(tup);
3149 }
3150 
3151 /* recursively populate a record field or an array element from a json/jsonb value */
3152 static Datum
3154  Oid typid,
3155  int32 typmod,
3156  const char *colname,
3157  MemoryContext mcxt,
3158  Datum defaultval,
3159  JsValue *jsv,
3160  bool *isnull)
3161 {
3162  TypeCat typcat;
3163 
3165 
3166  /*
3167  * Prepare column metadata cache for the given type. Force lookup of the
3168  * scalar_io data so that the json string hack below will work.
3169  */
3170  if (col->typid != typid || col->typmod != typmod)
3171  prepare_column_cache(col, typid, typmod, mcxt, true);
3172 
3173  *isnull = JsValueIsNull(jsv);
3174 
3175  typcat = col->typcat;
3176 
3177  /* try to convert json string to a non-scalar type through input function */
3178  if (JsValueIsString(jsv) &&
3179  (typcat == TYPECAT_ARRAY ||
3180  typcat == TYPECAT_COMPOSITE ||
3181  typcat == TYPECAT_COMPOSITE_DOMAIN))
3182  typcat = TYPECAT_SCALAR;
3183 
3184  /* we must perform domain checks for NULLs, otherwise exit immediately */
3185  if (*isnull &&
3186  typcat != TYPECAT_DOMAIN &&
3187  typcat != TYPECAT_COMPOSITE_DOMAIN)
3188  return (Datum) 0;
3189 
3190  switch (typcat)
3191  {
3192  case TYPECAT_SCALAR:
3193  return populate_scalar(&col->scalar_io, typid, typmod, jsv);
3194 
3195  case TYPECAT_ARRAY:
3196  return populate_array(&col->io.array, colname, mcxt, jsv);
3197 
3198  case TYPECAT_COMPOSITE:
3200  return populate_composite(&col->io.composite, typid,
3201  colname, mcxt,
3202  DatumGetPointer(defaultval)
3203  ? DatumGetHeapTupleHeader(defaultval)
3204  : NULL,
3205  jsv, *isnull);
3206 
3207  case TYPECAT_DOMAIN:
3208  return populate_domain(&col->io.domain, typid, colname, mcxt,
3209  jsv, *isnull);
3210 
3211  default:
3212  elog(ERROR, "unrecognized type category '%c'", typcat);
3213  return (Datum) 0;
3214  }
3215 }
3216 
3217 static RecordIOData *
3219 {
3221  MemoryContextAlloc(mcxt,
3222  offsetof(RecordIOData, columns) +
3223  ncolumns * sizeof(ColumnIOData));
3224 
3225  data->record_type = InvalidOid;
3226  data->record_typmod = 0;
3227  data->ncolumns = ncolumns;
3228  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3229 
3230  return data;
3231 }
3232 
3233 static bool
3234 JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
3235 {
3236  jsv->is_json = obj->is_json;
3237 
3238  if (jsv->is_json)
3239  {
3240  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3241  HASH_FIND, NULL);
3242 
3243  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3244  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3245  hashentry->val;
3246  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3247 
3248  return hashentry != NULL;
3249  }
3250  else
3251  {
3252  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3253  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3254  NULL);
3255 
3256  return jsv->val.jsonb != NULL;
3257  }
3258 }
3259 
3260 /* populate a record tuple from json/jsonb value */
3261 static HeapTupleHeader
3263  RecordIOData **record_p,
3264  HeapTupleHeader defaultval,
3265  MemoryContext mcxt,
3266  JsObject *obj)
3267 {
3268  RecordIOData *record = *record_p;
3269  Datum *values;
3270  bool *nulls;
3271  HeapTuple res;
3272  int ncolumns = tupdesc->natts;
3273  int i;
3274 
3275  /*
3276  * if the input json is empty, we can only skip the rest if we were passed
3277  * in a non-null record, since otherwise there may be issues with domain
3278  * nulls.
3279  */
3280  if (defaultval && JsObjectIsEmpty(obj))
3281  return defaultval;
3282 
3283  /* (re)allocate metadata cache */
3284  if (record == NULL ||
3285  record->ncolumns != ncolumns)
3286  *record_p = record = allocate_record_info(mcxt, ncolumns);
3287 
3288  /* invalidate metadata cache if the record type has changed */
3289  if (record->record_type != tupdesc->tdtypeid ||
3290  record->record_typmod != tupdesc->tdtypmod)
3291  {
3292  MemSet(record, 0, offsetof(RecordIOData, columns) +
3293  ncolumns * sizeof(ColumnIOData));
3294  record->record_type = tupdesc->tdtypeid;
3295  record->record_typmod = tupdesc->tdtypmod;
3296  record->ncolumns = ncolumns;
3297  }
3298 
3299  values = (Datum *) palloc(ncolumns * sizeof(Datum));
3300  nulls = (bool *) palloc(ncolumns * sizeof(bool));
3301 
3302  if (defaultval)
3303  {
3304  HeapTupleData tuple;
3305 
3306  /* Build a temporary HeapTuple control structure */
3307  tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
3308  ItemPointerSetInvalid(&(tuple.t_self));
3309  tuple.t_tableOid = InvalidOid;
3310  tuple.t_data = defaultval;
3311 
3312  /* Break down the tuple into fields */
3313  heap_deform_tuple(&tuple, tupdesc, values, nulls);
3314  }
3315  else
3316  {
3317  for (i = 0; i < ncolumns; ++i)
3318  {
3319  values[i] = (Datum) 0;
3320  nulls[i] = true;
3321  }
3322  }
3323 
3324  for (i = 0; i < ncolumns; ++i)
3325  {
3326  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
3327  char *colname = NameStr(att->attname);
3328  JsValue field = {0};
3329  bool found;
3330 
3331  /* Ignore dropped columns in datatype */
3332  if (att->attisdropped)
3333  {
3334  nulls[i] = true;
3335  continue;
3336  }
3337 
3338  found = JsObjectGetField(obj, colname, &field);
3339 
3340  /*
3341  * we can't just skip here if the key wasn't found since we might have
3342  * a domain to deal with. If we were passed in a non-null record
3343  * datum, we assume that the existing values are valid (if they're
3344  * not, then it's not our fault), but if we were passed in a null,
3345  * then every field which we don't populate needs to be run through
3346  * the input function just in case it's a domain type.
3347  */
3348  if (defaultval && !found)
3349  continue;
3350 
3351  values[i] = populate_record_field(&record->columns[i],
3352  att->atttypid,
3353  att->atttypmod,
3354  colname,
3355  mcxt,
3356  nulls[i] ? (Datum) 0 : values[i],
3357  &field,
3358  &nulls[i]);
3359  }
3360 
3361  res = heap_form_tuple(tupdesc, values, nulls);
3362 
3363  pfree(values);
3364  pfree(nulls);
3365 
3366  return res->t_data;
3367 }
3368 
3369 /*
3370  * Setup for json{b}_populate_record{set}: result type will be same as first
3371  * argument's type --- unless first argument is "null::record", which we can't
3372  * extract type info from; we handle that later.
3373  */
3374 static void
3376  const char *funcname,
3377  PopulateRecordCache *cache)
3378 {
3379  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3380  prepare_column_cache(&cache->c,
3381  cache->argtype, -1,
3382  cache->fn_mcxt, false);
3383  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3384  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3385  ereport(ERROR,
3386  (errcode(ERRCODE_DATATYPE_MISMATCH),
3387  /* translator: %s is a function name, eg json_to_record */
3388  errmsg("first argument of %s must be a row type",
3389  funcname)));
3390 }
3391 
3392 /*
3393  * Setup for json{b}_to_record{set}: result type is specified by calling
3394  * query. We'll also use this code for json{b}_populate_record{set},
3395  * if we discover that the first argument is a null of type RECORD.
3396  *
3397  * Here it is syntactically impossible to specify the target type
3398  * as domain-over-composite.
3399  */
3400 static void
3402  const char *funcname,
3403  PopulateRecordCache *cache)
3404 {
3405  TupleDesc tupdesc;
3406  MemoryContext old_cxt;
3407 
3408  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3409  ereport(ERROR,
3410  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3411  /* translator: %s is a function name, eg json_to_record */
3412  errmsg("could not determine row type for result of %s",
3413  funcname),
3414  errhint("Provide a non-null record argument, "
3415  "or call the function in the FROM clause "
3416  "using a column definition list.")));
3417 
3418  Assert(tupdesc);
3419  cache->argtype = tupdesc->tdtypeid;
3420 
3421  /* If we go through this more than once, avoid memory leak */
3422  if (cache->c.io.composite.tupdesc)
3424 
3425  /* Save identified tupdesc */
3426  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3427  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3428  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3429  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3430  MemoryContextSwitchTo(old_cxt);
3431 }
3432 
3433 /*
3434  * common worker for json{b}_populate_record() and json{b}_to_record()
3435  * is_json and have_record_arg identify the specific function
3436  */
3437 static Datum
3438 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
3439  bool is_json, bool have_record_arg)
3440 {
3441  int json_arg_num = have_record_arg ? 1 : 0;
3442  JsValue jsv = {0};
3443  HeapTupleHeader rec;
3444  Datum rettuple;
3445  JsonbValue jbv;
3446  MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
3447  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3448 
3449  /*
3450  * If first time through, identify input/result record type. Note that
3451  * this stanza looks only at fcinfo context, which can't change during the
3452  * query; so we may not be able to fully resolve a RECORD input type yet.
3453  */
3454  if (!cache)
3455  {
3456  fcinfo->flinfo->fn_extra = cache =
3457  MemoryContextAllocZero(fnmcxt, sizeof(*cache));
3458  cache->fn_mcxt = fnmcxt;
3459 
3460  if (have_record_arg)
3461  get_record_type_from_argument(fcinfo, funcname, cache);
3462  else
3463  get_record_type_from_query(fcinfo, funcname, cache);
3464  }
3465 
3466  /* Collect record arg if we have one */
3467  if (!have_record_arg)
3468  rec = NULL; /* it's json{b}_to_record() */
3469  else if (!PG_ARGISNULL(0))
3470  {
3471  rec = PG_GETARG_HEAPTUPLEHEADER(0);
3472 
3473  /*
3474  * When declared arg type is RECORD, identify actual record type from
3475  * the tuple itself.
3476  */
3477  if (cache->argtype == RECORDOID)
3478  {
3481  }
3482  }
3483  else
3484  {
3485  rec = NULL;
3486 
3487  /*
3488  * When declared arg type is RECORD, identify actual record type from
3489  * calling query, or fail if we can't.
3490  */
3491  if (cache->argtype == RECORDOID)
3492  {
3493  get_record_type_from_query(fcinfo, funcname, cache);
3494  /* This can't change argtype, which is important for next time */
3495  Assert(cache->argtype == RECORDOID);
3496  }
3497  }
3498 
3499  /* If no JSON argument, just return the record (if any) unchanged */
3500  if (PG_ARGISNULL(json_arg_num))
3501  {
3502  if (rec)
3503  PG_RETURN_POINTER(rec);
3504  else
3505  PG_RETURN_NULL();
3506  }
3507 
3508  jsv.is_json = is_json;
3509 
3510  if (is_json)
3511  {
3512  text *json = PG_GETARG_TEXT_PP(json_arg_num);
3513 
3514  jsv.val.json.str = VARDATA_ANY(json);
3515  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3516  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3517  * populate_composite() */
3518  }
3519  else
3520  {
3521  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3522 
3523  jsv.val.jsonb = &jbv;
3524 
3525  /* fill binary jsonb value pointing to jb */
3526  jbv.type = jbvBinary;
3527  jbv.val.binary.data = &jb->root;
3528  jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
3529  }
3530 
3531  rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
3532  NULL, fnmcxt, rec, &jsv, false);
3533 
3534  PG_RETURN_DATUM(rettuple);
3535 }
3536 
3537 /*
3538  * get_json_object_as_hash
3539  *
3540  * decompose a json object into a hash table.
3541  */
3542 static HTAB *
3543 get_json_object_as_hash(char *json, int len, const char *funcname)
3544 {
3545  HASHCTL ctl;
3546  HTAB *tab;
3547  JHashState *state;
3549  JsonSemAction *sem;
3550 
3551  ctl.keysize = NAMEDATALEN;
3552  ctl.entrysize = sizeof(JsonHashEntry);
3553  ctl.hcxt = CurrentMemoryContext;
3554  tab = hash_create("json object hashtable",
3555  100,
3556  &ctl,
3558 
3559  state = palloc0(sizeof(JHashState));
3560  sem = palloc0(sizeof(JsonSemAction));
3561 
3562  state->function_name = funcname;
3563  state->hash = tab;
3564  state->lex = lex;
3565 
3566  sem->semstate = (void *) state;
3568  sem->scalar = hash_scalar;
3571 
3572  pg_parse_json_or_ereport(lex, sem);
3573 
3574  return tab;
3575 }
3576 
3577 static JsonParseErrorType
3578 hash_object_field_start(void *state, char *fname, bool isnull)
3579 {
3580  JHashState *_state = (JHashState *) state;
3581 
3582  if (_state->lex->lex_level > 1)
3583  return JSON_SUCCESS;
3584 
3585  /* remember token type */
3586  _state->saved_token_type = _state->lex->token_type;
3587 
3588  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3590  {
3591  /* remember start position of the whole text of the subobject */
3592  _state->save_json_start = _state->lex->token_start;
3593  }
3594  else
3595  {
3596  /* must be a scalar */
3597  _state->save_json_start = NULL;
3598  }
3599 
3600  return JSON_SUCCESS;
3601 }
3602 
3603 static JsonParseErrorType
3604 hash_object_field_end(void *state, char *fname, bool isnull)
3605 {
3606  JHashState *_state = (JHashState *) state;
3607  JsonHashEntry *hashentry;
3608  bool found;
3609 
3610  /*
3611  * Ignore nested fields.
3612  */
3613  if (_state->lex->lex_level > 1)
3614  return JSON_SUCCESS;
3615 
3616  /*
3617  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3618  * (Note: without this test, the hash code would truncate the string at
3619  * NAMEDATALEN-1, and could then match against a similarly-truncated
3620  * record field name. That would be a reasonable behavior, but this code
3621  * has previously insisted on exact equality, so we keep this behavior.)
3622  */
3623  if (strlen(fname) >= NAMEDATALEN)
3624  return JSON_SUCCESS;
3625 
3626  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3627 
3628  /*
3629  * found being true indicates a duplicate. We don't do anything about
3630  * that, a later field with the same name overrides the earlier field.
3631  */
3632 
3633  hashentry->type = _state->saved_token_type;
3634  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3635 
3636  if (_state->save_json_start != NULL)
3637  {
3638  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3639  char *val = palloc((len + 1) * sizeof(char));
3640 
3641  memcpy(val, _state->save_json_start, len);
3642  val[len] = '\0';
3643  hashentry->val = val;
3644  }
3645  else
3646  {
3647  /* must have had a scalar instead */
3648  hashentry->val = _state->saved_scalar;
3649  }
3650 
3651  return JSON_SUCCESS;
3652 }
3653 
3654 static JsonParseErrorType
3656 {
3657  JHashState *_state = (JHashState *) state;
3658 
3659  if (_state->lex->lex_level == 0)
3660  ereport(ERROR,
3661  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3662  errmsg("cannot call %s on an array", _state->function_name)));
3663 
3664  return JSON_SUCCESS;
3665 }
3666 
3667 static JsonParseErrorType
3668 hash_scalar(void *state, char *token, JsonTokenType tokentype)
3669 {
3670  JHashState *_state = (JHashState *) state;
3671 
3672  if (_state->lex->lex_level == 0)
3673  ereport(ERROR,
3674  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3675  errmsg("cannot call %s on a scalar", _state->function_name)));
3676 
3677  if (_state->lex->lex_level == 1)
3678  {
3679  _state->saved_scalar = token;
3680  /* saved_token_type must already be set in hash_object_field_start() */
3681  Assert(_state->saved_token_type == tokentype);
3682  }
3683 
3684  return JSON_SUCCESS;
3685 }
3686 
3687 
3688 /*
3689  * SQL function json_populate_recordset
3690  *
3691  * set fields in a set of records from the argument json,
3692  * which must be an array of objects.
3693  *
3694  * similar to json_populate_record, but the tuple-building code
3695  * is pushed down into the semantic action handlers so it's done
3696  * per object in the array.
3697  */
3698 Datum
3700 {
3701  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3702  false, true);
3703 }
3704 
3705 Datum
3707 {
3708  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3709  false, false);
3710 }
3711 
3712 Datum
3714 {
3715  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3716  true, true);
3717 }
3718 
3719 Datum
3721 {
3722  return populate_recordset_worker(fcinfo, "json_to_recordset",
3723  true, false);
3724 }
3725 
3726 static void
3728 {
3729  PopulateRecordCache *cache = state->cache;
3730  HeapTupleHeader tuphead;
3731  HeapTupleData tuple;
3732 
3733  /* acquire/update cached tuple descriptor */
3734  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
3735 
3736  /* replace record fields from json */
3737  tuphead = populate_record(cache->c.io.composite.tupdesc,
3738  &cache->c.io.composite.record_io,
3739  state->rec,
3740  cache->fn_mcxt,
3741  obj);
3742 
3743  /* if it's domain over composite, check domain constraints */
3744  if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
3745  domain_check(HeapTupleHeaderGetDatum(tuphead), false,
3746  cache->argtype,
3747  &cache->c.io.composite.domain_info,
3748  cache->fn_mcxt);
3749 
3750  /* ok, save into tuplestore */
3751  tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
3752  ItemPointerSetInvalid(&(tuple.t_self));
3753  tuple.t_tableOid = InvalidOid;
3754  tuple.t_data = tuphead;
3755 
3756  tuplestore_puttuple(state->tuple_store, &tuple);
3757 }
3758 
3759 /*
3760  * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
3761  * is_json and have_record_arg identify the specific function
3762  */
3763 static Datum
3764 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
3765  bool is_json, bool have_record_arg)
3766 {
3767  int json_arg_num = have_record_arg ? 1 : 0;
3768  ReturnSetInfo *rsi;
3769  MemoryContext old_cxt;
3770  HeapTupleHeader rec;
3771  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3773 
3774  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
3775 
3776  if (!rsi || !IsA(rsi, ReturnSetInfo))
3777  ereport(ERROR,
3778  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3779  errmsg("set-valued function called in context that cannot accept a set")));
3780 
3781  if (!(rsi->allowedModes & SFRM_Materialize))
3782  ereport(ERROR,
3783  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3784  errmsg("materialize mode required, but it is not allowed in this context")));
3785 
3787 
3788  /*
3789  * If first time through, identify input/result record type. Note that
3790  * this stanza looks only at fcinfo context, which can't change during the
3791  * query; so we may not be able to fully resolve a RECORD input type yet.
3792  */
3793  if (!cache)
3794  {
3795  fcinfo->flinfo->fn_extra = cache =
3796  MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
3797  cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
3798 
3799  if (have_record_arg)
3800  get_record_type_from_argument(fcinfo, funcname, cache);
3801  else
3802  get_record_type_from_query(fcinfo, funcname, cache);
3803  }
3804 
3805  /* Collect record arg if we have one */
3806  if (!have_record_arg)
3807  rec = NULL; /* it's json{b}_to_recordset() */
3808  else if (!PG_ARGISNULL(0))
3809  {
3810  rec = PG_GETARG_HEAPTUPLEHEADER(0);
3811 
3812  /*
3813  * When declared arg type is RECORD, identify actual record type from
3814  * the tuple itself.
3815  */
3816  if (cache->argtype == RECORDOID)
3817  {
3820  }
3821  }
3822  else
3823  {
3824  rec = NULL;
3825 
3826  /*
3827  * When declared arg type is RECORD, identify actual record type from
3828  * calling query, or fail if we can't.
3829  */
3830  if (cache->argtype == RECORDOID)
3831  {
3832  get_record_type_from_query(fcinfo, funcname, cache);
3833  /* This can't change argtype, which is important for next time */
3834  Assert(cache->argtype == RECORDOID);
3835  }
3836  }
3837 
3838  /* if the json is null send back an empty set */
3839  if (PG_ARGISNULL(json_arg_num))
3840  PG_RETURN_NULL();
3841 
3842  /*
3843  * Forcibly update the cached tupdesc, to ensure we have the right tupdesc
3844  * to return even if the JSON contains no rows.
3845  */
3846  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
3847 
3849 
3850  /* make tuplestore in a sufficiently long-lived memory context */
3852  state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
3854  false, work_mem);
3855  MemoryContextSwitchTo(old_cxt);
3856 
3857  state->function_name = funcname;
3858  state->cache = cache;
3859  state->rec = rec;
3860 
3861  if (is_json)
3862  {
3863  text *json = PG_GETARG_TEXT_PP(json_arg_num);
3864  JsonLexContext *lex;
3865  JsonSemAction *sem;
3866 
3867  sem = palloc0(sizeof(JsonSemAction));
3868 
3869  lex = makeJsonLexContext(json, true);
3870 
3871  sem->semstate = (void *) state;
3879 
3880  state->lex = lex;
3881 
3882  pg_parse_json_or_ereport(lex, sem);
3883  }
3884  else
3885  {
3886  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3887  JsonbIterator *it;
3888  JsonbValue v;
3889  bool skipNested = false;
3891 
3892  if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
3893  ereport(ERROR,
3894  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3895  errmsg("cannot call %s on a non-array",
3896  funcname)));
3897 
3898  it = JsonbIteratorInit(&jb->root);
3899 
3900  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
3901  {
3902  skipNested = true;
3903 
3904  if (r == WJB_ELEM)
3905  {
3906  JsObject obj;
3907 
3908  if (v.type != jbvBinary ||
3909  !JsonContainerIsObject(v.val.binary.data))
3910  ereport(ERROR,
3911  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3912  errmsg("argument of %s must be an array of objects",
3913  funcname)));
3914 
3915  obj.is_json = false;
3916  obj.val.jsonb_cont = v.val.binary.data;
3917 
3919  }
3920  }
3921  }
3922 
3923  /*
3924  * Note: we must copy the cached tupdesc because the executor will free
3925  * the passed-back setDesc, but we want to hang onto the cache in case
3926  * we're called again in the same query.
3927  */
3928  rsi->setResult = state->tuple_store;
3930 
3931  PG_RETURN_NULL();
3932 }
3933 
3934 static JsonParseErrorType
3936 {
3938  int lex_level = _state->lex->lex_level;
3939  HASHCTL ctl;
3940 
3941  /* Reject object at top level: we must have an array at level 0 */
3942  if (lex_level == 0)
3943  ereport(ERROR,
3944  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3945  errmsg("cannot call %s on an object",
3946  _state->function_name)));
3947 
3948  /* Nested objects require no special processing */
3949  if (lex_level > 1)
3950  return JSON_SUCCESS;
3951 
3952  /* Object at level 1: set up a new hash table for this object */
3953  ctl.keysize = NAMEDATALEN;
3954  ctl.entrysize = sizeof(JsonHashEntry);
3955  ctl.hcxt = CurrentMemoryContext;
3956  _state->json_hash = hash_create("json object hashtable",
3957  100,
3958  &ctl,
3960 
3961  return JSON_SUCCESS;
3962 }
3963 
3964 static JsonParseErrorType
3966 {
3968  JsObject obj;
3969 
3970  /* Nested objects require no special processing */
3971  if (_state->lex->lex_level > 1)
3972  return JSON_SUCCESS;
3973 
3974  obj.is_json = true;
3975  obj.val.json_hash = _state->json_hash;
3976 
3977  /* Otherwise, construct and return a tuple based on this level-1 object */
3978  populate_recordset_record(_state, &obj);
3979 
3980  /* Done with hash for this object */
3981  hash_destroy(_state->json_hash);
3982  _state->json_hash = NULL;
3983 
3984  return JSON_SUCCESS;
3985 }
3986 
3987 static JsonParseErrorType
3989 {
3991 
3992  if (_state->lex->lex_level == 1 &&
3994  ereport(ERROR,
3995  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3996  errmsg("argument of %s must be an array of objects",
3997  _state->function_name)));
3998 
3999  return JSON_SUCCESS;
4000 }
4001 
4002 static JsonParseErrorType
4004 {
4005  /* nothing to do */
4006  return JSON_SUCCESS;
4007 }
4008 
4009 static JsonParseErrorType
4010 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
4011 {
4013 
4014  if (_state->lex->lex_level == 0)
4015  ereport(ERROR,
4016  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4017  errmsg("cannot call %s on a scalar",
4018  _state->function_name)));
4019 
4020  if (_state->lex->lex_level == 2)
4021  _state->saved_scalar = token;
4022 
4023  return JSON_SUCCESS;
4024 }
4025 
4026 static JsonParseErrorType
4027 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
4028 {
4030 
4031  if (_state->lex->lex_level > 2)
4032  return JSON_SUCCESS;
4033 
4034  _state->saved_token_type = _state->lex->token_type;
4035 
4036  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
4038  {
4039  _state->save_json_start = _state->lex->token_start;
4040  }
4041  else
4042  {
4043  _state->save_json_start = NULL;
4044  }
4045 
4046  return JSON_SUCCESS;
4047 }
4048 
4049 static JsonParseErrorType
4050 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
4051 {
4053  JsonHashEntry *hashentry;
4054  bool found;
4055 
4056  /*
4057  * Ignore nested fields.
4058  */
4059  if (_state->lex->lex_level > 2)
4060  return JSON_SUCCESS;
4061 
4062  /*
4063  * Ignore field names >= NAMEDATALEN - they can't match a record field.
4064  * (Note: without this test, the hash code would truncate the string at
4065  * NAMEDATALEN-1, and could then match against a similarly-truncated
4066  * record field name. That would be a reasonable behavior, but this code
4067  * has previously insisted on exact equality, so we keep this behavior.)
4068  */
4069  if (strlen(fname) >= NAMEDATALEN)
4070  return JSON_SUCCESS;
4071 
4072  hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
4073 
4074  /*
4075  * found being true indicates a duplicate. We don't do anything about
4076  * that, a later field with the same name overrides the earlier field.
4077  */
4078 
4079  hashentry->type = _state->saved_token_type;
4080  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
4081 
4082  if (_state->save_json_start != NULL)
4083  {
4084  int len = _state->lex->prev_token_terminator - _state->save_json_start;
4085  char *val = palloc((len + 1) * sizeof(char));
4086 
4087  memcpy(val, _state->save_json_start, len);
4088  val[len] = '\0';
4089  hashentry->val = val;
4090  }
4091  else
4092  {
4093  /* must have had a scalar instead */
4094  hashentry->val = _state->saved_scalar;
4095  }
4096 
4097  return JSON_SUCCESS;
4098 }
4099 
4100 /*
4101  * Semantic actions for json_strip_nulls.
4102  *
4103  * Simply repeat the input on the output unless we encounter
4104  * a null object field. State for this is set when the field
4105  * is started and reset when the scalar action (which must be next)
4106  * is called.
4107  */
4108 
4109 static JsonParseErrorType
4111 {
4112  StripnullState *_state = (StripnullState *) state;
4113 
4114  appendStringInfoCharMacro(_state->strval, '{');
4115 
4116  return JSON_SUCCESS;
4117 }
4118 
4119 static JsonParseErrorType
4121 {
4122  StripnullState *_state = (StripnullState *) state;
4123 
4124  appendStringInfoCharMacro(_state->strval, '}');
4125 
4126  return JSON_SUCCESS;
4127 }
4128 
4129 static JsonParseErrorType
4131 {
4132  StripnullState *_state = (StripnullState *) state;
4133 
4134  appendStringInfoCharMacro(_state->strval, '[');
4135 
4136  return JSON_SUCCESS;
4137 }
4138 
4139 static JsonParseErrorType
4141 {
4142  StripnullState *_state = (StripnullState *) state;
4143 
4144  appendStringInfoCharMacro(_state->strval, ']');
4145 
4146  return JSON_SUCCESS;
4147 }
4148 
4149 static JsonParseErrorType
4150 sn_object_field_start(void *state, char *fname, bool isnull)
4151 {
4152  StripnullState *_state = (StripnullState *) state;
4153 
4154  if (isnull)
4155  {
4156  /*
4157  * The next thing must be a scalar or isnull couldn't be true, so
4158  * there is no danger of this state being carried down into a nested
4159  * object or array. The flag will be reset in the scalar action.
4160  */
4161  _state->skip_next_null = true;
4162  return JSON_SUCCESS;
4163  }
4164 
4165  if (_state->strval->data[_state->strval->len - 1] != '{')
4166  appendStringInfoCharMacro(_state->strval, ',');
4167 
4168  /*
4169  * Unfortunately we don't have the quoted and escaped string any more, so
4170  * we have to re-escape it.
4171  */
4172  escape_json(_state->strval, fname);
4173 
4174  appendStringInfoCharMacro(_state->strval, ':');
4175 
4176  return JSON_SUCCESS;
4177 }
4178 
4179 static JsonParseErrorType
4180 sn_array_element_start(void *state, bool isnull)
4181 {
4182  StripnullState *_state = (StripnullState *) state;
4183 
4184  if (_state->strval->data[_state->strval->len - 1] != '[')
4185  appendStringInfoCharMacro(_state->strval, ',');
4186 
4187  return JSON_SUCCESS;
4188 }
4189 
4190 static JsonParseErrorType
4191 sn_scalar(void *state, char *token, JsonTokenType tokentype)
4192 {
4193  StripnullState *_state = (StripnullState *) state;
4194 
4195  if (_state->skip_next_null)
4196  {
4197  Assert(tokentype == JSON_TOKEN_NULL);
4198  _state->skip_next_null = false;
4199  return JSON_SUCCESS;
4200  }
4201 
4202  if (tokentype == JSON_TOKEN_STRING)
4203  escape_json(_state->strval, token);
4204  else
4205  appendStringInfoString(_state->strval, token);
4206 
4207  return JSON_SUCCESS;
4208 }
4209 
4210 /*
4211  * SQL function json_strip_nulls(json) -> json
4212  */
4213 Datum
4215 {
4216  text *json = PG_GETARG_TEXT_PP(0);
4218  JsonLexContext *lex;
4219  JsonSemAction *sem;
4220 
4221  lex = makeJsonLexContext(json, true);
4222  state = palloc0(sizeof(StripnullState));
4223  sem = palloc0(sizeof(JsonSemAction));
4224 
4225  state->strval = makeStringInfo();
4226  state->skip_next_null = false;
4227  state->lex = lex;
4228 
4229  sem->semstate = (void *) state;
4231  sem->object_end = sn_object_end;
4232  sem->array_start = sn_array_start;
4233  sem->array_end = sn_array_end;
4234  sem->scalar = sn_scalar;
4237 
4238  pg_parse_json_or_ereport(lex, sem);
4239 
4241  state->strval->len));
4242 }
4243 
4244 /*
4245  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
4246  */
4247 Datum
4249 {
4250  Jsonb *jb = PG_GETARG_JSONB_P(0);
4251  JsonbIterator *it;
4252  JsonbParseState *parseState = NULL;
4253  JsonbValue *res = NULL;
4254  JsonbValue v,
4255  k;
4257  bool last_was_key = false;
4258 
4259  if (JB_ROOT_IS_SCALAR(jb))
4260  PG_RETURN_POINTER(jb);
4261 
4262  it = JsonbIteratorInit(&jb->root);
4263 
4264  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4265  {
4266  Assert(!(type == WJB_KEY && last_was_key));
4267 
4268  if (type == WJB_KEY)
4269  {
4270  /* stash the key until we know if it has a null value */
4271  k = v;
4272  last_was_key = true;
4273  continue;
4274  }
4275 
4276  if (last_was_key)
4277  {
4278  /* if the last element was a key this one can't be */
4279  last_was_key = false;
4280 
4281  /* skip this field if value is null */
4282  if (type == WJB_VALUE && v.type == jbvNull)
4283  continue;
4284 
4285  /* otherwise, do a delayed push of the key */
4286  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4287  }
4288 
4289  if (type == WJB_VALUE || type == WJB_ELEM)
4290  res = pushJsonbValue(&parseState, type, &v);
4291  else
4292  res = pushJsonbValue(&parseState, type, NULL);
4293  }
4294 
4295  Assert(res != NULL);
4296 
4298 }
4299 
4300 /*
4301  * SQL function jsonb_pretty (jsonb)
4302  *
4303  * Pretty-printed text for the jsonb
4304  */
4305 Datum
4307 {
4308  Jsonb *jb = PG_GETARG_JSONB_P(0);
4310 
4311  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4312 
4314 }
4315 
4316 /*
4317  * SQL function jsonb_concat (jsonb, jsonb)
4318  *
4319  * function for || operator
4320  */
4321 Datum
4323 {
4324  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4325  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4326  JsonbParseState *state = NULL;
4327  JsonbValue *res;
4328  JsonbIterator *it1,
4329  *it2;
4330 
4331  /*
4332  * If one of the jsonb is empty, just return the other if it's not scalar
4333  * and both are of the same kind. If it's a scalar or they are of
4334  * different kinds we need to perform the concatenation even if one is
4335  * empty.
4336  */
4337  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4338  {
4339  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4340  PG_RETURN_JSONB_P(jb2);
4341  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4342  PG_RETURN_JSONB_P(jb1);
4343  }
4344 
4345  it1 = JsonbIteratorInit(&jb1->root);
4346  it2 = JsonbIteratorInit(&jb2->root);
4347 
4348  res = IteratorConcat(&it1, &it2, &state);
4349 
4350  Assert(res != NULL);
4351 
4353 }
4354 
4355 
4356 /*
4357  * SQL function jsonb_delete (jsonb, text)
4358  *
4359  * return a copy of the jsonb with the indicated item
4360  * removed.
4361  */
4362 Datum
4364 {
4365  Jsonb *in = PG_GETARG_JSONB_P(0);
4366  text *key = PG_GETARG_TEXT_PP(1);
4367  char *keyptr = VARDATA_ANY(key);
4368  int keylen = VARSIZE_ANY_EXHDR(key);
4369  JsonbParseState *state = NULL;
4370  JsonbIterator *it;
4371  JsonbValue v,
4372  *res = NULL;
4373  bool skipNested = false;
4375 
4376  if (JB_ROOT_IS_SCALAR(in))
4377  ereport(ERROR,
4378  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4379  errmsg("cannot delete from scalar")));
4380 
4381  if (JB_ROOT_COUNT(in) == 0)
4382  PG_RETURN_JSONB_P(in);
4383 
4384  it = JsonbIteratorInit(&in->root);
4385 
4386  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4387  {
4388  skipNested = true;
4389 
4390  if ((r == WJB_ELEM || r == WJB_KEY) &&
4391  (v.type == jbvString && keylen == v.val.string.len &&
4392  memcmp(keyptr, v.val.string.val, keylen) == 0))
4393  {
4394  /* skip corresponding value as well */
4395  if (r == WJB_KEY)
4396  (void) JsonbIteratorNext(&it, &v, true);
4397 
4398  continue;
4399  }
4400 
4401  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4402  }
4403 
4404  Assert(res != NULL);
4405 
4407 }
4408 
4409 /*
4410  * SQL function jsonb_delete (jsonb, variadic text[])
4411  *
4412  * return a copy of the jsonb with the indicated items
4413  * removed.
4414  */
4415 Datum
4417 {
4418  Jsonb *in = PG_GETARG_JSONB_P(0);
4419  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4420  Datum *keys_elems;
4421  bool *keys_nulls;
4422  int keys_len;
4423  JsonbParseState *state = NULL;
4424  JsonbIterator *it;
4425  JsonbValue v,
4426  *res = NULL;
4427  bool skipNested = false;
4429 
4430  if (ARR_NDIM(keys) > 1)
4431  ereport(ERROR,
4432  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4433  errmsg("wrong number of array subscripts")));
4434 
4435  if (JB_ROOT_IS_SCALAR(in))
4436  ereport(ERROR,
4437  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4438  errmsg("cannot delete from scalar")));
4439 
4440  if (JB_ROOT_COUNT(in) == 0)
4441  PG_RETURN_JSONB_P(in);
4442 
4443  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4444 
4445  if (keys_len == 0)
4446  PG_RETURN_JSONB_P(in);
4447 
4448  it = JsonbIteratorInit(&in->root);
4449 
4450  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4451  {
4452  skipNested = true;
4453 
4454  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4455  {
4456  int i;
4457  bool found = false;
4458 
4459  for (i = 0; i < keys_len; i++)
4460  {
4461  char *keyptr;
4462  int keylen;
4463 
4464  if (keys_nulls[i])
4465  continue;
4466 
4467  /* We rely on the array elements not being toasted */
4468  keyptr = VARDATA_ANY(keys_elems[i]);
4469  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4470  if (keylen == v.val.string.len &&
4471  memcmp(keyptr, v.val.string.val, keylen) == 0)
4472  {
4473  found = true;
4474  break;
4475  }
4476  }
4477  if (found)
4478  {
4479  /* skip corresponding value as well */
4480  if (r == WJB_KEY)
4481  (void) JsonbIteratorNext(&it, &v, true);
4482 
4483  continue;
4484  }
4485  }
4486 
4487  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4488  }
4489 
4490  Assert(res != NULL);
4491 
4493 }
4494 
4495 /*
4496  * SQL function jsonb_delete (jsonb, int)
4497  *
4498  * return a copy of the jsonb with the indicated item
4499  * removed. Negative int means count back from the
4500  * end of the items.
4501  */
4502 Datum
4504 {
4505  Jsonb *in = PG_GETARG_JSONB_P(0);
4506  int idx = PG_GETARG_INT32(1);
4507  JsonbParseState *state = NULL;
4508  JsonbIterator *it;
4509  uint32 i = 0,
4510  n;
4511  JsonbValue v,
4512  *res = NULL;
4514 
4515  if (JB_ROOT_IS_SCALAR(in))
4516  ereport(ERROR,
4517  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4518  errmsg("cannot delete from scalar")));
4519 
4520  if (JB_ROOT_IS_OBJECT(in))
4521  ereport(ERROR,
4522  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4523  errmsg("cannot delete from object using integer index")));
4524 
4525  if (JB_ROOT_COUNT(in) == 0)
4526  PG_RETURN_JSONB_P(in);
4527 
4528  it = JsonbIteratorInit(&in->root);
4529 
4530  r = JsonbIteratorNext(&it, &v, false);
4531  Assert(r == WJB_BEGIN_ARRAY);
4532  n = v.val.array.nElems;
4533 
4534  if (idx < 0)
4535  {
4536  if (-idx > n)
4537  idx = n;
4538  else
4539  idx = n + idx;
4540  }
4541 
4542  if (idx >= n)
4543  PG_RETURN_JSONB_P(in);
4544 
4545  pushJsonbValue(&state, r, NULL);
4546 
4547  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4548  {
4549  if (r == WJB_ELEM)
4550  {
4551  if (i++ == idx)
4552  continue;
4553  }
4554 
4555  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4556  }
4557 
4558  Assert(res != NULL);
4559 
4561 }
4562 
4563 /*
4564  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
4565  */
4566 Datum
4568 {
4569  Jsonb *in = PG_GETARG_JSONB_P(0);
4570  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4571  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4573  bool create = PG_GETARG_BOOL(3);
4574  JsonbValue *res = NULL;
4575  Datum *path_elems;
4576  bool *path_nulls;
4577  int path_len;
4578  JsonbIterator *it;
4579  JsonbParseState *st = NULL;
4580 
4581  JsonbToJsonbValue(newjsonb, &newval);
4582 
4583  if (ARR_NDIM(path) > 1)
4584  ereport(ERROR,
4585  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4586  errmsg("wrong number of array subscripts")));
4587 
4588  if (JB_ROOT_IS_SCALAR(in))
4589  ereport(ERROR,
4590  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4591  errmsg("cannot set path in scalar")));
4592 
4593  if (JB_ROOT_COUNT(in) == 0 && !create)
4594  PG_RETURN_JSONB_P(in);
4595 
4596  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4597 
4598  if (path_len == 0)
4599  PG_RETURN_JSONB_P(in);
4600 
4601  it = JsonbIteratorInit(&in->root);
4602 
4603  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4604  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4605 
4606  Assert(res != NULL);
4607 
4609 }
4610 
4611 
4612 /*
4613  * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text)
4614  */
4615 Datum
4617 {
4618  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4619  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4620  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4621  /* bool create = PG_GETARG_BOOL(3); */
4622  text *handle_null;
4623  char *handle_val;
4624 
4625  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4626  PG_RETURN_NULL();
4627 
4628  /* could happen if they pass in an explicit NULL */
4629  if (PG_ARGISNULL(4))
4630  ereport(ERROR,
4631  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4632  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4633 
4634  /* if the new value isn't an SQL NULL just call jsonb_set */
4635  if (!PG_ARGISNULL(2))
4636  return jsonb_set(fcinfo);
4637 
4638  handle_null = PG_GETARG_TEXT_P(4);
4639  handle_val = text_to_cstring(handle_null);
4640 
4641  if (strcmp(handle_val, "raise_exception") == 0)
4642  {
4643  ereport(ERROR,
4644  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4645  errmsg("JSON value must not be null"),
4646  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4647  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4648  return (Datum) 0; /* silence stupider compilers */
4649  }
4650  else if (strcmp(handle_val, "use_json_null") == 0)
4651  {
4652  Datum newval;
4653 
4655 
4656  fcinfo->args[2].value = newval;
4657  fcinfo->args[2].isnull = false;
4658  return jsonb_set(fcinfo);
4659  }
4660  else if (strcmp(handle_val, "delete_key") == 0)
4661  {
4662  return jsonb_delete_path(fcinfo);
4663  }
4664  else if (strcmp(handle_val, "return_target") == 0)
4665  {
4666  Jsonb *in = PG_GETARG_JSONB_P(0);
4667 
4668  PG_RETURN_JSONB_P(in);
4669  }
4670  else
4671  {
4672  ereport(ERROR,
4673  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4674  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4675  return (Datum) 0; /* silence stupider compilers */
4676  }
4677 }
4678 
4679 /*
4680  * SQL function jsonb_delete_path(jsonb, text[])
4681  */
4682 Datum
4684 {
4685  Jsonb *in = PG_GETARG_JSONB_P(0);
4686  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4687  JsonbValue *res = NULL;
4688  Datum *path_elems;
4689  bool *path_nulls;
4690  int path_len;
4691  JsonbIterator *it;
4692  JsonbParseState *st = NULL;
4693 
4694  if (ARR_NDIM(path) > 1)
4695  ereport(ERROR,
4696  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4697  errmsg("wrong number of array subscripts")));
4698 
4699  if (JB_ROOT_IS_SCALAR(in))
4700  ereport(ERROR,
4701  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4702  errmsg("cannot delete path in scalar")));
4703 
4704  if (JB_ROOT_COUNT(in) == 0)
4705  PG_RETURN_JSONB_P(in);
4706 
4707  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4708 
4709  if (path_len == 0)
4710  PG_RETURN_JSONB_P(in);
4711 
4712  it = JsonbIteratorInit(&in->root);
4713 
4714  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4715  0, NULL, JB_PATH_DELETE);
4716 
4717  Assert(res != NULL);
4718 
4720 }
4721 
4722 /*
4723  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
4724  */
4725 Datum
4727 {
4728  Jsonb *in = PG_GETARG_JSONB_P(0);
4729  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4730  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4732  bool after = PG_GETARG_BOOL(3);
4733  JsonbValue *res = NULL;
4734  Datum *path_elems;
4735  bool *path_nulls;
4736  int path_len;
4737  JsonbIterator *it;
4738  JsonbParseState *st = NULL;
4739 
4740  JsonbToJsonbValue(newjsonb, &newval);
4741 
4742  if (ARR_NDIM(path) > 1)
4743  ereport(ERROR,
4744  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4745  errmsg("wrong number of array subscripts")));
4746 
4747  if (JB_ROOT_IS_SCALAR(in))
4748  ereport(ERROR,
4749  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4750  errmsg("cannot set path in scalar")));
4751 
4752  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4753 
4754  if (path_len == 0)
4755  PG_RETURN_JSONB_P(in);
4756 
4757  it = JsonbIteratorInit(&in->root);
4758 
4759  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
4761 
4762  Assert(res != NULL);
4763 
4765 }
4766 
4767 /*
4768  * Iterate over all jsonb objects and merge them into one.
4769  * The logic of this function copied from the same hstore function,
4770  * except the case, when it1 & it2 represents jbvObject.
4771  * In that case we just append the content of it2 to it1 without any
4772  * verifications.
4773  */
4774 static JsonbValue *
4777 {
4778  JsonbValue v1,
4779  v2,
4780  *res = NULL;
4781  JsonbIteratorToken r1,
4782  r2,
4783  rk1,
4784  rk2;
4785 
4786  rk1 = JsonbIteratorNext(it1, &v1, false);
4787  rk2 = JsonbIteratorNext(it2, &v2, false);
4788 
4789  /*
4790  * JsonbIteratorNext reports raw scalars as if they were single-element
4791  * arrays; hence we only need consider "object" and "array" cases here.
4792  */
4793  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4794  {
4795  /*
4796  * Both inputs are objects.
4797  *
4798  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4799  * (because res will not be finished yet).
4800  */
4801  pushJsonbValue(state, rk1, NULL);
4802  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4803  pushJsonbValue(state, r1, &v1);
4804 
4805  /*
4806  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4807  * (the concatenation will be completed). Any duplicate keys will
4808  * automatically override the value from the first object.
4809  */
4810  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4811  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4812  }
4813  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4814  {
4815  /*
4816  * Both inputs are arrays.
4817  */
4818  pushJsonbValue(state, rk1, NULL);
4819 
4820  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4821  {
4822  Assert(r1 == WJB_ELEM);
4823  pushJsonbValue(state, r1, &v1);
4824  }
4825 
4826  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4827  {
4828  Assert(r2 == WJB_ELEM);
4829  pushJsonbValue(state, WJB_ELEM, &v2);
4830  }
4831 
4832  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4833  }
4834  else if (rk1 == WJB_BEGIN_OBJECT)
4835  {
4836  /*
4837  * We have object || array.
4838  */
4839  Assert(rk2 == WJB_BEGIN_ARRAY);
4840 
4842 
4844  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
4845  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4846 
4847  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4848  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4849  }
4850  else
4851  {
4852  /*
4853  * We have array || object.
4854  */
4855  Assert(rk1 == WJB_BEGIN_ARRAY);
4856  Assert(rk2 == WJB_BEGIN_OBJECT);
4857 
4859 
4860  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4861  pushJsonbValue(state, r1, &v1);
4862 
4864  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4865  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4866 
4868  }
4869 
4870  return res;
4871 }
4872 
4873 /*
4874  * Do most of the heavy work for jsonb_set/jsonb_insert
4875  *
4876  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
4877  *
4878  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
4879  * we create the new value if the key or array index does not exist.
4880  *
4881  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
4882  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
4883  *
4884  * If JB_PATH_FILL_GAPS bit is set, this will change an assignment logic in
4885  * case if target is an array. The assignment index will not be restricted by
4886  * number of elements in the array, and if there are any empty slots between
4887  * last element of the array and a new one they will be filled with nulls. If
4888  * the index is negative, it still will be considered an index from the end
4889  * of the array. Of a part of the path is not present and this part is more
4890  * than just one last element, this flag will instruct to create the whole
4891  * chain of corresponding objects and insert the value.
4892  *
4893  * JB_PATH_CONSISTENT_POSITION for an array indicates that the caller wants to
4894  * keep values with fixed indices. Indices for existing elements could be
4895  * changed (shifted forward) in case if the array is prepended with a new value
4896  * and a negative index out of the range, so this behavior will be prevented
4897  * and return an error.
4898  *
4899  * All path elements before the last must already exist
4900  * whatever bits in op_type are set, or nothing is done.
4901  */
4902 static JsonbValue *
4903 setPath(JsonbIterator **it, Datum *path_elems,
4904  bool *path_nulls, int path_len,
4905  JsonbParseState **st, int level, JsonbValue *newval, int op_type)
4906 {
4907  JsonbValue v;
4909  JsonbValue *res;
4910 
4912 
4913  if (path_nulls[level])
4914  ereport(ERROR,
4915  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4916  errmsg("path element at position %d is null",
4917  level + 1)));
4918 
4919  r = JsonbIteratorNext(it, &v, false);
4920 
4921  switch (r)
4922  {
4923  case WJB_BEGIN_ARRAY:
4924 
4925  /*
4926  * If instructed complain about attempts to replace within a raw
4927  * scalar value. This happens even when current level is equal to
4928  * path_len, because the last path key should also correspond to
4929  * an object or an array, not raw scalar.
4930  */
4931  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
4932  v.val.array.rawScalar)
4933  ereport(ERROR,
4934  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4935  errmsg("cannot replace existing key"),
4936  errdetail("The path assumes key is a composite object, "
4937  "but it is a scalar value.")));
4938 
4939  (void) pushJsonbValue(st, r, NULL);
4940  setPathArray(it, path_elems, path_nulls, path_len, st, level,
4941  newval, v.val.array.nElems, op_type);
4942  r = JsonbIteratorNext(it, &v, false);
4943  Assert(r == WJB_END_ARRAY);
4944  res = pushJsonbValue(st, r, NULL);
4945  break;
4946  case WJB_BEGIN_OBJECT:
4947  (void) pushJsonbValue(st, r, NULL);
4948  setPathObject(it, path_elems, path_nulls, path_len, st, level,
4949  newval, v.val.object.nPairs, op_type);
4950  r = JsonbIteratorNext(it, &v, true);
4951  Assert(r == WJB_END_OBJECT);
4952  res = pushJsonbValue(st, r, NULL);
4953  break;
4954  case WJB_ELEM:
4955  case WJB_VALUE:
4956 
4957  /*
4958  * If instructed complain about attempts to replace within a
4959  * scalar value. This happens even when current level is equal to
4960  * path_len, because the last path key should also correspond to
4961  * an object or an array, not an element or value.
4962  */
4963  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
4964  ereport(ERROR,
4965  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4966  errmsg("cannot replace existing key"),
4967  errdetail("The path assumes key is a composite object, "
4968  "but it is a scalar value.")));
4969 
4970  res = pushJsonbValue(st, r, &v);
4971  break;
4972  default:
4973  elog(ERROR, "unrecognized iterator result: %d", (int) r);
4974  res = NULL; /* keep compiler quiet */
4975  break;
4976  }
4977 
4978  return res;
4979 }
4980 
4981 /*
4982  * Object walker for setPath
4983  */
4984 static void
4985 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4986  int path_len, JsonbParseState **st, int level,
4987  JsonbValue *newval, uint32 npairs, int op_type)
4988 {
4989  text *pathelem = NULL;
4990  int i;
4991  JsonbValue k,
4992  v;
4993  bool done = false;
4994 
4995  if (level >= path_len || path_nulls[level])
4996  done = true;
4997  else
4998  {
4999  /* The path Datum could be toasted, in which case we must detoast it */
5000  pathelem = DatumGetTextPP(path_elems[level]);
5001  }
5002 
5003  /* empty object is a special case for create */
5004  if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
5005  (level == path_len - 1))
5006  {
5007  JsonbValue newkey;
5008 
5009  newkey.type = jbvString;
5010  newkey.val.string.val = VARDATA_ANY(pathelem);
5011  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5012 
5013  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5014  (void) pushJsonbValue(st, WJB_VALUE, newval);
5015  }
5016 
5017  for (i = 0; i < npairs; i++)
5018  {
5019  JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
5020 
5021  Assert(r == WJB_KEY);
5022 
5023  if (!done &&
5024  k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
5025  memcmp(k.val.string.val, VARDATA_ANY(pathelem),
5026  k.val.string.len) == 0)
5027  {
5028  done = true;
5029 
5030  if (level == path_len - 1)
5031  {
5032  /*
5033  * called from jsonb_insert(), it forbids redefining an
5034  * existing value
5035  */
5036  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
5037  ereport(ERROR,
5038  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5039  errmsg("cannot replace existing key"),
5040  errhint("Try using the function jsonb_set "
5041  "to replace key value.")));
5042 
5043  r = JsonbIteratorNext(it, &v, true); /* skip value */
5044  if (!(op_type & JB_PATH_DELETE))
5045  {
5046  (void) pushJsonbValue(st, WJB_KEY, &k);
5047  (void) pushJsonbValue(st, WJB_VALUE, newval);
5048  }
5049  }
5050  else
5051  {
5052  (void) pushJsonbValue(st, r, &k);
5053  setPath(it, path_elems, path_nulls, path_len,
5054  st, level + 1, newval, op_type);
5055  }
5056  }
5057  else
5058  {
5059  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
5060  level == path_len - 1 && i == npairs - 1)
5061  {
5062  JsonbValue newkey;
5063 
5064  newkey.type = jbvString;
5065  newkey.val.string.val = VARDATA_ANY(pathelem);
5066  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5067 
5068  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5069  (void) pushJsonbValue(st, WJB_VALUE, newval);
5070  }
5071 
5072  (void) pushJsonbValue(st, r, &k);
5073  r = JsonbIteratorNext(it, &v, false);
5074  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5075  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5076  {
5077  int walking_level = 1;
5078 
5079  while (walking_level != 0)
5080  {
5081  r = JsonbIteratorNext(it, &v, false);
5082 
5083  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5084  ++walking_level;
5085  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5086  --walking_level;
5087 
5088  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5089  }
5090  }
5091  }
5092  }
5093 
5094  /*--
5095  * If we got here there are only few possibilities:
5096  * - no target path was found, and an open object with some keys/values was
5097  * pushed into the state
5098  * - an object is empty, only WJB_BEGIN_OBJECT is pushed
5099  *
5100  * In both cases if instructed to create the path when not present,
5101  * generate the whole chain of empty objects and insert the new value
5102  * there.
5103  */
5104  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5105  {
5106  JsonbValue newkey;
5107 
5108  newkey.type = jbvString;
5109  newkey.val.string.val = VARDATA_ANY(pathelem);
5110  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5111 
5112  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5113  (void) push_path(st, level, path_elems, path_nulls,
5114  path_len, newval);
5115 
5116  /* Result is closed with WJB_END_OBJECT outside of this function */
5117  }
5118 }
5119 
5120 /*
5121  * Array walker for setPath
5122  */
5123 static void
5124 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
5125  int path_len, JsonbParseState **st, int level,
5126  JsonbValue *newval, uint32 nelems, int op_type)
5127 {
5128  JsonbValue v;
5129  int idx,
5130  i;
5131  bool done = false;
5132 
5133  /* pick correct index */
5134  if (level < path_len && !path_nulls[level])
5135  {
5136  char *c = TextDatumGetCString(path_elems[level]);
5137  char *badp;
5138 
5139  errno = 0;
5140  idx = strtoint(c, &badp, 10);
5141  if (badp == c || *badp != '\0' || errno != 0)
5142  ereport(ERROR,
5143  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5144  errmsg("path element at position %d is not an integer: \"%s\"",
5145  level + 1, c)));
5146  }
5147  else
5148  idx = nelems;
5149 
5150  if (idx < 0)
5151  {
5152  if (-idx > nelems)
5153  {
5154  /*
5155  * If asked to keep elements position consistent, it's not allowed
5156  * to prepend the array.
5157  */
5158  if (op_type & JB_PATH_CONSISTENT_POSITION)
5159  ereport(ERROR,
5160  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5161  errmsg("path element at position %d is out of range: %d",
5162  level + 1, idx)));
5163  else
5164  idx = INT_MIN;
5165  }
5166  else
5167  idx = nelems + idx;
5168  }
5169 
5170  /*
5171  * Filling the gaps means there are no limits on the positive index are
5172  * imposed, we can set any element. Otherwise limit the index by nelems.
5173  */
5174  if (!(op_type & JB_PATH_FILL_GAPS))
5175  {
5176  if (idx > 0 && idx > nelems)
5177  idx = nelems;
5178  }
5179 
5180  /*
5181  * if we're creating, and idx == INT_MIN, we prepend the new value to the
5182  * array also if the array is empty - in which case we don't really care
5183  * what the idx value is
5184  */
5185  if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5186  (op_type & JB_PATH_CREATE_OR_INSERT))
5187  {
5188  Assert(newval != NULL);
5189 
5190  if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
5191  push_null_elements(st, idx);
5192 
5193  (void) pushJsonbValue(st, WJB_ELEM, newval);
5194 
5195  done = true;
5196  }
5197 
5198  /* iterate over the array elements */
5199  for (i = 0; i < nelems; i++)
5200  {
5202 
5203  if (i == idx && level < path_len)
5204  {
5205  done = true;
5206 
5207  if (level == path_len - 1)
5208  {
5209  r = JsonbIteratorNext(it, &v, true); /* skip */
5210 
5211  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
5212  (void) pushJsonbValue(st, WJB_ELEM, newval);
5213 
5214  /*
5215  * We should keep current value only in case of
5216  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
5217  * otherwise it should be deleted or replaced
5218  */
5219  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
5220  (void) pushJsonbValue(st, r, &v);
5221 
5222  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
5223  (void) pushJsonbValue(st, WJB_ELEM, newval);
5224  }
5225  else
5226  (void) setPath(it, path_elems, path_nulls, path_len,
5227  st, level + 1, newval, op_type);
5228  }
5229  else
5230  {
5231  r = JsonbIteratorNext(it, &v, false);
5232 
5233  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5234 
5235  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5236  {
5237  int walking_level = 1;
5238 
5239  while (walking_level != 0)
5240  {
5241  r = JsonbIteratorNext(it, &v, false);
5242 
5243  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5244  ++walking_level;
5245  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5246  --walking_level;
5247 
5248  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5249  }
5250  }
5251  }
5252  }
5253 
5254  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
5255  {
5256  /*
5257  * If asked to fill the gaps, idx could be bigger than nelems, so
5258  * prepend the new element with nulls if that's the case.
5259  */
5260  if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
5261  push_null_elements(st, idx - nelems);
5262 
5263  (void) pushJsonbValue(st, WJB_ELEM, newval);
5264  done = true;
5265  }
5266 
5267  /*--
5268  * If we got here there are only few possibilities:
5269  * - no target path was found, and an open array with some keys/values was
5270  * pushed into the state
5271  * - an array is empty, only WJB_BEGIN_ARRAY is pushed
5272  *
5273  * In both cases if instructed to create the path when not present,
5274  * generate the whole chain of empty objects and insert the new value
5275  * there.
5276  */
5277  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5278  {
5279  if (idx > 0)
5280  push_null_elements(st, idx - nelems);
5281 
5282  (void) push_path(st, level, path_elems, path_nulls,
5283  path_len, newval);
5284 
5285  /* Result is closed with WJB_END_OBJECT outside of this function */
5286  }
5287 }
5288 
5289 /*
5290  * Parse information about what elements of a jsonb document we want to iterate
5291  * in functions iterate_json(b)_values. This information is presented in jsonb