1 /*-------------------------------------------------------------------------
4 * Functions to process JSON data types.
6 * Portions Copyright (c) 1996-2017, 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 /* Operations available for setPath */
37 #define JB_PATH_CREATE 0x0001
38 #define JB_PATH_DELETE 0x0002
39 #define JB_PATH_REPLACE 0x0004
40 #define JB_PATH_INSERT_BEFORE 0x0008
41 #define JB_PATH_INSERT_AFTER 0x0010
42 #define JB_PATH_CREATE_OR_INSERT \
43 (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
45 /* state for json_object_keys */
46 typedef struct OkeysState
55 /* state for json_get* functions */
56 typedef struct GetState
61 bool normalize_results;
63 int npath; /* length of each path-related array */
64 char **path_names; /* field name(s) being sought */
65 int *path_indexes; /* array index(es) being sought */
66 bool *pathok; /* is path matched to current depth? */
67 int *array_cur_index; /* current element index at each path level */
70 /* state for json_array_length */
71 typedef struct AlenState
77 /* state for json_each */
78 typedef struct EachState
81 Tuplestorestate *tuple_store;
83 MemoryContext tmp_cxt;
85 bool normalize_results;
87 char *normalized_scalar;
90 /* state for json_array_elements */
91 typedef struct ElementsState
94 const char *function_name;
95 Tuplestorestate *tuple_store;
97 MemoryContext tmp_cxt;
99 bool normalize_results;
101 char *normalized_scalar;
104 /* state for get_json_object_as_hash */
105 typedef struct JhashState
108 const char *function_name;
111 char *save_json_start;
114 /* hashtable element */
115 typedef struct JsonHashEntry
117 char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
123 /* these two are stolen from hstore / record_out, used in populate_record* */
124 typedef struct ColumnIOData
132 typedef struct RecordIOData
137 ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
140 /* state for populate_recordset */
141 typedef struct PopulateRecordsetState
144 const char *function_name;
147 char *save_json_start;
148 Tuplestorestate *tuple_store;
151 RecordIOData *my_extra;
152 MemoryContext fn_mcxt; /* used to stash IO funcs */
153 } PopulateRecordsetState;
155 /* state for json_strip_nulls */
156 typedef struct StripnullState
163 /* semantic action functions for json_object_keys */
164 static void okeys_object_field_start(void *state, char *fname, bool isnull);
165 static void okeys_array_start(void *state);
166 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
168 /* semantic action functions for json_get* functions */
169 static void get_object_start(void *state);
170 static void get_object_end(void *state);
171 static void get_object_field_start(void *state, char *fname, bool isnull);
172 static void get_object_field_end(void *state, char *fname, bool isnull);
173 static void get_array_start(void *state);
174 static void get_array_end(void *state);
175 static void get_array_element_start(void *state, bool isnull);
176 static void get_array_element_end(void *state, bool isnull);
177 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
179 /* common worker function for json getter functions */
180 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
181 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
182 bool normalize_results);
183 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
185 /* semantic action functions for json_array_length */
186 static void alen_object_start(void *state);
187 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
188 static void alen_array_element_start(void *state, bool isnull);
190 /* common workers for json{b}_each* functions */
191 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
192 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
195 /* semantic action functions for json_each */
196 static void each_object_field_start(void *state, char *fname, bool isnull);
197 static void each_object_field_end(void *state, char *fname, bool isnull);
198 static void each_array_start(void *state);
199 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
201 /* common workers for json{b}_array_elements_* functions */
202 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
204 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
207 /* semantic action functions for json_array_elements */
208 static void elements_object_start(void *state);
209 static void elements_array_element_start(void *state, bool isnull);
210 static void elements_array_element_end(void *state, bool isnull);
211 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
213 /* turn a json object into a hash table */
214 static HTAB *get_json_object_as_hash(text *json, const char *funcname);
216 /* common worker for populate_record and to_record */
217 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
218 bool have_record_arg);
220 /* semantic action functions for get_json_object_as_hash */
221 static void hash_object_field_start(void *state, char *fname, bool isnull);
222 static void hash_object_field_end(void *state, char *fname, bool isnull);
223 static void hash_array_start(void *state);
224 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
226 /* semantic action functions for populate_recordset */
227 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
228 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
229 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
230 static void populate_recordset_object_start(void *state);
231 static void populate_recordset_object_end(void *state);
232 static void populate_recordset_array_start(void *state);
233 static void populate_recordset_array_element_start(void *state, bool isnull);
235 /* semantic action functions for json_strip_nulls */
236 static void sn_object_start(void *state);
237 static void sn_object_end(void *state);
238 static void sn_array_start(void *state);
239 static void sn_array_end(void *state);
240 static void sn_object_field_start(void *state, char *fname, bool isnull);
241 static void sn_array_element_start(void *state, bool isnull);
242 static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
244 /* Turn a jsonb object into a record */
245 static void make_row_from_rec_and_jsonb(Jsonb *element,
246 PopulateRecordsetState *state);
248 /* worker function for populate_recordset and to_recordset */
249 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
250 bool have_record_arg);
252 /* Worker that takes care of common setup for us */
253 static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
258 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
259 static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
260 JsonbParseState **state);
261 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
262 bool *path_nulls, int path_len,
263 JsonbParseState **st, int level, Jsonb *newval,
265 static void setPathObject(JsonbIterator **it, Datum *path_elems,
266 bool *path_nulls, int path_len, JsonbParseState **st,
268 Jsonb *newval, uint32 npairs, int op_type);
269 static void setPathArray(JsonbIterator **it, Datum *path_elems,
270 bool *path_nulls, int path_len, JsonbParseState **st,
271 int level, Jsonb *newval, uint32 nelems, int op_type);
272 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
276 * SQL function json_object_keys
278 * Returns the set of keys for the object argument.
280 * This SRF operates in value-per-call mode. It processes the
281 * object during the first call, and the keys are simply stashed
282 * in an array, whose size is expanded as necessary. This is probably
283 * safe enough for a list of keys of a single object, since they are
284 * limited in size to NAMEDATALEN and the number of keys is unlikely to
285 * be so huge that it has major memory implications.
288 jsonb_object_keys(PG_FUNCTION_ARGS)
290 FuncCallContext *funcctx;
294 if (SRF_IS_FIRSTCALL())
296 MemoryContext oldcontext;
297 Jsonb *jb = PG_GETARG_JSONB(0);
298 bool skipNested = false;
301 JsonbIteratorToken r;
303 if (JB_ROOT_IS_SCALAR(jb))
305 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306 errmsg("cannot call %s on a scalar",
307 "jsonb_object_keys")));
308 else if (JB_ROOT_IS_ARRAY(jb))
310 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
311 errmsg("cannot call %s on an array",
312 "jsonb_object_keys")));
314 funcctx = SRF_FIRSTCALL_INIT();
315 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
317 state = palloc(sizeof(OkeysState));
319 state->result_size = JB_ROOT_COUNT(jb);
320 state->result_count = 0;
321 state->sent_count = 0;
322 state->result = palloc(state->result_size * sizeof(char *));
324 it = JsonbIteratorInit(&jb->root);
326 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
334 cstr = palloc(v.val.string.len + 1 * sizeof(char));
335 memcpy(cstr, v.val.string.val, v.val.string.len);
336 cstr[v.val.string.len] = '\0';
337 state->result[state->result_count++] = cstr;
341 MemoryContextSwitchTo(oldcontext);
342 funcctx->user_fctx = (void *) state;
345 funcctx = SRF_PERCALL_SETUP();
346 state = (OkeysState *) funcctx->user_fctx;
348 if (state->sent_count < state->result_count)
350 char *nxt = state->result[state->sent_count++];
352 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
355 /* cleanup to reduce or eliminate memory leaks */
356 for (i = 0; i < state->result_count; i++)
357 pfree(state->result[i]);
358 pfree(state->result);
361 SRF_RETURN_DONE(funcctx);
366 json_object_keys(PG_FUNCTION_ARGS)
368 FuncCallContext *funcctx;
372 if (SRF_IS_FIRSTCALL())
374 text *json = PG_GETARG_TEXT_P(0);
375 JsonLexContext *lex = makeJsonLexContext(json, true);
377 MemoryContext oldcontext;
379 funcctx = SRF_FIRSTCALL_INIT();
380 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
382 state = palloc(sizeof(OkeysState));
383 sem = palloc0(sizeof(JsonSemAction));
386 state->result_size = 256;
387 state->result_count = 0;
388 state->sent_count = 0;
389 state->result = palloc(256 * sizeof(char *));
391 sem->semstate = (void *) state;
392 sem->array_start = okeys_array_start;
393 sem->scalar = okeys_scalar;
394 sem->object_field_start = okeys_object_field_start;
395 /* remainder are all NULL, courtesy of palloc0 above */
397 pg_parse_json(lex, sem);
398 /* keys are now in state->result */
400 pfree(lex->strval->data);
405 MemoryContextSwitchTo(oldcontext);
406 funcctx->user_fctx = (void *) state;
409 funcctx = SRF_PERCALL_SETUP();
410 state = (OkeysState *) funcctx->user_fctx;
412 if (state->sent_count < state->result_count)
414 char *nxt = state->result[state->sent_count++];
416 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
419 /* cleanup to reduce or eliminate memory leaks */
420 for (i = 0; i < state->result_count; i++)
421 pfree(state->result[i]);
422 pfree(state->result);
425 SRF_RETURN_DONE(funcctx);
429 okeys_object_field_start(void *state, char *fname, bool isnull)
431 OkeysState *_state = (OkeysState *) state;
433 /* only collecting keys for the top level object */
434 if (_state->lex->lex_level != 1)
437 /* enlarge result array if necessary */
438 if (_state->result_count >= _state->result_size)
440 _state->result_size *= 2;
441 _state->result = (char **)
442 repalloc(_state->result, sizeof(char *) * _state->result_size);
445 /* save a copy of the field name */
446 _state->result[_state->result_count++] = pstrdup(fname);
450 okeys_array_start(void *state)
452 OkeysState *_state = (OkeysState *) state;
454 /* top level must be a json object */
455 if (_state->lex->lex_level == 0)
457 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
458 errmsg("cannot call %s on an array",
459 "json_object_keys")));
463 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
465 OkeysState *_state = (OkeysState *) state;
467 /* top level must be a json object */
468 if (_state->lex->lex_level == 0)
470 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
471 errmsg("cannot call %s on a scalar",
472 "json_object_keys")));
476 * json and jsonb getter functions
477 * these implement the -> ->> #> and #>> operators
478 * and the json{b?}_extract_path*(json, text, ...) functions
483 json_object_field(PG_FUNCTION_ARGS)
485 text *json = PG_GETARG_TEXT_P(0);
486 text *fname = PG_GETARG_TEXT_PP(1);
487 char *fnamestr = text_to_cstring(fname);
490 result = get_worker(json, &fnamestr, NULL, 1, false);
493 PG_RETURN_TEXT_P(result);
499 jsonb_object_field(PG_FUNCTION_ARGS)
501 Jsonb *jb = PG_GETARG_JSONB(0);
502 text *key = PG_GETARG_TEXT_PP(1);
505 if (!JB_ROOT_IS_OBJECT(jb))
508 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
510 VARSIZE_ANY_EXHDR(key));
513 PG_RETURN_JSONB(JsonbValueToJsonb(v));
519 json_object_field_text(PG_FUNCTION_ARGS)
521 text *json = PG_GETARG_TEXT_P(0);
522 text *fname = PG_GETARG_TEXT_PP(1);
523 char *fnamestr = text_to_cstring(fname);
526 result = get_worker(json, &fnamestr, NULL, 1, true);
529 PG_RETURN_TEXT_P(result);
535 jsonb_object_field_text(PG_FUNCTION_ARGS)
537 Jsonb *jb = PG_GETARG_JSONB(0);
538 text *key = PG_GETARG_TEXT_PP(1);
541 if (!JB_ROOT_IS_OBJECT(jb))
544 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
546 VARSIZE_ANY_EXHDR(key));
557 result = cstring_to_text(v->val.boolean ? "true" : "false");
560 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
563 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
564 PointerGetDatum(v->val.numeric))));
568 StringInfo jtext = makeStringInfo();
570 (void) JsonbToCString(jtext, v->val.binary.data, -1);
571 result = cstring_to_text_with_len(jtext->data, jtext->len);
575 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
579 PG_RETURN_TEXT_P(result);
586 json_array_element(PG_FUNCTION_ARGS)
588 text *json = PG_GETARG_TEXT_P(0);
589 int element = PG_GETARG_INT32(1);
592 result = get_worker(json, NULL, &element, 1, false);
595 PG_RETURN_TEXT_P(result);
601 jsonb_array_element(PG_FUNCTION_ARGS)
603 Jsonb *jb = PG_GETARG_JSONB(0);
604 int element = PG_GETARG_INT32(1);
607 if (!JB_ROOT_IS_ARRAY(jb))
610 /* Handle negative subscript */
613 uint32 nelements = JB_ROOT_COUNT(jb);
615 if (-element > nelements)
618 element += nelements;
621 v = getIthJsonbValueFromContainer(&jb->root, element);
623 PG_RETURN_JSONB(JsonbValueToJsonb(v));
629 json_array_element_text(PG_FUNCTION_ARGS)
631 text *json = PG_GETARG_TEXT_P(0);
632 int element = PG_GETARG_INT32(1);
635 result = get_worker(json, NULL, &element, 1, true);
638 PG_RETURN_TEXT_P(result);
644 jsonb_array_element_text(PG_FUNCTION_ARGS)
646 Jsonb *jb = PG_GETARG_JSONB(0);
647 int element = PG_GETARG_INT32(1);
650 if (!JB_ROOT_IS_ARRAY(jb))
653 /* Handle negative subscript */
656 uint32 nelements = JB_ROOT_COUNT(jb);
658 if (-element > nelements)
661 element += nelements;
664 v = getIthJsonbValueFromContainer(&jb->root, element);
674 result = cstring_to_text(v->val.boolean ? "true" : "false");
677 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
680 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
681 PointerGetDatum(v->val.numeric))));
685 StringInfo jtext = makeStringInfo();
687 (void) JsonbToCString(jtext, v->val.binary.data, -1);
688 result = cstring_to_text_with_len(jtext->data, jtext->len);
692 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
696 PG_RETURN_TEXT_P(result);
703 json_extract_path(PG_FUNCTION_ARGS)
705 return get_path_all(fcinfo, false);
709 json_extract_path_text(PG_FUNCTION_ARGS)
711 return get_path_all(fcinfo, true);
715 * common routine for extract_path functions
718 get_path_all(FunctionCallInfo fcinfo, bool as_text)
720 text *json = PG_GETARG_TEXT_P(0);
721 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
731 * If the array contains any null elements, return NULL, on the grounds
732 * that you'd have gotten NULL if any RHS value were NULL in a nested
733 * series of applications of the -> operator. (Note: because we also
734 * return NULL for error cases such as no-such-field, this is true
735 * regardless of the contents of the rest of the array.)
737 if (array_contains_nulls(path))
740 deconstruct_array(path, TEXTOID, -1, false, 'i',
741 &pathtext, &pathnulls, &npath);
743 tpath = palloc(npath * sizeof(char *));
744 ipath = palloc(npath * sizeof(int));
746 for (i = 0; i < npath; i++)
748 Assert(!pathnulls[i]);
749 tpath[i] = TextDatumGetCString(pathtext[i]);
752 * we have no idea at this stage what structure the document is so
753 * just convert anything in the path that we can to an integer and set
754 * all the other integers to INT_MIN which will never match.
756 if (*tpath[i] != '\0')
762 ind = strtol(tpath[i], &endptr, 10);
763 if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
764 ipath[i] = (int) ind;
772 result = get_worker(json, tpath, ipath, npath, as_text);
775 PG_RETURN_TEXT_P(result);
783 * common worker for all the json getter functions
785 * json: JSON object (in text form)
786 * tpath[]: field name(s) to extract
787 * ipath[]: array index(es) (zero-based) to extract, accepts negatives
788 * npath: length of tpath[] and/or ipath[]
789 * normalize_results: true to de-escape string and null scalars
791 * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
792 * field is not to be matched at that nesting level. Similarly, ipath can
793 * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
794 * not to be matched at that nesting level (a json datum should never be
795 * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
798 get_worker(text *json,
802 bool normalize_results)
804 JsonLexContext *lex = makeJsonLexContext(json, true);
805 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
806 GetState *state = palloc0(sizeof(GetState));
811 /* is it "_as_text" variant? */
812 state->normalize_results = normalize_results;
813 state->npath = npath;
814 state->path_names = tpath;
815 state->path_indexes = ipath;
816 state->pathok = palloc0(sizeof(bool) * npath);
817 state->array_cur_index = palloc(sizeof(int) * npath);
820 state->pathok[0] = true;
822 sem->semstate = (void *) state;
825 * Not all variants need all the semantic routines. Only set the ones that
826 * are actually needed for maximum efficiency.
828 sem->scalar = get_scalar;
831 sem->object_start = get_object_start;
832 sem->object_end = get_object_end;
833 sem->array_start = get_array_start;
834 sem->array_end = get_array_end;
838 sem->object_field_start = get_object_field_start;
839 sem->object_field_end = get_object_field_end;
843 sem->array_start = get_array_start;
844 sem->array_element_start = get_array_element_start;
845 sem->array_element_end = get_array_element_end;
848 pg_parse_json(lex, sem);
850 return state->tresult;
854 get_object_start(void *state)
856 GetState *_state = (GetState *) state;
857 int lex_level = _state->lex->lex_level;
859 if (lex_level == 0 && _state->npath == 0)
862 * Special case: we should match the entire object. We only need this
863 * at outermost level because at nested levels the match will have
864 * been started by the outer field or array element callback.
866 _state->result_start = _state->lex->token_start;
871 get_object_end(void *state)
873 GetState *_state = (GetState *) state;
874 int lex_level = _state->lex->lex_level;
876 if (lex_level == 0 && _state->npath == 0)
878 /* Special case: return the entire object */
879 char *start = _state->result_start;
880 int len = _state->lex->prev_token_terminator - start;
882 _state->tresult = cstring_to_text_with_len(start, len);
887 get_object_field_start(void *state, char *fname, bool isnull)
889 GetState *_state = (GetState *) state;
890 bool get_next = false;
891 int lex_level = _state->lex->lex_level;
893 if (lex_level <= _state->npath &&
894 _state->pathok[lex_level - 1] &&
895 _state->path_names != NULL &&
896 _state->path_names[lex_level - 1] != NULL &&
897 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
899 if (lex_level < _state->npath)
901 /* if not at end of path just mark path ok */
902 _state->pathok[lex_level] = true;
906 /* end of path, so we want this value */
913 /* this object overrides any previous matching object */
914 _state->tresult = NULL;
915 _state->result_start = NULL;
917 if (_state->normalize_results &&
918 _state->lex->token_type == JSON_TOKEN_STRING)
920 /* for as_text variants, tell get_scalar to set it for us */
921 _state->next_scalar = true;
925 /* for non-as_text variants, just note the json starting point */
926 _state->result_start = _state->lex->token_start;
932 get_object_field_end(void *state, char *fname, bool isnull)
934 GetState *_state = (GetState *) state;
935 bool get_last = false;
936 int lex_level = _state->lex->lex_level;
938 /* same tests as in get_object_field_start */
939 if (lex_level <= _state->npath &&
940 _state->pathok[lex_level - 1] &&
941 _state->path_names != NULL &&
942 _state->path_names[lex_level - 1] != NULL &&
943 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
945 if (lex_level < _state->npath)
947 /* done with this field so reset pathok */
948 _state->pathok[lex_level] = false;
952 /* end of path, so we want this value */
957 /* for as_text scalar case, our work is already done */
958 if (get_last && _state->result_start != NULL)
961 * make a text object from the string from the prevously noted json
962 * start up to the end of the previous token (the lexer is by now
963 * ahead of us on whatever came after what we're interested in).
965 if (isnull && _state->normalize_results)
966 _state->tresult = (text *) NULL;
969 char *start = _state->result_start;
970 int len = _state->lex->prev_token_terminator - start;
972 _state->tresult = cstring_to_text_with_len(start, len);
975 /* this should be unnecessary but let's do it for cleanliness: */
976 _state->result_start = NULL;
981 get_array_start(void *state)
983 GetState *_state = (GetState *) state;
984 int lex_level = _state->lex->lex_level;
986 if (lex_level < _state->npath)
988 /* Initialize counting of elements in this array */
989 _state->array_cur_index[lex_level] = -1;
991 /* INT_MIN value is reserved to represent invalid subscript */
992 if (_state->path_indexes[lex_level] < 0 &&
993 _state->path_indexes[lex_level] != INT_MIN)
995 /* Negative subscript -- convert to positive-wise subscript */
996 int nelements = json_count_array_elements(_state->lex);
998 if (-_state->path_indexes[lex_level] <= nelements)
999 _state->path_indexes[lex_level] += nelements;
1002 else if (lex_level == 0 && _state->npath == 0)
1005 * Special case: we should match the entire array. We only need this
1006 * at the outermost level because at nested levels the match will have
1007 * been started by the outer field or array element callback.
1009 _state->result_start = _state->lex->token_start;
1014 get_array_end(void *state)
1016 GetState *_state = (GetState *) state;
1017 int lex_level = _state->lex->lex_level;
1019 if (lex_level == 0 && _state->npath == 0)
1021 /* Special case: return the entire array */
1022 char *start = _state->result_start;
1023 int len = _state->lex->prev_token_terminator - start;
1025 _state->tresult = cstring_to_text_with_len(start, len);
1030 get_array_element_start(void *state, bool isnull)
1032 GetState *_state = (GetState *) state;
1033 bool get_next = false;
1034 int lex_level = _state->lex->lex_level;
1036 /* Update array element counter */
1037 if (lex_level <= _state->npath)
1038 _state->array_cur_index[lex_level - 1]++;
1040 if (lex_level <= _state->npath &&
1041 _state->pathok[lex_level - 1] &&
1042 _state->path_indexes != NULL &&
1043 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1045 if (lex_level < _state->npath)
1047 /* if not at end of path just mark path ok */
1048 _state->pathok[lex_level] = true;
1052 /* end of path, so we want this value */
1057 /* same logic as for objects */
1060 _state->tresult = NULL;
1061 _state->result_start = NULL;
1063 if (_state->normalize_results &&
1064 _state->lex->token_type == JSON_TOKEN_STRING)
1066 _state->next_scalar = true;
1070 _state->result_start = _state->lex->token_start;
1076 get_array_element_end(void *state, bool isnull)
1078 GetState *_state = (GetState *) state;
1079 bool get_last = false;
1080 int lex_level = _state->lex->lex_level;
1082 /* same tests as in get_array_element_start */
1083 if (lex_level <= _state->npath &&
1084 _state->pathok[lex_level - 1] &&
1085 _state->path_indexes != NULL &&
1086 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1088 if (lex_level < _state->npath)
1090 /* done with this element so reset pathok */
1091 _state->pathok[lex_level] = false;
1095 /* end of path, so we want this value */
1100 /* same logic as for objects */
1101 if (get_last && _state->result_start != NULL)
1103 if (isnull && _state->normalize_results)
1104 _state->tresult = (text *) NULL;
1107 char *start = _state->result_start;
1108 int len = _state->lex->prev_token_terminator - start;
1110 _state->tresult = cstring_to_text_with_len(start, len);
1113 _state->result_start = NULL;
1118 get_scalar(void *state, char *token, JsonTokenType tokentype)
1120 GetState *_state = (GetState *) state;
1121 int lex_level = _state->lex->lex_level;
1123 /* Check for whole-object match */
1124 if (lex_level == 0 && _state->npath == 0)
1126 if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1128 /* we want the de-escaped string */
1129 _state->next_scalar = true;
1131 else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1133 _state->tresult = (text *) NULL;
1138 * This is a bit hokey: we will suppress whitespace after the
1139 * scalar token, but not whitespace before it. Probably not worth
1140 * doing our own space-skipping to avoid that.
1142 char *start = _state->lex->input;
1143 int len = _state->lex->prev_token_terminator - start;
1145 _state->tresult = cstring_to_text_with_len(start, len);
1149 if (_state->next_scalar)
1151 /* a de-escaped text value is wanted, so supply it */
1152 _state->tresult = cstring_to_text(token);
1153 /* make sure the next call to get_scalar doesn't overwrite it */
1154 _state->next_scalar = false;
1159 jsonb_extract_path(PG_FUNCTION_ARGS)
1161 return get_jsonb_path_all(fcinfo, false);
1165 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1167 return get_jsonb_path_all(fcinfo, true);
1171 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1173 Jsonb *jb = PG_GETARG_JSONB(0);
1174 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1180 bool have_object = false,
1182 JsonbValue *jbvp = NULL;
1184 JsonbContainer *container;
1187 * If the array contains any null elements, return NULL, on the grounds
1188 * that you'd have gotten NULL if any RHS value were NULL in a nested
1189 * series of applications of the -> operator. (Note: because we also
1190 * return NULL for error cases such as no-such-field, this is true
1191 * regardless of the contents of the rest of the array.)
1193 if (array_contains_nulls(path))
1196 deconstruct_array(path, TEXTOID, -1, false, 'i',
1197 &pathtext, &pathnulls, &npath);
1199 /* Identify whether we have object, array, or scalar at top-level */
1200 container = &jb->root;
1202 if (JB_ROOT_IS_OBJECT(jb))
1204 else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1208 Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
1209 /* Extract the scalar value, if it is what we'll return */
1211 jbvp = getIthJsonbValueFromContainer(container, 0);
1215 * If the array is empty, return the entire LHS object, on the grounds
1216 * that we should do zero field or element extractions. For the
1217 * non-scalar case we can just hand back the object without much work. For
1218 * the scalar case, fall through and deal with the value below the loop.
1219 * (This inconsistency arises because there's no easy way to generate a
1220 * JsonbValue directly for root-level containers.)
1222 if (npath <= 0 && jbvp == NULL)
1226 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1232 /* not text mode - just hand back the jsonb */
1233 PG_RETURN_JSONB(jb);
1237 for (i = 0; i < npath; i++)
1241 jbvp = findJsonbValueFromContainerLen(container,
1243 VARDATA_ANY(pathtext[i]),
1244 VARSIZE_ANY_EXHDR(pathtext[i]));
1246 else if (have_array)
1250 char *indextext = TextDatumGetCString(pathtext[i]);
1254 lindex = strtol(indextext, &endptr, 10);
1255 if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1256 lindex > INT_MAX || lindex < INT_MIN)
1261 index = (uint32) lindex;
1265 /* Handle negative subscript */
1268 /* Container must be array, but make sure */
1269 if (!JsonContainerIsArray(container))
1270 elog(ERROR, "not a jsonb array");
1272 nelements = JsonContainerSize(container);
1274 if (-lindex > nelements)
1277 index = nelements + lindex;
1280 jbvp = getIthJsonbValueFromContainer(container, index);
1284 /* scalar, extraction yields a null */
1290 else if (i == npath - 1)
1293 if (jbvp->type == jbvBinary)
1295 JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1296 JsonbIteratorToken r;
1298 r = JsonbIteratorNext(&it, &tv, true);
1299 container = (JsonbContainer *) jbvp->val.binary.data;
1300 have_object = r == WJB_BEGIN_OBJECT;
1301 have_array = r == WJB_BEGIN_ARRAY;
1305 have_object = jbvp->type == jbvObject;
1306 have_array = jbvp->type == jbvArray;
1312 /* special-case outputs for string and null values */
1313 if (jbvp->type == jbvString)
1314 PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1315 jbvp->val.string.len));
1316 if (jbvp->type == jbvNull)
1320 res = JsonbValueToJsonb(jbvp);
1324 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1330 /* not text mode - just hand back the jsonb */
1331 PG_RETURN_JSONB(res);
1336 * SQL function json_array_length(json) -> int
1339 json_array_length(PG_FUNCTION_ARGS)
1341 text *json = PG_GETARG_TEXT_P(0);
1343 JsonLexContext *lex;
1346 lex = makeJsonLexContext(json, false);
1347 state = palloc0(sizeof(AlenState));
1348 sem = palloc0(sizeof(JsonSemAction));
1350 /* palloc0 does this for us */
1356 sem->semstate = (void *) state;
1357 sem->object_start = alen_object_start;
1358 sem->scalar = alen_scalar;
1359 sem->array_element_start = alen_array_element_start;
1361 pg_parse_json(lex, sem);
1363 PG_RETURN_INT32(state->count);
1367 jsonb_array_length(PG_FUNCTION_ARGS)
1369 Jsonb *jb = PG_GETARG_JSONB(0);
1371 if (JB_ROOT_IS_SCALAR(jb))
1373 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1374 errmsg("cannot get array length of a scalar")));
1375 else if (!JB_ROOT_IS_ARRAY(jb))
1377 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1378 errmsg("cannot get array length of a non-array")));
1380 PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1384 * These next two checks ensure that the json is an array (since it can't be
1385 * a scalar or an object).
1389 alen_object_start(void *state)
1391 AlenState *_state = (AlenState *) state;
1393 /* json structure check */
1394 if (_state->lex->lex_level == 0)
1396 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1397 errmsg("cannot get array length of a non-array")));
1401 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1403 AlenState *_state = (AlenState *) state;
1405 /* json structure check */
1406 if (_state->lex->lex_level == 0)
1408 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1409 errmsg("cannot get array length of a scalar")));
1413 alen_array_element_start(void *state, bool isnull)
1415 AlenState *_state = (AlenState *) state;
1417 /* just count up all the level 1 elements */
1418 if (_state->lex->lex_level == 1)
1423 * SQL function json_each and json_each_text
1425 * decompose a json object into key value pairs.
1427 * Unlike json_object_keys() these SRFs operate in materialize mode,
1428 * stashing results into a Tuplestore object as they go.
1429 * The construction of tuples is done using a temporary memory context
1430 * that is cleared out after each tuple is built.
1433 json_each(PG_FUNCTION_ARGS)
1435 return each_worker(fcinfo, false);
1439 jsonb_each(PG_FUNCTION_ARGS)
1441 return each_worker_jsonb(fcinfo, "jsonb_each", false);
1445 json_each_text(PG_FUNCTION_ARGS)
1447 return each_worker(fcinfo, true);
1451 jsonb_each_text(PG_FUNCTION_ARGS)
1453 return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1457 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1459 Jsonb *jb = PG_GETARG_JSONB(0);
1461 Tuplestorestate *tuple_store;
1463 TupleDesc ret_tdesc;
1464 MemoryContext old_cxt,
1466 bool skipNested = false;
1469 JsonbIteratorToken r;
1471 if (!JB_ROOT_IS_OBJECT(jb))
1473 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1474 errmsg("cannot call %s on a non-object",
1477 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1479 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1480 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1481 rsi->expectedDesc == NULL)
1483 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1484 errmsg("set-valued function called in context that "
1485 "cannot accept a set")));
1487 rsi->returnMode = SFRM_Materialize;
1489 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1491 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1492 errmsg("function returning record called in context "
1493 "that cannot accept type record")));
1495 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1497 ret_tdesc = CreateTupleDescCopy(tupdesc);
1498 BlessTupleDesc(ret_tdesc);
1500 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1503 MemoryContextSwitchTo(old_cxt);
1505 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1506 "jsonb_each temporary cxt",
1507 ALLOCSET_DEFAULT_SIZES);
1509 it = JsonbIteratorInit(&jb->root);
1511 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1520 bool nulls[2] = {false, false};
1522 /* Use the tmp context so we can clean up after each tuple is done */
1523 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1525 key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1528 * The next thing the iterator fetches should be the value, no
1529 * matter what shape it is.
1531 r = JsonbIteratorNext(&it, &v, skipNested);
1533 values[0] = PointerGetDatum(key);
1537 if (v.type == jbvNull)
1539 /* a json null is an sql null in text mode */
1541 values[1] = (Datum) NULL;
1547 if (v.type == jbvString)
1549 /* In text mode, scalar strings should be dequoted */
1550 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1554 /* Turn anything else into a json string */
1555 StringInfo jtext = makeStringInfo();
1556 Jsonb *jb = JsonbValueToJsonb(&v);
1558 (void) JsonbToCString(jtext, &jb->root, 0);
1559 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1562 values[1] = PointerGetDatum(sv);
1567 /* Not in text mode, just return the Jsonb */
1568 Jsonb *val = JsonbValueToJsonb(&v);
1570 values[1] = PointerGetDatum(val);
1573 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1575 tuplestore_puttuple(tuple_store, tuple);
1577 /* clean up and switch back */
1578 MemoryContextSwitchTo(old_cxt);
1579 MemoryContextReset(tmp_cxt);
1583 MemoryContextDelete(tmp_cxt);
1585 rsi->setResult = tuple_store;
1586 rsi->setDesc = ret_tdesc;
1593 each_worker(FunctionCallInfo fcinfo, bool as_text)
1595 text *json = PG_GETARG_TEXT_P(0);
1596 JsonLexContext *lex;
1599 MemoryContext old_cxt;
1603 lex = makeJsonLexContext(json, true);
1604 state = palloc0(sizeof(EachState));
1605 sem = palloc0(sizeof(JsonSemAction));
1607 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1609 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1610 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1611 rsi->expectedDesc == NULL)
1613 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1614 errmsg("set-valued function called in context that "
1615 "cannot accept a set")));
1617 rsi->returnMode = SFRM_Materialize;
1619 (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1621 /* make these in a sufficiently long-lived memory context */
1622 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1624 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1625 BlessTupleDesc(state->ret_tdesc);
1626 state->tuple_store =
1627 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1630 MemoryContextSwitchTo(old_cxt);
1632 sem->semstate = (void *) state;
1633 sem->array_start = each_array_start;
1634 sem->scalar = each_scalar;
1635 sem->object_field_start = each_object_field_start;
1636 sem->object_field_end = each_object_field_end;
1638 state->normalize_results = as_text;
1639 state->next_scalar = false;
1641 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1642 "json_each temporary cxt",
1643 ALLOCSET_DEFAULT_SIZES);
1645 pg_parse_json(lex, sem);
1647 MemoryContextDelete(state->tmp_cxt);
1649 rsi->setResult = state->tuple_store;
1650 rsi->setDesc = state->ret_tdesc;
1657 each_object_field_start(void *state, char *fname, bool isnull)
1659 EachState *_state = (EachState *) state;
1661 /* save a pointer to where the value starts */
1662 if (_state->lex->lex_level == 1)
1665 * next_scalar will be reset in the object_field_end handler, and
1666 * since we know the value is a scalar there is no danger of it being
1667 * on while recursing down the tree.
1669 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1670 _state->next_scalar = true;
1672 _state->result_start = _state->lex->token_start;
1677 each_object_field_end(void *state, char *fname, bool isnull)
1679 EachState *_state = (EachState *) state;
1680 MemoryContext old_cxt;
1685 bool nulls[2] = {false, false};
1687 /* skip over nested objects */
1688 if (_state->lex->lex_level != 1)
1691 /* use the tmp context so we can clean up after each tuple is done */
1692 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1694 values[0] = CStringGetTextDatum(fname);
1696 if (isnull && _state->normalize_results)
1699 values[1] = (Datum) 0;
1701 else if (_state->next_scalar)
1703 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1704 _state->next_scalar = false;
1708 len = _state->lex->prev_token_terminator - _state->result_start;
1709 val = cstring_to_text_with_len(_state->result_start, len);
1710 values[1] = PointerGetDatum(val);
1713 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1715 tuplestore_puttuple(_state->tuple_store, tuple);
1717 /* clean up and switch back */
1718 MemoryContextSwitchTo(old_cxt);
1719 MemoryContextReset(_state->tmp_cxt);
1723 each_array_start(void *state)
1725 EachState *_state = (EachState *) state;
1727 /* json structure check */
1728 if (_state->lex->lex_level == 0)
1730 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1731 errmsg("cannot deconstruct an array as an object")));
1735 each_scalar(void *state, char *token, JsonTokenType tokentype)
1737 EachState *_state = (EachState *) state;
1739 /* json structure check */
1740 if (_state->lex->lex_level == 0)
1742 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1743 errmsg("cannot deconstruct a scalar")));
1745 /* supply de-escaped value if required */
1746 if (_state->next_scalar)
1747 _state->normalized_scalar = token;
1751 * SQL functions json_array_elements and json_array_elements_text
1753 * get the elements from a json array
1755 * a lot of this processing is similar to the json_each* functions
1759 jsonb_array_elements(PG_FUNCTION_ARGS)
1761 return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1765 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1767 return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1771 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1774 Jsonb *jb = PG_GETARG_JSONB(0);
1776 Tuplestorestate *tuple_store;
1778 TupleDesc ret_tdesc;
1779 MemoryContext old_cxt,
1781 bool skipNested = false;
1784 JsonbIteratorToken r;
1786 if (JB_ROOT_IS_SCALAR(jb))
1788 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1789 errmsg("cannot extract elements from a scalar")));
1790 else if (!JB_ROOT_IS_ARRAY(jb))
1792 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1793 errmsg("cannot extract elements from an object")));
1795 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1797 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1798 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1799 rsi->expectedDesc == NULL)
1801 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1802 errmsg("set-valued function called in context that "
1803 "cannot accept a set")));
1805 rsi->returnMode = SFRM_Materialize;
1807 /* it's a simple type, so don't use get_call_result_type() */
1808 tupdesc = rsi->expectedDesc;
1810 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1812 ret_tdesc = CreateTupleDescCopy(tupdesc);
1813 BlessTupleDesc(ret_tdesc);
1815 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1818 MemoryContextSwitchTo(old_cxt);
1820 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1821 "jsonb_array_elements temporary cxt",
1822 ALLOCSET_DEFAULT_SIZES);
1824 it = JsonbIteratorInit(&jb->root);
1826 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1834 bool nulls[1] = {false};
1836 /* use the tmp context so we can clean up after each tuple is done */
1837 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1841 Jsonb *val = JsonbValueToJsonb(&v);
1843 values[0] = PointerGetDatum(val);
1847 if (v.type == jbvNull)
1849 /* a json null is an sql null in text mode */
1851 values[0] = (Datum) NULL;
1857 if (v.type == jbvString)
1859 /* in text mode scalar strings should be dequoted */
1860 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1864 /* turn anything else into a json string */
1865 StringInfo jtext = makeStringInfo();
1866 Jsonb *jb = JsonbValueToJsonb(&v);
1868 (void) JsonbToCString(jtext, &jb->root, 0);
1869 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1872 values[0] = PointerGetDatum(sv);
1876 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1878 tuplestore_puttuple(tuple_store, tuple);
1880 /* clean up and switch back */
1881 MemoryContextSwitchTo(old_cxt);
1882 MemoryContextReset(tmp_cxt);
1886 MemoryContextDelete(tmp_cxt);
1888 rsi->setResult = tuple_store;
1889 rsi->setDesc = ret_tdesc;
1895 json_array_elements(PG_FUNCTION_ARGS)
1897 return elements_worker(fcinfo, "json_array_elements", false);
1901 json_array_elements_text(PG_FUNCTION_ARGS)
1903 return elements_worker(fcinfo, "json_array_elements_text", true);
1907 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1909 text *json = PG_GETARG_TEXT_P(0);
1911 /* elements only needs escaped strings when as_text */
1912 JsonLexContext *lex = makeJsonLexContext(json, as_text);
1915 MemoryContext old_cxt;
1917 ElementsState *state;
1919 state = palloc0(sizeof(ElementsState));
1920 sem = palloc0(sizeof(JsonSemAction));
1922 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1924 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1925 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1926 rsi->expectedDesc == NULL)
1928 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1929 errmsg("set-valued function called in context that "
1930 "cannot accept a set")));
1932 rsi->returnMode = SFRM_Materialize;
1934 /* it's a simple type, so don't use get_call_result_type() */
1935 tupdesc = rsi->expectedDesc;
1937 /* make these in a sufficiently long-lived memory context */
1938 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1940 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1941 BlessTupleDesc(state->ret_tdesc);
1942 state->tuple_store =
1943 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1946 MemoryContextSwitchTo(old_cxt);
1948 sem->semstate = (void *) state;
1949 sem->object_start = elements_object_start;
1950 sem->scalar = elements_scalar;
1951 sem->array_element_start = elements_array_element_start;
1952 sem->array_element_end = elements_array_element_end;
1954 state->function_name = funcname;
1955 state->normalize_results = as_text;
1956 state->next_scalar = false;
1958 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1959 "json_array_elements temporary cxt",
1960 ALLOCSET_DEFAULT_SIZES);
1962 pg_parse_json(lex, sem);
1964 MemoryContextDelete(state->tmp_cxt);
1966 rsi->setResult = state->tuple_store;
1967 rsi->setDesc = state->ret_tdesc;
1973 elements_array_element_start(void *state, bool isnull)
1975 ElementsState *_state = (ElementsState *) state;
1977 /* save a pointer to where the value starts */
1978 if (_state->lex->lex_level == 1)
1981 * next_scalar will be reset in the array_element_end handler, and
1982 * since we know the value is a scalar there is no danger of it being
1983 * on while recursing down the tree.
1985 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1986 _state->next_scalar = true;
1988 _state->result_start = _state->lex->token_start;
1993 elements_array_element_end(void *state, bool isnull)
1995 ElementsState *_state = (ElementsState *) state;
1996 MemoryContext old_cxt;
2001 bool nulls[1] = {false};
2003 /* skip over nested objects */
2004 if (_state->lex->lex_level != 1)
2007 /* use the tmp context so we can clean up after each tuple is done */
2008 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2010 if (isnull && _state->normalize_results)
2013 values[0] = (Datum) NULL;
2015 else if (_state->next_scalar)
2017 values[0] = CStringGetTextDatum(_state->normalized_scalar);
2018 _state->next_scalar = false;
2022 len = _state->lex->prev_token_terminator - _state->result_start;
2023 val = cstring_to_text_with_len(_state->result_start, len);
2024 values[0] = PointerGetDatum(val);
2027 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2029 tuplestore_puttuple(_state->tuple_store, tuple);
2031 /* clean up and switch back */
2032 MemoryContextSwitchTo(old_cxt);
2033 MemoryContextReset(_state->tmp_cxt);
2037 elements_object_start(void *state)
2039 ElementsState *_state = (ElementsState *) state;
2041 /* json structure check */
2042 if (_state->lex->lex_level == 0)
2044 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2045 errmsg("cannot call %s on a non-array",
2046 _state->function_name)));
2050 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2052 ElementsState *_state = (ElementsState *) state;
2054 /* json structure check */
2055 if (_state->lex->lex_level == 0)
2057 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2058 errmsg("cannot call %s on a scalar",
2059 _state->function_name)));
2061 /* supply de-escaped value if required */
2062 if (_state->next_scalar)
2063 _state->normalized_scalar = token;
2067 * SQL function json_populate_record
2069 * set fields in a record from the argument json
2071 * Code adapted shamelessly from hstore's populate_record
2072 * which is in turn partly adapted from record_out.
2074 * The json is decomposed into a hash table, in which each
2075 * field in the record is then looked up by name. For jsonb
2076 * we fetch the values direct from the object.
2079 jsonb_populate_record(PG_FUNCTION_ARGS)
2081 return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2085 jsonb_to_record(PG_FUNCTION_ARGS)
2087 return populate_record_worker(fcinfo, "jsonb_to_record", false);
2091 json_populate_record(PG_FUNCTION_ARGS)
2093 return populate_record_worker(fcinfo, "json_populate_record", true);
2097 json_to_record(PG_FUNCTION_ARGS)
2099 return populate_record_worker(fcinfo, "json_to_record", false);
2103 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
2104 bool have_record_arg)
2106 int json_arg_num = have_record_arg ? 1 : 0;
2107 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2110 HTAB *json_hash = NULL;
2111 HeapTupleHeader rec = NULL;
2112 Oid tupType = InvalidOid;
2113 int32 tupTypmod = -1;
2115 HeapTupleData tuple;
2117 RecordIOData *my_extra;
2123 Assert(jtype == JSONOID || jtype == JSONBOID);
2125 if (have_record_arg)
2127 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2129 if (!type_is_rowtype(argtype))
2131 (errcode(ERRCODE_DATATYPE_MISMATCH),
2132 errmsg("first argument of %s must be a row type",
2135 if (PG_ARGISNULL(0))
2137 if (PG_ARGISNULL(1))
2141 * have no tuple to look at, so the only source of type info is
2142 * the argtype. The lookup_rowtype_tupdesc call below will error
2143 * out if we don't have a known composite type oid here.
2150 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2152 if (PG_ARGISNULL(1))
2153 PG_RETURN_POINTER(rec);
2155 /* Extract type info from the tuple itself */
2156 tupType = HeapTupleHeaderGetTypeId(rec);
2157 tupTypmod = HeapTupleHeaderGetTypMod(rec);
2160 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2164 /* json{b}_to_record case */
2165 if (PG_ARGISNULL(0))
2168 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2170 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2171 errmsg("function returning record called in context "
2172 "that cannot accept type record"),
2173 errhint("Try calling the function in the FROM clause "
2174 "using a column definition list.")));
2177 if (jtype == JSONOID)
2179 /* just get the text */
2180 json = PG_GETARG_TEXT_P(json_arg_num);
2182 json_hash = get_json_object_as_hash(json, funcname);
2185 * if the input json is empty, we can only skip the rest if we were
2186 * passed in a non-null record, since otherwise there may be issues
2187 * with domain nulls.
2189 if (hash_get_num_entries(json_hash) == 0 && rec)
2191 hash_destroy(json_hash);
2192 ReleaseTupleDesc(tupdesc);
2193 PG_RETURN_POINTER(rec);
2198 jb = PG_GETARG_JSONB(json_arg_num);
2200 /* same logic as for json */
2201 if (JB_ROOT_COUNT(jb) == 0 && rec)
2203 ReleaseTupleDesc(tupdesc);
2204 PG_RETURN_POINTER(rec);
2208 ncolumns = tupdesc->natts;
2212 /* Build a temporary HeapTuple control structure */
2213 tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2214 ItemPointerSetInvalid(&(tuple.t_self));
2215 tuple.t_tableOid = InvalidOid;
2220 * We arrange to look up the needed I/O info just once per series of
2221 * calls, assuming the record type doesn't change underneath us.
2223 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2224 if (my_extra == NULL ||
2225 my_extra->ncolumns != ncolumns)
2227 fcinfo->flinfo->fn_extra =
2228 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2229 offsetof(RecordIOData, columns) +
2230 ncolumns * sizeof(ColumnIOData));
2231 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2232 my_extra->record_type = InvalidOid;
2233 my_extra->record_typmod = 0;
2234 my_extra->ncolumns = ncolumns;
2235 MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2238 if (have_record_arg && (my_extra->record_type != tupType ||
2239 my_extra->record_typmod != tupTypmod))
2242 offsetof(RecordIOData, columns) +
2243 ncolumns * sizeof(ColumnIOData));
2244 my_extra->record_type = tupType;
2245 my_extra->record_typmod = tupTypmod;
2246 my_extra->ncolumns = ncolumns;
2249 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2250 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2254 /* Break down the tuple into fields */
2255 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2259 for (i = 0; i < ncolumns; ++i)
2261 values[i] = (Datum) 0;
2266 for (i = 0; i < ncolumns; ++i)
2268 ColumnIOData *column_info = &my_extra->columns[i];
2269 Oid column_type = tupdesc->attrs[i]->atttypid;
2270 JsonbValue *v = NULL;
2271 JsonHashEntry *hashentry = NULL;
2273 /* Ignore dropped columns in datatype */
2274 if (tupdesc->attrs[i]->attisdropped)
2280 if (jtype == JSONOID)
2282 hashentry = hash_search(json_hash,
2283 NameStr(tupdesc->attrs[i]->attname),
2288 char *key = NameStr(tupdesc->attrs[i]->attname);
2290 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
2295 * we can't just skip here if the key wasn't found since we might have
2296 * a domain to deal with. If we were passed in a non-null record
2297 * datum, we assume that the existing values are valid (if they're
2298 * not, then it's not our fault), but if we were passed in a null,
2299 * then every field which we don't populate needs to be run through
2300 * the input function just in case it's a domain type.
2302 if (((jtype == JSONOID && hashentry == NULL) ||
2303 (jtype == JSONBOID && v == NULL)) && rec)
2307 * Prepare to convert the column value from text
2309 if (column_info->column_type != column_type)
2311 getTypeInputInfo(column_type,
2312 &column_info->typiofunc,
2313 &column_info->typioparam);
2314 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2315 fcinfo->flinfo->fn_mcxt);
2316 column_info->column_type = column_type;
2318 if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2319 (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2322 * need InputFunctionCall to happen even for nulls, so that domain
2325 values[i] = InputFunctionCall(&column_info->proc, NULL,
2326 column_info->typioparam,
2327 tupdesc->attrs[i]->atttypmod);
2334 if (jtype == JSONOID)
2336 /* already done the hard work in the json case */
2341 if (v->type == jbvString)
2342 s = pnstrdup(v->val.string.val, v->val.string.len);
2343 else if (v->type == jbvBool)
2344 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2345 else if (v->type == jbvNumeric)
2346 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2347 PointerGetDatum(v->val.numeric)));
2348 else if (v->type == jbvBinary)
2349 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2351 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2354 values[i] = InputFunctionCall(&column_info->proc, s,
2355 column_info->typioparam,
2356 tupdesc->attrs[i]->atttypmod);
2361 rettuple = heap_form_tuple(tupdesc, values, nulls);
2363 ReleaseTupleDesc(tupdesc);
2366 hash_destroy(json_hash);
2368 PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
2372 * get_json_object_as_hash
2374 * decompose a json object into a hash table.
2377 get_json_object_as_hash(text *json, const char *funcname)
2382 JsonLexContext *lex = makeJsonLexContext(json, true);
2385 memset(&ctl, 0, sizeof(ctl));
2386 ctl.keysize = NAMEDATALEN;
2387 ctl.entrysize = sizeof(JsonHashEntry);
2388 ctl.hcxt = CurrentMemoryContext;
2389 tab = hash_create("json object hashtable",
2392 HASH_ELEM | HASH_CONTEXT);
2394 state = palloc0(sizeof(JHashState));
2395 sem = palloc0(sizeof(JsonSemAction));
2397 state->function_name = funcname;
2401 sem->semstate = (void *) state;
2402 sem->array_start = hash_array_start;
2403 sem->scalar = hash_scalar;
2404 sem->object_field_start = hash_object_field_start;
2405 sem->object_field_end = hash_object_field_end;
2407 pg_parse_json(lex, sem);
2413 hash_object_field_start(void *state, char *fname, bool isnull)
2415 JHashState *_state = (JHashState *) state;
2417 if (_state->lex->lex_level > 1)
2420 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2421 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2423 /* remember start position of the whole text of the subobject */
2424 _state->save_json_start = _state->lex->token_start;
2428 /* must be a scalar */
2429 _state->save_json_start = NULL;
2434 hash_object_field_end(void *state, char *fname, bool isnull)
2436 JHashState *_state = (JHashState *) state;
2437 JsonHashEntry *hashentry;
2441 * Ignore nested fields.
2443 if (_state->lex->lex_level > 1)
2447 * Ignore field names >= NAMEDATALEN - they can't match a record field.
2448 * (Note: without this test, the hash code would truncate the string at
2449 * NAMEDATALEN-1, and could then match against a similarly-truncated
2450 * record field name. That would be a reasonable behavior, but this code
2451 * has previously insisted on exact equality, so we keep this behavior.)
2453 if (strlen(fname) >= NAMEDATALEN)
2456 hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2459 * found being true indicates a duplicate. We don't do anything about
2460 * that, a later field with the same name overrides the earlier field.
2463 hashentry->isnull = isnull;
2464 if (_state->save_json_start != NULL)
2466 int len = _state->lex->prev_token_terminator - _state->save_json_start;
2467 char *val = palloc((len + 1) * sizeof(char));
2469 memcpy(val, _state->save_json_start, len);
2471 hashentry->val = val;
2475 /* must have had a scalar instead */
2476 hashentry->val = _state->saved_scalar;
2481 hash_array_start(void *state)
2483 JHashState *_state = (JHashState *) state;
2485 if (_state->lex->lex_level == 0)
2487 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2488 errmsg("cannot call %s on an array", _state->function_name)));
2492 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2494 JHashState *_state = (JHashState *) state;
2496 if (_state->lex->lex_level == 0)
2498 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2499 errmsg("cannot call %s on a scalar", _state->function_name)));
2501 if (_state->lex->lex_level == 1)
2502 _state->saved_scalar = token;
2507 * SQL function json_populate_recordset
2509 * set fields in a set of records from the argument json,
2510 * which must be an array of objects.
2512 * similar to json_populate_record, but the tuple-building code
2513 * is pushed down into the semantic action handlers so it's done
2514 * per object in the array.
2517 jsonb_populate_recordset(PG_FUNCTION_ARGS)
2519 return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2523 jsonb_to_recordset(PG_FUNCTION_ARGS)
2525 return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2529 json_populate_recordset(PG_FUNCTION_ARGS)
2531 return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2535 json_to_recordset(PG_FUNCTION_ARGS)
2537 return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2541 make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
2546 RecordIOData *my_extra = state->my_extra;
2547 int ncolumns = my_extra->ncolumns;
2548 TupleDesc tupdesc = state->ret_tdesc;
2549 HeapTupleHeader rec = state->rec;
2552 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2553 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2557 HeapTupleData tuple;
2559 /* Build a temporary HeapTuple control structure */
2560 tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2561 ItemPointerSetInvalid(&(tuple.t_self));
2562 tuple.t_tableOid = InvalidOid;
2563 tuple.t_data = state->rec;
2565 /* Break down the tuple into fields */
2566 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2570 for (i = 0; i < ncolumns; ++i)
2572 values[i] = (Datum) 0;
2577 for (i = 0; i < ncolumns; ++i)
2579 ColumnIOData *column_info = &my_extra->columns[i];
2580 Oid column_type = tupdesc->attrs[i]->atttypid;
2581 JsonbValue *v = NULL;
2584 /* Ignore dropped columns in datatype */
2585 if (tupdesc->attrs[i]->attisdropped)
2591 key = NameStr(tupdesc->attrs[i]->attname);
2593 v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
2597 * We can't just skip here if the key wasn't found since we might have
2598 * a domain to deal with. If we were passed in a non-null record
2599 * datum, we assume that the existing values are valid (if they're
2600 * not, then it's not our fault), but if we were passed in a null,
2601 * then every field which we don't populate needs to be run through
2602 * the input function just in case it's a domain type.
2604 if (v == NULL && rec)
2608 * Prepare to convert the column value from text
2610 if (column_info->column_type != column_type)
2612 getTypeInputInfo(column_type,
2613 &column_info->typiofunc,
2614 &column_info->typioparam);
2615 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2617 column_info->column_type = column_type;
2619 if (v == NULL || v->type == jbvNull)
2622 * Need InputFunctionCall to happen even for nulls, so that domain
2625 values[i] = InputFunctionCall(&column_info->proc, NULL,
2626 column_info->typioparam,
2627 tupdesc->attrs[i]->atttypmod);
2634 if (v->type == jbvString)
2635 s = pnstrdup(v->val.string.val, v->val.string.len);
2636 else if (v->type == jbvBool)
2637 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2638 else if (v->type == jbvNumeric)
2639 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2640 PointerGetDatum(v->val.numeric)));
2641 else if (v->type == jbvBinary)
2642 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2644 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2646 values[i] = InputFunctionCall(&column_info->proc, s,
2647 column_info->typioparam,
2648 tupdesc->attrs[i]->atttypmod);
2653 rettuple = heap_form_tuple(tupdesc, values, nulls);
2655 tuplestore_puttuple(state->tuple_store, rettuple);
2659 * common worker for json_populate_recordset() and json_to_recordset()
2662 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
2663 bool have_record_arg)
2665 int json_arg_num = have_record_arg ? 1 : 0;
2666 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2668 MemoryContext old_cxt;
2671 HeapTupleHeader rec;
2673 RecordIOData *my_extra;
2675 PopulateRecordsetState *state;
2677 if (have_record_arg)
2679 Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2681 if (!type_is_rowtype(argtype))
2683 (errcode(ERRCODE_DATATYPE_MISMATCH),
2684 errmsg("first argument of %s must be a row type",
2688 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2690 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2691 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2692 rsi->expectedDesc == NULL)
2694 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2695 errmsg("set-valued function called in context that "
2696 "cannot accept a set")));
2698 rsi->returnMode = SFRM_Materialize;
2701 * get the tupdesc from the result set info - it must be a record type
2702 * because we already checked that arg1 is a record type, or we're in a
2703 * to_record function which returns a setof record.
2705 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2707 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2708 errmsg("function returning record called in context "
2709 "that cannot accept type record")));
2711 /* if the json is null send back an empty set */
2712 if (PG_ARGISNULL(json_arg_num))
2715 if (!have_record_arg || PG_ARGISNULL(0))
2718 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2720 tupType = tupdesc->tdtypeid;
2721 tupTypmod = tupdesc->tdtypmod;
2722 ncolumns = tupdesc->natts;
2725 * We arrange to look up the needed I/O info just once per series of
2726 * calls, assuming the record type doesn't change underneath us.
2728 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2729 if (my_extra == NULL ||
2730 my_extra->ncolumns != ncolumns)
2732 fcinfo->flinfo->fn_extra =
2733 MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2734 offsetof(RecordIOData, columns) +
2735 ncolumns * sizeof(ColumnIOData));
2736 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2737 my_extra->record_type = InvalidOid;
2738 my_extra->record_typmod = 0;
2741 if (my_extra->record_type != tupType ||
2742 my_extra->record_typmod != tupTypmod)
2745 offsetof(RecordIOData, columns) +
2746 ncolumns * sizeof(ColumnIOData));
2747 my_extra->record_type = tupType;
2748 my_extra->record_typmod = tupTypmod;
2749 my_extra->ncolumns = ncolumns;
2752 state = palloc0(sizeof(PopulateRecordsetState));
2754 /* make these in a sufficiently long-lived memory context */
2755 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2756 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2757 BlessTupleDesc(state->ret_tdesc);
2758 state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
2759 SFRM_Materialize_Random,
2761 MemoryContextSwitchTo(old_cxt);
2763 state->function_name = funcname;
2764 state->my_extra = my_extra;
2766 state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2768 if (jtype == JSONOID)
2770 text *json = PG_GETARG_TEXT_P(json_arg_num);
2771 JsonLexContext *lex;
2774 sem = palloc0(sizeof(JsonSemAction));
2776 lex = makeJsonLexContext(json, true);
2778 sem->semstate = (void *) state;
2779 sem->array_start = populate_recordset_array_start;
2780 sem->array_element_start = populate_recordset_array_element_start;
2781 sem->scalar = populate_recordset_scalar;
2782 sem->object_field_start = populate_recordset_object_field_start;
2783 sem->object_field_end = populate_recordset_object_field_end;
2784 sem->object_start = populate_recordset_object_start;
2785 sem->object_end = populate_recordset_object_end;
2789 pg_parse_json(lex, sem);
2793 Jsonb *jb = PG_GETARG_JSONB(json_arg_num);
2796 bool skipNested = false;
2797 JsonbIteratorToken r;
2799 Assert(jtype == JSONBOID);
2801 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2803 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2804 errmsg("cannot call %s on a non-array",
2807 it = JsonbIteratorInit(&jb->root);
2809 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2815 Jsonb *element = JsonbValueToJsonb(&v);
2817 if (!JB_ROOT_IS_OBJECT(element))
2819 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2820 errmsg("argument of %s must be an array of objects",
2822 make_row_from_rec_and_jsonb(element, state);
2827 rsi->setResult = state->tuple_store;
2828 rsi->setDesc = state->ret_tdesc;
2834 populate_recordset_object_start(void *state)
2836 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2837 int lex_level = _state->lex->lex_level;
2840 /* Reject object at top level: we must have an array at level 0 */
2843 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2844 errmsg("cannot call %s on an object",
2845 _state->function_name)));
2847 /* Nested objects require no special processing */
2851 /* Object at level 1: set up a new hash table for this object */
2852 memset(&ctl, 0, sizeof(ctl));
2853 ctl.keysize = NAMEDATALEN;
2854 ctl.entrysize = sizeof(JsonHashEntry);
2855 ctl.hcxt = CurrentMemoryContext;
2856 _state->json_hash = hash_create("json object hashtable",
2859 HASH_ELEM | HASH_CONTEXT);
2863 populate_recordset_object_end(void *state)
2865 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2866 HTAB *json_hash = _state->json_hash;
2870 RecordIOData *my_extra = _state->my_extra;
2871 int ncolumns = my_extra->ncolumns;
2872 TupleDesc tupdesc = _state->ret_tdesc;
2873 JsonHashEntry *hashentry;
2874 HeapTupleHeader rec = _state->rec;
2877 /* Nested objects require no special processing */
2878 if (_state->lex->lex_level > 1)
2881 /* Otherwise, construct and return a tuple based on this level-1 object */
2882 values = (Datum *) palloc(ncolumns * sizeof(Datum));
2883 nulls = (bool *) palloc(ncolumns * sizeof(bool));
2887 HeapTupleData tuple;
2889 /* Build a temporary HeapTuple control structure */
2890 tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2891 ItemPointerSetInvalid(&(tuple.t_self));
2892 tuple.t_tableOid = InvalidOid;
2893 tuple.t_data = _state->rec;
2895 /* Break down the tuple into fields */
2896 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2900 for (i = 0; i < ncolumns; ++i)
2902 values[i] = (Datum) 0;
2907 for (i = 0; i < ncolumns; ++i)
2909 ColumnIOData *column_info = &my_extra->columns[i];
2910 Oid column_type = tupdesc->attrs[i]->atttypid;
2913 /* Ignore dropped columns in datatype */
2914 if (tupdesc->attrs[i]->attisdropped)
2920 hashentry = hash_search(json_hash,
2921 NameStr(tupdesc->attrs[i]->attname),
2925 * we can't just skip here if the key wasn't found since we might have
2926 * a domain to deal with. If we were passed in a non-null record
2927 * datum, we assume that the existing values are valid (if they're
2928 * not, then it's not our fault), but if we were passed in a null,
2929 * then every field which we don't populate needs to be run through
2930 * the input function just in case it's a domain type.
2932 if (hashentry == NULL && rec)
2936 * Prepare to convert the column value from text
2938 if (column_info->column_type != column_type)
2940 getTypeInputInfo(column_type,
2941 &column_info->typiofunc,
2942 &column_info->typioparam);
2943 fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2945 column_info->column_type = column_type;
2947 if (hashentry == NULL || hashentry->isnull)
2950 * need InputFunctionCall to happen even for nulls, so that domain
2953 values[i] = InputFunctionCall(&column_info->proc, NULL,
2954 column_info->typioparam,
2955 tupdesc->attrs[i]->atttypmod);
2960 value = hashentry->val;
2962 values[i] = InputFunctionCall(&column_info->proc, value,
2963 column_info->typioparam,
2964 tupdesc->attrs[i]->atttypmod);
2969 rettuple = heap_form_tuple(tupdesc, values, nulls);
2971 tuplestore_puttuple(_state->tuple_store, rettuple);
2973 /* Done with hash for this object */
2974 hash_destroy(json_hash);
2975 _state->json_hash = NULL;
2979 populate_recordset_array_element_start(void *state, bool isnull)
2981 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2983 if (_state->lex->lex_level == 1 &&
2984 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
2986 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2987 errmsg("argument of %s must be an array of objects",
2988 _state->function_name)));
2992 populate_recordset_array_start(void *state)
2998 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
3000 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3002 if (_state->lex->lex_level == 0)
3004 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3005 errmsg("cannot call %s on a scalar",
3006 _state->function_name)));
3008 if (_state->lex->lex_level == 2)
3009 _state->saved_scalar = token;
3013 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
3015 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3017 if (_state->lex->lex_level > 2)
3020 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3021 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
3023 _state->save_json_start = _state->lex->token_start;
3027 _state->save_json_start = NULL;
3032 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
3034 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3035 JsonHashEntry *hashentry;
3039 * Ignore nested fields.
3041 if (_state->lex->lex_level > 2)
3045 * Ignore field names >= NAMEDATALEN - they can't match a record field.
3046 * (Note: without this test, the hash code would truncate the string at
3047 * NAMEDATALEN-1, and could then match against a similarly-truncated
3048 * record field name. That would be a reasonable behavior, but this code
3049 * has previously insisted on exact equality, so we keep this behavior.)
3051 if (strlen(fname) >= NAMEDATALEN)
3054 hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
3057 * found being true indicates a duplicate. We don't do anything about
3058 * that, a later field with the same name overrides the earlier field.
3061 hashentry->isnull = isnull;
3062 if (_state->save_json_start != NULL)
3064 int len = _state->lex->prev_token_terminator - _state->save_json_start;
3065 char *val = palloc((len + 1) * sizeof(char));
3067 memcpy(val, _state->save_json_start, len);
3069 hashentry->val = val;
3073 /* must have had a scalar instead */
3074 hashentry->val = _state->saved_scalar;
3079 * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3082 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
3083 char *key, uint32 keylen)
3088 k.val.string.val = key;
3089 k.val.string.len = keylen;
3091 return findJsonbValueFromContainer(container, flags, &k);
3095 * Semantic actions for json_strip_nulls.
3097 * Simply repeat the input on the output unless we encounter
3098 * a null object field. State for this is set when the field
3099 * is started and reset when the scalar action (which must be next)
3104 sn_object_start(void *state)
3106 StripnullState *_state = (StripnullState *) state;
3108 appendStringInfoCharMacro(_state->strval, '{');
3112 sn_object_end(void *state)
3114 StripnullState *_state = (StripnullState *) state;
3116 appendStringInfoCharMacro(_state->strval, '}');
3120 sn_array_start(void *state)
3122 StripnullState *_state = (StripnullState *) state;
3124 appendStringInfoCharMacro(_state->strval, '[');
3128 sn_array_end(void *state)
3130 StripnullState *_state = (StripnullState *) state;
3132 appendStringInfoCharMacro(_state->strval, ']');
3136 sn_object_field_start(void *state, char *fname, bool isnull)
3138 StripnullState *_state = (StripnullState *) state;
3143 * The next thing must be a scalar or isnull couldn't be true, so
3144 * there is no danger of this state being carried down into a nested
3145 * object or array. The flag will be reset in the scalar action.
3147 _state->skip_next_null = true;
3151 if (_state->strval->data[_state->strval->len - 1] != '{')
3152 appendStringInfoCharMacro(_state->strval, ',');
3155 * Unfortunately we don't have the quoted and escaped string any more, so
3156 * we have to re-escape it.
3158 escape_json(_state->strval, fname);
3160 appendStringInfoCharMacro(_state->strval, ':');
3164 sn_array_element_start(void *state, bool isnull)
3166 StripnullState *_state = (StripnullState *) state;
3168 if (_state->strval->data[_state->strval->len - 1] != '[')
3169 appendStringInfoCharMacro(_state->strval, ',');
3173 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3175 StripnullState *_state = (StripnullState *) state;
3177 if (_state->skip_next_null)
3179 Assert(tokentype == JSON_TOKEN_NULL);
3180 _state->skip_next_null = false;
3184 if (tokentype == JSON_TOKEN_STRING)
3185 escape_json(_state->strval, token);
3187 appendStringInfoString(_state->strval, token);
3191 * SQL function json_strip_nulls(json) -> json
3194 json_strip_nulls(PG_FUNCTION_ARGS)
3196 text *json = PG_GETARG_TEXT_P(0);
3197 StripnullState *state;
3198 JsonLexContext *lex;
3201 lex = makeJsonLexContext(json, true);
3202 state = palloc0(sizeof(StripnullState));
3203 sem = palloc0(sizeof(JsonSemAction));
3205 state->strval = makeStringInfo();
3206 state->skip_next_null = false;
3209 sem->semstate = (void *) state;
3210 sem->object_start = sn_object_start;
3211 sem->object_end = sn_object_end;
3212 sem->array_start = sn_array_start;
3213 sem->array_end = sn_array_end;
3214 sem->scalar = sn_scalar;
3215 sem->array_element_start = sn_array_element_start;
3216 sem->object_field_start = sn_object_field_start;
3218 pg_parse_json(lex, sem);
3220 PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
3221 state->strval->len));
3226 * SQL function jsonb_strip_nulls(jsonb) -> jsonb
3229 jsonb_strip_nulls(PG_FUNCTION_ARGS)
3231 Jsonb *jb = PG_GETARG_JSONB(0);
3233 JsonbParseState *parseState = NULL;
3234 JsonbValue *res = NULL;
3237 JsonbIteratorToken type;
3238 bool last_was_key = false;
3240 if (JB_ROOT_IS_SCALAR(jb))
3241 PG_RETURN_POINTER(jb);
3243 it = JsonbIteratorInit(&jb->root);
3245 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3247 Assert(!(type == WJB_KEY && last_was_key));
3249 if (type == WJB_KEY)
3251 /* stash the key until we know if it has a null value */
3253 last_was_key = true;
3259 /* if the last element was a key this one can't be */
3260 last_was_key = false;
3262 /* skip this field if value is null */
3263 if (type == WJB_VALUE && v.type == jbvNull)
3266 /* otherwise, do a delayed push of the key */
3267 (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3270 if (type == WJB_VALUE || type == WJB_ELEM)
3271 res = pushJsonbValue(&parseState, type, &v);
3273 res = pushJsonbValue(&parseState, type, NULL);
3276 Assert(res != NULL);
3278 PG_RETURN_POINTER(JsonbValueToJsonb(res));
3282 * Add values from the jsonb to the parse state.
3284 * If the parse state container is an object, the jsonb is pushed as
3285 * a value, not a key.
3287 * This needs to be done using an iterator because pushJsonbValue doesn't
3288 * like getting jbvBinary values, so we can't just push jb as a whole.
3291 addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
3294 JsonbValue *o = &(*jbps)->contVal;
3296 JsonbIteratorToken type;
3298 it = JsonbIteratorInit(&jb->root);
3300 Assert(o->type == jbvArray || o->type == jbvObject);
3302 if (JB_ROOT_IS_SCALAR(jb))
3304 (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3305 (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3310 (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3313 (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3316 elog(ERROR, "unexpected parent of nested structure");
3321 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3323 if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3324 (void) pushJsonbValue(jbps, type, &v);
3326 (void) pushJsonbValue(jbps, type, NULL);
3333 * SQL function jsonb_pretty (jsonb)
3335 * Pretty-printed text for the jsonb
3338 jsonb_pretty(PG_FUNCTION_ARGS)
3340 Jsonb *jb = PG_GETARG_JSONB(0);
3341 StringInfo str = makeStringInfo();
3343 JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3345 PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
3349 * SQL function jsonb_concat (jsonb, jsonb)
3351 * function for || operator
3354 jsonb_concat(PG_FUNCTION_ARGS)
3356 Jsonb *jb1 = PG_GETARG_JSONB(0);
3357 Jsonb *jb2 = PG_GETARG_JSONB(1);
3358 JsonbParseState *state = NULL;
3364 * If one of the jsonb is empty, just return the other if it's not scalar
3365 * and both are of the same kind. If it's a scalar or they are of
3366 * different kinds we need to perform the concatenation even if one is
3369 if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
3371 if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
3372 PG_RETURN_JSONB(jb2);
3373 else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
3374 PG_RETURN_JSONB(jb1);
3377 it1 = JsonbIteratorInit(&jb1->root);
3378 it2 = JsonbIteratorInit(&jb2->root);
3380 res = IteratorConcat(&it1, &it2, &state);
3382 Assert(res != NULL);
3384 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3389 * SQL function jsonb_delete (jsonb, text)
3391 * return a copy of the jsonb with the indicated item
3395 jsonb_delete(PG_FUNCTION_ARGS)
3397 Jsonb *in = PG_GETARG_JSONB(0);
3398 text *key = PG_GETARG_TEXT_PP(1);
3399 char *keyptr = VARDATA_ANY(key);
3400 int keylen = VARSIZE_ANY_EXHDR(key);
3401 JsonbParseState *state = NULL;
3405 bool skipNested = false;
3406 JsonbIteratorToken r;
3408 if (JB_ROOT_IS_SCALAR(in))
3410 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3411 errmsg("cannot delete from scalar")));
3413 if (JB_ROOT_COUNT(in) == 0)
3414 PG_RETURN_JSONB(in);
3416 it = JsonbIteratorInit(&in->root);
3418 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3422 if ((r == WJB_ELEM || r == WJB_KEY) &&
3423 (v.type == jbvString && keylen == v.val.string.len &&
3424 memcmp(keyptr, v.val.string.val, keylen) == 0))
3426 /* skip corresponding value as well */
3428 JsonbIteratorNext(&it, &v, true);
3433 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3436 Assert(res != NULL);
3438 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3442 * SQL function jsonb_delete (jsonb, variadic text[])
3444 * return a copy of the jsonb with the indicated items
3448 jsonb_delete_array(PG_FUNCTION_ARGS)
3450 Jsonb *in = PG_GETARG_JSONB(0);
3451 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
3455 JsonbParseState *state = NULL;
3459 bool skipNested = false;
3460 JsonbIteratorToken r;
3462 if (ARR_NDIM(keys) > 1)
3464 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3465 errmsg("wrong number of array subscripts")));
3467 if (JB_ROOT_IS_SCALAR(in))
3469 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3470 errmsg("cannot delete from scalar")));
3472 if (JB_ROOT_COUNT(in) == 0)
3473 PG_RETURN_JSONB(in);
3475 deconstruct_array(keys, TEXTOID, -1, false, 'i',
3476 &keys_elems, &keys_nulls, &keys_len);
3479 PG_RETURN_JSONB(in);
3481 it = JsonbIteratorInit(&in->root);
3483 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3487 if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
3492 for (i = 0; i < keys_len; i++)
3500 keyptr = VARDATA_ANY(keys_elems[i]);
3501 keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
3502 if (keylen == v.val.string.len &&
3503 memcmp(keyptr, v.val.string.val, keylen) == 0)
3511 /* skip corresponding value as well */
3513 JsonbIteratorNext(&it, &v, true);
3519 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3522 Assert(res != NULL);
3524 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3528 * SQL function jsonb_delete (jsonb, int)
3530 * return a copy of the jsonb with the indicated item
3531 * removed. Negative int means count back from the
3535 jsonb_delete_idx(PG_FUNCTION_ARGS)
3537 Jsonb *in = PG_GETARG_JSONB(0);
3538 int idx = PG_GETARG_INT32(1);
3539 JsonbParseState *state = NULL;
3545 JsonbIteratorToken r;
3547 if (JB_ROOT_IS_SCALAR(in))
3549 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3550 errmsg("cannot delete from scalar")));
3552 if (JB_ROOT_IS_OBJECT(in))
3554 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3555 errmsg("cannot delete from object using integer index")));
3557 if (JB_ROOT_COUNT(in) == 0)
3558 PG_RETURN_JSONB(in);
3560 it = JsonbIteratorInit(&in->root);
3562 r = JsonbIteratorNext(&it, &v, false);
3563 Assert(r == WJB_BEGIN_ARRAY);
3564 n = v.val.array.nElems;
3575 PG_RETURN_JSONB(in);
3577 pushJsonbValue(&state, r, NULL);
3579 while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3587 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3590 Assert(res != NULL);
3592 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3596 * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
3600 jsonb_set(PG_FUNCTION_ARGS)
3602 Jsonb *in = PG_GETARG_JSONB(0);
3603 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3604 Jsonb *newval = PG_GETARG_JSONB(2);
3605 bool create = PG_GETARG_BOOL(3);
3606 JsonbValue *res = NULL;
3611 JsonbParseState *st = NULL;
3613 if (ARR_NDIM(path) > 1)
3615 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3616 errmsg("wrong number of array subscripts")));
3618 if (JB_ROOT_IS_SCALAR(in))
3620 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3621 errmsg("cannot set path in scalar")));
3623 if (JB_ROOT_COUNT(in) == 0 && !create)
3624 PG_RETURN_JSONB(in);
3626 deconstruct_array(path, TEXTOID, -1, false, 'i',
3627 &path_elems, &path_nulls, &path_len);
3630 PG_RETURN_JSONB(in);
3632 it = JsonbIteratorInit(&in->root);
3634 res = setPath(&it, path_elems, path_nulls, path_len, &st,
3635 0, newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
3637 Assert(res != NULL);
3639 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3644 * SQL function jsonb_delete_path(jsonb, text[])
3647 jsonb_delete_path(PG_FUNCTION_ARGS)
3649 Jsonb *in = PG_GETARG_JSONB(0);
3650 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3651 JsonbValue *res = NULL;
3656 JsonbParseState *st = NULL;
3658 if (ARR_NDIM(path) > 1)
3660 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3661 errmsg("wrong number of array subscripts")));
3663 if (JB_ROOT_IS_SCALAR(in))
3665 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3666 errmsg("cannot delete path in scalar")));
3668 if (JB_ROOT_COUNT(in) == 0)
3669 PG_RETURN_JSONB(in);
3671 deconstruct_array(path, TEXTOID, -1, false, 'i',
3672 &path_elems, &path_nulls, &path_len);
3675 PG_RETURN_JSONB(in);
3677 it = JsonbIteratorInit(&in->root);
3679 res = setPath(&it, path_elems, path_nulls, path_len, &st,
3680 0, NULL, JB_PATH_DELETE);
3682 Assert(res != NULL);
3684 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3688 * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
3692 jsonb_insert(PG_FUNCTION_ARGS)
3694 Jsonb *in = PG_GETARG_JSONB(0);
3695 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3696 Jsonb *newval = PG_GETARG_JSONB(2);
3697 bool after = PG_GETARG_BOOL(3);
3698 JsonbValue *res = NULL;
3703 JsonbParseState *st = NULL;
3705 if (ARR_NDIM(path) > 1)
3707 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3708 errmsg("wrong number of array subscripts")));
3710 if (JB_ROOT_IS_SCALAR(in))
3712 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3713 errmsg("cannot set path in scalar")));
3715 deconstruct_array(path, TEXTOID, -1, false, 'i',
3716 &path_elems, &path_nulls, &path_len);
3719 PG_RETURN_JSONB(in);
3721 it = JsonbIteratorInit(&in->root);
3723 res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
3724 after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
3726 Assert(res != NULL);
3728 PG_RETURN_JSONB(JsonbValueToJsonb(res));
3732 * Iterate over all jsonb objects and merge them into one.
3733 * The logic of this function copied from the same hstore function,
3734 * except the case, when it1 & it2 represents jbvObject.
3735 * In that case we just append the content of it2 to it1 without any
3739 IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3740 JsonbParseState **state)
3745 JsonbIteratorToken r1,
3750 r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3751 r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3754 * Both elements are objects.
3756 if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3759 * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3760 * (because res will not be finished yet).
3762 pushJsonbValue(state, r1, NULL);
3763 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3764 pushJsonbValue(state, r1, &v1);
3767 * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3768 * (the concatenation will be completed).
3770 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3771 res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3775 * Both elements are arrays (either can be scalar).
3777 else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3779 pushJsonbValue(state, r1, NULL);
3781 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3783 Assert(r1 == WJB_ELEM);
3784 pushJsonbValue(state, r1, &v1);
3787 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
3789 Assert(r2 == WJB_ELEM);
3790 pushJsonbValue(state, WJB_ELEM, &v2);
3793 res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
3795 /* have we got array || object or object || array? */
3796 else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3797 (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3800 JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3801 JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3803 bool prepend = (rk1 == WJB_BEGIN_OBJECT);
3805 pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
3809 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3810 while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3811 pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
3813 while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3814 res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
3818 while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3819 pushJsonbValue(state, r1, &v1);
3821 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3822 while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3823 pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3825 res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3831 * This must be scalar || object or object || scalar, as that's all
3832 * that's left. Both of these make no sense, so error out.
3835 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3836 errmsg("invalid concatenation of jsonb objects")));
3843 * Do most of the heavy work for jsonb_set/jsonb_insert
3845 * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
3847 * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
3848 * we create the new value if the key or array index does not exist.
3850 * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
3851 * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
3853 * All path elements before the last must already exist
3854 * whatever bits in op_type are set, or nothing is done.
3857 setPath(JsonbIterator **it, Datum *path_elems,
3858 bool *path_nulls, int path_len,
3859 JsonbParseState **st, int level, Jsonb *newval, int op_type)
3862 JsonbIteratorToken r;
3865 check_stack_depth();
3867 if (path_nulls[level])
3869 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3870 errmsg("path element at position %d is null",
3873 r = JsonbIteratorNext(it, &v, false);
3877 case WJB_BEGIN_ARRAY:
3878 (void) pushJsonbValue(st, r, NULL);
3879 setPathArray(it, path_elems, path_nulls, path_len, st, level,
3880 newval, v.val.array.nElems, op_type);
3881 r = JsonbIteratorNext(it, &v, false);
3882 Assert(r == WJB_END_ARRAY);
3883 res = pushJsonbValue(st, r, NULL);
3885 case WJB_BEGIN_OBJECT:
3886 (void) pushJsonbValue(st, r, NULL);
3887 setPathObject(it, path_elems, path_nulls, path_len, st, level,
3888 newval, v.val.object.nPairs, op_type);
3889 r = JsonbIteratorNext(it, &v, true);
3890 Assert(r == WJB_END_OBJECT);
3891 res = pushJsonbValue(st, r, NULL);
3895 res = pushJsonbValue(st, r, &v);
3898 elog(ERROR, "unrecognized iterator result: %d", (int) r);
3899 res = NULL; /* keep compiler quiet */
3907 * Object walker for setPath
3910 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3911 int path_len, JsonbParseState **st, int level,
3912 Jsonb *newval, uint32 npairs, int op_type)
3919 if (level >= path_len || path_nulls[level])
3922 /* empty object is a special case for create */
3923 if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
3924 (level == path_len - 1))
3928 newkey.type = jbvString;
3929 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3930 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3932 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3933 addJsonbToParseState(st, newval);
3936 for (i = 0; i < npairs; i++)
3938 JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
3940 Assert(r == WJB_KEY);
3943 k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
3944 memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
3945 k.val.string.len) == 0)
3947 if (level == path_len - 1)
3950 * called from jsonb_insert(), it forbids redefining an
3953 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
3955 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3956 errmsg("cannot replace existing key"),
3957 errhint("Try using the function jsonb_set "
3958 "to replace key value.")));
3960 r = JsonbIteratorNext(it, &v, true); /* skip value */
3961 if (!(op_type & JB_PATH_DELETE))
3963 (void) pushJsonbValue(st, WJB_KEY, &k);
3964 addJsonbToParseState(st, newval);
3970 (void) pushJsonbValue(st, r, &k);
3971 setPath(it, path_elems, path_nulls, path_len,
3972 st, level + 1, newval, op_type);
3977 if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
3978 level == path_len - 1 && i == npairs - 1)
3982 newkey.type = jbvString;
3983 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3984 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3986 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3987 addJsonbToParseState(st, newval);
3990 (void) pushJsonbValue(st, r, &k);
3991 r = JsonbIteratorNext(it, &v, false);
3992 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3993 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3995 int walking_level = 1;
3997 while (walking_level != 0)
3999 r = JsonbIteratorNext(it, &v, false);
4001 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4003 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4006 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4014 * Array walker for setPath
4017 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4018 int path_len, JsonbParseState **st, int level,
4019 Jsonb *newval, uint32 nelems, int op_type)
4026 /* pick correct index */
4027 if (level < path_len && !path_nulls[level])
4029 char *c = TextDatumGetCString(path_elems[level]);
4034 lindex = strtol(c, &badp, 10);
4035 if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
4038 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
4039 errmsg("path element at position %d is not an integer: \"%s\"",
4054 if (idx > 0 && idx > nelems)
4058 * if we're creating, and idx == INT_MIN, we prepend the new value to the
4059 * array also if the array is empty - in which case we don't really care
4060 * what the idx value is
4063 if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
4064 (op_type & JB_PATH_CREATE_OR_INSERT))
4066 Assert(newval != NULL);
4067 addJsonbToParseState(st, newval);
4071 /* iterate over the array elements */
4072 for (i = 0; i < nelems; i++)
4074 JsonbIteratorToken r;
4076 if (i == idx && level < path_len)
4078 if (level == path_len - 1)
4080 r = JsonbIteratorNext(it, &v, true); /* skip */
4082 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
4083 addJsonbToParseState(st, newval);
4086 * We should keep current value only in case of
4087 * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
4088 * otherwise it should be deleted or replaced
4090 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
4091 (void) pushJsonbValue(st, r, &v);
4093 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
4094 addJsonbToParseState(st, newval);
4099 (void) setPath(it, path_elems, path_nulls, path_len,
4100 st, level + 1, newval, op_type);
4104 r = JsonbIteratorNext(it, &v, false);
4106 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4108 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4110 int walking_level = 1;
4112 while (walking_level != 0)
4114 r = JsonbIteratorNext(it, &v, false);
4116 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4118 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4121 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4125 if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
4126 level == path_len - 1 && i == nelems - 1)
4128 addJsonbToParseState(st, newval);