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