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