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