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