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