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