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