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