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