PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2016, 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/typcache.h"
35 
36 /* Operations available for setPath */
37 #define JB_PATH_NOOP 0x0000
38 #define JB_PATH_CREATE 0x0001
39 #define JB_PATH_DELETE 0x0002
40 #define JB_PATH_INSERT_BEFORE 0x0004
41 #define JB_PATH_INSERT_AFTER 0x0008
42 #define JB_PATH_CREATE_OR_INSERT \
43  (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
44 
45 /* semantic action functions for json_object_keys */
46 static void okeys_object_field_start(void *state, char *fname, bool isnull);
47 static void okeys_array_start(void *state);
48 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
49 
50 /* semantic action functions for json_get* functions */
51 static void get_object_start(void *state);
52 static void get_object_end(void *state);
53 static void get_object_field_start(void *state, char *fname, bool isnull);
54 static void get_object_field_end(void *state, char *fname, bool isnull);
55 static void get_array_start(void *state);
56 static void get_array_end(void *state);
57 static void get_array_element_start(void *state, bool isnull);
58 static void get_array_element_end(void *state, bool isnull);
59 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
60 
61 /* common worker function for json getter functions */
62 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
63 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
64  bool normalize_results);
65 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
66 
67 /* semantic action functions for json_array_length */
68 static void alen_object_start(void *state);
69 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
70 static void alen_array_element_start(void *state, bool isnull);
71 
72 /* common workers for json{b}_each* functions */
73 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
74 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
75  bool as_text);
76 
77 /* semantic action functions for json_each */
78 static void each_object_field_start(void *state, char *fname, bool isnull);
79 static void each_object_field_end(void *state, char *fname, bool isnull);
80 static void each_array_start(void *state);
81 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
82 
83 /* common workers for json{b}_array_elements_* functions */
84 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
85  bool as_text);
86 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
87  bool as_text);
88 
89 /* semantic action functions for json_array_elements */
90 static void elements_object_start(void *state);
91 static void elements_array_element_start(void *state, bool isnull);
92 static void elements_array_element_end(void *state, bool isnull);
93 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
94 
95 /* turn a json object into a hash table */
96 static HTAB *get_json_object_as_hash(text *json, const char *funcname);
97 
98 /* common worker for populate_record and to_record */
99 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
100  bool have_record_arg);
101 
102 /* semantic action functions for get_json_object_as_hash */
103 static void hash_object_field_start(void *state, char *fname, bool isnull);
104 static void hash_object_field_end(void *state, char *fname, bool isnull);
105 static void hash_array_start(void *state);
106 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
107 
108 /* semantic action functions for populate_recordset */
109 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
110 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
111 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
112 static void populate_recordset_object_start(void *state);
113 static void populate_recordset_object_end(void *state);
114 static void populate_recordset_array_start(void *state);
115 static void populate_recordset_array_element_start(void *state, bool isnull);
116 
117 /* semantic action functions for json_strip_nulls */
118 static void sn_object_start(void *state);
119 static void sn_object_end(void *state);
120 static void sn_array_start(void *state);
121 static void sn_array_end(void *state);
122 static void sn_object_field_start(void *state, char *fname, bool isnull);
123 static void sn_array_element_start(void *state, bool isnull);
124 static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
125 
126 /* worker function for populate_recordset and to_recordset */
127 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
128  bool have_record_arg);
129 
130 /* Worker that takes care of common setup for us */
132  uint32 flags,
133  char *key,
134  uint32 keylen);
135 
136 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
139 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
140  bool *path_nulls, int path_len,
141  JsonbParseState **st, int level, Jsonb *newval,
142  int op_type);
143 static void setPathObject(JsonbIterator **it, Datum *path_elems,
144  bool *path_nulls, int path_len, JsonbParseState **st,
145  int level,
146  Jsonb *newval, uint32 npairs, int op_type);
147 static void setPathArray(JsonbIterator **it, Datum *path_elems,
148  bool *path_nulls, int path_len, JsonbParseState **st,
149  int level, Jsonb *newval, uint32 nelems, int op_type);
150 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
151 
152 /* state for json_object_keys */
153 typedef struct OkeysState
154 {
156  char **result;
160 } OkeysState;
161 
162 /* state for json_get* functions */
163 typedef struct GetState
164 {
170  int npath; /* length of each path-related array */
171  char **path_names; /* field name(s) being sought */
172  int *path_indexes; /* array index(es) being sought */
173  bool *pathok; /* is path matched to current depth? */
174  int *array_cur_index; /* current element index at each path level */
175 } GetState;
176 
177 /* state for json_array_length */
178 typedef struct AlenState
179 {
181  int count;
182 } AlenState;
183 
184 /* state for json_each */
185 typedef struct EachState
186 {
195 } EachState;
196 
197 /* state for json_array_elements */
198 typedef struct ElementsState
199 {
201  const char *function_name;
209 } ElementsState;
210 
211 /* state for get_json_object_as_hash */
212 typedef struct JhashState
213 {
215  const char *function_name;
219 } JHashState;
220 
221 /* hashtable element */
222 typedef struct JsonHashEntry
223 {
224  char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
225  char *val;
226  char *json;
227  bool isnull;
228 } JsonHashEntry;
229 
230 /* these two are stolen from hstore / record_out, used in populate_record* */
231 typedef struct ColumnIOData
232 {
234  Oid typiofunc;
235  Oid typioparam;
236  FmgrInfo proc;
237 } ColumnIOData;
238 
239 typedef struct RecordIOData
240 {
243  int ncolumns;
244  ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
245 } RecordIOData;
246 
247 /* state for populate_recordset */
249 {
251  const char *function_name;
259  MemoryContext fn_mcxt; /* used to stash IO funcs */
261 
262 /* state for json_strip_nulls */
263 typedef struct StripnullState
264 {
269 
270 /* Turn a jsonb object into a record */
273 
274 /*
275  * SQL function json_object_keys
276  *
277  * Returns the set of keys for the object argument.
278  *
279  * This SRF operates in value-per-call mode. It processes the
280  * object during the first call, and the keys are simply stashed
281  * in an array, whose size is expanded as necessary. This is probably
282  * safe enough for a list of keys of a single object, since they are
283  * limited in size to NAMEDATALEN and the number of keys is unlikely to
284  * be so huge that it has major memory implications.
285  */
286 Datum
288 {
289  FuncCallContext *funcctx;
290  OkeysState *state;
291  int i;
292 
293  if (SRF_IS_FIRSTCALL())
294  {
295  MemoryContext oldcontext;
296  Jsonb *jb = PG_GETARG_JSONB(0);
297  bool skipNested = false;
298  JsonbIterator *it;
299  JsonbValue v;
301 
302  if (JB_ROOT_IS_SCALAR(jb))
303  ereport(ERROR,
304  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
305  errmsg("cannot call %s on a scalar",
306  "jsonb_object_keys")));
307  else if (JB_ROOT_IS_ARRAY(jb))
308  ereport(ERROR,
309  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
310  errmsg("cannot call %s on an array",
311  "jsonb_object_keys")));
312 
313  funcctx = SRF_FIRSTCALL_INIT();
314  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
315 
316  state = palloc(sizeof(OkeysState));
317 
318  state->result_size = JB_ROOT_COUNT(jb);
319  state->result_count = 0;
320  state->sent_count = 0;
321  state->result = palloc(state->result_size * sizeof(char *));
322 
323  it = JsonbIteratorInit(&jb->root);
324 
325  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
326  {
327  skipNested = true;
328 
329  if (r == WJB_KEY)
330  {
331  char *cstr;
332 
333  cstr = palloc(v.val.string.len + 1 * sizeof(char));
334  memcpy(cstr, v.val.string.val, v.val.string.len);
335  cstr[v.val.string.len] = '\0';
336  state->result[state->result_count++] = cstr;
337  }
338  }
339 
340  MemoryContextSwitchTo(oldcontext);
341  funcctx->user_fctx = (void *) state;
342  }
343 
344  funcctx = SRF_PERCALL_SETUP();
345  state = (OkeysState *) funcctx->user_fctx;
346 
347  if (state->sent_count < state->result_count)
348  {
349  char *nxt = state->result[state->sent_count++];
350 
351  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
352  }
353 
354  /* cleanup to reduce or eliminate memory leaks */
355  for (i = 0; i < state->result_count; i++)
356  pfree(state->result[i]);
357  pfree(state->result);
358  pfree(state);
359 
360  SRF_RETURN_DONE(funcctx);
361 }
362 
363 
364 Datum
366 {
367  FuncCallContext *funcctx;
368  OkeysState *state;
369  int i;
370 
371  if (SRF_IS_FIRSTCALL())
372  {
373  text *json = PG_GETARG_TEXT_P(0);
374  JsonLexContext *lex = makeJsonLexContext(json, true);
375  JsonSemAction *sem;
376  MemoryContext oldcontext;
377 
378  funcctx = SRF_FIRSTCALL_INIT();
379  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
380 
381  state = palloc(sizeof(OkeysState));
382  sem = palloc0(sizeof(JsonSemAction));
383 
384  state->lex = lex;
385  state->result_size = 256;
386  state->result_count = 0;
387  state->sent_count = 0;
388  state->result = palloc(256 * sizeof(char *));
389 
390  sem->semstate = (void *) state;
392  sem->scalar = okeys_scalar;
394  /* remainder are all NULL, courtesy of palloc0 above */
395 
396  pg_parse_json(lex, sem);
397  /* keys are now in state->result */
398 
399  pfree(lex->strval->data);
400  pfree(lex->strval);
401  pfree(lex);
402  pfree(sem);
403 
404  MemoryContextSwitchTo(oldcontext);
405  funcctx->user_fctx = (void *) state;
406  }
407 
408  funcctx = SRF_PERCALL_SETUP();
409  state = (OkeysState *) funcctx->user_fctx;
410 
411  if (state->sent_count < state->result_count)
412  {
413  char *nxt = state->result[state->sent_count++];
414 
415  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
416  }
417 
418  /* cleanup to reduce or eliminate memory leaks */
419  for (i = 0; i < state->result_count; i++)
420  pfree(state->result[i]);
421  pfree(state->result);
422  pfree(state);
423 
424  SRF_RETURN_DONE(funcctx);
425 }
426 
427 static void
428 okeys_object_field_start(void *state, char *fname, bool isnull)
429 {
430  OkeysState *_state = (OkeysState *) state;
431 
432  /* only collecting keys for the top level object */
433  if (_state->lex->lex_level != 1)
434  return;
435 
436  /* enlarge result array if necessary */
437  if (_state->result_count >= _state->result_size)
438  {
439  _state->result_size *= 2;
440  _state->result = (char **)
441  repalloc(_state->result, sizeof(char *) * _state->result_size);
442  }
443 
444  /* save a copy of the field name */
445  _state->result[_state->result_count++] = pstrdup(fname);
446 }
447 
448 static void
450 {
451  OkeysState *_state = (OkeysState *) state;
452 
453  /* top level must be a json object */
454  if (_state->lex->lex_level == 0)
455  ereport(ERROR,
456  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
457  errmsg("cannot call %s on an array",
458  "json_object_keys")));
459 }
460 
461 static void
462 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
463 {
464  OkeysState *_state = (OkeysState *) state;
465 
466  /* top level must be a json object */
467  if (_state->lex->lex_level == 0)
468  ereport(ERROR,
469  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
470  errmsg("cannot call %s on a scalar",
471  "json_object_keys")));
472 }
473 
474 /*
475  * json and jsonb getter functions
476  * these implement the -> ->> #> and #>> operators
477  * and the json{b?}_extract_path*(json, text, ...) functions
478  */
479 
480 
481 Datum
483 {
484  text *json = PG_GETARG_TEXT_P(0);
485  text *fname = PG_GETARG_TEXT_PP(1);
486  char *fnamestr = text_to_cstring(fname);
487  text *result;
488 
489  result = get_worker(json, &fnamestr, NULL, 1, false);
490 
491  if (result != NULL)
492  PG_RETURN_TEXT_P(result);
493  else
494  PG_RETURN_NULL();
495 }
496 
497 Datum
499 {
500  Jsonb *jb = PG_GETARG_JSONB(0);
501  text *key = PG_GETARG_TEXT_PP(1);
502  JsonbValue *v;
503 
504  if (!JB_ROOT_IS_OBJECT(jb))
505  PG_RETURN_NULL();
506 
508  VARDATA_ANY(key),
509  VARSIZE_ANY_EXHDR(key));
510 
511  if (v != NULL)
513 
514  PG_RETURN_NULL();
515 }
516 
517 Datum
519 {
520  text *json = PG_GETARG_TEXT_P(0);
521  text *fname = PG_GETARG_TEXT_PP(1);
522  char *fnamestr = text_to_cstring(fname);
523  text *result;
524 
525  result = get_worker(json, &fnamestr, NULL, 1, true);
526 
527  if (result != NULL)
528  PG_RETURN_TEXT_P(result);
529  else
530  PG_RETURN_NULL();
531 }
532 
533 Datum
535 {
536  Jsonb *jb = PG_GETARG_JSONB(0);
537  text *key = PG_GETARG_TEXT_PP(1);
538  JsonbValue *v;
539 
540  if (!JB_ROOT_IS_OBJECT(jb))
541  PG_RETURN_NULL();
542 
544  VARDATA_ANY(key),
545  VARSIZE_ANY_EXHDR(key));
546 
547  if (v != NULL)
548  {
549  text *result = NULL;
550 
551  switch (v->type)
552  {
553  case jbvNull:
554  break;
555  case jbvBool:
556  result = cstring_to_text(v->val.boolean ? "true" : "false");
557  break;
558  case jbvString:
559  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
560  break;
561  case jbvNumeric:
563  PointerGetDatum(v->val.numeric))));
564  break;
565  case jbvBinary:
566  {
567  StringInfo jtext = makeStringInfo();
568 
569  (void) JsonbToCString(jtext, v->val.binary.data, -1);
570  result = cstring_to_text_with_len(jtext->data, jtext->len);
571  }
572  break;
573  default:
574  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
575  }
576 
577  if (result)
578  PG_RETURN_TEXT_P(result);
579  }
580 
581  PG_RETURN_NULL();
582 }
583 
584 Datum
586 {
587  text *json = PG_GETARG_TEXT_P(0);
588  int element = PG_GETARG_INT32(1);
589  text *result;
590 
591  result = get_worker(json, NULL, &element, 1, false);
592 
593  if (result != NULL)
594  PG_RETURN_TEXT_P(result);
595  else
596  PG_RETURN_NULL();
597 }
598 
599 Datum
601 {
602  Jsonb *jb = PG_GETARG_JSONB(0);
603  int element = PG_GETARG_INT32(1);
604  JsonbValue *v;
605 
606  if (!JB_ROOT_IS_ARRAY(jb))
607  PG_RETURN_NULL();
608 
609  /* Handle negative subscript */
610  if (element < 0)
611  {
612  uint32 nelements = JB_ROOT_COUNT(jb);
613 
614  if (-element > nelements)
615  PG_RETURN_NULL();
616  else
617  element += nelements;
618  }
619 
620  v = getIthJsonbValueFromContainer(&jb->root, element);
621  if (v != NULL)
623 
624  PG_RETURN_NULL();
625 }
626 
627 Datum
629 {
630  text *json = PG_GETARG_TEXT_P(0);
631  int element = PG_GETARG_INT32(1);
632  text *result;
633 
634  result = get_worker(json, NULL, &element, 1, true);
635 
636  if (result != NULL)
637  PG_RETURN_TEXT_P(result);
638  else
639  PG_RETURN_NULL();
640 }
641 
642 Datum
644 {
645  Jsonb *jb = PG_GETARG_JSONB(0);
646  int element = PG_GETARG_INT32(1);
647  JsonbValue *v;
648 
649  if (!JB_ROOT_IS_ARRAY(jb))
650  PG_RETURN_NULL();
651 
652  /* Handle negative subscript */
653  if (element < 0)
654  {
655  uint32 nelements = JB_ROOT_COUNT(jb);
656 
657  if (-element > nelements)
658  PG_RETURN_NULL();
659  else
660  element += nelements;
661  }
662 
663  v = getIthJsonbValueFromContainer(&jb->root, element);
664  if (v != NULL)
665  {
666  text *result = NULL;
667 
668  switch (v->type)
669  {
670  case jbvNull:
671  break;
672  case jbvBool:
673  result = cstring_to_text(v->val.boolean ? "true" : "false");
674  break;
675  case jbvString:
676  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
677  break;
678  case jbvNumeric:
680  PointerGetDatum(v->val.numeric))));
681  break;
682  case jbvBinary:
683  {
684  StringInfo jtext = makeStringInfo();
685 
686  (void) JsonbToCString(jtext, v->val.binary.data, -1);
687  result = cstring_to_text_with_len(jtext->data, jtext->len);
688  }
689  break;
690  default:
691  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
692  }
693 
694  if (result)
695  PG_RETURN_TEXT_P(result);
696  }
697 
698  PG_RETURN_NULL();
699 }
700 
701 Datum
703 {
704  return get_path_all(fcinfo, false);
705 }
706 
707 Datum
709 {
710  return get_path_all(fcinfo, true);
711 }
712 
713 /*
714  * common routine for extract_path functions
715  */
716 static Datum
717 get_path_all(FunctionCallInfo fcinfo, bool as_text)
718 {
719  text *json = PG_GETARG_TEXT_P(0);
720  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
721  text *result;
722  Datum *pathtext;
723  bool *pathnulls;
724  int npath;
725  char **tpath;
726  int *ipath;
727  int i;
728 
729  /*
730  * If the array contains any null elements, return NULL, on the grounds
731  * that you'd have gotten NULL if any RHS value were NULL in a nested
732  * series of applications of the -> operator. (Note: because we also
733  * return NULL for error cases such as no-such-field, this is true
734  * regardless of the contents of the rest of the array.)
735  */
736  if (array_contains_nulls(path))
737  PG_RETURN_NULL();
738 
739  deconstruct_array(path, TEXTOID, -1, false, 'i',
740  &pathtext, &pathnulls, &npath);
741 
742  tpath = palloc(npath * sizeof(char *));
743  ipath = palloc(npath * sizeof(int));
744 
745  for (i = 0; i < npath; i++)
746  {
747  Assert(!pathnulls[i]);
748  tpath[i] = TextDatumGetCString(pathtext[i]);
749 
750  /*
751  * we have no idea at this stage what structure the document is so
752  * just convert anything in the path that we can to an integer and set
753  * all the other integers to INT_MIN which will never match.
754  */
755  if (*tpath[i] != '\0')
756  {
757  long ind;
758  char *endptr;
759 
760  errno = 0;
761  ind = strtol(tpath[i], &endptr, 10);
762  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
763  ipath[i] = (int) ind;
764  else
765  ipath[i] = INT_MIN;
766  }
767  else
768  ipath[i] = INT_MIN;
769  }
770 
771  result = get_worker(json, tpath, ipath, npath, as_text);
772 
773  if (result != NULL)
774  PG_RETURN_TEXT_P(result);
775  else
776  PG_RETURN_NULL();
777 }
778 
779 /*
780  * get_worker
781  *
782  * common worker for all the json getter functions
783  *
784  * json: JSON object (in text form)
785  * tpath[]: field name(s) to extract
786  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
787  * npath: length of tpath[] and/or ipath[]
788  * normalize_results: true to de-escape string and null scalars
789  *
790  * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
791  * field is not to be matched at that nesting level. Similarly, ipath can
792  * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
793  * not to be matched at that nesting level (a json datum should never be
794  * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
795  */
796 static text *
798  char **tpath,
799  int *ipath,
800  int npath,
801  bool normalize_results)
802 {
803  JsonLexContext *lex = makeJsonLexContext(json, true);
804  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
805  GetState *state = palloc0(sizeof(GetState));
806 
807  Assert(npath >= 0);
808 
809  state->lex = lex;
810  /* is it "_as_text" variant? */
811  state->normalize_results = normalize_results;
812  state->npath = npath;
813  state->path_names = tpath;
814  state->path_indexes = ipath;
815  state->pathok = palloc0(sizeof(bool) * npath);
816  state->array_cur_index = palloc(sizeof(int) * npath);
817 
818  if (npath > 0)
819  state->pathok[0] = true;
820 
821  sem->semstate = (void *) state;
822 
823  /*
824  * Not all variants need all the semantic routines. Only set the ones that
825  * are actually needed for maximum efficiency.
826  */
827  sem->scalar = get_scalar;
828  if (npath == 0)
829  {
831  sem->object_end = get_object_end;
833  sem->array_end = get_array_end;
834  }
835  if (tpath != NULL)
836  {
839  }
840  if (ipath != NULL)
841  {
845  }
846 
847  pg_parse_json(lex, sem);
848 
849  return state->tresult;
850 }
851 
852 static void
854 {
855  GetState *_state = (GetState *) state;
856  int lex_level = _state->lex->lex_level;
857 
858  if (lex_level == 0 && _state->npath == 0)
859  {
860  /*
861  * Special case: we should match the entire object. We only need this
862  * at outermost level because at nested levels the match will have
863  * been started by the outer field or array element callback.
864  */
865  _state->result_start = _state->lex->token_start;
866  }
867 }
868 
869 static void
871 {
872  GetState *_state = (GetState *) state;
873  int lex_level = _state->lex->lex_level;
874 
875  if (lex_level == 0 && _state->npath == 0)
876  {
877  /* Special case: return the entire object */
878  char *start = _state->result_start;
879  int len = _state->lex->prev_token_terminator - start;
880 
881  _state->tresult = cstring_to_text_with_len(start, len);
882  }
883 }
884 
885 static void
886 get_object_field_start(void *state, char *fname, bool isnull)
887 {
888  GetState *_state = (GetState *) state;
889  bool get_next = false;
890  int lex_level = _state->lex->lex_level;
891 
892  if (lex_level <= _state->npath &&
893  _state->pathok[lex_level - 1] &&
894  _state->path_names != NULL &&
895  _state->path_names[lex_level - 1] != NULL &&
896  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
897  {
898  if (lex_level < _state->npath)
899  {
900  /* if not at end of path just mark path ok */
901  _state->pathok[lex_level] = true;
902  }
903  else
904  {
905  /* end of path, so we want this value */
906  get_next = true;
907  }
908  }
909 
910  if (get_next)
911  {
912  /* this object overrides any previous matching object */
913  _state->tresult = NULL;
914  _state->result_start = NULL;
915 
916  if (_state->normalize_results &&
917  _state->lex->token_type == JSON_TOKEN_STRING)
918  {
919  /* for as_text variants, tell get_scalar to set it for us */
920  _state->next_scalar = true;
921  }
922  else
923  {
924  /* for non-as_text variants, just note the json starting point */
925  _state->result_start = _state->lex->token_start;
926  }
927  }
928 }
929 
930 static void
931 get_object_field_end(void *state, char *fname, bool isnull)
932 {
933  GetState *_state = (GetState *) state;
934  bool get_last = false;
935  int lex_level = _state->lex->lex_level;
936 
937  /* same tests as in get_object_field_start */
938  if (lex_level <= _state->npath &&
939  _state->pathok[lex_level - 1] &&
940  _state->path_names != NULL &&
941  _state->path_names[lex_level - 1] != NULL &&
942  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
943  {
944  if (lex_level < _state->npath)
945  {
946  /* done with this field so reset pathok */
947  _state->pathok[lex_level] = false;
948  }
949  else
950  {
951  /* end of path, so we want this value */
952  get_last = true;
953  }
954  }
955 
956  /* for as_text scalar case, our work is already done */
957  if (get_last && _state->result_start != NULL)
958  {
959  /*
960  * make a text object from the string from the prevously noted json
961  * start up to the end of the previous token (the lexer is by now
962  * ahead of us on whatever came after what we're interested in).
963  */
964  if (isnull && _state->normalize_results)
965  _state->tresult = (text *) NULL;
966  else
967  {
968  char *start = _state->result_start;
969  int len = _state->lex->prev_token_terminator - start;
970 
971  _state->tresult = cstring_to_text_with_len(start, len);
972  }
973 
974  /* this should be unnecessary but let's do it for cleanliness: */
975  _state->result_start = NULL;
976  }
977 }
978 
979 static void
981 {
982  GetState *_state = (GetState *) state;
983  int lex_level = _state->lex->lex_level;
984 
985  if (lex_level < _state->npath)
986  {
987  /* Initialize counting of elements in this array */
988  _state->array_cur_index[lex_level] = -1;
989 
990  /* INT_MIN value is reserved to represent invalid subscript */
991  if (_state->path_indexes[lex_level] < 0 &&
992  _state->path_indexes[lex_level] != INT_MIN)
993  {
994  /* Negative subscript -- convert to positive-wise subscript */
995  int nelements = json_count_array_elements(_state->lex);
996 
997  if (-_state->path_indexes[lex_level] <= nelements)
998  _state->path_indexes[lex_level] += nelements;
999  }
1000  }
1001  else if (lex_level == 0 && _state->npath == 0)
1002  {
1003  /*
1004  * Special case: we should match the entire array. We only need this
1005  * at the outermost level because at nested levels the match will have
1006  * been started by the outer field or array element callback.
1007  */
1008  _state->result_start = _state->lex->token_start;
1009  }
1010 }
1011 
1012 static void
1014 {
1015  GetState *_state = (GetState *) state;
1016  int lex_level = _state->lex->lex_level;
1017 
1018  if (lex_level == 0 && _state->npath == 0)
1019  {
1020  /* Special case: return the entire array */
1021  char *start = _state->result_start;
1022  int len = _state->lex->prev_token_terminator - start;
1023 
1024  _state->tresult = cstring_to_text_with_len(start, len);
1025  }
1026 }
1027 
1028 static void
1029 get_array_element_start(void *state, bool isnull)
1030 {
1031  GetState *_state = (GetState *) state;
1032  bool get_next = false;
1033  int lex_level = _state->lex->lex_level;
1034 
1035  /* Update array element counter */
1036  if (lex_level <= _state->npath)
1037  _state->array_cur_index[lex_level - 1]++;
1038 
1039  if (lex_level <= _state->npath &&
1040  _state->pathok[lex_level - 1] &&
1041  _state->path_indexes != NULL &&
1042  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1043  {
1044  if (lex_level < _state->npath)
1045  {
1046  /* if not at end of path just mark path ok */
1047  _state->pathok[lex_level] = true;
1048  }
1049  else
1050  {
1051  /* end of path, so we want this value */
1052  get_next = true;
1053  }
1054  }
1055 
1056  /* same logic as for objects */
1057  if (get_next)
1058  {
1059  _state->tresult = NULL;
1060  _state->result_start = NULL;
1061 
1062  if (_state->normalize_results &&
1063  _state->lex->token_type == JSON_TOKEN_STRING)
1064  {
1065  _state->next_scalar = true;
1066  }
1067  else
1068  {
1069  _state->result_start = _state->lex->token_start;
1070  }
1071  }
1072 }
1073 
1074 static void
1075 get_array_element_end(void *state, bool isnull)
1076 {
1077  GetState *_state = (GetState *) state;
1078  bool get_last = false;
1079  int lex_level = _state->lex->lex_level;
1080 
1081  /* same tests as in get_array_element_start */
1082  if (lex_level <= _state->npath &&
1083  _state->pathok[lex_level - 1] &&
1084  _state->path_indexes != NULL &&
1085  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1086  {
1087  if (lex_level < _state->npath)
1088  {
1089  /* done with this element so reset pathok */
1090  _state->pathok[lex_level] = false;
1091  }
1092  else
1093  {
1094  /* end of path, so we want this value */
1095  get_last = true;
1096  }
1097  }
1098 
1099  /* same logic as for objects */
1100  if (get_last && _state->result_start != NULL)
1101  {
1102  if (isnull && _state->normalize_results)
1103  _state->tresult = (text *) NULL;
1104  else
1105  {
1106  char *start = _state->result_start;
1107  int len = _state->lex->prev_token_terminator - start;
1108 
1109  _state->tresult = cstring_to_text_with_len(start, len);
1110  }
1111 
1112  _state->result_start = NULL;
1113  }
1114 }
1115 
1116 static void
1117 get_scalar(void *state, char *token, JsonTokenType tokentype)
1118 {
1119  GetState *_state = (GetState *) state;
1120  int lex_level = _state->lex->lex_level;
1121 
1122  /* Check for whole-object match */
1123  if (lex_level == 0 && _state->npath == 0)
1124  {
1125  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1126  {
1127  /* we want the de-escaped string */
1128  _state->next_scalar = true;
1129  }
1130  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1131  {
1132  _state->tresult = (text *) NULL;
1133  }
1134  else
1135  {
1136  /*
1137  * This is a bit hokey: we will suppress whitespace after the
1138  * scalar token, but not whitespace before it. Probably not worth
1139  * doing our own space-skipping to avoid that.
1140  */
1141  char *start = _state->lex->input;
1142  int len = _state->lex->prev_token_terminator - start;
1143 
1144  _state->tresult = cstring_to_text_with_len(start, len);
1145  }
1146  }
1147 
1148  if (_state->next_scalar)
1149  {
1150  /* a de-escaped text value is wanted, so supply it */
1151  _state->tresult = cstring_to_text(token);
1152  /* make sure the next call to get_scalar doesn't overwrite it */
1153  _state->next_scalar = false;
1154  }
1155 }
1156 
1157 Datum
1159 {
1160  return get_jsonb_path_all(fcinfo, false);
1161 }
1162 
1163 Datum
1165 {
1166  return get_jsonb_path_all(fcinfo, true);
1167 }
1168 
1169 static Datum
1171 {
1172  Jsonb *jb = PG_GETARG_JSONB(0);
1173  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1174  Jsonb *res;
1175  Datum *pathtext;
1176  bool *pathnulls;
1177  int npath;
1178  int i;
1179  bool have_object = false,
1180  have_array = false;
1181  JsonbValue *jbvp = NULL;
1182  JsonbValue tv;
1183  JsonbContainer *container;
1184 
1185  /*
1186  * If the array contains any null elements, return NULL, on the grounds
1187  * that you'd have gotten NULL if any RHS value were NULL in a nested
1188  * series of applications of the -> operator. (Note: because we also
1189  * return NULL for error cases such as no-such-field, this is true
1190  * regardless of the contents of the rest of the array.)
1191  */
1192  if (array_contains_nulls(path))
1193  PG_RETURN_NULL();
1194 
1195  deconstruct_array(path, TEXTOID, -1, false, 'i',
1196  &pathtext, &pathnulls, &npath);
1197 
1198  /* Identify whether we have object, array, or scalar at top-level */
1199  container = &jb->root;
1200 
1201  if (JB_ROOT_IS_OBJECT(jb))
1202  have_object = true;
1203  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1204  have_array = true;
1205  else
1206  {
1208  /* Extract the scalar value, if it is what we'll return */
1209  if (npath <= 0)
1210  jbvp = getIthJsonbValueFromContainer(container, 0);
1211  }
1212 
1213  /*
1214  * If the array is empty, return the entire LHS object, on the grounds
1215  * that we should do zero field or element extractions. For the
1216  * non-scalar case we can just hand back the object without much work. For
1217  * the scalar case, fall through and deal with the value below the loop.
1218  * (This inconsistency arises because there's no easy way to generate a
1219  * JsonbValue directly for root-level containers.)
1220  */
1221  if (npath <= 0 && jbvp == NULL)
1222  {
1223  if (as_text)
1224  {
1226  container,
1227  VARSIZE(jb))));
1228  }
1229  else
1230  {
1231  /* not text mode - just hand back the jsonb */
1232  PG_RETURN_JSONB(jb);
1233  }
1234  }
1235 
1236  for (i = 0; i < npath; i++)
1237  {
1238  if (have_object)
1239  {
1240  jbvp = findJsonbValueFromContainerLen(container,
1241  JB_FOBJECT,
1242  VARDATA_ANY(pathtext[i]),
1243  VARSIZE_ANY_EXHDR(pathtext[i]));
1244  }
1245  else if (have_array)
1246  {
1247  long lindex;
1248  uint32 index;
1249  char *indextext = TextDatumGetCString(pathtext[i]);
1250  char *endptr;
1251 
1252  errno = 0;
1253  lindex = strtol(indextext, &endptr, 10);
1254  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1255  lindex > INT_MAX || lindex < INT_MIN)
1256  PG_RETURN_NULL();
1257 
1258  if (lindex >= 0)
1259  {
1260  index = (uint32) lindex;
1261  }
1262  else
1263  {
1264  /* Handle negative subscript */
1265  uint32 nelements;
1266 
1267  /* Container must be array, but make sure */
1268  if ((container->header & JB_FARRAY) == 0)
1269  elog(ERROR, "not a jsonb array");
1270 
1271  nelements = container->header & JB_CMASK;
1272 
1273  if (-lindex > nelements)
1274  PG_RETURN_NULL();
1275  else
1276  index = nelements + lindex;
1277  }
1278 
1279  jbvp = getIthJsonbValueFromContainer(container, index);
1280  }
1281  else
1282  {
1283  /* scalar, extraction yields a null */
1284  PG_RETURN_NULL();
1285  }
1286 
1287  if (jbvp == NULL)
1288  PG_RETURN_NULL();
1289  else if (i == npath - 1)
1290  break;
1291 
1292  if (jbvp->type == jbvBinary)
1293  {
1294  JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1296 
1297  r = JsonbIteratorNext(&it, &tv, true);
1298  container = (JsonbContainer *) jbvp->val.binary.data;
1299  have_object = r == WJB_BEGIN_OBJECT;
1300  have_array = r == WJB_BEGIN_ARRAY;
1301  }
1302  else
1303  {
1304  have_object = jbvp->type == jbvObject;
1305  have_array = jbvp->type == jbvArray;
1306  }
1307  }
1308 
1309  if (as_text)
1310  {
1311  /* special-case outputs for string and null values */
1312  if (jbvp->type == jbvString)
1314  jbvp->val.string.len));
1315  if (jbvp->type == jbvNull)
1316  PG_RETURN_NULL();
1317  }
1318 
1319  res = JsonbValueToJsonb(jbvp);
1320 
1321  if (as_text)
1322  {
1324  &res->root,
1325  VARSIZE(res))));
1326  }
1327  else
1328  {
1329  /* not text mode - just hand back the jsonb */
1330  PG_RETURN_JSONB(res);
1331  }
1332 }
1333 
1334 /*
1335  * SQL function json_array_length(json) -> int
1336  */
1337 Datum
1339 {
1340  text *json = PG_GETARG_TEXT_P(0);
1341  AlenState *state;
1342  JsonLexContext *lex;
1343  JsonSemAction *sem;
1344 
1345  lex = makeJsonLexContext(json, false);
1346  state = palloc0(sizeof(AlenState));
1347  sem = palloc0(sizeof(JsonSemAction));
1348 
1349  /* palloc0 does this for us */
1350 #if 0
1351  state->count = 0;
1352 #endif
1353  state->lex = lex;
1354 
1355  sem->semstate = (void *) state;
1357  sem->scalar = alen_scalar;
1359 
1360  pg_parse_json(lex, sem);
1361 
1362  PG_RETURN_INT32(state->count);
1363 }
1364 
1365 Datum
1367 {
1368  Jsonb *jb = PG_GETARG_JSONB(0);
1369 
1370  if (JB_ROOT_IS_SCALAR(jb))
1371  ereport(ERROR,
1372  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1373  errmsg("cannot get array length of a scalar")));
1374  else if (!JB_ROOT_IS_ARRAY(jb))
1375  ereport(ERROR,
1376  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1377  errmsg("cannot get array length of a non-array")));
1378 
1380 }
1381 
1382 /*
1383  * These next two checks ensure that the json is an array (since it can't be
1384  * a scalar or an object).
1385  */
1386 
1387 static void
1389 {
1390  AlenState *_state = (AlenState *) state;
1391 
1392  /* json structure check */
1393  if (_state->lex->lex_level == 0)
1394  ereport(ERROR,
1395  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1396  errmsg("cannot get array length of a non-array")));
1397 }
1398 
1399 static void
1400 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1401 {
1402  AlenState *_state = (AlenState *) state;
1403 
1404  /* json structure check */
1405  if (_state->lex->lex_level == 0)
1406  ereport(ERROR,
1407  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1408  errmsg("cannot get array length of a scalar")));
1409 }
1410 
1411 static void
1412 alen_array_element_start(void *state, bool isnull)
1413 {
1414  AlenState *_state = (AlenState *) state;
1415 
1416  /* just count up all the level 1 elements */
1417  if (_state->lex->lex_level == 1)
1418  _state->count++;
1419 }
1420 
1421 /*
1422  * SQL function json_each and json_each_text
1423  *
1424  * decompose a json object into key value pairs.
1425  *
1426  * Unlike json_object_keys() these SRFs operate in materialize mode,
1427  * stashing results into a Tuplestore object as they go.
1428  * The construction of tuples is done using a temporary memory context
1429  * that is cleared out after each tuple is built.
1430  */
1431 Datum
1433 {
1434  return each_worker(fcinfo, false);
1435 }
1436 
1437 Datum
1439 {
1440  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1441 }
1442 
1443 Datum
1445 {
1446  return each_worker(fcinfo, true);
1447 }
1448 
1449 Datum
1451 {
1452  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1453 }
1454 
1455 static Datum
1456 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1457 {
1458  Jsonb *jb = PG_GETARG_JSONB(0);
1459  ReturnSetInfo *rsi;
1460  Tuplestorestate *tuple_store;
1461  TupleDesc tupdesc;
1462  TupleDesc ret_tdesc;
1463  MemoryContext old_cxt,
1464  tmp_cxt;
1465  bool skipNested = false;
1466  JsonbIterator *it;
1467  JsonbValue v;
1469 
1470  if (!JB_ROOT_IS_OBJECT(jb))
1471  ereport(ERROR,
1472  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1473  errmsg("cannot call %s on a non-object",
1474  funcname)));
1475 
1476  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1477 
1478  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1479  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1480  rsi->expectedDesc == NULL)
1481  ereport(ERROR,
1482  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1483  errmsg("set-valued function called in context that "
1484  "cannot accept a set")));
1485 
1487 
1488  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1489  ereport(ERROR,
1490  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1491  errmsg("function returning record called in context "
1492  "that cannot accept type record")));
1493 
1495 
1496  ret_tdesc = CreateTupleDescCopy(tupdesc);
1497  BlessTupleDesc(ret_tdesc);
1498  tuple_store =
1500  false, work_mem);
1501 
1502  MemoryContextSwitchTo(old_cxt);
1503 
1505  "jsonb_each temporary cxt",
1509 
1510  it = JsonbIteratorInit(&jb->root);
1511 
1512  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1513  {
1514  skipNested = true;
1515 
1516  if (r == WJB_KEY)
1517  {
1518  text *key;
1519  HeapTuple tuple;
1520  Datum values[2];
1521  bool nulls[2] = {false, false};
1522 
1523  /* Use the tmp context so we can clean up after each tuple is done */
1524  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1525 
1526  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1527 
1528  /*
1529  * The next thing the iterator fetches should be the value, no
1530  * matter what shape it is.
1531  */
1532  r = JsonbIteratorNext(&it, &v, skipNested);
1533 
1534  values[0] = PointerGetDatum(key);
1535 
1536  if (as_text)
1537  {
1538  if (v.type == jbvNull)
1539  {
1540  /* a json null is an sql null in text mode */
1541  nulls[1] = true;
1542  values[1] = (Datum) NULL;
1543  }
1544  else
1545  {
1546  text *sv;
1547 
1548  if (v.type == jbvString)
1549  {
1550  /* In text mode, scalar strings should be dequoted */
1551  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1552  }
1553  else
1554  {
1555  /* Turn anything else into a json string */
1556  StringInfo jtext = makeStringInfo();
1557  Jsonb *jb = JsonbValueToJsonb(&v);
1558 
1559  (void) JsonbToCString(jtext, &jb->root, 0);
1560  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1561  }
1562 
1563  values[1] = PointerGetDatum(sv);
1564  }
1565  }
1566  else
1567  {
1568  /* Not in text mode, just return the Jsonb */
1569  Jsonb *val = JsonbValueToJsonb(&v);
1570 
1571  values[1] = PointerGetDatum(val);
1572  }
1573 
1574  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1575 
1576  tuplestore_puttuple(tuple_store, tuple);
1577 
1578  /* clean up and switch back */
1579  MemoryContextSwitchTo(old_cxt);
1580  MemoryContextReset(tmp_cxt);
1581  }
1582  }
1583 
1584  MemoryContextDelete(tmp_cxt);
1585 
1586  rsi->setResult = tuple_store;
1587  rsi->setDesc = ret_tdesc;
1588 
1589  PG_RETURN_NULL();
1590 }
1591 
1592 
1593 static Datum
1594 each_worker(FunctionCallInfo fcinfo, bool as_text)
1595 {
1596  text *json = PG_GETARG_TEXT_P(0);
1597  JsonLexContext *lex;
1598  JsonSemAction *sem;
1599  ReturnSetInfo *rsi;
1600  MemoryContext old_cxt;
1601  TupleDesc tupdesc;
1602  EachState *state;
1603 
1604  lex = makeJsonLexContext(json, true);
1605  state = palloc0(sizeof(EachState));
1606  sem = palloc0(sizeof(JsonSemAction));
1607 
1608  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1609 
1610  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1611  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1612  rsi->expectedDesc == NULL)
1613  ereport(ERROR,
1614  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1615  errmsg("set-valued function called in context that "
1616  "cannot accept a set")));
1617 
1619 
1620  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1621 
1622  /* make these in a sufficiently long-lived memory context */
1624 
1625  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1626  BlessTupleDesc(state->ret_tdesc);
1627  state->tuple_store =
1629  false, work_mem);
1630 
1631  MemoryContextSwitchTo(old_cxt);
1632 
1633  sem->semstate = (void *) state;
1635  sem->scalar = each_scalar;
1638 
1639  state->normalize_results = as_text;
1640  state->next_scalar = false;
1641  state->lex = lex;
1643  "json_each temporary cxt",
1647 
1648  pg_parse_json(lex, sem);
1649 
1650  MemoryContextDelete(state->tmp_cxt);
1651 
1652  rsi->setResult = state->tuple_store;
1653  rsi->setDesc = state->ret_tdesc;
1654 
1655  PG_RETURN_NULL();
1656 }
1657 
1658 
1659 static void
1660 each_object_field_start(void *state, char *fname, bool isnull)
1661 {
1662  EachState *_state = (EachState *) state;
1663 
1664  /* save a pointer to where the value starts */
1665  if (_state->lex->lex_level == 1)
1666  {
1667  /*
1668  * next_scalar will be reset in the object_field_end handler, and
1669  * since we know the value is a scalar there is no danger of it being
1670  * on while recursing down the tree.
1671  */
1672  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1673  _state->next_scalar = true;
1674  else
1675  _state->result_start = _state->lex->token_start;
1676  }
1677 }
1678 
1679 static void
1680 each_object_field_end(void *state, char *fname, bool isnull)
1681 {
1682  EachState *_state = (EachState *) state;
1683  MemoryContext old_cxt;
1684  int len;
1685  text *val;
1686  HeapTuple tuple;
1687  Datum values[2];
1688  bool nulls[2] = {false, false};
1689 
1690  /* skip over nested objects */
1691  if (_state->lex->lex_level != 1)
1692  return;
1693 
1694  /* use the tmp context so we can clean up after each tuple is done */
1695  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1696 
1697  values[0] = CStringGetTextDatum(fname);
1698 
1699  if (isnull && _state->normalize_results)
1700  {
1701  nulls[1] = true;
1702  values[1] = (Datum) 0;
1703  }
1704  else if (_state->next_scalar)
1705  {
1706  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1707  _state->next_scalar = false;
1708  }
1709  else
1710  {
1711  len = _state->lex->prev_token_terminator - _state->result_start;
1712  val = cstring_to_text_with_len(_state->result_start, len);
1713  values[1] = PointerGetDatum(val);
1714  }
1715 
1716  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1717 
1718  tuplestore_puttuple(_state->tuple_store, tuple);
1719 
1720  /* clean up and switch back */
1721  MemoryContextSwitchTo(old_cxt);
1722  MemoryContextReset(_state->tmp_cxt);
1723 }
1724 
1725 static void
1727 {
1728  EachState *_state = (EachState *) state;
1729 
1730  /* json structure check */
1731  if (_state->lex->lex_level == 0)
1732  ereport(ERROR,
1733  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1734  errmsg("cannot deconstruct an array as an object")));
1735 }
1736 
1737 static void
1738 each_scalar(void *state, char *token, JsonTokenType tokentype)
1739 {
1740  EachState *_state = (EachState *) state;
1741 
1742  /* json structure check */
1743  if (_state->lex->lex_level == 0)
1744  ereport(ERROR,
1745  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1746  errmsg("cannot deconstruct a scalar")));
1747 
1748  /* supply de-escaped value if required */
1749  if (_state->next_scalar)
1750  _state->normalized_scalar = token;
1751 }
1752 
1753 /*
1754  * SQL functions json_array_elements and json_array_elements_text
1755  *
1756  * get the elements from a json array
1757  *
1758  * a lot of this processing is similar to the json_each* functions
1759  */
1760 
1761 Datum
1763 {
1764  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1765 }
1766 
1767 Datum
1769 {
1770  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1771 }
1772 
1773 static Datum
1774 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1775  bool as_text)
1776 {
1777  Jsonb *jb = PG_GETARG_JSONB(0);
1778  ReturnSetInfo *rsi;
1779  Tuplestorestate *tuple_store;
1780  TupleDesc tupdesc;
1781  TupleDesc ret_tdesc;
1782  MemoryContext old_cxt,
1783  tmp_cxt;
1784  bool skipNested = false;
1785  JsonbIterator *it;
1786  JsonbValue v;
1788 
1789  if (JB_ROOT_IS_SCALAR(jb))
1790  ereport(ERROR,
1791  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1792  errmsg("cannot extract elements from a scalar")));
1793  else if (!JB_ROOT_IS_ARRAY(jb))
1794  ereport(ERROR,
1795  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1796  errmsg("cannot extract elements from an object")));
1797 
1798  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1799 
1800  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1801  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1802  rsi->expectedDesc == NULL)
1803  ereport(ERROR,
1804  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1805  errmsg("set-valued function called in context that "
1806  "cannot accept a set")));
1807 
1809 
1810  /* it's a simple type, so don't use get_call_result_type() */
1811  tupdesc = rsi->expectedDesc;
1812 
1814 
1815  ret_tdesc = CreateTupleDescCopy(tupdesc);
1816  BlessTupleDesc(ret_tdesc);
1817  tuple_store =
1819  false, work_mem);
1820 
1821  MemoryContextSwitchTo(old_cxt);
1822 
1824  "jsonb_array_elements temporary cxt",
1828 
1829  it = JsonbIteratorInit(&jb->root);
1830 
1831  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1832  {
1833  skipNested = true;
1834 
1835  if (r == WJB_ELEM)
1836  {
1837  HeapTuple tuple;
1838  Datum values[1];
1839  bool nulls[1] = {false};
1840 
1841  /* use the tmp context so we can clean up after each tuple is done */
1842  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1843 
1844  if (!as_text)
1845  {
1846  Jsonb *val = JsonbValueToJsonb(&v);
1847 
1848  values[0] = PointerGetDatum(val);
1849  }
1850  else
1851  {
1852  if (v.type == jbvNull)
1853  {
1854  /* a json null is an sql null in text mode */
1855  nulls[0] = true;
1856  values[0] = (Datum) NULL;
1857  }
1858  else
1859  {
1860  text *sv;
1861 
1862  if (v.type == jbvString)
1863  {
1864  /* in text mode scalar strings should be dequoted */
1865  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1866  }
1867  else
1868  {
1869  /* turn anything else into a json string */
1870  StringInfo jtext = makeStringInfo();
1871  Jsonb *jb = JsonbValueToJsonb(&v);
1872 
1873  (void) JsonbToCString(jtext, &jb->root, 0);
1874  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1875  }
1876 
1877  values[0] = PointerGetDatum(sv);
1878  }
1879  }
1880 
1881  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1882 
1883  tuplestore_puttuple(tuple_store, tuple);
1884 
1885  /* clean up and switch back */
1886  MemoryContextSwitchTo(old_cxt);
1887  MemoryContextReset(tmp_cxt);
1888  }
1889  }
1890 
1891  MemoryContextDelete(tmp_cxt);
1892 
1893  rsi->setResult = tuple_store;
1894  rsi->setDesc = ret_tdesc;
1895 
1896  PG_RETURN_NULL();
1897 }
1898 
1899 Datum
1901 {
1902  return elements_worker(fcinfo, "json_array_elements", false);
1903 }
1904 
1905 Datum
1907 {
1908  return elements_worker(fcinfo, "json_array_elements_text", true);
1909 }
1910 
1911 static Datum
1912 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1913 {
1914  text *json = PG_GETARG_TEXT_P(0);
1915 
1916  /* elements only needs escaped strings when as_text */
1917  JsonLexContext *lex = makeJsonLexContext(json, as_text);
1918  JsonSemAction *sem;
1919  ReturnSetInfo *rsi;
1920  MemoryContext old_cxt;
1921  TupleDesc tupdesc;
1923 
1924  state = palloc0(sizeof(ElementsState));
1925  sem = palloc0(sizeof(JsonSemAction));
1926 
1927  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1928 
1929  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1930  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1931  rsi->expectedDesc == NULL)
1932  ereport(ERROR,
1933  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1934  errmsg("set-valued function called in context that "
1935  "cannot accept a set")));
1936 
1938 
1939  /* it's a simple type, so don't use get_call_result_type() */
1940  tupdesc = rsi->expectedDesc;
1941 
1942  /* make these in a sufficiently long-lived memory context */
1944 
1945  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1946  BlessTupleDesc(state->ret_tdesc);
1947  state->tuple_store =
1949  false, work_mem);
1950 
1951  MemoryContextSwitchTo(old_cxt);
1952 
1953  sem->semstate = (void *) state;
1955  sem->scalar = elements_scalar;
1958 
1959  state->function_name = funcname;
1960  state->normalize_results = as_text;
1961  state->next_scalar = false;
1962  state->lex = lex;
1964  "json_array_elements temporary cxt",
1968 
1969  pg_parse_json(lex, sem);
1970 
1971  MemoryContextDelete(state->tmp_cxt);
1972 
1973  rsi->setResult = state->tuple_store;
1974  rsi->setDesc = state->ret_tdesc;
1975 
1976  PG_RETURN_NULL();
1977 }
1978 
1979 static void
1981 {
1982  ElementsState *_state = (ElementsState *) state;
1983 
1984  /* save a pointer to where the value starts */
1985  if (_state->lex->lex_level == 1)
1986  {
1987  /*
1988  * next_scalar will be reset in the array_element_end handler, and
1989  * since we know the value is a scalar there is no danger of it being
1990  * on while recursing down the tree.
1991  */
1992  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1993  _state->next_scalar = true;
1994  else
1995  _state->result_start = _state->lex->token_start;
1996  }
1997 }
1998 
1999 static void
2001 {
2002  ElementsState *_state = (ElementsState *) state;
2003  MemoryContext old_cxt;
2004  int len;
2005  text *val;
2006  HeapTuple tuple;
2007  Datum values[1];
2008  bool nulls[1] = {false};
2009 
2010  /* skip over nested objects */
2011  if (_state->lex->lex_level != 1)
2012  return;
2013 
2014  /* use the tmp context so we can clean up after each tuple is done */
2015  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2016 
2017  if (isnull && _state->normalize_results)
2018  {
2019  nulls[0] = true;
2020  values[0] = (Datum) NULL;
2021  }
2022  else if (_state->next_scalar)
2023  {
2024  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2025  _state->next_scalar = false;
2026  }
2027  else
2028  {
2029  len = _state->lex->prev_token_terminator - _state->result_start;
2030  val = cstring_to_text_with_len(_state->result_start, len);
2031  values[0] = PointerGetDatum(val);
2032  }
2033 
2034  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2035 
2036  tuplestore_puttuple(_state->tuple_store, tuple);
2037 
2038  /* clean up and switch back */
2039  MemoryContextSwitchTo(old_cxt);
2040  MemoryContextReset(_state->tmp_cxt);
2041 }
2042 
2043 static void
2045 {
2046  ElementsState *_state = (ElementsState *) state;
2047 
2048  /* json structure check */
2049  if (_state->lex->lex_level == 0)
2050  ereport(ERROR,
2051  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2052  errmsg("cannot call %s on a non-array",
2053  _state->function_name)));
2054 }
2055 
2056 static void
2057 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2058 {
2059  ElementsState *_state = (ElementsState *) state;
2060 
2061  /* json structure check */
2062  if (_state->lex->lex_level == 0)
2063  ereport(ERROR,
2064  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2065  errmsg("cannot call %s on a scalar",
2066  _state->function_name)));
2067 
2068  /* supply de-escaped value if required */
2069  if (_state->next_scalar)
2070  _state->normalized_scalar = token;
2071 }
2072 
2073 /*
2074  * SQL function json_populate_record
2075  *
2076  * set fields in a record from the argument json
2077  *
2078  * Code adapted shamelessly from hstore's populate_record
2079  * which is in turn partly adapted from record_out.
2080  *
2081  * The json is decomposed into a hash table, in which each
2082  * field in the record is then looked up by name. For jsonb
2083  * we fetch the values direct from the object.
2084  */
2085 Datum
2087 {
2088  return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2089 }
2090 
2091 Datum
2093 {
2094  return populate_record_worker(fcinfo, "jsonb_to_record", false);
2095 }
2096 
2097 Datum
2099 {
2100  return populate_record_worker(fcinfo, "json_populate_record", true);
2101 }
2102 
2103 Datum
2105 {
2106  return populate_record_worker(fcinfo, "json_to_record", false);
2107 }
2108 
2109 static Datum
2110 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
2111  bool have_record_arg)
2112 {
2113  int json_arg_num = have_record_arg ? 1 : 0;
2114  Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2115  text *json;
2116  Jsonb *jb = NULL;
2117  HTAB *json_hash = NULL;
2118  HeapTupleHeader rec = NULL;
2119  Oid tupType = InvalidOid;
2120  int32 tupTypmod = -1;
2121  TupleDesc tupdesc;
2122  HeapTupleData tuple;
2123  HeapTuple rettuple;
2124  RecordIOData *my_extra;
2125  int ncolumns;
2126  int i;
2127  Datum *values;
2128  bool *nulls;
2129 
2130  Assert(jtype == JSONOID || jtype == JSONBOID);
2131 
2132  if (have_record_arg)
2133  {
2134  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2135 
2136  if (!type_is_rowtype(argtype))
2137  ereport(ERROR,
2138  (errcode(ERRCODE_DATATYPE_MISMATCH),
2139  errmsg("first argument of %s must be a row type",
2140  funcname)));
2141 
2142  if (PG_ARGISNULL(0))
2143  {
2144  if (PG_ARGISNULL(1))
2145  PG_RETURN_NULL();
2146 
2147  /*
2148  * have no tuple to look at, so the only source of type info is
2149  * the argtype. The lookup_rowtype_tupdesc call below will error
2150  * out if we don't have a known composite type oid here.
2151  */
2152  tupType = argtype;
2153  tupTypmod = -1;
2154  }
2155  else
2156  {
2157  rec = PG_GETARG_HEAPTUPLEHEADER(0);
2158 
2159  if (PG_ARGISNULL(1))
2160  PG_RETURN_POINTER(rec);
2161 
2162  /* Extract type info from the tuple itself */
2163  tupType = HeapTupleHeaderGetTypeId(rec);
2164  tupTypmod = HeapTupleHeaderGetTypMod(rec);
2165  }
2166 
2167  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2168  }
2169  else
2170  {
2171  /* json{b}_to_record case */
2172  if (PG_ARGISNULL(0))
2173  PG_RETURN_NULL();
2174 
2175  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2176  ereport(ERROR,
2177  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2178  errmsg("function returning record called in context "
2179  "that cannot accept type record"),
2180  errhint("Try calling the function in the FROM clause "
2181  "using a column definition list.")));
2182  }
2183 
2184  if (jtype == JSONOID)
2185  {
2186  /* just get the text */
2187  json = PG_GETARG_TEXT_P(json_arg_num);
2188 
2189  json_hash = get_json_object_as_hash(json, funcname);
2190 
2191  /*
2192  * if the input json is empty, we can only skip the rest if we were
2193  * passed in a non-null record, since otherwise there may be issues
2194  * with domain nulls.
2195  */
2196  if (hash_get_num_entries(json_hash) == 0 && rec)
2197  {
2198  hash_destroy(json_hash);
2199  ReleaseTupleDesc(tupdesc);
2200  PG_RETURN_POINTER(rec);
2201  }
2202  }
2203  else
2204  {
2205  jb = PG_GETARG_JSONB(json_arg_num);
2206 
2207  /* same logic as for json */
2208  if (JB_ROOT_COUNT(jb) == 0 && rec)
2209  {
2210  ReleaseTupleDesc(tupdesc);
2211  PG_RETURN_POINTER(rec);
2212  }
2213  }
2214 
2215  ncolumns = tupdesc->natts;
2216 
2217  if (rec)
2218  {
2219  /* Build a temporary HeapTuple control structure */
2220  tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2221  ItemPointerSetInvalid(&(tuple.t_self));
2222  tuple.t_tableOid = InvalidOid;
2223  tuple.t_data = rec;
2224  }
2225 
2226  /*
2227  * We arrange to look up the needed I/O info just once per series of
2228  * calls, assuming the record type doesn't change underneath us.
2229  */
2230  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2231  if (my_extra == NULL ||
2232  my_extra->ncolumns != ncolumns)
2233  {
2234  fcinfo->flinfo->fn_extra =
2236  offsetof(RecordIOData, columns) +
2237  ncolumns * sizeof(ColumnIOData));
2238  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2239  my_extra->record_type = InvalidOid;
2240  my_extra->record_typmod = 0;
2241  my_extra->ncolumns = ncolumns;
2242  MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2243  }
2244 
2245  if (have_record_arg && (my_extra->record_type != tupType ||
2246  my_extra->record_typmod != tupTypmod))
2247  {
2248  MemSet(my_extra, 0,
2249  offsetof(RecordIOData, columns) +
2250  ncolumns * sizeof(ColumnIOData));
2251  my_extra->record_type = tupType;
2252  my_extra->record_typmod = tupTypmod;
2253  my_extra->ncolumns = ncolumns;
2254  }
2255 
2256  values = (Datum *) palloc(ncolumns * sizeof(Datum));
2257  nulls = (bool *) palloc(ncolumns * sizeof(bool));
2258 
2259  if (rec)
2260  {
2261  /* Break down the tuple into fields */
2262  heap_deform_tuple(&tuple, tupdesc, values, nulls);
2263  }
2264  else
2265  {
2266  for (i = 0; i < ncolumns; ++i)
2267  {
2268  values[i] = (Datum) 0;
2269  nulls[i] = true;
2270  }
2271  }
2272 
2273  for (i = 0; i < ncolumns; ++i)
2274  {
2275  ColumnIOData *column_info = &my_extra->columns[i];
2276  Oid column_type = tupdesc->attrs[i]->atttypid;
2277  JsonbValue *v = NULL;
2278  JsonHashEntry *hashentry = NULL;
2279 
2280  /* Ignore dropped columns in datatype */
2281  if (tupdesc->attrs[i]->attisdropped)
2282  {
2283  nulls[i] = true;
2284  continue;
2285  }
2286 
2287  if (jtype == JSONOID)
2288  {
2289  hashentry = hash_search(json_hash,
2290  NameStr(tupdesc->attrs[i]->attname),
2291  HASH_FIND, NULL);
2292  }
2293  else
2294  {
2295  char *key = NameStr(tupdesc->attrs[i]->attname);
2296 
2298  strlen(key));
2299  }
2300 
2301  /*
2302  * we can't just skip here if the key wasn't found since we might have
2303  * a domain to deal with. If we were passed in a non-null record
2304  * datum, we assume that the existing values are valid (if they're
2305  * not, then it's not our fault), but if we were passed in a null,
2306  * then every field which we don't populate needs to be run through
2307  * the input function just in case it's a domain type.
2308  */
2309  if (((jtype == JSONOID && hashentry == NULL) ||
2310  (jtype == JSONBOID && v == NULL)) && rec)
2311  continue;
2312 
2313  /*
2314  * Prepare to convert the column value from text
2315  */
2316  if (column_info->column_type != column_type)
2317  {
2318  getTypeInputInfo(column_type,
2319  &column_info->typiofunc,
2320  &column_info->typioparam);
2321  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2322  fcinfo->flinfo->fn_mcxt);
2323  column_info->column_type = column_type;
2324  }
2325  if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2326  (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2327  {
2328  /*
2329  * need InputFunctionCall to happen even for nulls, so that domain
2330  * checks are done
2331  */
2332  values[i] = InputFunctionCall(&column_info->proc, NULL,
2333  column_info->typioparam,
2334  tupdesc->attrs[i]->atttypmod);
2335  nulls[i] = true;
2336  }
2337  else
2338  {
2339  char *s = NULL;
2340 
2341  if (jtype == JSONOID)
2342  {
2343  /* already done the hard work in the json case */
2344  s = hashentry->val;
2345  }
2346  else
2347  {
2348  if (v->type == jbvString)
2349  s = pnstrdup(v->val.string.val, v->val.string.len);
2350  else if (v->type == jbvBool)
2351  s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2352  else if (v->type == jbvNumeric)
2354  PointerGetDatum(v->val.numeric)));
2355  else if (v->type == jbvBinary)
2356  s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2357  else
2358  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2359  }
2360 
2361  values[i] = InputFunctionCall(&column_info->proc, s,
2362  column_info->typioparam,
2363  tupdesc->attrs[i]->atttypmod);
2364  nulls[i] = false;
2365  }
2366  }
2367 
2368  rettuple = heap_form_tuple(tupdesc, values, nulls);
2369 
2370  ReleaseTupleDesc(tupdesc);
2371 
2372  if (json_hash)
2373  hash_destroy(json_hash);
2374 
2376 }
2377 
2378 /*
2379  * get_json_object_as_hash
2380  *
2381  * decompose a json object into a hash table.
2382  */
2383 static HTAB *
2384 get_json_object_as_hash(text *json, const char *funcname)
2385 {
2386  HASHCTL ctl;
2387  HTAB *tab;
2388  JHashState *state;
2389  JsonLexContext *lex = makeJsonLexContext(json, true);
2390  JsonSemAction *sem;
2391 
2392  memset(&ctl, 0, sizeof(ctl));
2393  ctl.keysize = NAMEDATALEN;
2394  ctl.entrysize = sizeof(JsonHashEntry);
2395  ctl.hcxt = CurrentMemoryContext;
2396  tab = hash_create("json object hashtable",
2397  100,
2398  &ctl,
2400 
2401  state = palloc0(sizeof(JHashState));
2402  sem = palloc0(sizeof(JsonSemAction));
2403 
2404  state->function_name = funcname;
2405  state->hash = tab;
2406  state->lex = lex;
2407 
2408  sem->semstate = (void *) state;
2410  sem->scalar = hash_scalar;
2413 
2414  pg_parse_json(lex, sem);
2415 
2416  return tab;
2417 }
2418 
2419 static void
2420 hash_object_field_start(void *state, char *fname, bool isnull)
2421 {
2422  JHashState *_state = (JHashState *) state;
2423 
2424  if (_state->lex->lex_level > 1)
2425  return;
2426 
2427  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2429  {
2430  /* remember start position of the whole text of the subobject */
2431  _state->save_json_start = _state->lex->token_start;
2432  }
2433  else
2434  {
2435  /* must be a scalar */
2436  _state->save_json_start = NULL;
2437  }
2438 }
2439 
2440 static void
2441 hash_object_field_end(void *state, char *fname, bool isnull)
2442 {
2443  JHashState *_state = (JHashState *) state;
2444  JsonHashEntry *hashentry;
2445  bool found;
2446 
2447  /*
2448  * Ignore nested fields.
2449  */
2450  if (_state->lex->lex_level > 1)
2451  return;
2452 
2453  /*
2454  * Ignore field names >= NAMEDATALEN - they can't match a record field.
2455  * (Note: without this test, the hash code would truncate the string at
2456  * NAMEDATALEN-1, and could then match against a similarly-truncated
2457  * record field name. That would be a reasonable behavior, but this code
2458  * has previously insisted on exact equality, so we keep this behavior.)
2459  */
2460  if (strlen(fname) >= NAMEDATALEN)
2461  return;
2462 
2463  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2464 
2465  /*
2466  * found being true indicates a duplicate. We don't do anything about
2467  * that, a later field with the same name overrides the earlier field.
2468  */
2469 
2470  hashentry->isnull = isnull;
2471  if (_state->save_json_start != NULL)
2472  {
2473  int len = _state->lex->prev_token_terminator - _state->save_json_start;
2474  char *val = palloc((len + 1) * sizeof(char));
2475 
2476  memcpy(val, _state->save_json_start, len);
2477  val[len] = '\0';
2478  hashentry->val = val;
2479  }
2480  else
2481  {
2482  /* must have had a scalar instead */
2483  hashentry->val = _state->saved_scalar;
2484  }
2485 }
2486 
2487 static void
2489 {
2490  JHashState *_state = (JHashState *) state;
2491 
2492  if (_state->lex->lex_level == 0)
2493  ereport(ERROR,
2494  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2495  errmsg("cannot call %s on an array", _state->function_name)));
2496 }
2497 
2498 static void
2499 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2500 {
2501  JHashState *_state = (JHashState *) state;
2502 
2503  if (_state->lex->lex_level == 0)
2504  ereport(ERROR,
2505  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2506  errmsg("cannot call %s on a scalar", _state->function_name)));
2507 
2508  if (_state->lex->lex_level == 1)
2509  _state->saved_scalar = token;
2510 }
2511 
2512 
2513 /*
2514  * SQL function json_populate_recordset
2515  *
2516  * set fields in a set of records from the argument json,
2517  * which must be an array of objects.
2518  *
2519  * similar to json_populate_record, but the tuple-building code
2520  * is pushed down into the semantic action handlers so it's done
2521  * per object in the array.
2522  */
2523 Datum
2525 {
2526  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2527 }
2528 
2529 Datum
2531 {
2532  return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2533 }
2534 
2535 Datum
2537 {
2538  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2539 }
2540 
2541 Datum
2543 {
2544  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2545 }
2546 
2547 static void
2549 {
2550  Datum *values;
2551  bool *nulls;
2552  int i;
2553  RecordIOData *my_extra = state->my_extra;
2554  int ncolumns = my_extra->ncolumns;
2555  TupleDesc tupdesc = state->ret_tdesc;
2556  HeapTupleHeader rec = state->rec;
2557  HeapTuple rettuple;
2558 
2559  values = (Datum *) palloc(ncolumns * sizeof(Datum));
2560  nulls = (bool *) palloc(ncolumns * sizeof(bool));
2561 
2562  if (state->rec)
2563  {
2564  HeapTupleData tuple;
2565 
2566  /* Build a temporary HeapTuple control structure */
2567  tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2568  ItemPointerSetInvalid(&(tuple.t_self));
2569  tuple.t_tableOid = InvalidOid;
2570  tuple.t_data = state->rec;
2571 
2572  /* Break down the tuple into fields */
2573  heap_deform_tuple(&tuple, tupdesc, values, nulls);
2574  }
2575  else
2576  {
2577  for (i = 0; i < ncolumns; ++i)
2578  {
2579  values[i] = (Datum) 0;
2580  nulls[i] = true;
2581  }
2582  }
2583 
2584  for (i = 0; i < ncolumns; ++i)
2585  {
2586  ColumnIOData *column_info = &my_extra->columns[i];
2587  Oid column_type = tupdesc->attrs[i]->atttypid;
2588  JsonbValue *v = NULL;
2589  char *key;
2590 
2591  /* Ignore dropped columns in datatype */
2592  if (tupdesc->attrs[i]->attisdropped)
2593  {
2594  nulls[i] = true;
2595  continue;
2596  }
2597 
2598  key = NameStr(tupdesc->attrs[i]->attname);
2599 
2601  key, strlen(key));
2602 
2603  /*
2604  * We can't just skip here if the key wasn't found since we might have
2605  * a domain to deal with. If we were passed in a non-null record
2606  * datum, we assume that the existing values are valid (if they're
2607  * not, then it's not our fault), but if we were passed in a null,
2608  * then every field which we don't populate needs to be run through
2609  * the input function just in case it's a domain type.
2610  */
2611  if (v == NULL && rec)
2612  continue;
2613 
2614  /*
2615  * Prepare to convert the column value from text
2616  */
2617  if (column_info->column_type != column_type)
2618  {
2619  getTypeInputInfo(column_type,
2620  &column_info->typiofunc,
2621  &column_info->typioparam);
2622  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2623  state->fn_mcxt);
2624  column_info->column_type = column_type;
2625  }
2626  if (v == NULL || v->type == jbvNull)
2627  {
2628  /*
2629  * Need InputFunctionCall to happen even for nulls, so that domain
2630  * checks are done
2631  */
2632  values[i] = InputFunctionCall(&column_info->proc, NULL,
2633  column_info->typioparam,
2634  tupdesc->attrs[i]->atttypmod);
2635  nulls[i] = true;
2636  }
2637  else
2638  {
2639  char *s = NULL;
2640 
2641  if (v->type == jbvString)
2642  s = pnstrdup(v->val.string.val, v->val.string.len);
2643  else if (v->type == jbvBool)
2644  s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2645  else if (v->type == jbvNumeric)
2647  PointerGetDatum(v->val.numeric)));
2648  else if (v->type == jbvBinary)
2649  s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2650  else
2651  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2652 
2653  values[i] = InputFunctionCall(&column_info->proc, s,
2654  column_info->typioparam,
2655  tupdesc->attrs[i]->atttypmod);
2656  nulls[i] = false;
2657  }
2658  }
2659 
2660  rettuple = heap_form_tuple(tupdesc, values, nulls);
2661 
2662  tuplestore_puttuple(state->tuple_store, rettuple);
2663 }
2664 
2665 /*
2666  * common worker for json_populate_recordset() and json_to_recordset()
2667  */
2668 static Datum
2669 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
2670  bool have_record_arg)
2671 {
2672  int json_arg_num = have_record_arg ? 1 : 0;
2673  Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2674  ReturnSetInfo *rsi;
2675  MemoryContext old_cxt;
2676  Oid tupType;
2677  int32 tupTypmod;
2678  HeapTupleHeader rec;
2679  TupleDesc tupdesc;
2680  RecordIOData *my_extra;
2681  int ncolumns;
2683 
2684  if (have_record_arg)
2685  {
2686  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2687 
2688  if (!type_is_rowtype(argtype))
2689  ereport(ERROR,
2690  (errcode(ERRCODE_DATATYPE_MISMATCH),
2691  errmsg("first argument of %s must be a row type",
2692  funcname)));
2693  }
2694 
2695  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2696 
2697  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2698  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2699  rsi->expectedDesc == NULL)
2700  ereport(ERROR,
2701  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2702  errmsg("set-valued function called in context that "
2703  "cannot accept a set")));
2704 
2706 
2707  /*
2708  * get the tupdesc from the result set info - it must be a record type
2709  * because we already checked that arg1 is a record type, or we're in a
2710  * to_record function which returns a setof record.
2711  */
2712  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2713  ereport(ERROR,
2714  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2715  errmsg("function returning record called in context "
2716  "that cannot accept type record")));
2717 
2718  /* if the json is null send back an empty set */
2719  if (PG_ARGISNULL(json_arg_num))
2720  PG_RETURN_NULL();
2721 
2722  if (!have_record_arg || PG_ARGISNULL(0))
2723  rec = NULL;
2724  else
2725  rec = PG_GETARG_HEAPTUPLEHEADER(0);
2726 
2727  tupType = tupdesc->tdtypeid;
2728  tupTypmod = tupdesc->tdtypmod;
2729  ncolumns = tupdesc->natts;
2730 
2731  /*
2732  * We arrange to look up the needed I/O info just once per series of
2733  * calls, assuming the record type doesn't change underneath us.
2734  */
2735  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2736  if (my_extra == NULL ||
2737  my_extra->ncolumns != ncolumns)
2738  {
2739  fcinfo->flinfo->fn_extra =
2741  offsetof(RecordIOData, columns) +
2742  ncolumns * sizeof(ColumnIOData));
2743  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2744  my_extra->record_type = InvalidOid;
2745  my_extra->record_typmod = 0;
2746  }
2747 
2748  if (my_extra->record_type != tupType ||
2749  my_extra->record_typmod != tupTypmod)
2750  {
2751  MemSet(my_extra, 0,
2752  offsetof(RecordIOData, columns) +
2753  ncolumns * sizeof(ColumnIOData));
2754  my_extra->record_type = tupType;
2755  my_extra->record_typmod = tupTypmod;
2756  my_extra->ncolumns = ncolumns;
2757  }
2758 
2759  state = palloc0(sizeof(PopulateRecordsetState));
2760 
2761  /* make these in a sufficiently long-lived memory context */
2763  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2764  BlessTupleDesc(state->ret_tdesc);
2767  false, work_mem);
2768  MemoryContextSwitchTo(old_cxt);
2769 
2770  state->function_name = funcname;
2771  state->my_extra = my_extra;
2772  state->rec = rec;
2773  state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2774 
2775  if (jtype == JSONOID)
2776  {
2777  text *json = PG_GETARG_TEXT_P(json_arg_num);
2778  JsonLexContext *lex;
2779  JsonSemAction *sem;
2780 
2781  sem = palloc0(sizeof(JsonSemAction));
2782 
2783  lex = makeJsonLexContext(json, true);
2784 
2785  sem->semstate = (void *) state;
2793 
2794  state->lex = lex;
2795 
2796  pg_parse_json(lex, sem);
2797  }
2798  else
2799  {
2800  Jsonb *jb = PG_GETARG_JSONB(json_arg_num);
2801  JsonbIterator *it;
2802  JsonbValue v;
2803  bool skipNested = false;
2805 
2806  Assert(jtype == JSONBOID);
2807 
2808  if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2809  ereport(ERROR,
2810  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2811  errmsg("cannot call %s on a non-array",
2812  funcname)));
2813 
2814  it = JsonbIteratorInit(&jb->root);
2815 
2816  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2817  {
2818  skipNested = true;
2819 
2820  if (r == WJB_ELEM)
2821  {
2823 
2824  if (!JB_ROOT_IS_OBJECT(element))
2825  ereport(ERROR,
2826  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2827  errmsg("argument of %s must be an array of objects",
2828  funcname)));
2829  make_row_from_rec_and_jsonb(element, state);
2830  }
2831  }
2832  }
2833 
2834  rsi->setResult = state->tuple_store;
2835  rsi->setDesc = state->ret_tdesc;
2836 
2837  PG_RETURN_NULL();
2838 }
2839 
2840 static void
2842 {
2843  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2844  int lex_level = _state->lex->lex_level;
2845  HASHCTL ctl;
2846 
2847  /* Reject object at top level: we must have an array at level 0 */
2848  if (lex_level == 0)
2849  ereport(ERROR,
2850  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2851  errmsg("cannot call %s on an object",
2852  _state->function_name)));
2853 
2854  /* Nested objects require no special processing */
2855  if (lex_level > 1)
2856  return;
2857 
2858  /* Object at level 1: set up a new hash table for this object */
2859  memset(&ctl, 0, sizeof(ctl));
2860  ctl.keysize = NAMEDATALEN;
2861  ctl.entrysize = sizeof(JsonHashEntry);
2862  ctl.hcxt = CurrentMemoryContext;
2863  _state->json_hash = hash_create("json object hashtable",
2864  100,
2865  &ctl,
2867 }
2868 
2869 static void
2871 {
2872  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2873  HTAB *json_hash = _state->json_hash;
2874  Datum *values;
2875  bool *nulls;
2876  int i;
2877  RecordIOData *my_extra = _state->my_extra;
2878  int ncolumns = my_extra->ncolumns;
2879  TupleDesc tupdesc = _state->ret_tdesc;
2880  JsonHashEntry *hashentry;
2881  HeapTupleHeader rec = _state->rec;
2882  HeapTuple rettuple;
2883 
2884  /* Nested objects require no special processing */
2885  if (_state->lex->lex_level > 1)
2886  return;
2887 
2888  /* Otherwise, construct and return a tuple based on this level-1 object */
2889  values = (Datum *) palloc(ncolumns * sizeof(Datum));
2890  nulls = (bool *) palloc(ncolumns * sizeof(bool));
2891 
2892  if (_state->rec)
2893  {
2894  HeapTupleData tuple;
2895 
2896  /* Build a temporary HeapTuple control structure */
2897  tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2898  ItemPointerSetInvalid(&(tuple.t_self));
2899  tuple.t_tableOid = InvalidOid;
2900  tuple.t_data = _state->rec;
2901 
2902  /* Break down the tuple into fields */
2903  heap_deform_tuple(&tuple, tupdesc, values, nulls);
2904  }
2905  else
2906  {
2907  for (i = 0; i < ncolumns; ++i)
2908  {
2909  values[i] = (Datum) 0;
2910  nulls[i] = true;
2911  }
2912  }
2913 
2914  for (i = 0; i < ncolumns; ++i)
2915  {
2916  ColumnIOData *column_info = &my_extra->columns[i];
2917  Oid column_type = tupdesc->attrs[i]->atttypid;
2918  char *value;
2919 
2920  /* Ignore dropped columns in datatype */
2921  if (tupdesc->attrs[i]->attisdropped)
2922  {
2923  nulls[i] = true;
2924  continue;
2925  }
2926 
2927  hashentry = hash_search(json_hash,
2928  NameStr(tupdesc->attrs[i]->attname),
2929  HASH_FIND, NULL);
2930 
2931  /*
2932  * we can't just skip here if the key wasn't found since we might have
2933  * a domain to deal with. If we were passed in a non-null record
2934  * datum, we assume that the existing values are valid (if they're
2935  * not, then it's not our fault), but if we were passed in a null,
2936  * then every field which we don't populate needs to be run through
2937  * the input function just in case it's a domain type.
2938  */
2939  if (hashentry == NULL && rec)
2940  continue;
2941 
2942  /*
2943  * Prepare to convert the column value from text
2944  */
2945  if (column_info->column_type != column_type)
2946  {
2947  getTypeInputInfo(column_type,
2948  &column_info->typiofunc,
2949  &column_info->typioparam);
2950  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2951  _state->fn_mcxt);
2952  column_info->column_type = column_type;
2953  }
2954  if (hashentry == NULL || hashentry->isnull)
2955  {
2956  /*
2957  * need InputFunctionCall to happen even for nulls, so that domain
2958  * checks are done
2959  */
2960  values[i] = InputFunctionCall(&column_info->proc, NULL,
2961  column_info->typioparam,
2962  tupdesc->attrs[i]->atttypmod);
2963  nulls[i] = true;
2964  }
2965  else
2966  {
2967  value = hashentry->val;
2968 
2969  values[i] = InputFunctionCall(&column_info->proc, value,
2970  column_info->typioparam,
2971  tupdesc->attrs[i]->atttypmod);
2972  nulls[i] = false;
2973  }
2974  }
2975 
2976  rettuple = heap_form_tuple(tupdesc, values, nulls);
2977 
2978  tuplestore_puttuple(_state->tuple_store, rettuple);
2979 
2980  /* Done with hash for this object */
2981  hash_destroy(json_hash);
2982  _state->json_hash = NULL;
2983 }
2984 
2985 static void
2987 {
2988  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2989 
2990  if (_state->lex->lex_level == 1 &&
2992  ereport(ERROR,
2993  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2994  errmsg("argument of %s must be an array of objects",
2995  _state->function_name)));
2996 }
2997 
2998 static void
3000 {
3001  /* nothing to do */
3002 }
3003 
3004 static void
3005 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
3006 {
3007  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3008 
3009  if (_state->lex->lex_level == 0)
3010  ereport(ERROR,
3011  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3012  errmsg("cannot call %s on a scalar",
3013  _state->function_name)));
3014 
3015  if (_state->lex->lex_level == 2)
3016  _state->saved_scalar = token;
3017 }
3018 
3019 static void
3020 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
3021 {
3022  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3023 
3024  if (_state->lex->lex_level > 2)
3025  return;
3026 
3027  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3029  {
3030  _state->save_json_start = _state->lex->token_start;
3031  }
3032  else
3033  {
3034  _state->save_json_start = NULL;
3035  }
3036 }
3037 
3038 static void
3039 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
3040 {
3041  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3042  JsonHashEntry *hashentry;
3043  bool found;
3044 
3045  /*
3046  * Ignore nested fields.
3047  */
3048  if (_state->lex->lex_level > 2)
3049  return;
3050 
3051  /*
3052  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3053  * (Note: without this test, the hash code would truncate the string at
3054  * NAMEDATALEN-1, and could then match against a similarly-truncated
3055  * record field name. That would be a reasonable behavior, but this code
3056  * has previously insisted on exact equality, so we keep this behavior.)
3057  */
3058  if (strlen(fname) >= NAMEDATALEN)
3059  return;
3060 
3061  hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
3062 
3063  /*
3064  * found being true indicates a duplicate. We don't do anything about
3065  * that, a later field with the same name overrides the earlier field.
3066  */
3067 
3068  hashentry->isnull = isnull;
3069  if (_state->save_json_start != NULL)
3070  {
3071  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3072  char *val = palloc((len + 1) * sizeof(char));
3073 
3074  memcpy(val, _state->save_json_start, len);
3075  val[len] = '\0';
3076  hashentry->val = val;
3077  }
3078  else
3079  {
3080  /* must have had a scalar instead */
3081  hashentry->val = _state->saved_scalar;
3082  }
3083 }
3084 
3085 /*
3086  * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3087  */
3088 static JsonbValue *
3090  char *key, uint32 keylen)
3091 {
3092  JsonbValue k;
3093 
3094  k.type = jbvString;
3095  k.val.string.val = key;
3096  k.val.string.len = keylen;
3097 
3098  return findJsonbValueFromContainer(container, flags, &k);
3099 }
3100 
3101 /*
3102  * Semantic actions for json_strip_nulls.
3103  *
3104  * Simply repeat the input on the output unless we encounter
3105  * a null object field. State for this is set when the field
3106  * is started and reset when the scalar action (which must be next)
3107  * is called.
3108  */
3109 
3110 static void
3112 {
3113  StripnullState *_state = (StripnullState *) state;
3114 
3115  appendStringInfoCharMacro(_state->strval, '{');
3116 }
3117 
3118 static void
3120 {
3121  StripnullState *_state = (StripnullState *) state;
3122 
3123  appendStringInfoCharMacro(_state->strval, '}');
3124 }
3125 
3126 static void
3128 {
3129  StripnullState *_state = (StripnullState *) state;
3130 
3131  appendStringInfoCharMacro(_state->strval, '[');
3132 }
3133 
3134 static void
3136 {
3137  StripnullState *_state = (StripnullState *) state;
3138 
3139  appendStringInfoCharMacro(_state->strval, ']');
3140 }
3141 
3142 static void
3143 sn_object_field_start(void *state, char *fname, bool isnull)
3144 {
3145  StripnullState *_state = (StripnullState *) state;
3146 
3147  if (isnull)
3148  {
3149  /*
3150  * The next thing must be a scalar or isnull couldn't be true, so
3151  * there is no danger of this state being carried down into a nested
3152  * object or array. The flag will be reset in the scalar action.
3153  */
3154  _state->skip_next_null = true;
3155  return;
3156  }
3157 
3158  if (_state->strval->data[_state->strval->len - 1] != '{')
3159  appendStringInfoCharMacro(_state->strval, ',');
3160 
3161  /*
3162  * Unfortunately we don't have the quoted and escaped string any more, so
3163  * we have to re-escape it.
3164  */
3165  escape_json(_state->strval, fname);
3166 
3167  appendStringInfoCharMacro(_state->strval, ':');
3168 }
3169 
3170 static void
3171 sn_array_element_start(void *state, bool isnull)
3172 {
3173  StripnullState *_state = (StripnullState *) state;
3174 
3175  if (_state->strval->data[_state->strval->len - 1] != '[')
3176  appendStringInfoCharMacro(_state->strval, ',');
3177 }
3178 
3179 static void
3180 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3181 {
3182  StripnullState *_state = (StripnullState *) state;
3183 
3184  if (_state->skip_next_null)
3185  {
3186  Assert(tokentype == JSON_TOKEN_NULL);
3187  _state->skip_next_null = false;
3188  return;
3189  }
3190 
3191  if (tokentype == JSON_TOKEN_STRING)
3192  escape_json(_state->strval, token);
3193  else
3194  appendStringInfoString(_state->strval, token);
3195 }
3196 
3197 /*
3198  * SQL function json_strip_nulls(json) -> json
3199  */
3200 Datum
3202 {
3203  text *json = PG_GETARG_TEXT_P(0);
3205  JsonLexContext *lex;
3206  JsonSemAction *sem;
3207 
3208  lex = makeJsonLexContext(json, true);
3209  state = palloc0(sizeof(StripnullState));
3210  sem = palloc0(sizeof(JsonSemAction));
3211 
3212  state->strval = makeStringInfo();
3213  state->skip_next_null = false;
3214  state->lex = lex;
3215 
3216  sem->semstate = (void *) state;
3218  sem->object_end = sn_object_end;
3219  sem->array_start = sn_array_start;
3220  sem->array_end = sn_array_end;
3221  sem->scalar = sn_scalar;
3224 
3225  pg_parse_json(lex, sem);
3226 
3228  state->strval->len));
3229 
3230 }
3231 
3232 /*
3233  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
3234  */
3235 Datum
3237 {
3238  Jsonb *jb = PG_GETARG_JSONB(0);
3239  JsonbIterator *it;
3240  JsonbParseState *parseState = NULL;
3241  JsonbValue *res = NULL;
3242  JsonbValue v,
3243  k;
3244  JsonbIteratorToken type;
3245  bool last_was_key = false;
3246 
3247  if (JB_ROOT_IS_SCALAR(jb))
3248  PG_RETURN_POINTER(jb);
3249 
3250  it = JsonbIteratorInit(&jb->root);
3251 
3252  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3253  {
3254  Assert(!(type == WJB_KEY && last_was_key));
3255 
3256  if (type == WJB_KEY)
3257  {
3258  /* stash the key until we know if it has a null value */
3259  k = v;
3260  last_was_key = true;
3261  continue;
3262  }
3263 
3264  if (last_was_key)
3265  {
3266  /* if the last element was a key this one can't be */
3267  last_was_key = false;
3268 
3269  /* skip this field if value is null */
3270  if (type == WJB_VALUE && v.type == jbvNull)
3271  continue;
3272 
3273  /* otherwise, do a delayed push of the key */
3274  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3275  }
3276 
3277  if (type == WJB_VALUE || type == WJB_ELEM)
3278  res = pushJsonbValue(&parseState, type, &v);
3279  else
3280  res = pushJsonbValue(&parseState, type, NULL);
3281  }
3282 
3283  Assert(res != NULL);
3284 
3286 }
3287 
3288 /*
3289  * Add values from the jsonb to the parse state.
3290  *
3291  * If the parse state container is an object, the jsonb is pushed as
3292  * a value, not a key.
3293  *
3294  * This needs to be done using an iterator because pushJsonbValue doesn't
3295  * like getting jbvBinary values, so we can't just push jb as a whole.
3296  */
3297 static void
3299 {
3300  JsonbIterator *it;
3301  JsonbValue *o = &(*jbps)->contVal;
3302  JsonbValue v;
3303  JsonbIteratorToken type;
3304 
3305  it = JsonbIteratorInit(&jb->root);
3306 
3307  Assert(o->type == jbvArray || o->type == jbvObject);
3308 
3309  if (JB_ROOT_IS_SCALAR(jb))
3310  {
3311  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3312  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3313 
3314  switch (o->type)
3315  {
3316  case jbvArray:
3317  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3318  break;
3319  case jbvObject:
3320  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3321  break;
3322  default:
3323  elog(ERROR, "unexpected parent of nested structure");
3324  }
3325  }
3326  else
3327  {
3328  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3329  {
3330  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3331  (void) pushJsonbValue(jbps, type, &v);
3332  else
3333  (void) pushJsonbValue(jbps, type, NULL);
3334  }
3335  }
3336 
3337 }
3338 
3339 /*
3340  * SQL function jsonb_pretty (jsonb)
3341  *
3342  * Pretty-printed text for the jsonb
3343  */
3344 Datum
3346 {
3347  Jsonb *jb = PG_GETARG_JSONB(0);
3348  StringInfo str = makeStringInfo();
3349 
3350  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3351 
3353 }
3354 
3355 /*
3356  * SQL function jsonb_concat (jsonb, jsonb)
3357  *
3358  * function for || operator
3359  */
3360 Datum
3362 {
3363  Jsonb *jb1 = PG_GETARG_JSONB(0);
3364  Jsonb *jb2 = PG_GETARG_JSONB(1);
3366  JsonbValue *res;
3367  JsonbIterator *it1,
3368  *it2;
3369 
3370  /*
3371  * If one of the jsonb is empty, just return the other if it's not scalar
3372  * and both are of the same kind. If it's a scalar or they are of
3373  * different kinds we need to perform the concatenation even if one is
3374  * empty.
3375  */
3376  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
3377  {
3378  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
3379  PG_RETURN_JSONB(jb2);
3380  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
3381  PG_RETURN_JSONB(jb1);
3382  }
3383 
3384  it1 = JsonbIteratorInit(&jb1->root);
3385  it2 = JsonbIteratorInit(&jb2->root);
3386 
3387  res = IteratorConcat(&it1, &it2, &state);
3388 
3389  Assert(res != NULL);
3390 
3392 }
3393 
3394 
3395 /*
3396  * SQL function jsonb_delete (jsonb, text)
3397  *
3398  * return a copy of the jsonb with the indicated item
3399  * removed.
3400  */
3401 Datum
3403 {
3404  Jsonb *in = PG_GETARG_JSONB(0);
3405  text *key = PG_GETARG_TEXT_PP(1);
3406  char *keyptr = VARDATA_ANY(key);
3407  int keylen = VARSIZE_ANY_EXHDR(key);
3409  JsonbIterator *it;
3410  JsonbValue v,
3411  *res = NULL;
3412  bool skipNested = false;
3414 
3415  if (JB_ROOT_IS_SCALAR(in))
3416  ereport(ERROR,
3417  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3418  errmsg("cannot delete from scalar")));
3419 
3420  if (JB_ROOT_COUNT(in) == 0)
3421  PG_RETURN_JSONB(in);
3422 
3423  it = JsonbIteratorInit(&in->root);
3424 
3425  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3426  {
3427  skipNested = true;
3428 
3429  if ((r == WJB_ELEM || r == WJB_KEY) &&
3430  (v.type == jbvString && keylen == v.val.string.len &&
3431  memcmp(keyptr, v.val.string.val, keylen) == 0))
3432  {
3433  /* skip corresponding value as well */
3434  if (r == WJB_KEY)
3435  JsonbIteratorNext(&it, &v, true);
3436 
3437  continue;
3438  }
3439 
3440  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3441  }
3442 
3443  Assert(res != NULL);
3444 
3446 }
3447 
3448 /*
3449  * SQL function jsonb_delete (jsonb, int)
3450  *
3451  * return a copy of the jsonb with the indicated item
3452  * removed. Negative int means count back from the
3453  * end of the items.
3454  */
3455 Datum
3457 {
3458  Jsonb *in = PG_GETARG_JSONB(0);
3459  int idx = PG_GETARG_INT32(1);
3461  JsonbIterator *it;
3462  uint32 i = 0,
3463  n;
3464  JsonbValue v,
3465  *res = NULL;
3467 
3468  if (JB_ROOT_IS_SCALAR(in))
3469  ereport(ERROR,
3470  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3471  errmsg("cannot delete from scalar")));
3472 
3473  if (JB_ROOT_IS_OBJECT(in))
3474  ereport(ERROR,
3475  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3476  errmsg("cannot delete from object using integer index")));
3477 
3478  if (JB_ROOT_COUNT(in) == 0)
3479  PG_RETURN_JSONB(in);
3480 
3481  it = JsonbIteratorInit(&in->root);
3482 
3483  r = JsonbIteratorNext(&it, &v, false);
3484  Assert(r == WJB_BEGIN_ARRAY);
3485  n = v.val.array.nElems;
3486 
3487  if (idx < 0)
3488  {
3489  if (-idx > n)
3490  idx = n;
3491  else
3492  idx = n + idx;
3493  }
3494 
3495  if (idx >= n)
3496  PG_RETURN_JSONB(in);
3497 
3498  pushJsonbValue(&state, r, NULL);
3499 
3500  while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3501  {
3502  if (r == WJB_ELEM)
3503  {
3504  if (i++ == idx)
3505  continue;
3506  }
3507 
3508  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3509  }
3510 
3511  Assert(res != NULL);
3512 
3514 }
3515 
3516 /*
3517  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
3518  *
3519  */
3520 Datum
3522 {
3523  Jsonb *in = PG_GETARG_JSONB(0);
3524  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3526  bool create = PG_GETARG_BOOL(3);
3527  JsonbValue *res = NULL;
3528  Datum *path_elems;
3529  bool *path_nulls;
3530  int path_len;
3531  JsonbIterator *it;
3532  JsonbParseState *st = NULL;
3533 
3534  if (ARR_NDIM(path) > 1)
3535  ereport(ERROR,
3536  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3537  errmsg("wrong number of array subscripts")));
3538 
3539  if (JB_ROOT_IS_SCALAR(in))
3540  ereport(ERROR,
3541  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3542  errmsg("cannot set path in scalar")));
3543 
3544  if (JB_ROOT_COUNT(in) == 0 && !create)
3545  PG_RETURN_JSONB(in);
3546 
3547  deconstruct_array(path, TEXTOID, -1, false, 'i',
3548  &path_elems, &path_nulls, &path_len);
3549 
3550  if (path_len == 0)
3551  PG_RETURN_JSONB(in);
3552 
3553  it = JsonbIteratorInit(&in->root);
3554 
3555  res = setPath(&it, path_elems, path_nulls, path_len, &st,
3556  0, newval, create ? JB_PATH_CREATE : JB_PATH_NOOP);
3557 
3558  Assert(res != NULL);
3559 
3561 }
3562 
3563 
3564 /*
3565  * SQL function jsonb_delete(jsonb, text[])
3566  */
3567 Datum
3569 {
3570  Jsonb *in = PG_GETARG_JSONB(0);
3571  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3572  JsonbValue *res = NULL;
3573  Datum *path_elems;
3574  bool *path_nulls;
3575  int path_len;
3576  JsonbIterator *it;
3577  JsonbParseState *st = NULL;
3578 
3579  if (ARR_NDIM(path) > 1)
3580  ereport(ERROR,
3581  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3582  errmsg("wrong number of array subscripts")));
3583 
3584  if (JB_ROOT_IS_SCALAR(in))
3585  ereport(ERROR,
3586  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3587  errmsg("cannot delete path in scalar")));
3588 
3589  if (JB_ROOT_COUNT(in) == 0)
3590  PG_RETURN_JSONB(in);
3591 
3592  deconstruct_array(path, TEXTOID, -1, false, 'i',
3593  &path_elems, &path_nulls, &path_len);
3594 
3595  if (path_len == 0)
3596  PG_RETURN_JSONB(in);
3597 
3598  it = JsonbIteratorInit(&in->root);
3599 
3600  res = setPath(&it, path_elems, path_nulls, path_len, &st,
3601  0, NULL, JB_PATH_DELETE);
3602 
3603  Assert(res != NULL);
3604 
3606 }
3607 
3608 /*
3609  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
3610  *
3611  */
3612 Datum
3614 {
3615  Jsonb *in = PG_GETARG_JSONB(0);
3616  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3618  bool after = PG_GETARG_BOOL(3);
3619  JsonbValue *res = NULL;
3620  Datum *path_elems;
3621  bool *path_nulls;
3622  int path_len;
3623  JsonbIterator *it;
3624  JsonbParseState *st = NULL;
3625 
3626  if (ARR_NDIM(path) > 1)
3627  ereport(ERROR,
3628  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3629  errmsg("wrong number of array subscripts")));
3630 
3631  if (JB_ROOT_IS_SCALAR(in))
3632  ereport(ERROR,
3633  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3634  errmsg("cannot set path in scalar")));
3635 
3636  deconstruct_array(path, TEXTOID, -1, false, 'i',
3637  &path_elems, &path_nulls, &path_len);
3638 
3639  if (path_len == 0)
3640  PG_RETURN_JSONB(in);
3641 
3642  it = JsonbIteratorInit(&in->root);
3643 
3644  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
3646 
3647  Assert(res != NULL);
3648 
3650 }
3651 
3652 /*
3653  * Iterate over all jsonb objects and merge them into one.
3654  * The logic of this function copied from the same hstore function,
3655  * except the case, when it1 & it2 represents jbvObject.
3656  * In that case we just append the content of it2 to it1 without any
3657  * verifications.
3658  */
3659 static JsonbValue *
3662 {
3663  JsonbValue v1,
3664  v2,
3665  *res = NULL;
3666  JsonbIteratorToken r1,
3667  r2,
3668  rk1,
3669  rk2;
3670 
3671  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3672  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3673 
3674  /*
3675  * Both elements are objects.
3676  */
3677  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3678  {
3679  /*
3680  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3681  * (because res will not be finished yet).
3682  */
3683  pushJsonbValue(state, r1, NULL);
3684  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3685  pushJsonbValue(state, r1, &v1);
3686 
3687  /*
3688  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3689  * (the concatenation will be completed).
3690  */
3691  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3692  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3693  }
3694 
3695  /*
3696  * Both elements are arrays (either can be scalar).
3697  */
3698  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3699  {
3700  pushJsonbValue(state, r1, NULL);
3701 
3702  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3703  {
3704  Assert(r1 == WJB_ELEM);
3705  pushJsonbValue(state, r1, &v1);
3706  }
3707 
3708  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
3709  {
3710  Assert(r2 == WJB_ELEM);
3711  pushJsonbValue(state, WJB_ELEM, &v2);
3712  }
3713 
3714  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
3715  }
3716  /* have we got array || object or object || array? */
3717  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3718  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3719  {
3720 
3721  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3722  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3723 
3724  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
3725 
3727 
3728  if (prepend)
3729  {
3731  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3732  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
3733 
3734  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3735  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
3736  }
3737  else
3738  {
3739  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3740  pushJsonbValue(state, r1, &v1);
3741 
3743  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3744  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3745 
3746  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3747  }
3748  }
3749  else
3750  {
3751  /*
3752  * This must be scalar || object or object || scalar, as that's all
3753  * that's left. Both of these make no sense, so error out.
3754  */
3755  ereport(ERROR,
3756  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3757  errmsg("invalid concatenation of jsonb objects")));
3758  }
3759 
3760  return res;
3761 }
3762 
3763 /*
3764  * Do most of the heavy work for jsonb_set/jsonb_insert
3765  *
3766  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
3767  *
3768  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
3769  * we create the new value if the key or array index does not exist.
3770  *
3771  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
3772  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
3773  *
3774  * All path elements before the last must already exist
3775  * whatever bits in op_type are set, or nothing is done.
3776  */
3777 static JsonbValue *
3778 setPath(JsonbIterator **it, Datum *path_elems,
3779  bool *path_nulls, int path_len,
3780  JsonbParseState **st, int level, Jsonb *newval, int op_type)
3781 {
3782  JsonbValue v;
3784  JsonbValue *res;
3785 
3787 
3788  if (path_nulls[level])
3789  ereport(ERROR,
3790  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3791  errmsg("path element at position %d is null",
3792  level + 1)));
3793 
3794  r = JsonbIteratorNext(it, &v, false);
3795 
3796  switch (r)
3797  {
3798  case WJB_BEGIN_ARRAY:
3799  (void) pushJsonbValue(st, r, NULL);
3800  setPathArray(it, path_elems, path_nulls, path_len, st, level,
3801  newval, v.val.array.nElems, op_type);
3802  r = JsonbIteratorNext(it, &v, false);
3803  Assert(r == WJB_END_ARRAY);
3804  res = pushJsonbValue(st, r, NULL);
3805  break;
3806  case WJB_BEGIN_OBJECT:
3807  (void) pushJsonbValue(st, r, NULL);
3808  setPathObject(it, path_elems, path_nulls, path_len, st, level,
3809  newval, v.val.object.nPairs, op_type);
3810  r = JsonbIteratorNext(it, &v, true);
3811  Assert(r == WJB_END_OBJECT);
3812  res = pushJsonbValue(st, r, NULL);
3813  break;
3814  case WJB_ELEM:
3815  case WJB_VALUE:
3816  res = pushJsonbValue(st, r, &v);
3817  break;
3818  default:
3819  elog(ERROR, "unrecognized iterator result: %d", (int) r);
3820  res = NULL; /* keep compiler quiet */
3821  break;
3822  }
3823 
3824  return res;
3825 }
3826 
3827 /*
3828  * Object walker for setPath
3829  */
3830 static void
3831 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3832  int path_len, JsonbParseState **st, int level,
3833  Jsonb *newval, uint32 npairs, int op_type)
3834 {
3835  JsonbValue v;
3836  int i;
3837  JsonbValue k;
3838  bool done = false;
3839 
3840  if (level >= path_len || path_nulls[level])
3841  done = true;
3842 
3843  /* empty object is a special case for create */
3844  if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
3845  (level == path_len - 1))
3846  {
3847  JsonbValue newkey;
3848 
3849  newkey.type = jbvString;
3850  newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3851  newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3852 
3853  (void) pushJsonbValue(st, WJB_KEY, &newkey);
3854  addJsonbToParseState(st, newval);
3855  }
3856 
3857  for (i = 0; i < npairs; i++)
3858  {
3859  JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
3860 
3861  Assert(r == WJB_KEY);
3862 
3863  if (!done &&
3864  k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
3865  memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
3866  k.val.string.len) == 0)
3867  {
3868  if (level == path_len - 1)
3869  {
3870  /*
3871  * called from jsonb_insert(), it forbids redefining an
3872  * existsing value
3873  */
3874  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
3875  ereport(ERROR,
3876  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3877  errmsg("cannot replace existing key"),
3878  errhint("Try using the function jsonb_set "
3879  "to replace key value.")));
3880 
3881  r = JsonbIteratorNext(it, &v, true); /* skip value */
3882  if (!(op_type & JB_PATH_DELETE))
3883  {
3884  (void) pushJsonbValue(st, WJB_KEY, &k);
3885  addJsonbToParseState(st, newval);
3886  }
3887  done = true;
3888  }
3889  else
3890  {
3891  (void) pushJsonbValue(st, r, &k);
3892  setPath(it, path_elems, path_nulls, path_len,
3893  st, level + 1, newval, op_type);
3894  }
3895  }
3896  else
3897  {
3898  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
3899  level == path_len - 1 && i == npairs - 1)
3900  {
3901  JsonbValue newkey;
3902 
3903  newkey.type = jbvString;
3904  newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3905  newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3906 
3907  (void) pushJsonbValue(st, WJB_KEY, &newkey);
3908  addJsonbToParseState(st, newval);
3909  }
3910 
3911  (void) pushJsonbValue(st, r, &k);
3912  r = JsonbIteratorNext(it, &v, false);
3913  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3914  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3915  {
3916  int walking_level = 1;
3917 
3918  while (walking_level != 0)
3919  {
3920  r = JsonbIteratorNext(it, &v, false);
3921 
3922  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3923  ++walking_level;
3924  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
3925  --walking_level;
3926 
3927  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3928  }
3929  }
3930  }
3931  }
3932 }
3933 
3934 /*
3935  * Array walker for setPath
3936  */
3937 static void
3938 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3939  int path_len, JsonbParseState **st, int level,
3940  Jsonb *newval, uint32 nelems, int op_type)
3941 {
3942  JsonbValue v;
3943  int idx,
3944  i;
3945  bool done = false;
3946 
3947  /* pick correct index */
3948  if (level < path_len && !path_nulls[level])
3949  {
3950  char *c = TextDatumGetCString(path_elems[level]);
3951  long lindex;
3952  char *badp;
3953 
3954  errno = 0;
3955  lindex = strtol(c, &badp, 10);
3956  if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
3957  lindex < INT_MIN)
3958  ereport(ERROR,
3959  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3960  errmsg("path element at position %d is not an integer: \"%s\"",
3961  level + 1, c)));
3962  idx = lindex;
3963  }
3964  else
3965  idx = nelems;
3966 
3967  if (idx < 0)
3968  {
3969  if (-idx > nelems)
3970  idx = INT_MIN;
3971  else
3972  idx = nelems + idx;
3973  }
3974 
3975  if (idx > 0 && idx > nelems)
3976  idx = nelems;
3977 
3978  /*
3979  * if we're creating, and idx == INT_MIN, we prepend the new value to the
3980  * array also if the array is empty - in which case we don't really care
3981  * what the idx value is
3982  */
3983 
3984  if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
3985  (op_type & JB_PATH_CREATE_OR_INSERT))
3986  {
3987  Assert(newval != NULL);
3988  addJsonbToParseState(st, newval);
3989  done = true;
3990  }
3991 
3992  /* iterate over the array elements */
3993  for (i = 0; i < nelems; i++)
3994  {
3996 
3997  if (i == idx && level < path_len)
3998  {
3999  if (level == path_len - 1)
4000  {
4001  r = JsonbIteratorNext(it, &v, true); /* skip */
4002 
4003  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
4004  addJsonbToParseState(st, newval);
4005 
4006  /*
4007  * We should keep current value only in case of
4008  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
4009  * otherwise it should be deleted or replaced
4010  */
4011  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
4012  (void) pushJsonbValue(st, r, &v);
4013 
4014  if (op_type & JB_PATH_INSERT_AFTER)
4015  addJsonbToParseState(st, newval);
4016 
4017  done = true;
4018  }
4019  else
4020  (void) setPath(it, path_elems, path_nulls, path_len,
4021  st, level + 1, newval, op_type);
4022  }
4023  else
4024  {
4025  r = JsonbIteratorNext(it, &v, false);
4026 
4027  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4028 
4029  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4030  {
4031  int walking_level = 1;
4032 
4033  while (walking_level != 0)
4034  {
4035  r = JsonbIteratorNext(it, &v, false);
4036 
4037  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4038  ++walking_level;
4039  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4040  --walking_level;
4041 
4042  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4043  }
4044  }
4045 
4046  if (op_type & JB_PATH_CREATE_OR_INSERT && !done &&
4047  level == path_len - 1 && i == nelems - 1)
4048  {
4049  addJsonbToParseState(st, newval);
4050  }
4051  }
4052  }
4053 }
json_struct_action array_end
Definition: jsonapi.h:87
static void get_array_end(void *state)
Definition: jsonfuncs.c:1013
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1774
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
static void populate_recordset_object_start(void *state)
Definition: jsonfuncs.c:2841
Datum jsonb_array_elements(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1762
int result_count
Definition: jsonfuncs.c:158
bool normalize_results
Definition: jsonfuncs.c:206
struct JhashState JHashState
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
Definition: fmgr.h:53
Datum jsonb_array_length(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1366
static struct @76 value
bool skip_next_null
Definition: jsonfuncs.c:267
FmgrInfo proc
Definition: hstore_io.c:742
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:795
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:140
#define IsA(nodeptr, _type_)
Definition: nodes.h:543
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:188
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:203
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:218
Oid tdtypeid
Definition: tupdesc.h:77
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1660
const char * function_name
Definition: jsonfuncs.c:201
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:212
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:3938
int errhint(const char *fmt,...)
Definition: elog.c:987
#define JB_FARRAY
Definition: jsonb.h:206
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1179
int * array_cur_index
Definition: jsonfuncs.c:174
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:78
JsonLexContext * lex
Definition: jsonfuncs.c:200
Definition: jsonb.h:209
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3111
MemoryContext fn_mcxt
Definition: fmgr.h:62
struct RecordIOData RecordIOData
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2669
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2428
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1029
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2044
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1243
struct ColumnIOData ColumnIOData
bool next_scalar
Definition: jsonfuncs.c:207
json_struct_action object_end
Definition: jsonapi.h:85
Datum json_extract_path_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:708
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3171
MemoryContext hcxt
Definition: hsearch.h:78
Datum jsonb_object_keys(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:287
#define JB_PATH_CREATE_OR_INSERT
Definition: jsonfuncs.c:42
Oid record_type
Definition: hstore_io.c:747
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:306
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static void get_object_start(void *state)
Definition: jsonfuncs.c:853
#define PointerGetDatum(X)
Definition: postgres.h:564
#define JSONOID
Definition: pg_type.h:356
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:3778
char * pstrdup(const char *in)
Definition: mcxt.c:1168
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3143
char * val
Definition: jsonb.h:251
char * saved_scalar
Definition: jsonfuncs.c:217
Datum json_each_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1444
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
JsonTokenType token_type
Definition: jsonapi.h:57
const char * function_name
Definition: jsonfuncs.c:251
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:590
json_struct_action object_start
Definition: jsonapi.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
char * prev_token_terminator
Definition: jsonapi.h:56
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:216
Size entrysize
Definition: hsearch.h:73
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:449
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3089
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2441
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum json_strip_nulls(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3201
json_scalar_action scalar
Definition: jsonapi.h:92
#define MemSet(start, val, len)
Definition: c.h:849
Datum jsonb_strip_nulls(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3236
static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3005
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1299
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:138
static void each_array_start(void *state)
Definition: jsonfuncs.c:1726
int sent_count
Definition: jsonfuncs.c:159
int count
Definition: jsonfuncs.c:181
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
TupleDesc ret_tdesc
Definition: jsonfuncs.c:189
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:548
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
HeapTupleHeader rec
Definition: jsonfuncs.c:257
struct PopulateRecordsetState PopulateRecordsetState
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:887
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:40
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:217
#define PG_GETARG_HEAPTUPLEHEADER(n)
Definition: fmgr.h:275
unsigned int Oid
Definition: postgres_ext.h:31
struct ElementsState ElementsState
#define JB_PATH_CREATE
Definition: jsonfuncs.c:38
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:931
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
int natts
Definition: tupdesc.h:73
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:165
Datum jsonb_populate_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2524
#define JB_PATH_NOOP
Definition: jsonfuncs.c:37
int32 record_typmod
Definition: hstore_io.c:748
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:142
int32 tdtypmod
Definition: tupdesc.h:78
signed int int32
Definition: c.h:253
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:437
Datum json_array_element_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:628
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
MemoryContext tmp_cxt
Definition: jsonfuncs.c:190
char * result_start
Definition: jsonfuncs.c:191
static void get_object_end(void *state)
Definition: jsonfuncs.c:870
HeapTupleHeader t_data
Definition: htup.h:67
struct StripnullState StripnullState
Definition: type.h:90
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1738
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
#define NAMEDATALEN
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1400
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:41
char * result_start
Definition: jsonfuncs.c:167
FmgrInfo * flinfo
Definition: fmgr.h:71
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:516
Definition: dynahash.c:193
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
TupleDesc expectedDesc
Definition: execnodes.h:191
TupleDesc ret_tdesc
Definition: jsonfuncs.c:203
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:127
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pfree(void *pointer)
Definition: mcxt.c:995
Datum jsonb_array_elements_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1768
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:574
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
Datum json_array_element(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:585
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3127
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2313
char fname[NAMEDATALEN]
Definition: jsonfuncs.c:224
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:219
Datum jsonb_to_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2092
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1170
ItemPointerData t_self
Definition: htup.h:65
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
char * val
Definition: jsonfuncs.c:225
static void populate_recordset_object_end(void *state)
Definition: jsonfuncs.c:2870
JsonLexContext * lex
Definition: jsonfuncs.c:187
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1034
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
uint32 t_len
Definition: htup.h:64
char * c
Datum jsonb_array_element_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:643
text * tresult
Definition: jsonfuncs.c:166
Datum json_array_elements(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1900
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:162
Datum jsonb_object_field(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:498
int npath
Definition: jsonfuncs.c:170
void check_stack_depth(void)
Definition: postgres.c:3110
Datum jsonb_populate_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2086
int json_count_array_elements(JsonLexContext *lex)
Definition: json.c:366
JsonLexContext * lex
Definition: jsonfuncs.c:180
JsonLexContext * lex
Definition: jsonfuncs.c:250
JsonLexContext * lex
Definition: jsonfuncs.c:265
StringInfo strval
Definition: jsonapi.h:61
#define JSONBOID
Definition: pg_type.h:626
fmNodePtr resultinfo
Definition: fmgr.h:73
unsigned int uint32
Definition: c.h:265
Oid t_tableOid
Definition: htup.h:66
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3119
Datum jsonb_each_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1450
#define JB_CMASK
Definition: jsonb.h:203
Definition: jsonb.h:23
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum json_to_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2104
char * json
Definition: jsonfuncs.c:226
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:428
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2372
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:170
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2567
#define ereport(elevel, rest)
Definition: elog.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:89
JsonbIteratorToken
Definition: jsonb.h:20
JsonLexContext * lex
Definition: jsonfuncs.c:214
char * token_start
Definition: jsonapi.h:54
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1075
bool * pathok
Definition: jsonfuncs.c:173
JsonbContainer root
Definition: jsonb.h:212
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1980
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2420
bool normalize_results
Definition: jsonfuncs.c:168
Datum jsonb_concat(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3361
bool next_scalar
Definition: jsonfuncs.c:169
Datum jsonb_array_element(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:600
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:750
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
static void populate_recordset_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3039
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1117
uint32 header
Definition: jsonb.h:195
struct EachState EachState
char ** result
Definition: jsonfuncs.c:156
#define TextDatumGetCString(d)
Definition: builtins.h:807
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3568
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:436
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2000
void * palloc0(Size size)
Definition: mcxt.c:923
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2057
JsonLexContext * lex
Definition: jsonfuncs.c:155
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
static void get_array_start(void *state)
Definition: jsonfuncs.c:980
Datum json_object_field(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:482
json_aelem_action array_element_start
Definition: jsonapi.h:90
HTAB * hash
Definition: jsonfuncs.c:216
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3180
bool normalize_results
Definition: jsonfuncs.c:192
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:202
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:445
Size keysize
Definition: hsearch.h:72
int work_mem
Definition: globals.c:112
static void make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
Definition: jsonfuncs.c:2548
struct OkeysState OkeysState
Datum jsonb_each(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1438
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1893
char ** path_names
Definition: jsonfuncs.c:171
#define InvalidOid
Definition: postgres_ext.h:36
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:717
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:797
int allowedModes
Definition: execnodes.h:192
char * normalized_scalar
Definition: jsonfuncs.c:194
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
Datum json_object_field_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:518
SetFunctionReturnMode returnMode
Definition: execnodes.h:194
Datum json_array_elements_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1906
text * cstring_to_text(const char *s)
Definition: varlena.c:150
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:418
Datum jsonb_object_field_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:534
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:667
Datum json_to_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2542
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1912
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2110
char * input
Definition: jsonapi.h:52
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:717
#define JB_FOBJECT
Definition: jsonb.h:205
json_struct_action array_start
Definition: jsonapi.h:86
char * result_start
Definition: jsonfuncs.c:205
Datum json_populate_record(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2098
Definition: regguts.h:313
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
#define newval
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:462
Datum json_array_length(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1338
void * fn_extra
Definition: fmgr.h:61
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:127
Oid typioparam
Definition: hstore_io.c:741
#define ARR_NDIM(a)
Definition: array.h:271
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1024
struct JsonHashEntry JsonHashEntry
int result_size
Definition: jsonfuncs.c:157
struct AlenState AlenState
Datum json_extract_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:702
Tuplestorestate * setResult
Definition: execnodes.h:197
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:255
Datum jsonb_extract_path_text(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1164
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:867
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
static Datum values[MAXATTR]
Definition: bootstrap.c:160
MemoryContext fn_mcxt
Definition: jsonfuncs.c:259
char * text_to_cstring(const text *t)
Definition: varlena.c:183
ExprContext * econtext
Definition: execnodes.h:190
char * normalized_scalar
Definition: jsonfuncs.c:208
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:135
int * path_indexes
Definition: jsonfuncs.c:172
RecordIOData * my_extra
Definition: jsonfuncs.c:258
Datum json_each(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1432
void * user_fctx
Definition: funcapi.h:90
TupleDesc setDesc
Definition: execnodes.h:198
struct GetState GetState
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Datum jsonb_pretty(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3345
char * save_json_start
Definition: jsonfuncs.c:218
Datum jsonb_delete(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3402
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:752
Datum jsonb_to_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2530
Datum jsonb_delete_idx(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3456
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:143
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:3660
int i
static celt element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:367
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:886
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3521
#define NameStr(name)
Definition: c.h:494
#define CStringGetTextDatum(s)
Definition: builtins.h:806
StringInfo strval
Definition: jsonfuncs.c:266
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:326
MemoryContext tmp_cxt
Definition: jsonfuncs.c:204
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1388
Definition: c.h:434
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1594
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:144
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2499
json_ofield_action object_field_start
Definition: jsonapi.h:88
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1412
#define elog
Definition: elog.h:218
Datum jsonb_insert(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:3613
Datum json_populate_recordset(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:2536
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3135
static void populate_recordset_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2986
static HTAB * get_json_object_as_hash(text *json, const char *funcname)
Definition: jsonfuncs.c:2384
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
Datum jsonb_extract_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:1158
Datum json_object_keys(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:365
void * semstate
Definition: jsonapi.h:83
enum JsonbValue::@70 type
static void setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, uint32 npairs, int op_type)
Definition: jsonfuncs.c:3831
long val
Definition: informix.c:689
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1680
#define PG_RETURN_NULL()
Definition: fmgr.h:289
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:753
json_aelem_action array_element_end
Definition: jsonapi.h:91
Definition: jsonb.h:25
static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
Definition: jsonfuncs.c:3298
#define offsetof(type, field)
Definition: c.h:547
static void populate_recordset_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3020
#define JB_PATH_DELETE
Definition: jsonfuncs.c:39
Oid column_type
Definition: hstore_io.c:739
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
bool next_scalar
Definition: jsonfuncs.c:193
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1456
JsonTokenType
Definition: jsonapi.h:19
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:439
static void populate_recordset_array_start(void *state)
Definition: jsonfuncs.c:2999
static void hash_array_start(void *state)
Definition: jsonfuncs.c:2488
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
const char * function_name
Definition: jsonfuncs.c:215