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