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