1 /*-------------------------------------------------------------------------
4 * Functions to process JSON data types.
6 * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/adt/jsonfuncs.c
12 *-------------------------------------------------------------------------
19 #include "access/htup_details.h"
20 #include "catalog/pg_type.h"
23 #include "lib/stringinfo.h"
24 #include "mb/pg_wchar.h"
25 #include "miscadmin.h"
26 #include "utils/array.h"
27 #include "utils/builtins.h"
28 #include "utils/hsearch.h"
29 #include "utils/json.h"
30 #include "utils/jsonapi.h"
31 #include "utils/jsonb.h"
32 #include "utils/lsyscache.h"
33 #include "utils/memutils.h"
34 #include "utils/typcache.h"
36 /* semantic action functions for json_object_keys */
37 static void okeys_object_field_start(void *state, char *fname, bool isnull);
38 static void okeys_array_start(void *state);
39 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
41 /* semantic action functions for json_get* functions */
42 static void get_object_start(void *state);
43 static void get_object_end(void *state);
44 static void get_object_field_start(void *state, char *fname, bool isnull);
45 static void get_object_field_end(void *state, char *fname, bool isnull);
46 static void get_array_start(void *state);
47 static void get_array_end(void *state);
48 static void get_array_element_start(void *state, bool isnull);
49 static void get_array_element_end(void *state, bool isnull);
50 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
52 /* common worker function for json getter functions */
53 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
54 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
55 bool normalize_results);
56 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
58 /* semantic action functions for json_array_length */
59 static void alen_object_start(void *state);
60 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
61 static void alen_array_element_start(void *state, bool isnull);
63 /* common workers for json{b}_each* functions */
64 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
65 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
68 /* semantic action functions for json_each */
69 static void each_object_field_start(void *state, char *fname, bool isnull);
70 static void each_object_field_end(void *state, char *fname, bool isnull);
71 static void each_array_start(void *state);
72 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
74 /* common workers for json{b}_array_elements_* functions */
75 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
77 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
80 /* semantic action functions for json_array_elements */
81 static void elements_object_start(void *state);
82 static void elements_array_element_start(void *state, bool isnull);
83 static void elements_array_element_end(void *state, bool isnull);
84 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
86 /* turn a json object into a hash table */
87 static HTAB *get_json_object_as_hash(text *json, const char *funcname);
89 /* common worker for populate_record and to_record */
90 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
91 bool have_record_arg);
93 /* semantic action functions for get_json_object_as_hash */
94 static void hash_object_field_start(void *state, char *fname, bool isnull);
95 static void hash_object_field_end(void *state, char *fname, bool isnull);
96 static void hash_array_start(void *state);
97 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
99 /* semantic action functions for populate_recordset */
100 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
101 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
102 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
103 static void populate_recordset_object_start(void *state);
104 static void populate_recordset_object_end(void *state);
105 static void populate_recordset_array_start(void *state);
106 static void populate_recordset_array_element_start(void *state, bool isnull);
108 /* semantic action functions for json_strip_nulls */
109 static void sn_object_start(void *state);
110 static void sn_object_end(void *state);
111 static void sn_array_start(void *state);
112 static void sn_array_end(void *state);
113 static void sn_object_field_start (void *state, char *fname, bool isnull);
114 static void sn_array_element_start (void *state, bool isnull);
115 static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
117 /* worker function for populate_recordset and to_recordset */
118 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
119 bool have_record_arg);
121 /* Worker that takes care of common setup for us */
122 static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
127 /* functions supporting jsonb_delete, jsonb_replace and jsonb_concat */
128 static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
129 JsonbParseState **state);
130 static JsonbValue *walkJsonb(JsonbIterator **it, JsonbParseState **state, bool stop_at_level_zero);
131 static JsonbValue *replacePath(JsonbIterator **it, Datum *path_elems,
132 bool *path_nulls, int path_len,
133 JsonbParseState **st, int level, Jsonb *newval);
134 static void replacePathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
135 int path_len, JsonbParseState **st, int level,
136 Jsonb *newval, uint32 nelems);
137 static void replacePathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
138 int path_len, JsonbParseState **st, int level,
139 Jsonb *newval, uint32 npairs);
140 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb * jb);
142 /* state for json_object_keys */
143 typedef struct OkeysState
152 /* state for json_get* functions */
153 typedef struct GetState
158 bool normalize_results;
160 int npath; /* length of each path-related array */
161 char **path_names; /* field name(s) being sought */
162 int *path_indexes; /* array index(es) being sought */
163 bool *pathok; /* is path matched to current depth? */
164 int *array_cur_index; /* current element index at each path level */
167 /* state for json_array_length */
168 typedef struct AlenState
174 /* state for json_each */
175 typedef struct EachState
178 Tuplestorestate *tuple_store;
180 MemoryContext tmp_cxt;
182 bool normalize_results;
184 char *normalized_scalar;
187 /* state for json_array_elements */
188 typedef struct ElementsState
191 const char *function_name;
192 Tuplestorestate *tuple_store;
194 MemoryContext tmp_cxt;
196 bool normalize_results;
198 char *normalized_scalar;
201 /* state for get_json_object_as_hash */
202 typedef struct JhashState
205 const char *function_name;
208 char *save_json_start;
211 /* hashtable element */
212 typedef struct JsonHashEntry
214 char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
220 /* these two are stolen from hstore / record_out, used in populate_record* */
221 typedef struct ColumnIOData
229 typedef struct RecordIOData
234 ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
237 /* state for populate_recordset */
238 typedef struct PopulateRecordsetState
241 const char *function_name;
244 char *save_json_start;
245 Tuplestorestate *tuple_store;
248 RecordIOData *my_extra;
249 MemoryContext fn_mcxt; /* used to stash IO funcs */
250 } PopulateRecordsetState;
252 /* state for json_strip_nulls */
253 typedef struct StripnullState{
259 /* Turn a jsonb object into a record */
260 static void make_row_from_rec_and_jsonb(Jsonb *element,
261 PopulateRecordsetState *state);
264 * SQL function json_object_keys
266 * Returns the set of keys for the object argument.
268 * This SRF operates in value-per-call mode. It processes the
269 * object during the first call, and the keys are simply stashed
270 * in an array, whose size is expanded as necessary. This is probably
271 * safe enough for a list of keys of a single object, since they are
272 * limited in size to NAMEDATALEN and the number of keys is unlikely to
273 * be so huge that it has major memory implications.
276 jsonb_object_keys(PG_FUNCTION_ARGS)
278 FuncCallContext *funcctx;
282 if (SRF_IS_FIRSTCALL())
284 MemoryContext oldcontext;
285 Jsonb *jb = PG_GETARG_JSONB(0);
286 bool skipNested = false;
291 if (JB_ROOT_IS_SCALAR(jb))
293 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
294 errmsg("cannot call %s on a scalar",
295 "jsonb_object_keys")));
296 else if (JB_ROOT_IS_ARRAY(jb))
298 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
299 errmsg("cannot call %s on an array",
300 "jsonb_object_keys")));
302 funcctx = SRF_FIRSTCALL_INIT();
303 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
305 state = palloc(sizeof(OkeysState));
307 state->result_size = JB_ROOT_COUNT(jb);
308 state->result_count = 0;
309 state->sent_count = 0;
310 state->result = palloc(state->result_size * sizeof(char *));
312 it = JsonbIteratorInit(&jb->root);
314 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
322 cstr = palloc(v.val.string.len + 1 * sizeof(char));
323 memcpy(cstr, v.val.string.val, v.val.string.len);
324 cstr[v.val.string.len] = '\0';
325 state->result[state->result_count++] = cstr;
329 MemoryContextSwitchTo(oldcontext);
330 funcctx->user_fctx = (void *) state;
333 funcctx = SRF_PERCALL_SETUP();
334 state = (OkeysState *) funcctx->user_fctx;
336 if (state->sent_count < state->result_count)
338 char *nxt = state->result[state->sent_count++];
340 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
343 /* cleanup to reduce or eliminate memory leaks */
344 for (i = 0; i < state->result_count; i++)
345 pfree(state->result[i]);
346 pfree(state->result);
349 SRF_RETURN_DONE(funcctx);
354 json_object_keys(PG_FUNCTION_ARGS)
356 FuncCallContext *funcctx;
360 if (SRF_IS_FIRSTCALL())
362 text *json = PG_GETARG_TEXT_P(0);
363 JsonLexContext *lex = makeJsonLexContext(json, true);
365 MemoryContext oldcontext;
367 funcctx = SRF_FIRSTCALL_INIT();
368 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
370 state = palloc(sizeof(OkeysState));
371 sem = palloc0(sizeof(JsonSemAction));
374 state->result_size = 256;
375 state->result_count = 0;
376 state->sent_count = 0;
377 state->result = palloc(256 * sizeof(char *));
379 sem->semstate = (void *) state;
380 sem->array_start = okeys_array_start;
381 sem->scalar = okeys_scalar;
382 sem->object_field_start = okeys_object_field_start;
383 /* remainder are all NULL, courtesy of palloc0 above */
385 pg_parse_json(lex, sem);
386 /* keys are now in state->result */
388 pfree(lex->strval->data);
393 MemoryContextSwitchTo(oldcontext);
394 funcctx->user_fctx = (void *) state;
397 funcctx = SRF_PERCALL_SETUP();
398 state = (OkeysState *) funcctx->user_fctx;
400 if (state->sent_count < state->result_count)
402 char *nxt = state->result[state->sent_count++];
404 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
407 /* cleanup to reduce or eliminate memory leaks */
408 for (i = 0; i < state->result_count; i++)
409 pfree(state->result[i]);
410 pfree(state->result);
413 SRF_RETURN_DONE(funcctx);
417 okeys_object_field_start(void *state, char *fname, bool isnull)
419 OkeysState *_state = (OkeysState *) state;
421 /* only collecting keys for the top level object */
422 if (_state->lex->lex_level != 1)
425 /* enlarge result array if necessary */
426 if (_state->result_count >= _state->result_size)
428 _state->result_size *= 2;
429 _state->result = (char **)
430 repalloc(_state->result, sizeof(char *) * _state->result_size);
433 /* save a copy of the field name */
434 _state->result[_state->result_count++] = pstrdup(fname);
438 okeys_array_start(void *state)
440 OkeysState *_state = (OkeysState *) state;
442 /* top level must be a json object */
443 if (_state->lex->lex_level == 0)
445 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
446 errmsg("cannot call %s on an array",
447 "json_object_keys")));
451 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
453 OkeysState *_state = (OkeysState *) state;
455 /* top level must be a json object */
456 if (_state->lex->lex_level == 0)
458 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
459 errmsg("cannot call %s on a scalar",
460 "json_object_keys")));
464 * json and jsonb getter functions
465 * these implement the -> ->> #> and #>> operators
466 * and the json{b?}_extract_path*(json, text, ...) functions
471 json_object_field(PG_FUNCTION_ARGS)
473 text *json = PG_GETARG_TEXT_P(0);
474 text *fname = PG_GETARG_TEXT_PP(1);
475 char *fnamestr = text_to_cstring(fname);
478 result = get_worker(json, &fnamestr, NULL, 1, false);
481 PG_RETURN_TEXT_P(result);
487 jsonb_object_field(PG_FUNCTION_ARGS)
489 Jsonb *jb = PG_GETARG_JSONB(0);
490 text *key = PG_GETARG_TEXT_PP(1);
493 if (!JB_ROOT_IS_OBJECT(jb))
496 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
498 VARSIZE_ANY_EXHDR(key));
501 PG_RETURN_JSONB(JsonbValueToJsonb(v));
507 json_object_field_text(PG_FUNCTION_ARGS)
509 text *json = PG_GETARG_TEXT_P(0);
510 text *fname = PG_GETARG_TEXT_PP(1);
511 char *fnamestr = text_to_cstring(fname);
514 result = get_worker(json, &fnamestr, NULL, 1, true);
517 PG_RETURN_TEXT_P(result);
523 jsonb_object_field_text(PG_FUNCTION_ARGS)
525 Jsonb *jb = PG_GETARG_JSONB(0);
526 text *key = PG_GETARG_TEXT_PP(1);
529 if (!JB_ROOT_IS_OBJECT(jb))
532 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
534 VARSIZE_ANY_EXHDR(key));
545 result = cstring_to_text(v->val.boolean ? "true" : "false");
548 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
551 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
552 PointerGetDatum(v->val.numeric))));
556 StringInfo jtext = makeStringInfo();
558 (void) JsonbToCString(jtext, v->val.binary.data, -1);
559 result = cstring_to_text_with_len(jtext->data, jtext->len);
563 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
567 PG_RETURN_TEXT_P(result);
574 json_array_element(PG_FUNCTION_ARGS)
576 text *json = PG_GETARG_TEXT_P(0);
577 int element = PG_GETARG_INT32(1);
580 result = get_worker(json, NULL, &element, 1, false);
583 PG_RETURN_TEXT_P(result);
589 jsonb_array_element(PG_FUNCTION_ARGS)
591 Jsonb *jb = PG_GETARG_JSONB(0);
592 int element = PG_GETARG_INT32(1);
595 if (!JB_ROOT_IS_ARRAY(jb))
598 v = getIthJsonbValueFromContainer(&jb->root, element);
600 PG_RETURN_JSONB(JsonbValueToJsonb(v));
606 json_array_element_text(PG_FUNCTION_ARGS)
608 text *json = PG_GETARG_TEXT_P(0);
609 int element = PG_GETARG_INT32(1);
612 result = get_worker(json, NULL, &element, 1, true);
615 PG_RETURN_TEXT_P(result);
621 jsonb_array_element_text(PG_FUNCTION_ARGS)
623 Jsonb *jb = PG_GETARG_JSONB(0);
624 int element = PG_GETARG_INT32(1);
627 if (!JB_ROOT_IS_ARRAY(jb))
630 v = getIthJsonbValueFromContainer(&jb->root, element);
640 result = cstring_to_text(v->val.boolean ? "true" : "false");
643 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
646 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
647 PointerGetDatum(v->val.numeric))));
651 StringInfo jtext = makeStringInfo();
653 (void) JsonbToCString(jtext, v->val.binary.data, -1);
654 result = cstring_to_text_with_len(jtext->data, jtext->len);
658 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
662 PG_RETURN_TEXT_P(result);
669 json_extract_path(PG_FUNCTION_ARGS)
671 return get_path_all(fcinfo, false);
675 json_extract_path_text(PG_FUNCTION_ARGS)
677 return get_path_all(fcinfo, true);
681 * common routine for extract_path functions
684 get_path_all(FunctionCallInfo fcinfo, bool as_text)
686 text *json = PG_GETARG_TEXT_P(0);
687 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
697 * If the array contains any null elements, return NULL, on the grounds
698 * that you'd have gotten NULL if any RHS value were NULL in a nested
699 * series of applications of the -> operator. (Note: because we also
700 * return NULL for error cases such as no-such-field, this is true
701 * regardless of the contents of the rest of the array.)
703 if (array_contains_nulls(path))
706 deconstruct_array(path, TEXTOID, -1, false, 'i',
707 &pathtext, &pathnulls, &npath);
709 tpath = palloc(npath * sizeof(char *));
710 ipath = palloc(npath * sizeof(int));
712 for (i = 0; i < npath; i++)
714 Assert(!pathnulls[i]);
715 tpath[i] = TextDatumGetCString(pathtext[i]);
718 * we have no idea at this stage what structure the document is so
719 * just convert anything in the path that we can to an integer and set
720 * all the other integers to -1 which will never match.
722 if (*tpath[i] != '\0')
728 ind = strtol(tpath[i], &endptr, 10);
729 if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= 0)
730 ipath[i] = (int) ind;
738 result = get_worker(json, tpath, ipath, npath, as_text);
741 PG_RETURN_TEXT_P(result);
749 * common worker for all the json getter functions
751 * json: JSON object (in text form)
752 * tpath[]: field name(s) to extract
753 * ipath[]: array index(es) (zero-based) to extract
754 * npath: length of tpath[] and/or ipath[]
755 * normalize_results: true to de-escape string and null scalars
757 * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
758 * field is not to be matched at that nesting level. Similarly, ipath can
759 * be NULL, or any one ipath[] entry can be -1, if an array element is not
760 * to be matched at that nesting level.
763 get_worker(text *json,
767 bool normalize_results)
769 JsonLexContext *lex = makeJsonLexContext(json, true);
770 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
771 GetState *state = palloc0(sizeof(GetState));
776 /* is it "_as_text" variant? */
777 state->normalize_results = normalize_results;
778 state->npath = npath;
779 state->path_names = tpath;
780 state->path_indexes = ipath;
781 state->pathok = palloc0(sizeof(bool) * npath);
782 state->array_cur_index = palloc(sizeof(int) * npath);
785 state->pathok[0] = true;
787 sem->semstate = (void *) state;
790 * Not all variants need all the semantic routines. Only set the ones that
791 * are actually needed for maximum efficiency.
793 sem->scalar = get_scalar;
796 sem->object_start = get_object_start;
797 sem->object_end = get_object_end;
798 sem->array_start = get_array_start;
799 sem->array_end = get_array_end;
803 sem->object_field_start = get_object_field_start;
804 sem->object_field_end = get_object_field_end;
808 sem->array_start = get_array_start;
809 sem->array_element_start = get_array_element_start;
810 sem->array_element_end = get_array_element_end;
813 pg_parse_json(lex, sem);
815 return state->tresult;
819 get_object_start(void *state)
821 GetState *_state = (GetState *) state;
822 int lex_level = _state->lex->lex_level;
824 if (lex_level == 0 && _state->npath == 0)
827 * Special case: we should match the entire object. We only need this
828 * at outermost level because at nested levels the match will have
829 * been started by the outer field or array element callback.
831 _state->result_start = _state->lex->token_start;
836 get_object_end(void *state)
838 GetState *_state = (GetState *) state;
839 int lex_level = _state->lex->lex_level;
841 if (lex_level == 0 && _state->npath == 0)
843 /* Special case: return the entire object */
844 char *start = _state->result_start;
845 int len = _state->lex->prev_token_terminator - start;
847 _state->tresult = cstring_to_text_with_len(start, len);
852 get_object_field_start(void *state, char *fname, bool isnull)
854 GetState *_state = (GetState *) state;
855 bool get_next = false;
856 int lex_level = _state->lex->lex_level;
858 if (lex_level <= _state->npath &&
859 _state->pathok[lex_level - 1] &&
860 _state->path_names != NULL &&
861 _state->path_names[lex_level - 1] != NULL &&
862 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
864 if (lex_level < _state->npath)
866 /* if not at end of path just mark path ok */
867 _state->pathok[lex_level] = true;
871 /* end of path, so we want this value */
878 /* this object overrides any previous matching object */
879 _state->tresult = NULL;
880 _state->result_start = NULL;
882 if (_state->normalize_results &&
883 _state->lex->token_type == JSON_TOKEN_STRING)
885 /* for as_text variants, tell get_scalar to set it for us */
886 _state->next_scalar = true;
890 /* for non-as_text variants, just note the json starting point */
891 _state->result_start = _state->lex->token_start;
897 get_object_field_end(void *state, char *fname, bool isnull)
899 GetState *_state = (GetState *) state;
900 bool get_last = false;
901 int lex_level = _state->lex->lex_level;
903 /* same tests as in get_object_field_start */
904 if (lex_level <= _state->npath &&
905 _state->pathok[lex_level - 1] &&
906 _state->path_names != NULL &&
907 _state->path_names[lex_level - 1] != NULL &&
908 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
910 if (lex_level < _state->npath)
912 /* done with this field so reset pathok */
913 _state->pathok[lex_level] = false;
917 /* end of path, so we want this value */
922 /* for as_text scalar case, our work is already done */
923 if (get_last && _state->result_start != NULL)
926 * make a text object from the string from the prevously noted json
927 * start up to the end of the previous token (the lexer is by now
928 * ahead of us on whatever came after what we're interested in).
930 if (isnull && _state->normalize_results)
931 _state->tresult = (text *) NULL;
934 char *start = _state->result_start;
935 int len = _state->lex->prev_token_terminator - start;
937 _state->tresult = cstring_to_text_with_len(start, len);
940 /* this should be unnecessary but let's do it for cleanliness: */
941 _state->result_start = NULL;
946 get_array_start(void *state)
948 GetState *_state = (GetState *) state;
949 int lex_level = _state->lex->lex_level;
951 if (lex_level < _state->npath)
953 /* Initialize counting of elements in this array */
954 _state->array_cur_index[lex_level] = -1;
956 else if (lex_level == 0 && _state->npath == 0)
959 * Special case: we should match the entire array. We only need this
960 * at outermost level because at nested levels the match will have
961 * been started by the outer field or array element callback.
963 _state->result_start = _state->lex->token_start;
968 get_array_end(void *state)
970 GetState *_state = (GetState *) state;
971 int lex_level = _state->lex->lex_level;
973 if (lex_level == 0 && _state->npath == 0)
975 /* Special case: return the entire array */
976 char *start = _state->result_start;
977 int len = _state->lex->prev_token_terminator - start;
979 _state->tresult = cstring_to_text_with_len(start, len);
984 get_array_element_start(void *state, bool isnull)
986 GetState *_state = (GetState *) state;
987 bool get_next = false;
988 int lex_level = _state->lex->lex_level;
990 /* Update array element counter */
991 if (lex_level <= _state->npath)
992 _state->array_cur_index[lex_level - 1]++;
994 if (lex_level <= _state->npath &&
995 _state->pathok[lex_level - 1] &&
996 _state->path_indexes != NULL &&
997 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
999 if (lex_level < _state->npath)
1001 /* if not at end of path just mark path ok */
1002 _state->pathok[lex_level] = true;
1006 /* end of path, so we want this value */
1011 /* same logic as for objects */
1014 _state->tresult = NULL;
1015 _state->result_start = NULL;
1017 if (_state->normalize_results &&
1018 _state->lex->token_type == JSON_TOKEN_STRING)
1020 _state->next_scalar = true;
1024 _state->result_start = _state->lex->token_start;
1030 get_array_element_end(void *state, bool isnull)
1032 GetState *_state = (GetState *) state;
1033 bool get_last = false;
1034 int lex_level = _state->lex->lex_level;
1036 /* same tests as in get_array_element_start */
1037 if (lex_level <= _state->npath &&
1038 _state->pathok[lex_level - 1] &&
1039 _state->path_indexes != NULL &&
1040 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1042 if (lex_level < _state->npath)
1044 /* done with this element so reset pathok */
1045 _state->pathok[lex_level] = false;
1049 /* end of path, so we want this value */
1054 /* same logic as for objects */
1055 if (get_last && _state->result_start != NULL)
1057 if (isnull && _state->normalize_results)
1058 _state->tresult = (text *) NULL;
1061 char *start = _state->result_start;
1062 int len = _state->lex->prev_token_terminator - start;
1064 _state->tresult = cstring_to_text_with_len(start, len);
1067 _state->result_start = NULL;
1072 get_scalar(void *state, char *token, JsonTokenType tokentype)
1074 GetState *_state = (GetState *) state;
1075 int lex_level = _state->lex->lex_level;
1077 /* Check for whole-object match */
1078 if (lex_level == 0 && _state->npath == 0)
1080 if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1082 /* we want the de-escaped string */
1083 _state->next_scalar = true;
1085 else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1087 _state->tresult = (text *) NULL;
1092 * This is a bit hokey: we will suppress whitespace after the
1093 * scalar token, but not whitespace before it. Probably not worth
1094 * doing our own space-skipping to avoid that.
1096 char *start = _state->lex->input;
1097 int len = _state->lex->prev_token_terminator - start;
1099 _state->tresult = cstring_to_text_with_len(start, len);
1103 if (_state->next_scalar)
1105 /* a de-escaped text value is wanted, so supply it */
1106 _state->tresult = cstring_to_text(token);
1107 /* make sure the next call to get_scalar doesn't overwrite it */
1108 _state->next_scalar = false;
1113 jsonb_extract_path(PG_FUNCTION_ARGS)
1115 return get_jsonb_path_all(fcinfo, false);
1119 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1121 return get_jsonb_path_all(fcinfo, true);
1125 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1127 Jsonb *jb = PG_GETARG_JSONB(0);
1128 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1134 bool have_object = false,
1136 JsonbValue *jbvp = NULL;
1138 JsonbContainer *container;
1141 * If the array contains any null elements, return NULL, on the grounds
1142 * that you'd have gotten NULL if any RHS value were NULL in a nested
1143 * series of applications of the -> operator. (Note: because we also
1144 * return NULL for error cases such as no-such-field, this is true
1145 * regardless of the contents of the rest of the array.)
1147 if (array_contains_nulls(path))
1150 deconstruct_array(path, TEXTOID, -1, false, 'i',
1151 &pathtext, &pathnulls, &npath);
1153 /* Identify whether we have object, array, or scalar at top-level */
1154 container = &jb->root;
1156 if (JB_ROOT_IS_OBJECT(jb))
1158 else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1162 Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
1163 /* Extract the scalar value, if it is what we'll return */
1165 jbvp = getIthJsonbValueFromContainer(container, 0);
1169 * If the array is empty, return the entire LHS object, on the grounds
1170 * that we should do zero field or element extractions. For the
1171 * non-scalar case we can just hand back the object without much work. For
1172 * the scalar case, fall through and deal with the value below the loop.
1173 * (This inconsistency arises because there's no easy way to generate a
1174 * JsonbValue directly for root-level containers.)
1176 if (npath <= 0 && jbvp == NULL)
1180 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1186 /* not text mode - just hand back the jsonb */
1187 PG_RETURN_JSONB(jb);
1191 for (i = 0; i < npath; i++)
1195 jbvp = findJsonbValueFromContainerLen(container,
1197 VARDATA_ANY(pathtext[i]),
1198 VARSIZE_ANY_EXHDR(pathtext[i]));
1200 else if (have_array)
1204 char *indextext = TextDatumGetCString(pathtext[i]);
1208 lindex = strtol(indextext, &endptr, 10);
1209 if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1210 lindex > INT_MAX || lindex < 0)
1212 index = (uint32) lindex;
1213 jbvp = getIthJsonbValueFromContainer(container, index);
1217 /* scalar, extraction yields a null */
1223 else if (i == npath - 1)
1226 if (jbvp->type == jbvBinary)
1228 JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1231 r = JsonbIteratorNext(&it, &tv, true);
1232 container = (JsonbContainer *) jbvp->val.binary.data;
1233 have_object = r == WJB_BEGIN_OBJECT;
1234 have_array = r == WJB_BEGIN_ARRAY;
1238 have_object = jbvp->type == jbvObject;
1239 have_array = jbvp->type == jbvArray;
1245 /* special-case outputs for string and null values */
1246 if (jbvp->type == jbvString)
1247 PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1248 jbvp->val.string.len));
1249 if (jbvp->type == jbvNull)
1253 res = JsonbValueToJsonb(jbvp);
1257 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1263 /* not text mode - just hand back the jsonb */
1264 PG_RETURN_JSONB(res);
1269 * SQL function json_array_length(json) -> int
1272 json_array_length(PG_FUNCTION_ARGS)
1274 text *json = PG_GETARG_TEXT_P(0);
1276 JsonLexContext *lex;
1279 lex = makeJsonLexContext(json, false);
1280 state = palloc0(sizeof(AlenState));
1281 sem = palloc0(sizeof(JsonSemAction));
1283 /* palloc0 does this for us */
1289 sem->semstate = (void *) state;
1290 sem->object_start = alen_object_start;
1291 sem->scalar = alen_scalar;
1292 sem->array_element_start = alen_array_element_start;
1294 pg_parse_json(lex, sem);
1296 PG_RETURN_INT32(state->count);
1300 jsonb_array_length(PG_FUNCTION_ARGS)
1302 Jsonb *jb = PG_GETARG_JSONB(0);
1304 if (JB_ROOT_IS_SCALAR(jb))
1306 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1307 errmsg("cannot get array length of a scalar")));
1308 else if (!JB_ROOT_IS_ARRAY(jb))
1310 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1311 errmsg("cannot get array length of a non-array")));
1313 PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1317 * These next two checks ensure that the json is an array (since it can't be
1318 * a scalar or an object).
1322 alen_object_start(void *state)
1324 AlenState *_state = (AlenState *) state;
1326 /* json structure check */
1327 if (_state->lex->lex_level == 0)
1329 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1330 errmsg("cannot get array length of a non-array")));
1334 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1336 AlenState *_state = (AlenState *) state;
1338 /* json structure check */
1339 if (_state->lex->lex_level == 0)
1341 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1342 errmsg("cannot get array length of a scalar")));
1346 alen_array_element_start(void *state, bool isnull)
1348 AlenState *_state = (AlenState *) state;
1350 /* just count up all the level 1 elements */
1351 if (_state->lex->lex_level == 1)
1356 * SQL function json_each and json_each_text
1358 * decompose a json object into key value pairs.
1360 * Unlike json_object_keys() these SRFs operate in materialize mode,
1361 * stashing results into a Tuplestore object as they go.
1362 * The construction of tuples is done using a temporary memory context
1363 * that is cleared out after each tuple is built.
1366 json_each(PG_FUNCTION_ARGS)
1368 return each_worker(fcinfo, false);
1372 jsonb_each(PG_FUNCTION_ARGS)
1374 return each_worker_jsonb(fcinfo, "jsonb_each", false);
1378 json_each_text(PG_FUNCTION_ARGS)
1380 return each_worker(fcinfo, true);
1384 jsonb_each_text(PG_FUNCTION_ARGS)
1386 return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1390 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1392 Jsonb *jb = PG_GETARG_JSONB(0);
1394 Tuplestorestate *tuple_store;
1396 TupleDesc ret_tdesc;
1397 MemoryContext old_cxt,
1399 bool skipNested = false;
1404 if (!JB_ROOT_IS_OBJECT(jb))
1406 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1407 errmsg("cannot call %s on a non-object",
1410 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1412 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1413 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1414 rsi->expectedDesc == NULL)
1416 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1417 errmsg("set-valued function called in context that "
1418 "cannot accept a set")));
1420 rsi->returnMode = SFRM_Materialize;
1422 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1424 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1425 errmsg("function returning record called in context "
1426 "that cannot accept type record")));
1428 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1430 ret_tdesc = CreateTupleDescCopy(tupdesc);
1431 BlessTupleDesc(ret_tdesc);
1433 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1436 MemoryContextSwitchTo(old_cxt);
1438 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1439 "jsonb_each temporary cxt",
1440 ALLOCSET_DEFAULT_MINSIZE,
1441 ALLOCSET_DEFAULT_INITSIZE,
1442 ALLOCSET_DEFAULT_MAXSIZE);
1444 it = JsonbIteratorInit(&jb->root);
1446 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1455 bool nulls[2] = {false, false};
1457 /* Use the tmp context so we can clean up after each tuple is done */
1458 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1460 key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1463 * The next thing the iterator fetches should be the value, no
1464 * matter what shape it is.
1466 r = JsonbIteratorNext(&it, &v, skipNested);
1468 values[0] = PointerGetDatum(key);
1472 if (v.type == jbvNull)
1474 /* a json null is an sql null in text mode */
1476 values[1] = (Datum) NULL;
1482 if (v.type == jbvString)
1484 /* In text mode, scalar strings should be dequoted */
1485 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1489 /* Turn anything else into a json string */
1490 StringInfo jtext = makeStringInfo();
1491 Jsonb *jb = JsonbValueToJsonb(&v);
1493 (void) JsonbToCString(jtext, &jb->root, 0);
1494 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1497 values[1] = PointerGetDatum(sv);
1502 /* Not in text mode, just return the Jsonb */
1503 Jsonb *val = JsonbValueToJsonb(&v);
1505 values[1] = PointerGetDatum(val);
1508 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1510 tuplestore_puttuple(tuple_store, tuple);
1512 /* clean up and switch back */
1513 MemoryContextSwitchTo(old_cxt);
1514 MemoryContextReset(tmp_cxt);
1518 MemoryContextDelete(tmp_cxt);
1520 rsi->setResult = tuple_store;
1521 rsi->setDesc = ret_tdesc;
1528 each_worker(FunctionCallInfo fcinfo, bool as_text)
1530 text *json = PG_GETARG_TEXT_P(0);
1531 JsonLexContext *lex;
1534 MemoryContext old_cxt;
1538 lex = makeJsonLexContext(json, true);
1539 state = palloc0(sizeof(EachState));
1540 sem = palloc0(sizeof(JsonSemAction));
1542 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1544 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1545 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1546 rsi->expectedDesc == NULL)
1548 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1549 errmsg("set-valued function called in context that "
1550 "cannot accept a set")));
1552 rsi->returnMode = SFRM_Materialize;
1554 (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1556 /* make these in a sufficiently long-lived memory context */
1557 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1559 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1560 BlessTupleDesc(state->ret_tdesc);
1561 state->tuple_store =
1562 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1565 MemoryContextSwitchTo(old_cxt);
1567 sem->semstate = (void *) state;
1568 sem->array_start = each_array_start;
1569 sem->scalar = each_scalar;
1570 sem->object_field_start = each_object_field_start;
1571 sem->object_field_end = each_object_field_end;
1573 state->normalize_results = as_text;
1574 state->next_scalar = false;
1576 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1577 "json_each temporary cxt",
1578 ALLOCSET_DEFAULT_MINSIZE,
1579 ALLOCSET_DEFAULT_INITSIZE,
1580 ALLOCSET_DEFAULT_MAXSIZE);
1582 pg_parse_json(lex, sem);
1584 MemoryContextDelete(state->tmp_cxt);
1586 rsi->setResult = state->tuple_store;
1587 rsi->setDesc = state->ret_tdesc;
1594 each_object_field_start(void *state, char *fname, bool isnull)
1596 EachState *_state = (EachState *) state;
1598 /* save a pointer to where the value starts */
1599 if (_state->lex->lex_level == 1)
1602 * next_scalar will be reset in the object_field_end handler, and
1603 * since we know the value is a scalar there is no danger of it being
1604 * on while recursing down the tree.
1606 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1607 _state->next_scalar = true;
1609 _state->result_start = _state->lex->token_start;
1614 each_object_field_end(void *state, char *fname, bool isnull)
1616 EachState *_state = (EachState *) state;
1617 MemoryContext old_cxt;
1622 bool nulls[2] = {false, false};
1624 /* skip over nested objects */
1625 if (_state->lex->lex_level != 1)
1628 /* use the tmp context so we can clean up after each tuple is done */
1629 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1631 values[0] = CStringGetTextDatum(fname);
1633 if (isnull && _state->normalize_results)
1636 values[1] = (Datum) 0;
1638 else if (_state->next_scalar)
1640 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1641 _state->next_scalar = false;
1645 len = _state->lex->prev_token_terminator - _state->result_start;
1646 val = cstring_to_text_with_len(_state->result_start, len);
1647 values[1] = PointerGetDatum(val);
1650 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1652 tuplestore_puttuple(_state->tuple_store, tuple);
1654 /* clean up and switch back */
1655 MemoryContextSwitchTo(old_cxt);
1656 MemoryContextReset(_state->tmp_cxt);
1660 each_array_start(void *state)
1662 EachState *_state = (EachState *) state;
1664 /* json structure check */
1665 if (_state->lex->lex_level == 0)
1667 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1668 errmsg("cannot deconstruct an array as an object")));
1672 each_scalar(void *state, char *token, JsonTokenType tokentype)
1674 EachState *_state = (EachState *) state;
1676 /* json structure check */
1677 if (_state->lex->lex_level == 0)
1679 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1680 errmsg("cannot deconstruct a scalar")));
1682 /* supply de-escaped value if required */
1683 if (_state->next_scalar)
1684 _state->normalized_scalar = token;
1688 * SQL functions json_array_elements and json_array_elements_text
1690 * get the elements from a json array
1692 * a lot of this processing is similar to the json_each* functions
1696 jsonb_array_elements(PG_FUNCTION_ARGS)
1698 return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1702 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1704 return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1708 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1711 Jsonb *jb = PG_GETARG_JSONB(0);
1713 Tuplestorestate *tuple_store;
1715 TupleDesc ret_tdesc;
1716 MemoryContext old_cxt,
1718 bool skipNested = false;
1723 if (JB_ROOT_IS_SCALAR(jb))
1725 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1726 errmsg("cannot extract elements from a scalar")));
1727 else if (!JB_ROOT_IS_ARRAY(jb))
1729 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1730 errmsg("cannot extract elements from an object")));
1732 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1734 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1735 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1736 rsi->expectedDesc == NULL)
1738 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1739 errmsg("set-valued function called in context that "
1740 "cannot accept a set")));
1742 rsi->returnMode = SFRM_Materialize;
1744 /* it's a simple type, so don't use get_call_result_type() */
1745 tupdesc = rsi->expectedDesc;
1747 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1749 ret_tdesc = CreateTupleDescCopy(tupdesc);
1750 BlessTupleDesc(ret_tdesc);
1752 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1755 MemoryContextSwitchTo(old_cxt);
1757 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1758 "jsonb_array_elements temporary cxt",
1759 ALLOCSET_DEFAULT_MINSIZE,
1760 ALLOCSET_DEFAULT_INITSIZE,
1761 ALLOCSET_DEFAULT_MAXSIZE);
1763 it = JsonbIteratorInit(&jb->root);
1765 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1773 bool nulls[1] = {false};
1775 /* use the tmp context so we can clean up after each tuple is done */
1776 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1780 Jsonb *val = JsonbValueToJsonb(&v);
1782 values[0] = PointerGetDatum(val);
1786 if (v.type == jbvNull)
1788 /* a json null is an sql null in text mode */
1790 values[0] = (Datum) NULL;
1796 if (v.type == jbvString)
1798 /* in text mode scalar strings should be dequoted */
1799 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1803 /* turn anything else into a json string */
1804 StringInfo jtext = makeStringInfo();
1805 Jsonb *jb = JsonbValueToJsonb(&v);
1807 (void) JsonbToCString(jtext, &jb->root, 0);
1808 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1811 values[0] = PointerGetDatum(sv);
1815 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1817 tuplestore_puttuple(tuple_store, tuple);
1819 /* clean up and switch back */
1820 MemoryContextSwitchTo(old_cxt);
1821 MemoryContextReset(tmp_cxt);
1825 MemoryContextDelete(tmp_cxt);
1827 rsi->setResult = tuple_store;
1828 rsi->setDesc = ret_tdesc;
1834 json_array_elements(PG_FUNCTION_ARGS)
1836 return elements_worker(fcinfo, "json_array_elements", false);
1840 json_array_elements_text(PG_FUNCTION_ARGS)
1842 return elements_worker(fcinfo, "json_array_elements_text", true);
1846 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1848 text *json = PG_GETARG_TEXT_P(0);
1850 /* elements only needs escaped strings when as_text */
1851 JsonLexContext *lex = makeJsonLexContext(json, as_text);
1854 MemoryContext old_cxt;
1856 ElementsState *state;
1858 state = palloc0(sizeof(ElementsState));
1859 sem = palloc0(sizeof(JsonSemAction));
1861 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1863 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1864 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1865 rsi->expectedDesc == NULL)
1867 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1868 errmsg("set-valued function called in context that "
1869 "cannot accept a set")));
1871 rsi->returnMode = SFRM_Materialize;
1873 /* it's a simple type, so don't use get_call_result_type() */
1874 tupdesc = rsi->expectedDesc;
1876 /* make these in a sufficiently long-lived memory context */
1877 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1879 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1880 BlessTupleDesc(state->ret_tdesc);
1881 state->tuple_store =
1882 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1885 MemoryContextSwitchTo(old_cxt);
1887 sem->semstate = (void *) state;
1888 sem->object_start = elements_object_start;
1889 sem->scalar = elements_scalar;
1890 sem->array_element_start = elements_array_element_start;
1891 sem->array_element_end = elements_array_element_end;
1893 state->function_name = funcname;
1894 state->normalize_results = as_text;
1895 state->next_scalar = false;
1897 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1898 "json_array_elements temporary cxt",
1899 ALLOCSET_DEFAULT_MINSIZE,
1900 ALLOCSET_DEFAULT_INITSIZE,
1901 ALLOCSET_DEFAULT_MAXSIZE);
1903 pg_parse_json(lex, sem);
1905 MemoryContextDelete(state->tmp_cxt);
1907 rsi->setResult = state->tuple_store;
1908 rsi->setDesc = state->ret_tdesc;
1914 elements_array_element_start(void *state, bool isnull)
1916 ElementsState *_state = (ElementsState *) state;
1918 /* save a pointer to where the value starts */
1919 if (_state->lex->lex_level == 1)
1922 * next_scalar will be reset in the array_element_end handler, and
1923 * since we know the value is a scalar there is no danger of it being
1924 * on while recursing down the tree.
1926 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1927 _state->next_scalar = true;
1929 _state->result_start = _state->lex->token_start;
1934 elements_array_element_end(void *state, bool isnull)
1936 ElementsState *_state = (ElementsState *) state;
1937 MemoryContext old_cxt;
1942 bool nulls[1] = {false};
1944 /* skip over nested objects */
1945 if (_state->lex->lex_level != 1)
1948 /* use the tmp context so we can clean up after each tuple is done */
1949 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1951 if (isnull && _state->normalize_results)
1954 values[0] = (Datum) NULL;
1956 else if (_state->next_scalar)
1958 values[0] = CStringGetTextDatum(_state->normalized_scalar);
1959 _state->next_scalar = false;
1963 len = _state->lex->prev_token_terminator - _state->result_start;
1964 val = cstring_to_text_with_len(_state->result_start, len);
1965 values[0] = PointerGetDatum(val);
1968 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1970 tuplestore_puttuple(_state->tuple_store, tuple);
1972 /* clean up and switch back */
1973 MemoryContextSwitchTo(old_cxt);
1974 MemoryContextReset(_state->tmp_cxt);
1978 elements_object_start(void *state)
1980 ElementsState *_state = (ElementsState *) state;
1982 /* json structure check */
1983 if (_state->lex->lex_level == 0)
1985 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1986 errmsg("cannot call %s on a non-array",
1987 _state->function_name)));
1991 elements_scalar(void *state, char *token, JsonTokenType tokentype)
1993 ElementsState *_state = (ElementsState *) state;
1995 /* json structure check */
1996 if (_state->lex->lex_level == 0)
1998 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1999 errmsg("cannot call %s on a scalar",
2000 _state->function_name)));
2002 /* supply de-escaped value if required */
2003 if (_state->next_scalar)
2004 _state->normalized_scalar = token;
2008 * SQL function json_populate_record
2010 * set fields in a record from the argument json
2012 * Code adapted shamelessly from hstore's populate_record
2013 * which is in turn partly adapted from record_out.
2015 * The json is decomposed into a hash table, in which each
2016 * field in the record is then looked up by name. For jsonb
2017 * we fetch the values direct from the object.
2020 jsonb_populate_record(PG_FUNCTION_ARGS)
2022 return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2026 jsonb_to_record(PG_FUNCTION_ARGS)
2028 return populate_record_worker(fcinfo, "jsonb_to_record", false);
2032 json_populate_record(PG_FUNCTION_ARGS)
2034 return populate_record_worker(fcinfo, "json_populate_record", true);
2038 json_to_record(PG_FUNCTION_ARGS)
2040 return populate_record_worker(fcinfo, "json_to_record", false);
2044 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
2045 bool have_record_arg)
2047 int json_arg_num = have_record_arg ? 1 : 0;
2048 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2051 HTAB *json_hash = NULL;
2052 HeapTupleHeader rec = NULL;
2053 Oid tupType = InvalidOid;
2054 int32 tupTypmod = -1;
2056 HeapTupleData tuple;
2058 RecordIOData *my_extra;
2064 Assert(jtype == JSONOID || jtype == JSONBOID);
2066 if (have_record_arg)
2068 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2070 if (!type_is_rowtype(argtype))
2072 (errcode(ERRCODE_DATATYPE_MISMATCH),
2073 errmsg("first argument of %s must be a row type",
2076 if (PG_ARGISNULL(0))
2078 if (PG_ARGISNULL(1))
2082 * have no tuple to look at, so the only source of type info is
2083 * the argtype. The lookup_rowtype_tupdesc call below will error
2084 * out if we don't have a known composite type oid here.
2091 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2093 if (PG_ARGISNULL(1))
2094 PG_RETURN_POINTER(rec);
2096 /* Extract type info from the tuple itself */
2097 tupType = HeapTupleHeaderGetTypeId(rec);
2098 tupTypmod = HeapTupleHeaderGetTypMod(rec);
2101 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2105 /* json{b}_to_record case */
2106 if (PG_ARGISNULL(0))
2109 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2111 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2112 errmsg("function returning record called in context "
2113 "that cannot accept type record"),
2114 errhint("Try calling the function in the FROM clause "
2115 "using a column definition list.")));
2118 if (jtype == JSONOID)
2120 /* just get the text */
2121 json = PG_GETARG_TEXT_P(json_arg_num);
2123 json_hash = get_json_object_as_hash(json, funcname);
2126 * if the input json is empty, we can only skip the rest if we were
2127 * passed in a non-null record, since otherwise there may be issues
2128 * with domain nulls.
2130 if (hash_get_num_entries(json_hash) == 0 && rec)
2132 hash_destroy(json_hash);
2133 ReleaseTupleDesc(tupdesc);
2134 PG_RETURN_POINTER(rec);
2139 jb = PG_GETARG_JSONB(json_arg_num);
2141 /* same logic as for json */
2142 if (JB_ROOT_COUNT(jb) == 0 && rec)
2144 ReleaseTupleDesc(tupdesc);
2145 PG_RETURN_POINTER(rec);
2149 ncolumns = tupdesc->natts;
2153 /* Build a temporary HeapTuple control structure */
2154 tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2155 ItemPointerSetInvalid(&(tuple.t_self));
2156 tuple.t_tableOid = InvalidOid;
2161 * We arrange to look up the needed I/O info just once per series of
2162 * calls, assuming the record type doesn't change underneath us.
2164 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2165 if (my_extra == NULL ||
2166 my_extra->ncolumns != ncolumns)
2168 fcinfo->flinfo->fn_extra =
2169 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2170 offsetof(RecordIOData, columns) +
2171 ncolumns * sizeof(ColumnIOData));
2172 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2173 my_extra->record_type = InvalidOid;
2174 my_extra->record_typmod = 0;
2175 my_extra->ncolumns = ncolumns;
2176 MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2179 if (have_record_arg && (my_extra->record_type != tupType ||
2180 my_extra->record_typmod != tupTypmod))
2183 offsetof(RecordIOData, columns) +
2184 ncolumns * sizeof(ColumnIOData));
2185 my_extra->record_type = tupType;
2186 my_extra->record_typmod = tupTypmod;
2187 my_extra->ncolumns = ncolumns;
2190 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2191 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2195 /* Break down the tuple into fields */
2196 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2200 for (i = 0; i < ncolumns; ++i)
2202 values[i] = (Datum) 0;
2207 for (i = 0; i < ncolumns; ++i)
2209 ColumnIOData *column_info = &my_extra->columns[i];
2210 Oid column_type = tupdesc->attrs[i]->atttypid;
2211 JsonbValue *v = NULL;
2212 JsonHashEntry *hashentry = NULL;
2214 /* Ignore dropped columns in datatype */
2215 if (tupdesc->attrs[i]->attisdropped)
2221 if (jtype == JSONOID)
2223 hashentry = hash_search(json_hash,
2224 NameStr(tupdesc->attrs[i]->attname),
2229 char *key = NameStr(tupdesc->attrs[i]->attname);
2231 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
2236 * we can't just skip here if the key wasn't found since we might have
2237 * a domain to deal with. If we were passed in a non-null record
2238 * datum, we assume that the existing values are valid (if they're
2239 * not, then it's not our fault), but if we were passed in a null,
2240 * then every field which we don't populate needs to be run through
2241 * the input function just in case it's a domain type.
2243 if (((jtype == JSONOID && hashentry == NULL) ||
2244 (jtype == JSONBOID && v == NULL)) && rec)
2248 * Prepare to convert the column value from text
2250 if (column_info->column_type != column_type)
2252 getTypeInputInfo(column_type,
2253 &column_info->typiofunc,
2254 &column_info->typioparam);
2255 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2256 fcinfo->flinfo->fn_mcxt);
2257 column_info->column_type = column_type;
2259 if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2260 (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2263 * need InputFunctionCall to happen even for nulls, so that domain
2266 values[i] = InputFunctionCall(&column_info->proc, NULL,
2267 column_info->typioparam,
2268 tupdesc->attrs[i]->atttypmod);
2275 if (jtype == JSONOID)
2277 /* already done the hard work in the json case */
2282 if (v->type == jbvString)
2283 s = pnstrdup(v->val.string.val, v->val.string.len);
2284 else if (v->type == jbvBool)
2285 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2286 else if (v->type == jbvNumeric)
2287 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2288 PointerGetDatum(v->val.numeric)));
2289 else if (v->type == jbvBinary)
2290 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2292 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2295 values[i] = InputFunctionCall(&column_info->proc, s,
2296 column_info->typioparam,
2297 tupdesc->attrs[i]->atttypmod);
2302 rettuple = heap_form_tuple(tupdesc, values, nulls);
2304 ReleaseTupleDesc(tupdesc);
2307 hash_destroy(json_hash);
2309 PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
2313 * get_json_object_as_hash
2315 * decompose a json object into a hash table.
2318 get_json_object_as_hash(text *json, const char *funcname)
2323 JsonLexContext *lex = makeJsonLexContext(json, true);
2326 memset(&ctl, 0, sizeof(ctl));
2327 ctl.keysize = NAMEDATALEN;
2328 ctl.entrysize = sizeof(JsonHashEntry);
2329 ctl.hcxt = CurrentMemoryContext;
2330 tab = hash_create("json object hashtable",
2333 HASH_ELEM | HASH_CONTEXT);
2335 state = palloc0(sizeof(JHashState));
2336 sem = palloc0(sizeof(JsonSemAction));
2338 state->function_name = funcname;
2342 sem->semstate = (void *) state;
2343 sem->array_start = hash_array_start;
2344 sem->scalar = hash_scalar;
2345 sem->object_field_start = hash_object_field_start;
2346 sem->object_field_end = hash_object_field_end;
2348 pg_parse_json(lex, sem);
2354 hash_object_field_start(void *state, char *fname, bool isnull)
2356 JHashState *_state = (JHashState *) state;
2358 if (_state->lex->lex_level > 1)
2361 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2362 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2364 /* remember start position of the whole text of the subobject */
2365 _state->save_json_start = _state->lex->token_start;
2369 /* must be a scalar */
2370 _state->save_json_start = NULL;
2375 hash_object_field_end(void *state, char *fname, bool isnull)
2377 JHashState *_state = (JHashState *) state;
2378 JsonHashEntry *hashentry;
2382 * Ignore nested fields.
2384 if (_state->lex->lex_level > 2)
2388 * Ignore field names >= NAMEDATALEN - they can't match a record field.
2389 * (Note: without this test, the hash code would truncate the string at
2390 * NAMEDATALEN-1, and could then match against a similarly-truncated
2391 * record field name. That would be a reasonable behavior, but this code
2392 * has previously insisted on exact equality, so we keep this behavior.)
2394 if (strlen(fname) >= NAMEDATALEN)
2397 hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2400 * found being true indicates a duplicate. We don't do anything about
2401 * that, a later field with the same name overrides the earlier field.
2404 hashentry->isnull = isnull;
2405 if (_state->save_json_start != NULL)
2407 int len = _state->lex->prev_token_terminator - _state->save_json_start;
2408 char *val = palloc((len + 1) * sizeof(char));
2410 memcpy(val, _state->save_json_start, len);
2412 hashentry->val = val;
2416 /* must have had a scalar instead */
2417 hashentry->val = _state->saved_scalar;
2422 hash_array_start(void *state)
2424 JHashState *_state = (JHashState *) state;
2426 if (_state->lex->lex_level == 0)
2428 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2429 errmsg("cannot call %s on an array", _state->function_name)));
2433 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2435 JHashState *_state = (JHashState *) state;
2437 if (_state->lex->lex_level == 0)
2439 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2440 errmsg("cannot call %s on a scalar", _state->function_name)));
2442 if (_state->lex->lex_level == 1)
2443 _state->saved_scalar = token;
2448 * SQL function json_populate_recordset
2450 * set fields in a set of records from the argument json,
2451 * which must be an array of objects.
2453 * similar to json_populate_record, but the tuple-building code
2454 * is pushed down into the semantic action handlers so it's done
2455 * per object in the array.
2458 jsonb_populate_recordset(PG_FUNCTION_ARGS)
2460 return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2464 jsonb_to_recordset(PG_FUNCTION_ARGS)
2466 return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2470 json_populate_recordset(PG_FUNCTION_ARGS)
2472 return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2476 json_to_recordset(PG_FUNCTION_ARGS)
2478 return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2482 make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
2487 RecordIOData *my_extra = state->my_extra;
2488 int ncolumns = my_extra->ncolumns;
2489 TupleDesc tupdesc = state->ret_tdesc;
2490 HeapTupleHeader rec = state->rec;
2493 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2494 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2498 HeapTupleData tuple;
2500 /* Build a temporary HeapTuple control structure */
2501 tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2502 ItemPointerSetInvalid(&(tuple.t_self));
2503 tuple.t_tableOid = InvalidOid;
2504 tuple.t_data = state->rec;
2506 /* Break down the tuple into fields */
2507 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2511 for (i = 0; i < ncolumns; ++i)
2513 values[i] = (Datum) 0;
2518 for (i = 0; i < ncolumns; ++i)
2520 ColumnIOData *column_info = &my_extra->columns[i];
2521 Oid column_type = tupdesc->attrs[i]->atttypid;
2522 JsonbValue *v = NULL;
2525 /* Ignore dropped columns in datatype */
2526 if (tupdesc->attrs[i]->attisdropped)
2532 key = NameStr(tupdesc->attrs[i]->attname);
2534 v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
2538 * We can't just skip here if the key wasn't found since we might have
2539 * a domain to deal with. If we were passed in a non-null record
2540 * datum, we assume that the existing values are valid (if they're
2541 * not, then it's not our fault), but if we were passed in a null,
2542 * then every field which we don't populate needs to be run through
2543 * the input function just in case it's a domain type.
2545 if (v == NULL && rec)
2549 * Prepare to convert the column value from text
2551 if (column_info->column_type != column_type)
2553 getTypeInputInfo(column_type,
2554 &column_info->typiofunc,
2555 &column_info->typioparam);
2556 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2558 column_info->column_type = column_type;
2560 if (v == NULL || v->type == jbvNull)
2563 * Need InputFunctionCall to happen even for nulls, so that domain
2566 values[i] = InputFunctionCall(&column_info->proc, NULL,
2567 column_info->typioparam,
2568 tupdesc->attrs[i]->atttypmod);
2575 if (v->type == jbvString)
2576 s = pnstrdup(v->val.string.val, v->val.string.len);
2577 else if (v->type == jbvBool)
2578 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2579 else if (v->type == jbvNumeric)
2580 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2581 PointerGetDatum(v->val.numeric)));
2582 else if (v->type == jbvBinary)
2583 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2585 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2587 values[i] = InputFunctionCall(&column_info->proc, s,
2588 column_info->typioparam,
2589 tupdesc->attrs[i]->atttypmod);
2594 rettuple = heap_form_tuple(tupdesc, values, nulls);
2596 tuplestore_puttuple(state->tuple_store, rettuple);
2600 * common worker for json_populate_recordset() and json_to_recordset()
2603 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
2604 bool have_record_arg)
2606 int json_arg_num = have_record_arg ? 1 : 0;
2607 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2609 MemoryContext old_cxt;
2612 HeapTupleHeader rec;
2614 RecordIOData *my_extra;
2616 PopulateRecordsetState *state;
2618 if (have_record_arg)
2620 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2622 if (!type_is_rowtype(argtype))
2624 (errcode(ERRCODE_DATATYPE_MISMATCH),
2625 errmsg("first argument of %s must be a row type",
2629 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2631 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2632 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2633 rsi->expectedDesc == NULL)
2635 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2636 errmsg("set-valued function called in context that "
2637 "cannot accept a set")));
2639 rsi->returnMode = SFRM_Materialize;
2642 * get the tupdesc from the result set info - it must be a record type
2643 * because we already checked that arg1 is a record type, or we're in a
2644 * to_record function which returns a setof record.
2646 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2648 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2649 errmsg("function returning record called in context "
2650 "that cannot accept type record")));
2652 /* if the json is null send back an empty set */
2653 if (PG_ARGISNULL(json_arg_num))
2656 if (!have_record_arg || PG_ARGISNULL(0))
2659 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2661 tupType = tupdesc->tdtypeid;
2662 tupTypmod = tupdesc->tdtypmod;
2663 ncolumns = tupdesc->natts;
2666 * We arrange to look up the needed I/O info just once per series of
2667 * calls, assuming the record type doesn't change underneath us.
2669 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2670 if (my_extra == NULL ||
2671 my_extra->ncolumns != ncolumns)
2673 fcinfo->flinfo->fn_extra =
2674 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2675 offsetof(RecordIOData, columns) +
2676 ncolumns * sizeof(ColumnIOData));
2677 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2678 my_extra->record_type = InvalidOid;
2679 my_extra->record_typmod = 0;
2682 if (my_extra->record_type != tupType ||
2683 my_extra->record_typmod != tupTypmod)
2686 offsetof(RecordIOData, columns) +
2687 ncolumns * sizeof(ColumnIOData));
2688 my_extra->record_type = tupType;
2689 my_extra->record_typmod = tupTypmod;
2690 my_extra->ncolumns = ncolumns;
2693 state = palloc0(sizeof(PopulateRecordsetState));
2695 /* make these in a sufficiently long-lived memory context */
2696 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2697 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2698 BlessTupleDesc(state->ret_tdesc);
2699 state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
2700 SFRM_Materialize_Random,
2702 MemoryContextSwitchTo(old_cxt);
2704 state->function_name = funcname;
2705 state->my_extra = my_extra;
2707 state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2709 if (jtype == JSONOID)
2711 text *json = PG_GETARG_TEXT_P(json_arg_num);
2712 JsonLexContext *lex;
2715 sem = palloc0(sizeof(JsonSemAction));
2717 lex = makeJsonLexContext(json, true);
2719 sem->semstate = (void *) state;
2720 sem->array_start = populate_recordset_array_start;
2721 sem->array_element_start = populate_recordset_array_element_start;
2722 sem->scalar = populate_recordset_scalar;
2723 sem->object_field_start = populate_recordset_object_field_start;
2724 sem->object_field_end = populate_recordset_object_field_end;
2725 sem->object_start = populate_recordset_object_start;
2726 sem->object_end = populate_recordset_object_end;
2730 pg_parse_json(lex, sem);
2734 Jsonb *jb = PG_GETARG_JSONB(json_arg_num);
2737 bool skipNested = false;
2740 Assert(jtype == JSONBOID);
2742 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2744 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2745 errmsg("cannot call %s on a non-array",
2748 it = JsonbIteratorInit(&jb->root);
2750 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2756 Jsonb *element = JsonbValueToJsonb(&v);
2758 if (!JB_ROOT_IS_OBJECT(element))
2760 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2761 errmsg("argument of %s must be an array of objects",
2763 make_row_from_rec_and_jsonb(element, state);
2768 rsi->setResult = state->tuple_store;
2769 rsi->setDesc = state->ret_tdesc;
2775 populate_recordset_object_start(void *state)
2777 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2778 int lex_level = _state->lex->lex_level;
2781 /* Reject object at top level: we must have an array at level 0 */
2784 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2785 errmsg("cannot call %s on an object",
2786 _state->function_name)));
2788 /* Nested objects require no special processing */
2792 /* Object at level 1: set up a new hash table for this object */
2793 memset(&ctl, 0, sizeof(ctl));
2794 ctl.keysize = NAMEDATALEN;
2795 ctl.entrysize = sizeof(JsonHashEntry);
2796 ctl.hcxt = CurrentMemoryContext;
2797 _state->json_hash = hash_create("json object hashtable",
2800 HASH_ELEM | HASH_CONTEXT);
2804 populate_recordset_object_end(void *state)
2806 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2807 HTAB *json_hash = _state->json_hash;
2811 RecordIOData *my_extra = _state->my_extra;
2812 int ncolumns = my_extra->ncolumns;
2813 TupleDesc tupdesc = _state->ret_tdesc;
2814 JsonHashEntry *hashentry;
2815 HeapTupleHeader rec = _state->rec;
2818 /* Nested objects require no special processing */
2819 if (_state->lex->lex_level > 1)
2822 /* Otherwise, construct and return a tuple based on this level-1 object */
2823 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2824 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2828 HeapTupleData tuple;
2830 /* Build a temporary HeapTuple control structure */
2831 tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2832 ItemPointerSetInvalid(&(tuple.t_self));
2833 tuple.t_tableOid = InvalidOid;
2834 tuple.t_data = _state->rec;
2836 /* Break down the tuple into fields */
2837 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2841 for (i = 0; i < ncolumns; ++i)
2843 values[i] = (Datum) 0;
2848 for (i = 0; i < ncolumns; ++i)
2850 ColumnIOData *column_info = &my_extra->columns[i];
2851 Oid column_type = tupdesc->attrs[i]->atttypid;
2854 /* Ignore dropped columns in datatype */
2855 if (tupdesc->attrs[i]->attisdropped)
2861 hashentry = hash_search(json_hash,
2862 NameStr(tupdesc->attrs[i]->attname),
2866 * we can't just skip here if the key wasn't found since we might have
2867 * a domain to deal with. If we were passed in a non-null record
2868 * datum, we assume that the existing values are valid (if they're
2869 * not, then it's not our fault), but if we were passed in a null,
2870 * then every field which we don't populate needs to be run through
2871 * the input function just in case it's a domain type.
2873 if (hashentry == NULL && rec)
2877 * Prepare to convert the column value from text
2879 if (column_info->column_type != column_type)
2881 getTypeInputInfo(column_type,
2882 &column_info->typiofunc,
2883 &column_info->typioparam);
2884 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2886 column_info->column_type = column_type;
2888 if (hashentry == NULL || hashentry->isnull)
2891 * need InputFunctionCall to happen even for nulls, so that domain
2894 values[i] = InputFunctionCall(&column_info->proc, NULL,
2895 column_info->typioparam,
2896 tupdesc->attrs[i]->atttypmod);
2901 value = hashentry->val;
2903 values[i] = InputFunctionCall(&column_info->proc, value,
2904 column_info->typioparam,
2905 tupdesc->attrs[i]->atttypmod);
2910 rettuple = heap_form_tuple(tupdesc, values, nulls);
2912 tuplestore_puttuple(_state->tuple_store, rettuple);
2914 /* Done with hash for this object */
2915 hash_destroy(json_hash);
2916 _state->json_hash = NULL;
2920 populate_recordset_array_element_start(void *state, bool isnull)
2922 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2924 if (_state->lex->lex_level == 1 &&
2925 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
2927 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2928 errmsg("argument of %s must be an array of objects",
2929 _state->function_name)));
2933 populate_recordset_array_start(void *state)
2939 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
2941 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2943 if (_state->lex->lex_level == 0)
2945 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2946 errmsg("cannot call %s on a scalar",
2947 _state->function_name)));
2949 if (_state->lex->lex_level == 2)
2950 _state->saved_scalar = token;
2954 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
2956 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2958 if (_state->lex->lex_level > 2)
2961 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2962 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2964 _state->save_json_start = _state->lex->token_start;
2968 _state->save_json_start = NULL;
2973 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
2975 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2976 JsonHashEntry *hashentry;
2980 * Ignore nested fields.
2982 if (_state->lex->lex_level > 2)
2986 * Ignore field names >= NAMEDATALEN - they can't match a record field.
2987 * (Note: without this test, the hash code would truncate the string at
2988 * NAMEDATALEN-1, and could then match against a similarly-truncated
2989 * record field name. That would be a reasonable behavior, but this code
2990 * has previously insisted on exact equality, so we keep this behavior.)
2992 if (strlen(fname) >= NAMEDATALEN)
2995 hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
2998 * found being true indicates a duplicate. We don't do anything about
2999 * that, a later field with the same name overrides the earlier field.
3002 hashentry->isnull = isnull;
3003 if (_state->save_json_start != NULL)
3005 int len = _state->lex->prev_token_terminator - _state->save_json_start;
3006 char *val = palloc((len + 1) * sizeof(char));
3008 memcpy(val, _state->save_json_start, len);
3010 hashentry->val = val;
3014 /* must have had a scalar instead */
3015 hashentry->val = _state->saved_scalar;
3020 * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3023 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
3024 char *key, uint32 keylen)
3029 k.val.string.val = key;
3030 k.val.string.len = keylen;
3032 return findJsonbValueFromContainer(container, flags, &k);
3036 * Semantic actions for json_strip_nulls.
3038 * Simply repeat the input on the output unless we encounter
3039 * a null object field. State for this is set when the field
3040 * is started and reset when the scalar action (which must be next)
3045 sn_object_start(void *state)
3047 StripnullState *_state = (StripnullState *) state;
3048 appendStringInfoCharMacro(_state->strval, '{');
3052 sn_object_end(void *state)
3054 StripnullState *_state = (StripnullState *) state;
3055 appendStringInfoCharMacro(_state->strval, '}');
3059 sn_array_start(void *state)
3061 StripnullState *_state = (StripnullState *) state;
3062 appendStringInfoCharMacro(_state->strval, '[');
3066 sn_array_end(void *state)
3068 StripnullState *_state = (StripnullState *) state;
3069 appendStringInfoCharMacro(_state->strval, ']');
3073 sn_object_field_start (void *state, char *fname, bool isnull)
3075 StripnullState *_state = (StripnullState *) state;
3080 * The next thing must be a scalar or isnull couldn't be true,
3081 * so there is no danger of this state being carried down
3082 * into a nested object or array. The flag will be reset in the
3085 _state->skip_next_null = true;
3089 if (_state->strval->data[_state->strval->len - 1] != '{')
3090 appendStringInfoCharMacro(_state->strval, ',');
3093 * Unfortunately we don't have the quoted and escaped string any more,
3094 * so we have to re-escape it.
3096 escape_json(_state->strval,fname);
3098 appendStringInfoCharMacro(_state->strval, ':');
3102 sn_array_element_start (void *state, bool isnull)
3104 StripnullState *_state = (StripnullState *) state;
3106 if (_state->strval->data[_state->strval->len - 1] != '[')
3107 appendStringInfoCharMacro(_state->strval, ',');
3111 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3113 StripnullState *_state = (StripnullState *) state;
3115 if (_state->skip_next_null)
3117 Assert (tokentype == JSON_TOKEN_NULL);
3118 _state->skip_next_null = false;
3122 if (tokentype == JSON_TOKEN_STRING)
3123 escape_json(_state->strval, token);
3125 appendStringInfoString(_state->strval, token);
3129 * SQL function json_strip_nulls(json) -> json
3132 json_strip_nulls(PG_FUNCTION_ARGS)
3134 text *json = PG_GETARG_TEXT_P(0);
3135 StripnullState *state;
3136 JsonLexContext *lex;
3139 lex = makeJsonLexContext(json, true);
3140 state = palloc0(sizeof(StripnullState));
3141 sem = palloc0(sizeof(JsonSemAction));
3143 state->strval = makeStringInfo();
3144 state->skip_next_null = false;
3147 sem->semstate = (void *) state;
3148 sem->object_start = sn_object_start;
3149 sem->object_end = sn_object_end;
3150 sem->array_start = sn_array_start;
3151 sem->array_end = sn_array_end;
3152 sem->scalar = sn_scalar;
3153 sem->array_element_start = sn_array_element_start;
3154 sem->object_field_start = sn_object_field_start;
3156 pg_parse_json(lex, sem);
3158 PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
3159 state->strval->len));
3164 * SQL function jsonb_strip_nulls(jsonb) -> jsonb
3167 jsonb_strip_nulls(PG_FUNCTION_ARGS)
3169 Jsonb * jb = PG_GETARG_JSONB(0);
3171 JsonbParseState *parseState = NULL;
3172 JsonbValue *res = NULL;
3175 bool last_was_key = false;
3177 if (JB_ROOT_IS_SCALAR(jb))
3178 PG_RETURN_POINTER(jb);
3180 it = JsonbIteratorInit(&jb->root);
3182 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3184 Assert( ! (type == WJB_KEY && last_was_key));
3186 if (type == WJB_KEY)
3188 /* stash the key until we know if it has a null value */
3190 last_was_key = true;
3196 /* if the last element was a key this one can't be */
3197 last_was_key = false;
3199 /* skip this field if value is null */
3200 if (type == WJB_VALUE && v.type == jbvNull)
3203 /* otherwise, do a delayed push of the key */
3204 (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3207 if (type == WJB_VALUE || type == WJB_ELEM)
3208 res = pushJsonbValue(&parseState, type, &v);
3210 res = pushJsonbValue(&parseState, type, NULL);
3213 Assert(res != NULL);
3215 PG_RETURN_POINTER(JsonbValueToJsonb(res));
3219 * Add values from the jsonb to the parse state.
3221 * If the parse state container is an object, the jsonb is pushed as
3222 * a value, not a key.
3224 * This needs to be done using an iterator because pushJsonbValue doesn't
3225 * like getting jbvBinary values, so we can't just push jb as a whole.
3228 addJsonbToParseState(JsonbParseState **jbps, Jsonb * jb)
3232 JsonbValue *o = &(*jbps)->contVal;
3236 it = JsonbIteratorInit(&jb->root);
3238 Assert(o->type == jbvArray || o->type == jbvObject);
3240 if (JB_ROOT_IS_SCALAR(jb))
3242 (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3243 (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3248 (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3251 (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3254 elog(ERROR, "unexpected parent of nested structure");
3259 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3261 if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3262 (void) pushJsonbValue(jbps, type, &v);
3264 (void) pushJsonbValue(jbps, type, NULL);
3271 * SQL function jsonb_pretty (jsonb)
3273 * Pretty-printed text for the jsonb
3276 jsonb_pretty(PG_FUNCTION_ARGS)
3278 Jsonb *jb = PG_GETARG_JSONB(0);
3279 StringInfo str = makeStringInfo();
3281 JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3283 PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
3288 * SQL function jsonb_concat (jsonb, jsonb)
3290 * function for || operator
3293 jsonb_concat(PG_FUNCTION_ARGS)
3295 Jsonb *jb1 = PG_GETARG_JSONB(0);
3296 Jsonb *jb2 = PG_GETARG_JSONB(1);
3297 Jsonb *out = palloc(VARSIZE(jb1) + VARSIZE(jb2));
3298 JsonbParseState *state = NULL;
3304 * If one of the jsonb is empty, just return other.
3306 if (JB_ROOT_COUNT(jb1) == 0)
3308 memcpy(out, jb2, VARSIZE(jb2));
3309 PG_RETURN_POINTER(out);
3311 else if (JB_ROOT_COUNT(jb2) == 0)
3313 memcpy(out, jb1, VARSIZE(jb1));
3314 PG_RETURN_POINTER(out);
3317 it1 = JsonbIteratorInit(&jb1->root);
3318 it2 = JsonbIteratorInit(&jb2->root);
3320 res = IteratorConcat(&it1, &it2, &state);
3322 if (res == NULL || (res->type == jbvArray && res->val.array.nElems == 0) ||
3323 (res->type == jbvObject && res->val.object.nPairs == 0))
3325 SET_VARSIZE(out, VARHDRSZ);
3329 if (res->type == jbvArray && res->val.array.nElems > 1)
3330 res->val.array.rawScalar = false;
3332 out = JsonbValueToJsonb(res);
3335 PG_RETURN_POINTER(out);
3340 * SQL function jsonb_delete (jsonb, text)
3342 * return a copy of the jsonb with the indicated item
3346 jsonb_delete(PG_FUNCTION_ARGS)
3348 Jsonb *in = PG_GETARG_JSONB(0);
3349 text *key = PG_GETARG_TEXT_PP(1);
3350 char *keyptr = VARDATA_ANY(key);
3351 int keylen = VARSIZE_ANY_EXHDR(key);
3352 Jsonb *out = palloc(VARSIZE(in));
3353 JsonbParseState *state = NULL;
3358 bool skipNested = false;
3360 SET_VARSIZE(out, VARSIZE(in));
3362 if (JB_ROOT_COUNT(in) == 0)
3363 PG_RETURN_POINTER(out);
3365 it = JsonbIteratorInit(&in->root);
3367 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3371 if ((r == WJB_ELEM || r == WJB_KEY) &&
3372 (v.type == jbvString && keylen == v.val.string.len &&
3373 memcmp(keyptr, v.val.string.val, keylen) == 0))
3375 /* skip corresponding value as well */
3377 JsonbIteratorNext(&it, &v, true);
3382 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3385 if (res == NULL || (res->type == jbvArray && res->val.array.nElems == 0) ||
3386 (res->type == jbvObject && res->val.object.nPairs == 0))
3387 SET_VARSIZE(out, VARHDRSZ);
3389 out = JsonbValueToJsonb(res);
3391 PG_RETURN_POINTER(out);
3395 * SQL function jsonb_delete (jsonb, int)
3397 * return a copy of the jsonb with the indicated item
3398 * removed. Negative int means count back from the
3402 jsonb_delete_idx(PG_FUNCTION_ARGS)
3404 Jsonb *in = PG_GETARG_JSONB(0);
3405 int idx = PG_GETARG_INT32(1);
3406 Jsonb *out = palloc(VARSIZE(in));
3407 JsonbParseState *state = NULL;
3415 if (JB_ROOT_COUNT(in) == 0)
3417 memcpy(out, in, VARSIZE(in));
3418 PG_RETURN_POINTER(out);
3421 it = JsonbIteratorInit(&in->root);
3423 r = JsonbIteratorNext(&it, &v, false);
3424 if (r == WJB_BEGIN_ARRAY)
3425 n = v.val.array.nElems;
3427 n = v.val.object.nPairs;
3439 memcpy(out, in, VARSIZE(in));
3440 PG_RETURN_POINTER(out);
3443 pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3445 while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3447 if (r == WJB_ELEM || r == WJB_KEY)
3452 JsonbIteratorNext(&it, &v, true); /* skip value */
3457 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3460 if (res == NULL || (res->type == jbvArray && res->val.array.nElems == 0) ||
3461 (res->type == jbvObject && res->val.object.nPairs == 0))
3462 SET_VARSIZE(out, VARHDRSZ);
3464 out = JsonbValueToJsonb(res);
3466 PG_RETURN_POINTER(out);
3470 * SQL function jsonb_replace(jsonb, text[], jsonb)
3473 jsonb_replace(PG_FUNCTION_ARGS)
3475 Jsonb *in = PG_GETARG_JSONB(0);
3476 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3477 Jsonb *newval = PG_GETARG_JSONB(2);
3478 Jsonb *out = palloc(VARSIZE(in) + VARSIZE(newval));
3479 JsonbValue *res = NULL;
3484 JsonbParseState *st = NULL;
3486 if (ARR_NDIM(path) > 1)
3488 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3489 errmsg("wrong number of array subscripts")));
3491 if (JB_ROOT_COUNT(in) == 0)
3493 memcpy(out, in, VARSIZE(in));
3494 PG_RETURN_POINTER(out);
3497 deconstruct_array(path, TEXTOID, -1, false, 'i',
3498 &path_elems, &path_nulls, &path_len);
3502 memcpy(out, in, VARSIZE(in));
3503 PG_RETURN_POINTER(out);
3506 it = JsonbIteratorInit(&in->root);
3508 res = replacePath(&it, path_elems, path_nulls, path_len, &st, 0, newval);
3511 SET_VARSIZE(out, VARHDRSZ);
3513 out = JsonbValueToJsonb(res);
3515 PG_RETURN_POINTER(out);
3520 * SQL function jsonb_delete(jsonb, text[])
3523 jsonb_delete_path(PG_FUNCTION_ARGS)
3525 Jsonb *in = PG_GETARG_JSONB(0);
3526 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3527 Jsonb *out = palloc(VARSIZE(in));
3528 JsonbValue *res = NULL;
3533 JsonbParseState *st = NULL;
3535 if (ARR_NDIM(path) > 1)
3537 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3538 errmsg("wrong number of array subscripts")));
3540 if (JB_ROOT_COUNT(in) == 0)
3542 memcpy(out, in, VARSIZE(in));
3543 PG_RETURN_POINTER(out);
3546 deconstruct_array(path, TEXTOID, -1, false, 'i',
3547 &path_elems, &path_nulls, &path_len);
3551 memcpy(out, in, VARSIZE(in));
3552 PG_RETURN_POINTER(out);
3555 it = JsonbIteratorInit(&in->root);
3557 res = replacePath(&it, path_elems, path_nulls, path_len, &st, 0, NULL);
3560 SET_VARSIZE(out, VARHDRSZ);
3562 out = JsonbValueToJsonb(res);
3564 PG_RETURN_POINTER(out);
3569 * Iterate over all jsonb objects and merge them into one.
3570 * The logic of this function copied from the same hstore function,
3571 * except the case, when it1 & it2 represents jbvObject.
3572 * In that case we just append the content of it2 to it1 without any
3576 IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3577 JsonbParseState **state)
3587 r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3588 r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3591 * Both elements are objects.
3593 if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3598 * Append the all tokens from v1 to res, exept last WJB_END_OBJECT
3599 * (because res will not be finished yet).
3601 (void) pushJsonbValue(state, r1, NULL);
3602 while ((r1 = JsonbIteratorNext(it1, &v1, false)) != 0)
3604 if (r1 == WJB_BEGIN_OBJECT)
3606 else if (r1 == WJB_END_OBJECT)
3610 res = pushJsonbValue(state, r1, r1 < WJB_BEGIN_ARRAY ? &v1 : NULL);
3614 * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3615 * (the concatenation will be completed).
3617 while ((r2 = JsonbIteratorNext(it2, &v2, false)) != 0)
3618 res = pushJsonbValue(state, r2, r2 < WJB_BEGIN_ARRAY ? &v2 : NULL);
3622 * Both elements are arrays (either can be scalar).
3624 else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3626 res = pushJsonbValue(state, r1, NULL);
3629 r1 = JsonbIteratorNext(it1, &v1, true);
3630 if (r1 == WJB_END_OBJECT || r1 == WJB_END_ARRAY)
3633 Assert(r1 == WJB_KEY || r1 == WJB_VALUE || r1 == WJB_ELEM);
3634 pushJsonbValue(state, r1, &v1);
3637 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3639 if (!(r2 == WJB_END_OBJECT || r2 == WJB_END_ARRAY))
3641 if (rk1 == WJB_BEGIN_OBJECT)
3643 pushJsonbValue(state, WJB_KEY, NULL);
3644 r2 = JsonbIteratorNext(it2, &v2, true);
3645 Assert(r2 == WJB_ELEM);
3646 pushJsonbValue(state, WJB_VALUE, &v2);
3649 pushJsonbValue(state, WJB_ELEM, &v2);
3653 res = pushJsonbValue(state,
3654 (rk1 == WJB_BEGIN_OBJECT) ? WJB_END_OBJECT : WJB_END_ARRAY,
3655 NULL /* signal to sort */ );
3657 /* have we got array || object or object || array? */
3658 else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3659 (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3662 JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3663 JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3665 bool prepend = (rk1 == WJB_BEGIN_OBJECT) ? true : false;
3667 pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
3670 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3671 walkJsonb(it_object, state, false);
3673 res = walkJsonb(it_array, state, false);
3677 walkJsonb(it_array, state, true);
3679 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3680 walkJsonb(it_object, state, false);
3682 res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3688 * This must be scalar || object or object || scalar, as that's all
3689 * that's left. Both of these make no sense, so error out.
3692 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3693 errmsg("invalid concatenation of jsonb objects")));
3700 * copy elements from the iterator to the parse state
3701 * stopping at level zero if required.
3704 walkJsonb(JsonbIterator **it, JsonbParseState **state, bool stop_at_level_zero)
3709 JsonbValue *res = NULL;
3711 while ((r = JsonbIteratorNext(it, &v, false)) != WJB_DONE)
3713 if (r == WJB_BEGIN_OBJECT || r == WJB_BEGIN_ARRAY)
3715 else if (r == WJB_END_OBJECT || r == WJB_END_ARRAY)
3718 if (stop_at_level_zero && level == 0)
3721 res = pushJsonbValue(state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3729 * do most of the heavy work for jsonb_replace
3732 replacePath(JsonbIterator **it, Datum *path_elems,
3733 bool *path_nulls, int path_len,
3734 JsonbParseState **st, int level, Jsonb *newval)
3737 JsonbValue *res = NULL;
3740 r = JsonbIteratorNext(it, &v, false);
3744 case WJB_BEGIN_ARRAY:
3745 (void) pushJsonbValue(st, r, NULL);
3746 replacePathArray(it, path_elems, path_nulls, path_len, st, level,
3747 newval, v.val.array.nElems);
3748 r = JsonbIteratorNext(it, &v, false);
3749 Assert(r == WJB_END_ARRAY);
3750 res = pushJsonbValue(st, r, NULL);
3753 case WJB_BEGIN_OBJECT:
3754 (void) pushJsonbValue(st, r, NULL);
3755 replacePathObject(it, path_elems, path_nulls, path_len, st, level,
3756 newval, v.val.object.nPairs);
3757 r = JsonbIteratorNext(it, &v, true);
3758 Assert(r == WJB_END_OBJECT);
3759 res = pushJsonbValue(st, r, NULL);
3764 res = pushJsonbValue(st, r, &v);
3767 elog(ERROR, "impossible state");
3774 * Object walker for replacePath
3777 replacePathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3778 int path_len, JsonbParseState **st, int level,
3779 Jsonb *newval, uint32 nelems)
3786 if (level >= path_len || path_nulls[level])
3789 for (i = 0; i < nelems; i++)
3791 int r = JsonbIteratorNext(it, &k, true);
3792 Assert(r == WJB_KEY);
3795 k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
3796 memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
3797 k.val.string.len) == 0)
3799 if (level == path_len - 1)
3801 r = JsonbIteratorNext(it, &v, true); /* skip */
3804 (void) pushJsonbValue(st, WJB_KEY, &k);
3805 addJsonbToParseState(st, newval);
3810 (void) pushJsonbValue(st, r, &k);
3811 replacePath(it, path_elems, path_nulls, path_len,
3812 st, level + 1, newval);
3817 (void) pushJsonbValue(st, r, &k);
3818 r = JsonbIteratorNext(it, &v, false);
3819 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3820 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3822 int walking_level = 1;
3824 while (walking_level != 0)
3826 r = JsonbIteratorNext(it, &v, false);
3828 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3830 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
3833 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3841 * Array walker for replacePath
3844 replacePathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3845 int path_len, JsonbParseState **st, int level,
3846 Jsonb *newval, uint32 npairs)
3853 /* pick correct index */
3854 if (level < path_len && !path_nulls[level])
3856 char *c = VARDATA_ANY(path_elems[level]);
3859 idx = (int) strtol(c, &badp, 10);
3860 if (errno != 0 || badp == c)
3877 /* iterate over the array elements */
3878 for (i = 0; i < npairs; i++)
3882 if (i == idx && level < path_len)
3884 if (level == path_len - 1)
3886 r = JsonbIteratorNext(it, &v, true); /* skip */
3888 addJsonbToParseState(st, newval);
3891 (void) replacePath(it, path_elems, path_nulls, path_len,
3892 st, level + 1, newval);
3896 r = JsonbIteratorNext(it, &v, false);
3898 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3900 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3902 int walking_level = 1;
3904 while (walking_level != 0)
3906 r = JsonbIteratorNext(it, &v, false);
3908 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3910 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
3913 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);