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;
738  JsonSemAction *sem;
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;
755  sem->scalar = okeys_scalar;
757  /* remainder are all NULL, courtesy of palloc0 above */
758 
759  pg_parse_json_or_ereport(&lex, sem);
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  {
1134  sem->object_end = get_object_end;
1136  sem->array_end = get_array_end;
1137  }
1138  if (tpath != NULL)
1139  {
1142  }
1143  if (ipath != NULL)
1144  {
1148  }
1149 
1150  pg_parse_json_or_ereport(state->lex, sem);
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 
1187  _state->tresult = cstring_to_text_with_len(start, len);
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 
1281  _state->tresult = cstring_to_text_with_len(start, len);
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 
1343  _state->tresult = cstring_to_text_with_len(start, len);
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 
1432  _state->tresult = cstring_to_text_with_len(start, len);
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 
1469  _state->tresult = cstring_to_text_with_len(start, len);
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 
1869  pg_parse_json_or_ereport(state->lex, sem);
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 
2085  pg_parse_json_or_ereport(&lex, sem);
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;
2326  sem->scalar = elements_scalar;
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 
2338  pg_parse_json_or_ereport(&lex, sem);
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 {
2788  JsonSemAction sem;
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  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
2834  {
2835  populate_array_report_expected_array(ctx, ndim - 1);
2836  /* Getting here means the error was reported softly. */
2838  return false;
2839  }
2840 
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 /* recursively populate a record field or an array element from a json/jsonb value */
3327 static Datum
3329  Oid typid,
3330  int32 typmod,
3331  const char *colname,
3332  MemoryContext mcxt,
3333  Datum defaultval,
3334  JsValue *jsv,
3335  bool *isnull,
3336  Node *escontext)
3337 {
3338  TypeCat typcat;
3339 
3341 
3342  /*
3343  * Prepare column metadata cache for the given type. Force lookup of the
3344  * scalar_io data so that the json string hack below will work.
3345  */
3346  if (col->typid != typid || col->typmod != typmod)
3347  prepare_column_cache(col, typid, typmod, mcxt, true);
3348 
3349  *isnull = JsValueIsNull(jsv);
3350 
3351  typcat = col->typcat;
3352 
3353  /* try to convert json string to a non-scalar type through input function */
3354  if (JsValueIsString(jsv) &&
3355  (typcat == TYPECAT_ARRAY ||
3356  typcat == TYPECAT_COMPOSITE ||
3357  typcat == TYPECAT_COMPOSITE_DOMAIN))
3358  typcat = TYPECAT_SCALAR;
3359 
3360  /* we must perform domain checks for NULLs, otherwise exit immediately */
3361  if (*isnull &&
3362  typcat != TYPECAT_DOMAIN &&
3363  typcat != TYPECAT_COMPOSITE_DOMAIN)
3364  return (Datum) 0;
3365 
3366  switch (typcat)
3367  {
3368  case TYPECAT_SCALAR:
3369  return populate_scalar(&col->scalar_io, typid, typmod, jsv,
3370  isnull, escontext);
3371 
3372  case TYPECAT_ARRAY:
3373  return populate_array(&col->io.array, colname, mcxt, jsv,
3374  isnull, escontext);
3375 
3376  case TYPECAT_COMPOSITE:
3378  return populate_composite(&col->io.composite, typid,
3379  colname, mcxt,
3380  DatumGetPointer(defaultval)
3381  ? DatumGetHeapTupleHeader(defaultval)
3382  : NULL,
3383  jsv, isnull,
3384  escontext);
3385 
3386  case TYPECAT_DOMAIN:
3387  return populate_domain(&col->io.domain, typid, colname, mcxt,
3388  jsv, isnull, escontext);
3389 
3390  default:
3391  elog(ERROR, "unrecognized type category '%c'", typcat);
3392  return (Datum) 0;
3393  }
3394 }
3395 
3396 static RecordIOData *
3398 {
3400  MemoryContextAlloc(mcxt,
3401  offsetof(RecordIOData, columns) +
3402  ncolumns * sizeof(ColumnIOData));
3403 
3404  data->record_type = InvalidOid;
3405  data->record_typmod = 0;
3406  data->ncolumns = ncolumns;
3407  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3408 
3409  return data;
3410 }
3411 
3412 static bool
3413 JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
3414 {
3415  jsv->is_json = obj->is_json;
3416 
3417  if (jsv->is_json)
3418  {
3419  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3420  HASH_FIND, NULL);
3421 
3422  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3423  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3424  hashentry->val;
3425  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3426 
3427  return hashentry != NULL;
3428  }
3429  else
3430  {
3431  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3432  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3433  NULL);
3434 
3435  return jsv->val.jsonb != NULL;
3436  }
3437 }
3438 
3439 /* populate a record tuple from json/jsonb value */
3440 static HeapTupleHeader
3442  RecordIOData **record_p,
3443  HeapTupleHeader defaultval,
3444  MemoryContext mcxt,
3445  JsObject *obj,
3446  Node *escontext)
3447 {
3448  RecordIOData *record = *record_p;
3449  Datum *values;
3450  bool *nulls;
3451  HeapTuple res;
3452  int ncolumns = tupdesc->natts;
3453  int i;
3454 
3455  /*
3456  * if the input json is empty, we can only skip the rest if we were passed
3457  * in a non-null record, since otherwise there may be issues with domain
3458  * nulls.
3459  */
3460  if (defaultval && JsObjectIsEmpty(obj))
3461  return defaultval;
3462 
3463  /* (re)allocate metadata cache */
3464  if (record == NULL ||
3465  record->ncolumns != ncolumns)
3466  *record_p = record = allocate_record_info(mcxt, ncolumns);
3467 
3468  /* invalidate metadata cache if the record type has changed */
3469  if (record->record_type != tupdesc->tdtypeid ||
3470  record->record_typmod != tupdesc->tdtypmod)
3471  {
3472  MemSet(record, 0, offsetof(RecordIOData, columns) +
3473  ncolumns * sizeof(ColumnIOData));
3474  record->record_type = tupdesc->tdtypeid;
3475  record->record_typmod = tupdesc->tdtypmod;
3476  record->ncolumns = ncolumns;
3477  }
3478 
3479  values = (Datum *) palloc(ncolumns * sizeof(Datum));
3480  nulls = (bool *) palloc(ncolumns * sizeof(bool));
3481 
3482  if (defaultval)
3483  {
3484  HeapTupleData tuple;
3485 
3486  /* Build a temporary HeapTuple control structure */
3487  tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
3488  ItemPointerSetInvalid(&(tuple.t_self));
3489  tuple.t_tableOid = InvalidOid;
3490  tuple.t_data = defaultval;
3491 
3492  /* Break down the tuple into fields */
3493  heap_deform_tuple(&tuple, tupdesc, values, nulls);
3494  }
3495  else
3496  {
3497  for (i = 0; i < ncolumns; ++i)
3498  {
3499  values[i] = (Datum) 0;
3500  nulls[i] = true;
3501  }
3502  }
3503 
3504  for (i = 0; i < ncolumns; ++i)
3505  {
3506  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
3507  char *colname = NameStr(att->attname);
3508  JsValue field = {0};
3509  bool found;
3510 
3511  /* Ignore dropped columns in datatype */
3512  if (att->attisdropped)
3513  {
3514  nulls[i] = true;
3515  continue;
3516  }
3517 
3518  found = JsObjectGetField(obj, colname, &field);
3519 
3520  /*
3521  * we can't just skip here if the key wasn't found since we might have
3522  * a domain to deal with. If we were passed in a non-null record
3523  * datum, we assume that the existing values are valid (if they're
3524  * not, then it's not our fault), but if we were passed in a null,
3525  * then every field which we don't populate needs to be run through
3526  * the input function just in case it's a domain type.
3527  */
3528  if (defaultval && !found)
3529  continue;
3530 
3531  values[i] = populate_record_field(&record->columns[i],
3532  att->atttypid,
3533  att->atttypmod,
3534  colname,
3535  mcxt,
3536  nulls[i] ? (Datum) 0 : values[i],
3537  &field,
3538  &nulls[i],
3539  escontext);
3540  }
3541 
3542  res = heap_form_tuple(tupdesc, values, nulls);
3543 
3544  pfree(values);
3545  pfree(nulls);
3546 
3547  return res->t_data;
3548 }
3549 
3550 /*
3551  * Setup for json{b}_populate_record{set}: result type will be same as first
3552  * argument's type --- unless first argument is "null::record", which we can't
3553  * extract type info from; we handle that later.
3554  */
3555 static void
3557  const char *funcname,
3558  PopulateRecordCache *cache)
3559 {
3560  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3561  prepare_column_cache(&cache->c,
3562  cache->argtype, -1,
3563  cache->fn_mcxt, false);
3564  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3565  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3566  ereport(ERROR,
3567  (errcode(ERRCODE_DATATYPE_MISMATCH),
3568  /* translator: %s is a function name, eg json_to_record */
3569  errmsg("first argument of %s must be a row type",
3570  funcname)));
3571 }
3572 
3573 /*
3574  * Setup for json{b}_to_record{set}: result type is specified by calling
3575  * query. We'll also use this code for json{b}_populate_record{set},
3576  * if we discover that the first argument is a null of type RECORD.
3577  *
3578  * Here it is syntactically impossible to specify the target type
3579  * as domain-over-composite.
3580  */
3581 static void
3583  const char *funcname,
3584  PopulateRecordCache *cache)
3585 {
3586  TupleDesc tupdesc;
3587  MemoryContext old_cxt;
3588 
3589  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3590  ereport(ERROR,
3591  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3592  /* translator: %s is a function name, eg json_to_record */
3593  errmsg("could not determine row type for result of %s",
3594  funcname),
3595  errhint("Provide a non-null record argument, "
3596  "or call the function in the FROM clause "
3597  "using a column definition list.")));
3598 
3599  Assert(tupdesc);
3600  cache->argtype = tupdesc->tdtypeid;
3601 
3602  /* If we go through this more than once, avoid memory leak */
3603  if (cache->c.io.composite.tupdesc)
3605 
3606  /* Save identified tupdesc */
3607  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3608  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3609  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3610  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3611  MemoryContextSwitchTo(old_cxt);
3612 }
3613 
3614 /*
3615  * common worker for json{b}_populate_record() and json{b}_to_record()
3616  * is_json and have_record_arg identify the specific function
3617  */
3618 static Datum
3620  bool is_json, bool have_record_arg,
3621  Node *escontext)
3622 {
3623  int json_arg_num = have_record_arg ? 1 : 0;
3624  JsValue jsv = {0};
3625  HeapTupleHeader rec;
3626  Datum rettuple;
3627  bool isnull;
3628  JsonbValue jbv;
3629  MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
3630  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3631 
3632  /*
3633  * If first time through, identify input/result record type. Note that
3634  * this stanza looks only at fcinfo context, which can't change during the
3635  * query; so we may not be able to fully resolve a RECORD input type yet.
3636  */
3637  if (!cache)
3638  {
3639  fcinfo->flinfo->fn_extra = cache =
3640  MemoryContextAllocZero(fnmcxt, sizeof(*cache));
3641  cache->fn_mcxt = fnmcxt;
3642 
3643  if (have_record_arg)
3644  get_record_type_from_argument(fcinfo, funcname, cache);
3645  else
3646  get_record_type_from_query(fcinfo, funcname, cache);
3647  }
3648 
3649  /* Collect record arg if we have one */
3650  if (!have_record_arg)
3651  rec = NULL; /* it's json{b}_to_record() */
3652  else if (!PG_ARGISNULL(0))
3653  {
3654  rec = PG_GETARG_HEAPTUPLEHEADER(0);
3655 
3656  /*
3657  * When declared arg type is RECORD, identify actual record type from
3658  * the tuple itself.
3659  */
3660  if (cache->argtype == RECORDOID)
3661  {
3664  }
3665  }
3666  else
3667  {
3668  rec = NULL;
3669 
3670  /*
3671  * When declared arg type is RECORD, identify actual record type from
3672  * calling query, or fail if we can't.
3673  */
3674  if (cache->argtype == RECORDOID)
3675  {
3676  get_record_type_from_query(fcinfo, funcname, cache);
3677  /* This can't change argtype, which is important for next time */
3678  Assert(cache->argtype == RECORDOID);
3679  }
3680  }
3681 
3682  /* If no JSON argument, just return the record (if any) unchanged */
3683  if (PG_ARGISNULL(json_arg_num))
3684  {
3685  if (rec)
3686  PG_RETURN_POINTER(rec);
3687  else
3688  PG_RETURN_NULL();
3689  }
3690 
3691  jsv.is_json = is_json;
3692 
3693  if (is_json)
3694  {
3695  text *json = PG_GETARG_TEXT_PP(json_arg_num);
3696 
3697  jsv.val.json.str = VARDATA_ANY(json);
3698  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3699  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3700  * populate_composite() */
3701  }
3702  else
3703  {
3704  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3705 
3706  jsv.val.jsonb = &jbv;
3707 
3708  /* fill binary jsonb value pointing to jb */
3709  jbv.type = jbvBinary;
3710  jbv.val.binary.data = &jb->root;
3711  jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
3712  }
3713 
3714  isnull = false;
3715  rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
3716  NULL, fnmcxt, rec, &jsv, &isnull,
3717  escontext);
3718  Assert(!isnull || SOFT_ERROR_OCCURRED(escontext));
3719 
3720  PG_RETURN_DATUM(rettuple);
3721 }
3722 
3723 /*
3724  * get_json_object_as_hash
3725  *
3726  * Decomposes a json object into a hash table.
3727  *
3728  * Returns the hash table if the json is parsed successfully, NULL otherwise.
3729  */
3730 static HTAB *
3731 get_json_object_as_hash(char *json, int len, const char *funcname,
3732  Node *escontext)
3733 {
3734  HASHCTL ctl;
3735  HTAB *tab;
3736  JHashState *state;
3737  JsonSemAction *sem;
3738 
3739  ctl.keysize = NAMEDATALEN;
3740  ctl.entrysize = sizeof(JsonHashEntry);
3741  ctl.hcxt = CurrentMemoryContext;
3742  tab = hash_create("json object hashtable",
3743  100,
3744  &ctl,
3746 
3747  state = palloc0(sizeof(JHashState));
3748  sem = palloc0(sizeof(JsonSemAction));
3749 
3750  state->function_name = funcname;
3751  state->hash = tab;
3752  state->lex = makeJsonLexContextCstringLen(NULL, json, len,
3753  GetDatabaseEncoding(), true);
3754 
3755  sem->semstate = (void *) state;
3757  sem->scalar = hash_scalar;
3760 
3761  if (!pg_parse_json_or_errsave(state->lex, sem, escontext))
3762  {
3763  hash_destroy(state->hash);
3764  tab = NULL;
3765  }
3766 
3767  freeJsonLexContext(state->lex);
3768 
3769  return tab;
3770 }
3771 
3772 static JsonParseErrorType
3773 hash_object_field_start(void *state, char *fname, bool isnull)
3774 {
3775  JHashState *_state = (JHashState *) state;
3776 
3777  if (_state->lex->lex_level > 1)
3778  return JSON_SUCCESS;
3779 
3780  /* remember token type */
3781  _state->saved_token_type = _state->lex->token_type;
3782 
3783  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3785  {
3786  /* remember start position of the whole text of the subobject */
3787  _state->save_json_start = _state->lex->token_start;
3788  }
3789  else
3790  {
3791  /* must be a scalar */
3792  _state->save_json_start = NULL;
3793  }
3794 
3795  return JSON_SUCCESS;
3796 }
3797 
3798 static JsonParseErrorType
3799 hash_object_field_end(void *state, char *fname, bool isnull)
3800 {
3801  JHashState *_state = (JHashState *) state;
3802  JsonHashEntry *hashentry;
3803  bool found;
3804 
3805  /*
3806  * Ignore nested fields.
3807  */
3808  if (_state->lex->lex_level > 1)
3809  return JSON_SUCCESS;
3810 
3811  /*
3812  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3813  * (Note: without this test, the hash code would truncate the string at
3814  * NAMEDATALEN-1, and could then match against a similarly-truncated
3815  * record field name. That would be a reasonable behavior, but this code
3816  * has previously insisted on exact equality, so we keep this behavior.)
3817  */
3818  if (strlen(fname) >= NAMEDATALEN)
3819  return JSON_SUCCESS;
3820 
3821  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3822 
3823  /*
3824  * found being true indicates a duplicate. We don't do anything about
3825  * that, a later field with the same name overrides the earlier field.
3826  */
3827 
3828  hashentry->type = _state->saved_token_type;
3829  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3830 
3831  if (_state->save_json_start != NULL)
3832  {
3833  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3834  char *val = palloc((len + 1) * sizeof(char));
3835 
3836  memcpy(val, _state->save_json_start, len);
3837  val[len] = '\0';
3838  hashentry->val = val;
3839  }
3840  else
3841  {
3842  /* must have had a scalar instead */
3843  hashentry->val = _state->saved_scalar;
3844  }
3845 
3846  return JSON_SUCCESS;
3847 }
3848 
3849 static JsonParseErrorType
3851 {
3852  JHashState *_state = (JHashState *) state;
3853 
3854  if (_state->lex->lex_level == 0)
3855  ereport(ERROR,
3856  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3857  errmsg("cannot call %s on an array", _state->function_name)));
3858 
3859  return JSON_SUCCESS;
3860 }
3861 
3862 static JsonParseErrorType
3863 hash_scalar(void *state, char *token, JsonTokenType tokentype)
3864 {
3865  JHashState *_state = (JHashState *) state;
3866 
3867  if (_state->lex->lex_level == 0)
3868  ereport(ERROR,
3869  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3870  errmsg("cannot call %s on a scalar", _state->function_name)));
3871 
3872  if (_state->lex->lex_level == 1)
3873  {
3874  _state->saved_scalar = token;
3875  /* saved_token_type must already be set in hash_object_field_start() */
3876  Assert(_state->saved_token_type == tokentype);
3877  }
3878 
3879  return JSON_SUCCESS;
3880 }
3881 
3882 
3883 /*
3884  * SQL function json_populate_recordset
3885  *
3886  * set fields in a set of records from the argument json,
3887  * which must be an array of objects.
3888  *
3889  * similar to json_populate_record, but the tuple-building code
3890  * is pushed down into the semantic action handlers so it's done
3891  * per object in the array.
3892  */
3893 Datum
3895 {
3896  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3897  false, true);
3898 }
3899 
3900 Datum
3902 {
3903  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3904  false, false);
3905 }
3906 
3907 Datum
3909 {
3910  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3911  true, true);
3912 }
3913 
3914 Datum
3916 {
3917  return populate_recordset_worker(fcinfo, "json_to_recordset",
3918  true, false);
3919 }
3920 
3921 static void
3923 {
3924  PopulateRecordCache *cache = state->cache;
3925  HeapTupleHeader tuphead;
3926  HeapTupleData tuple;
3927 
3928  /* acquire/update cached tuple descriptor */
3929  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
3930 
3931  /* replace record fields from json */
3932  tuphead = populate_record(cache->c.io.composite.tupdesc,
3933  &cache->c.io.composite.record_io,
3934  state->rec,
3935  cache->fn_mcxt,
3936  obj,
3937  NULL);
3938 
3939  /* if it's domain over composite, check domain constraints */
3940  if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
3941  (void) domain_check_safe(HeapTupleHeaderGetDatum(tuphead), false,
3942  cache->argtype,
3943  &cache->c.io.composite.domain_info,
3944  cache->fn_mcxt,
3945  NULL);
3946 
3947  /* ok, save into tuplestore */
3948  tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
3949  ItemPointerSetInvalid(&(tuple.t_self));
3950  tuple.t_tableOid = InvalidOid;
3951  tuple.t_data = tuphead;
3952 
3953  tuplestore_puttuple(state->tuple_store, &tuple);
3954 }
3955 
3956 /*
3957  * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
3958  * is_json and have_record_arg identify the specific function
3959  */
3960 static Datum
3962  bool is_json, bool have_record_arg)
3963 {
3964  int json_arg_num = have_record_arg ? 1 : 0;
3965  ReturnSetInfo *rsi;
3966  MemoryContext old_cxt;
3967  HeapTupleHeader rec;
3968  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3970 
3971  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
3972 
3973  if (!rsi || !IsA(rsi, ReturnSetInfo))
3974  ereport(ERROR,
3975  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3976  errmsg("set-valued function called in context that cannot accept a set")));
3977 
3978  if (!(rsi->allowedModes & SFRM_Materialize))
3979  ereport(ERROR,
3980  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3981  errmsg("materialize mode required, but it is not allowed in this context")));
3982 
3984 
3985  /*
3986  * If first time through, identify input/result record type. Note that
3987  * this stanza looks only at fcinfo context, which can't change during the
3988  * query; so we may not be able to fully resolve a RECORD input type yet.
3989  */
3990  if (!cache)
3991  {
3992  fcinfo->flinfo->fn_extra = cache =
3993  MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
3994  cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
3995 
3996  if (have_record_arg)
3997  get_record_type_from_argument(fcinfo, funcname, cache);
3998  else
3999  get_record_type_from_query(fcinfo, funcname, cache);
4000  }
4001 
4002  /* Collect record arg if we have one */
4003  if (!have_record_arg)
4004  rec = NULL; /* it's json{b}_to_recordset() */
4005  else if (!PG_ARGISNULL(0))
4006  {
4007  rec = PG_GETARG_HEAPTUPLEHEADER(0);
4008 
4009  /*
4010  * When declared arg type is RECORD, identify actual record type from
4011  * the tuple itself.
4012  */
4013  if (cache->argtype == RECORDOID)
4014  {
4017  }
4018  }
4019  else
4020  {
4021  rec = NULL;
4022 
4023  /*
4024  * When declared arg type is RECORD, identify actual record type from
4025  * calling query, or fail if we can't.
4026  */
4027  if (cache->argtype == RECORDOID)
4028  {
4029  get_record_type_from_query(fcinfo, funcname, cache);
4030  /* This can't change argtype, which is important for next time */
4031  Assert(cache->argtype == RECORDOID);
4032  }
4033  }
4034 
4035  /* if the json is null send back an empty set */
4036  if (PG_ARGISNULL(json_arg_num))
4037  PG_RETURN_NULL();
4038 
4039  /*
4040  * Forcibly update the cached tupdesc, to ensure we have the right tupdesc
4041  * to return even if the JSON contains no rows.
4042  */
4043  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
4044 
4046 
4047  /* make tuplestore in a sufficiently long-lived memory context */
4049  state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
4051  false, work_mem);
4052  MemoryContextSwitchTo(old_cxt);
4053 
4054  state->function_name = funcname;
4055  state->cache = cache;
4056  state->rec = rec;
4057 
4058  if (is_json)
4059  {
4060  text *json = PG_GETARG_TEXT_PP(json_arg_num);
4061  JsonLexContext lex;
4062  JsonSemAction *sem;
4063 
4064  sem = palloc0(sizeof(JsonSemAction));
4065 
4066  makeJsonLexContext(&lex, json, true);
4067 
4068  sem->semstate = (void *) state;
4076 
4077  state->lex = &lex;
4078 
4079  pg_parse_json_or_ereport(&lex, sem);
4080 
4081  freeJsonLexContext(&lex);
4082  state->lex = NULL;
4083  }
4084  else
4085  {
4086  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
4087  JsonbIterator *it;
4088  JsonbValue v;
4089  bool skipNested = false;
4091 
4092  if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
4093  ereport(ERROR,
4094  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4095  errmsg("cannot call %s on a non-array",
4096  funcname)));
4097 
4098  it = JsonbIteratorInit(&jb->root);
4099 
4100  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4101  {
4102  skipNested = true;
4103 
4104  if (r == WJB_ELEM)
4105  {
4106  JsObject obj;
4107 
4108  if (v.type != jbvBinary ||
4109  !JsonContainerIsObject(v.val.binary.data))
4110  ereport(ERROR,
4111  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4112  errmsg("argument of %s must be an array of objects",
4113  funcname)));
4114 
4115  obj.is_json = false;
4116  obj.val.jsonb_cont = v.val.binary.data;
4117 
4119  }
4120  }
4121  }
4122 
4123  /*
4124  * Note: we must copy the cached tupdesc because the executor will free
4125  * the passed-back setDesc, but we want to hang onto the cache in case
4126  * we're called again in the same query.
4127  */
4128  rsi->setResult = state->tuple_store;
4130 
4131  PG_RETURN_NULL();
4132 }
4133 
4134 static JsonParseErrorType
4136 {
4138  int lex_level = _state->lex->lex_level;
4139  HASHCTL ctl;
4140 
4141  /* Reject object at top level: we must have an array at level 0 */
4142  if (lex_level == 0)
4143  ereport(ERROR,
4144  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4145  errmsg("cannot call %s on an object",
4146  _state->function_name)));
4147 
4148  /* Nested objects require no special processing */
4149  if (lex_level > 1)
4150  return JSON_SUCCESS;
4151 
4152  /* Object at level 1: set up a new hash table for this object */
4153  ctl.keysize = NAMEDATALEN;
4154  ctl.entrysize = sizeof(JsonHashEntry);
4155  ctl.hcxt = CurrentMemoryContext;
4156  _state->json_hash = hash_create("json object hashtable",
4157  100,
4158  &ctl,
4160 
4161  return JSON_SUCCESS;
4162 }
4163 
4164 static JsonParseErrorType
4166 {
4168  JsObject obj;
4169 
4170  /* Nested objects require no special processing */
4171  if (_state->lex->lex_level > 1)
4172  return JSON_SUCCESS;
4173 
4174  obj.is_json = true;
4175  obj.val.json_hash = _state->json_hash;
4176 
4177  /* Otherwise, construct and return a tuple based on this level-1 object */
4178  populate_recordset_record(_state, &obj);
4179 
4180  /* Done with hash for this object */
4181  hash_destroy(_state->json_hash);
4182  _state->json_hash = NULL;
4183 
4184  return JSON_SUCCESS;
4185 }
4186 
4187 static JsonParseErrorType
4189 {
4191 
4192  if (_state->lex->lex_level == 1 &&
4194  ereport(ERROR,
4195  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4196  errmsg("argument of %s must be an array of objects",
4197  _state->function_name)));
4198 
4199  return JSON_SUCCESS;
4200 }
4201 
4202 static JsonParseErrorType
4204 {
4205  /* nothing to do */
4206  return JSON_SUCCESS;
4207 }
4208 
4209 static JsonParseErrorType
4211 {
4213 
4214  if (_state->lex->lex_level == 0)
4215  ereport(ERROR,
4216  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4217  errmsg("cannot call %s on a scalar",
4218  _state->function_name)));
4219 
4220  if (_state->lex->lex_level == 2)
4221  _state->saved_scalar = token;
4222 
4223  return JSON_SUCCESS;
4224 }
4225 
4226 static JsonParseErrorType
4227 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
4228 {
4230 
4231  if (_state->lex->lex_level > 2)
4232  return JSON_SUCCESS;
4233 
4234  _state->saved_token_type = _state->lex->token_type;
4235 
4236  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
4238  {
4239  _state->save_json_start = _state->lex->token_start;
4240  }
4241  else
4242  {
4243  _state->save_json_start = NULL;
4244  }
4245 
4246  return JSON_SUCCESS;
4247 }
4248 
4249 static JsonParseErrorType
4250 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
4251 {
4253  JsonHashEntry *hashentry;
4254  bool found;
4255 
4256  /*
4257  * Ignore nested fields.
4258  */
4259  if (_state->lex->lex_level > 2)
4260  return JSON_SUCCESS;
4261 
4262  /*
4263  * Ignore field names >= NAMEDATALEN - they can't match a record field.
4264  * (Note: without this test, the hash code would truncate the string at
4265  * NAMEDATALEN-1, and could then match against a similarly-truncated
4266  * record field name. That would be a reasonable behavior, but this code
4267  * has previously insisted on exact equality, so we keep this behavior.)
4268  */
4269  if (strlen(fname) >= NAMEDATALEN)
4270  return JSON_SUCCESS;
4271 
4272  hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
4273 
4274  /*
4275  * found being true indicates a duplicate. We don't do anything about
4276  * that, a later field with the same name overrides the earlier field.
4277  */
4278 
4279  hashentry->type = _state->saved_token_type;
4280  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
4281 
4282  if (_state->save_json_start != NULL)
4283  {
4284  int len = _state->lex->prev_token_terminator - _state->save_json_start;
4285  char *val = palloc((len + 1) * sizeof(char));
4286 
4287  memcpy(val, _state->save_json_start, len);
4288  val[len] = '\0';
4289  hashentry->val = val;
4290  }
4291  else
4292  {
4293  /* must have had a scalar instead */
4294  hashentry->val = _state->saved_scalar;
4295  }
4296 
4297  return JSON_SUCCESS;
4298 }
4299 
4300 /*
4301  * Semantic actions for json_strip_nulls.
4302  *
4303  * Simply repeat the input on the output unless we encounter
4304  * a null object field. State for this is set when the field
4305  * is started and reset when the scalar action (which must be next)
4306  * is called.
4307  */
4308 
4309 static JsonParseErrorType
4311 {
4312  StripnullState *_state = (StripnullState *) state;
4313 
4314  appendStringInfoCharMacro(_state->strval, '{');
4315 
4316  return JSON_SUCCESS;
4317 }
4318 
4319 static JsonParseErrorType
4321 {
4322  StripnullState *_state = (StripnullState *) state;
4323 
4324  appendStringInfoCharMacro(_state->strval, '}');
4325 
4326  return JSON_SUCCESS;
4327 }
4328 
4329 static JsonParseErrorType
4331 {
4332  StripnullState *_state = (StripnullState *) state;
4333 
4334  appendStringInfoCharMacro(_state->strval, '[');
4335 
4336  return JSON_SUCCESS;
4337 }
4338 
4339 static JsonParseErrorType
4341 {
4342  StripnullState *_state = (StripnullState *) state;
4343 
4344  appendStringInfoCharMacro(_state->strval, ']');
4345 
4346  return JSON_SUCCESS;
4347 }
4348 
4349 static JsonParseErrorType
4350 sn_object_field_start(void *state, char *fname, bool isnull)
4351 {
4352  StripnullState *_state = (StripnullState *) state;
4353 
4354  if (isnull)
4355  {
4356  /*
4357  * The next thing must be a scalar or isnull couldn't be true, so
4358  * there is no danger of this state being carried down into a nested
4359  * object or array. The flag will be reset in the scalar action.
4360  */
4361  _state->skip_next_null = true;
4362  return JSON_SUCCESS;
4363  }
4364 
4365  if (_state->strval->data[_state->strval->len - 1] != '{')
4366  appendStringInfoCharMacro(_state->strval, ',');
4367 
4368  /*
4369  * Unfortunately we don't have the quoted and escaped string any more, so
4370  * we have to re-escape it.
4371  */
4372  escape_json(_state->strval, fname);
4373 
4374  appendStringInfoCharMacro(_state->strval, ':');
4375 
4376  return JSON_SUCCESS;
4377 }
4378 
4379 static JsonParseErrorType
4380 sn_array_element_start(void *state, bool isnull)
4381 {
4382  StripnullState *_state = (StripnullState *) state;
4383 
4384  if (_state->strval->data[_state->strval->len - 1] != '[')
4385  appendStringInfoCharMacro(_state->strval, ',');
4386 
4387  return JSON_SUCCESS;
4388 }
4389 
4390 static JsonParseErrorType
4391 sn_scalar(void *state, char *token, JsonTokenType tokentype)
4392 {
4393  StripnullState *_state = (StripnullState *) state;
4394 
4395  if (_state->skip_next_null)
4396  {
4397  Assert(tokentype == JSON_TOKEN_NULL);
4398  _state->skip_next_null = false;
4399  return JSON_SUCCESS;
4400  }
4401 
4402  if (tokentype == JSON_TOKEN_STRING)
4403  escape_json(_state->strval, token);
4404  else
4406 
4407  return JSON_SUCCESS;
4408 }
4409 
4410 /*
4411  * SQL function json_strip_nulls(json) -> json
4412  */
4413 Datum
4415 {
4416  text *json = PG_GETARG_TEXT_PP(0);
4418  JsonLexContext lex;
4419  JsonSemAction *sem;
4420 
4421  state = palloc0(sizeof(StripnullState));
4422  sem = palloc0(sizeof(JsonSemAction));
4423 
4424  state->lex = makeJsonLexContext(&lex, json, true);
4425  state->strval = makeStringInfo();
4426  state->skip_next_null = false;
4427 
4428  sem->semstate = (void *) state;
4430  sem->object_end = sn_object_end;
4431  sem->array_start = sn_array_start;
4432  sem->array_end = sn_array_end;
4433  sem->scalar = sn_scalar;
4436 
4437  pg_parse_json_or_ereport(&lex, sem);
4438 
4440  state->strval->len));
4441 }
4442 
4443 /*
4444  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
4445  */
4446 Datum
4448 {
4449  Jsonb *jb = PG_GETARG_JSONB_P(0);
4450  JsonbIterator *it;
4451  JsonbParseState *parseState = NULL;
4452  JsonbValue *res = NULL;
4453  JsonbValue v,
4454  k;
4456  bool last_was_key = false;
4457 
4458  if (JB_ROOT_IS_SCALAR(jb))
4459  PG_RETURN_POINTER(jb);
4460 
4461  it = JsonbIteratorInit(&jb->root);
4462 
4463  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4464  {
4465  Assert(!(type == WJB_KEY && last_was_key));
4466 
4467  if (type == WJB_KEY)
4468  {
4469  /* stash the key until we know if it has a null value */
4470  k = v;
4471  last_was_key = true;
4472  continue;
4473  }
4474 
4475  if (last_was_key)
4476  {
4477  /* if the last element was a key this one can't be */
4478  last_was_key = false;
4479 
4480  /* skip this field if value is null */
4481  if (type == WJB_VALUE && v.type == jbvNull)
4482  continue;
4483 
4484  /* otherwise, do a delayed push of the key */
4485  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4486  }
4487 
4488  if (type == WJB_VALUE || type == WJB_ELEM)
4489  res = pushJsonbValue(&parseState, type, &v);
4490  else
4491  res = pushJsonbValue(&parseState, type, NULL);
4492  }
4493 
4494  Assert(res != NULL);
4495 
4497 }
4498 
4499 /*
4500  * SQL function jsonb_pretty (jsonb)
4501  *
4502  * Pretty-printed text for the jsonb
4503  */
4504 Datum
4506 {
4507  Jsonb *jb = PG_GETARG_JSONB_P(0);
4509 
4510  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4511 
4513 }
4514 
4515 /*
4516  * SQL function jsonb_concat (jsonb, jsonb)
4517  *
4518  * function for || operator
4519  */
4520 Datum
4522 {
4523  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4524  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4525  JsonbParseState *state = NULL;
4526  JsonbValue *res;
4527  JsonbIterator *it1,
4528  *it2;
4529 
4530  /*
4531  * If one of the jsonb is empty, just return the other if it's not scalar
4532  * and both are of the same kind. If it's a scalar or they are of
4533  * different kinds we need to perform the concatenation even if one is
4534  * empty.
4535  */
4536  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4537  {
4538  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4539  PG_RETURN_JSONB_P(jb2);
4540  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4541  PG_RETURN_JSONB_P(jb1);
4542  }
4543 
4544  it1 = JsonbIteratorInit(&jb1->root);
4545  it2 = JsonbIteratorInit(&jb2->root);
4546 
4547  res = IteratorConcat(&it1, &it2, &state);
4548 
4549  Assert(res != NULL);
4550 
4552 }
4553 
4554 
4555 /*
4556  * SQL function jsonb_delete (jsonb, text)
4557  *
4558  * return a copy of the jsonb with the indicated item
4559  * removed.
4560  */
4561 Datum
4563 {
4564  Jsonb *in = PG_GETARG_JSONB_P(0);
4565  text *key = PG_GETARG_TEXT_PP(1);
4566  char *keyptr = VARDATA_ANY(key);
4567  int keylen = VARSIZE_ANY_EXHDR(key);
4568  JsonbParseState *state = NULL;
4569  JsonbIterator *it;
4570  JsonbValue v,
4571  *res = NULL;
4572  bool skipNested = false;
4574 
4575  if (JB_ROOT_IS_SCALAR(in))
4576  ereport(ERROR,
4577  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4578  errmsg("cannot delete from scalar")));
4579 
4580  if (JB_ROOT_COUNT(in) == 0)
4581  PG_RETURN_JSONB_P(in);
4582 
4583  it = JsonbIteratorInit(&in->root);
4584 
4585  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4586  {
4587  skipNested = true;
4588 
4589  if ((r == WJB_ELEM || r == WJB_KEY) &&
4590  (v.type == jbvString && keylen == v.val.string.len &&
4591  memcmp(keyptr, v.val.string.val, keylen) == 0))
4592  {
4593  /* skip corresponding value as well */
4594  if (r == WJB_KEY)
4595  (void) JsonbIteratorNext(&it, &v, true);
4596 
4597  continue;
4598  }
4599 
4600  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4601  }
4602 
4603  Assert(res != NULL);
4604 
4606 }
4607 
4608 /*
4609  * SQL function jsonb_delete (jsonb, variadic text[])
4610  *
4611  * return a copy of the jsonb with the indicated items
4612  * removed.
4613  */
4614 Datum
4616 {
4617  Jsonb *in = PG_GETARG_JSONB_P(0);
4618  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4619  Datum *keys_elems;
4620  bool *keys_nulls;
4621  int keys_len;
4622  JsonbParseState *state = NULL;
4623  JsonbIterator *it;
4624  JsonbValue v,
4625  *res = NULL;
4626  bool skipNested = false;
4628 
4629  if (ARR_NDIM(keys) > 1)
4630  ereport(ERROR,
4631  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4632  errmsg("wrong number of array subscripts")));
4633 
4634  if (JB_ROOT_IS_SCALAR(in))
4635  ereport(ERROR,
4636  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4637  errmsg("cannot delete from scalar")));
4638 
4639  if (JB_ROOT_COUNT(in) == 0)
4640  PG_RETURN_JSONB_P(in);
4641 
4642  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4643 
4644  if (keys_len == 0)
4645  PG_RETURN_JSONB_P(in);
4646 
4647  it = JsonbIteratorInit(&in->root);
4648 
4649  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4650  {
4651  skipNested = true;
4652 
4653  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4654  {
4655  int i;
4656  bool found = false;
4657 
4658  for (i = 0; i < keys_len; i++)
4659  {
4660  char *keyptr;
4661  int keylen;
4662 
4663  if (keys_nulls[i])
4664  continue;
4665 
4666  /* We rely on the array elements not being toasted */
4667  keyptr = VARDATA_ANY(keys_elems[i]);
4668  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4669  if (keylen == v.val.string.len &&
4670  memcmp(keyptr, v.val.string.val, keylen) == 0)
4671  {
4672  found = true;
4673  break;
4674  }
4675  }
4676  if (found)
4677  {
4678  /* skip corresponding value as well */
4679  if (r == WJB_KEY)
4680  (void) JsonbIteratorNext(&it, &v, true);
4681 
4682  continue;
4683  }
4684  }
4685 
4686  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4687  }
4688 
4689  Assert(res != NULL);
4690 
4692 }
4693 
4694 /*
4695  * SQL function jsonb_delete (jsonb, int)
4696  *
4697  * return a copy of the jsonb with the indicated item
4698  * removed. Negative int means count back from the
4699  * end of the items.
4700  */
4701 Datum
4703 {
4704  Jsonb *in = PG_GETARG_JSONB_P(0);
4705  int idx = PG_GETARG_INT32(1);
4706  JsonbParseState *state = NULL;
4707  JsonbIterator *it;
4708  uint32 i = 0,
4709  n;
4710  JsonbValue v,
4711  *res = NULL;
4713 
4714  if (JB_ROOT_IS_SCALAR(in))
4715  ereport(ERROR,
4716  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4717  errmsg("cannot delete from scalar")));
4718 
4719  if (JB_ROOT_IS_OBJECT(in))
4720  ereport(ERROR,
4721  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4722  errmsg("cannot delete from object using integer index")));
4723 
4724  if (JB_ROOT_COUNT(in) == 0)
4725  PG_RETURN_JSONB_P(in);
4726 
4727  it = JsonbIteratorInit(&in->root);
4728 
4729  r = JsonbIteratorNext(&it, &v, false);
4730  Assert(r == WJB_BEGIN_ARRAY);
4731  n = v.val.array.nElems;
4732 
4733  if (idx < 0)
4734  {
4735  if (-idx > n)
4736  idx = n;
4737  else
4738  idx = n + idx;
4739  }
4740 
4741  if (idx >= n)
4742  PG_RETURN_JSONB_P(in);
4743 
4744  pushJsonbValue(&state, r, NULL);
4745 
4746  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4747  {
4748  if (r == WJB_ELEM)
4749  {
4750  if (i++ == idx)
4751  continue;
4752  }
4753 
4754  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4755  }
4756 
4757  Assert(res != NULL);
4758 
4760 }
4761 
4762 /*
4763  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
4764  */
4765 Datum
4767 {
4768  Jsonb *in = PG_GETARG_JSONB_P(0);
4769  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4770  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4772  bool create = PG_GETARG_BOOL(3);
4773  JsonbValue *res = NULL;
4774  Datum *path_elems;
4775  bool *path_nulls;
4776  int path_len;
4777  JsonbIterator *it;
4778  JsonbParseState *st = NULL;
4779 
4780  JsonbToJsonbValue(newjsonb, &newval);
4781 
4782  if (ARR_NDIM(path) > 1)
4783  ereport(ERROR,
4784  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4785  errmsg("wrong number of array subscripts")));
4786 
4787  if (JB_ROOT_IS_SCALAR(in))
4788  ereport(ERROR,
4789  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4790  errmsg("cannot set path in scalar")));
4791 
4792  if (JB_ROOT_COUNT(in) == 0 && !create)
4793  PG_RETURN_JSONB_P(in);
4794 
4795  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4796 
4797  if (path_len == 0)
4798  PG_RETURN_JSONB_P(in);
4799 
4800  it = JsonbIteratorInit(&in->root);
4801 
4802  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4803  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4804 
4805  Assert(res != NULL);
4806 
4808 }
4809 
4810 
4811 /*
4812  * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text)
4813  */
4814 Datum
4816 {
4817  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4818  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4819  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4820  /* bool create = PG_GETARG_BOOL(3); */
4821  text *handle_null;
4822  char *handle_val;
4823 
4824  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4825  PG_RETURN_NULL();
4826 
4827  /* could happen if they pass in an explicit NULL */
4828  if (PG_ARGISNULL(4))
4829  ereport(ERROR,
4830  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4831  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4832 
4833  /* if the new value isn't an SQL NULL just call jsonb_set */
4834  if (!PG_ARGISNULL(2))
4835  return jsonb_set(fcinfo);
4836 
4837  handle_null = PG_GETARG_TEXT_P(4);
4838  handle_val = text_to_cstring(handle_null);
4839 
4840  if (strcmp(handle_val, "raise_exception") == 0)
4841  {
4842  ereport(ERROR,
4843  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4844  errmsg("JSON value must not be null"),
4845  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4846  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4847  return (Datum) 0; /* silence stupider compilers */
4848  }
4849  else if (strcmp(handle_val, "use_json_null") == 0)
4850  {
4851  Datum newval;
4852 
4854 
4855  fcinfo->args[2].value = newval;
4856  fcinfo->args[2].isnull = false;
4857  return jsonb_set(fcinfo);
4858  }
4859  else if (strcmp(handle_val, "delete_key") == 0)
4860  {
4861  return jsonb_delete_path(fcinfo);
4862  }
4863  else if (strcmp(handle_val, "return_target") == 0)
4864  {
4865  Jsonb *in = PG_GETARG_JSONB_P(0);
4866 
4867  PG_RETURN_JSONB_P(in);
4868  }
4869  else
4870  {
4871  ereport(ERROR,
4872  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4873  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4874  return (Datum) 0; /* silence stupider compilers */
4875  }
4876 }
4877 
4878 /*
4879  * SQL function jsonb_delete_path(jsonb, text[])
4880  */
4881 Datum
4883 {
4884  Jsonb *in = PG_GETARG_JSONB_P(0);
4885  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4886  JsonbValue *res = NULL;
4887  Datum *path_elems;
4888  bool *path_nulls;
4889  int path_len;
4890  JsonbIterator *it;
4891  JsonbParseState *st = NULL;
4892 
4893  if (ARR_NDIM(path) > 1)
4894  ereport(ERROR,
4895  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4896  errmsg("wrong number of array subscripts")));
4897 
4898  if (JB_ROOT_IS_SCALAR(in))
4899  ereport(ERROR,
4900  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4901  errmsg("cannot delete path in scalar")));
4902 
4903  if (JB_ROOT_COUNT(in) == 0)
4904  PG_RETURN_JSONB_P(in);
4905 
4906  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4907 
4908  if (path_len == 0)
4909  PG_RETURN_JSONB_P(in);
4910 
4911  it = JsonbIteratorInit(&in->root);
4912 
4913  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4914  0, NULL, JB_PATH_DELETE);
4915 
4916  Assert(res != NULL);
4917 
4919 }
4920 
4921 /*
4922  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
4923  */
4924 Datum
4926 {
4927  Jsonb *in = PG_GETARG_JSONB_P(0);
4928  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4929  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4931  bool after = PG_GETARG_BOOL(3);
4932  JsonbValue *res = NULL;
4933  Datum *path_elems;
4934  bool *path_nulls;
4935  int path_len;
4936  JsonbIterator *it;
4937  JsonbParseState *st = NULL;
4938 
4939  JsonbToJsonbValue(newjsonb, &newval);
4940 
4941  if (ARR_NDIM(path) > 1)
4942  ereport(ERROR,
4943  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4944  errmsg("wrong number of array subscripts")));
4945 
4946  if (JB_ROOT_IS_SCALAR(in))
4947  ereport(ERROR,
4948  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4949  errmsg("cannot set path in scalar")));
4950 
4951  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4952 
4953  if (path_len == 0)
4954  PG_RETURN_JSONB_P(in);
4955 
4956  it = JsonbIteratorInit(&in->root);
4957 
4958  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
4960 
4961  Assert(res != NULL);
4962 
4964 }
4965 
4966 /*
4967  * Iterate over all jsonb objects and merge them into one.
4968  * The logic of this function copied from the same hstore function,
4969  * except the case, when it1 & it2 represents jbvObject.
4970  * In that case we just append the content of it2 to it1 without any
4971  * verifications.
4972  */
4973 static JsonbValue *
4976 {
4977  JsonbValue v1,
4978  v2,
4979  *res = NULL;
4980  JsonbIteratorToken r1,
4981  r2,
4982  rk1,
4983  rk2;
4984 
4985  rk1 = JsonbIteratorNext(it1, &v1, false);
4986  rk2 = JsonbIteratorNext(it2, &v2, false);
4987 
4988  /*
4989  * JsonbIteratorNext reports raw scalars as if they were single-element
4990  * arrays; hence we only need consider "object" and "array" cases here.
4991  */
4992  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4993  {
4994  /*
4995  * Both inputs are objects.
4996  *
4997  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4998  * (because res will not be finished yet).
4999  */
5000  pushJsonbValue(state, rk1, NULL);
5001  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
5002  pushJsonbValue(state, r1, &v1);
5003 
5004  /*
5005  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
5006  * (the concatenation will be completed). Any duplicate keys will
5007  * automatically override the value from the first object.
5008  */
5009  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5010  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5011  }
5012  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
5013  {
5014  /*
5015  * Both inputs are arrays.
5016  */
5017  pushJsonbValue(state, rk1, NULL);
5018 
5019  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5020  {
5021  Assert(r1 == WJB_ELEM);
5022  pushJsonbValue(state, r1, &v1);
5023  }
5024 
5025  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
5026  {
5027  Assert(r2 == WJB_ELEM);
5028  pushJsonbValue(state, WJB_ELEM, &v2);
5029  }
5030 
5031  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
5032  }
5033  else if (rk1 == WJB_BEGIN_OBJECT)
5034  {
5035  /*
5036  * We have object || array.
5037  */
5038  Assert(rk2 == WJB_BEGIN_ARRAY);
5039 
5041 
5043  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
5044  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
5045 
5046  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5047  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
5048  }
5049  else
5050  {
5051  /*
5052  * We have array || object.
5053  */
5054  Assert(rk1 == WJB_BEGIN_ARRAY);
5055  Assert(rk2 == WJB_BEGIN_OBJECT);
5056 
5058 
5059  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5060  pushJsonbValue(state, r1, &v1);
5061 
5063  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5064  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5065 
5067  }
5068 
5069  return res;
5070 }
5071 
5072 /*
5073  * Do most of the heavy work for jsonb_set/jsonb_insert
5074  *
5075  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
5076  *
5077  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
5078  * we create the new value if the key or array index does not exist.
5079  *
5080  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
5081  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
5082  *
5083  * If JB_PATH_FILL_GAPS bit is set, this will change an assignment logic in
5084  * case if target is an array. The assignment index will not be restricted by
5085  * number of elements in the array, and if there are any empty slots between
5086  * last element of the array and a new one they will be filled with nulls. If
5087  * the index is negative, it still will be considered an index from the end
5088  * of the array. Of a part of the path is not present and this part is more
5089  * than just one last element, this flag will instruct to create the whole
5090  * chain of corresponding objects and insert the value.
5091  *
5092  * JB_PATH_CONSISTENT_POSITION for an array indicates that the caller wants to
5093  * keep values with fixed indices. Indices for existing elements could be
5094  * changed (shifted forward) in case if the array is prepended with a new value
5095  * and a negative index out of the range, so this behavior will be prevented
5096  * and return an error.
5097  *
5098  * All path elements before the last must already exist
5099  * whatever bits in op_type are set, or nothing is done.
5100  */
5101 static JsonbValue *
5102 setPath(JsonbIterator **it, Datum *path_elems,
5103  bool *path_nulls, int path_len,
5104  JsonbParseState **st, int level, JsonbValue *newval, int op_type)
5105 {
5106  JsonbValue v;
5108  JsonbValue *res;
5109 
5111 
5112  if (path_nulls[level])
5113  ereport(ERROR,
5114  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5115  errmsg("path element at position %d is null",
5116  level + 1)));
5117 
5118  r = JsonbIteratorNext(it, &v, false);
5119 
5120  switch (r)
5121  {
5122  case WJB_BEGIN_ARRAY:
5123 
5124  /*
5125  * If instructed complain about attempts to replace within a raw
5126  * scalar value. This happens even when current level is equal to
5127  * path_len, because the last path key should also correspond to
5128  * an object or an array, not raw scalar.
5129  */
5130  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
5131  v.val.array.rawScalar)
5132  ereport(ERROR,
5133  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5134  errmsg("cannot replace existing key"),
5135  errdetail("The path assumes key is a composite object, "
5136  "but it is a scalar value.")));
5137 
5138  (void) pushJsonbValue(st, r, NULL);
5139  setPathArray(it, path_elems, path_nulls, path_len, st, level,
5140  newval, v.val.array.nElems, op_type);
5141  r = JsonbIteratorNext(it, &v, false);
5142  Assert(r == WJB_END_ARRAY);
5143  res = pushJsonbValue(st, r, NULL);
5144  break;
5145  case WJB_BEGIN_OBJECT:
5146  (void) pushJsonbValue(st, r, NULL);
5147  setPathObject(it, path_elems, path_nulls, path_len, st, level,
5148  newval, v.val.object.nPairs, op_type);
5149  r = JsonbIteratorNext(it, &v, true);
5150  Assert(r == WJB_END_OBJECT);
5151  res = pushJsonbValue(st, r, NULL);
5152  break;
5153  case WJB_ELEM:
5154  case WJB_VALUE:
5155 
5156  /*
5157  * If instructed complain about attempts to replace within a
5158  * scalar value. This happens even when current level is equal to
5159  * path_len, because the last path key should also correspond to
5160  * an object or an array, not an element or value.
5161  */
5162  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
5163  ereport(ERROR,
5164  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5165  errmsg("cannot replace existing key"),
5166  errdetail("The path assumes key is a composite object, "
5167  "but it is a scalar value.")));
5168 
5169  res = pushJsonbValue(st, r, &v);
5170  break;
5171  default:
5172  elog(ERROR, "unrecognized iterator result: %d", (int) r);
5173  res = NULL; /* keep compiler quiet */
5174  break;
5175  }
5176 
5177  return res;
5178 }
5179 
5180 /*
5181  * Object walker for setPath
5182  */
5183 static void
5184 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
5185  int path_len, JsonbParseState **st, int level,
5186  JsonbValue *newval, uint32 npairs, int op_type)
5187 {
5188  text *pathelem = NULL;
5189  int i;
5190  JsonbValue k,
5191  v;
5192  bool done = false;
5193 
5194  if (level >= path_len || path_nulls[level])
5195  done = true;
5196  else
5197  {
5198  /* The path Datum could be toasted, in which case we must detoast it */
5199  pathelem = DatumGetTextPP(path_elems[level]);
5200  }
5201 
5202  /* empty object is a special case for create */
5203  if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
5204  (level == path_len - 1))
5205  {
5206  JsonbValue newkey;
5207 
5208  newkey.type = jbvString;
5209  newkey.val.string.val = VARDATA_ANY(pathelem);
5210  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5211 
5212  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5213  (void) pushJsonbValue(st, WJB_VALUE, newval);
5214  }
5215 
5216  for (i = 0; i < npairs; i++)
5217  {
5218  JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
5219 
5220  Assert(r == WJB_KEY);
5221 
5222  if (!done &&
5223  k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
5224  memcmp(k.val.string.val, VARDATA_ANY(pathelem),
5225  k.val.string.len) == 0)
5226  {
5227  done = true;
5228 
5229  if (level == path_len - 1)
5230  {
5231  /*
5232  * called from jsonb_insert(), it forbids redefining an
5233  * existing value
5234  */
5235  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
5236  ereport(ERROR,
5237  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5238  errmsg("cannot replace existing key"),
5239  errhint("Try using the function jsonb_set "
5240  "to replace key value.")));
5241 
5242  r = JsonbIteratorNext(it, &v, true); /* skip value */
5243  if (!(op_type & JB_PATH_DELETE))
5244  {
5245  (void) pushJsonbValue(st, WJB_KEY, &k);
5246  (void) pushJsonbValue(st, WJB_VALUE, newval);
5247  }
5248  }
5249  else
5250  {
5251  (void) pushJsonbValue(st, r, &k);
5252  setPath(it, path_elems, path_nulls, path_len,
5253  st, level + 1, newval, op_type);
5254  }
5255  }
5256  else
5257  {
5258  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
5259  level == path_len - 1 && i == npairs - 1)
5260  {
5261  JsonbValue newkey;
5262 
5263  newkey.type = jbvString;
5264  newkey.val.string.val = VARDATA_ANY(pathelem);
5265  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5266 
5267  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5268  (void) pushJsonbValue(st, WJB_VALUE, newval);
5269  }
5270 
5271  (void) pushJsonbValue(st, r, &k);
5272  r = JsonbIteratorNext(it, &v, false);
5273  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5274  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5275  {
5276  int walking_level = 1;
5277 
5278  while (walking_level != 0)
5279  {
5280  r = JsonbIteratorNext(it, &v, false);
5281 
5282  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5283  ++walking_level;
5284  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5285  --walking_level;
5286 
5287  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5288  }
5289  }
5290  }
5291  }
5292 
5293  /*--
5294  * If we got here there are only few possibilities:
5295  * - no target path was found, and an open object with some keys/values was
5296  * pushed into the state
5297  * - an object is empty, only WJB_BEGIN_OBJECT is pushed
5298  *
5299  * In both cases if instructed to create the path when not present,
5300  * generate the whole chain of empty objects and insert the new value
5301  * there.
5302  */
5303  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5304  {
5305  JsonbValue newkey;
5306 
5307  newkey.type = jbvString;
5308  newkey.val.string.val = VARDATA_ANY(pathelem);
5309  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5310 
5311  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5312  (void) push_path(st, level, path_elems, path_nulls,
5313  path_len, newval);
5314 
5315  /* Result is closed with WJB_END_OBJECT outside of this function */
5316  }
5317 }
5318 
5319 /*
5320  * Array walker for setPath
5321  */
5322 static void
5323 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
5324  int path_len, JsonbParseState **st, int level,
5325  JsonbValue *newval, uint32 nelems, int op_type)
5326 {
5327  JsonbValue v;
5328  int idx,
5329  i;
5330  bool done = false;
5331 
5332  /* pick correct index */
5333  if (level < path_len && !path_nulls[level])
5334  {
5335  char *c = TextDatumGetCString(path_elems[level]);
5336  char *badp;
5337 
5338  errno = 0;
5339  idx = strtoint(c, &badp, 10);
5340  if (badp == c || *badp != '\0' || errno != 0)
5341  ereport(ERROR,
5342  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5343  errmsg("path element at position %d is not an integer: \"%s\"",
5344  level + 1, c)));
5345  }
5346  else
5347  idx = nelems;
5348 
5349  if (idx < 0)
5350  {
5351  if (-idx > nelems)
5352  {
5353  /*
5354  * If asked to keep elements position consistent, it's not allowed
5355  * to prepend the array.
5356  */
5357  if (op_type & JB_PATH_CONSISTENT_POSITION)
5358  ereport(ERROR,
5359  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5360  errmsg("path element at position %d is out of range: %d",
5361  level + 1, idx)));
5362  else
5363  idx = INT_MIN;
5364  }
5365  else
5366  idx = nelems + idx;
5367  }
5368 
5369  /*
5370  * Filling the gaps means there are no limits on the positive index are
5371  * imposed, we can set any element. Otherwise limit the index by nelems.
5372  */
5373  if (!(op_type & JB_PATH_FILL_GAPS))
5374  {
5375  if (idx > 0 && idx > nelems)
5376  idx = nelems;
5377  }
5378 
5379  /*
5380  * if we're creating, and idx == INT_MIN, we prepend the new value to the
5381  * array also if the array is empty - in which case we don't really care
5382  * what the idx value is
5383  */
5384  if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5385  (op_type & JB_PATH_CREATE_OR_INSERT))
5386  {
5387  Assert(newval != NULL);
5388 
5389  if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
5390  push_null_elements(st, idx);
5391 
5392  (void) pushJsonbValue(st, WJB_ELEM, newval);
5393 
5394  done = true;
5395  }
5396 
5397  /* iterate over the array elements */
5398  for (i = 0; i < nelems; i++)
5399  {
5401 
5402  if (i == idx && level < path_len)
5403  {
5404  done = true;
5405 
5406  if (level == path_len - 1)
5407  {
5408  r = JsonbIteratorNext(it, &v, true); /* skip */
5409 
5410  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
5411  (void) pushJsonbValue(st, WJB_ELEM, newval);
5412 
5413  /*
5414  * We should keep current value only in case of
5415  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
5416  * otherwise it should be deleted or replaced
5417  */
5418  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
5419  (void) pushJsonbValue(st, r, &v);
5420 
5421  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
5422  (void) pushJsonbValue(st, WJB_ELEM, newval);
5423  }
5424  else
5425  (void) setPath(it, path_elems, path_nulls, path_len,
5426  st, level + 1, newval, op_type);
5427  }
5428  else
5429  {
5430  r = JsonbIteratorNext(it, &v, false);
5431 
5432  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5433 
5434  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5435  {
5436  int walking_level = 1;
5437 
5438  while (walking_level != 0)
5439  {
5440  r = JsonbIteratorNext(it, &v, false);
5441 
5442  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5443  ++walking_level;
5444  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5445  --walking_level;
5446 
5447  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5448  }
5449  }
5450  }
5451  }
5452 
5453  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
5454  {
5455  /*
5456  * If asked to fill the gaps, idx could be bigger than nelems, so
5457  * prepend the new element with nulls if that's the case.
5458  */
5459  if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
5460  push_null_elements(st, idx - nelems);
5461 
5462  (void) pushJsonbValue(st, WJB_ELEM, newval);
5463  done = true;
5464  }
5465 
5466  /*--
5467  * If we got here there are only few possibilities:
5468  * - no target path was found, and an open array with some keys/values was
5469  * pushed into the state
5470  * - an array is empty, only WJB_BEGIN_ARRAY is pushed
5471  *
5472  * In both cases if instructed to create the path when not present,
5473  * generate the whole chain of empty objects and insert the new value
5474  * there.
5475  */
5476  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5477  {
5478  if (idx > 0)
5479  push_null_elements(st, idx - nelems);
5480 
5481  (void) push_path(st, level, path_elems, path_nulls,
5482  path_len, newval);
5483 
5484  /* Result is closed with WJB_END_OBJECT outside of this function */
5485  }
5486 }
5487 
5488 /*
5489  * Parse information about what elements of a jsonb document we want to iterate
5490  * in functions iterate_json(b)_values. This information is presented in jsonb
5491  * format, so that it can be easily extended in the future.
5492  */
5493 uint32
5495 {
5496  JsonbIterator *it;
5497  JsonbValue v;
5499  uint32 flags = 0;
5500 
5501  it = JsonbIteratorInit(&jb->root);
5502 
5503  type = JsonbIteratorNext(&it, &v, false);
5504 
5505  /*
5506  * We iterate over array (scalar internally is represented as array, so,
5507  * we will accept it too) to check all its elements. Flag names are
5508  * chosen the same as jsonb_typeof uses.
5509  */
5510  if (type != WJB_BEGIN_ARRAY)
5511  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5512  errmsg("wrong flag type, only arrays and scalars are allowed")));
5513 
5514  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5515  {
5516  if (v.type != jbvString)
5517  ereport(ERROR,
5518  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5519  errmsg("flag array element is not a string"),
5520  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5521 
5522  if (v.val.string.len == 3 &&
5523  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5524  flags |= jtiAll;
5525  else if (v.val.string.len == 3 &&
5526  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5527  flags |= jtiKey;
5528  else if (v.val.string.len == 6 &&
5529  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5530  flags |= jtiString;
5531  else if (v.val.string.len == 7 &&
5532  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5533  flags |= jtiNumeric;
5534  else if (v.val.string.len == 7 &&
5535  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5536  flags |= jtiBool;
5537  else
5538  ereport(ERROR,
5539  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5540  errmsg("wrong flag in flag array: \"%s\"",
5541  pnstrdup(v.val.string.val, v.val.string.len)),
5542  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5543  }
5544 
5545  /* expect end of array now */
5546  if (type != WJB_END_ARRAY)
5547  elog(ERROR, "unexpected end of flag array");
5548 
5549  /* get final WJB_DONE and free iterator */
5550  type = JsonbIteratorNext(&it, &v, false);
5551  if (type != WJB_DONE)
5552  elog(ERROR, "unexpected end of flag array");
5553 
5554  return flags;
5555 }
5556 
5557 /*
5558  * Iterate over jsonb values or elements, specified by flags, and pass them
5559  * together with an iteration state to a specified JsonIterateStringValuesAction.
5560  */
5561 void
5564 {
5565  JsonbIterator *it;
5566  JsonbValue v;
5568 
5569  it = JsonbIteratorInit(&jb->root);
5570 
5571  /*
5572  * Just recursively iterating over jsonb and call callback on all
5573  * corresponding elements
5574  */
5575  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5576  {
5577  if (type == WJB_KEY)
5578  {
5579  if (flags & jtiKey)
5580  action(state, v.val.string.val, v.val.string.len);
5581 
5582  continue;
5583  }
5584  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5585  {
5586  /* do not call callback for composite JsonbValue */
5587  continue;
5588  }
5589 
5590  /* JsonbValue is a value of object or element of array */
5591  switch (v.type)
5592  {
5593  case jbvString:
5594  if (flags & jtiString)
5595  action(state, v.val.string.val, v.val.string.len);
5596  break;
5597  case jbvNumeric:
5598  if (flags & jtiNumeric)
5599  {
5600  char *val;
5601 
5603  NumericGetDatum(v.val.numeric)));
5604 
5605  action(state, val, strlen(val));
5606  pfree(val);
5607  }
5608  break;
5609  case jbvBool:
5610  if (flags & jtiBool)
5611  {
5612  if (v.val.boolean)
5613  action(state, "true", 4);
5614  else
5615  action(state, "false", 5);
5616  }
5617  break;
5618  default:
5619  /* do not call callback for composite JsonbValue */
5620  break;
5621  }
5622  }
5623 }
5624 
5625 /*
5626  * Iterate over json values and elements, specified by flags, and pass them
5627  * together with an iteration state to a specified JsonIterateStringValuesAction.
5628  */
5629 void
5630 iterate_json_values(text *json, uint32 flags, void *action_state,
5632 {
5633  JsonLexContext lex;
5634  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5636 
5637  state->lex = makeJsonLexContext(&lex, json, true);
5638  state->action = action;
5639  state->action_state = action_state;
5640  state->flags = flags;
5641 
5642  sem->semstate = (void *) state;
5645 
5646  pg_parse_json_or_ereport(&lex, sem);
5647  freeJsonLexContext(&lex);
5648 }
5649 
5650 /*
5651  * An auxiliary function for iterate_json_values to invoke a specified
5652  * JsonIterateStringValuesAction for specified values.
5653  */
5654 static JsonParseErrorType
5656 {
5658 
5659  switch (tokentype)
5660  {
5661  case JSON_TOKEN_STRING:
5662  if (_state->flags & jtiString)
5663  _state->action(_state->action_state, token, strlen(token));
5664  break;
5665  case JSON_TOKEN_NUMBER:
5666  if (_state->flags & jtiNumeric)
5667  _state->action(_state->action_state, token, strlen(token));
5668  break;
5669  case JSON_TOKEN_TRUE:
5670  case JSON_TOKEN_FALSE:
5671  if (_state->flags & jtiBool)
5672  _state->action(_state->action_state, token, strlen(token));
5673  break;
5674  default:
5675  /* do not call callback for any other token */
5676  break;
5677  }
5678 
5679  return JSON_SUCCESS;
5680 }
5681 
5682 static JsonParseErrorType
5683 iterate_values_object_field_start(void *state, char *fname, bool isnull)
5684 {
5686 
5687  if (_state->flags & jtiKey)
5688  {
5689  char *val = pstrdup(fname);
5690 
5691  _state->action(_state->action_state, val, strlen(val));
5692  }
5693 
5694  return JSON_SUCCESS;
5695 }
5696 
5697 /*
5698  * Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
5699  * to every string value or element. Any necessary context for a
5700  * JsonTransformStringValuesAction can be passed in the action_state variable.
5701  * Function returns a copy of an original jsonb object with transformed values.
5702  */
5703 Jsonb *
5704 transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
5705  JsonTransformStringValuesAction transform_action)
5706 {
5707  JsonbIterator *it;
5708  JsonbValue v,
5709  *res = NULL;
5711  JsonbParseState *st = NULL;
5712  text *out;
5713  bool is_scalar = false;
5714 
5715  it = JsonbIteratorInit(&jsonb->root);
5716  is_scalar = it->isScalar;
5717 
5718  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5719  {
5720  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
5721  {
5722  out = transform_action(action_state, v.val.string.val, v.val.string.len);
5723  /* out is probably not toasted, but let's be sure */
5724  out = pg_detoast_datum_packed(out);
5725  v.val.string.val = VARDATA_ANY(out);
5726  v.val.string.len = VARSIZE_ANY_EXHDR(out);
5727  res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
5728  }
5729  else
5730  {
5731  res = pushJsonbValue(&st, type, (type == WJB_KEY ||
5732  type == WJB_VALUE ||
5733  type == WJB_ELEM) ? &v : NULL);
5734  }
5735  }
5736 
5737  if (res->type == jbvArray)
5738  res->val.array.rawScalar = is_scalar;
5739 
5740  return JsonbValueToJsonb(res);
5741 }
5742 
5743 /*
5744  * Iterate over a json, and apply a specified JsonTransformStringValuesAction
5745  * to every string value or element. Any necessary context for a
5746  * JsonTransformStringValuesAction can be passed in the action_state variable.
5747  * Function returns a StringInfo, which is a copy of an original json with
5748  * transformed values.
5749  */
5750 text *
5751 transform_json_string_values(text *json, void *action_state,
5752  JsonTransformStringValuesAction transform_action)
5753 {
5754  JsonLexContext lex;
5755  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5757 
5758  state->lex = makeJsonLexContext(&lex, json, true);
5759  state->strval = makeStringInfo();
5760  state->action = transform_action;
5761  state->action_state = action_state;
5762 
5763  sem->semstate = (void *) state;
5771 
5772  pg_parse_json_or_ereport(&lex, sem);
5773  freeJsonLexContext(&lex);
5774 
5775  return cstring_to_text_with_len(state->strval->data, state->strval->len);
5776 }
5777 
5778 /*
5779  * Set of auxiliary functions for transform_json_string_values to invoke a
5780  * specified JsonTransformStringValuesAction for all values and left everything
5781  * else untouched.
5782  */
5783 static JsonParseErrorType
5785 {
5787 
5788  appendStringInfoCharMacro(_state->strval, '{');
5789 
5790  return JSON_SUCCESS;
5791 }
5792 
5793 static JsonParseErrorType
5795 {
5797 
5798  appendStringInfoCharMacro(_state->strval, '}');
5799 
5800  return JSON_SUCCESS;
5801 }
5802 
5803 static JsonParseErrorType
5805 {
5807 
5808  appendStringInfoCharMacro(_state->strval, '[');
5809 
5810  return JSON_SUCCESS;
5811 }
5812 
5813 static JsonParseErrorType
5815 {
5817 
5818  appendStringInfoCharMacro(_state->strval, ']');
5819 
5820  return JSON_SUCCESS;
5821 }
5822 
5823 static JsonParseErrorType
5824 transform_string_values_object_field_start(void *state, char *fname, bool isnull)
5825 {
5827 
5828  if (_state->strval->data[_state->strval->len - 1] != '{')
5829  appendStringInfoCharMacro(_state->strval, ',');
5830 
5831  /*
5832  * Unfortunately we don't have the quoted and escaped string any more, so
5833  * we have to re-escape it.
5834  */
5835  escape_json(_state->strval, fname);
5836  appendStringInfoCharMacro(_state->strval, ':');
5837 
5838  return JSON_SUCCESS;
5839 }
5840 
5841 static JsonParseErrorType
5843 {
5845 
5846  if (_state->strval->data[_state->strval->len - 1] != '[')
5847  appendStringInfoCharMacro(_state->strval, ',');
5848 
5849  return JSON_SUCCESS;
5850 }
5851 
5852 static JsonParseErrorType
5854 {
5856 
5857  if (tokentype == JSON_TOKEN_STRING)
5858  {
5859  text *out = _state->action(_state->action_state, token, strlen(token));
5860 
5861  escape_json(_state->strval, text_to_cstring(out));
5862  }
5863  else
5865 
5866  return JSON_SUCCESS;
5867 }
5868 
5870 json_get_first_token(text *json, bool throw_error)
5871 {
5872  JsonLexContext lex;
5873  JsonParseErrorType result;
5874 
5875  makeJsonLexContext(&lex, json, false);
5876 
5877  /* Lex exactly one token from the input and check its type. */
5878  result = json_lex(&lex);
5879 
5880  if (result == JSON_SUCCESS)
5881  return lex.token_type;
5882 
5883  if (throw_error)
5884  json_errsave_error(result, &lex, NULL);
5885 
5886  return JSON_TOKEN_INVALID; /* invalid json */
5887 }
5888 
5889 /*
5890  * Determine how we want to print values of a given type in datum_to_json(b).
5891  *
5892  * Given the datatype OID, return its JsonTypeCategory, as well as the type's
5893  * output function OID. If the returned category is JSONTYPE_CAST, we return
5894  * the OID of the type->JSON cast function instead.
5895  */
5896 void
5897 json_categorize_type(Oid typoid, bool is_jsonb,
5898  JsonTypeCategory *tcategory, Oid *outfuncoid)
5899 {
5900  bool typisvarlena;
5901 
5902  /* Look through any domain */
5903  typoid = getBaseType(typoid);
5904 
5905  *outfuncoid = InvalidOid;
5906 
5907  switch (typoid)
5908  {
5909  case BOOLOID:
5910  *outfuncoid = F_BOOLOUT;
5911  *tcategory = JSONTYPE_BOOL;
5912  break;
5913 
5914  case INT2OID:
5915  case INT4OID:
5916  case INT8OID:
5917  case FLOAT4OID:
5918  case FLOAT8OID:
5919  case NUMERICOID:
5920  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5921  *tcategory = JSONTYPE_NUMERIC;
5922  break;
5923 
5924  case DATEOID:
5925  *outfuncoid = F_DATE_OUT;
5926  *tcategory = JSONTYPE_DATE;
5927  break;
5928 
5929  case TIMESTAMPOID:
5930  *outfuncoid = F_TIMESTAMP_OUT;
5931  *tcategory = JSONTYPE_TIMESTAMP;
5932  break;
5933 
5934  case TIMESTAMPTZOID:
5935  *outfuncoid = F_TIMESTAMPTZ_OUT;
5936  *tcategory = JSONTYPE_TIMESTAMPTZ;
5937  break;
5938 
5939  case JSONOID:
5940  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5941  *tcategory = JSONTYPE_JSON;
5942  break;
5943 
5944  case JSONBOID:
5945  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5946  *tcategory = is_jsonb ? JSONTYPE_JSONB : JSONTYPE_JSON;
5947  break;
5948 
5949  default:
5950  /* Check for arrays and composites */
5951  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
5952  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
5953  {
5954  *outfuncoid = F_ARRAY_OUT;
5955  *tcategory = JSONTYPE_ARRAY;
5956  }
5957  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
5958  {
5959  *outfuncoid = F_RECORD_OUT;
5960  *tcategory = JSONTYPE_COMPOSITE;
5961  }
5962  else
5963  {
5964  /*
5965  * It's probably the general case. But let's look for a cast
5966  * to json (note: not to jsonb even if is_jsonb is true), if
5967  * it's not built-in.
5968  */
5969  *tcategory = JSONTYPE_OTHER;
5970  if (typoid >= FirstNormalObjectId)
5971  {
5972  Oid castfunc;
5973  CoercionPathType ctype;
5974 
5975  ctype = find_coercion_pathway(JSONOID, typoid,
5977  &castfunc);
5978  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
5979  {
5980  *outfuncoid = castfunc;
5981  *tcategory = JSONTYPE_CAST;
5982  }
5983  else
5984  {
5985  /* non builtin type with no cast */
5986  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5987  }
5988  }
5989  else
5990  {
5991  /* any other builtin type */
5992  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5993  }
5994  }
5995  break;
5996  }
5997 }
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:805
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:733
unsigned int uint32
Definition: c.h:493
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1142
signed int int32
Definition: c.h:481
#define VARHDRSZ
Definition: c.h:679
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:385
#define MemSet(start, val, len)
Definition: c.h:1007
#define OidIsValid(objectId)
Definition: c.h:762
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:2223
@ 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
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:664
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:1159
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:209
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:592
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:153
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
Definition: jsonapi.c:249
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:186
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:57
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:51
@ JSON_SUCCESS
Definition: jsonapi.h:38
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:54
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:53
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
#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:3894
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:3850
Datum jsonb_object_keys(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:565
static JsonParseErrorType populate_recordset_array_start(void *state)
Definition: jsonfuncs.c:4203
static JsonParseErrorType transform_string_values_array_start(void *state)
Definition: jsonfuncs.c:5804
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:5751
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:5824
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:5683
struct PopulateArrayContext PopulateArrayContext
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4974
Datum json_each_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1959
Datum json_populate_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3908
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2749
Datum jsonb_delete(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4562
Jsonb * transform_jsonb_string_values(Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
Definition: jsonfuncs.c:5704
struct TransformJsonStringValuesState TransformJsonStringValuesState
Datum jsonb_delete_array(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4615
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:5102
Datum jsonb_pretty(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4505
struct DomainIOData DomainIOData
static JsonParseErrorType transform_string_values_array_end(void *state)
Definition: jsonfuncs.c:5814
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:537
static JsonParseErrorType populate_recordset_object_start(void *state)
Definition: jsonfuncs.c:4135
static RecordIOData * allocate_record_info(MemoryContext mcxt, int ncolumns)
Definition: jsonfuncs.c:3397
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5655
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1802
Datum jsonb_insert(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4925
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:4227
static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4250
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:3556
Datum json_array_element(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:919
Datum jsonb_delete_idx(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4702
#define JB_PATH_DELETE
Definition: jsonfuncs.c:44
struct GetState GetState
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4320
#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:3863
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4380
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg, Node *escontext)
Definition: jsonfuncs.c:3619
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:5323
struct IterateJsonStringValuesState IterateJsonStringValuesState
#define JsValueIsString(jsv)
Definition: jsonfuncs.c:323
static JsonParseErrorType populate_recordset_object_end(void *state)
Definition: jsonfuncs.c:4165
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4882
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:4414
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:4521
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:5494
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:4310
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4330
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:4340
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:3915
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:3328
#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:5870
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4766
#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:5562
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2706
Datum jsonb_set_lax(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4815
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:4350
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:4447
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:5897
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:5630
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:3582
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:4188
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:50
static JsonParseErrorType transform_string_values_object_end(void *state)
Definition: jsonfuncs.c:5794
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:3731
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:4210
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:3961
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj, Node *escontext)
Definition: jsonfuncs.c:3441
static JsonParseErrorType alen_object_start(void *state)
Definition: jsonfuncs.c:1897
static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
Definition: jsonfuncs.c:3413
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:3901
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4391
#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:3799
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:45
static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
Definition: jsonfuncs.c:3922
#define JsObjectFree(jso)
Definition: jsonfuncs.c:333
struct PopulateRecordsetState PopulateRecordsetState
static JsonParseErrorType transform_string_values_object_start(void *state)
Definition: jsonfuncs.c:5784
static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:5842
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:5184
static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5853
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3773
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:46
@ jtiKey
Definition: jsonfuncs.h:26
@ jtiAll
Definition: jsonfuncs.h:30
@ jtiNumeric
Definition: jsonfuncs.h:28
@ jtiBool
Definition: jsonfuncs.h:29
@ jtiString
Definition: jsonfuncs.h:27
void(* JsonIterateStringValuesAction)(void *state, char *elem_value, int elem_len)
Definition: jsonfuncs.h:34
JsonTypeCategory
Definition: jsonfuncs.h:68
@ JSONTYPE_JSON
Definition: jsonfuncs.h:75
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:73
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:71
@ JSONTYPE_DATE
Definition: jsonfuncs.h:72
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:70
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:80
@ JSONTYPE_CAST
Definition: jsonfuncs.h:79
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:78
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:77
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:74
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:76
text *(* JsonTransformStringValuesAction)(void *state, char *elem_value, int elem_len)
Definition: jsonfuncs.h:37
Assert(fmt[strlen(fmt) - 1] !='\n')
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2715
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2611
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2863
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2830
char get_typtype(Oid typid)
Definition: lsyscache.c:2585
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2494
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2477
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:1694
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:371
char * pstrdup(const char *in)
Definition: mcxt.c:1683
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc0(Size size)
Definition: mcxt.c:1334
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1202
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1528
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1168
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:442
void * palloc(Size size)
Definition: mcxt.c:1304
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#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:72
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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:673
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::@23 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
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
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::@26 val
char * str
Definition: jsonfuncs.c:298
union JsValue::@24 val
JsonbValue * jsonb
Definition: jsonfuncs.c:303
int len
Definition: jsonfuncs.c:299
JsonTokenType type
Definition: jsonfuncs.c:300
bool is_json
Definition: jsonfuncs.c:293
struct JsValue::@24::@25 json
char * val
Definition: jsonfuncs.c:149
char fname[NAMEDATALEN]
Definition: jsonfuncs.c:148
JsonTokenType type
Definition: jsonfuncs.c:150
char * input
Definition: jsonapi.h:80
char * token_start
Definition: jsonapi.h:83
char * token_terminator
Definition: jsonapi.h:84
char * prev_token_terminator
Definition: jsonapi.h:85
char * line_start
Definition: jsonapi.h:90
int lex_level
Definition: jsonapi.h:87
int input_length
Definition: jsonapi.h:81
int line_number
Definition: jsonapi.h:89
JsonTokenType token_type
Definition: jsonapi.h:86
json_struct_action array_end
Definition: jsonapi.h:124
json_struct_action object_start
Definition: jsonapi.h:121
json_ofield_action object_field_start
Definition: jsonapi.h:125
json_aelem_action array_element_start
Definition: jsonapi.h:127
json_scalar_action scalar
Definition: jsonapi.h:129
void * semstate
Definition: jsonapi.h:120
json_aelem_action array_element_end
Definition: jsonapi.h:128
json_struct_action array_start
Definition: jsonapi.h:123
json_struct_action object_end
Definition: jsonapi.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:126
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:674
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
#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