1 /*-------------------------------------------------------------------------
4 * Functions to process JSON data types.
6 * Portions Copyright (c) 1996-2016, 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_set and jsonb_concat */
128 static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
129 JsonbParseState **state);
130 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
131 bool *path_nulls, int path_len,
132 JsonbParseState **st, int level, Jsonb *newval,
134 static void setPathObject(JsonbIterator **it, Datum *path_elems,
135 bool *path_nulls, int path_len, JsonbParseState **st,
137 Jsonb *newval, uint32 npairs, bool create);
138 static void setPathArray(JsonbIterator **it, Datum *path_elems,
139 bool *path_nulls, int path_len, JsonbParseState **st,
140 int level, Jsonb *newval, uint32 nelems, bool create);
141 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
143 /* state for json_object_keys */
144 typedef struct OkeysState
153 /* state for json_get* functions */
154 typedef struct GetState
159 bool normalize_results;
161 int npath; /* length of each path-related array */
162 char **path_names; /* field name(s) being sought */
163 int *path_indexes; /* array index(es) being sought */
164 bool *pathok; /* is path matched to current depth? */
165 int *array_cur_index; /* current element index at each path level */
168 /* state for json_array_length */
169 typedef struct AlenState
175 /* state for json_each */
176 typedef struct EachState
179 Tuplestorestate *tuple_store;
181 MemoryContext tmp_cxt;
183 bool normalize_results;
185 char *normalized_scalar;
188 /* state for json_array_elements */
189 typedef struct ElementsState
192 const char *function_name;
193 Tuplestorestate *tuple_store;
195 MemoryContext tmp_cxt;
197 bool normalize_results;
199 char *normalized_scalar;
202 /* state for get_json_object_as_hash */
203 typedef struct JhashState
206 const char *function_name;
209 char *save_json_start;
212 /* hashtable element */
213 typedef struct JsonHashEntry
215 char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
221 /* these two are stolen from hstore / record_out, used in populate_record* */
222 typedef struct ColumnIOData
230 typedef struct RecordIOData
235 ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
238 /* state for populate_recordset */
239 typedef struct PopulateRecordsetState
242 const char *function_name;
245 char *save_json_start;
246 Tuplestorestate *tuple_store;
249 RecordIOData *my_extra;
250 MemoryContext fn_mcxt; /* used to stash IO funcs */
251 } PopulateRecordsetState;
253 /* state for json_strip_nulls */
254 typedef struct StripnullState
261 /* Turn a jsonb object into a record */
262 static void make_row_from_rec_and_jsonb(Jsonb *element,
263 PopulateRecordsetState *state);
266 * SQL function json_object_keys
268 * Returns the set of keys for the object argument.
270 * This SRF operates in value-per-call mode. It processes the
271 * object during the first call, and the keys are simply stashed
272 * in an array, whose size is expanded as necessary. This is probably
273 * safe enough for a list of keys of a single object, since they are
274 * limited in size to NAMEDATALEN and the number of keys is unlikely to
275 * be so huge that it has major memory implications.
278 jsonb_object_keys(PG_FUNCTION_ARGS)
280 FuncCallContext *funcctx;
284 if (SRF_IS_FIRSTCALL())
286 MemoryContext oldcontext;
287 Jsonb *jb = PG_GETARG_JSONB(0);
288 bool skipNested = false;
291 JsonbIteratorToken r;
293 if (JB_ROOT_IS_SCALAR(jb))
295 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
296 errmsg("cannot call %s on a scalar",
297 "jsonb_object_keys")));
298 else if (JB_ROOT_IS_ARRAY(jb))
300 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
301 errmsg("cannot call %s on an array",
302 "jsonb_object_keys")));
304 funcctx = SRF_FIRSTCALL_INIT();
305 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
307 state = palloc(sizeof(OkeysState));
309 state->result_size = JB_ROOT_COUNT(jb);
310 state->result_count = 0;
311 state->sent_count = 0;
312 state->result = palloc(state->result_size * sizeof(char *));
314 it = JsonbIteratorInit(&jb->root);
316 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
324 cstr = palloc(v.val.string.len + 1 * sizeof(char));
325 memcpy(cstr, v.val.string.val, v.val.string.len);
326 cstr[v.val.string.len] = '\0';
327 state->result[state->result_count++] = cstr;
331 MemoryContextSwitchTo(oldcontext);
332 funcctx->user_fctx = (void *) state;
335 funcctx = SRF_PERCALL_SETUP();
336 state = (OkeysState *) funcctx->user_fctx;
338 if (state->sent_count < state->result_count)
340 char *nxt = state->result[state->sent_count++];
342 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
345 /* cleanup to reduce or eliminate memory leaks */
346 for (i = 0; i < state->result_count; i++)
347 pfree(state->result[i]);
348 pfree(state->result);
351 SRF_RETURN_DONE(funcctx);
356 json_object_keys(PG_FUNCTION_ARGS)
358 FuncCallContext *funcctx;
362 if (SRF_IS_FIRSTCALL())
364 text *json = PG_GETARG_TEXT_P(0);
365 JsonLexContext *lex = makeJsonLexContext(json, true);
367 MemoryContext oldcontext;
369 funcctx = SRF_FIRSTCALL_INIT();
370 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
372 state = palloc(sizeof(OkeysState));
373 sem = palloc0(sizeof(JsonSemAction));
376 state->result_size = 256;
377 state->result_count = 0;
378 state->sent_count = 0;
379 state->result = palloc(256 * sizeof(char *));
381 sem->semstate = (void *) state;
382 sem->array_start = okeys_array_start;
383 sem->scalar = okeys_scalar;
384 sem->object_field_start = okeys_object_field_start;
385 /* remainder are all NULL, courtesy of palloc0 above */
387 pg_parse_json(lex, sem);
388 /* keys are now in state->result */
390 pfree(lex->strval->data);
395 MemoryContextSwitchTo(oldcontext);
396 funcctx->user_fctx = (void *) state;
399 funcctx = SRF_PERCALL_SETUP();
400 state = (OkeysState *) funcctx->user_fctx;
402 if (state->sent_count < state->result_count)
404 char *nxt = state->result[state->sent_count++];
406 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
409 /* cleanup to reduce or eliminate memory leaks */
410 for (i = 0; i < state->result_count; i++)
411 pfree(state->result[i]);
412 pfree(state->result);
415 SRF_RETURN_DONE(funcctx);
419 okeys_object_field_start(void *state, char *fname, bool isnull)
421 OkeysState *_state = (OkeysState *) state;
423 /* only collecting keys for the top level object */
424 if (_state->lex->lex_level != 1)
427 /* enlarge result array if necessary */
428 if (_state->result_count >= _state->result_size)
430 _state->result_size *= 2;
431 _state->result = (char **)
432 repalloc(_state->result, sizeof(char *) * _state->result_size);
435 /* save a copy of the field name */
436 _state->result[_state->result_count++] = pstrdup(fname);
440 okeys_array_start(void *state)
442 OkeysState *_state = (OkeysState *) state;
444 /* top level must be a json object */
445 if (_state->lex->lex_level == 0)
447 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
448 errmsg("cannot call %s on an array",
449 "json_object_keys")));
453 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
455 OkeysState *_state = (OkeysState *) state;
457 /* top level must be a json object */
458 if (_state->lex->lex_level == 0)
460 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
461 errmsg("cannot call %s on a scalar",
462 "json_object_keys")));
466 * json and jsonb getter functions
467 * these implement the -> ->> #> and #>> operators
468 * and the json{b?}_extract_path*(json, text, ...) functions
473 json_object_field(PG_FUNCTION_ARGS)
475 text *json = PG_GETARG_TEXT_P(0);
476 text *fname = PG_GETARG_TEXT_PP(1);
477 char *fnamestr = text_to_cstring(fname);
480 result = get_worker(json, &fnamestr, NULL, 1, false);
483 PG_RETURN_TEXT_P(result);
489 jsonb_object_field(PG_FUNCTION_ARGS)
491 Jsonb *jb = PG_GETARG_JSONB(0);
492 text *key = PG_GETARG_TEXT_PP(1);
495 if (!JB_ROOT_IS_OBJECT(jb))
498 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
500 VARSIZE_ANY_EXHDR(key));
503 PG_RETURN_JSONB(JsonbValueToJsonb(v));
509 json_object_field_text(PG_FUNCTION_ARGS)
511 text *json = PG_GETARG_TEXT_P(0);
512 text *fname = PG_GETARG_TEXT_PP(1);
513 char *fnamestr = text_to_cstring(fname);
516 result = get_worker(json, &fnamestr, NULL, 1, true);
519 PG_RETURN_TEXT_P(result);
525 jsonb_object_field_text(PG_FUNCTION_ARGS)
527 Jsonb *jb = PG_GETARG_JSONB(0);
528 text *key = PG_GETARG_TEXT_PP(1);
531 if (!JB_ROOT_IS_OBJECT(jb))
534 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
536 VARSIZE_ANY_EXHDR(key));
547 result = cstring_to_text(v->val.boolean ? "true" : "false");
550 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
553 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
554 PointerGetDatum(v->val.numeric))));
558 StringInfo jtext = makeStringInfo();
560 (void) JsonbToCString(jtext, v->val.binary.data, -1);
561 result = cstring_to_text_with_len(jtext->data, jtext->len);
565 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
569 PG_RETURN_TEXT_P(result);
576 json_array_element(PG_FUNCTION_ARGS)
578 text *json = PG_GETARG_TEXT_P(0);
579 int element = PG_GETARG_INT32(1);
582 result = get_worker(json, NULL, &element, 1, false);
585 PG_RETURN_TEXT_P(result);
591 jsonb_array_element(PG_FUNCTION_ARGS)
593 Jsonb *jb = PG_GETARG_JSONB(0);
594 int element = PG_GETARG_INT32(1);
597 if (!JB_ROOT_IS_ARRAY(jb))
600 /* Handle negative subscript */
603 uint32 nelements = JB_ROOT_COUNT(jb);
605 if (-element > nelements)
608 element += nelements;
611 v = getIthJsonbValueFromContainer(&jb->root, element);
613 PG_RETURN_JSONB(JsonbValueToJsonb(v));
619 json_array_element_text(PG_FUNCTION_ARGS)
621 text *json = PG_GETARG_TEXT_P(0);
622 int element = PG_GETARG_INT32(1);
625 result = get_worker(json, NULL, &element, 1, true);
628 PG_RETURN_TEXT_P(result);
634 jsonb_array_element_text(PG_FUNCTION_ARGS)
636 Jsonb *jb = PG_GETARG_JSONB(0);
637 int element = PG_GETARG_INT32(1);
640 if (!JB_ROOT_IS_ARRAY(jb))
643 /* Handle negative subscript */
646 uint32 nelements = JB_ROOT_COUNT(jb);
648 if (-element > nelements)
651 element += nelements;
654 v = getIthJsonbValueFromContainer(&jb->root, element);
664 result = cstring_to_text(v->val.boolean ? "true" : "false");
667 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
670 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
671 PointerGetDatum(v->val.numeric))));
675 StringInfo jtext = makeStringInfo();
677 (void) JsonbToCString(jtext, v->val.binary.data, -1);
678 result = cstring_to_text_with_len(jtext->data, jtext->len);
682 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
686 PG_RETURN_TEXT_P(result);
693 json_extract_path(PG_FUNCTION_ARGS)
695 return get_path_all(fcinfo, false);
699 json_extract_path_text(PG_FUNCTION_ARGS)
701 return get_path_all(fcinfo, true);
705 * common routine for extract_path functions
708 get_path_all(FunctionCallInfo fcinfo, bool as_text)
710 text *json = PG_GETARG_TEXT_P(0);
711 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
721 * If the array contains any null elements, return NULL, on the grounds
722 * that you'd have gotten NULL if any RHS value were NULL in a nested
723 * series of applications of the -> operator. (Note: because we also
724 * return NULL for error cases such as no-such-field, this is true
725 * regardless of the contents of the rest of the array.)
727 if (array_contains_nulls(path))
730 deconstruct_array(path, TEXTOID, -1, false, 'i',
731 &pathtext, &pathnulls, &npath);
733 tpath = palloc(npath * sizeof(char *));
734 ipath = palloc(npath * sizeof(int));
736 for (i = 0; i < npath; i++)
738 Assert(!pathnulls[i]);
739 tpath[i] = TextDatumGetCString(pathtext[i]);
742 * we have no idea at this stage what structure the document is so
743 * just convert anything in the path that we can to an integer and set
744 * all the other integers to INT_MIN which will never match.
746 if (*tpath[i] != '\0')
752 ind = strtol(tpath[i], &endptr, 10);
753 if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
754 ipath[i] = (int) ind;
762 result = get_worker(json, tpath, ipath, npath, as_text);
765 PG_RETURN_TEXT_P(result);
773 * common worker for all the json getter functions
775 * json: JSON object (in text form)
776 * tpath[]: field name(s) to extract
777 * ipath[]: array index(es) (zero-based) to extract, accepts negatives
778 * npath: length of tpath[] and/or ipath[]
779 * normalize_results: true to de-escape string and null scalars
781 * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
782 * field is not to be matched at that nesting level. Similarly, ipath can
783 * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
784 * not to be matched at that nesting level (a json datum should never be
785 * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
788 get_worker(text *json,
792 bool normalize_results)
794 JsonLexContext *lex = makeJsonLexContext(json, true);
795 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
796 GetState *state = palloc0(sizeof(GetState));
801 /* is it "_as_text" variant? */
802 state->normalize_results = normalize_results;
803 state->npath = npath;
804 state->path_names = tpath;
805 state->path_indexes = ipath;
806 state->pathok = palloc0(sizeof(bool) * npath);
807 state->array_cur_index = palloc(sizeof(int) * npath);
810 state->pathok[0] = true;
812 sem->semstate = (void *) state;
815 * Not all variants need all the semantic routines. Only set the ones that
816 * are actually needed for maximum efficiency.
818 sem->scalar = get_scalar;
821 sem->object_start = get_object_start;
822 sem->object_end = get_object_end;
823 sem->array_start = get_array_start;
824 sem->array_end = get_array_end;
828 sem->object_field_start = get_object_field_start;
829 sem->object_field_end = get_object_field_end;
833 sem->array_start = get_array_start;
834 sem->array_element_start = get_array_element_start;
835 sem->array_element_end = get_array_element_end;
838 pg_parse_json(lex, sem);
840 return state->tresult;
844 get_object_start(void *state)
846 GetState *_state = (GetState *) state;
847 int lex_level = _state->lex->lex_level;
849 if (lex_level == 0 && _state->npath == 0)
852 * Special case: we should match the entire object. We only need this
853 * at outermost level because at nested levels the match will have
854 * been started by the outer field or array element callback.
856 _state->result_start = _state->lex->token_start;
861 get_object_end(void *state)
863 GetState *_state = (GetState *) state;
864 int lex_level = _state->lex->lex_level;
866 if (lex_level == 0 && _state->npath == 0)
868 /* Special case: return the entire object */
869 char *start = _state->result_start;
870 int len = _state->lex->prev_token_terminator - start;
872 _state->tresult = cstring_to_text_with_len(start, len);
877 get_object_field_start(void *state, char *fname, bool isnull)
879 GetState *_state = (GetState *) state;
880 bool get_next = false;
881 int lex_level = _state->lex->lex_level;
883 if (lex_level <= _state->npath &&
884 _state->pathok[lex_level - 1] &&
885 _state->path_names != NULL &&
886 _state->path_names[lex_level - 1] != NULL &&
887 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
889 if (lex_level < _state->npath)
891 /* if not at end of path just mark path ok */
892 _state->pathok[lex_level] = true;
896 /* end of path, so we want this value */
903 /* this object overrides any previous matching object */
904 _state->tresult = NULL;
905 _state->result_start = NULL;
907 if (_state->normalize_results &&
908 _state->lex->token_type == JSON_TOKEN_STRING)
910 /* for as_text variants, tell get_scalar to set it for us */
911 _state->next_scalar = true;
915 /* for non-as_text variants, just note the json starting point */
916 _state->result_start = _state->lex->token_start;
922 get_object_field_end(void *state, char *fname, bool isnull)
924 GetState *_state = (GetState *) state;
925 bool get_last = false;
926 int lex_level = _state->lex->lex_level;
928 /* same tests as in get_object_field_start */
929 if (lex_level <= _state->npath &&
930 _state->pathok[lex_level - 1] &&
931 _state->path_names != NULL &&
932 _state->path_names[lex_level - 1] != NULL &&
933 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
935 if (lex_level < _state->npath)
937 /* done with this field so reset pathok */
938 _state->pathok[lex_level] = false;
942 /* end of path, so we want this value */
947 /* for as_text scalar case, our work is already done */
948 if (get_last && _state->result_start != NULL)
951 * make a text object from the string from the prevously noted json
952 * start up to the end of the previous token (the lexer is by now
953 * ahead of us on whatever came after what we're interested in).
955 if (isnull && _state->normalize_results)
956 _state->tresult = (text *) NULL;
959 char *start = _state->result_start;
960 int len = _state->lex->prev_token_terminator - start;
962 _state->tresult = cstring_to_text_with_len(start, len);
965 /* this should be unnecessary but let's do it for cleanliness: */
966 _state->result_start = NULL;
971 get_array_start(void *state)
973 GetState *_state = (GetState *) state;
974 int lex_level = _state->lex->lex_level;
976 if (lex_level < _state->npath)
978 /* Initialize counting of elements in this array */
979 _state->array_cur_index[lex_level] = -1;
981 /* INT_MIN value is reserved to represent invalid subscript */
982 if (_state->path_indexes[lex_level] < 0 &&
983 _state->path_indexes[lex_level] != INT_MIN)
985 /* Negative subscript -- convert to positive-wise subscript */
986 int nelements = json_count_array_elements(_state->lex);
988 if (-_state->path_indexes[lex_level] <= nelements)
989 _state->path_indexes[lex_level] += nelements;
992 else if (lex_level == 0 && _state->npath == 0)
995 * Special case: we should match the entire array. We only need this
996 * at the outermost level because at nested levels the match will
997 * have been started by the outer field or array element callback.
999 _state->result_start = _state->lex->token_start;
1004 get_array_end(void *state)
1006 GetState *_state = (GetState *) state;
1007 int lex_level = _state->lex->lex_level;
1009 if (lex_level == 0 && _state->npath == 0)
1011 /* Special case: return the entire array */
1012 char *start = _state->result_start;
1013 int len = _state->lex->prev_token_terminator - start;
1015 _state->tresult = cstring_to_text_with_len(start, len);
1020 get_array_element_start(void *state, bool isnull)
1022 GetState *_state = (GetState *) state;
1023 bool get_next = false;
1024 int lex_level = _state->lex->lex_level;
1026 /* Update array element counter */
1027 if (lex_level <= _state->npath)
1028 _state->array_cur_index[lex_level - 1]++;
1030 if (lex_level <= _state->npath &&
1031 _state->pathok[lex_level - 1] &&
1032 _state->path_indexes != NULL &&
1033 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1035 if (lex_level < _state->npath)
1037 /* if not at end of path just mark path ok */
1038 _state->pathok[lex_level] = true;
1042 /* end of path, so we want this value */
1047 /* same logic as for objects */
1050 _state->tresult = NULL;
1051 _state->result_start = NULL;
1053 if (_state->normalize_results &&
1054 _state->lex->token_type == JSON_TOKEN_STRING)
1056 _state->next_scalar = true;
1060 _state->result_start = _state->lex->token_start;
1066 get_array_element_end(void *state, bool isnull)
1068 GetState *_state = (GetState *) state;
1069 bool get_last = false;
1070 int lex_level = _state->lex->lex_level;
1072 /* same tests as in get_array_element_start */
1073 if (lex_level <= _state->npath &&
1074 _state->pathok[lex_level - 1] &&
1075 _state->path_indexes != NULL &&
1076 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1078 if (lex_level < _state->npath)
1080 /* done with this element so reset pathok */
1081 _state->pathok[lex_level] = false;
1085 /* end of path, so we want this value */
1090 /* same logic as for objects */
1091 if (get_last && _state->result_start != NULL)
1093 if (isnull && _state->normalize_results)
1094 _state->tresult = (text *) NULL;
1097 char *start = _state->result_start;
1098 int len = _state->lex->prev_token_terminator - start;
1100 _state->tresult = cstring_to_text_with_len(start, len);
1103 _state->result_start = NULL;
1108 get_scalar(void *state, char *token, JsonTokenType tokentype)
1110 GetState *_state = (GetState *) state;
1111 int lex_level = _state->lex->lex_level;
1113 /* Check for whole-object match */
1114 if (lex_level == 0 && _state->npath == 0)
1116 if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1118 /* we want the de-escaped string */
1119 _state->next_scalar = true;
1121 else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1123 _state->tresult = (text *) NULL;
1128 * This is a bit hokey: we will suppress whitespace after the
1129 * scalar token, but not whitespace before it. Probably not worth
1130 * doing our own space-skipping to avoid that.
1132 char *start = _state->lex->input;
1133 int len = _state->lex->prev_token_terminator - start;
1135 _state->tresult = cstring_to_text_with_len(start, len);
1139 if (_state->next_scalar)
1141 /* a de-escaped text value is wanted, so supply it */
1142 _state->tresult = cstring_to_text(token);
1143 /* make sure the next call to get_scalar doesn't overwrite it */
1144 _state->next_scalar = false;
1149 jsonb_extract_path(PG_FUNCTION_ARGS)
1151 return get_jsonb_path_all(fcinfo, false);
1155 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1157 return get_jsonb_path_all(fcinfo, true);
1161 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1163 Jsonb *jb = PG_GETARG_JSONB(0);
1164 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1170 bool have_object = false,
1172 JsonbValue *jbvp = NULL;
1174 JsonbContainer *container;
1177 * If the array contains any null elements, return NULL, on the grounds
1178 * that you'd have gotten NULL if any RHS value were NULL in a nested
1179 * series of applications of the -> operator. (Note: because we also
1180 * return NULL for error cases such as no-such-field, this is true
1181 * regardless of the contents of the rest of the array.)
1183 if (array_contains_nulls(path))
1186 deconstruct_array(path, TEXTOID, -1, false, 'i',
1187 &pathtext, &pathnulls, &npath);
1189 /* Identify whether we have object, array, or scalar at top-level */
1190 container = &jb->root;
1192 if (JB_ROOT_IS_OBJECT(jb))
1194 else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1198 Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
1199 /* Extract the scalar value, if it is what we'll return */
1201 jbvp = getIthJsonbValueFromContainer(container, 0);
1205 * If the array is empty, return the entire LHS object, on the grounds
1206 * that we should do zero field or element extractions. For the
1207 * non-scalar case we can just hand back the object without much work. For
1208 * the scalar case, fall through and deal with the value below the loop.
1209 * (This inconsistency arises because there's no easy way to generate a
1210 * JsonbValue directly for root-level containers.)
1212 if (npath <= 0 && jbvp == NULL)
1216 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1222 /* not text mode - just hand back the jsonb */
1223 PG_RETURN_JSONB(jb);
1227 for (i = 0; i < npath; i++)
1231 jbvp = findJsonbValueFromContainerLen(container,
1233 VARDATA_ANY(pathtext[i]),
1234 VARSIZE_ANY_EXHDR(pathtext[i]));
1236 else if (have_array)
1240 char *indextext = TextDatumGetCString(pathtext[i]);
1244 lindex = strtol(indextext, &endptr, 10);
1245 if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1246 lindex > INT_MAX || lindex < INT_MIN)
1251 index = (uint32) lindex;
1255 /* Handle negative subscript */
1258 /* Container must be array, but make sure */
1259 if ((container->header & JB_FARRAY) == 0)
1260 elog(ERROR, "not a jsonb array");
1262 nelements = container->header & JB_CMASK;
1264 if (-lindex > nelements)
1267 index = nelements + lindex;
1270 jbvp = getIthJsonbValueFromContainer(container, index);
1274 /* scalar, extraction yields a null */
1280 else if (i == npath - 1)
1283 if (jbvp->type == jbvBinary)
1285 JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1286 JsonbIteratorToken r;
1288 r = JsonbIteratorNext(&it, &tv, true);
1289 container = (JsonbContainer *) jbvp->val.binary.data;
1290 have_object = r == WJB_BEGIN_OBJECT;
1291 have_array = r == WJB_BEGIN_ARRAY;
1295 have_object = jbvp->type == jbvObject;
1296 have_array = jbvp->type == jbvArray;
1302 /* special-case outputs for string and null values */
1303 if (jbvp->type == jbvString)
1304 PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1305 jbvp->val.string.len));
1306 if (jbvp->type == jbvNull)
1310 res = JsonbValueToJsonb(jbvp);
1314 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1320 /* not text mode - just hand back the jsonb */
1321 PG_RETURN_JSONB(res);
1326 * SQL function json_array_length(json) -> int
1329 json_array_length(PG_FUNCTION_ARGS)
1331 text *json = PG_GETARG_TEXT_P(0);
1333 JsonLexContext *lex;
1336 lex = makeJsonLexContext(json, false);
1337 state = palloc0(sizeof(AlenState));
1338 sem = palloc0(sizeof(JsonSemAction));
1340 /* palloc0 does this for us */
1346 sem->semstate = (void *) state;
1347 sem->object_start = alen_object_start;
1348 sem->scalar = alen_scalar;
1349 sem->array_element_start = alen_array_element_start;
1351 pg_parse_json(lex, sem);
1353 PG_RETURN_INT32(state->count);
1357 jsonb_array_length(PG_FUNCTION_ARGS)
1359 Jsonb *jb = PG_GETARG_JSONB(0);
1361 if (JB_ROOT_IS_SCALAR(jb))
1363 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1364 errmsg("cannot get array length of a scalar")));
1365 else if (!JB_ROOT_IS_ARRAY(jb))
1367 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1368 errmsg("cannot get array length of a non-array")));
1370 PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1374 * These next two checks ensure that the json is an array (since it can't be
1375 * a scalar or an object).
1379 alen_object_start(void *state)
1381 AlenState *_state = (AlenState *) state;
1383 /* json structure check */
1384 if (_state->lex->lex_level == 0)
1386 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1387 errmsg("cannot get array length of a non-array")));
1391 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1393 AlenState *_state = (AlenState *) state;
1395 /* json structure check */
1396 if (_state->lex->lex_level == 0)
1398 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1399 errmsg("cannot get array length of a scalar")));
1403 alen_array_element_start(void *state, bool isnull)
1405 AlenState *_state = (AlenState *) state;
1407 /* just count up all the level 1 elements */
1408 if (_state->lex->lex_level == 1)
1413 * SQL function json_each and json_each_text
1415 * decompose a json object into key value pairs.
1417 * Unlike json_object_keys() these SRFs operate in materialize mode,
1418 * stashing results into a Tuplestore object as they go.
1419 * The construction of tuples is done using a temporary memory context
1420 * that is cleared out after each tuple is built.
1423 json_each(PG_FUNCTION_ARGS)
1425 return each_worker(fcinfo, false);
1429 jsonb_each(PG_FUNCTION_ARGS)
1431 return each_worker_jsonb(fcinfo, "jsonb_each", false);
1435 json_each_text(PG_FUNCTION_ARGS)
1437 return each_worker(fcinfo, true);
1441 jsonb_each_text(PG_FUNCTION_ARGS)
1443 return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1447 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1449 Jsonb *jb = PG_GETARG_JSONB(0);
1451 Tuplestorestate *tuple_store;
1453 TupleDesc ret_tdesc;
1454 MemoryContext old_cxt,
1456 bool skipNested = false;
1459 JsonbIteratorToken r;
1461 if (!JB_ROOT_IS_OBJECT(jb))
1463 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1464 errmsg("cannot call %s on a non-object",
1467 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1469 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1470 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1471 rsi->expectedDesc == NULL)
1473 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1474 errmsg("set-valued function called in context that "
1475 "cannot accept a set")));
1477 rsi->returnMode = SFRM_Materialize;
1479 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1481 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1482 errmsg("function returning record called in context "
1483 "that cannot accept type record")));
1485 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1487 ret_tdesc = CreateTupleDescCopy(tupdesc);
1488 BlessTupleDesc(ret_tdesc);
1490 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1493 MemoryContextSwitchTo(old_cxt);
1495 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1496 "jsonb_each temporary cxt",
1497 ALLOCSET_DEFAULT_MINSIZE,
1498 ALLOCSET_DEFAULT_INITSIZE,
1499 ALLOCSET_DEFAULT_MAXSIZE);
1501 it = JsonbIteratorInit(&jb->root);
1503 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1512 bool nulls[2] = {false, false};
1514 /* Use the tmp context so we can clean up after each tuple is done */
1515 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1517 key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1520 * The next thing the iterator fetches should be the value, no
1521 * matter what shape it is.
1523 r = JsonbIteratorNext(&it, &v, skipNested);
1525 values[0] = PointerGetDatum(key);
1529 if (v.type == jbvNull)
1531 /* a json null is an sql null in text mode */
1533 values[1] = (Datum) NULL;
1539 if (v.type == jbvString)
1541 /* In text mode, scalar strings should be dequoted */
1542 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1546 /* Turn anything else into a json string */
1547 StringInfo jtext = makeStringInfo();
1548 Jsonb *jb = JsonbValueToJsonb(&v);
1550 (void) JsonbToCString(jtext, &jb->root, 0);
1551 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1554 values[1] = PointerGetDatum(sv);
1559 /* Not in text mode, just return the Jsonb */
1560 Jsonb *val = JsonbValueToJsonb(&v);
1562 values[1] = PointerGetDatum(val);
1565 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1567 tuplestore_puttuple(tuple_store, tuple);
1569 /* clean up and switch back */
1570 MemoryContextSwitchTo(old_cxt);
1571 MemoryContextReset(tmp_cxt);
1575 MemoryContextDelete(tmp_cxt);
1577 rsi->setResult = tuple_store;
1578 rsi->setDesc = ret_tdesc;
1585 each_worker(FunctionCallInfo fcinfo, bool as_text)
1587 text *json = PG_GETARG_TEXT_P(0);
1588 JsonLexContext *lex;
1591 MemoryContext old_cxt;
1595 lex = makeJsonLexContext(json, true);
1596 state = palloc0(sizeof(EachState));
1597 sem = palloc0(sizeof(JsonSemAction));
1599 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1601 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1602 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1603 rsi->expectedDesc == NULL)
1605 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1606 errmsg("set-valued function called in context that "
1607 "cannot accept a set")));
1609 rsi->returnMode = SFRM_Materialize;
1611 (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1613 /* make these in a sufficiently long-lived memory context */
1614 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1616 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1617 BlessTupleDesc(state->ret_tdesc);
1618 state->tuple_store =
1619 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1622 MemoryContextSwitchTo(old_cxt);
1624 sem->semstate = (void *) state;
1625 sem->array_start = each_array_start;
1626 sem->scalar = each_scalar;
1627 sem->object_field_start = each_object_field_start;
1628 sem->object_field_end = each_object_field_end;
1630 state->normalize_results = as_text;
1631 state->next_scalar = false;
1633 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1634 "json_each temporary cxt",
1635 ALLOCSET_DEFAULT_MINSIZE,
1636 ALLOCSET_DEFAULT_INITSIZE,
1637 ALLOCSET_DEFAULT_MAXSIZE);
1639 pg_parse_json(lex, sem);
1641 MemoryContextDelete(state->tmp_cxt);
1643 rsi->setResult = state->tuple_store;
1644 rsi->setDesc = state->ret_tdesc;
1651 each_object_field_start(void *state, char *fname, bool isnull)
1653 EachState *_state = (EachState *) state;
1655 /* save a pointer to where the value starts */
1656 if (_state->lex->lex_level == 1)
1659 * next_scalar will be reset in the object_field_end handler, and
1660 * since we know the value is a scalar there is no danger of it being
1661 * on while recursing down the tree.
1663 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1664 _state->next_scalar = true;
1666 _state->result_start = _state->lex->token_start;
1671 each_object_field_end(void *state, char *fname, bool isnull)
1673 EachState *_state = (EachState *) state;
1674 MemoryContext old_cxt;
1679 bool nulls[2] = {false, false};
1681 /* skip over nested objects */
1682 if (_state->lex->lex_level != 1)
1685 /* use the tmp context so we can clean up after each tuple is done */
1686 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1688 values[0] = CStringGetTextDatum(fname);
1690 if (isnull && _state->normalize_results)
1693 values[1] = (Datum) 0;
1695 else if (_state->next_scalar)
1697 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1698 _state->next_scalar = false;
1702 len = _state->lex->prev_token_terminator - _state->result_start;
1703 val = cstring_to_text_with_len(_state->result_start, len);
1704 values[1] = PointerGetDatum(val);
1707 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1709 tuplestore_puttuple(_state->tuple_store, tuple);
1711 /* clean up and switch back */
1712 MemoryContextSwitchTo(old_cxt);
1713 MemoryContextReset(_state->tmp_cxt);
1717 each_array_start(void *state)
1719 EachState *_state = (EachState *) state;
1721 /* json structure check */
1722 if (_state->lex->lex_level == 0)
1724 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1725 errmsg("cannot deconstruct an array as an object")));
1729 each_scalar(void *state, char *token, JsonTokenType tokentype)
1731 EachState *_state = (EachState *) state;
1733 /* json structure check */
1734 if (_state->lex->lex_level == 0)
1736 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1737 errmsg("cannot deconstruct a scalar")));
1739 /* supply de-escaped value if required */
1740 if (_state->next_scalar)
1741 _state->normalized_scalar = token;
1745 * SQL functions json_array_elements and json_array_elements_text
1747 * get the elements from a json array
1749 * a lot of this processing is similar to the json_each* functions
1753 jsonb_array_elements(PG_FUNCTION_ARGS)
1755 return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1759 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1761 return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1765 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1768 Jsonb *jb = PG_GETARG_JSONB(0);
1770 Tuplestorestate *tuple_store;
1772 TupleDesc ret_tdesc;
1773 MemoryContext old_cxt,
1775 bool skipNested = false;
1778 JsonbIteratorToken r;
1780 if (JB_ROOT_IS_SCALAR(jb))
1782 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1783 errmsg("cannot extract elements from a scalar")));
1784 else if (!JB_ROOT_IS_ARRAY(jb))
1786 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1787 errmsg("cannot extract elements from an object")));
1789 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1791 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1792 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1793 rsi->expectedDesc == NULL)
1795 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1796 errmsg("set-valued function called in context that "
1797 "cannot accept a set")));
1799 rsi->returnMode = SFRM_Materialize;
1801 /* it's a simple type, so don't use get_call_result_type() */
1802 tupdesc = rsi->expectedDesc;
1804 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1806 ret_tdesc = CreateTupleDescCopy(tupdesc);
1807 BlessTupleDesc(ret_tdesc);
1809 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1812 MemoryContextSwitchTo(old_cxt);
1814 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1815 "jsonb_array_elements temporary cxt",
1816 ALLOCSET_DEFAULT_MINSIZE,
1817 ALLOCSET_DEFAULT_INITSIZE,
1818 ALLOCSET_DEFAULT_MAXSIZE);
1820 it = JsonbIteratorInit(&jb->root);
1822 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1830 bool nulls[1] = {false};
1832 /* use the tmp context so we can clean up after each tuple is done */
1833 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1837 Jsonb *val = JsonbValueToJsonb(&v);
1839 values[0] = PointerGetDatum(val);
1843 if (v.type == jbvNull)
1845 /* a json null is an sql null in text mode */
1847 values[0] = (Datum) NULL;
1853 if (v.type == jbvString)
1855 /* in text mode scalar strings should be dequoted */
1856 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1860 /* turn anything else into a json string */
1861 StringInfo jtext = makeStringInfo();
1862 Jsonb *jb = JsonbValueToJsonb(&v);
1864 (void) JsonbToCString(jtext, &jb->root, 0);
1865 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1868 values[0] = PointerGetDatum(sv);
1872 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1874 tuplestore_puttuple(tuple_store, tuple);
1876 /* clean up and switch back */
1877 MemoryContextSwitchTo(old_cxt);
1878 MemoryContextReset(tmp_cxt);
1882 MemoryContextDelete(tmp_cxt);
1884 rsi->setResult = tuple_store;
1885 rsi->setDesc = ret_tdesc;
1891 json_array_elements(PG_FUNCTION_ARGS)
1893 return elements_worker(fcinfo, "json_array_elements", false);
1897 json_array_elements_text(PG_FUNCTION_ARGS)
1899 return elements_worker(fcinfo, "json_array_elements_text", true);
1903 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1905 text *json = PG_GETARG_TEXT_P(0);
1907 /* elements only needs escaped strings when as_text */
1908 JsonLexContext *lex = makeJsonLexContext(json, as_text);
1911 MemoryContext old_cxt;
1913 ElementsState *state;
1915 state = palloc0(sizeof(ElementsState));
1916 sem = palloc0(sizeof(JsonSemAction));
1918 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1920 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1921 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1922 rsi->expectedDesc == NULL)
1924 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1925 errmsg("set-valued function called in context that "
1926 "cannot accept a set")));
1928 rsi->returnMode = SFRM_Materialize;
1930 /* it's a simple type, so don't use get_call_result_type() */
1931 tupdesc = rsi->expectedDesc;
1933 /* make these in a sufficiently long-lived memory context */
1934 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1936 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1937 BlessTupleDesc(state->ret_tdesc);
1938 state->tuple_store =
1939 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1942 MemoryContextSwitchTo(old_cxt);
1944 sem->semstate = (void *) state;
1945 sem->object_start = elements_object_start;
1946 sem->scalar = elements_scalar;
1947 sem->array_element_start = elements_array_element_start;
1948 sem->array_element_end = elements_array_element_end;
1950 state->function_name = funcname;
1951 state->normalize_results = as_text;
1952 state->next_scalar = false;
1954 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1955 "json_array_elements temporary cxt",
1956 ALLOCSET_DEFAULT_MINSIZE,
1957 ALLOCSET_DEFAULT_INITSIZE,
1958 ALLOCSET_DEFAULT_MAXSIZE);
1960 pg_parse_json(lex, sem);
1962 MemoryContextDelete(state->tmp_cxt);
1964 rsi->setResult = state->tuple_store;
1965 rsi->setDesc = state->ret_tdesc;
1971 elements_array_element_start(void *state, bool isnull)
1973 ElementsState *_state = (ElementsState *) state;
1975 /* save a pointer to where the value starts */
1976 if (_state->lex->lex_level == 1)
1979 * next_scalar will be reset in the array_element_end handler, and
1980 * since we know the value is a scalar there is no danger of it being
1981 * on while recursing down the tree.
1983 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1984 _state->next_scalar = true;
1986 _state->result_start = _state->lex->token_start;
1991 elements_array_element_end(void *state, bool isnull)
1993 ElementsState *_state = (ElementsState *) state;
1994 MemoryContext old_cxt;
1999 bool nulls[1] = {false};
2001 /* skip over nested objects */
2002 if (_state->lex->lex_level != 1)
2005 /* use the tmp context so we can clean up after each tuple is done */
2006 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2008 if (isnull && _state->normalize_results)
2011 values[0] = (Datum) NULL;
2013 else if (_state->next_scalar)
2015 values[0] = CStringGetTextDatum(_state->normalized_scalar);
2016 _state->next_scalar = false;
2020 len = _state->lex->prev_token_terminator - _state->result_start;
2021 val = cstring_to_text_with_len(_state->result_start, len);
2022 values[0] = PointerGetDatum(val);
2025 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2027 tuplestore_puttuple(_state->tuple_store, tuple);
2029 /* clean up and switch back */
2030 MemoryContextSwitchTo(old_cxt);
2031 MemoryContextReset(_state->tmp_cxt);
2035 elements_object_start(void *state)
2037 ElementsState *_state = (ElementsState *) state;
2039 /* json structure check */
2040 if (_state->lex->lex_level == 0)
2042 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2043 errmsg("cannot call %s on a non-array",
2044 _state->function_name)));
2048 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2050 ElementsState *_state = (ElementsState *) state;
2052 /* json structure check */
2053 if (_state->lex->lex_level == 0)
2055 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2056 errmsg("cannot call %s on a scalar",
2057 _state->function_name)));
2059 /* supply de-escaped value if required */
2060 if (_state->next_scalar)
2061 _state->normalized_scalar = token;
2065 * SQL function json_populate_record
2067 * set fields in a record from the argument json
2069 * Code adapted shamelessly from hstore's populate_record
2070 * which is in turn partly adapted from record_out.
2072 * The json is decomposed into a hash table, in which each
2073 * field in the record is then looked up by name. For jsonb
2074 * we fetch the values direct from the object.
2077 jsonb_populate_record(PG_FUNCTION_ARGS)
2079 return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2083 jsonb_to_record(PG_FUNCTION_ARGS)
2085 return populate_record_worker(fcinfo, "jsonb_to_record", false);
2089 json_populate_record(PG_FUNCTION_ARGS)
2091 return populate_record_worker(fcinfo, "json_populate_record", true);
2095 json_to_record(PG_FUNCTION_ARGS)
2097 return populate_record_worker(fcinfo, "json_to_record", false);
2101 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
2102 bool have_record_arg)
2104 int json_arg_num = have_record_arg ? 1 : 0;
2105 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2108 HTAB *json_hash = NULL;
2109 HeapTupleHeader rec = NULL;
2110 Oid tupType = InvalidOid;
2111 int32 tupTypmod = -1;
2113 HeapTupleData tuple;
2115 RecordIOData *my_extra;
2121 Assert(jtype == JSONOID || jtype == JSONBOID);
2123 if (have_record_arg)
2125 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2127 if (!type_is_rowtype(argtype))
2129 (errcode(ERRCODE_DATATYPE_MISMATCH),
2130 errmsg("first argument of %s must be a row type",
2133 if (PG_ARGISNULL(0))
2135 if (PG_ARGISNULL(1))
2139 * have no tuple to look at, so the only source of type info is
2140 * the argtype. The lookup_rowtype_tupdesc call below will error
2141 * out if we don't have a known composite type oid here.
2148 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2150 if (PG_ARGISNULL(1))
2151 PG_RETURN_POINTER(rec);
2153 /* Extract type info from the tuple itself */
2154 tupType = HeapTupleHeaderGetTypeId(rec);
2155 tupTypmod = HeapTupleHeaderGetTypMod(rec);
2158 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2162 /* json{b}_to_record case */
2163 if (PG_ARGISNULL(0))
2166 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2168 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2169 errmsg("function returning record called in context "
2170 "that cannot accept type record"),
2171 errhint("Try calling the function in the FROM clause "
2172 "using a column definition list.")));
2175 if (jtype == JSONOID)
2177 /* just get the text */
2178 json = PG_GETARG_TEXT_P(json_arg_num);
2180 json_hash = get_json_object_as_hash(json, funcname);
2183 * if the input json is empty, we can only skip the rest if we were
2184 * passed in a non-null record, since otherwise there may be issues
2185 * with domain nulls.
2187 if (hash_get_num_entries(json_hash) == 0 && rec)
2189 hash_destroy(json_hash);
2190 ReleaseTupleDesc(tupdesc);
2191 PG_RETURN_POINTER(rec);
2196 jb = PG_GETARG_JSONB(json_arg_num);
2198 /* same logic as for json */
2199 if (JB_ROOT_COUNT(jb) == 0 && rec)
2201 ReleaseTupleDesc(tupdesc);
2202 PG_RETURN_POINTER(rec);
2206 ncolumns = tupdesc->natts;
2210 /* Build a temporary HeapTuple control structure */
2211 tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2212 ItemPointerSetInvalid(&(tuple.t_self));
2213 tuple.t_tableOid = InvalidOid;
2218 * We arrange to look up the needed I/O info just once per series of
2219 * calls, assuming the record type doesn't change underneath us.
2221 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2222 if (my_extra == NULL ||
2223 my_extra->ncolumns != ncolumns)
2225 fcinfo->flinfo->fn_extra =
2226 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2227 offsetof(RecordIOData, columns) +
2228 ncolumns * sizeof(ColumnIOData));
2229 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2230 my_extra->record_type = InvalidOid;
2231 my_extra->record_typmod = 0;
2232 my_extra->ncolumns = ncolumns;
2233 MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2236 if (have_record_arg && (my_extra->record_type != tupType ||
2237 my_extra->record_typmod != tupTypmod))
2240 offsetof(RecordIOData, columns) +
2241 ncolumns * sizeof(ColumnIOData));
2242 my_extra->record_type = tupType;
2243 my_extra->record_typmod = tupTypmod;
2244 my_extra->ncolumns = ncolumns;
2247 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2248 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2252 /* Break down the tuple into fields */
2253 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2257 for (i = 0; i < ncolumns; ++i)
2259 values[i] = (Datum) 0;
2264 for (i = 0; i < ncolumns; ++i)
2266 ColumnIOData *column_info = &my_extra->columns[i];
2267 Oid column_type = tupdesc->attrs[i]->atttypid;
2268 JsonbValue *v = NULL;
2269 JsonHashEntry *hashentry = NULL;
2271 /* Ignore dropped columns in datatype */
2272 if (tupdesc->attrs[i]->attisdropped)
2278 if (jtype == JSONOID)
2280 hashentry = hash_search(json_hash,
2281 NameStr(tupdesc->attrs[i]->attname),
2286 char *key = NameStr(tupdesc->attrs[i]->attname);
2288 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
2293 * we can't just skip here if the key wasn't found since we might have
2294 * a domain to deal with. If we were passed in a non-null record
2295 * datum, we assume that the existing values are valid (if they're
2296 * not, then it's not our fault), but if we were passed in a null,
2297 * then every field which we don't populate needs to be run through
2298 * the input function just in case it's a domain type.
2300 if (((jtype == JSONOID && hashentry == NULL) ||
2301 (jtype == JSONBOID && v == NULL)) && rec)
2305 * Prepare to convert the column value from text
2307 if (column_info->column_type != column_type)
2309 getTypeInputInfo(column_type,
2310 &column_info->typiofunc,
2311 &column_info->typioparam);
2312 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2313 fcinfo->flinfo->fn_mcxt);
2314 column_info->column_type = column_type;
2316 if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2317 (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2320 * need InputFunctionCall to happen even for nulls, so that domain
2323 values[i] = InputFunctionCall(&column_info->proc, NULL,
2324 column_info->typioparam,
2325 tupdesc->attrs[i]->atttypmod);
2332 if (jtype == JSONOID)
2334 /* already done the hard work in the json case */
2339 if (v->type == jbvString)
2340 s = pnstrdup(v->val.string.val, v->val.string.len);
2341 else if (v->type == jbvBool)
2342 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2343 else if (v->type == jbvNumeric)
2344 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2345 PointerGetDatum(v->val.numeric)));
2346 else if (v->type == jbvBinary)
2347 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2349 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2352 values[i] = InputFunctionCall(&column_info->proc, s,
2353 column_info->typioparam,
2354 tupdesc->attrs[i]->atttypmod);
2359 rettuple = heap_form_tuple(tupdesc, values, nulls);
2361 ReleaseTupleDesc(tupdesc);
2364 hash_destroy(json_hash);
2366 PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
2370 * get_json_object_as_hash
2372 * decompose a json object into a hash table.
2375 get_json_object_as_hash(text *json, const char *funcname)
2380 JsonLexContext *lex = makeJsonLexContext(json, true);
2383 memset(&ctl, 0, sizeof(ctl));
2384 ctl.keysize = NAMEDATALEN;
2385 ctl.entrysize = sizeof(JsonHashEntry);
2386 ctl.hcxt = CurrentMemoryContext;
2387 tab = hash_create("json object hashtable",
2390 HASH_ELEM | HASH_CONTEXT);
2392 state = palloc0(sizeof(JHashState));
2393 sem = palloc0(sizeof(JsonSemAction));
2395 state->function_name = funcname;
2399 sem->semstate = (void *) state;
2400 sem->array_start = hash_array_start;
2401 sem->scalar = hash_scalar;
2402 sem->object_field_start = hash_object_field_start;
2403 sem->object_field_end = hash_object_field_end;
2405 pg_parse_json(lex, sem);
2411 hash_object_field_start(void *state, char *fname, bool isnull)
2413 JHashState *_state = (JHashState *) state;
2415 if (_state->lex->lex_level > 1)
2418 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2419 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2421 /* remember start position of the whole text of the subobject */
2422 _state->save_json_start = _state->lex->token_start;
2426 /* must be a scalar */
2427 _state->save_json_start = NULL;
2432 hash_object_field_end(void *state, char *fname, bool isnull)
2434 JHashState *_state = (JHashState *) state;
2435 JsonHashEntry *hashentry;
2439 * Ignore nested fields.
2441 if (_state->lex->lex_level > 1)
2445 * Ignore field names >= NAMEDATALEN - they can't match a record field.
2446 * (Note: without this test, the hash code would truncate the string at
2447 * NAMEDATALEN-1, and could then match against a similarly-truncated
2448 * record field name. That would be a reasonable behavior, but this code
2449 * has previously insisted on exact equality, so we keep this behavior.)
2451 if (strlen(fname) >= NAMEDATALEN)
2454 hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2457 * found being true indicates a duplicate. We don't do anything about
2458 * that, a later field with the same name overrides the earlier field.
2461 hashentry->isnull = isnull;
2462 if (_state->save_json_start != NULL)
2464 int len = _state->lex->prev_token_terminator - _state->save_json_start;
2465 char *val = palloc((len + 1) * sizeof(char));
2467 memcpy(val, _state->save_json_start, len);
2469 hashentry->val = val;
2473 /* must have had a scalar instead */
2474 hashentry->val = _state->saved_scalar;
2479 hash_array_start(void *state)
2481 JHashState *_state = (JHashState *) state;
2483 if (_state->lex->lex_level == 0)
2485 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2486 errmsg("cannot call %s on an array", _state->function_name)));
2490 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2492 JHashState *_state = (JHashState *) state;
2494 if (_state->lex->lex_level == 0)
2496 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2497 errmsg("cannot call %s on a scalar", _state->function_name)));
2499 if (_state->lex->lex_level == 1)
2500 _state->saved_scalar = token;
2505 * SQL function json_populate_recordset
2507 * set fields in a set of records from the argument json,
2508 * which must be an array of objects.
2510 * similar to json_populate_record, but the tuple-building code
2511 * is pushed down into the semantic action handlers so it's done
2512 * per object in the array.
2515 jsonb_populate_recordset(PG_FUNCTION_ARGS)
2517 return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2521 jsonb_to_recordset(PG_FUNCTION_ARGS)
2523 return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2527 json_populate_recordset(PG_FUNCTION_ARGS)
2529 return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2533 json_to_recordset(PG_FUNCTION_ARGS)
2535 return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2539 make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
2544 RecordIOData *my_extra = state->my_extra;
2545 int ncolumns = my_extra->ncolumns;
2546 TupleDesc tupdesc = state->ret_tdesc;
2547 HeapTupleHeader rec = state->rec;
2550 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2551 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2555 HeapTupleData tuple;
2557 /* Build a temporary HeapTuple control structure */
2558 tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2559 ItemPointerSetInvalid(&(tuple.t_self));
2560 tuple.t_tableOid = InvalidOid;
2561 tuple.t_data = state->rec;
2563 /* Break down the tuple into fields */
2564 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2568 for (i = 0; i < ncolumns; ++i)
2570 values[i] = (Datum) 0;
2575 for (i = 0; i < ncolumns; ++i)
2577 ColumnIOData *column_info = &my_extra->columns[i];
2578 Oid column_type = tupdesc->attrs[i]->atttypid;
2579 JsonbValue *v = NULL;
2582 /* Ignore dropped columns in datatype */
2583 if (tupdesc->attrs[i]->attisdropped)
2589 key = NameStr(tupdesc->attrs[i]->attname);
2591 v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
2595 * We can't just skip here if the key wasn't found since we might have
2596 * a domain to deal with. If we were passed in a non-null record
2597 * datum, we assume that the existing values are valid (if they're
2598 * not, then it's not our fault), but if we were passed in a null,
2599 * then every field which we don't populate needs to be run through
2600 * the input function just in case it's a domain type.
2602 if (v == NULL && rec)
2606 * Prepare to convert the column value from text
2608 if (column_info->column_type != column_type)
2610 getTypeInputInfo(column_type,
2611 &column_info->typiofunc,
2612 &column_info->typioparam);
2613 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2615 column_info->column_type = column_type;
2617 if (v == NULL || v->type == jbvNull)
2620 * Need InputFunctionCall to happen even for nulls, so that domain
2623 values[i] = InputFunctionCall(&column_info->proc, NULL,
2624 column_info->typioparam,
2625 tupdesc->attrs[i]->atttypmod);
2632 if (v->type == jbvString)
2633 s = pnstrdup(v->val.string.val, v->val.string.len);
2634 else if (v->type == jbvBool)
2635 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2636 else if (v->type == jbvNumeric)
2637 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2638 PointerGetDatum(v->val.numeric)));
2639 else if (v->type == jbvBinary)
2640 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2642 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2644 values[i] = InputFunctionCall(&column_info->proc, s,
2645 column_info->typioparam,
2646 tupdesc->attrs[i]->atttypmod);
2651 rettuple = heap_form_tuple(tupdesc, values, nulls);
2653 tuplestore_puttuple(state->tuple_store, rettuple);
2657 * common worker for json_populate_recordset() and json_to_recordset()
2660 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
2661 bool have_record_arg)
2663 int json_arg_num = have_record_arg ? 1 : 0;
2664 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2666 MemoryContext old_cxt;
2669 HeapTupleHeader rec;
2671 RecordIOData *my_extra;
2673 PopulateRecordsetState *state;
2675 if (have_record_arg)
2677 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2679 if (!type_is_rowtype(argtype))
2681 (errcode(ERRCODE_DATATYPE_MISMATCH),
2682 errmsg("first argument of %s must be a row type",
2686 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2688 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2689 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2690 rsi->expectedDesc == NULL)
2692 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2693 errmsg("set-valued function called in context that "
2694 "cannot accept a set")));
2696 rsi->returnMode = SFRM_Materialize;
2699 * get the tupdesc from the result set info - it must be a record type
2700 * because we already checked that arg1 is a record type, or we're in a
2701 * to_record function which returns a setof record.
2703 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2705 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2706 errmsg("function returning record called in context "
2707 "that cannot accept type record")));
2709 /* if the json is null send back an empty set */
2710 if (PG_ARGISNULL(json_arg_num))
2713 if (!have_record_arg || PG_ARGISNULL(0))
2716 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2718 tupType = tupdesc->tdtypeid;
2719 tupTypmod = tupdesc->tdtypmod;
2720 ncolumns = tupdesc->natts;
2723 * We arrange to look up the needed I/O info just once per series of
2724 * calls, assuming the record type doesn't change underneath us.
2726 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2727 if (my_extra == NULL ||
2728 my_extra->ncolumns != ncolumns)
2730 fcinfo->flinfo->fn_extra =
2731 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2732 offsetof(RecordIOData, columns) +
2733 ncolumns * sizeof(ColumnIOData));
2734 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2735 my_extra->record_type = InvalidOid;
2736 my_extra->record_typmod = 0;
2739 if (my_extra->record_type != tupType ||
2740 my_extra->record_typmod != tupTypmod)
2743 offsetof(RecordIOData, columns) +
2744 ncolumns * sizeof(ColumnIOData));
2745 my_extra->record_type = tupType;
2746 my_extra->record_typmod = tupTypmod;
2747 my_extra->ncolumns = ncolumns;
2750 state = palloc0(sizeof(PopulateRecordsetState));
2752 /* make these in a sufficiently long-lived memory context */
2753 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2754 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2755 BlessTupleDesc(state->ret_tdesc);
2756 state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
2757 SFRM_Materialize_Random,
2759 MemoryContextSwitchTo(old_cxt);
2761 state->function_name = funcname;
2762 state->my_extra = my_extra;
2764 state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2766 if (jtype == JSONOID)
2768 text *json = PG_GETARG_TEXT_P(json_arg_num);
2769 JsonLexContext *lex;
2772 sem = palloc0(sizeof(JsonSemAction));
2774 lex = makeJsonLexContext(json, true);
2776 sem->semstate = (void *) state;
2777 sem->array_start = populate_recordset_array_start;
2778 sem->array_element_start = populate_recordset_array_element_start;
2779 sem->scalar = populate_recordset_scalar;
2780 sem->object_field_start = populate_recordset_object_field_start;
2781 sem->object_field_end = populate_recordset_object_field_end;
2782 sem->object_start = populate_recordset_object_start;
2783 sem->object_end = populate_recordset_object_end;
2787 pg_parse_json(lex, sem);
2791 Jsonb *jb = PG_GETARG_JSONB(json_arg_num);
2794 bool skipNested = false;
2795 JsonbIteratorToken r;
2797 Assert(jtype == JSONBOID);
2799 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2801 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2802 errmsg("cannot call %s on a non-array",
2805 it = JsonbIteratorInit(&jb->root);
2807 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2813 Jsonb *element = JsonbValueToJsonb(&v);
2815 if (!JB_ROOT_IS_OBJECT(element))
2817 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2818 errmsg("argument of %s must be an array of objects",
2820 make_row_from_rec_and_jsonb(element, state);
2825 rsi->setResult = state->tuple_store;
2826 rsi->setDesc = state->ret_tdesc;
2832 populate_recordset_object_start(void *state)
2834 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2835 int lex_level = _state->lex->lex_level;
2838 /* Reject object at top level: we must have an array at level 0 */
2841 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2842 errmsg("cannot call %s on an object",
2843 _state->function_name)));
2845 /* Nested objects require no special processing */
2849 /* Object at level 1: set up a new hash table for this object */
2850 memset(&ctl, 0, sizeof(ctl));
2851 ctl.keysize = NAMEDATALEN;
2852 ctl.entrysize = sizeof(JsonHashEntry);
2853 ctl.hcxt = CurrentMemoryContext;
2854 _state->json_hash = hash_create("json object hashtable",
2857 HASH_ELEM | HASH_CONTEXT);
2861 populate_recordset_object_end(void *state)
2863 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2864 HTAB *json_hash = _state->json_hash;
2868 RecordIOData *my_extra = _state->my_extra;
2869 int ncolumns = my_extra->ncolumns;
2870 TupleDesc tupdesc = _state->ret_tdesc;
2871 JsonHashEntry *hashentry;
2872 HeapTupleHeader rec = _state->rec;
2875 /* Nested objects require no special processing */
2876 if (_state->lex->lex_level > 1)
2879 /* Otherwise, construct and return a tuple based on this level-1 object */
2880 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2881 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2885 HeapTupleData tuple;
2887 /* Build a temporary HeapTuple control structure */
2888 tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2889 ItemPointerSetInvalid(&(tuple.t_self));
2890 tuple.t_tableOid = InvalidOid;
2891 tuple.t_data = _state->rec;
2893 /* Break down the tuple into fields */
2894 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2898 for (i = 0; i < ncolumns; ++i)
2900 values[i] = (Datum) 0;
2905 for (i = 0; i < ncolumns; ++i)
2907 ColumnIOData *column_info = &my_extra->columns[i];
2908 Oid column_type = tupdesc->attrs[i]->atttypid;
2911 /* Ignore dropped columns in datatype */
2912 if (tupdesc->attrs[i]->attisdropped)
2918 hashentry = hash_search(json_hash,
2919 NameStr(tupdesc->attrs[i]->attname),
2923 * we can't just skip here if the key wasn't found since we might have
2924 * a domain to deal with. If we were passed in a non-null record
2925 * datum, we assume that the existing values are valid (if they're
2926 * not, then it's not our fault), but if we were passed in a null,
2927 * then every field which we don't populate needs to be run through
2928 * the input function just in case it's a domain type.
2930 if (hashentry == NULL && rec)
2934 * Prepare to convert the column value from text
2936 if (column_info->column_type != column_type)
2938 getTypeInputInfo(column_type,
2939 &column_info->typiofunc,
2940 &column_info->typioparam);
2941 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2943 column_info->column_type = column_type;
2945 if (hashentry == NULL || hashentry->isnull)
2948 * need InputFunctionCall to happen even for nulls, so that domain
2951 values[i] = InputFunctionCall(&column_info->proc, NULL,
2952 column_info->typioparam,
2953 tupdesc->attrs[i]->atttypmod);
2958 value = hashentry->val;
2960 values[i] = InputFunctionCall(&column_info->proc, value,
2961 column_info->typioparam,
2962 tupdesc->attrs[i]->atttypmod);
2967 rettuple = heap_form_tuple(tupdesc, values, nulls);
2969 tuplestore_puttuple(_state->tuple_store, rettuple);
2971 /* Done with hash for this object */
2972 hash_destroy(json_hash);
2973 _state->json_hash = NULL;
2977 populate_recordset_array_element_start(void *state, bool isnull)
2979 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2981 if (_state->lex->lex_level == 1 &&
2982 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
2984 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2985 errmsg("argument of %s must be an array of objects",
2986 _state->function_name)));
2990 populate_recordset_array_start(void *state)
2996 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
2998 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3000 if (_state->lex->lex_level == 0)
3002 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3003 errmsg("cannot call %s on a scalar",
3004 _state->function_name)));
3006 if (_state->lex->lex_level == 2)
3007 _state->saved_scalar = token;
3011 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
3013 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3015 if (_state->lex->lex_level > 2)
3018 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3019 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
3021 _state->save_json_start = _state->lex->token_start;
3025 _state->save_json_start = NULL;
3030 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
3032 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3033 JsonHashEntry *hashentry;
3037 * Ignore nested fields.
3039 if (_state->lex->lex_level > 2)
3043 * Ignore field names >= NAMEDATALEN - they can't match a record field.
3044 * (Note: without this test, the hash code would truncate the string at
3045 * NAMEDATALEN-1, and could then match against a similarly-truncated
3046 * record field name. That would be a reasonable behavior, but this code
3047 * has previously insisted on exact equality, so we keep this behavior.)
3049 if (strlen(fname) >= NAMEDATALEN)
3052 hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
3055 * found being true indicates a duplicate. We don't do anything about
3056 * that, a later field with the same name overrides the earlier field.
3059 hashentry->isnull = isnull;
3060 if (_state->save_json_start != NULL)
3062 int len = _state->lex->prev_token_terminator - _state->save_json_start;
3063 char *val = palloc((len + 1) * sizeof(char));
3065 memcpy(val, _state->save_json_start, len);
3067 hashentry->val = val;
3071 /* must have had a scalar instead */
3072 hashentry->val = _state->saved_scalar;
3077 * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3080 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
3081 char *key, uint32 keylen)
3086 k.val.string.val = key;
3087 k.val.string.len = keylen;
3089 return findJsonbValueFromContainer(container, flags, &k);
3093 * Semantic actions for json_strip_nulls.
3095 * Simply repeat the input on the output unless we encounter
3096 * a null object field. State for this is set when the field
3097 * is started and reset when the scalar action (which must be next)
3102 sn_object_start(void *state)
3104 StripnullState *_state = (StripnullState *) state;
3106 appendStringInfoCharMacro(_state->strval, '{');
3110 sn_object_end(void *state)
3112 StripnullState *_state = (StripnullState *) state;
3114 appendStringInfoCharMacro(_state->strval, '}');
3118 sn_array_start(void *state)
3120 StripnullState *_state = (StripnullState *) state;
3122 appendStringInfoCharMacro(_state->strval, '[');
3126 sn_array_end(void *state)
3128 StripnullState *_state = (StripnullState *) state;
3130 appendStringInfoCharMacro(_state->strval, ']');
3134 sn_object_field_start(void *state, char *fname, bool isnull)
3136 StripnullState *_state = (StripnullState *) state;
3141 * The next thing must be a scalar or isnull couldn't be true, so
3142 * there is no danger of this state being carried down into a nested
3143 * object or array. The flag will be reset in the scalar action.
3145 _state->skip_next_null = true;
3149 if (_state->strval->data[_state->strval->len - 1] != '{')
3150 appendStringInfoCharMacro(_state->strval, ',');
3153 * Unfortunately we don't have the quoted and escaped string any more, so
3154 * we have to re-escape it.
3156 escape_json(_state->strval, fname);
3158 appendStringInfoCharMacro(_state->strval, ':');
3162 sn_array_element_start(void *state, bool isnull)
3164 StripnullState *_state = (StripnullState *) state;
3166 if (_state->strval->data[_state->strval->len - 1] != '[')
3167 appendStringInfoCharMacro(_state->strval, ',');
3171 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3173 StripnullState *_state = (StripnullState *) state;
3175 if (_state->skip_next_null)
3177 Assert(tokentype == JSON_TOKEN_NULL);
3178 _state->skip_next_null = false;
3182 if (tokentype == JSON_TOKEN_STRING)
3183 escape_json(_state->strval, token);
3185 appendStringInfoString(_state->strval, token);
3189 * SQL function json_strip_nulls(json) -> json
3192 json_strip_nulls(PG_FUNCTION_ARGS)
3194 text *json = PG_GETARG_TEXT_P(0);
3195 StripnullState *state;
3196 JsonLexContext *lex;
3199 lex = makeJsonLexContext(json, true);
3200 state = palloc0(sizeof(StripnullState));
3201 sem = palloc0(sizeof(JsonSemAction));
3203 state->strval = makeStringInfo();
3204 state->skip_next_null = false;
3207 sem->semstate = (void *) state;
3208 sem->object_start = sn_object_start;
3209 sem->object_end = sn_object_end;
3210 sem->array_start = sn_array_start;
3211 sem->array_end = sn_array_end;
3212 sem->scalar = sn_scalar;
3213 sem->array_element_start = sn_array_element_start;
3214 sem->object_field_start = sn_object_field_start;
3216 pg_parse_json(lex, sem);
3218 PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
3219 state->strval->len));
3224 * SQL function jsonb_strip_nulls(jsonb) -> jsonb
3227 jsonb_strip_nulls(PG_FUNCTION_ARGS)
3229 Jsonb *jb = PG_GETARG_JSONB(0);
3231 JsonbParseState *parseState = NULL;
3232 JsonbValue *res = NULL;
3235 JsonbIteratorToken type;
3236 bool last_was_key = false;
3238 if (JB_ROOT_IS_SCALAR(jb))
3239 PG_RETURN_POINTER(jb);
3241 it = JsonbIteratorInit(&jb->root);
3243 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3245 Assert(!(type == WJB_KEY && last_was_key));
3247 if (type == WJB_KEY)
3249 /* stash the key until we know if it has a null value */
3251 last_was_key = true;
3257 /* if the last element was a key this one can't be */
3258 last_was_key = false;
3260 /* skip this field if value is null */
3261 if (type == WJB_VALUE && v.type == jbvNull)
3264 /* otherwise, do a delayed push of the key */
3265 (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3268 if (type == WJB_VALUE || type == WJB_ELEM)
3269 res = pushJsonbValue(&parseState, type, &v);
3271 res = pushJsonbValue(&parseState, type, NULL);
3274 Assert(res != NULL);
3276 PG_RETURN_POINTER(JsonbValueToJsonb(res));
3280 * Add values from the jsonb to the parse state.
3282 * If the parse state container is an object, the jsonb is pushed as
3283 * a value, not a key.
3285 * This needs to be done using an iterator because pushJsonbValue doesn't
3286 * like getting jbvBinary values, so we can't just push jb as a whole.
3289 addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
3292 JsonbValue *o = &(*jbps)->contVal;
3294 JsonbIteratorToken type;
3296 it = JsonbIteratorInit(&jb->root);
3298 Assert(o->type == jbvArray || o->type == jbvObject);
3300 if (JB_ROOT_IS_SCALAR(jb))
3302 (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3303 (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3308 (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3311 (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3314 elog(ERROR, "unexpected parent of nested structure");
3319 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3321 if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3322 (void) pushJsonbValue(jbps, type, &v);
3324 (void) pushJsonbValue(jbps, type, NULL);
3331 * SQL function jsonb_pretty (jsonb)
3333 * Pretty-printed text for the jsonb
3336 jsonb_pretty(PG_FUNCTION_ARGS)
3338 Jsonb *jb = PG_GETARG_JSONB(0);
3339 StringInfo str = makeStringInfo();
3341 JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3343 PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
3347 * SQL function jsonb_concat (jsonb, jsonb)
3349 * function for || operator
3352 jsonb_concat(PG_FUNCTION_ARGS)
3354 Jsonb *jb1 = PG_GETARG_JSONB(0);
3355 Jsonb *jb2 = PG_GETARG_JSONB(1);
3356 JsonbParseState *state = NULL;
3362 * If one of the jsonb is empty, just return the other if it's not
3363 * scalar and both are of the same kind. If it's a scalar or they are
3364 * of different kinds we need to perform the concatenation even if one is
3367 if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
3369 if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
3370 PG_RETURN_JSONB(jb2);
3371 else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
3372 PG_RETURN_JSONB(jb1);
3375 it1 = JsonbIteratorInit(&jb1->root);
3376 it2 = JsonbIteratorInit(&jb2->root);
3378 res = IteratorConcat(&it1, &it2, &state);
3380 Assert(res != NULL);
3382 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3387 * SQL function jsonb_delete (jsonb, text)
3389 * return a copy of the jsonb with the indicated item
3393 jsonb_delete(PG_FUNCTION_ARGS)
3395 Jsonb *in = PG_GETARG_JSONB(0);
3396 text *key = PG_GETARG_TEXT_PP(1);
3397 char *keyptr = VARDATA_ANY(key);
3398 int keylen = VARSIZE_ANY_EXHDR(key);
3399 JsonbParseState *state = NULL;
3403 bool skipNested = false;
3404 JsonbIteratorToken r;
3406 if (JB_ROOT_IS_SCALAR(in))
3408 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3409 errmsg("cannot delete from scalar")));
3411 if (JB_ROOT_COUNT(in) == 0)
3412 PG_RETURN_JSONB(in);
3414 it = JsonbIteratorInit(&in->root);
3416 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3420 if ((r == WJB_ELEM || r == WJB_KEY) &&
3421 (v.type == jbvString && keylen == v.val.string.len &&
3422 memcmp(keyptr, v.val.string.val, keylen) == 0))
3424 /* skip corresponding value as well */
3426 JsonbIteratorNext(&it, &v, true);
3431 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3434 Assert(res != NULL);
3436 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3440 * SQL function jsonb_delete (jsonb, int)
3442 * return a copy of the jsonb with the indicated item
3443 * removed. Negative int means count back from the
3447 jsonb_delete_idx(PG_FUNCTION_ARGS)
3449 Jsonb *in = PG_GETARG_JSONB(0);
3450 int idx = PG_GETARG_INT32(1);
3451 JsonbParseState *state = NULL;
3457 JsonbIteratorToken r;
3459 if (JB_ROOT_IS_SCALAR(in))
3461 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3462 errmsg("cannot delete from scalar")));
3464 if (JB_ROOT_IS_OBJECT(in))
3466 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3467 errmsg("cannot delete from object using integer index")));
3469 if (JB_ROOT_COUNT(in) == 0)
3470 PG_RETURN_JSONB(in);
3472 it = JsonbIteratorInit(&in->root);
3474 r = JsonbIteratorNext(&it, &v, false);
3475 Assert (r == WJB_BEGIN_ARRAY);
3476 n = v.val.array.nElems;
3487 PG_RETURN_JSONB(in);
3489 pushJsonbValue(&state, r, NULL);
3491 while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3499 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3502 Assert(res != NULL);
3504 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3508 * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
3512 jsonb_set(PG_FUNCTION_ARGS)
3514 Jsonb *in = PG_GETARG_JSONB(0);
3515 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3516 Jsonb *newval = PG_GETARG_JSONB(2);
3517 bool create = PG_GETARG_BOOL(3);
3518 JsonbValue *res = NULL;
3523 JsonbParseState *st = NULL;
3525 if (ARR_NDIM(path) > 1)
3527 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3528 errmsg("wrong number of array subscripts")));
3530 if (JB_ROOT_IS_SCALAR(in))
3532 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3533 errmsg("cannot set path in scalar")));
3535 if (JB_ROOT_COUNT(in) == 0 && !create)
3536 PG_RETURN_JSONB(in);
3538 deconstruct_array(path, TEXTOID, -1, false, 'i',
3539 &path_elems, &path_nulls, &path_len);
3542 PG_RETURN_JSONB(in);
3544 it = JsonbIteratorInit(&in->root);
3546 res = setPath(&it, path_elems, path_nulls, path_len, &st,
3549 Assert(res != NULL);
3551 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3556 * SQL function jsonb_delete(jsonb, text[])
3559 jsonb_delete_path(PG_FUNCTION_ARGS)
3561 Jsonb *in = PG_GETARG_JSONB(0);
3562 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3563 JsonbValue *res = NULL;
3568 JsonbParseState *st = NULL;
3570 if (ARR_NDIM(path) > 1)
3572 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3573 errmsg("wrong number of array subscripts")));
3575 if (JB_ROOT_IS_SCALAR(in))
3577 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3578 errmsg("cannot delete path in scalar")));
3580 if (JB_ROOT_COUNT(in) == 0)
3581 PG_RETURN_JSONB(in);
3583 deconstruct_array(path, TEXTOID, -1, false, 'i',
3584 &path_elems, &path_nulls, &path_len);
3587 PG_RETURN_JSONB(in);
3589 it = JsonbIteratorInit(&in->root);
3591 res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, NULL, false);
3593 Assert(res != NULL);
3595 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3599 * Iterate over all jsonb objects and merge them into one.
3600 * The logic of this function copied from the same hstore function,
3601 * except the case, when it1 & it2 represents jbvObject.
3602 * In that case we just append the content of it2 to it1 without any
3606 IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3607 JsonbParseState **state)
3612 JsonbIteratorToken r1,
3617 r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3618 r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3621 * Both elements are objects.
3623 if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3626 * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3627 * (because res will not be finished yet).
3629 pushJsonbValue(state, r1, NULL);
3630 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3631 pushJsonbValue(state, r1, &v1);
3634 * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3635 * (the concatenation will be completed).
3637 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3638 res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3642 * Both elements are arrays (either can be scalar).
3644 else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3646 pushJsonbValue(state, r1, NULL);
3648 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3650 Assert(r1 == WJB_ELEM);
3651 pushJsonbValue(state, r1, &v1);
3654 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
3656 Assert(r2 == WJB_ELEM);
3657 pushJsonbValue(state, WJB_ELEM, &v2);
3660 res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
3662 /* have we got array || object or object || array? */
3663 else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3664 (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3667 JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3668 JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3670 bool prepend = (rk1 == WJB_BEGIN_OBJECT);
3672 pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
3676 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3677 while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3678 pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
3680 while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3681 res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
3685 while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3686 pushJsonbValue(state, r1, &v1);
3688 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3689 while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3690 pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3692 res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3698 * This must be scalar || object or object || scalar, as that's all
3699 * that's left. Both of these make no sense, so error out.
3702 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3703 errmsg("invalid concatenation of jsonb objects")));
3710 * Do most of the heavy work for jsonb_set
3712 * If newval is null, the element is to be removed.
3714 * If create is true, we create the new value if the key or array index
3715 * does not exist. All path elements before the last must already exist
3716 * whether or not create is true, or nothing is done.
3719 setPath(JsonbIterator **it, Datum *path_elems,
3720 bool *path_nulls, int path_len,
3721 JsonbParseState **st, int level, Jsonb *newval, bool create)
3724 JsonbIteratorToken r;
3725 JsonbValue *res = NULL;
3727 check_stack_depth();
3729 if (path_nulls[level])
3730 elog(ERROR, "path element at the position %d is NULL", level + 1);
3732 r = JsonbIteratorNext(it, &v, false);
3736 case WJB_BEGIN_ARRAY:
3737 (void) pushJsonbValue(st, r, NULL);
3738 setPathArray(it, path_elems, path_nulls, path_len, st, level,
3739 newval, v.val.array.nElems, create);
3740 r = JsonbIteratorNext(it, &v, false);
3741 Assert(r == WJB_END_ARRAY);
3742 res = pushJsonbValue(st, r, NULL);
3745 case WJB_BEGIN_OBJECT:
3746 (void) pushJsonbValue(st, r, NULL);
3747 setPathObject(it, path_elems, path_nulls, path_len, st, level,
3748 newval, v.val.object.nPairs, create);
3749 r = JsonbIteratorNext(it, &v, true);
3750 Assert(r == WJB_END_OBJECT);
3751 res = pushJsonbValue(st, r, NULL);
3756 res = pushJsonbValue(st, r, &v);
3759 elog(ERROR, "impossible state");
3766 * Object walker for setPath
3769 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3770 int path_len, JsonbParseState **st, int level,
3771 Jsonb *newval, uint32 npairs, bool create)
3778 if (level >= path_len || path_nulls[level])
3781 /* empty object is a special case for create */
3782 if ((npairs == 0) && create && (level == path_len - 1))
3786 newkey.type = jbvString;
3787 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3788 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3790 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3791 addJsonbToParseState(st, newval);
3794 for (i = 0; i < npairs; i++)
3796 JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
3798 Assert(r == WJB_KEY);
3801 k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
3802 memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
3803 k.val.string.len) == 0)
3805 if (level == path_len - 1)
3807 r = JsonbIteratorNext(it, &v, true); /* skip */
3810 (void) pushJsonbValue(st, WJB_KEY, &k);
3811 addJsonbToParseState(st, newval);
3817 (void) pushJsonbValue(st, r, &k);
3818 setPath(it, path_elems, path_nulls, path_len,
3819 st, level + 1, newval, create);
3824 if (create && !done && level == path_len - 1 && i == npairs - 1)
3828 newkey.type = jbvString;
3829 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3830 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3832 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3833 addJsonbToParseState(st, newval);
3836 (void) pushJsonbValue(st, r, &k);
3837 r = JsonbIteratorNext(it, &v, false);
3838 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3839 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3841 int walking_level = 1;
3843 while (walking_level != 0)
3845 r = JsonbIteratorNext(it, &v, false);
3847 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3849 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
3852 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3860 * Array walker for setPath
3863 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3864 int path_len, JsonbParseState **st, int level,
3865 Jsonb *newval, uint32 nelems, bool create)
3873 /* pick correct index */
3874 if (level < path_len && !path_nulls[level])
3876 char *c = VARDATA_ANY(path_elems[level]);
3880 lindex = strtol(c, &badp, 10);
3881 if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
3883 elog(ERROR, "path element at the position %d is not an integer", level + 1);
3898 if (idx > 0 && idx > nelems)
3902 * if we're creating, and idx == INT_MIN, we prepend the new value to the
3903 * array also if the array is empty - in which case we don't really care
3904 * what the idx value is
3907 if ((idx == INT_MIN || nelems == 0) && create && (level == path_len - 1))
3909 Assert(newval != NULL);
3910 addJsonbToParseState(st, newval);
3914 /* iterate over the array elements */
3915 for (i = 0; i < nelems; i++)
3917 JsonbIteratorToken r;
3919 if (i == idx && level < path_len)
3921 if (level == path_len - 1)
3923 r = JsonbIteratorNext(it, &v, true); /* skip */
3925 addJsonbToParseState(st, newval);
3930 (void) setPath(it, path_elems, path_nulls, path_len,
3931 st, level + 1, newval, create);
3935 r = JsonbIteratorNext(it, &v, false);
3937 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3939 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3941 int walking_level = 1;
3943 while (walking_level != 0)
3945 r = JsonbIteratorNext(it, &v, false);
3947 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3949 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
3952 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3956 if (create && !done && level == path_len - 1 && i == nelems - 1)
3958 addJsonbToParseState(st, newval);