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/jsonapi.h"
22 #include "common/string.h"
23 #include "fmgr.h"
24 #include "funcapi.h"
25 #include "lib/stringinfo.h"
26 #include "mb/pg_wchar.h"
27 #include "miscadmin.h"
28 #include "nodes/miscnodes.h"
29 #include "parser/parse_coerce.h"
30 #include "utils/array.h"
31 #include "utils/builtins.h"
32 #include "utils/fmgroids.h"
33 #include "utils/hsearch.h"
34 #include "utils/json.h"
35 #include "utils/jsonb.h"
36 #include "utils/jsonfuncs.h"
37 #include "utils/lsyscache.h"
38 #include "utils/memutils.h"
39 #include "utils/syscache.h"
40 #include "utils/typcache.h"
41 
42 /* Operations available for setPath */
43 #define JB_PATH_CREATE 0x0001
44 #define JB_PATH_DELETE 0x0002
45 #define JB_PATH_REPLACE 0x0004
46 #define JB_PATH_INSERT_BEFORE 0x0008
47 #define JB_PATH_INSERT_AFTER 0x0010
48 #define JB_PATH_CREATE_OR_INSERT \
49  (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
50 #define JB_PATH_FILL_GAPS 0x0020
51 #define JB_PATH_CONSISTENT_POSITION 0x0040
52 
53 /* state for json_object_keys */
54 typedef struct OkeysState
55 {
57  char **result;
62 
63 /* state for iterate_json_values function */
65 {
67  JsonIterateStringValuesAction action; /* an action that will be applied
68  * to each json value */
69  void *action_state; /* any necessary context for iteration */
70  uint32 flags; /* what kind of elements from a json we want
71  * to iterate */
73 
74 /* state for transform_json_string_values function */
76 {
78  StringInfo strval; /* resulting json */
79  JsonTransformStringValuesAction action; /* an action that will be applied
80  * to each json value */
81  void *action_state; /* any necessary context for transformation */
83 
84 /* state for json_get* functions */
85 typedef struct GetState
86 {
89  const char *result_start;
92  int npath; /* length of each path-related array */
93  char **path_names; /* field name(s) being sought */
94  int *path_indexes; /* array index(es) being sought */
95  bool *pathok; /* is path matched to current depth? */
96  int *array_cur_index; /* current element index at each path
97  * level */
99 
100 /* state for json_array_length */
101 typedef struct AlenState
102 {
104  int count;
106 
107 /* state for json_each */
108 typedef struct EachState
109 {
114  const char *result_start;
119 
120 /* state for json_array_elements */
121 typedef struct ElementsState
122 {
124  const char *function_name;
128  const char *result_start;
133 
134 /* state for get_json_object_as_hash */
135 typedef struct JHashState
136 {
138  const char *function_name;
141  const char *save_json_start;
144 
145 /* hashtable element */
146 typedef struct JsonHashEntry
147 {
148  char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
149  char *val;
152 
153 /* structure to cache type I/O metadata needed for populate_scalar() */
154 typedef struct ScalarIOData
155 {
159 
160 /* these two structures are used recursively */
161 typedef struct ColumnIOData ColumnIOData;
162 typedef struct RecordIOData RecordIOData;
163 
164 /* structure to cache metadata needed for populate_array() */
165 typedef struct ArrayIOData
166 {
167  ColumnIOData *element_info; /* metadata cache */
168  Oid element_type; /* array element type id */
169  int32 element_typmod; /* array element type modifier */
171 
172 /* structure to cache metadata needed for populate_composite() */
173 typedef struct CompositeIOData
174 {
175  /*
176  * We use pointer to a RecordIOData here because variable-length struct
177  * RecordIOData can't be used directly in ColumnIOData.io union
178  */
179  RecordIOData *record_io; /* metadata cache for populate_record() */
180  TupleDesc tupdesc; /* cached tuple descriptor */
181  /* these fields differ from target type only if domain over composite: */
182  Oid base_typid; /* base type id */
183  int32 base_typmod; /* base type modifier */
184  /* this field is used only if target type is domain over composite: */
185  void *domain_info; /* opaque cache for domain checks */
187 
188 /* structure to cache metadata needed for populate_domain() */
189 typedef struct DomainIOData
190 {
191  ColumnIOData *base_io; /* metadata cache */
192  Oid base_typid; /* base type id */
193  int32 base_typmod; /* base type modifier */
194  void *domain_info; /* opaque cache for domain checks */
196 
197 /* enumeration type categories */
198 typedef enum TypeCat
199 {
206 
207 /* these two are stolen from hstore / record_out, used in populate_record* */
208 
209 /* structure to cache record metadata needed for populate_record_field() */
210 struct ColumnIOData
211 {
212  Oid typid; /* column type id */
213  int32 typmod; /* column type modifier */
214  TypeCat typcat; /* column type category */
215  ScalarIOData scalar_io; /* metadata cache for direct conversion
216  * through input function */
217  union
218  {
222  } io; /* metadata cache for various column type
223  * categories */
224 };
225 
226 /* structure to cache record metadata needed for populate_record() */
227 struct RecordIOData
228 {
231  int ncolumns;
233 };
234 
235 /* per-query cache for populate_record_worker and populate_recordset_worker */
236 typedef struct PopulateRecordCache
237 {
238  Oid argtype; /* declared type of the record argument */
239  ColumnIOData c; /* metadata cache for populate_composite() */
240  MemoryContext fn_mcxt; /* where this is stored */
242 
243 /* per-call state for populate_recordset */
245 {
247  const char *function_name;
250  const char *save_json_start;
256 
257 /* common data for populate_array_json() and populate_array_dim_jsonb() */
258 typedef struct PopulateArrayContext
259 {
260  ArrayBuildState *astate; /* array build state */
261  ArrayIOData *aio; /* metadata cache */
262  MemoryContext acxt; /* array build memory context */
263  MemoryContext mcxt; /* cache memory context */
264  const char *colname; /* for diagnostics only */
265  int *dims; /* dimensions */
266  int *sizes; /* current dimension counters */
267  int ndims; /* number of dimensions */
268  Node *escontext; /* For soft-error handling */
270 
271 /* state for populate_array_json() */
272 typedef struct PopulateArrayState
273 {
274  JsonLexContext *lex; /* json lexer */
275  PopulateArrayContext *ctx; /* context */
276  const char *element_start; /* start of the current array element */
277  char *element_scalar; /* current array element token if it is a
278  * scalar */
279  JsonTokenType element_type; /* current array element type */
281 
282 /* state for json_strip_nulls */
283 typedef struct StripnullState
284 {
289 
290 /* structure for generalized json/jsonb value passing */
291 typedef struct JsValue
292 {
293  bool is_json; /* json/jsonb */
294  union
295  {
296  struct
297  {
298  const char *str; /* json string */
299  int len; /* json string length or -1 if null-terminated */
300  JsonTokenType type; /* json type */
301  } json; /* json value */
302 
303  JsonbValue *jsonb; /* jsonb value */
304  } val;
306 
307 typedef struct JsObject
308 {
309  bool is_json; /* json/jsonb */
310  union
311  {
314  } val;
316 
317 /* useful macros for testing JsValue properties */
318 #define JsValueIsNull(jsv) \
319  ((jsv)->is_json ? \
320  (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
321  (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
322 
323 #define JsValueIsString(jsv) \
324  ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
325  : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
326 
327 #define JsObjectIsEmpty(jso) \
328  ((jso)->is_json \
329  ? hash_get_num_entries((jso)->val.json_hash) == 0 \
330  : ((jso)->val.jsonb_cont == NULL || \
331  JsonContainerSize((jso)->val.jsonb_cont) == 0))
332 
333 #define JsObjectFree(jso) \
334  do { \
335  if ((jso)->is_json) \
336  hash_destroy((jso)->val.json_hash); \
337  } while (0)
338 
339 static int report_json_context(JsonLexContext *lex);
340 
341 /* semantic action functions for json_object_keys */
342 static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull);
344 static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype);
345 
346 /* semantic action functions for json_get* functions */
349 static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull);
350 static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull);
353 static JsonParseErrorType get_array_element_start(void *state, bool isnull);
354 static JsonParseErrorType get_array_element_end(void *state, bool isnull);
355 static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype);
356 
357 /* common worker function for json getter functions */
358 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
359 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
360  bool normalize_results);
361 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
362 static text *JsonbValueAsText(JsonbValue *v);
363 
364 /* semantic action functions for json_array_length */
366 static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype);
367 static JsonParseErrorType alen_array_element_start(void *state, bool isnull);
368 
369 /* common workers for json{b}_each* functions */
370 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
371 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
372  bool as_text);
373 
374 /* semantic action functions for json_each */
375 static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull);
376 static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull);
378 static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype);
379 
380 /* common workers for json{b}_array_elements_* functions */
381 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
382  bool as_text);
383 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
384  bool as_text);
385 
386 /* semantic action functions for json_array_elements */
388 static JsonParseErrorType elements_array_element_start(void *state, bool isnull);
389 static JsonParseErrorType elements_array_element_end(void *state, bool isnull);
390 static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype);
391 
392 /* turn a json object into a hash table */
393 static HTAB *get_json_object_as_hash(const char *json, int len, const char *funcname,
394  Node *escontext);
395 
396 /* semantic actions for populate_array_json */
398 static JsonParseErrorType populate_array_array_end(void *_state);
399 static JsonParseErrorType populate_array_element_start(void *_state, bool isnull);
400 static JsonParseErrorType populate_array_element_end(void *_state, bool isnull);
401 static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
402 
403 /* semantic action functions for get_json_object_as_hash */
404 static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull);
405 static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull);
407 static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype);
408 
409 /* semantic action functions for populate_recordset */
410 static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull);
411 static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull);
417 
418 /* semantic action functions for json_strip_nulls */
423 static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull);
424 static JsonParseErrorType sn_array_element_start(void *state, bool isnull);
425 static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype);
426 
427 /* worker functions for populate_record, to_record, populate_recordset and to_recordset */
428 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
429  bool is_json, bool have_record_arg);
430 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
431  bool is_json, bool have_record_arg,
432  Node *escontext);
433 
434 /* helper functions for populate_record[set] */
435 static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p,
436  HeapTupleHeader defaultval, MemoryContext mcxt,
437  JsObject *obj, Node *escontext);
439  const char *funcname,
440  PopulateRecordCache *cache);
442  const char *funcname,
443  PopulateRecordCache *cache);
444 static bool JsValueToJsObject(JsValue *jsv, JsObject *jso, Node *escontext);
445 static Datum populate_composite(CompositeIOData *io, Oid typid,
446  const char *colname, MemoryContext mcxt,
447  HeapTupleHeader defaultval, JsValue *jsv, bool *isnull,
448  Node *escontext);
449 static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv,
450  bool *isnull, Node *escontext, bool omit_quotes);
451 static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod,
452  MemoryContext mcxt, bool need_scalar);
453 static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod,
454  const char *colname, MemoryContext mcxt, Datum defaultval,
455  JsValue *jsv, bool *isnull, Node *escontext,
456  bool omit_scalar_quotes);
457 static RecordIOData *allocate_record_info(MemoryContext mcxt, int ncolumns);
458 static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv);
460 static bool populate_array_json(PopulateArrayContext *ctx, const char *json, int len);
462  int ndim);
464 static bool populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims);
465 static bool populate_array_check_dimension(PopulateArrayContext *ctx, int ndim);
466 static bool populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv);
467 static Datum populate_array(ArrayIOData *aio, const char *colname,
468  MemoryContext mcxt, JsValue *jsv,
469  bool *isnull,
470  Node *escontext);
471 static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname,
472  MemoryContext mcxt, JsValue *jsv, bool *isnull,
473  Node *escontext, bool omit_quotes);
474 
475 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
478 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
479  bool *path_nulls, int path_len,
480  JsonbParseState **st, int level, JsonbValue *newval,
481  int op_type);
482 static void setPathObject(JsonbIterator **it, Datum *path_elems,
483  bool *path_nulls, int path_len, JsonbParseState **st,
484  int level,
485  JsonbValue *newval, uint32 npairs, int op_type);
486 static void setPathArray(JsonbIterator **it, Datum *path_elems,
487  bool *path_nulls, int path_len, JsonbParseState **st,
488  int level,
489  JsonbValue *newval, uint32 nelems, int op_type);
490 
491 /* function supporting iterate_json_values */
492 static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
493 static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull);
494 
495 /* functions supporting transform_json_string_values */
500 static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull);
503 
504 
505 /*
506  * pg_parse_json_or_errsave
507  *
508  * This function is like pg_parse_json, except that it does not return a
509  * JsonParseErrorType. Instead, in case of any failure, this function will
510  * save error data into *escontext if that's an ErrorSaveContext, otherwise
511  * ereport(ERROR).
512  *
513  * Returns a boolean indicating success or failure (failure will only be
514  * returned when escontext is an ErrorSaveContext).
515  */
516 bool
518  Node *escontext)
519 {
520  JsonParseErrorType result;
521 
522  result = pg_parse_json(lex, sem);
523  if (result != JSON_SUCCESS)
524  {
525  json_errsave_error(result, lex, escontext);
526  return false;
527  }
528  return true;
529 }
530 
531 /*
532  * makeJsonLexContext
533  *
534  * This is like makeJsonLexContextCstringLen, but it accepts a text value
535  * directly.
536  */
538 makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
539 {
540  /*
541  * Most callers pass a detoasted datum, but it's not clear that they all
542  * do. pg_detoast_datum_packed() is cheap insurance.
543  */
544  json = pg_detoast_datum_packed(json);
545 
546  return makeJsonLexContextCstringLen(lex,
547  VARDATA_ANY(json),
548  VARSIZE_ANY_EXHDR(json),
550  need_escapes);
551 }
552 
553 /*
554  * SQL function json_object_keys
555  *
556  * Returns the set of keys for the object argument.
557  *
558  * This SRF operates in value-per-call mode. It processes the
559  * object during the first call, and the keys are simply stashed
560  * in an array, whose size is expanded as necessary. This is probably
561  * safe enough for a list of keys of a single object, since they are
562  * limited in size to NAMEDATALEN and the number of keys is unlikely to
563  * be so huge that it has major memory implications.
564  */
565 Datum
567 {
568  FuncCallContext *funcctx;
569  OkeysState *state;
570 
571  if (SRF_IS_FIRSTCALL())
572  {
573  MemoryContext oldcontext;
574  Jsonb *jb = PG_GETARG_JSONB_P(0);
575  bool skipNested = false;
576  JsonbIterator *it;
577  JsonbValue v;
579 
580  if (JB_ROOT_IS_SCALAR(jb))
581  ereport(ERROR,
582  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
583  errmsg("cannot call %s on a scalar",
584  "jsonb_object_keys")));
585  else if (JB_ROOT_IS_ARRAY(jb))
586  ereport(ERROR,
587  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
588  errmsg("cannot call %s on an array",
589  "jsonb_object_keys")));
590 
591  funcctx = SRF_FIRSTCALL_INIT();
592  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
593 
594  state = palloc(sizeof(OkeysState));
595 
596  state->result_size = JB_ROOT_COUNT(jb);
597  state->result_count = 0;
598  state->sent_count = 0;
599  state->result = palloc(state->result_size * sizeof(char *));
600 
601  it = JsonbIteratorInit(&jb->root);
602 
603  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
604  {
605  skipNested = true;
606 
607  if (r == WJB_KEY)
608  {
609  char *cstr;
610 
611  cstr = palloc(v.val.string.len + 1 * sizeof(char));
612  memcpy(cstr, v.val.string.val, v.val.string.len);
613  cstr[v.val.string.len] = '\0';
614  state->result[state->result_count++] = cstr;
615  }
616  }
617 
618  MemoryContextSwitchTo(oldcontext);
619  funcctx->user_fctx = (void *) state;
620  }
621 
622  funcctx = SRF_PERCALL_SETUP();
623  state = (OkeysState *) funcctx->user_fctx;
624 
625  if (state->sent_count < state->result_count)
626  {
627  char *nxt = state->result[state->sent_count++];
628 
629  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
630  }
631 
632  SRF_RETURN_DONE(funcctx);
633 }
634 
635 /*
636  * Report a JSON error.
637  */
638 void
640  Node *escontext)
641 {
645  errsave(escontext,
646  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
647  errmsg("unsupported Unicode escape sequence"),
649  report_json_context(lex)));
650  else if (error == JSON_SEM_ACTION_FAILED)
651  {
652  /* semantic action function had better have reported something */
653  if (!SOFT_ERROR_OCCURRED(escontext))
654  elog(ERROR, "JSON semantic action function did not provide error information");
655  }
656  else
657  errsave(escontext,
658  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
659  errmsg("invalid input syntax for type %s", "json"),
661  report_json_context(lex)));
662 }
663 
664 /*
665  * Report a CONTEXT line for bogus JSON input.
666  *
667  * lex->token_terminator must be set to identify the spot where we detected
668  * the error. Note that lex->token_start might be NULL, in case we recognized
669  * error at EOF.
670  *
671  * The return value isn't meaningful, but we make it non-void so that this
672  * can be invoked inside ereport().
673  */
674 static int
676 {
677  const char *context_start;
678  const char *context_end;
679  const char *line_start;
680  char *ctxt;
681  int ctxtlen;
682  const char *prefix;
683  const char *suffix;
684 
685  /* Choose boundaries for the part of the input we will display */
686  line_start = lex->line_start;
687  context_start = line_start;
688  context_end = lex->token_terminator;
689  Assert(context_end >= context_start);
690 
691  /* Advance until we are close enough to context_end */
692  while (context_end - context_start >= 50)
693  {
694  /* Advance to next multibyte character */
695  if (IS_HIGHBIT_SET(*context_start))
696  context_start += pg_mblen(context_start);
697  else
698  context_start++;
699  }
700 
701  /*
702  * We add "..." to indicate that the excerpt doesn't start at the
703  * beginning of the line ... but if we're within 3 characters of the
704  * beginning of the line, we might as well just show the whole line.
705  */
706  if (context_start - line_start <= 3)
707  context_start = line_start;
708 
709  /* Get a null-terminated copy of the data to present */
710  ctxtlen = context_end - context_start;
711  ctxt = palloc(ctxtlen + 1);
712  memcpy(ctxt, context_start, ctxtlen);
713  ctxt[ctxtlen] = '\0';
714 
715  /*
716  * Show the context, prefixing "..." if not starting at start of line, and
717  * suffixing "..." if not ending at end of line.
718  */
719  prefix = (context_start > line_start) ? "..." : "";
720  suffix = (lex->token_type != JSON_TOKEN_END &&
721  context_end - lex->input < lex->input_length &&
722  *context_end != '\n' && *context_end != '\r') ? "..." : "";
723 
724  return errcontext("JSON data, line %d: %s%s%s",
725  lex->line_number, prefix, ctxt, suffix);
726 }
727 
728 
729 Datum
731 {
732  FuncCallContext *funcctx;
733  OkeysState *state;
734 
735  if (SRF_IS_FIRSTCALL())
736  {
737  text *json = PG_GETARG_TEXT_PP(0);
738  JsonLexContext lex;
740  MemoryContext oldcontext;
741 
742  funcctx = SRF_FIRSTCALL_INIT();
743  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
744 
745  state = palloc(sizeof(OkeysState));
746  sem = palloc0(sizeof(JsonSemAction));
747 
748  state->lex = makeJsonLexContext(&lex, json, true);
749  state->result_size = 256;
750  state->result_count = 0;
751  state->sent_count = 0;
752  state->result = palloc(256 * sizeof(char *));
753 
754  sem->semstate = (void *) state;
758  /* remainder are all NULL, courtesy of palloc0 above */
759 
761  /* keys are now in state->result */
762 
763  freeJsonLexContext(&lex);
764  pfree(sem);
765 
766  MemoryContextSwitchTo(oldcontext);
767  funcctx->user_fctx = (void *) state;
768  }
769 
770  funcctx = SRF_PERCALL_SETUP();
771  state = (OkeysState *) funcctx->user_fctx;
772 
773  if (state->sent_count < state->result_count)
774  {
775  char *nxt = state->result[state->sent_count++];
776 
777  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
778  }
779 
780  SRF_RETURN_DONE(funcctx);
781 }
782 
783 static JsonParseErrorType
784 okeys_object_field_start(void *state, char *fname, bool isnull)
785 {
786  OkeysState *_state = (OkeysState *) state;
787 
788  /* only collecting keys for the top level object */
789  if (_state->lex->lex_level != 1)
790  return JSON_SUCCESS;
791 
792  /* enlarge result array if necessary */
793  if (_state->result_count >= _state->result_size)
794  {
795  _state->result_size *= 2;
796  _state->result = (char **)
797  repalloc(_state->result, sizeof(char *) * _state->result_size);
798  }
799 
800  /* save a copy of the field name */
801  _state->result[_state->result_count++] = pstrdup(fname);
802 
803  return JSON_SUCCESS;
804 }
805 
806 static JsonParseErrorType
808 {
809  OkeysState *_state = (OkeysState *) state;
810 
811  /* top level must be a json object */
812  if (_state->lex->lex_level == 0)
813  ereport(ERROR,
814  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
815  errmsg("cannot call %s on an array",
816  "json_object_keys")));
817 
818  return JSON_SUCCESS;
819 }
820 
821 static JsonParseErrorType
822 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
823 {
824  OkeysState *_state = (OkeysState *) state;
825 
826  /* top level must be a json object */
827  if (_state->lex->lex_level == 0)
828  ereport(ERROR,
829  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
830  errmsg("cannot call %s on a scalar",
831  "json_object_keys")));
832 
833  return JSON_SUCCESS;
834 }
835 
836 /*
837  * json and jsonb getter functions
838  * these implement the -> ->> #> and #>> operators
839  * and the json{b?}_extract_path*(json, text, ...) functions
840  */
841 
842 
843 Datum
845 {
846  text *json = PG_GETARG_TEXT_PP(0);
847  text *fname = PG_GETARG_TEXT_PP(1);
848  char *fnamestr = text_to_cstring(fname);
849  text *result;
850 
851  result = get_worker(json, &fnamestr, NULL, 1, false);
852 
853  if (result != NULL)
854  PG_RETURN_TEXT_P(result);
855  else
856  PG_RETURN_NULL();
857 }
858 
859 Datum
861 {
862  Jsonb *jb = PG_GETARG_JSONB_P(0);
863  text *key = PG_GETARG_TEXT_PP(1);
864  JsonbValue *v;
865  JsonbValue vbuf;
866 
867  if (!JB_ROOT_IS_OBJECT(jb))
868  PG_RETURN_NULL();
869 
871  VARDATA_ANY(key),
873  &vbuf);
874 
875  if (v != NULL)
877 
878  PG_RETURN_NULL();
879 }
880 
881 Datum
883 {
884  text *json = PG_GETARG_TEXT_PP(0);
885  text *fname = PG_GETARG_TEXT_PP(1);
886  char *fnamestr = text_to_cstring(fname);
887  text *result;
888 
889  result = get_worker(json, &fnamestr, NULL, 1, true);
890 
891  if (result != NULL)
892  PG_RETURN_TEXT_P(result);
893  else
894  PG_RETURN_NULL();
895 }
896 
897 Datum
899 {
900  Jsonb *jb = PG_GETARG_JSONB_P(0);
901  text *key = PG_GETARG_TEXT_PP(1);
902  JsonbValue *v;
903  JsonbValue vbuf;
904 
905  if (!JB_ROOT_IS_OBJECT(jb))
906  PG_RETURN_NULL();
907 
909  VARDATA_ANY(key),
911  &vbuf);
912 
913  if (v != NULL && v->type != jbvNull)
915 
916  PG_RETURN_NULL();
917 }
918 
919 Datum
921 {
922  text *json = PG_GETARG_TEXT_PP(0);
923  int element = PG_GETARG_INT32(1);
924  text *result;
925 
926  result = get_worker(json, NULL, &element, 1, false);
927 
928  if (result != NULL)
929  PG_RETURN_TEXT_P(result);
930  else
931  PG_RETURN_NULL();
932 }
933 
934 Datum
936 {
937  Jsonb *jb = PG_GETARG_JSONB_P(0);
938  int element = PG_GETARG_INT32(1);
939  JsonbValue *v;
940 
941  if (!JB_ROOT_IS_ARRAY(jb))
942  PG_RETURN_NULL();
943 
944  /* Handle negative subscript */
945  if (element < 0)
946  {
947  uint32 nelements = JB_ROOT_COUNT(jb);
948 
949  if (-element > nelements)
950  PG_RETURN_NULL();
951  else
952  element += nelements;
953  }
954 
956  if (v != NULL)
958 
959  PG_RETURN_NULL();
960 }
961 
962 Datum
964 {
965  text *json = PG_GETARG_TEXT_PP(0);
966  int element = PG_GETARG_INT32(1);
967  text *result;
968 
969  result = get_worker(json, NULL, &element, 1, true);
970 
971  if (result != NULL)
972  PG_RETURN_TEXT_P(result);
973  else
974  PG_RETURN_NULL();
975 }
976 
977 Datum
979 {
980  Jsonb *jb = PG_GETARG_JSONB_P(0);
981  int element = PG_GETARG_INT32(1);
982  JsonbValue *v;
983 
984  if (!JB_ROOT_IS_ARRAY(jb))
985  PG_RETURN_NULL();
986 
987  /* Handle negative subscript */
988  if (element < 0)
989  {
990  uint32 nelements = JB_ROOT_COUNT(jb);
991 
992  if (-element > nelements)
993  PG_RETURN_NULL();
994  else
995  element += nelements;
996  }
997 
999 
1000  if (v != NULL && v->type != jbvNull)
1002 
1003  PG_RETURN_NULL();
1004 }
1005 
1006 Datum
1008 {
1009  return get_path_all(fcinfo, false);
1010 }
1011 
1012 Datum
1014 {
1015  return get_path_all(fcinfo, true);
1016 }
1017 
1018 /*
1019  * common routine for extract_path functions
1020  */
1021 static Datum
1022 get_path_all(FunctionCallInfo fcinfo, bool as_text)
1023 {
1024  text *json = PG_GETARG_TEXT_PP(0);
1025  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1026  text *result;
1027  Datum *pathtext;
1028  bool *pathnulls;
1029  int npath;
1030  char **tpath;
1031  int *ipath;
1032  int i;
1033 
1034  /*
1035  * If the array contains any null elements, return NULL, on the grounds
1036  * that you'd have gotten NULL if any RHS value were NULL in a nested
1037  * series of applications of the -> operator. (Note: because we also
1038  * return NULL for error cases such as no-such-field, this is true
1039  * regardless of the contents of the rest of the array.)
1040  */
1041  if (array_contains_nulls(path))
1042  PG_RETURN_NULL();
1043 
1044  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1045 
1046  tpath = palloc(npath * sizeof(char *));
1047  ipath = palloc(npath * sizeof(int));
1048 
1049  for (i = 0; i < npath; i++)
1050  {
1051  Assert(!pathnulls[i]);
1052  tpath[i] = TextDatumGetCString(pathtext[i]);
1053 
1054  /*
1055  * we have no idea at this stage what structure the document is so
1056  * just convert anything in the path that we can to an integer and set
1057  * all the other integers to INT_MIN which will never match.
1058  */
1059  if (*tpath[i] != '\0')
1060  {
1061  int ind;
1062  char *endptr;
1063 
1064  errno = 0;
1065  ind = strtoint(tpath[i], &endptr, 10);
1066  if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1067  ipath[i] = INT_MIN;
1068  else
1069  ipath[i] = ind;
1070  }
1071  else
1072  ipath[i] = INT_MIN;
1073  }
1074 
1075  result = get_worker(json, tpath, ipath, npath, as_text);
1076 
1077  if (result != NULL)
1078  PG_RETURN_TEXT_P(result);
1079  else
1080  PG_RETURN_NULL();
1081 }
1082 
1083 /*
1084  * get_worker
1085  *
1086  * common worker for all the json getter functions
1087  *
1088  * json: JSON object (in text form)
1089  * tpath[]: field name(s) to extract
1090  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
1091  * npath: length of tpath[] and/or ipath[]
1092  * normalize_results: true to de-escape string and null scalars
1093  *
1094  * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
1095  * field is not to be matched at that nesting level. Similarly, ipath can
1096  * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
1097  * not to be matched at that nesting level (a json datum should never be
1098  * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
1099  */
1100 static text *
1102  char **tpath,
1103  int *ipath,
1104  int npath,
1105  bool normalize_results)
1106 {
1107  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1108  GetState *state = palloc0(sizeof(GetState));
1109 
1110  Assert(npath >= 0);
1111 
1112  state->lex = makeJsonLexContext(NULL, json, true);
1113 
1114  /* is it "_as_text" variant? */
1115  state->normalize_results = normalize_results;
1116  state->npath = npath;
1117  state->path_names = tpath;
1118  state->path_indexes = ipath;
1119  state->pathok = palloc0(sizeof(bool) * npath);
1120  state->array_cur_index = palloc(sizeof(int) * npath);
1121 
1122  if (npath > 0)
1123  state->pathok[0] = true;
1124 
1125  sem->semstate = (void *) state;
1126 
1127  /*
1128  * Not all variants need all the semantic routines. Only set the ones that
1129  * are actually needed for maximum efficiency.
1130  */
1131  sem->scalar = get_scalar;
1132  if (npath == 0)
1133  {
1138  }
1139  if (tpath != NULL)
1140  {
1143  }
1144  if (ipath != NULL)
1145  {
1149  }
1150 
1152  freeJsonLexContext(state->lex);
1153 
1154  return state->tresult;
1155 }
1156 
1157 static JsonParseErrorType
1159 {
1160  GetState *_state = (GetState *) state;
1161  int lex_level = _state->lex->lex_level;
1162 
1163  if (lex_level == 0 && _state->npath == 0)
1164  {
1165  /*
1166  * Special case: we should match the entire object. We only need this
1167  * at outermost level because at nested levels the match will have
1168  * been started by the outer field or array element callback.
1169  */
1170  _state->result_start = _state->lex->token_start;
1171  }
1172 
1173  return JSON_SUCCESS;
1174 }
1175 
1176 static JsonParseErrorType
1178 {
1179  GetState *_state = (GetState *) state;
1180  int lex_level = _state->lex->lex_level;
1181 
1182  if (lex_level == 0 && _state->npath == 0)
1183  {
1184  /* Special case: return the entire object */
1185  const char *start = _state->result_start;
1186  int len = _state->lex->prev_token_terminator - start;
1187 
1189  }
1190 
1191  return JSON_SUCCESS;
1192 }
1193 
1194 static JsonParseErrorType
1195 get_object_field_start(void *state, char *fname, bool isnull)
1196 {
1197  GetState *_state = (GetState *) state;
1198  bool get_next = false;
1199  int lex_level = _state->lex->lex_level;
1200 
1201  if (lex_level <= _state->npath &&
1202  _state->pathok[lex_level - 1] &&
1203  _state->path_names != NULL &&
1204  _state->path_names[lex_level - 1] != NULL &&
1205  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1206  {
1207  if (lex_level < _state->npath)
1208  {
1209  /* if not at end of path just mark path ok */
1210  _state->pathok[lex_level] = true;
1211  }
1212  else
1213  {
1214  /* end of path, so we want this value */
1215  get_next = true;
1216  }
1217  }
1218 
1219  if (get_next)
1220  {
1221  /* this object overrides any previous matching object */
1222  _state->tresult = NULL;
1223  _state->result_start = NULL;
1224 
1225  if (_state->normalize_results &&
1226  _state->lex->token_type == JSON_TOKEN_STRING)
1227  {
1228  /* for as_text variants, tell get_scalar to set it for us */
1229  _state->next_scalar = true;
1230  }
1231  else
1232  {
1233  /* for non-as_text variants, just note the json starting point */
1234  _state->result_start = _state->lex->token_start;
1235  }
1236  }
1237 
1238  return JSON_SUCCESS;
1239 }
1240 
1241 static JsonParseErrorType
1242 get_object_field_end(void *state, char *fname, bool isnull)
1243 {
1244  GetState *_state = (GetState *) state;
1245  bool get_last = false;
1246  int lex_level = _state->lex->lex_level;
1247 
1248  /* same tests as in get_object_field_start */
1249  if (lex_level <= _state->npath &&
1250  _state->pathok[lex_level - 1] &&
1251  _state->path_names != NULL &&
1252  _state->path_names[lex_level - 1] != NULL &&
1253  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1254  {
1255  if (lex_level < _state->npath)
1256  {
1257  /* done with this field so reset pathok */
1258  _state->pathok[lex_level] = false;
1259  }
1260  else
1261  {
1262  /* end of path, so we want this value */
1263  get_last = true;
1264  }
1265  }
1266 
1267  /* for as_text scalar case, our work is already done */
1268  if (get_last && _state->result_start != NULL)
1269  {
1270  /*
1271  * make a text object from the string from the previously noted json
1272  * start up to the end of the previous token (the lexer is by now
1273  * ahead of us on whatever came after what we're interested in).
1274  */
1275  if (isnull && _state->normalize_results)
1276  _state->tresult = (text *) NULL;
1277  else
1278  {
1279  const char *start = _state->result_start;
1280  int len = _state->lex->prev_token_terminator - start;
1281 
1283  }
1284 
1285  /* this should be unnecessary but let's do it for cleanliness: */
1286  _state->result_start = NULL;
1287  }
1288 
1289  return JSON_SUCCESS;
1290 }
1291 
1292 static JsonParseErrorType
1294 {
1295  GetState *_state = (GetState *) state;
1296  int lex_level = _state->lex->lex_level;
1297 
1298  if (lex_level < _state->npath)
1299  {
1300  /* Initialize counting of elements in this array */
1301  _state->array_cur_index[lex_level] = -1;
1302 
1303  /* INT_MIN value is reserved to represent invalid subscript */
1304  if (_state->path_indexes[lex_level] < 0 &&
1305  _state->path_indexes[lex_level] != INT_MIN)
1306  {
1307  /* Negative subscript -- convert to positive-wise subscript */
1309  int nelements;
1310 
1311  error = json_count_array_elements(_state->lex, &nelements);
1312  if (error != JSON_SUCCESS)
1313  json_errsave_error(error, _state->lex, NULL);
1314 
1315  if (-_state->path_indexes[lex_level] <= nelements)
1316  _state->path_indexes[lex_level] += nelements;
1317  }
1318  }
1319  else if (lex_level == 0 && _state->npath == 0)
1320  {
1321  /*
1322  * Special case: we should match the entire array. We only need this
1323  * at the outermost level because at nested levels the match will have
1324  * been started by the outer field or array element callback.
1325  */
1326  _state->result_start = _state->lex->token_start;
1327  }
1328 
1329  return JSON_SUCCESS;
1330 }
1331 
1332 static JsonParseErrorType
1334 {
1335  GetState *_state = (GetState *) state;
1336  int lex_level = _state->lex->lex_level;
1337 
1338  if (lex_level == 0 && _state->npath == 0)
1339  {
1340  /* Special case: return the entire array */
1341  const char *start = _state->result_start;
1342  int len = _state->lex->prev_token_terminator - start;
1343 
1345  }
1346 
1347  return JSON_SUCCESS;
1348 }
1349 
1350 static JsonParseErrorType
1351 get_array_element_start(void *state, bool isnull)
1352 {
1353  GetState *_state = (GetState *) state;
1354  bool get_next = false;
1355  int lex_level = _state->lex->lex_level;
1356 
1357  /* Update array element counter */
1358  if (lex_level <= _state->npath)
1359  _state->array_cur_index[lex_level - 1]++;
1360 
1361  if (lex_level <= _state->npath &&
1362  _state->pathok[lex_level - 1] &&
1363  _state->path_indexes != NULL &&
1364  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1365  {
1366  if (lex_level < _state->npath)
1367  {
1368  /* if not at end of path just mark path ok */
1369  _state->pathok[lex_level] = true;
1370  }
1371  else
1372  {
1373  /* end of path, so we want this value */
1374  get_next = true;
1375  }
1376  }
1377 
1378  /* same logic as for objects */
1379  if (get_next)
1380  {
1381  _state->tresult = NULL;
1382  _state->result_start = NULL;
1383 
1384  if (_state->normalize_results &&
1385  _state->lex->token_type == JSON_TOKEN_STRING)
1386  {
1387  _state->next_scalar = true;
1388  }
1389  else
1390  {
1391  _state->result_start = _state->lex->token_start;
1392  }
1393  }
1394 
1395  return JSON_SUCCESS;
1396 }
1397 
1398 static JsonParseErrorType
1399 get_array_element_end(void *state, bool isnull)
1400 {
1401  GetState *_state = (GetState *) state;
1402  bool get_last = false;
1403  int lex_level = _state->lex->lex_level;
1404 
1405  /* same tests as in get_array_element_start */
1406  if (lex_level <= _state->npath &&
1407  _state->pathok[lex_level - 1] &&
1408  _state->path_indexes != NULL &&
1409  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1410  {
1411  if (lex_level < _state->npath)
1412  {
1413  /* done with this element so reset pathok */
1414  _state->pathok[lex_level] = false;
1415  }
1416  else
1417  {
1418  /* end of path, so we want this value */
1419  get_last = true;
1420  }
1421  }
1422 
1423  /* same logic as for objects */
1424  if (get_last && _state->result_start != NULL)
1425  {
1426  if (isnull && _state->normalize_results)
1427  _state->tresult = (text *) NULL;
1428  else
1429  {
1430  const char *start = _state->result_start;
1431  int len = _state->lex->prev_token_terminator - start;
1432 
1434  }
1435 
1436  _state->result_start = NULL;
1437  }
1438 
1439  return JSON_SUCCESS;
1440 }
1441 
1442 static JsonParseErrorType
1443 get_scalar(void *state, char *token, JsonTokenType tokentype)
1444 {
1445  GetState *_state = (GetState *) state;
1446  int lex_level = _state->lex->lex_level;
1447 
1448  /* Check for whole-object match */
1449  if (lex_level == 0 && _state->npath == 0)
1450  {
1451  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1452  {
1453  /* we want the de-escaped string */
1454  _state->next_scalar = true;
1455  }
1456  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1457  {
1458  _state->tresult = (text *) NULL;
1459  }
1460  else
1461  {
1462  /*
1463  * This is a bit hokey: we will suppress whitespace after the
1464  * scalar token, but not whitespace before it. Probably not worth
1465  * doing our own space-skipping to avoid that.
1466  */
1467  const char *start = _state->lex->input;
1468  int len = _state->lex->prev_token_terminator - start;
1469 
1471  }
1472  }
1473 
1474  if (_state->next_scalar)
1475  {
1476  /* a de-escaped text value is wanted, so supply it */
1477  _state->tresult = cstring_to_text(token);
1478  /* make sure the next call to get_scalar doesn't overwrite it */
1479  _state->next_scalar = false;
1480  }
1481 
1482  return JSON_SUCCESS;
1483 }
1484 
1485 Datum
1487 {
1488  return get_jsonb_path_all(fcinfo, false);
1489 }
1490 
1491 Datum
1493 {
1494  return get_jsonb_path_all(fcinfo, true);
1495 }
1496 
1497 static Datum
1499 {
1500  Jsonb *jb = PG_GETARG_JSONB_P(0);
1501  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1502  Datum *pathtext;
1503  bool *pathnulls;
1504  bool isnull;
1505  int npath;
1506  Datum res;
1507 
1508  /*
1509  * If the array contains any null elements, return NULL, on the grounds
1510  * that you'd have gotten NULL if any RHS value were NULL in a nested
1511  * series of applications of the -> operator. (Note: because we also
1512  * return NULL for error cases such as no-such-field, this is true
1513  * regardless of the contents of the rest of the array.)
1514  */
1515  if (array_contains_nulls(path))
1516  PG_RETURN_NULL();
1517 
1518  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1519 
1520  res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
1521 
1522  if (isnull)
1523  PG_RETURN_NULL();
1524  else
1526 }
1527 
1528 Datum
1529 jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
1530 {
1531  JsonbContainer *container = &jb->root;
1532  JsonbValue *jbvp = NULL;
1533  int i;
1534  bool have_object = false,
1535  have_array = false;
1536 
1537  *isnull = false;
1538 
1539  /* Identify whether we have object, array, or scalar at top-level */
1540  if (JB_ROOT_IS_OBJECT(jb))
1541  have_object = true;
1542  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1543  have_array = true;
1544  else
1545  {
1547  /* Extract the scalar value, if it is what we'll return */
1548  if (npath <= 0)
1549  jbvp = getIthJsonbValueFromContainer(container, 0);
1550  }
1551 
1552  /*
1553  * If the array is empty, return the entire LHS object, on the grounds
1554  * that we should do zero field or element extractions. For the
1555  * non-scalar case we can just hand back the object without much work. For
1556  * the scalar case, fall through and deal with the value below the loop.
1557  * (This inconsistency arises because there's no easy way to generate a
1558  * JsonbValue directly for root-level containers.)
1559  */
1560  if (npath <= 0 && jbvp == NULL)
1561  {
1562  if (as_text)
1563  {
1565  container,
1566  VARSIZE(jb))));
1567  }
1568  else
1569  {
1570  /* not text mode - just hand back the jsonb */
1571  PG_RETURN_JSONB_P(jb);
1572  }
1573  }
1574 
1575  for (i = 0; i < npath; i++)
1576  {
1577  if (have_object)
1578  {
1579  text *subscr = DatumGetTextPP(path[i]);
1580 
1581  jbvp = getKeyJsonValueFromContainer(container,
1582  VARDATA_ANY(subscr),
1583  VARSIZE_ANY_EXHDR(subscr),
1584  NULL);
1585  }
1586  else if (have_array)
1587  {
1588  int lindex;
1589  uint32 index;
1590  char *indextext = TextDatumGetCString(path[i]);
1591  char *endptr;
1592 
1593  errno = 0;
1594  lindex = strtoint(indextext, &endptr, 10);
1595  if (endptr == indextext || *endptr != '\0' || errno != 0)
1596  {
1597  *isnull = true;
1598  return PointerGetDatum(NULL);
1599  }
1600 
1601  if (lindex >= 0)
1602  {
1603  index = (uint32) lindex;
1604  }
1605  else
1606  {
1607  /* Handle negative subscript */
1608  uint32 nelements;
1609 
1610  /* Container must be array, but make sure */
1611  if (!JsonContainerIsArray(container))
1612  elog(ERROR, "not a jsonb array");
1613 
1614  nelements = JsonContainerSize(container);
1615 
1616  if (lindex == INT_MIN || -lindex > nelements)
1617  {
1618  *isnull = true;
1619  return PointerGetDatum(NULL);
1620  }
1621  else
1622  index = nelements + lindex;
1623  }
1624 
1625  jbvp = getIthJsonbValueFromContainer(container, index);
1626  }
1627  else
1628  {
1629  /* scalar, extraction yields a null */
1630  *isnull = true;
1631  return PointerGetDatum(NULL);
1632  }
1633 
1634  if (jbvp == NULL)
1635  {
1636  *isnull = true;
1637  return PointerGetDatum(NULL);
1638  }
1639  else if (i == npath - 1)
1640  break;
1641 
1642  if (jbvp->type == jbvBinary)
1643  {
1644  container = jbvp->val.binary.data;
1645  have_object = JsonContainerIsObject(container);
1646  have_array = JsonContainerIsArray(container);
1647  Assert(!JsonContainerIsScalar(container));
1648  }
1649  else
1650  {
1651  Assert(IsAJsonbScalar(jbvp));
1652  have_object = false;
1653  have_array = false;
1654  }
1655  }
1656 
1657  if (as_text)
1658  {
1659  if (jbvp->type == jbvNull)
1660  {
1661  *isnull = true;
1662  return PointerGetDatum(NULL);
1663  }
1664 
1665  return PointerGetDatum(JsonbValueAsText(jbvp));
1666  }
1667  else
1668  {
1669  Jsonb *res = JsonbValueToJsonb(jbvp);
1670 
1671  /* not text mode - just hand back the jsonb */
1673  }
1674 }
1675 
1676 Datum
1677 jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
1678  JsonbValue *newval)
1679 {
1680  JsonbValue *res;
1681  JsonbParseState *state = NULL;
1682  JsonbIterator *it;
1683  bool *path_nulls = palloc0(path_len * sizeof(bool));
1684 
1685  if (newval->type == jbvArray && newval->val.array.rawScalar)
1686  *newval = newval->val.array.elems[0];
1687 
1688  it = JsonbIteratorInit(&jb->root);
1689 
1690  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1693 
1694  pfree(path_nulls);
1695 
1697 }
1698 
1699 static void
1701 {
1702  JsonbValue null;
1703 
1704  null.type = jbvNull;
1705 
1706  while (num-- > 0)
1707  pushJsonbValue(ps, WJB_ELEM, &null);
1708 }
1709 
1710 /*
1711  * Prepare a new structure containing nested empty objects and arrays
1712  * corresponding to the specified path, and assign a new value at the end of
1713  * this path. E.g. the path [a][0][b] with the new value 1 will produce the
1714  * structure {a: [{b: 1}]}.
1715  *
1716  * Caller is responsible to make sure such path does not exist yet.
1717  */
1718 static void
1719 push_path(JsonbParseState **st, int level, Datum *path_elems,
1720  bool *path_nulls, int path_len, JsonbValue *newval)
1721 {
1722  /*
1723  * tpath contains expected type of an empty jsonb created at each level
1724  * higher or equal than the current one, either jbvObject or jbvArray.
1725  * Since it contains only information about path slice from level to the
1726  * end, the access index must be normalized by level.
1727  */
1728  enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
1729  JsonbValue newkey;
1730 
1731  /*
1732  * Create first part of the chain with beginning tokens. For the current
1733  * level WJB_BEGIN_OBJECT/WJB_BEGIN_ARRAY was already created, so start
1734  * with the next one.
1735  */
1736  for (int i = level + 1; i < path_len; i++)
1737  {
1738  char *c,
1739  *badp;
1740  int lindex;
1741 
1742  if (path_nulls[i])
1743  break;
1744 
1745  /*
1746  * Try to convert to an integer to find out the expected type, object
1747  * or array.
1748  */
1749  c = TextDatumGetCString(path_elems[i]);
1750  errno = 0;
1751  lindex = strtoint(c, &badp, 10);
1752  if (badp == c || *badp != '\0' || errno != 0)
1753  {
1754  /* text, an object is expected */
1755  newkey.type = jbvString;
1756  newkey.val.string.val = c;
1757  newkey.val.string.len = strlen(c);
1758 
1759  (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL);
1760  (void) pushJsonbValue(st, WJB_KEY, &newkey);
1761 
1762  tpath[i - level] = jbvObject;
1763  }
1764  else
1765  {
1766  /* integer, an array is expected */
1767  (void) pushJsonbValue(st, WJB_BEGIN_ARRAY, NULL);
1768 
1769  push_null_elements(st, lindex);
1770 
1771  tpath[i - level] = jbvArray;
1772  }
1773  }
1774 
1775  /* Insert an actual value for either an object or array */
1776  if (tpath[(path_len - level) - 1] == jbvArray)
1777  {
1778  (void) pushJsonbValue(st, WJB_ELEM, newval);
1779  }
1780  else
1781  (void) pushJsonbValue(st, WJB_VALUE, newval);
1782 
1783  /*
1784  * Close everything up to the last but one level. The last one will be
1785  * closed outside of this function.
1786  */
1787  for (int i = path_len - 1; i > level; i--)
1788  {
1789  if (path_nulls[i])
1790  break;
1791 
1792  if (tpath[i - level] == jbvObject)
1793  (void) pushJsonbValue(st, WJB_END_OBJECT, NULL);
1794  else
1795  (void) pushJsonbValue(st, WJB_END_ARRAY, NULL);
1796  }
1797 }
1798 
1799 /*
1800  * Return the text representation of the given JsonbValue.
1801  */
1802 static text *
1804 {
1805  switch (v->type)
1806  {
1807  case jbvNull:
1808  return NULL;
1809 
1810  case jbvBool:
1811  return v->val.boolean ?
1812  cstring_to_text_with_len("true", 4) :
1813  cstring_to_text_with_len("false", 5);
1814 
1815  case jbvString:
1816  return cstring_to_text_with_len(v->val.string.val,
1817  v->val.string.len);
1818 
1819  case jbvNumeric:
1820  {
1821  Datum cstr;
1822 
1824  PointerGetDatum(v->val.numeric));
1825 
1826  return cstring_to_text(DatumGetCString(cstr));
1827  }
1828 
1829  case jbvBinary:
1830  {
1831  StringInfoData jtext;
1832 
1833  initStringInfo(&jtext);
1834  (void) JsonbToCString(&jtext, v->val.binary.data,
1835  v->val.binary.len);
1836 
1837  return cstring_to_text_with_len(jtext.data, jtext.len);
1838  }
1839 
1840  default:
1841  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1842  return NULL;
1843  }
1844 }
1845 
1846 /*
1847  * SQL function json_array_length(json) -> int
1848  */
1849 Datum
1851 {
1852  text *json = PG_GETARG_TEXT_PP(0);
1853  AlenState *state;
1854  JsonLexContext lex;
1855  JsonSemAction *sem;
1856 
1857  state = palloc0(sizeof(AlenState));
1858  state->lex = makeJsonLexContext(&lex, json, false);
1859  /* palloc0 does this for us */
1860 #if 0
1861  state->count = 0;
1862 #endif
1863 
1864  sem = palloc0(sizeof(JsonSemAction));
1865  sem->semstate = (void *) state;
1867  sem->scalar = alen_scalar;
1869 
1871 
1872  PG_RETURN_INT32(state->count);
1873 }
1874 
1875 Datum
1877 {
1878  Jsonb *jb = PG_GETARG_JSONB_P(0);
1879 
1880  if (JB_ROOT_IS_SCALAR(jb))
1881  ereport(ERROR,
1882  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1883  errmsg("cannot get array length of a scalar")));
1884  else if (!JB_ROOT_IS_ARRAY(jb))
1885  ereport(ERROR,
1886  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1887  errmsg("cannot get array length of a non-array")));
1888 
1890 }
1891 
1892 /*
1893  * These next two checks ensure that the json is an array (since it can't be
1894  * a scalar or an object).
1895  */
1896 
1897 static JsonParseErrorType
1899 {
1900  AlenState *_state = (AlenState *) state;
1901 
1902  /* json structure check */
1903  if (_state->lex->lex_level == 0)
1904  ereport(ERROR,
1905  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1906  errmsg("cannot get array length of a non-array")));
1907 
1908  return JSON_SUCCESS;
1909 }
1910 
1911 static JsonParseErrorType
1912 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1913 {
1914  AlenState *_state = (AlenState *) state;
1915 
1916  /* json structure check */
1917  if (_state->lex->lex_level == 0)
1918  ereport(ERROR,
1919  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1920  errmsg("cannot get array length of a scalar")));
1921 
1922  return JSON_SUCCESS;
1923 }
1924 
1925 static JsonParseErrorType
1926 alen_array_element_start(void *state, bool isnull)
1927 {
1928  AlenState *_state = (AlenState *) state;
1929 
1930  /* just count up all the level 1 elements */
1931  if (_state->lex->lex_level == 1)
1932  _state->count++;
1933 
1934  return JSON_SUCCESS;
1935 }
1936 
1937 /*
1938  * SQL function json_each and json_each_text
1939  *
1940  * decompose a json object into key value pairs.
1941  *
1942  * Unlike json_object_keys() these SRFs operate in materialize mode,
1943  * stashing results into a Tuplestore object as they go.
1944  * The construction of tuples is done using a temporary memory context
1945  * that is cleared out after each tuple is built.
1946  */
1947 Datum
1949 {
1950  return each_worker(fcinfo, false);
1951 }
1952 
1953 Datum
1955 {
1956  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1957 }
1958 
1959 Datum
1961 {
1962  return each_worker(fcinfo, true);
1963 }
1964 
1965 Datum
1967 {
1968  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1969 }
1970 
1971 static Datum
1972 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1973 {
1974  Jsonb *jb = PG_GETARG_JSONB_P(0);
1975  ReturnSetInfo *rsi;
1976  MemoryContext old_cxt,
1977  tmp_cxt;
1978  bool skipNested = false;
1979  JsonbIterator *it;
1980  JsonbValue v;
1982 
1983  if (!JB_ROOT_IS_OBJECT(jb))
1984  ereport(ERROR,
1985  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1986  errmsg("cannot call %s on a non-object",
1987  funcname)));
1988 
1989  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1991 
1993  "jsonb_each temporary cxt",
1995 
1996  it = JsonbIteratorInit(&jb->root);
1997 
1998  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1999  {
2000  skipNested = true;
2001 
2002  if (r == WJB_KEY)
2003  {
2004  text *key;
2005  Datum values[2];
2006  bool nulls[2] = {false, false};
2007 
2008  /* Use the tmp context so we can clean up after each tuple is done */
2009  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2010 
2011  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2012 
2013  /*
2014  * The next thing the iterator fetches should be the value, no
2015  * matter what shape it is.
2016  */
2017  r = JsonbIteratorNext(&it, &v, skipNested);
2018  Assert(r != WJB_DONE);
2019 
2020  values[0] = PointerGetDatum(key);
2021 
2022  if (as_text)
2023  {
2024  if (v.type == jbvNull)
2025  {
2026  /* a json null is an sql null in text mode */
2027  nulls[1] = true;
2028  values[1] = (Datum) NULL;
2029  }
2030  else
2032  }
2033  else
2034  {
2035  /* Not in text mode, just return the Jsonb */
2036  Jsonb *val = JsonbValueToJsonb(&v);
2037 
2038  values[1] = PointerGetDatum(val);
2039  }
2040 
2041  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2042 
2043  /* clean up and switch back */
2044  MemoryContextSwitchTo(old_cxt);
2045  MemoryContextReset(tmp_cxt);
2046  }
2047  }
2048 
2049  MemoryContextDelete(tmp_cxt);
2050 
2051  PG_RETURN_NULL();
2052 }
2053 
2054 
2055 static Datum
2056 each_worker(FunctionCallInfo fcinfo, bool as_text)
2057 {
2058  text *json = PG_GETARG_TEXT_PP(0);
2059  JsonLexContext lex;
2060  JsonSemAction *sem;
2061  ReturnSetInfo *rsi;
2062  EachState *state;
2063 
2064  state = palloc0(sizeof(EachState));
2065  sem = palloc0(sizeof(JsonSemAction));
2066 
2067  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2068 
2070  state->tuple_store = rsi->setResult;
2071  state->ret_tdesc = rsi->setDesc;
2072 
2073  sem->semstate = (void *) state;
2075  sem->scalar = each_scalar;
2078 
2079  state->normalize_results = as_text;
2080  state->next_scalar = false;
2081  state->lex = makeJsonLexContext(&lex, json, true);
2083  "json_each temporary cxt",
2085 
2087 
2088  MemoryContextDelete(state->tmp_cxt);
2089  freeJsonLexContext(&lex);
2090 
2091  PG_RETURN_NULL();
2092 }
2093 
2094 
2095 static JsonParseErrorType
2096 each_object_field_start(void *state, char *fname, bool isnull)
2097 {
2098  EachState *_state = (EachState *) state;
2099 
2100  /* save a pointer to where the value starts */
2101  if (_state->lex->lex_level == 1)
2102  {
2103  /*
2104  * next_scalar will be reset in the object_field_end handler, and
2105  * since we know the value is a scalar there is no danger of it being
2106  * on while recursing down the tree.
2107  */
2108  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2109  _state->next_scalar = true;
2110  else
2111  _state->result_start = _state->lex->token_start;
2112  }
2113 
2114  return JSON_SUCCESS;
2115 }
2116 
2117 static JsonParseErrorType
2118 each_object_field_end(void *state, char *fname, bool isnull)
2119 {
2120  EachState *_state = (EachState *) state;
2121  MemoryContext old_cxt;
2122  int len;
2123  text *val;
2124  HeapTuple tuple;
2125  Datum values[2];
2126  bool nulls[2] = {false, false};
2127 
2128  /* skip over nested objects */
2129  if (_state->lex->lex_level != 1)
2130  return JSON_SUCCESS;
2131 
2132  /* use the tmp context so we can clean up after each tuple is done */
2133  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2134 
2135  values[0] = CStringGetTextDatum(fname);
2136 
2137  if (isnull && _state->normalize_results)
2138  {
2139  nulls[1] = true;
2140  values[1] = (Datum) 0;
2141  }
2142  else if (_state->next_scalar)
2143  {
2145  _state->next_scalar = false;
2146  }
2147  else
2148  {
2149  len = _state->lex->prev_token_terminator - _state->result_start;
2151  values[1] = PointerGetDatum(val);
2152  }
2153 
2154  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2155 
2156  tuplestore_puttuple(_state->tuple_store, tuple);
2157 
2158  /* clean up and switch back */
2159  MemoryContextSwitchTo(old_cxt);
2160  MemoryContextReset(_state->tmp_cxt);
2161 
2162  return JSON_SUCCESS;
2163 }
2164 
2165 static JsonParseErrorType
2167 {
2168  EachState *_state = (EachState *) state;
2169 
2170  /* json structure check */
2171  if (_state->lex->lex_level == 0)
2172  ereport(ERROR,
2173  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2174  errmsg("cannot deconstruct an array as an object")));
2175 
2176  return JSON_SUCCESS;
2177 }
2178 
2179 static JsonParseErrorType
2180 each_scalar(void *state, char *token, JsonTokenType tokentype)
2181 {
2182  EachState *_state = (EachState *) state;
2183 
2184  /* json structure check */
2185  if (_state->lex->lex_level == 0)
2186  ereport(ERROR,
2187  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2188  errmsg("cannot deconstruct a scalar")));
2189 
2190  /* supply de-escaped value if required */
2191  if (_state->next_scalar)
2192  _state->normalized_scalar = token;
2193 
2194  return JSON_SUCCESS;
2195 }
2196 
2197 /*
2198  * SQL functions json_array_elements and json_array_elements_text
2199  *
2200  * get the elements from a json array
2201  *
2202  * a lot of this processing is similar to the json_each* functions
2203  */
2204 
2205 Datum
2207 {
2208  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2209 }
2210 
2211 Datum
2213 {
2214  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2215 }
2216 
2217 static Datum
2219  bool as_text)
2220 {
2221  Jsonb *jb = PG_GETARG_JSONB_P(0);
2222  ReturnSetInfo *rsi;
2223  MemoryContext old_cxt,
2224  tmp_cxt;
2225  bool skipNested = false;
2226  JsonbIterator *it;
2227  JsonbValue v;
2229 
2230  if (JB_ROOT_IS_SCALAR(jb))
2231  ereport(ERROR,
2232  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2233  errmsg("cannot extract elements from a scalar")));
2234  else if (!JB_ROOT_IS_ARRAY(jb))
2235  ereport(ERROR,
2236  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2237  errmsg("cannot extract elements from an object")));
2238 
2239  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2240 
2242 
2244  "jsonb_array_elements temporary cxt",
2246 
2247  it = JsonbIteratorInit(&jb->root);
2248 
2249  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2250  {
2251  skipNested = true;
2252 
2253  if (r == WJB_ELEM)
2254  {
2255  Datum values[1];
2256  bool nulls[1] = {false};
2257 
2258  /* use the tmp context so we can clean up after each tuple is done */
2259  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2260 
2261  if (as_text)
2262  {
2263  if (v.type == jbvNull)
2264  {
2265  /* a json null is an sql null in text mode */
2266  nulls[0] = true;
2267  values[0] = (Datum) NULL;
2268  }
2269  else
2271  }
2272  else
2273  {
2274  /* Not in text mode, just return the Jsonb */
2275  Jsonb *val = JsonbValueToJsonb(&v);
2276 
2277  values[0] = PointerGetDatum(val);
2278  }
2279 
2280  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2281 
2282  /* clean up and switch back */
2283  MemoryContextSwitchTo(old_cxt);
2284  MemoryContextReset(tmp_cxt);
2285  }
2286  }
2287 
2288  MemoryContextDelete(tmp_cxt);
2289 
2290  PG_RETURN_NULL();
2291 }
2292 
2293 Datum
2295 {
2296  return elements_worker(fcinfo, "json_array_elements", false);
2297 }
2298 
2299 Datum
2301 {
2302  return elements_worker(fcinfo, "json_array_elements_text", true);
2303 }
2304 
2305 static Datum
2306 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
2307 {
2308  text *json = PG_GETARG_TEXT_PP(0);
2309  JsonLexContext lex;
2310  JsonSemAction *sem;
2311  ReturnSetInfo *rsi;
2313 
2314  /* elements only needs escaped strings when as_text */
2315  makeJsonLexContext(&lex, json, as_text);
2316 
2317  state = palloc0(sizeof(ElementsState));
2318  sem = palloc0(sizeof(JsonSemAction));
2319 
2321  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2322  state->tuple_store = rsi->setResult;
2323  state->ret_tdesc = rsi->setDesc;
2324 
2325  sem->semstate = (void *) state;
2330 
2331  state->function_name = funcname;
2332  state->normalize_results = as_text;
2333  state->next_scalar = false;
2334  state->lex = &lex;
2336  "json_array_elements temporary cxt",
2338 
2340 
2341  MemoryContextDelete(state->tmp_cxt);
2342  freeJsonLexContext(&lex);
2343 
2344  PG_RETURN_NULL();
2345 }
2346 
2347 static JsonParseErrorType
2349 {
2350  ElementsState *_state = (ElementsState *) state;
2351 
2352  /* save a pointer to where the value starts */
2353  if (_state->lex->lex_level == 1)
2354  {
2355  /*
2356  * next_scalar will be reset in the array_element_end handler, and
2357  * since we know the value is a scalar there is no danger of it being
2358  * on while recursing down the tree.
2359  */
2360  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2361  _state->next_scalar = true;
2362  else
2363  _state->result_start = _state->lex->token_start;
2364  }
2365 
2366  return JSON_SUCCESS;
2367 }
2368 
2369 static JsonParseErrorType
2371 {
2372  ElementsState *_state = (ElementsState *) state;
2373  MemoryContext old_cxt;
2374  int len;
2375  text *val;
2376  HeapTuple tuple;
2377  Datum values[1];
2378  bool nulls[1] = {false};
2379 
2380  /* skip over nested objects */
2381  if (_state->lex->lex_level != 1)
2382  return JSON_SUCCESS;
2383 
2384  /* use the tmp context so we can clean up after each tuple is done */
2385  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2386 
2387  if (isnull && _state->normalize_results)
2388  {
2389  nulls[0] = true;
2390  values[0] = (Datum) NULL;
2391  }
2392  else if (_state->next_scalar)
2393  {
2395  _state->next_scalar = false;
2396  }
2397  else
2398  {
2399  len = _state->lex->prev_token_terminator - _state->result_start;
2401  values[0] = PointerGetDatum(val);
2402  }
2403 
2404  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2405 
2406  tuplestore_puttuple(_state->tuple_store, tuple);
2407 
2408  /* clean up and switch back */
2409  MemoryContextSwitchTo(old_cxt);
2410  MemoryContextReset(_state->tmp_cxt);
2411 
2412  return JSON_SUCCESS;
2413 }
2414 
2415 static JsonParseErrorType
2417 {
2418  ElementsState *_state = (ElementsState *) state;
2419 
2420  /* json structure check */
2421  if (_state->lex->lex_level == 0)
2422  ereport(ERROR,
2423  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2424  errmsg("cannot call %s on a non-array",
2425  _state->function_name)));
2426 
2427  return JSON_SUCCESS;
2428 }
2429 
2430 static JsonParseErrorType
2431 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2432 {
2433  ElementsState *_state = (ElementsState *) state;
2434 
2435  /* json structure check */
2436  if (_state->lex->lex_level == 0)
2437  ereport(ERROR,
2438  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2439  errmsg("cannot call %s on a scalar",
2440  _state->function_name)));
2441 
2442  /* supply de-escaped value if required */
2443  if (_state->next_scalar)
2444  _state->normalized_scalar = token;
2445 
2446  return JSON_SUCCESS;
2447 }
2448 
2449 /*
2450  * SQL function json_populate_record
2451  *
2452  * set fields in a record from the argument json
2453  *
2454  * Code adapted shamelessly from hstore's populate_record
2455  * which is in turn partly adapted from record_out.
2456  *
2457  * The json is decomposed into a hash table, in which each
2458  * field in the record is then looked up by name. For jsonb
2459  * we fetch the values direct from the object.
2460  */
2461 Datum
2463 {
2464  return populate_record_worker(fcinfo, "jsonb_populate_record",
2465  false, true, NULL);
2466 }
2467 
2468 /*
2469  * SQL function that can be used for testing json_populate_record().
2470  *
2471  * Returns false if json_populate_record() encounters an error for the
2472  * provided input JSON object, true otherwise.
2473  */
2474 Datum
2476 {
2477  ErrorSaveContext escontext = {T_ErrorSaveContext};
2478 
2479  (void) populate_record_worker(fcinfo, "jsonb_populate_record",
2480  false, true, (Node *) &escontext);
2481 
2482  return BoolGetDatum(!escontext.error_occurred);
2483 }
2484 
2485 Datum
2487 {
2488  return populate_record_worker(fcinfo, "jsonb_to_record",
2489  false, false, NULL);
2490 }
2491 
2492 Datum
2494 {
2495  return populate_record_worker(fcinfo, "json_populate_record",
2496  true, true, NULL);
2497 }
2498 
2499 Datum
2501 {
2502  return populate_record_worker(fcinfo, "json_to_record",
2503  true, false, NULL);
2504 }
2505 
2506 /* helper function for diagnostics */
2507 static void
2509 {
2510  if (ndim <= 0)
2511  {
2512  if (ctx->colname)
2513  errsave(ctx->escontext,
2514  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2515  errmsg("expected JSON array"),
2516  errhint("See the value of key \"%s\".", ctx->colname)));
2517  else
2518  errsave(ctx->escontext,
2519  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2520  errmsg("expected JSON array")));
2521  return;
2522  }
2523  else
2524  {
2525  StringInfoData indices;
2526  int i;
2527 
2528  initStringInfo(&indices);
2529 
2530  Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2531 
2532  for (i = 0; i < ndim; i++)
2533  appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2534 
2535  if (ctx->colname)
2536  errsave(ctx->escontext,
2537  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2538  errmsg("expected JSON array"),
2539  errhint("See the array element %s of key \"%s\".",
2540  indices.data, ctx->colname)));
2541  else
2542  errsave(ctx->escontext,
2543  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2544  errmsg("expected JSON array"),
2545  errhint("See the array element %s.",
2546  indices.data)));
2547  return;
2548  }
2549 }
2550 
2551 /*
2552  * Validate and set ndims for populating an array with some
2553  * populate_array_*() function.
2554  *
2555  * Returns false if the input (ndims) is erroneous.
2556  */
2557 static bool
2559 {
2560  int i;
2561 
2562  Assert(ctx->ndims <= 0);
2563 
2564  if (ndims <= 0)
2565  {
2567  /* Getting here means the error was reported softly. */
2569  return false;
2570  }
2571 
2572  ctx->ndims = ndims;
2573  ctx->dims = palloc(sizeof(int) * ndims);
2574  ctx->sizes = palloc0(sizeof(int) * ndims);
2575 
2576  for (i = 0; i < ndims; i++)
2577  ctx->dims[i] = -1; /* dimensions are unknown yet */
2578 
2579  return true;
2580 }
2581 
2582 /*
2583  * Check the populated subarray dimension
2584  *
2585  * Returns false if the input (ndims) is erroneous.
2586  */
2587 static bool
2589 {
2590  int dim = ctx->sizes[ndim]; /* current dimension counter */
2591 
2592  if (ctx->dims[ndim] == -1)
2593  ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2594  else if (ctx->dims[ndim] != dim)
2595  ereturn(ctx->escontext, false,
2596  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2597  errmsg("malformed JSON array"),
2598  errdetail("Multidimensional arrays must have "
2599  "sub-arrays with matching dimensions.")));
2600 
2601  /* reset the current array dimension size counter */
2602  ctx->sizes[ndim] = 0;
2603 
2604  /* increment the parent dimension counter if it is a nested sub-array */
2605  if (ndim > 0)
2606  ctx->sizes[ndim - 1]++;
2607 
2608  return true;
2609 }
2610 
2611 /*
2612  * Returns true if the array element value was successfully extracted from jsv
2613  * and added to ctx->astate. False if an error occurred when doing so.
2614  */
2615 static bool
2617 {
2618  Datum element;
2619  bool element_isnull;
2620 
2621  /* populate the array element */
2623  ctx->aio->element_type,
2624  ctx->aio->element_typmod,
2625  NULL, ctx->mcxt, PointerGetDatum(NULL),
2626  jsv, &element_isnull, ctx->escontext,
2627  false);
2628  /* Nothing to do on an error. */
2629  if (SOFT_ERROR_OCCURRED(ctx->escontext))
2630  return false;
2631 
2632  accumArrayResult(ctx->astate, element, element_isnull,
2633  ctx->aio->element_type, ctx->acxt);
2634 
2635  Assert(ndim > 0);
2636  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2637 
2638  return true;
2639 }
2640 
2641 /* json object start handler for populate_array_json() */
2642 static JsonParseErrorType
2644 {
2646  int ndim = state->lex->lex_level;
2647 
2648  if (state->ctx->ndims <= 0)
2649  {
2650  if (!populate_array_assign_ndims(state->ctx, ndim))
2651  return JSON_SEM_ACTION_FAILED;
2652  }
2653  else if (ndim < state->ctx->ndims)
2654  {
2656  /* Getting here means the error was reported softly. */
2657  Assert(SOFT_ERROR_OCCURRED(state->ctx->escontext));
2658  return JSON_SEM_ACTION_FAILED;
2659  }
2660 
2661  return JSON_SUCCESS;
2662 }
2663 
2664 /* json array end handler for populate_array_json() */
2665 static JsonParseErrorType
2667 {
2669  PopulateArrayContext *ctx = state->ctx;
2670  int ndim = state->lex->lex_level;
2671 
2672  if (ctx->ndims <= 0)
2673  {
2674  if (!populate_array_assign_ndims(ctx, ndim + 1))
2675  return JSON_SEM_ACTION_FAILED;
2676  }
2677 
2678  if (ndim < ctx->ndims)
2679  {
2680  /* Report if an error occurred. */
2681  if (!populate_array_check_dimension(ctx, ndim))
2682  return JSON_SEM_ACTION_FAILED;
2683  }
2684 
2685  return JSON_SUCCESS;
2686 }
2687 
2688 /* json array element start handler for populate_array_json() */
2689 static JsonParseErrorType
2690 populate_array_element_start(void *_state, bool isnull)
2691 {
2693  int ndim = state->lex->lex_level;
2694 
2695  if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2696  {
2697  /* remember current array element start */
2698  state->element_start = state->lex->token_start;
2699  state->element_type = state->lex->token_type;
2700  state->element_scalar = NULL;
2701  }
2702 
2703  return JSON_SUCCESS;
2704 }
2705 
2706 /* json array element end handler for populate_array_json() */
2707 static JsonParseErrorType
2708 populate_array_element_end(void *_state, bool isnull)
2709 {
2711  PopulateArrayContext *ctx = state->ctx;
2712  int ndim = state->lex->lex_level;
2713 
2714  Assert(ctx->ndims > 0);
2715 
2716  if (ndim == ctx->ndims)
2717  {
2718  JsValue jsv;
2719 
2720  jsv.is_json = true;
2721  jsv.val.json.type = state->element_type;
2722 
2723  if (isnull)
2724  {
2725  Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2726  jsv.val.json.str = NULL;
2727  jsv.val.json.len = 0;
2728  }
2729  else if (state->element_scalar)
2730  {
2731  jsv.val.json.str = state->element_scalar;
2732  jsv.val.json.len = -1; /* null-terminated */
2733  }
2734  else
2735  {
2736  jsv.val.json.str = state->element_start;
2737  jsv.val.json.len = (state->lex->prev_token_terminator -
2738  state->element_start) * sizeof(char);
2739  }
2740 
2741  /* Report if an error occurred. */
2742  if (!populate_array_element(ctx, ndim, &jsv))
2743  return JSON_SEM_ACTION_FAILED;
2744  }
2745 
2746  return JSON_SUCCESS;
2747 }
2748 
2749 /* json scalar handler for populate_array_json() */
2750 static JsonParseErrorType
2751 populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
2752 {
2754  PopulateArrayContext *ctx = state->ctx;
2755  int ndim = state->lex->lex_level;
2756 
2757  if (ctx->ndims <= 0)
2758  {
2759  if (!populate_array_assign_ndims(ctx, ndim))
2760  return JSON_SEM_ACTION_FAILED;
2761  }
2762  else if (ndim < ctx->ndims)
2763  {
2765  /* Getting here means the error was reported softly. */
2767  return JSON_SEM_ACTION_FAILED;
2768  }
2769 
2770  if (ndim == ctx->ndims)
2771  {
2772  /* remember the scalar element token */
2773  state->element_scalar = token;
2774  /* element_type must already be set in populate_array_element_start() */
2775  Assert(state->element_type == tokentype);
2776  }
2777 
2778  return JSON_SUCCESS;
2779 }
2780 
2781 /*
2782  * Parse a json array and populate array
2783  *
2784  * Returns false if an error occurs when parsing.
2785  */
2786 static bool
2787 populate_array_json(PopulateArrayContext *ctx, const char *json, int len)
2788 {
2791 
2792  state.lex = makeJsonLexContextCstringLen(NULL, json, len,
2793  GetDatabaseEncoding(), true);
2794  state.ctx = ctx;
2795 
2796  memset(&sem, 0, sizeof(sem));
2797  sem.semstate = (void *) &state;
2803 
2804  if (pg_parse_json_or_errsave(state.lex, &sem, ctx->escontext))
2805  {
2806  /* number of dimensions should be already known */
2807  Assert(ctx->ndims > 0 && ctx->dims);
2808  }
2809 
2811 
2812  return !SOFT_ERROR_OCCURRED(ctx->escontext);
2813 }
2814 
2815 /*
2816  * populate_array_dim_jsonb() -- Iterate recursively through jsonb sub-array
2817  * elements and accumulate result using given ArrayBuildState.
2818  *
2819  * Returns false if we return partway through because of an error in a
2820  * subroutine.
2821  */
2822 static bool
2824  JsonbValue *jbv, /* jsonb sub-array */
2825  int ndim) /* current dimension */
2826 {
2827  JsonbContainer *jbc = jbv->val.binary.data;
2828  JsonbIterator *it;
2829  JsonbIteratorToken tok;
2830  JsonbValue val;
2831  JsValue jsv;
2832 
2834 
2835  /* Even scalars can end up here thanks to ExecEvalJsonCoercion(). */
2836  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc) ||
2837  JsonContainerIsScalar(jbc))
2838  {
2839  populate_array_report_expected_array(ctx, ndim - 1);
2840  /* Getting here means the error was reported softly. */
2842  return false;
2843  }
2844 
2845  it = JsonbIteratorInit(jbc);
2846 
2847  tok = JsonbIteratorNext(&it, &val, true);
2848  Assert(tok == WJB_BEGIN_ARRAY);
2849 
2850  tok = JsonbIteratorNext(&it, &val, true);
2851 
2852  /*
2853  * If the number of dimensions is not yet known and we have found end of
2854  * the array, or the first child element is not an array, then assign the
2855  * number of dimensions now.
2856  */
2857  if (ctx->ndims <= 0 &&
2858  (tok == WJB_END_ARRAY ||
2859  (tok == WJB_ELEM &&
2860  (val.type != jbvBinary ||
2861  !JsonContainerIsArray(val.val.binary.data)))))
2862  {
2863  if (!populate_array_assign_ndims(ctx, ndim))
2864  return false;
2865  }
2866 
2867  jsv.is_json = false;
2868  jsv.val.jsonb = &val;
2869 
2870  /* process all the array elements */
2871  while (tok == WJB_ELEM)
2872  {
2873  /*
2874  * Recurse only if the dimensions of dimensions is still unknown or if
2875  * it is not the innermost dimension.
2876  */
2877  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2878  {
2879  if (!populate_array_element(ctx, ndim, &jsv))
2880  return false;
2881  }
2882  else
2883  {
2884  /* populate child sub-array */
2885  if (!populate_array_dim_jsonb(ctx, &val, ndim + 1))
2886  return false;
2887 
2888  /* number of dimensions should be already known */
2889  Assert(ctx->ndims > 0 && ctx->dims);
2890 
2891  if (!populate_array_check_dimension(ctx, ndim))
2892  return false;
2893  }
2894 
2895  tok = JsonbIteratorNext(&it, &val, true);
2896  }
2897 
2898  Assert(tok == WJB_END_ARRAY);
2899 
2900  /* free iterator, iterating until WJB_DONE */
2901  tok = JsonbIteratorNext(&it, &val, true);
2902  Assert(tok == WJB_DONE && !it);
2903 
2904  return true;
2905 }
2906 
2907 /*
2908  * Recursively populate an array from json/jsonb
2909  *
2910  * *isnull is set to true if an error is reported during parsing.
2911  */
2912 static Datum
2914  const char *colname,
2915  MemoryContext mcxt,
2916  JsValue *jsv,
2917  bool *isnull,
2918  Node *escontext)
2919 {
2921  Datum result;
2922  int *lbs;
2923  int i;
2924 
2925  ctx.aio = aio;
2926  ctx.mcxt = mcxt;
2927  ctx.acxt = CurrentMemoryContext;
2928  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2929  ctx.colname = colname;
2930  ctx.ndims = 0; /* unknown yet */
2931  ctx.dims = NULL;
2932  ctx.sizes = NULL;
2933  ctx.escontext = escontext;
2934 
2935  if (jsv->is_json)
2936  {
2937  /* Return null if an error was found. */
2938  if (!populate_array_json(&ctx, jsv->val.json.str,
2939  jsv->val.json.len >= 0 ? jsv->val.json.len
2940  : strlen(jsv->val.json.str)))
2941  {
2942  *isnull = true;
2943  return (Datum) 0;
2944  }
2945  }
2946  else
2947  {
2948  /* Return null if an error was found. */
2949  if (!populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1))
2950  {
2951  *isnull = true;
2952  return (Datum) 0;
2953  }
2954  ctx.dims[0] = ctx.sizes[0];
2955  }
2956 
2957  Assert(ctx.ndims > 0);
2958 
2959  lbs = palloc(sizeof(int) * ctx.ndims);
2960 
2961  for (i = 0; i < ctx.ndims; i++)
2962  lbs[i] = 1;
2963 
2964  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2965  ctx.acxt, true);
2966 
2967  pfree(ctx.dims);
2968  pfree(ctx.sizes);
2969  pfree(lbs);
2970 
2971  *isnull = false;
2972  return result;
2973 }
2974 
2975 /*
2976  * Returns false if an error occurs, provided escontext points to an
2977  * ErrorSaveContext.
2978  */
2979 static bool
2980 JsValueToJsObject(JsValue *jsv, JsObject *jso, Node *escontext)
2981 {
2982  jso->is_json = jsv->is_json;
2983 
2984  if (jsv->is_json)
2985  {
2986  /* convert plain-text json into a hash table */
2987  jso->val.json_hash =
2988  get_json_object_as_hash(jsv->val.json.str,
2989  jsv->val.json.len >= 0
2990  ? jsv->val.json.len
2991  : strlen(jsv->val.json.str),
2992  "populate_composite",
2993  escontext);
2994  Assert(jso->val.json_hash != NULL || SOFT_ERROR_OCCURRED(escontext));
2995  }
2996  else
2997  {
2998  JsonbValue *jbv = jsv->val.jsonb;
2999 
3000  if (jbv->type == jbvBinary &&
3001  JsonContainerIsObject(jbv->val.binary.data))
3002  {
3003  jso->val.jsonb_cont = jbv->val.binary.data;
3004  }
3005  else
3006  {
3007  bool is_scalar;
3008 
3009  is_scalar = IsAJsonbScalar(jbv) ||
3010  (jbv->type == jbvBinary &&
3011  JsonContainerIsScalar(jbv->val.binary.data));
3012  errsave(escontext,
3013  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3014  is_scalar
3015  ? errmsg("cannot call %s on a scalar",
3016  "populate_composite")
3017  : errmsg("cannot call %s on an array",
3018  "populate_composite")));
3019  }
3020  }
3021 
3022  return !SOFT_ERROR_OCCURRED(escontext);
3023 }
3024 
3025 /* acquire or update cached tuple descriptor for a composite type */
3026 static void
3028 {
3029  if (!io->tupdesc ||
3030  io->tupdesc->tdtypeid != io->base_typid ||
3031  io->tupdesc->tdtypmod != io->base_typmod)
3032  {
3034  io->base_typmod);
3035  MemoryContext oldcxt;
3036 
3037  if (io->tupdesc)
3038  FreeTupleDesc(io->tupdesc);
3039 
3040  /* copy tuple desc without constraints into cache memory context */
3041  oldcxt = MemoryContextSwitchTo(mcxt);
3042  io->tupdesc = CreateTupleDescCopy(tupdesc);
3043  MemoryContextSwitchTo(oldcxt);
3044 
3045  ReleaseTupleDesc(tupdesc);
3046  }
3047 }
3048 
3049 /*
3050  * Recursively populate a composite (row type) value from json/jsonb
3051  *
3052  * Returns null if an error occurs in a subroutine, provided escontext points
3053  * to an ErrorSaveContext.
3054  */
3055 static Datum
3057  Oid typid,
3058  const char *colname,
3059  MemoryContext mcxt,
3060  HeapTupleHeader defaultval,
3061  JsValue *jsv,
3062  bool *isnull,
3063  Node *escontext)
3064 {
3065  Datum result;
3066 
3067  /* acquire/update cached tuple descriptor */
3068  update_cached_tupdesc(io, mcxt);
3069 
3070  if (*isnull)
3071  result = (Datum) 0;
3072  else
3073  {
3074  HeapTupleHeader tuple;
3075  JsObject jso;
3076 
3077  /* prepare input value */
3078  if (!JsValueToJsObject(jsv, &jso, escontext))
3079  {
3080  *isnull = true;
3081  return (Datum) 0;
3082  }
3083 
3084  /* populate resulting record tuple */
3085  tuple = populate_record(io->tupdesc, &io->record_io,
3086  defaultval, mcxt, &jso, escontext);
3087 
3088  if (SOFT_ERROR_OCCURRED(escontext))
3089  {
3090  *isnull = true;
3091  return (Datum) 0;
3092  }
3093  result = HeapTupleHeaderGetDatum(tuple);
3094 
3095  JsObjectFree(&jso);
3096  }
3097 
3098  /*
3099  * If it's domain over composite, check domain constraints. (This should
3100  * probably get refactored so that we can see the TYPECAT value, but for
3101  * now, we can tell by comparing typid to base_typid.)
3102  */
3103  if (typid != io->base_typid && typid != RECORDOID)
3104  {
3105  if (!domain_check_safe(result, *isnull, typid, &io->domain_info, mcxt,
3106  escontext))
3107  {
3108  *isnull = true;
3109  return (Datum) 0;
3110  }
3111  }
3112 
3113  return result;
3114 }
3115 
3116 /*
3117  * Populate non-null scalar value from json/jsonb value.
3118  *
3119  * Returns null if an error occurs during the call to type input function,
3120  * provided escontext is valid.
3121  */
3122 static Datum
3123 populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv,
3124  bool *isnull, Node *escontext, bool omit_quotes)
3125 {
3126  Datum res;
3127  char *str = NULL;
3128  const char *json = NULL;
3129 
3130  if (jsv->is_json)
3131  {
3132  int len = jsv->val.json.len;
3133 
3134  json = jsv->val.json.str;
3135  Assert(json);
3136  if (len >= 0)
3137  {
3138  /* Need to copy non-null-terminated string */
3139  str = palloc(len + 1 * sizeof(char));
3140  memcpy(str, json, len);
3141  str[len] = '\0';
3142  }
3143  else
3144  {
3145  /* string is already null-terminated */
3146  str = unconstify(char *, json);
3147  }
3148 
3149  /* If converting to json/jsonb, make string into valid JSON literal */
3150  if ((typid == JSONOID || typid == JSONBOID) &&
3151  jsv->val.json.type == JSON_TOKEN_STRING)
3152  {
3154 
3155  initStringInfo(&buf);
3156  escape_json(&buf, str);
3157  /* free temporary buffer */
3158  if (str != json)
3159  pfree(str);
3160  str = buf.data;
3161  }
3162  }
3163  else
3164  {
3165  JsonbValue *jbv = jsv->val.jsonb;
3166 
3167  if (jbv->type == jbvString && omit_quotes)
3168  str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
3169  else if (typid == JSONBOID)
3170  {
3171  Jsonb *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
3172 
3173  return JsonbPGetDatum(jsonb);
3174  }
3175  /* convert jsonb to string for typio call */
3176  else if (typid == JSONOID && jbv->type != jbvBinary)
3177  {
3178  /*
3179  * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
3180  * to json string, preserving quotes around top-level strings.
3181  */
3182  Jsonb *jsonb = JsonbValueToJsonb(jbv);
3183 
3184  str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
3185  }
3186  else if (jbv->type == jbvString) /* quotes are stripped */
3187  str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
3188  else if (jbv->type == jbvBool)
3189  str = pstrdup(jbv->val.boolean ? "true" : "false");
3190  else if (jbv->type == jbvNumeric)
3192  PointerGetDatum(jbv->val.numeric)));
3193  else if (jbv->type == jbvBinary)
3194  str = JsonbToCString(NULL, jbv->val.binary.data,
3195  jbv->val.binary.len);
3196  else
3197  elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
3198  }
3199 
3200  if (!InputFunctionCallSafe(&io->typiofunc, str, io->typioparam, typmod,
3201  escontext, &res))
3202  {
3203  res = (Datum) 0;
3204  *isnull = true;
3205  }
3206 
3207  /* free temporary buffer */
3208  if (str != json)
3209  pfree(str);
3210 
3211  return res;
3212 }
3213 
3214 static Datum
3216  Oid typid,
3217  const char *colname,
3218  MemoryContext mcxt,
3219  JsValue *jsv,
3220  bool *isnull,
3221  Node *escontext,
3222  bool omit_quotes)
3223 {
3224  Datum res;
3225 
3226  if (*isnull)
3227  res = (Datum) 0;
3228  else
3229  {
3231  io->base_typid, io->base_typmod,
3232  colname, mcxt, PointerGetDatum(NULL),
3233  jsv, isnull, escontext, omit_quotes);
3234  Assert(!*isnull || SOFT_ERROR_OCCURRED(escontext));
3235  }
3236 
3237  if (!domain_check_safe(res, *isnull, typid, &io->domain_info, mcxt,
3238  escontext))
3239  {
3240  *isnull = true;
3241  return (Datum) 0;
3242  }
3243 
3244  return res;
3245 }
3246 
3247 /* prepare column metadata cache for the given type */
3248 static void
3250  Oid typid,
3251  int32 typmod,
3252  MemoryContext mcxt,
3253  bool need_scalar)
3254 {
3255  HeapTuple tup;
3257 
3258  column->typid = typid;
3259  column->typmod = typmod;
3260 
3261  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3262  if (!HeapTupleIsValid(tup))
3263  elog(ERROR, "cache lookup failed for type %u", typid);
3264 
3265  type = (Form_pg_type) GETSTRUCT(tup);
3266 
3267  if (type->typtype == TYPTYPE_DOMAIN)
3268  {
3269  /*
3270  * We can move directly to the bottom base type; domain_check() will
3271  * take care of checking all constraints for a stack of domains.
3272  */
3273  Oid base_typid;
3274  int32 base_typmod = typmod;
3275 
3276  base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
3277  if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
3278  {
3279  /* domain over composite has its own code path */
3280  column->typcat = TYPECAT_COMPOSITE_DOMAIN;
3281  column->io.composite.record_io = NULL;
3282  column->io.composite.tupdesc = NULL;
3283  column->io.composite.base_typid = base_typid;
3284  column->io.composite.base_typmod = base_typmod;
3285  column->io.composite.domain_info = NULL;
3286  }
3287  else
3288  {
3289  /* domain over anything else */
3290  column->typcat = TYPECAT_DOMAIN;
3291  column->io.domain.base_typid = base_typid;
3292  column->io.domain.base_typmod = base_typmod;
3293  column->io.domain.base_io =
3294  MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3295  column->io.domain.domain_info = NULL;
3296  }
3297  }
3298  else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3299  {
3300  column->typcat = TYPECAT_COMPOSITE;
3301  column->io.composite.record_io = NULL;
3302  column->io.composite.tupdesc = NULL;
3303  column->io.composite.base_typid = typid;
3304  column->io.composite.base_typmod = typmod;
3305  column->io.composite.domain_info = NULL;
3306  }
3307  else if (IsTrueArrayType(type))
3308  {
3309  column->typcat = TYPECAT_ARRAY;
3311  sizeof(ColumnIOData));
3312  column->io.array.element_type = type->typelem;
3313  /* array element typemod stored in attribute's typmod */
3314  column->io.array.element_typmod = typmod;
3315  }
3316  else
3317  {
3318  column->typcat = TYPECAT_SCALAR;
3319  need_scalar = true;
3320  }
3321 
3322  /* caller can force us to look up scalar_io info even for non-scalars */
3323  if (need_scalar)
3324  {
3325  Oid typioproc;
3326 
3327  getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
3328  fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
3329  }
3330 
3331  ReleaseSysCache(tup);
3332 }
3333 
3334 /*
3335  * Populate and return the value of specified type from a given json/jsonb
3336  * value 'json_val'. 'cache' is caller-specified pointer to save the
3337  * ColumnIOData that will be initialized on the 1st call and then reused
3338  * during any subsequent calls. 'mcxt' gives the memory context to allocate
3339  * the ColumnIOData and any other subsidiary memory in. 'escontext',
3340  * if not NULL, tells that any errors that occur should be handled softly.
3341  */
3342 Datum
3343 json_populate_type(Datum json_val, Oid json_type,
3344  Oid typid, int32 typmod,
3345  void **cache, MemoryContext mcxt,
3346  bool *isnull, bool omit_quotes,
3347  Node *escontext)
3348 {
3349  JsValue jsv = {0};
3350  JsonbValue jbv;
3351 
3352  jsv.is_json = json_type == JSONOID;
3353 
3354  if (*isnull)
3355  {
3356  if (jsv.is_json)
3357  jsv.val.json.str = NULL;
3358  else
3359  jsv.val.jsonb = NULL;
3360  }
3361  else if (jsv.is_json)
3362  {
3363  text *json = DatumGetTextPP(json_val);
3364 
3365  jsv.val.json.str = VARDATA_ANY(json);
3366  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3367  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3368  * populate_composite() */
3369  }
3370  else
3371  {
3372  Jsonb *jsonb = DatumGetJsonbP(json_val);
3373 
3374  jsv.val.jsonb = &jbv;
3375 
3376  if (omit_quotes)
3377  {
3378  char *str = JsonbUnquote(DatumGetJsonbP(json_val));
3379 
3380  /* fill the quote-stripped string */
3381  jbv.type = jbvString;
3382  jbv.val.string.len = strlen(str);
3383  jbv.val.string.val = str;
3384  }
3385  else
3386  {
3387  /* fill binary jsonb value pointing to jb */
3388  jbv.type = jbvBinary;
3389  jbv.val.binary.data = &jsonb->root;
3390  jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
3391  }
3392  }
3393 
3394  if (*cache == NULL)
3395  *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3396 
3397  return populate_record_field(*cache, typid, typmod, NULL, mcxt,
3398  PointerGetDatum(NULL), &jsv, isnull,
3399  escontext, omit_quotes);
3400 }
3401 
3402 /* recursively populate a record field or an array element from a json/jsonb value */
3403 static Datum
3405  Oid typid,
3406  int32 typmod,
3407  const char *colname,
3408  MemoryContext mcxt,
3409  Datum defaultval,
3410  JsValue *jsv,
3411  bool *isnull,
3412  Node *escontext,
3413  bool omit_scalar_quotes)
3414 {
3415  TypeCat typcat;
3416 
3418 
3419  /*
3420  * Prepare column metadata cache for the given type. Force lookup of the
3421  * scalar_io data so that the json string hack below will work.
3422  */
3423  if (col->typid != typid || col->typmod != typmod)
3424  prepare_column_cache(col, typid, typmod, mcxt, true);
3425 
3426  *isnull = JsValueIsNull(jsv);
3427 
3428  typcat = col->typcat;
3429 
3430  /* try to convert json string to a non-scalar type through input function */
3431  if (JsValueIsString(jsv) &&
3432  (typcat == TYPECAT_ARRAY ||
3433  typcat == TYPECAT_COMPOSITE ||
3434  typcat == TYPECAT_COMPOSITE_DOMAIN))
3435  typcat = TYPECAT_SCALAR;
3436 
3437  /* we must perform domain checks for NULLs, otherwise exit immediately */
3438  if (*isnull &&
3439  typcat != TYPECAT_DOMAIN &&
3440  typcat != TYPECAT_COMPOSITE_DOMAIN)
3441  return (Datum) 0;
3442 
3443  switch (typcat)
3444  {
3445  case TYPECAT_SCALAR:
3446  return populate_scalar(&col->scalar_io, typid, typmod, jsv,
3447  isnull, escontext, omit_scalar_quotes);
3448 
3449  case TYPECAT_ARRAY:
3450  return populate_array(&col->io.array, colname, mcxt, jsv,
3451  isnull, escontext);
3452 
3453  case TYPECAT_COMPOSITE:
3455  return populate_composite(&col->io.composite, typid,
3456  colname, mcxt,
3457  DatumGetPointer(defaultval)
3458  ? DatumGetHeapTupleHeader(defaultval)
3459  : NULL,
3460  jsv, isnull,
3461  escontext);
3462 
3463  case TYPECAT_DOMAIN:
3464  return populate_domain(&col->io.domain, typid, colname, mcxt,
3465  jsv, isnull, escontext, omit_scalar_quotes);
3466 
3467  default:
3468  elog(ERROR, "unrecognized type category '%c'", typcat);
3469  return (Datum) 0;
3470  }
3471 }
3472 
3473 static RecordIOData *
3475 {
3477  MemoryContextAlloc(mcxt,
3478  offsetof(RecordIOData, columns) +
3479  ncolumns * sizeof(ColumnIOData));
3480 
3481  data->record_type = InvalidOid;
3482  data->record_typmod = 0;
3483  data->ncolumns = ncolumns;
3484  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3485 
3486  return data;
3487 }
3488 
3489 static bool
3490 JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
3491 {
3492  jsv->is_json = obj->is_json;
3493 
3494  if (jsv->is_json)
3495  {
3496  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3497  HASH_FIND, NULL);
3498 
3499  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3500  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3501  hashentry->val;
3502  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3503 
3504  return hashentry != NULL;
3505  }
3506  else
3507  {
3508  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3509  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3510  NULL);
3511 
3512  return jsv->val.jsonb != NULL;
3513  }
3514 }
3515 
3516 /* populate a record tuple from json/jsonb value */
3517 static HeapTupleHeader
3519  RecordIOData **record_p,
3520  HeapTupleHeader defaultval,
3521  MemoryContext mcxt,
3522  JsObject *obj,
3523  Node *escontext)
3524 {
3525  RecordIOData *record = *record_p;
3526  Datum *values;
3527  bool *nulls;
3528  HeapTuple res;
3529  int ncolumns = tupdesc->natts;
3530  int i;
3531 
3532  /*
3533  * if the input json is empty, we can only skip the rest if we were passed
3534  * in a non-null record, since otherwise there may be issues with domain
3535  * nulls.
3536  */
3537  if (defaultval && JsObjectIsEmpty(obj))
3538  return defaultval;
3539 
3540  /* (re)allocate metadata cache */
3541  if (record == NULL ||
3542  record->ncolumns != ncolumns)
3543  *record_p = record = allocate_record_info(mcxt, ncolumns);
3544 
3545  /* invalidate metadata cache if the record type has changed */
3546  if (record->record_type != tupdesc->tdtypeid ||
3547  record->record_typmod != tupdesc->tdtypmod)
3548  {
3549  MemSet(record, 0, offsetof(RecordIOData, columns) +
3550  ncolumns * sizeof(ColumnIOData));
3551  record->record_type = tupdesc->tdtypeid;
3552  record->record_typmod = tupdesc->tdtypmod;
3553  record->ncolumns = ncolumns;
3554  }
3555 
3556  values = (Datum *) palloc(ncolumns * sizeof(Datum));
3557  nulls = (bool *) palloc(ncolumns * sizeof(bool));
3558 
3559  if (defaultval)
3560  {
3561  HeapTupleData tuple;
3562 
3563  /* Build a temporary HeapTuple control structure */
3564  tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
3565  ItemPointerSetInvalid(&(tuple.t_self));
3566  tuple.t_tableOid = InvalidOid;
3567  tuple.t_data = defaultval;
3568 
3569  /* Break down the tuple into fields */
3570  heap_deform_tuple(&tuple, tupdesc, values, nulls);
3571  }
3572  else
3573  {
3574  for (i = 0; i < ncolumns; ++i)
3575  {
3576  values[i] = (Datum) 0;
3577  nulls[i] = true;
3578  }
3579  }
3580 
3581  for (i = 0; i < ncolumns; ++i)
3582  {
3583  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
3584  char *colname = NameStr(att->attname);
3585  JsValue field = {0};
3586  bool found;
3587 
3588  /* Ignore dropped columns in datatype */
3589  if (att->attisdropped)
3590  {
3591  nulls[i] = true;
3592  continue;
3593  }
3594 
3595  found = JsObjectGetField(obj, colname, &field);
3596 
3597  /*
3598  * we can't just skip here if the key wasn't found since we might have
3599  * a domain to deal with. If we were passed in a non-null record
3600  * datum, we assume that the existing values are valid (if they're
3601  * not, then it's not our fault), but if we were passed in a null,
3602  * then every field which we don't populate needs to be run through
3603  * the input function just in case it's a domain type.
3604  */
3605  if (defaultval && !found)
3606  continue;
3607 
3608  values[i] = populate_record_field(&record->columns[i],
3609  att->atttypid,
3610  att->atttypmod,
3611  colname,
3612  mcxt,
3613  nulls[i] ? (Datum) 0 : values[i],
3614  &field,
3615  &nulls[i],
3616  escontext,
3617  false);
3618  }
3619 
3620  res = heap_form_tuple(tupdesc, values, nulls);
3621 
3622  pfree(values);
3623  pfree(nulls);
3624 
3625  return res->t_data;
3626 }
3627 
3628 /*
3629  * Setup for json{b}_populate_record{set}: result type will be same as first
3630  * argument's type --- unless first argument is "null::record", which we can't
3631  * extract type info from; we handle that later.
3632  */
3633 static void
3635  const char *funcname,
3636  PopulateRecordCache *cache)
3637 {
3638  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3639  prepare_column_cache(&cache->c,
3640  cache->argtype, -1,
3641  cache->fn_mcxt, false);
3642  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3643  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3644  ereport(ERROR,
3645  (errcode(ERRCODE_DATATYPE_MISMATCH),
3646  /* translator: %s is a function name, eg json_to_record */
3647  errmsg("first argument of %s must be a row type",
3648  funcname)));
3649 }
3650 
3651 /*
3652  * Setup for json{b}_to_record{set}: result type is specified by calling
3653  * query. We'll also use this code for json{b}_populate_record{set},
3654  * if we discover that the first argument is a null of type RECORD.
3655  *
3656  * Here it is syntactically impossible to specify the target type
3657  * as domain-over-composite.
3658  */
3659 static void
3661  const char *funcname,
3662  PopulateRecordCache *cache)
3663 {
3664  TupleDesc tupdesc;
3665  MemoryContext old_cxt;
3666 
3667  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3668  ereport(ERROR,
3669  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3670  /* translator: %s is a function name, eg json_to_record */
3671  errmsg("could not determine row type for result of %s",
3672  funcname),
3673  errhint("Provide a non-null record argument, "
3674  "or call the function in the FROM clause "
3675  "using a column definition list.")));
3676 
3677  Assert(tupdesc);
3678  cache->argtype = tupdesc->tdtypeid;
3679 
3680  /* If we go through this more than once, avoid memory leak */
3681  if (cache->c.io.composite.tupdesc)
3683 
3684  /* Save identified tupdesc */
3685  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3686  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3687  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3688  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3689  MemoryContextSwitchTo(old_cxt);
3690 }
3691 
3692 /*
3693  * common worker for json{b}_populate_record() and json{b}_to_record()
3694  * is_json and have_record_arg identify the specific function
3695  */
3696 static Datum
3698  bool is_json, bool have_record_arg,
3699  Node *escontext)
3700 {
3701  int json_arg_num = have_record_arg ? 1 : 0;
3702  JsValue jsv = {0};
3703  HeapTupleHeader rec;
3704  Datum rettuple;
3705  bool isnull;
3706  JsonbValue jbv;
3707  MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
3708  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3709 
3710  /*
3711  * If first time through, identify input/result record type. Note that
3712  * this stanza looks only at fcinfo context, which can't change during the
3713  * query; so we may not be able to fully resolve a RECORD input type yet.
3714  */
3715  if (!cache)
3716  {
3717  fcinfo->flinfo->fn_extra = cache =
3718  MemoryContextAllocZero(fnmcxt, sizeof(*cache));
3719  cache->fn_mcxt = fnmcxt;
3720 
3721  if (have_record_arg)
3722  get_record_type_from_argument(fcinfo, funcname, cache);
3723  else
3724  get_record_type_from_query(fcinfo, funcname, cache);
3725  }
3726 
3727  /* Collect record arg if we have one */
3728  if (!have_record_arg)
3729  rec = NULL; /* it's json{b}_to_record() */
3730  else if (!PG_ARGISNULL(0))
3731  {
3732  rec = PG_GETARG_HEAPTUPLEHEADER(0);
3733 
3734  /*
3735  * When declared arg type is RECORD, identify actual record type from
3736  * the tuple itself.
3737  */
3738  if (cache->argtype == RECORDOID)
3739  {
3742  }
3743  }
3744  else
3745  {
3746  rec = NULL;
3747 
3748  /*
3749  * When declared arg type is RECORD, identify actual record type from
3750  * calling query, or fail if we can't.
3751  */
3752  if (cache->argtype == RECORDOID)
3753  {
3754  get_record_type_from_query(fcinfo, funcname, cache);
3755  /* This can't change argtype, which is important for next time */
3756  Assert(cache->argtype == RECORDOID);
3757  }
3758  }
3759 
3760  /* If no JSON argument, just return the record (if any) unchanged */
3761  if (PG_ARGISNULL(json_arg_num))
3762  {
3763  if (rec)
3764  PG_RETURN_POINTER(rec);
3765  else
3766  PG_RETURN_NULL();
3767  }
3768 
3769  jsv.is_json = is_json;
3770 
3771  if (is_json)
3772  {
3773  text *json = PG_GETARG_TEXT_PP(json_arg_num);
3774 
3775  jsv.val.json.str = VARDATA_ANY(json);
3776  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3777  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3778  * populate_composite() */
3779  }
3780  else
3781  {
3782  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3783 
3784  jsv.val.jsonb = &jbv;
3785 
3786  /* fill binary jsonb value pointing to jb */
3787  jbv.type = jbvBinary;
3788  jbv.val.binary.data = &jb->root;
3789  jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
3790  }
3791 
3792  isnull = false;
3793  rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
3794  NULL, fnmcxt, rec, &jsv, &isnull,
3795  escontext);
3796  Assert(!isnull || SOFT_ERROR_OCCURRED(escontext));
3797 
3798  PG_RETURN_DATUM(rettuple);
3799 }
3800 
3801 /*
3802  * get_json_object_as_hash
3803  *
3804  * Decomposes a json object into a hash table.
3805  *
3806  * Returns the hash table if the json is parsed successfully, NULL otherwise.
3807  */
3808 static HTAB *
3809 get_json_object_as_hash(const char *json, int len, const char *funcname,
3810  Node *escontext)
3811 {
3812  HASHCTL ctl;
3813  HTAB *tab;
3814  JHashState *state;
3815  JsonSemAction *sem;
3816 
3817  ctl.keysize = NAMEDATALEN;
3818  ctl.entrysize = sizeof(JsonHashEntry);
3819  ctl.hcxt = CurrentMemoryContext;
3820  tab = hash_create("json object hashtable",
3821  100,
3822  &ctl,
3824 
3825  state = palloc0(sizeof(JHashState));
3826  sem = palloc0(sizeof(JsonSemAction));
3827 
3828  state->function_name = funcname;
3829  state->hash = tab;
3830  state->lex = makeJsonLexContextCstringLen(NULL, json, len,
3831  GetDatabaseEncoding(), true);
3832 
3833  sem->semstate = (void *) state;
3835  sem->scalar = hash_scalar;
3838 
3839  if (!pg_parse_json_or_errsave(state->lex, sem, escontext))
3840  {
3841  hash_destroy(state->hash);
3842  tab = NULL;
3843  }
3844 
3845  freeJsonLexContext(state->lex);
3846 
3847  return tab;
3848 }
3849 
3850 static JsonParseErrorType
3851 hash_object_field_start(void *state, char *fname, bool isnull)
3852 {
3853  JHashState *_state = (JHashState *) state;
3854 
3855  if (_state->lex->lex_level > 1)
3856  return JSON_SUCCESS;
3857 
3858  /* remember token type */
3859  _state->saved_token_type = _state->lex->token_type;
3860 
3861  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3863  {
3864  /* remember start position of the whole text of the subobject */
3865  _state->save_json_start = _state->lex->token_start;
3866  }
3867  else
3868  {
3869  /* must be a scalar */
3870  _state->save_json_start = NULL;
3871  }
3872 
3873  return JSON_SUCCESS;
3874 }
3875 
3876 static JsonParseErrorType
3877 hash_object_field_end(void *state, char *fname, bool isnull)
3878 {
3879  JHashState *_state = (JHashState *) state;
3880  JsonHashEntry *hashentry;
3881  bool found;
3882 
3883  /*
3884  * Ignore nested fields.
3885  */
3886  if (_state->lex->lex_level > 1)
3887  return JSON_SUCCESS;
3888 
3889  /*
3890  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3891  * (Note: without this test, the hash code would truncate the string at
3892  * NAMEDATALEN-1, and could then match against a similarly-truncated
3893  * record field name. That would be a reasonable behavior, but this code
3894  * has previously insisted on exact equality, so we keep this behavior.)
3895  */
3896  if (strlen(fname) >= NAMEDATALEN)
3897  return JSON_SUCCESS;
3898 
3899  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3900 
3901  /*
3902  * found being true indicates a duplicate. We don't do anything about
3903  * that, a later field with the same name overrides the earlier field.
3904  */
3905 
3906  hashentry->type = _state->saved_token_type;
3907  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3908 
3909  if (_state->save_json_start != NULL)
3910  {
3911  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3912  char *val = palloc((len + 1) * sizeof(char));
3913 
3914  memcpy(val, _state->save_json_start, len);
3915  val[len] = '\0';
3916  hashentry->val = val;
3917  }
3918  else
3919  {
3920  /* must have had a scalar instead */
3921  hashentry->val = _state->saved_scalar;
3922  }
3923 
3924  return JSON_SUCCESS;
3925 }
3926 
3927 static JsonParseErrorType
3929 {
3930  JHashState *_state = (JHashState *) state;
3931 
3932  if (_state->lex->lex_level == 0)
3933  ereport(ERROR,
3934  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3935  errmsg("cannot call %s on an array", _state->function_name)));
3936 
3937  return JSON_SUCCESS;
3938 }
3939 
3940 static JsonParseErrorType
3941 hash_scalar(void *state, char *token, JsonTokenType tokentype)
3942 {
3943  JHashState *_state = (JHashState *) state;
3944 
3945  if (_state->lex->lex_level == 0)
3946  ereport(ERROR,
3947  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3948  errmsg("cannot call %s on a scalar", _state->function_name)));
3949 
3950  if (_state->lex->lex_level == 1)
3951  {
3952  _state->saved_scalar = token;
3953  /* saved_token_type must already be set in hash_object_field_start() */
3954  Assert(_state->saved_token_type == tokentype);
3955  }
3956 
3957  return JSON_SUCCESS;
3958 }
3959 
3960 
3961 /*
3962  * SQL function json_populate_recordset
3963  *
3964  * set fields in a set of records from the argument json,
3965  * which must be an array of objects.
3966  *
3967  * similar to json_populate_record, but the tuple-building code
3968  * is pushed down into the semantic action handlers so it's done
3969  * per object in the array.
3970  */
3971 Datum
3973 {
3974  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3975  false, true);
3976 }
3977 
3978 Datum
3980 {
3981  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3982  false, false);
3983 }
3984 
3985 Datum
3987 {
3988  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3989  true, true);
3990 }
3991 
3992 Datum
3994 {
3995  return populate_recordset_worker(fcinfo, "json_to_recordset",
3996  true, false);
3997 }
3998 
3999 static void
4001 {
4002  PopulateRecordCache *cache = state->cache;
4003  HeapTupleHeader tuphead;
4004  HeapTupleData tuple;
4005 
4006  /* acquire/update cached tuple descriptor */
4007  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
4008 
4009  /* replace record fields from json */
4010  tuphead = populate_record(cache->c.io.composite.tupdesc,
4011  &cache->c.io.composite.record_io,
4012  state->rec,
4013  cache->fn_mcxt,
4014  obj,
4015  NULL);
4016 
4017  /* if it's domain over composite, check domain constraints */
4018  if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
4019  (void) domain_check_safe(HeapTupleHeaderGetDatum(tuphead), false,
4020  cache->argtype,
4021  &cache->c.io.composite.domain_info,
4022  cache->fn_mcxt,
4023  NULL);
4024 
4025  /* ok, save into tuplestore */
4026  tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
4027  ItemPointerSetInvalid(&(tuple.t_self));
4028  tuple.t_tableOid = InvalidOid;
4029  tuple.t_data = tuphead;
4030 
4031  tuplestore_puttuple(state->tuple_store, &tuple);
4032 }
4033 
4034 /*
4035  * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
4036  * is_json and have_record_arg identify the specific function
4037  */
4038 static Datum
4040  bool is_json, bool have_record_arg)
4041 {
4042  int json_arg_num = have_record_arg ? 1 : 0;
4043  ReturnSetInfo *rsi;
4044  MemoryContext old_cxt;
4045  HeapTupleHeader rec;
4046  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
4048 
4049  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
4050 
4051  if (!rsi || !IsA(rsi, ReturnSetInfo))
4052  ereport(ERROR,
4053  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4054  errmsg("set-valued function called in context that cannot accept a set")));
4055 
4056  if (!(rsi->allowedModes & SFRM_Materialize))
4057  ereport(ERROR,
4058  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4059  errmsg("materialize mode required, but it is not allowed in this context")));
4060 
4062 
4063  /*
4064  * If first time through, identify input/result record type. Note that
4065  * this stanza looks only at fcinfo context, which can't change during the
4066  * query; so we may not be able to fully resolve a RECORD input type yet.
4067  */
4068  if (!cache)
4069  {
4070  fcinfo->flinfo->fn_extra = cache =
4071  MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
4072  cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
4073 
4074  if (have_record_arg)
4075  get_record_type_from_argument(fcinfo, funcname, cache);
4076  else
4077  get_record_type_from_query(fcinfo, funcname, cache);
4078  }
4079 
4080  /* Collect record arg if we have one */
4081  if (!have_record_arg)
4082  rec = NULL; /* it's json{b}_to_recordset() */
4083  else if (!PG_ARGISNULL(0))
4084  {
4085  rec = PG_GETARG_HEAPTUPLEHEADER(0);
4086 
4087  /*
4088  * When declared arg type is RECORD, identify actual record type from
4089  * the tuple itself.
4090  */
4091  if (cache->argtype == RECORDOID)
4092  {
4095  }
4096  }
4097  else
4098  {
4099  rec = NULL;
4100 
4101  /*
4102  * When declared arg type is RECORD, identify actual record type from
4103  * calling query, or fail if we can't.
4104  */
4105  if (cache->argtype == RECORDOID)
4106  {
4107  get_record_type_from_query(fcinfo, funcname, cache);
4108  /* This can't change argtype, which is important for next time */
4109  Assert(cache->argtype == RECORDOID);
4110  }
4111  }
4112 
4113  /* if the json is null send back an empty set */
4114  if (PG_ARGISNULL(json_arg_num))
4115  PG_RETURN_NULL();
4116 
4117  /*
4118  * Forcibly update the cached tupdesc, to ensure we have the right tupdesc
4119  * to return even if the JSON contains no rows.
4120  */
4121  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
4122 
4124 
4125  /* make tuplestore in a sufficiently long-lived memory context */
4127  state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
4129  false, work_mem);
4130  MemoryContextSwitchTo(old_cxt);
4131 
4132  state->function_name = funcname;
4133  state->cache = cache;
4134  state->rec = rec;
4135 
4136  if (is_json)
4137  {
4138  text *json = PG_GETARG_TEXT_PP(json_arg_num);
4139  JsonLexContext lex;
4140  JsonSemAction *sem;
4141 
4142  sem = palloc0(sizeof(JsonSemAction));
4143 
4144  makeJsonLexContext(&lex, json, true);
4145 
4146  sem->semstate = (void *) state;
4154 
4155  state->lex = &lex;
4156 
4158 
4159  freeJsonLexContext(&lex);
4160  state->lex = NULL;
4161  }
4162  else
4163  {
4164  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
4165  JsonbIterator *it;
4166  JsonbValue v;
4167  bool skipNested = false;
4169 
4170  if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
4171  ereport(ERROR,
4172  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4173  errmsg("cannot call %s on a non-array",
4174  funcname)));
4175 
4176  it = JsonbIteratorInit(&jb->root);
4177 
4178  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4179  {
4180  skipNested = true;
4181 
4182  if (r == WJB_ELEM)
4183  {
4184  JsObject obj;
4185 
4186  if (v.type != jbvBinary ||
4187  !JsonContainerIsObject(v.val.binary.data))
4188  ereport(ERROR,
4189  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4190  errmsg("argument of %s must be an array of objects",
4191  funcname)));
4192 
4193  obj.is_json = false;
4194  obj.val.jsonb_cont = v.val.binary.data;
4195 
4197  }
4198  }
4199  }
4200 
4201  /*
4202  * Note: we must copy the cached tupdesc because the executor will free
4203  * the passed-back setDesc, but we want to hang onto the cache in case
4204  * we're called again in the same query.
4205  */
4206  rsi->setResult = state->tuple_store;
4208 
4209  PG_RETURN_NULL();
4210 }
4211 
4212 static JsonParseErrorType
4214 {
4216  int lex_level = _state->lex->lex_level;
4217  HASHCTL ctl;
4218 
4219  /* Reject object at top level: we must have an array at level 0 */
4220  if (lex_level == 0)
4221  ereport(ERROR,
4222  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4223  errmsg("cannot call %s on an object",
4224  _state->function_name)));
4225 
4226  /* Nested objects require no special processing */
4227  if (lex_level > 1)
4228  return JSON_SUCCESS;
4229 
4230  /* Object at level 1: set up a new hash table for this object */
4231  ctl.keysize = NAMEDATALEN;
4232  ctl.entrysize = sizeof(JsonHashEntry);
4233  ctl.hcxt = CurrentMemoryContext;
4234  _state->json_hash = hash_create("json object hashtable",
4235  100,
4236  &ctl,
4238 
4239  return JSON_SUCCESS;
4240 }
4241 
4242 static JsonParseErrorType
4244 {
4246  JsObject obj;
4247 
4248  /* Nested objects require no special processing */
4249  if (_state->lex->lex_level > 1)
4250  return JSON_SUCCESS;
4251 
4252  obj.is_json = true;
4253  obj.val.json_hash = _state->json_hash;
4254 
4255  /* Otherwise, construct and return a tuple based on this level-1 object */
4256  populate_recordset_record(_state, &obj);
4257 
4258  /* Done with hash for this object */
4259  hash_destroy(_state->json_hash);
4260  _state->json_hash = NULL;
4261 
4262  return JSON_SUCCESS;
4263 }
4264 
4265 static JsonParseErrorType
4267 {
4269 
4270  if (_state->lex->lex_level == 1 &&
4272  ereport(ERROR,
4273  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4274  errmsg("argument of %s must be an array of objects",
4275  _state->function_name)));
4276 
4277  return JSON_SUCCESS;
4278 }
4279 
4280 static JsonParseErrorType
4282 {
4283  /* nothing to do */
4284  return JSON_SUCCESS;
4285 }
4286 
4287 static JsonParseErrorType
4289 {
4291 
4292  if (_state->lex->lex_level == 0)
4293  ereport(ERROR,
4294  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4295  errmsg("cannot call %s on a scalar",
4296  _state->function_name)));
4297 
4298  if (_state->lex->lex_level == 2)
4299  _state->saved_scalar = token;
4300 
4301  return JSON_SUCCESS;
4302 }
4303 
4304 static JsonParseErrorType
4305 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
4306 {
4308 
4309  if (_state->lex->lex_level > 2)
4310  return JSON_SUCCESS;
4311 
4312  _state->saved_token_type = _state->lex->token_type;
4313 
4314  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
4316  {
4317  _state->save_json_start = _state->lex->token_start;
4318  }
4319  else
4320  {
4321  _state->save_json_start = NULL;
4322  }
4323 
4324  return JSON_SUCCESS;
4325 }
4326 
4327 static JsonParseErrorType
4328 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
4329 {
4331  JsonHashEntry *hashentry;
4332  bool found;
4333 
4334  /*
4335  * Ignore nested fields.
4336  */
4337  if (_state->lex->lex_level > 2)
4338  return JSON_SUCCESS;
4339 
4340  /*
4341  * Ignore field names >= NAMEDATALEN - they can't match a record field.
4342  * (Note: without this test, the hash code would truncate the string at
4343  * NAMEDATALEN-1, and could then match against a similarly-truncated
4344  * record field name. That would be a reasonable behavior, but this code
4345  * has previously insisted on exact equality, so we keep this behavior.)
4346  */
4347  if (strlen(fname) >= NAMEDATALEN)
4348  return JSON_SUCCESS;
4349 
4350  hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
4351 
4352  /*
4353  * found being true indicates a duplicate. We don't do anything about
4354  * that, a later field with the same name overrides the earlier field.
4355  */
4356 
4357  hashentry->type = _state->saved_token_type;
4358  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
4359 
4360  if (_state->save_json_start != NULL)
4361  {
4362  int len = _state->lex->prev_token_terminator - _state->save_json_start;
4363  char *val = palloc((len + 1) * sizeof(char));
4364 
4365  memcpy(val, _state->save_json_start, len);
4366  val[len] = '\0';
4367  hashentry->val = val;
4368  }
4369  else
4370  {
4371  /* must have had a scalar instead */
4372  hashentry->val = _state->saved_scalar;
4373  }
4374 
4375  return JSON_SUCCESS;
4376 }
4377 
4378 /*
4379  * Semantic actions for json_strip_nulls.
4380  *
4381  * Simply repeat the input on the output unless we encounter
4382  * a null object field. State for this is set when the field
4383  * is started and reset when the scalar action (which must be next)
4384  * is called.
4385  */
4386 
4387 static JsonParseErrorType
4389 {
4390  StripnullState *_state = (StripnullState *) state;
4391 
4392  appendStringInfoCharMacro(_state->strval, '{');
4393 
4394  return JSON_SUCCESS;
4395 }
4396 
4397 static JsonParseErrorType
4399 {
4400  StripnullState *_state = (StripnullState *) state;
4401 
4402  appendStringInfoCharMacro(_state->strval, '}');
4403 
4404  return JSON_SUCCESS;
4405 }
4406 
4407 static JsonParseErrorType
4409 {
4410  StripnullState *_state = (StripnullState *) state;
4411 
4412  appendStringInfoCharMacro(_state->strval, '[');
4413 
4414  return JSON_SUCCESS;
4415 }
4416 
4417 static JsonParseErrorType
4419 {
4420  StripnullState *_state = (StripnullState *) state;
4421 
4422  appendStringInfoCharMacro(_state->strval, ']');
4423 
4424  return JSON_SUCCESS;
4425 }
4426 
4427 static JsonParseErrorType
4428 sn_object_field_start(void *state, char *fname, bool isnull)
4429 {
4430  StripnullState *_state = (StripnullState *) state;
4431 
4432  if (isnull)
4433  {
4434  /*
4435  * The next thing must be a scalar or isnull couldn't be true, so
4436  * there is no danger of this state being carried down into a nested
4437  * object or array. The flag will be reset in the scalar action.
4438  */
4439  _state->skip_next_null = true;
4440  return JSON_SUCCESS;
4441  }
4442 
4443  if (_state->strval->data[_state->strval->len - 1] != '{')
4444  appendStringInfoCharMacro(_state->strval, ',');
4445 
4446  /*
4447  * Unfortunately we don't have the quoted and escaped string any more, so
4448  * we have to re-escape it.
4449  */
4450  escape_json(_state->strval, fname);
4451 
4452  appendStringInfoCharMacro(_state->strval, ':');
4453 
4454  return JSON_SUCCESS;
4455 }
4456 
4457 static JsonParseErrorType
4458 sn_array_element_start(void *state, bool isnull)
4459 {
4460  StripnullState *_state = (StripnullState *) state;
4461 
4462  if (_state->strval->data[_state->strval->len - 1] != '[')
4463  appendStringInfoCharMacro(_state->strval, ',');
4464 
4465  return JSON_SUCCESS;
4466 }
4467 
4468 static JsonParseErrorType
4469 sn_scalar(void *state, char *token, JsonTokenType tokentype)
4470 {
4471  StripnullState *_state = (StripnullState *) state;
4472 
4473  if (_state->skip_next_null)
4474  {
4475  Assert(tokentype == JSON_TOKEN_NULL);
4476  _state->skip_next_null = false;
4477  return JSON_SUCCESS;
4478  }
4479 
4480  if (tokentype == JSON_TOKEN_STRING)
4481  escape_json(_state->strval, token);
4482  else
4484 
4485  return JSON_SUCCESS;
4486 }
4487 
4488 /*
4489  * SQL function json_strip_nulls(json) -> json
4490  */
4491 Datum
4493 {
4494  text *json = PG_GETARG_TEXT_PP(0);
4496  JsonLexContext lex;
4497  JsonSemAction *sem;
4498 
4499  state = palloc0(sizeof(StripnullState));
4500  sem = palloc0(sizeof(JsonSemAction));
4501 
4502  state->lex = makeJsonLexContext(&lex, json, true);
4503  state->strval = makeStringInfo();
4504  state->skip_next_null = false;
4505 
4506  sem->semstate = (void *) state;
4511  sem->scalar = sn_scalar;
4514 
4516 
4518  state->strval->len));
4519 }
4520 
4521 /*
4522  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
4523  */
4524 Datum
4526 {
4527  Jsonb *jb = PG_GETARG_JSONB_P(0);
4528  JsonbIterator *it;
4529  JsonbParseState *parseState = NULL;
4530  JsonbValue *res = NULL;
4531  JsonbValue v,
4532  k;
4534  bool last_was_key = false;
4535 
4536  if (JB_ROOT_IS_SCALAR(jb))
4537  PG_RETURN_POINTER(jb);
4538 
4539  it = JsonbIteratorInit(&jb->root);
4540 
4541  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4542  {
4543  Assert(!(type == WJB_KEY && last_was_key));
4544 
4545  if (type == WJB_KEY)
4546  {
4547  /* stash the key until we know if it has a null value */
4548  k = v;
4549  last_was_key = true;
4550  continue;
4551  }
4552 
4553  if (last_was_key)
4554  {
4555  /* if the last element was a key this one can't be */
4556  last_was_key = false;
4557 
4558  /* skip this field if value is null */
4559  if (type == WJB_VALUE && v.type == jbvNull)
4560  continue;
4561 
4562  /* otherwise, do a delayed push of the key */
4563  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4564  }
4565 
4566  if (type == WJB_VALUE || type == WJB_ELEM)
4567  res = pushJsonbValue(&parseState, type, &v);
4568  else
4569  res = pushJsonbValue(&parseState, type, NULL);
4570  }
4571 
4572  Assert(res != NULL);
4573 
4575 }
4576 
4577 /*
4578  * SQL function jsonb_pretty (jsonb)
4579  *
4580  * Pretty-printed text for the jsonb
4581  */
4582 Datum
4584 {
4585  Jsonb *jb = PG_GETARG_JSONB_P(0);
4587 
4588  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4589 
4591 }
4592 
4593 /*
4594  * SQL function jsonb_concat (jsonb, jsonb)
4595  *
4596  * function for || operator
4597  */
4598 Datum
4600 {
4601  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4602  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4603  JsonbParseState *state = NULL;
4604  JsonbValue *res;
4605  JsonbIterator *it1,
4606  *it2;
4607 
4608  /*
4609  * If one of the jsonb is empty, just return the other if it's not scalar
4610  * and both are of the same kind. If it's a scalar or they are of
4611  * different kinds we need to perform the concatenation even if one is
4612  * empty.
4613  */
4614  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4615  {
4616  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4617  PG_RETURN_JSONB_P(jb2);
4618  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4619  PG_RETURN_JSONB_P(jb1);
4620  }
4621 
4622  it1 = JsonbIteratorInit(&jb1->root);
4623  it2 = JsonbIteratorInit(&jb2->root);
4624 
4625  res = IteratorConcat(&it1, &it2, &state);
4626 
4627  Assert(res != NULL);
4628 
4630 }
4631 
4632 
4633 /*
4634  * SQL function jsonb_delete (jsonb, text)
4635  *
4636  * return a copy of the jsonb with the indicated item
4637  * removed.
4638  */
4639 Datum
4641 {
4642  Jsonb *in = PG_GETARG_JSONB_P(0);
4643  text *key = PG_GETARG_TEXT_PP(1);
4644  char *keyptr = VARDATA_ANY(key);
4645  int keylen = VARSIZE_ANY_EXHDR(key);
4646  JsonbParseState *state = NULL;
4647  JsonbIterator *it;
4648  JsonbValue v,
4649  *res = NULL;
4650  bool skipNested = false;
4652 
4653  if (JB_ROOT_IS_SCALAR(in))
4654  ereport(ERROR,
4655  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4656  errmsg("cannot delete from scalar")));
4657 
4658  if (JB_ROOT_COUNT(in) == 0)
4659  PG_RETURN_JSONB_P(in);
4660 
4661  it = JsonbIteratorInit(&in->root);
4662 
4663  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4664  {
4665  skipNested = true;
4666 
4667  if ((r == WJB_ELEM || r == WJB_KEY) &&
4668  (v.type == jbvString && keylen == v.val.string.len &&
4669  memcmp(keyptr, v.val.string.val, keylen) == 0))
4670  {
4671  /* skip corresponding value as well */
4672  if (r == WJB_KEY)
4673  (void) JsonbIteratorNext(&it, &v, true);
4674 
4675  continue;
4676  }
4677 
4678  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4679  }
4680 
4681  Assert(res != NULL);
4682 
4684 }
4685 
4686 /*
4687  * SQL function jsonb_delete (jsonb, variadic text[])
4688  *
4689  * return a copy of the jsonb with the indicated items
4690  * removed.
4691  */
4692 Datum
4694 {
4695  Jsonb *in = PG_GETARG_JSONB_P(0);
4696  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4697  Datum *keys_elems;
4698  bool *keys_nulls;
4699  int keys_len;
4700  JsonbParseState *state = NULL;
4701  JsonbIterator *it;
4702  JsonbValue v,
4703  *res = NULL;
4704  bool skipNested = false;
4706 
4707  if (ARR_NDIM(keys) > 1)
4708  ereport(ERROR,
4709  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4710  errmsg("wrong number of array subscripts")));
4711 
4712  if (JB_ROOT_IS_SCALAR(in))
4713  ereport(ERROR,
4714  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4715  errmsg("cannot delete from scalar")));
4716 
4717  if (JB_ROOT_COUNT(in) == 0)
4718  PG_RETURN_JSONB_P(in);
4719 
4720  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4721 
4722  if (keys_len == 0)
4723  PG_RETURN_JSONB_P(in);
4724 
4725  it = JsonbIteratorInit(&in->root);
4726 
4727  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4728  {
4729  skipNested = true;
4730 
4731  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4732  {
4733  int i;
4734  bool found = false;
4735 
4736  for (i = 0; i < keys_len; i++)
4737  {
4738  char *keyptr;
4739  int keylen;
4740 
4741  if (keys_nulls[i])
4742  continue;
4743 
4744  /* We rely on the array elements not being toasted */
4745  keyptr = VARDATA_ANY(keys_elems[i]);
4746  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4747  if (keylen == v.val.string.len &&
4748  memcmp(keyptr, v.val.string.val, keylen) == 0)
4749  {
4750  found = true;
4751  break;
4752  }
4753  }
4754  if (found)
4755  {
4756  /* skip corresponding value as well */
4757  if (r == WJB_KEY)
4758  (void) JsonbIteratorNext(&it, &v, true);
4759 
4760  continue;
4761  }
4762  }
4763 
4764  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4765  }
4766 
4767  Assert(res != NULL);
4768 
4770 }
4771 
4772 /*
4773  * SQL function jsonb_delete (jsonb, int)
4774  *
4775  * return a copy of the jsonb with the indicated item
4776  * removed. Negative int means count back from the
4777  * end of the items.
4778  */
4779 Datum
4781 {
4782  Jsonb *in = PG_GETARG_JSONB_P(0);
4783  int idx = PG_GETARG_INT32(1);
4784  JsonbParseState *state = NULL;
4785  JsonbIterator *it;
4786  uint32 i = 0,
4787  n;
4788  JsonbValue v,
4789  *res = NULL;
4791 
4792  if (JB_ROOT_IS_SCALAR(in))
4793  ereport(ERROR,
4794  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4795  errmsg("cannot delete from scalar")));
4796 
4797  if (JB_ROOT_IS_OBJECT(in))
4798  ereport(ERROR,
4799  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4800  errmsg("cannot delete from object using integer index")));
4801 
4802  if (JB_ROOT_COUNT(in) == 0)
4803  PG_RETURN_JSONB_P(in);
4804 
4805  it = JsonbIteratorInit(&in->root);
4806 
4807  r = JsonbIteratorNext(&it, &v, false);
4808  Assert(r == WJB_BEGIN_ARRAY);
4809  n = v.val.array.nElems;
4810 
4811  if (idx < 0)
4812  {
4813  if (-idx > n)
4814  idx = n;
4815  else
4816  idx = n + idx;
4817  }
4818 
4819  if (idx >= n)
4820  PG_RETURN_JSONB_P(in);
4821 
4822  pushJsonbValue(&state, r, NULL);
4823 
4824  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4825  {
4826  if (r == WJB_ELEM)
4827  {
4828  if (i++ == idx)
4829  continue;
4830  }
4831 
4832  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4833  }
4834 
4835  Assert(res != NULL);
4836 
4838 }
4839 
4840 /*
4841  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
4842  */
4843 Datum
4845 {
4846  Jsonb *in = PG_GETARG_JSONB_P(0);
4847  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4848  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4850  bool create = PG_GETARG_BOOL(3);
4851  JsonbValue *res = NULL;
4852  Datum *path_elems;
4853  bool *path_nulls;
4854  int path_len;
4855  JsonbIterator *it;
4856  JsonbParseState *st = NULL;
4857 
4858  JsonbToJsonbValue(newjsonb, &newval);
4859 
4860  if (ARR_NDIM(path) > 1)
4861  ereport(ERROR,
4862  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4863  errmsg("wrong number of array subscripts")));
4864 
4865  if (JB_ROOT_IS_SCALAR(in))
4866  ereport(ERROR,
4867  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4868  errmsg("cannot set path in scalar")));
4869 
4870  if (JB_ROOT_COUNT(in) == 0 && !create)
4871  PG_RETURN_JSONB_P(in);
4872 
4873  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4874 
4875  if (path_len == 0)
4876  PG_RETURN_JSONB_P(in);
4877 
4878  it = JsonbIteratorInit(&in->root);
4879 
4880  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4881  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4882 
4883  Assert(res != NULL);
4884 
4886 }
4887 
4888 
4889 /*
4890  * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text)
4891  */
4892 Datum
4894 {
4895  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4896  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4897  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4898  /* bool create = PG_GETARG_BOOL(3); */
4899  text *handle_null;
4900  char *handle_val;
4901 
4902  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4903  PG_RETURN_NULL();
4904 
4905  /* could happen if they pass in an explicit NULL */
4906  if (PG_ARGISNULL(4))
4907  ereport(ERROR,
4908  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4909  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4910 
4911  /* if the new value isn't an SQL NULL just call jsonb_set */
4912  if (!PG_ARGISNULL(2))
4913  return jsonb_set(fcinfo);
4914 
4915  handle_null = PG_GETARG_TEXT_P(4);
4916  handle_val = text_to_cstring(handle_null);
4917 
4918  if (strcmp(handle_val, "raise_exception") == 0)
4919  {
4920  ereport(ERROR,
4921  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4922  errmsg("JSON value must not be null"),
4923  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4924  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4925  return (Datum) 0; /* silence stupider compilers */
4926  }
4927  else if (strcmp(handle_val, "use_json_null") == 0)
4928  {
4929  Datum newval;
4930 
4932 
4933  fcinfo->args[2].value = newval;
4934  fcinfo->args[2].isnull = false;
4935  return jsonb_set(fcinfo);
4936  }
4937  else if (strcmp(handle_val, "delete_key") == 0)
4938  {
4939  return jsonb_delete_path(fcinfo);
4940  }
4941  else if (strcmp(handle_val, "return_target") == 0)
4942  {
4943  Jsonb *in = PG_GETARG_JSONB_P(0);
4944 
4945  PG_RETURN_JSONB_P(in);
4946  }
4947  else
4948  {
4949  ereport(ERROR,
4950  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4951  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4952  return (Datum) 0; /* silence stupider compilers */
4953  }
4954 }
4955 
4956 /*
4957  * SQL function jsonb_delete_path(jsonb, text[])
4958  */
4959 Datum
4961 {
4962  Jsonb *in = PG_GETARG_JSONB_P(0);
4963  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4964  JsonbValue *res = NULL;
4965  Datum *path_elems;
4966  bool *path_nulls;
4967  int path_len;
4968  JsonbIterator *it;
4969  JsonbParseState *st = NULL;
4970 
4971  if (ARR_NDIM(path) > 1)
4972  ereport(ERROR,
4973  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4974  errmsg("wrong number of array subscripts")));
4975 
4976  if (JB_ROOT_IS_SCALAR(in))
4977  ereport(ERROR,
4978  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4979  errmsg("cannot delete path in scalar")));
4980 
4981  if (JB_ROOT_COUNT(in) == 0)
4982  PG_RETURN_JSONB_P(in);
4983 
4984  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4985 
4986  if (path_len == 0)
4987  PG_RETURN_JSONB_P(in);
4988 
4989  it = JsonbIteratorInit(&in->root);
4990 
4991  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4992  0, NULL, JB_PATH_DELETE);
4993 
4994  Assert(res != NULL);
4995 
4997 }
4998 
4999 /*
5000  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
5001  */
5002 Datum
5004 {
5005  Jsonb *in = PG_GETARG_JSONB_P(0);
5006  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
5007  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
5009  bool after = PG_GETARG_BOOL(3);
5010  JsonbValue *res = NULL;
5011  Datum *path_elems;
5012  bool *path_nulls;
5013  int path_len;
5014  JsonbIterator *it;
5015  JsonbParseState *st = NULL;
5016 
5017  JsonbToJsonbValue(newjsonb, &newval);
5018 
5019  if (ARR_NDIM(path) > 1)
5020  ereport(ERROR,
5021  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5022  errmsg("wrong number of array subscripts")));
5023 
5024  if (JB_ROOT_IS_SCALAR(in))
5025  ereport(ERROR,
5026  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5027  errmsg("cannot set path in scalar")));
5028 
5029  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
5030 
5031  if (path_len == 0)
5032  PG_RETURN_JSONB_P(in);
5033 
5034  it = JsonbIteratorInit(&in->root);
5035 
5036  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5038 
5039  Assert(res != NULL);
5040 
5042 }
5043 
5044 /*
5045  * Iterate over all jsonb objects and merge them into one.
5046  * The logic of this function copied from the same hstore function,
5047  * except the case, when it1 & it2 represents jbvObject.
5048  * In that case we just append the content of it2 to it1 without any
5049  * verifications.
5050  */
5051 static JsonbValue *
5054 {
5055  JsonbValue v1,
5056  v2,
5057  *res = NULL;
5058  JsonbIteratorToken r1,
5059  r2,
5060  rk1,
5061  rk2;
5062 
5063  rk1 = JsonbIteratorNext(it1, &v1, false);
5064  rk2 = JsonbIteratorNext(it2, &v2, false);
5065 
5066  /*
5067  * JsonbIteratorNext reports raw scalars as if they were single-element
5068  * arrays; hence we only need consider "object" and "array" cases here.
5069  */
5070  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
5071  {
5072  /*
5073  * Both inputs are objects.
5074  *
5075  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
5076  * (because res will not be finished yet).
5077  */
5078  pushJsonbValue(state, rk1, NULL);
5079  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
5080  pushJsonbValue(state, r1, &v1);
5081 
5082  /*
5083  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
5084  * (the concatenation will be completed). Any duplicate keys will
5085  * automatically override the value from the first object.
5086  */
5087  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5088  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5089  }
5090  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
5091  {
5092  /*
5093  * Both inputs are arrays.
5094  */
5095  pushJsonbValue(state, rk1, NULL);
5096 
5097  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5098  {
5099  Assert(r1 == WJB_ELEM);
5100  pushJsonbValue(state, r1, &v1);
5101  }
5102 
5103  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
5104  {
5105  Assert(r2 == WJB_ELEM);
5106  pushJsonbValue(state, WJB_ELEM, &v2);
5107  }
5108 
5109  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
5110  }
5111  else if (rk1 == WJB_BEGIN_OBJECT)
5112  {
5113  /*
5114  * We have object || array.
5115  */
5116  Assert(rk2 == WJB_BEGIN_ARRAY);
5117 
5119 
5121  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
5122  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
5123 
5124  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5125  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
5126  }
5127  else
5128  {
5129  /*
5130  * We have array || object.
5131  */
5132  Assert(rk1 == WJB_BEGIN_ARRAY);
5133  Assert(rk2 == WJB_BEGIN_OBJECT);
5134 
5136 
5137  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5138  pushJsonbValue(state, r1, &v1);
5139 
5141  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5142  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5143 
5145  }
5146 
5147  return res;
5148 }
5149 
5150 /*
5151  * Do most of the heavy work for jsonb_set/jsonb_insert
5152  *
5153  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
5154  *
5155  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
5156  * we create the new value if the key or array index does not exist.
5157  *
5158  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
5159  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
5160  *
5161  * If JB_PATH_FILL_GAPS bit is set, this will change an assignment logic in
5162  * case if target is an array. The assignment index will not be restricted by
5163  * number of elements in the array, and if there are any empty slots between
5164  * last element of the array and a new one they will be filled with nulls. If
5165  * the index is negative, it still will be considered an index from the end
5166  * of the array. Of a part of the path is not present and this part is more
5167  * than just one last element, this flag will instruct to create the whole
5168  * chain of corresponding objects and insert the value.
5169  *
5170  * JB_PATH_CONSISTENT_POSITION for an array indicates that the caller wants to
5171  * keep values with fixed indices. Indices for existing elements could be
5172  * changed (shifted forward) in case if the array is prepended with a new value
5173  * and a negative index out of the range, so this behavior will be prevented
5174  * and return an error.
5175  *
5176  * All path elements before the last must already exist
5177  * whatever bits in op_type are set, or nothing is done.
5178  */
5179 static JsonbValue *
5180 setPath(JsonbIterator **it, Datum *path_elems,
5181  bool *path_nulls, int path_len,
5182  JsonbParseState **st, int level, JsonbValue *newval, int op_type)
5183 {
5184  JsonbValue v;
5186  JsonbValue *res;
5187 
5189 
5190  if (path_nulls[level])
5191  ereport(ERROR,
5192  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5193  errmsg("path element at position %d is null",
5194  level + 1)));
5195 
5196  r = JsonbIteratorNext(it, &v, false);
5197 
5198  switch (r)
5199  {
5200  case WJB_BEGIN_ARRAY:
5201 
5202  /*
5203  * If instructed complain about attempts to replace within a raw
5204  * scalar value. This happens even when current level is equal to
5205  * path_len, because the last path key should also correspond to
5206  * an object or an array, not raw scalar.
5207  */
5208  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
5209  v.val.array.rawScalar)
5210  ereport(ERROR,
5211  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5212  errmsg("cannot replace existing key"),
5213  errdetail("The path assumes key is a composite object, "
5214  "but it is a scalar value.")));
5215 
5216  (void) pushJsonbValue(st, r, NULL);
5217  setPathArray(it, path_elems, path_nulls, path_len, st, level,
5218  newval, v.val.array.nElems, op_type);
5219  r = JsonbIteratorNext(it, &v, false);
5220  Assert(r == WJB_END_ARRAY);
5221  res = pushJsonbValue(st, r, NULL);
5222  break;
5223  case WJB_BEGIN_OBJECT:
5224  (void) pushJsonbValue(st, r, NULL);
5225  setPathObject(it, path_elems, path_nulls, path_len, st, level,
5226  newval, v.val.object.nPairs, op_type);
5227  r = JsonbIteratorNext(it, &v, true);
5228  Assert(r == WJB_END_OBJECT);
5229  res = pushJsonbValue(st, r, NULL);
5230  break;
5231  case WJB_ELEM:
5232  case WJB_VALUE:
5233 
5234  /*
5235  * If instructed complain about attempts to replace within a
5236  * scalar value. This happens even when current level is equal to
5237  * path_len, because the last path key should also correspond to
5238  * an object or an array, not an element or value.
5239  */
5240  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
5241  ereport(ERROR,
5242  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5243  errmsg("cannot replace existing key"),
5244  errdetail("The path assumes key is a composite object, "
5245  "but it is a scalar value.")));
5246 
5247  res = pushJsonbValue(st, r, &v);
5248  break;
5249  default:
5250  elog(ERROR, "unrecognized iterator result: %d", (int) r);
5251  res = NULL; /* keep compiler quiet */
5252  break;
5253  }
5254 
5255  return res;
5256 }
5257 
5258 /*
5259  * Object walker for setPath
5260  */
5261 static void
5262 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
5263  int path_len, JsonbParseState **st, int level,
5264  JsonbValue *newval, uint32 npairs, int op_type)
5265 {
5266  text *pathelem = NULL;
5267  int i;
5268  JsonbValue k,
5269  v;
5270  bool done = false;
5271 
5272  if (level >= path_len || path_nulls[level])
5273  done = true;
5274  else
5275  {
5276  /* The path Datum could be toasted, in which case we must detoast it */
5277  pathelem = DatumGetTextPP(path_elems[level]);
5278  }
5279 
5280  /* empty object is a special case for create */
5281  if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
5282  (level == path_len - 1))
5283  {
5284  JsonbValue newkey;
5285 
5286  newkey.type = jbvString;
5287  newkey.val.string.val = VARDATA_ANY(pathelem);
5288  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5289 
5290  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5291  (void) pushJsonbValue(st, WJB_VALUE, newval);
5292  }
5293 
5294  for (i = 0; i < npairs; i++)
5295  {
5296  JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
5297 
5298  Assert(r == WJB_KEY);
5299 
5300  if (!done &&
5301  k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
5302  memcmp(k.val.string.val, VARDATA_ANY(pathelem),
5303  k.val.string.len) == 0)
5304  {
5305  done = true;
5306 
5307  if (level == path_len - 1)
5308  {
5309  /*
5310  * called from jsonb_insert(), it forbids redefining an
5311  * existing value
5312  */
5313  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
5314  ereport(ERROR,
5315  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5316  errmsg("cannot replace existing key"),
5317  errhint("Try using the function jsonb_set "
5318  "to replace key value.")));
5319 
5320  r = JsonbIteratorNext(it, &v, true); /* skip value */
5321  if (!(op_type & JB_PATH_DELETE))
5322  {
5323  (void) pushJsonbValue(st, WJB_KEY, &k);
5324  (void) pushJsonbValue(st, WJB_VALUE, newval);
5325  }
5326  }
5327  else
5328  {
5329  (void) pushJsonbValue(st, r, &k);
5330  setPath(it, path_elems, path_nulls, path_len,
5331  st, level + 1, newval, op_type);
5332  }
5333  }
5334  else
5335  {
5336  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
5337  level == path_len - 1 && i == npairs - 1)
5338  {
5339  JsonbValue newkey;
5340 
5341  newkey.type = jbvString;
5342  newkey.val.string.val = VARDATA_ANY(pathelem);
5343  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5344 
5345  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5346  (void) pushJsonbValue(st, WJB_VALUE, newval);
5347  }
5348 
5349  (void) pushJsonbValue(st, r, &k);
5350  r = JsonbIteratorNext(it, &v, false);
5351  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5352  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5353  {
5354  int walking_level = 1;
5355 
5356  while (walking_level != 0)
5357  {
5358  r = JsonbIteratorNext(it, &v, false);
5359 
5360  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5361  ++walking_level;
5362  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5363  --walking_level;
5364 
5365  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5366  }
5367  }
5368  }
5369  }
5370 
5371  /*--
5372  * If we got here there are only few possibilities:
5373  * - no target path was found, and an open object with some keys/values was
5374  * pushed into the state
5375  * - an object is empty, only WJB_BEGIN_OBJECT is pushed
5376  *
5377  * In both cases if instructed to create the path when not present,
5378  * generate the whole chain of empty objects and insert the new value
5379  * there.
5380  */
5381  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5382  {
5383  JsonbValue newkey;
5384 
5385  newkey.type = jbvString;
5386  newkey.val.string.val = VARDATA_ANY(pathelem);
5387  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5388 
5389  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5390  (void) push_path(st, level, path_elems, path_nulls,
5391  path_len, newval);
5392 
5393  /* Result is closed with WJB_END_OBJECT outside of this function */
5394  }
5395 }
5396 
5397 /*
5398  * Array walker for setPath
5399  */
5400 static void
5401 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
5402  int path_len, JsonbParseState **st, int level,
5403  JsonbValue *newval, uint32 nelems, int op_type)
5404 {
5405  JsonbValue v;
5406  int idx,
5407  i;
5408  bool done = false;
5409 
5410  /* pick correct index */
5411  if (level < path_len && !path_nulls[level])
5412  {
5413  char *c = TextDatumGetCString(path_elems[level]);
5414  char *badp;
5415 
5416  errno = 0;
5417  idx = strtoint(c, &badp, 10);
5418  if (badp == c || *badp != '\0' || errno != 0)
5419  ereport(ERROR,
5420  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5421  errmsg("path element at position %d is not an integer: \"%s\"",
5422  level + 1, c)));
5423  }
5424  else
5425  idx = nelems;
5426 
5427  if (idx < 0)
5428  {
5429  if (-idx > nelems)
5430  {
5431  /*
5432  * If asked to keep elements position consistent, it's not allowed
5433  * to prepend the array.
5434  */
5435  if (op_type & JB_PATH_CONSISTENT_POSITION)
5436  ereport(ERROR,
5437  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5438  errmsg("path element at position %d is out of range: %d",
5439  level + 1, idx)));
5440  else
5441  idx = INT_MIN;
5442  }
5443  else
5444  idx = nelems + idx;
5445  }
5446 
5447  /*
5448  * Filling the gaps means there are no limits on the positive index are
5449  * imposed, we can set any element. Otherwise limit the index by nelems.
5450  */
5451  if (!(op_type & JB_PATH_FILL_GAPS))
5452  {
5453  if (idx > 0 && idx > nelems)
5454  idx = nelems;
5455  }
5456 
5457  /*
5458  * if we're creating, and idx == INT_MIN, we prepend the new value to the
5459  * array also if the array is empty - in which case we don't really care
5460  * what the idx value is
5461  */
5462  if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5463  (op_type & JB_PATH_CREATE_OR_INSERT))
5464  {
5465  Assert(newval != NULL);
5466 
5467  if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
5468  push_null_elements(st, idx);
5469 
5470  (void) pushJsonbValue(st, WJB_ELEM, newval);
5471 
5472  done = true;
5473  }
5474 
5475  /* iterate over the array elements */
5476  for (i = 0; i < nelems; i++)
5477  {
5479 
5480  if (i == idx && level < path_len)
5481  {
5482  done = true;
5483 
5484  if (level == path_len - 1)
5485  {
5486  r = JsonbIteratorNext(it, &v, true); /* skip */
5487 
5488  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
5489  (void) pushJsonbValue(st, WJB_ELEM, newval);
5490 
5491  /*
5492  * We should keep current value only in case of
5493  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
5494  * otherwise it should be deleted or replaced
5495  */
5496  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
5497  (void) pushJsonbValue(st, r, &v);
5498 
5499  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
5500  (void) pushJsonbValue(st, WJB_ELEM, newval);
5501  }
5502  else
5503  (void) setPath(it, path_elems, path_nulls, path_len,
5504  st, level + 1, newval, op_type);
5505  }
5506  else
5507  {
5508  r = JsonbIteratorNext(it, &v, false);
5509 
5510  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5511 
5512  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5513  {
5514  int walking_level = 1;
5515 
5516  while (walking_level != 0)
5517  {
5518  r = JsonbIteratorNext(it, &v, false);
5519 
5520  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5521  ++walking_level;
5522  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5523  --walking_level;
5524 
5525  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5526  }
5527  }
5528  }
5529  }
5530 
5531  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
5532  {
5533  /*
5534  * If asked to fill the gaps, idx could be bigger than nelems, so
5535  * prepend the new element with nulls if that's the case.
5536  */
5537  if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
5538  push_null_elements(st, idx - nelems);
5539 
5540  (void) pushJsonbValue(st, WJB_ELEM, newval);
5541  done = true;
5542  }
5543 
5544  /*--
5545  * If we got here there are only few possibilities:
5546  * - no target path was found, and an open array with some keys/values was
5547  * pushed into the state
5548  * - an array is empty, only WJB_BEGIN_ARRAY is pushed
5549  *
5550  * In both cases if instructed to create the path when not present,
5551  * generate the whole chain of empty objects and insert the new value
5552  * there.
5553  */
5554  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5555  {
5556  if (idx > 0)
5557  push_null_elements(st, idx - nelems);
5558 
5559  (void) push_path(st, level, path_elems, path_nulls,
5560  path_len, newval);
5561 
5562  /* Result is closed with WJB_END_OBJECT outside of this function */
5563  }
5564 }
5565 
5566 /*
5567  * Parse information about what elements of a jsonb document we want to iterate
5568  * in functions iterate_json(b)_values. This information is presented in jsonb
5569  * format, so that it can be easily extended in the future.
5570  */
5571 uint32
5573 {
5574  JsonbIterator *it;
5575  JsonbValue v;
5577  uint32 flags = 0;
5578 
5579  it = JsonbIteratorInit(&jb->root);
5580 
5581  type = JsonbIteratorNext(&it, &v, false);
5582 
5583  /*
5584  * We iterate over array (scalar internally is represented as array, so,
5585  * we will accept it too) to check all its elements. Flag names are
5586  * chosen the same as jsonb_typeof uses.
5587  */
5588  if (type != WJB_BEGIN_ARRAY)
5589  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5590  errmsg("wrong flag type, only arrays and scalars are allowed")));
5591 
5592  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5593  {
5594  if (v.type != jbvString)
5595  ereport(ERROR,
5596  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5597  errmsg("flag array element is not a string"),
5598  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5599 
5600  if (v.val.string.len == 3 &&
5601  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5602  flags |= jtiAll;
5603  else if (v.val.string.len == 3 &&
5604  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5605  flags |= jtiKey;
5606  else if (v.val.string.len == 6 &&
5607  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5608  flags |= jtiString;
5609  else if (v.val.string.len == 7 &&
5610  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5611  flags |= jtiNumeric;
5612  else if (v.val.string.len == 7 &&
5613  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5614  flags |= jtiBool;
5615  else
5616  ereport(ERROR,
5617  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5618  errmsg("wrong flag in flag array: \"%s\"",
5619  pnstrdup(v.val.string.val, v.val.string.len)),
5620  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5621  }
5622 
5623  /* expect end of array now */
5624  if (type != WJB_END_ARRAY)
5625  elog(ERROR, "unexpected end of flag array");
5626 
5627  /* get final WJB_DONE and free iterator */
5628  type = JsonbIteratorNext(&it, &v, false);
5629  if (type != WJB_DONE)
5630  elog(ERROR, "unexpected end of flag array");
5631 
5632  return flags;
5633 }
5634 
5635 /*
5636  * Iterate over jsonb values or elements, specified by flags, and pass them
5637  * together with an iteration state to a specified JsonIterateStringValuesAction.
5638  */
5639 void
5642 {
5643  JsonbIterator *it;
5644  JsonbValue v;
5646 
5647  it = JsonbIteratorInit(&jb->root);
5648 
5649  /*
5650  * Just recursively iterating over jsonb and call callback on all
5651  * corresponding elements
5652  */
5653  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5654  {
5655  if (type == WJB_KEY)
5656  {
5657  if (flags & jtiKey)
5658  action(state, v.val.string.val, v.val.string.len);
5659 
5660  continue;
5661  }
5662  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5663  {
5664  /* do not call callback for composite JsonbValue */
5665  continue;
5666  }
5667 
5668  /* JsonbValue is a value of object or element of array */
5669  switch (v.type)
5670  {
5671  case jbvString:
5672  if (flags & jtiString)
5673  action(state, v.val.string.val, v.val.string.len);
5674  break;
5675  case jbvNumeric:
5676  if (flags & jtiNumeric)
5677  {
5678  char *val;
5679 
5681  NumericGetDatum(v.val.numeric)));
5682 
5683  action(state, val, strlen(val));
5684  pfree(val);
5685  }
5686  break;
5687  case jbvBool:
5688  if (flags & jtiBool)
5689  {
5690  if (v.val.boolean)
5691  action(state, "true", 4);
5692  else
5693  action(state, "false", 5);
5694  }
5695  break;
5696  default:
5697  /* do not call callback for composite JsonbValue */
5698  break;
5699  }
5700  }
5701 }
5702 
5703 /*
5704  * Iterate over json values and elements, specified by flags, and pass them
5705  * together with an iteration state to a specified JsonIterateStringValuesAction.
5706  */
5707 void
5708 iterate_json_values(text *json, uint32 flags, void *action_state,
5710 {
5711  JsonLexContext lex;
5712  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5714 
5715  state->lex = makeJsonLexContext(&lex, json, true);
5716  state->action = action;
5717  state->action_state = action_state;
5718  state->flags = flags;
5719 
5720  sem->semstate = (void *) state;
5723 
5725  freeJsonLexContext(&lex);
5726 }
5727 
5728 /*
5729  * An auxiliary function for iterate_json_values to invoke a specified
5730  * JsonIterateStringValuesAction for specified values.
5731  */
5732 static JsonParseErrorType
5734 {
5736 
5737  switch (tokentype)
5738  {
5739  case JSON_TOKEN_STRING:
5740  if (_state->flags & jtiString)
5741  _state->action(_state->action_state, token, strlen(token));
5742  break;
5743  case JSON_TOKEN_NUMBER:
5744  if (_state->flags & jtiNumeric)
5745  _state->action(_state->action_state, token, strlen(token));
5746  break;
5747  case JSON_TOKEN_TRUE:
5748  case JSON_TOKEN_FALSE:
5749  if (_state->flags & jtiBool)
5750  _state->action(_state->action_state, token, strlen(token));
5751  break;
5752  default:
5753  /* do not call callback for any other token */
5754  break;
5755  }
5756 
5757  return JSON_SUCCESS;
5758 }
5759 
5760 static JsonParseErrorType
5761 iterate_values_object_field_start(void *state, char *fname, bool isnull)
5762 {
5764 
5765  if (_state->flags & jtiKey)
5766  {
5767  char *val = pstrdup(fname);
5768 
5769  _state->action(_state->action_state, val, strlen(val));
5770  }
5771 
5772  return JSON_SUCCESS;
5773 }
5774 
5775 /*
5776  * Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
5777  * to every string value or element. Any necessary context for a
5778  * JsonTransformStringValuesAction can be passed in the action_state variable.
5779  * Function returns a copy of an original jsonb object with transformed values.
5780  */
5781 Jsonb *
5782 transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
5783  JsonTransformStringValuesAction transform_action)
5784 {
5785  JsonbIterator *it;
5786  JsonbValue v,
5787  *res = NULL;
5789  JsonbParseState *st = NULL;
5790  text *out;
5791  bool is_scalar = false;
5792 
5793  it = JsonbIteratorInit(&jsonb->root);
5794  is_scalar = it->isScalar;
5795 
5796  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5797  {
5798  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
5799  {
5800  out = transform_action(action_state, v.val.string.val, v.val.string.len);
5801  /* out is probably not toasted, but let's be sure */
5802  out = pg_detoast_datum_packed(out);
5803  v.val.string.val = VARDATA_ANY(out);
5804  v.val.string.len = VARSIZE_ANY_EXHDR(out);
5805  res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
5806  }
5807  else
5808  {
5809  res = pushJsonbValue(&st, type, (type == WJB_KEY ||
5810  type == WJB_VALUE ||
5811  type == WJB_ELEM) ? &v : NULL);
5812  }
5813  }
5814 
5815  if (res->type == jbvArray)
5816  res->val.array.rawScalar = is_scalar;
5817 
5818  return JsonbValueToJsonb(res);
5819 }
5820 
5821 /*
5822  * Iterate over a json, and apply a specified JsonTransformStringValuesAction
5823  * to every string value or element. Any necessary context for a
5824  * JsonTransformStringValuesAction can be passed in the action_state variable.
5825  * Function returns a StringInfo, which is a copy of an original json with
5826  * transformed values.
5827  */
5828 text *
5829 transform_json_string_values(text *json, void *action_state,
5830  JsonTransformStringValuesAction transform_action)
5831 {
5832  JsonLexContext lex;
5833  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5835 
5836  state->lex = makeJsonLexContext(&lex, json, true);
5837  state->strval = makeStringInfo();
5838  state->action = transform_action;
5839  state->action_state = action_state;
5840 
5841  sem->semstate = (void *) state;
5849 
5851  freeJsonLexContext(&lex);
5852 
5853  return cstring_to_text_with_len(state->strval->data, state->strval->len);
5854 }
5855 
5856 /*
5857  * Set of auxiliary functions for transform_json_string_values to invoke a
5858  * specified JsonTransformStringValuesAction for all values and left everything
5859  * else untouched.
5860  */
5861 static JsonParseErrorType
5863 {
5865 
5866  appendStringInfoCharMacro(_state->strval, '{');
5867 
5868  return JSON_SUCCESS;
5869 }
5870 
5871 static JsonParseErrorType
5873 {
5875 
5876  appendStringInfoCharMacro(_state->strval, '}');
5877 
5878  return JSON_SUCCESS;
5879 }
5880 
5881 static JsonParseErrorType
5883 {
5885 
5886  appendStringInfoCharMacro(_state->strval, '[');
5887 
5888  return JSON_SUCCESS;
5889 }
5890 
5891 static JsonParseErrorType
5893 {
5895 
5896  appendStringInfoCharMacro(_state->strval, ']');
5897 
5898  return JSON_SUCCESS;
5899 }
5900 
5901 static JsonParseErrorType
5902 transform_string_values_object_field_start(void *state, char *fname, bool isnull)
5903 {
5905 
5906  if (_state->strval->data[_state->strval->len - 1] != '{')
5907  appendStringInfoCharMacro(_state->strval, ',');
5908 
5909  /*
5910  * Unfortunately we don't have the quoted and escaped string any more, so
5911  * we have to re-escape it.
5912  */
5913  escape_json(_state->strval, fname);
5914  appendStringInfoCharMacro(_state->strval, ':');
5915 
5916  return JSON_SUCCESS;
5917 }
5918 
5919 static JsonParseErrorType
5921 {
5923 
5924  if (_state->strval->data[_state->strval->len - 1] != '[')
5925  appendStringInfoCharMacro(_state->strval, ',');
5926 
5927  return JSON_SUCCESS;
5928 }
5929 
5930 static JsonParseErrorType
5932 {
5934 
5935  if (tokentype == JSON_TOKEN_STRING)
5936  {
5937  text *out = _state->action(_state->action_state, token, strlen(token));
5938 
5939  escape_json(_state->strval, text_to_cstring(out));
5940  }
5941  else
5943 
5944  return JSON_SUCCESS;
5945 }
5946 
5948 json_get_first_token(text *json, bool throw_error)
5949 {
5950  JsonLexContext lex;
5951  JsonParseErrorType result;
5952 
5953  makeJsonLexContext(&lex, json, false);
5954 
5955  /* Lex exactly one token from the input and check its type. */
5956  result = json_lex(&lex);
5957 
5958  if (result == JSON_SUCCESS)
5959  return lex.token_type;
5960 
5961  if (throw_error)
5962  json_errsave_error(result, &lex, NULL);
5963 
5964  return JSON_TOKEN_INVALID; /* invalid json */
5965 }
5966 
5967 /*
5968  * Determine how we want to print values of a given type in datum_to_json(b).
5969  *
5970  * Given the datatype OID, return its JsonTypeCategory, as well as the type's
5971  * output function OID. If the returned category is JSONTYPE_CAST, we return
5972  * the OID of the type->JSON cast function instead.
5973  */
5974 void
5975 json_categorize_type(Oid typoid, bool is_jsonb,
5976  JsonTypeCategory *tcategory, Oid *outfuncoid)
5977 {
5978  bool typisvarlena;
5979 
5980  /* Look through any domain */
5981  typoid = getBaseType(typoid);
5982 
5983  *outfuncoid = InvalidOid;
5984 
5985  switch (typoid)
5986  {
5987  case BOOLOID:
5988  *outfuncoid = F_BOOLOUT;
5989  *tcategory = JSONTYPE_BOOL;
5990  break;
5991 
5992  case INT2OID:
5993  case INT4OID:
5994  case INT8OID:
5995  case FLOAT4OID:
5996  case FLOAT8OID:
5997  case NUMERICOID:
5998  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5999  *tcategory = JSONTYPE_NUMERIC;
6000  break;
6001 
6002  case DATEOID:
6003  *outfuncoid = F_DATE_OUT;
6004  *tcategory = JSONTYPE_DATE;
6005  break;
6006 
6007  case TIMESTAMPOID:
6008  *outfuncoid = F_TIMESTAMP_OUT;
6009  *tcategory = JSONTYPE_TIMESTAMP;
6010  break;
6011 
6012  case TIMESTAMPTZOID:
6013  *outfuncoid = F_TIMESTAMPTZ_OUT;
6014  *tcategory = JSONTYPE_TIMESTAMPTZ;
6015  break;
6016 
6017  case JSONOID:
6018  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6019  *tcategory = JSONTYPE_JSON;
6020  break;
6021 
6022  case JSONBOID:
6023  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6024  *tcategory = is_jsonb ? JSONTYPE_JSONB : JSONTYPE_JSON;
6025  break;
6026 
6027  default:
6028  /* Check for arrays and composites */
6029  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
6030  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
6031  {
6032  *outfuncoid = F_ARRAY_OUT;
6033  *tcategory = JSONTYPE_ARRAY;
6034  }
6035  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
6036  {
6037  *outfuncoid = F_RECORD_OUT;
6038  *tcategory = JSONTYPE_COMPOSITE;
6039  }
6040  else
6041  {
6042  /*
6043  * It's probably the general case. But let's look for a cast
6044  * to json (note: not to jsonb even if is_jsonb is true), if
6045  * it's not built-in.
6046  */
6047  *tcategory = JSONTYPE_OTHER;
6048  if (typoid >= FirstNormalObjectId)
6049  {
6050  Oid castfunc;
6051  CoercionPathType ctype;
6052 
6053  ctype = find_coercion_pathway(JSONOID, typoid,
6055  &castfunc);
6056  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
6057  {
6058  *outfuncoid = castfunc;
6059  *tcategory = JSONTYPE_CAST;
6060  }
6061  else
6062  {
6063  /* non builtin type with no cast */
6064  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6065  }
6066  }
6067  else
6068  {
6069  /* any other builtin type */
6070  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6071  }
6072  }
6073  break;
6074  }
6075 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3755
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5338
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5281
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5440
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3685
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:746
#define unconstify(underlying_type, expr)
Definition: c.h:1245
unsigned int uint32
Definition: c.h:506
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1155
signed int int32
Definition: c.h:494
#define VARHDRSZ
Definition: c.h:692
#define Assert(condition)
Definition: c.h:858
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:398
#define MemSet(start, val, len)
Definition: c.h:1020
#define OidIsValid(objectId)
Definition: c.h:775
bool domain_check_safe(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt, Node *escontext)
Definition: domains.c:355
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define errsave(context,...)
Definition: elog.h:260
#define errcontext
Definition: elog.h:196
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
Definition: execTuples.c:2311
@ SFRM_Materialize_Random
Definition: execnodes.h:318
@ SFRM_Materialize
Definition: execnodes.h:317
struct varlena * pg_detoast_datum_packed(struct varlena *datum)
Definition: fmgr.c:1864
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_HEAPTUPLEHEADER(n)
Definition: fmgr.h:312
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:336
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
#define MAT_SRF_BLESS
Definition: funcapi.h:297
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
int work_mem
Definition: globals.c:129
#define newval
return str start
const char * str
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1345
#define HASH_STRINGS
Definition: hsearch.h:96
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define funcname
Definition: indent_codes.h:69
#define token
Definition: indent_globs.h:126
struct parser_state ps
long val
Definition: informix.c:670
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:2096
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:521
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:1308
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:326
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
Definition: jsonapi.c:587
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:482
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:60
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:54
@ JSON_SUCCESS
Definition: jsonapi.h:38
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:57
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:56
JsonTokenType
Definition: jsonapi.h:20
@ JSON_TOKEN_INVALID
Definition: jsonapi.h:21
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_END
Definition: jsonapi.h:33
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:73
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:482
char * JsonbUnquote(Jsonb *jb)
Definition: jsonb.c:2166
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:473
jbvType
Definition: jsonb.h:226
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvNull
Definition: jsonb.h:228
@ jbvString
Definition: jsonb.h:229
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
#define JsonContainerIsArray(jc)
Definition: jsonb.h:209
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
#define JsonContainerSize(jc)
Definition: jsonb.h:206
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:221
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:222
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:220
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:219
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:817
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:398
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:72
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566
Datum jsonb_populate_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3972
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1399
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2306
static JsonParseErrorType hash_array_start(void *state)
Definition: jsonfuncs.c:3928
Datum jsonb_object_keys(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:566
static JsonParseErrorType populate_recordset_array_start(void *state)
Definition: jsonfuncs.c:4281
static JsonParseErrorType transform_string_values_array_start(void *state)
Definition: jsonfuncs.c:5882
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1195
text * transform_json_string_values(text *json, void *action_state, JsonTransformStringValuesAction transform_action)
Definition: jsonfuncs.c:5829
static JsonParseErrorType elements_object_start(void *state)
Definition: jsonfuncs.c:2416
static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5902
Datum jsonb_array_elements(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2206
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5761
struct PopulateArrayContext PopulateArrayContext
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:5052
Datum json_each_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1960
Datum json_populate_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3986
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2751
Datum jsonb_delete(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4640
Jsonb * transform_jsonb_string_values(Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
Definition: jsonfuncs.c:5782
struct TransformJsonStringValuesState TransformJsonStringValuesState
Datum json_populate_type(Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull, bool omit_quotes, Node *escontext)
Definition: jsonfuncs.c:3343
Datum jsonb_delete_array(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4693
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
Definition: jsonfuncs.c:5180
Datum jsonb_pretty(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4583
struct DomainIOData DomainIOData
static JsonParseErrorType transform_string_values_array_end(void *state)
Definition: jsonfuncs.c:5892
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:538
static JsonParseErrorType populate_recordset_object_start(void *state)
Definition: jsonfuncs.c:4213
static RecordIOData * allocate_record_info(MemoryContext mcxt, int ncolumns)
Definition: jsonfuncs.c:3474
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5733
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1803
Datum jsonb_insert(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:5003
static JsonParseErrorType get_object_start(void *state)
Definition: jsonfuncs.c:1158
static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4305
static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4328
static JsonParseErrorType populate_array_object_start(void *_state)
Definition: jsonfuncs.c:2643
#define JsObjectIsEmpty(jso)
Definition: jsonfuncs.c:327
static void get_record_type_from_argument(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Definition: jsonfuncs.c:3634
Datum json_array_element(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:920
Datum jsonb_delete_idx(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4780
#define JB_PATH_DELETE
Definition: jsonfuncs.c:44
struct GetState GetState
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4398
#define JB_PATH_CREATE_OR_INSERT
Definition: jsonfuncs.c:48
Datum jsonb_populate_record_valid(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2475
Datum json_array_elements_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2300
#define JB_PATH_CREATE
Definition: jsonfuncs.c:43
struct EachState EachState
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3941
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4458
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg, Node *escontext)
Definition: jsonfuncs.c:3697
static HTAB * get_json_object_as_hash(const char *json, int len, const char *funcname, Node *escontext)
Definition: jsonfuncs.c:3809
static bool populate_array_json(PopulateArrayContext *ctx, const char *json, int len)
Definition: jsonfuncs.c:2787
struct StripnullState StripnullState
static void setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
Definition: jsonfuncs.c:5401
struct IterateJsonStringValuesState IterateJsonStringValuesState
#define JsValueIsString(jsv)
Definition: jsonfuncs.c:323
static JsonParseErrorType populate_recordset_object_end(void *state)
Definition: jsonfuncs.c:4243
static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull, Node *escontext, bool omit_scalar_quotes)
Definition: jsonfuncs.c:3404
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4960
struct JsValue JsValue
struct CompositeIOData CompositeIOData
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2118
Datum jsonb_object_field_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:898
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2056
static JsonParseErrorType get_array_start(void *state)
Definition: jsonfuncs.c:1293
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2180
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:675
Datum json_strip_nulls(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4492
static void push_path(JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
Definition: jsonfuncs.c:1719
struct JsonHashEntry JsonHashEntry
Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len, JsonbValue *newval)
Definition: jsonfuncs.c:1677
Datum json_array_elements(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2294
Datum jsonb_concat(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4599
struct ArrayIOData ArrayIOData
static JsonParseErrorType okeys_array_start(void *state)
Definition: jsonfuncs.c:807
Datum json_object_field_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:882
uint32 parse_jsonb_index_flags(Jsonb *jb)
Definition: jsonfuncs.c:5572
Datum jsonb_extract_path_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1492
Datum json_each(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1948
static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1912
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4388
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4408
static bool populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2588
Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
Definition: jsonfuncs.c:1529
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1972
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4418
Datum json_to_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3993
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1443
#define JB_PATH_CONSISTENT_POSITION
Definition: jsonfuncs.c:51
static bool populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
Definition: jsonfuncs.c:2558
JsonTokenType json_get_first_token(text *json, bool throw_error)
Definition: jsonfuncs.c:5948
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4844
#define JsValueIsNull(jsv)
Definition: jsonfuncs.c:318
static void update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
Definition: jsonfuncs.c:3027
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:161
void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
Definition: jsonfuncs.c:5640
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2708
Datum jsonb_set_lax(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4893
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2370
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4428
Datum jsonb_each_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1966
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:517
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2431
struct ScalarIOData ScalarIOData
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2096
Datum jsonb_strip_nulls(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4525
struct OkeysState OkeysState
struct PopulateArrayState PopulateArrayState
struct PopulateRecordCache PopulateRecordCache
Datum jsonb_extract_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1486
static void push_null_elements(JsonbParseState **ps, int num)
Definition: jsonfuncs.c:1700
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5975
static Datum populate_array(ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext)
Definition: jsonfuncs.c:2913
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:784
Datum json_array_length(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1850
struct JHashState JHashState
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
Definition: jsonfuncs.c:639
struct ElementsState ElementsState
Datum jsonb_array_length(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1876
Datum jsonb_object_field(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:860
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2218
void iterate_json_values(text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
Definition: jsonfuncs.c:5708
Datum jsonb_populate_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2462
Datum json_extract_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1007
Datum json_extract_path_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1013
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2348
static void get_record_type_from_query(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Definition: jsonfuncs.c:3660
Datum json_populate_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2493
static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4266
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:50
static JsonParseErrorType transform_string_values_object_end(void *state)
Definition: jsonfuncs.c:5872
static bool JsValueToJsObject(JsValue *jsv, JsObject *jso, Node *escontext)
Definition: jsonfuncs.c:2980
Datum json_object_field(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:844
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:822
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1498
static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2508
static JsonParseErrorType get_object_end(void *state)
Definition: jsonfuncs.c:1177
static Datum populate_composite(CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool *isnull, Node *escontext)
Definition: jsonfuncs.c:3056
Datum jsonb_to_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2486
Datum jsonb_array_element(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:935
Datum json_object_keys(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:730
struct AlenState AlenState
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:46
static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4288
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1242
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1022
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:4039
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj, Node *escontext)
Definition: jsonfuncs.c:3518
static JsonParseErrorType alen_object_start(void *state)
Definition: jsonfuncs.c:1898
static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
Definition: jsonfuncs.c:3490
static bool populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
Definition: jsonfuncs.c:2616
static JsonParseErrorType populate_array_element_start(void *_state, bool isnull)
Definition: jsonfuncs.c:2690
static JsonParseErrorType populate_array_array_end(void *_state)
Definition: jsonfuncs.c:2666
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:3249
static JsonParseErrorType get_array_end(void *state)
Definition: jsonfuncs.c:1333
Datum jsonb_to_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3979
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4469
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:47
Datum jsonb_each(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1954
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1351
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3877
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:45
static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
Definition: jsonfuncs.c:4000
#define JsObjectFree(jso)
Definition: jsonfuncs.c:333
struct PopulateRecordsetState PopulateRecordsetState
static JsonParseErrorType transform_string_values_object_start(void *state)
Definition: jsonfuncs.c:5862
static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:5920
static JsonParseErrorType alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1926
static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
Definition: jsonfuncs.c:3123
static bool populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Definition: jsonfuncs.c:2823
Datum jsonb_array_element_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:978
TypeCat
Definition: jsonfuncs.c:199
@ TYPECAT_COMPOSITE
Definition: jsonfuncs.c:202
@ TYPECAT_SCALAR
Definition: jsonfuncs.c:200
@ TYPECAT_COMPOSITE_DOMAIN
Definition: jsonfuncs.c:203
@ TYPECAT_DOMAIN
Definition: jsonfuncs.c:204
@ TYPECAT_ARRAY
Definition: jsonfuncs.c:201
Datum json_to_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2500
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2166
Datum json_array_element_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:963
static void setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
Definition: jsonfuncs.c:5262
static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
Definition: jsonfuncs.c:3215
static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5931
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3851
Datum jsonb_array_elements_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2212
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1101
struct JsObject JsObject
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
@ jtiKey
Definition: jsonfuncs.h:27
@ jtiAll
Definition: jsonfuncs.h:31
@ jtiNumeric
Definition: jsonfuncs.h:29
@ jtiBool
Definition: jsonfuncs.h:30
@ jtiString
Definition: jsonfuncs.h:28
void(* JsonIterateStringValuesAction)(void *state, char *elem_value, int elem_len)
Definition: jsonfuncs.h:35
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
text *(* JsonTransformStringValuesAction)(void *state, char *elem_value, int elem_len)
Definition: jsonfuncs.h:38
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2759
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2655
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2538
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void * palloc(Size size)
Definition: mcxt.c:1317
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
CoercionPathType
Definition: parse_coerce.h:25
@ COERCION_PATH_FUNC
Definition: parse_coerce.h:27
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define NAMEDATALEN
const void size_t len
const void * data
static char * buf
Definition: pg_test_fsync.c:73
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void check_stack_depth(void)
Definition: postgres.c:3530
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
char * c
@ COERCION_EXPLICIT
Definition: primnodes.h:717
MemoryContextSwitchTo(old_ctx)
tree ctl
Definition: radixtree.h:1853
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
static void error(void)
Definition: sql-dyntest.c:147
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:51
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
int count
Definition: jsonfuncs.c:104
JsonLexContext * lex
Definition: jsonfuncs.c:103
int32 element_typmod
Definition: jsonfuncs.c:169
ColumnIOData * element_info
Definition: jsonfuncs.c:167
Oid element_type
Definition: jsonfuncs.c:168
CompositeIOData composite
Definition: jsonfuncs.c:220
TypeCat typcat
Definition: jsonfuncs.c:214
union ColumnIOData::@26 io
int32 typmod
Definition: jsonfuncs.c:213
ScalarIOData scalar_io
Definition: jsonfuncs.c:215
ArrayIOData array
Definition: jsonfuncs.c:219
DomainIOData domain
Definition: jsonfuncs.c:221
int32 base_typmod
Definition: jsonfuncs.c:183
RecordIOData * record_io
Definition: jsonfuncs.c:179
void * domain_info
Definition: jsonfuncs.c:185
TupleDesc tupdesc
Definition: jsonfuncs.c:180
void * domain_info
Definition: jsonfuncs.c:194
int32 base_typmod
Definition: jsonfuncs.c:193
Oid base_typid
Definition: jsonfuncs.c:192
ColumnIOData * base_io
Definition: jsonfuncs.c:191
bool normalize_results
Definition: jsonfuncs.c:115
TupleDesc ret_tdesc
Definition: jsonfuncs.c:112
char * normalized_scalar
Definition: jsonfuncs.c:117
JsonLexContext * lex
Definition: jsonfuncs.c:110
const char * result_start
Definition: jsonfuncs.c:114
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:111
MemoryContext tmp_cxt
Definition: jsonfuncs.c:113
bool next_scalar
Definition: jsonfuncs.c:116
bool next_scalar
Definition: jsonfuncs.c:130
TupleDesc ret_tdesc
Definition: jsonfuncs.c:126
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:125
bool normalize_results
Definition: jsonfuncs.c:129
MemoryContext tmp_cxt
Definition: jsonfuncs.c:127
JsonLexContext * lex
Definition: jsonfuncs.c:123
const char * function_name
Definition: jsonfuncs.c:124
const char * result_start
Definition: jsonfuncs.c:128
char * normalized_scalar
Definition: jsonfuncs.c:131
bool error_occurred
Definition: miscnodes.h:46
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:262
Definition: fmgr.h:57
void * fn_extra
Definition: fmgr.h:64
MemoryContext fn_mcxt
Definition: fmgr.h:65
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
fmNodePtr resultinfo
Definition: fmgr.h:89
FmgrInfo * flinfo
Definition: fmgr.h:87
bool next_scalar
Definition: jsonfuncs.c:91
int * path_indexes
Definition: jsonfuncs.c:94
char ** path_names
Definition: jsonfuncs.c:93
bool * pathok
Definition: jsonfuncs.c:95
const char * result_start
Definition: jsonfuncs.c:89
int * array_cur_index
Definition: jsonfuncs.c:96
text * tresult
Definition: jsonfuncs.c:88
JsonLexContext * lex
Definition: jsonfuncs.c:87
bool normalize_results
Definition: jsonfuncs.c:90
int npath
Definition: jsonfuncs.c:92
Definition: dynahash.c:220
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:67
JsonLexContext * lex
Definition: jsonfuncs.c:66
char * saved_scalar
Definition: jsonfuncs.c:140
const char * save_json_start
Definition: jsonfuncs.c:141
const char * function_name
Definition: jsonfuncs.c:138
JsonTokenType saved_token_type
Definition: jsonfuncs.c:142
JsonLexContext * lex
Definition: jsonfuncs.c:137
HTAB * hash
Definition: jsonfuncs.c:139
bool is_json
Definition: jsonfuncs.c:309
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:313
HTAB * json_hash
Definition: jsonfuncs.c:312
union JsObject::@29 val
const char * str
Definition: jsonfuncs.c:298
union JsValue::@27 val
JsonbValue * jsonb
Definition: jsonfuncs.c:303
int len
Definition: jsonfuncs.c:299
JsonTokenType type
Definition: jsonfuncs.c:300
struct JsValue::@27::@28 json
bool is_json
Definition: jsonfuncs.c:293
char * val
Definition: jsonfuncs.c:149
char fname[NAMEDATALEN]
Definition: jsonfuncs.c:148
JsonTokenType type
Definition: jsonfuncs.c:150
const char * prev_token_terminator
Definition: jsonapi.h:96
const char * input
Definition: jsonapi.h:91
const char * token_start
Definition: jsonapi.h:94
int lex_level
Definition: jsonapi.h:99
size_t input_length
Definition: jsonapi.h:92
const char * line_start
Definition: jsonapi.h:102
int line_number
Definition: jsonapi.h:101
JsonTokenType token_type
Definition: jsonapi.h:98
const char * token_terminator
Definition: jsonapi.h:95
json_struct_action array_end
Definition: jsonapi.h:138
json_struct_action object_start
Definition: jsonapi.h:135
json_ofield_action object_field_start
Definition: jsonapi.h:139
json_aelem_action array_element_start
Definition: jsonapi.h:141
json_scalar_action scalar
Definition: jsonapi.h:143
void * semstate
Definition: jsonapi.h:134
json_aelem_action array_element_end
Definition: jsonapi.h:142
json_struct_action array_start
Definition: jsonapi.h:137
json_struct_action object_end
Definition: jsonapi.h:136
json_ofield_action object_field_end
Definition: jsonapi.h:140
bool isScalar
Definition: jsonb.h:347
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: nodes.h:129
int result_size
Definition: jsonfuncs.c:58
char ** result
Definition: jsonfuncs.c:57
int result_count
Definition: jsonfuncs.c:59
int sent_count
Definition: jsonfuncs.c:60
JsonLexContext * lex
Definition: jsonfuncs.c:56
ArrayBuildState * astate
Definition: jsonfuncs.c:260
MemoryContext mcxt
Definition: jsonfuncs.c:263
ArrayIOData * aio
Definition: jsonfuncs.c:261
MemoryContext acxt
Definition: jsonfuncs.c:262
const char * colname
Definition: jsonfuncs.c:264
JsonTokenType element_type
Definition: jsonfuncs.c:279
JsonLexContext * lex
Definition: jsonfuncs.c:274
PopulateArrayContext * ctx
Definition: jsonfuncs.c:275
const char * element_start
Definition: jsonfuncs.c:276
char * element_scalar
Definition: jsonfuncs.c:277
ColumnIOData c
Definition: jsonfuncs.c:239
MemoryContext fn_mcxt
Definition: jsonfuncs.c:240
JsonLexContext * lex
Definition: jsonfuncs.c:246
HeapTupleHeader rec
Definition: jsonfuncs.c:253
const char * save_json_start
Definition: jsonfuncs.c:250
const char * function_name
Definition: jsonfuncs.c:247
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:252
PopulateRecordCache * cache
Definition: jsonfuncs.c:254
JsonTokenType saved_token_type
Definition: jsonfuncs.c:251
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:826
Oid record_type
Definition: hstore_io.c:821
int32 record_typmod
Definition: hstore_io.c:822
SetFunctionReturnMode returnMode
Definition: execnodes.h:336
ExprContext * econtext
Definition: execnodes.h:332
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
int allowedModes
Definition: execnodes.h:334
Oid typioparam
Definition: jsonfuncs.c:156
FmgrInfo typiofunc
Definition: jsonfuncs.c:157
bool skip_next_null
Definition: jsonfuncs.c:287
JsonLexContext * lex
Definition: jsonfuncs.c:285
StringInfo strval
Definition: jsonfuncs.c:286
JsonTransformStringValuesAction action
Definition: jsonfuncs.c:79
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
Definition: type.h:95
Definition: regguts.h:323
Definition: c.h:687
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
static JsonSemAction sem
#define FirstNormalObjectId
Definition: transam.h:197
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:328
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:782
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:762
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
char * text_to_cstring(const text *t)
Definition: varlena.c:217
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type