1 /*-------------------------------------------------------------------------
4 * Functions to process JSON data types.
6 * Portions Copyright (c) 1996-2018, 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/syscache.h"
35 #include "utils/typcache.h"
37 /* Operations available for setPath */
38 #define JB_PATH_CREATE 0x0001
39 #define JB_PATH_DELETE 0x0002
40 #define JB_PATH_REPLACE 0x0004
41 #define JB_PATH_INSERT_BEFORE 0x0008
42 #define JB_PATH_INSERT_AFTER 0x0010
43 #define JB_PATH_CREATE_OR_INSERT \
44 (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
46 /* state for json_object_keys */
47 typedef struct OkeysState
56 /* state for iterate_json_string_values function */
57 typedef struct IterateJsonStringValuesState
60 JsonIterateStringValuesAction action; /* an action that will be applied
61 * to each json value */
62 void *action_state; /* any necessary context for iteration */
63 } IterateJsonStringValuesState;
65 /* state for transform_json_string_values function */
66 typedef struct TransformJsonStringValuesState
69 StringInfo strval; /* resulting json */
70 JsonTransformStringValuesAction action; /* an action that will be applied
71 * to each json value */
72 void *action_state; /* any necessary context for transformation */
73 } TransformJsonStringValuesState;
75 /* state for json_get* functions */
76 typedef struct GetState
81 bool normalize_results;
83 int npath; /* length of each path-related array */
84 char **path_names; /* field name(s) being sought */
85 int *path_indexes; /* array index(es) being sought */
86 bool *pathok; /* is path matched to current depth? */
87 int *array_cur_index; /* current element index at each path
91 /* state for json_array_length */
92 typedef struct AlenState
98 /* state for json_each */
99 typedef struct EachState
102 Tuplestorestate *tuple_store;
104 MemoryContext tmp_cxt;
106 bool normalize_results;
108 char *normalized_scalar;
111 /* state for json_array_elements */
112 typedef struct ElementsState
115 const char *function_name;
116 Tuplestorestate *tuple_store;
118 MemoryContext tmp_cxt;
120 bool normalize_results;
122 char *normalized_scalar;
125 /* state for get_json_object_as_hash */
126 typedef struct JHashState
129 const char *function_name;
132 char *save_json_start;
133 JsonTokenType saved_token_type;
136 /* hashtable element */
137 typedef struct JsonHashEntry
139 char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
144 /* structure to cache type I/O metadata needed for populate_scalar() */
145 typedef struct ScalarIOData
151 /* these two structures are used recursively */
152 typedef struct ColumnIOData ColumnIOData;
153 typedef struct RecordIOData RecordIOData;
155 /* structure to cache metadata needed for populate_array() */
156 typedef struct ArrayIOData
158 ColumnIOData *element_info; /* metadata cache */
159 Oid element_type; /* array element type id */
160 int32 element_typmod; /* array element type modifier */
163 /* structure to cache metadata needed for populate_composite() */
164 typedef struct CompositeIOData
167 * We use pointer to a RecordIOData here because variable-length struct
168 * RecordIOData can't be used directly in ColumnIOData.io union
170 RecordIOData *record_io; /* metadata cache for populate_record() */
171 TupleDesc tupdesc; /* cached tuple descriptor */
172 /* these fields differ from target type only if domain over composite: */
173 Oid base_typid; /* base type id */
174 int32 base_typmod; /* base type modifier */
175 /* this field is used only if target type is domain over composite: */
176 void *domain_info; /* opaque cache for domain checks */
179 /* structure to cache metadata needed for populate_domain() */
180 typedef struct DomainIOData
182 ColumnIOData *base_io; /* metadata cache */
183 Oid base_typid; /* base type id */
184 int32 base_typmod; /* base type modifier */
185 void *domain_info; /* opaque cache for domain checks */
188 /* enumeration type categories */
191 TYPECAT_SCALAR = 's',
193 TYPECAT_COMPOSITE = 'c',
194 TYPECAT_COMPOSITE_DOMAIN = 'C',
198 /* these two are stolen from hstore / record_out, used in populate_record* */
200 /* structure to cache record metadata needed for populate_record_field() */
203 Oid typid; /* column type id */
204 int32 typmod; /* column type modifier */
205 TypeCat typcat; /* column type category */
206 ScalarIOData scalar_io; /* metadata cache for directi conversion
207 * through input function */
211 CompositeIOData composite;
213 } io; /* metadata cache for various column type
217 /* structure to cache record metadata needed for populate_record() */
223 ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
226 /* per-query cache for populate_recordset */
227 typedef struct PopulateRecordsetCache
229 Oid argtype; /* declared type of the record argument */
230 ColumnIOData c; /* metadata cache for populate_composite() */
231 MemoryContext fn_mcxt; /* where this is stored */
232 } PopulateRecordsetCache;
234 /* per-call state for populate_recordset */
235 typedef struct PopulateRecordsetState
238 const char *function_name;
241 char *save_json_start;
242 JsonTokenType saved_token_type;
243 Tuplestorestate *tuple_store;
245 PopulateRecordsetCache *cache;
246 } PopulateRecordsetState;
248 /* structure to cache metadata needed for populate_record_worker() */
249 typedef struct PopulateRecordCache
251 Oid argtype; /* declared type of the record argument */
252 ColumnIOData c; /* metadata cache for populate_composite() */
253 } PopulateRecordCache;
255 /* common data for populate_array_json() and populate_array_dim_jsonb() */
256 typedef struct PopulateArrayContext
258 ArrayBuildState *astate; /* array build state */
259 ArrayIOData *aio; /* metadata cache */
260 MemoryContext acxt; /* array build memory context */
261 MemoryContext mcxt; /* cache memory context */
262 const char *colname; /* for diagnostics only */
263 int *dims; /* dimensions */
264 int *sizes; /* current dimension counters */
265 int ndims; /* number of dimensions */
266 } PopulateArrayContext;
268 /* state for populate_array_json() */
269 typedef struct PopulateArrayState
271 JsonLexContext *lex; /* json lexer */
272 PopulateArrayContext *ctx; /* context */
273 char *element_start; /* start of the current array element */
274 char *element_scalar; /* current array element token if it is a
276 JsonTokenType element_type; /* current array element type */
277 } PopulateArrayState;
279 /* state for json_strip_nulls */
280 typedef struct StripnullState
287 /* structure for generalized json/jsonb value passing */
288 typedef struct JsValue
290 bool is_json; /* json/jsonb */
295 char *str; /* json string */
296 int len; /* json string length or -1 if null-terminated */
297 JsonTokenType type; /* json type */
298 } json; /* json value */
300 JsonbValue *jsonb; /* jsonb value */
304 typedef struct JsObject
306 bool is_json; /* json/jsonb */
310 JsonbContainer *jsonb_cont;
314 /* useful macros for testing JsValue properties */
315 #define JsValueIsNull(jsv) \
317 (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
318 (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
320 #define JsValueIsString(jsv) \
321 ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
322 : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
324 #define JsObjectIsEmpty(jso) \
326 ? hash_get_num_entries((jso)->val.json_hash) == 0 \
327 : ((jso)->val.jsonb_cont == NULL || \
328 JsonContainerSize((jso)->val.jsonb_cont) == 0))
330 #define JsObjectFree(jso) \
332 if ((jso)->is_json) \
333 hash_destroy((jso)->val.json_hash); \
336 /* semantic action functions for json_object_keys */
337 static void okeys_object_field_start(void *state, char *fname, bool isnull);
338 static void okeys_array_start(void *state);
339 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
341 /* semantic action functions for json_get* functions */
342 static void get_object_start(void *state);
343 static void get_object_end(void *state);
344 static void get_object_field_start(void *state, char *fname, bool isnull);
345 static void get_object_field_end(void *state, char *fname, bool isnull);
346 static void get_array_start(void *state);
347 static void get_array_end(void *state);
348 static void get_array_element_start(void *state, bool isnull);
349 static void get_array_element_end(void *state, bool isnull);
350 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
352 /* common worker function for json getter functions */
353 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
354 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
355 bool normalize_results);
356 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
358 /* semantic action functions for json_array_length */
359 static void alen_object_start(void *state);
360 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
361 static void alen_array_element_start(void *state, bool isnull);
363 /* common workers for json{b}_each* functions */
364 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
365 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
368 /* semantic action functions for json_each */
369 static void each_object_field_start(void *state, char *fname, bool isnull);
370 static void each_object_field_end(void *state, char *fname, bool isnull);
371 static void each_array_start(void *state);
372 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
374 /* common workers for json{b}_array_elements_* functions */
375 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
377 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
380 /* semantic action functions for json_array_elements */
381 static void elements_object_start(void *state);
382 static void elements_array_element_start(void *state, bool isnull);
383 static void elements_array_element_end(void *state, bool isnull);
384 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
386 /* turn a json object into a hash table */
387 static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname);
389 /* semantic actions for populate_array_json */
390 static void populate_array_object_start(void *_state);
391 static void populate_array_array_end(void *_state);
392 static void populate_array_element_start(void *_state, bool isnull);
393 static void populate_array_element_end(void *_state, bool isnull);
394 static void populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
396 /* semantic action functions for get_json_object_as_hash */
397 static void hash_object_field_start(void *state, char *fname, bool isnull);
398 static void hash_object_field_end(void *state, char *fname, bool isnull);
399 static void hash_array_start(void *state);
400 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
402 /* semantic action functions for populate_recordset */
403 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
404 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
405 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
406 static void populate_recordset_object_start(void *state);
407 static void populate_recordset_object_end(void *state);
408 static void populate_recordset_array_start(void *state);
409 static void populate_recordset_array_element_start(void *state, bool isnull);
411 /* semantic action functions for json_strip_nulls */
412 static void sn_object_start(void *state);
413 static void sn_object_end(void *state);
414 static void sn_array_start(void *state);
415 static void sn_array_end(void *state);
416 static void sn_object_field_start(void *state, char *fname, bool isnull);
417 static void sn_array_element_start(void *state, bool isnull);
418 static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
420 /* worker functions for populate_record, to_record, populate_recordset and to_recordset */
421 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
422 bool have_record_arg);
423 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
424 bool have_record_arg);
426 /* helper functions for populate_record[set] */
427 static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p,
428 HeapTupleHeader defaultval, MemoryContext mcxt,
430 static void JsValueToJsObject(JsValue *jsv, JsObject *jso);
431 static Datum populate_composite(CompositeIOData *io, Oid typid,
432 const char *colname, MemoryContext mcxt,
433 HeapTupleHeader defaultval, JsValue *jsv, bool isnull);
434 static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv);
435 static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod,
436 MemoryContext mcxt, bool need_scalar);
437 static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod,
438 const char *colname, MemoryContext mcxt, Datum defaultval,
439 JsValue *jsv, bool *isnull);
440 static RecordIOData *allocate_record_info(MemoryContext mcxt, int ncolumns);
441 static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv);
442 static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj);
443 static void populate_array_json(PopulateArrayContext *ctx, char *json, int len);
444 static void populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv,
446 static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim);
447 static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims);
448 static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim);
449 static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv);
450 static Datum populate_array(ArrayIOData *aio, const char *colname,
451 MemoryContext mcxt, JsValue *jsv);
452 static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname,
453 MemoryContext mcxt, JsValue *jsv, bool isnull);
455 /* Worker that takes care of common setup for us */
456 static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
461 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
462 static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
463 JsonbParseState **state);
464 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
465 bool *path_nulls, int path_len,
466 JsonbParseState **st, int level, Jsonb *newval,
468 static void setPathObject(JsonbIterator **it, Datum *path_elems,
469 bool *path_nulls, int path_len, JsonbParseState **st,
471 Jsonb *newval, uint32 npairs, int op_type);
472 static void setPathArray(JsonbIterator **it, Datum *path_elems,
473 bool *path_nulls, int path_len, JsonbParseState **st,
474 int level, Jsonb *newval, uint32 nelems, int op_type);
475 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
477 /* function supporting iterate_json_string_values */
478 static void iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
480 /* functions supporting transform_json_string_values */
481 static void transform_string_values_object_start(void *state);
482 static void transform_string_values_object_end(void *state);
483 static void transform_string_values_array_start(void *state);
484 static void transform_string_values_array_end(void *state);
485 static void transform_string_values_object_field_start(void *state, char *fname, bool isnull);
486 static void transform_string_values_array_element_start(void *state, bool isnull);
487 static void transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
490 * SQL function json_object_keys
492 * Returns the set of keys for the object argument.
494 * This SRF operates in value-per-call mode. It processes the
495 * object during the first call, and the keys are simply stashed
496 * in an array, whose size is expanded as necessary. This is probably
497 * safe enough for a list of keys of a single object, since they are
498 * limited in size to NAMEDATALEN and the number of keys is unlikely to
499 * be so huge that it has major memory implications.
502 jsonb_object_keys(PG_FUNCTION_ARGS)
504 FuncCallContext *funcctx;
508 if (SRF_IS_FIRSTCALL())
510 MemoryContext oldcontext;
511 Jsonb *jb = PG_GETARG_JSONB_P(0);
512 bool skipNested = false;
515 JsonbIteratorToken r;
517 if (JB_ROOT_IS_SCALAR(jb))
519 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
520 errmsg("cannot call %s on a scalar",
521 "jsonb_object_keys")));
522 else if (JB_ROOT_IS_ARRAY(jb))
524 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
525 errmsg("cannot call %s on an array",
526 "jsonb_object_keys")));
528 funcctx = SRF_FIRSTCALL_INIT();
529 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
531 state = palloc(sizeof(OkeysState));
533 state->result_size = JB_ROOT_COUNT(jb);
534 state->result_count = 0;
535 state->sent_count = 0;
536 state->result = palloc(state->result_size * sizeof(char *));
538 it = JsonbIteratorInit(&jb->root);
540 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
548 cstr = palloc(v.val.string.len + 1 * sizeof(char));
549 memcpy(cstr, v.val.string.val, v.val.string.len);
550 cstr[v.val.string.len] = '\0';
551 state->result[state->result_count++] = cstr;
555 MemoryContextSwitchTo(oldcontext);
556 funcctx->user_fctx = (void *) state;
559 funcctx = SRF_PERCALL_SETUP();
560 state = (OkeysState *) funcctx->user_fctx;
562 if (state->sent_count < state->result_count)
564 char *nxt = state->result[state->sent_count++];
566 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
569 /* cleanup to reduce or eliminate memory leaks */
570 for (i = 0; i < state->result_count; i++)
571 pfree(state->result[i]);
572 pfree(state->result);
575 SRF_RETURN_DONE(funcctx);
580 json_object_keys(PG_FUNCTION_ARGS)
582 FuncCallContext *funcctx;
586 if (SRF_IS_FIRSTCALL())
588 text *json = PG_GETARG_TEXT_PP(0);
589 JsonLexContext *lex = makeJsonLexContext(json, true);
591 MemoryContext oldcontext;
593 funcctx = SRF_FIRSTCALL_INIT();
594 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
596 state = palloc(sizeof(OkeysState));
597 sem = palloc0(sizeof(JsonSemAction));
600 state->result_size = 256;
601 state->result_count = 0;
602 state->sent_count = 0;
603 state->result = palloc(256 * sizeof(char *));
605 sem->semstate = (void *) state;
606 sem->array_start = okeys_array_start;
607 sem->scalar = okeys_scalar;
608 sem->object_field_start = okeys_object_field_start;
609 /* remainder are all NULL, courtesy of palloc0 above */
611 pg_parse_json(lex, sem);
612 /* keys are now in state->result */
614 pfree(lex->strval->data);
619 MemoryContextSwitchTo(oldcontext);
620 funcctx->user_fctx = (void *) state;
623 funcctx = SRF_PERCALL_SETUP();
624 state = (OkeysState *) funcctx->user_fctx;
626 if (state->sent_count < state->result_count)
628 char *nxt = state->result[state->sent_count++];
630 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
633 /* cleanup to reduce or eliminate memory leaks */
634 for (i = 0; i < state->result_count; i++)
635 pfree(state->result[i]);
636 pfree(state->result);
639 SRF_RETURN_DONE(funcctx);
643 okeys_object_field_start(void *state, char *fname, bool isnull)
645 OkeysState *_state = (OkeysState *) state;
647 /* only collecting keys for the top level object */
648 if (_state->lex->lex_level != 1)
651 /* enlarge result array if necessary */
652 if (_state->result_count >= _state->result_size)
654 _state->result_size *= 2;
655 _state->result = (char **)
656 repalloc(_state->result, sizeof(char *) * _state->result_size);
659 /* save a copy of the field name */
660 _state->result[_state->result_count++] = pstrdup(fname);
664 okeys_array_start(void *state)
666 OkeysState *_state = (OkeysState *) state;
668 /* top level must be a json object */
669 if (_state->lex->lex_level == 0)
671 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
672 errmsg("cannot call %s on an array",
673 "json_object_keys")));
677 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
679 OkeysState *_state = (OkeysState *) state;
681 /* top level must be a json object */
682 if (_state->lex->lex_level == 0)
684 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
685 errmsg("cannot call %s on a scalar",
686 "json_object_keys")));
690 * json and jsonb getter functions
691 * these implement the -> ->> #> and #>> operators
692 * and the json{b?}_extract_path*(json, text, ...) functions
697 json_object_field(PG_FUNCTION_ARGS)
699 text *json = PG_GETARG_TEXT_PP(0);
700 text *fname = PG_GETARG_TEXT_PP(1);
701 char *fnamestr = text_to_cstring(fname);
704 result = get_worker(json, &fnamestr, NULL, 1, false);
707 PG_RETURN_TEXT_P(result);
713 jsonb_object_field(PG_FUNCTION_ARGS)
715 Jsonb *jb = PG_GETARG_JSONB_P(0);
716 text *key = PG_GETARG_TEXT_PP(1);
719 if (!JB_ROOT_IS_OBJECT(jb))
722 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
724 VARSIZE_ANY_EXHDR(key));
727 PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
733 json_object_field_text(PG_FUNCTION_ARGS)
735 text *json = PG_GETARG_TEXT_PP(0);
736 text *fname = PG_GETARG_TEXT_PP(1);
737 char *fnamestr = text_to_cstring(fname);
740 result = get_worker(json, &fnamestr, NULL, 1, true);
743 PG_RETURN_TEXT_P(result);
749 jsonb_object_field_text(PG_FUNCTION_ARGS)
751 Jsonb *jb = PG_GETARG_JSONB_P(0);
752 text *key = PG_GETARG_TEXT_PP(1);
755 if (!JB_ROOT_IS_OBJECT(jb))
758 v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
760 VARSIZE_ANY_EXHDR(key));
771 result = cstring_to_text(v->val.boolean ? "true" : "false");
774 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
777 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
778 PointerGetDatum(v->val.numeric))));
782 StringInfo jtext = makeStringInfo();
784 (void) JsonbToCString(jtext, v->val.binary.data, -1);
785 result = cstring_to_text_with_len(jtext->data, jtext->len);
789 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
793 PG_RETURN_TEXT_P(result);
800 json_array_element(PG_FUNCTION_ARGS)
802 text *json = PG_GETARG_TEXT_PP(0);
803 int element = PG_GETARG_INT32(1);
806 result = get_worker(json, NULL, &element, 1, false);
809 PG_RETURN_TEXT_P(result);
815 jsonb_array_element(PG_FUNCTION_ARGS)
817 Jsonb *jb = PG_GETARG_JSONB_P(0);
818 int element = PG_GETARG_INT32(1);
821 if (!JB_ROOT_IS_ARRAY(jb))
824 /* Handle negative subscript */
827 uint32 nelements = JB_ROOT_COUNT(jb);
829 if (-element > nelements)
832 element += nelements;
835 v = getIthJsonbValueFromContainer(&jb->root, element);
837 PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
843 json_array_element_text(PG_FUNCTION_ARGS)
845 text *json = PG_GETARG_TEXT_PP(0);
846 int element = PG_GETARG_INT32(1);
849 result = get_worker(json, NULL, &element, 1, true);
852 PG_RETURN_TEXT_P(result);
858 jsonb_array_element_text(PG_FUNCTION_ARGS)
860 Jsonb *jb = PG_GETARG_JSONB_P(0);
861 int element = PG_GETARG_INT32(1);
864 if (!JB_ROOT_IS_ARRAY(jb))
867 /* Handle negative subscript */
870 uint32 nelements = JB_ROOT_COUNT(jb);
872 if (-element > nelements)
875 element += nelements;
878 v = getIthJsonbValueFromContainer(&jb->root, element);
888 result = cstring_to_text(v->val.boolean ? "true" : "false");
891 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
894 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
895 PointerGetDatum(v->val.numeric))));
899 StringInfo jtext = makeStringInfo();
901 (void) JsonbToCString(jtext, v->val.binary.data, -1);
902 result = cstring_to_text_with_len(jtext->data, jtext->len);
906 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
910 PG_RETURN_TEXT_P(result);
917 json_extract_path(PG_FUNCTION_ARGS)
919 return get_path_all(fcinfo, false);
923 json_extract_path_text(PG_FUNCTION_ARGS)
925 return get_path_all(fcinfo, true);
929 * common routine for extract_path functions
932 get_path_all(FunctionCallInfo fcinfo, bool as_text)
934 text *json = PG_GETARG_TEXT_PP(0);
935 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
945 * If the array contains any null elements, return NULL, on the grounds
946 * that you'd have gotten NULL if any RHS value were NULL in a nested
947 * series of applications of the -> operator. (Note: because we also
948 * return NULL for error cases such as no-such-field, this is true
949 * regardless of the contents of the rest of the array.)
951 if (array_contains_nulls(path))
954 deconstruct_array(path, TEXTOID, -1, false, 'i',
955 &pathtext, &pathnulls, &npath);
957 tpath = palloc(npath * sizeof(char *));
958 ipath = palloc(npath * sizeof(int));
960 for (i = 0; i < npath; i++)
962 Assert(!pathnulls[i]);
963 tpath[i] = TextDatumGetCString(pathtext[i]);
966 * we have no idea at this stage what structure the document is so
967 * just convert anything in the path that we can to an integer and set
968 * all the other integers to INT_MIN which will never match.
970 if (*tpath[i] != '\0')
976 ind = strtol(tpath[i], &endptr, 10);
977 if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
978 ipath[i] = (int) ind;
986 result = get_worker(json, tpath, ipath, npath, as_text);
989 PG_RETURN_TEXT_P(result);
997 * common worker for all the json getter functions
999 * json: JSON object (in text form)
1000 * tpath[]: field name(s) to extract
1001 * ipath[]: array index(es) (zero-based) to extract, accepts negatives
1002 * npath: length of tpath[] and/or ipath[]
1003 * normalize_results: true to de-escape string and null scalars
1005 * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
1006 * field is not to be matched at that nesting level. Similarly, ipath can
1007 * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
1008 * not to be matched at that nesting level (a json datum should never be
1009 * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
1012 get_worker(text *json,
1016 bool normalize_results)
1018 JsonLexContext *lex = makeJsonLexContext(json, true);
1019 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1020 GetState *state = palloc0(sizeof(GetState));
1025 /* is it "_as_text" variant? */
1026 state->normalize_results = normalize_results;
1027 state->npath = npath;
1028 state->path_names = tpath;
1029 state->path_indexes = ipath;
1030 state->pathok = palloc0(sizeof(bool) * npath);
1031 state->array_cur_index = palloc(sizeof(int) * npath);
1034 state->pathok[0] = true;
1036 sem->semstate = (void *) state;
1039 * Not all variants need all the semantic routines. Only set the ones that
1040 * are actually needed for maximum efficiency.
1042 sem->scalar = get_scalar;
1045 sem->object_start = get_object_start;
1046 sem->object_end = get_object_end;
1047 sem->array_start = get_array_start;
1048 sem->array_end = get_array_end;
1052 sem->object_field_start = get_object_field_start;
1053 sem->object_field_end = get_object_field_end;
1057 sem->array_start = get_array_start;
1058 sem->array_element_start = get_array_element_start;
1059 sem->array_element_end = get_array_element_end;
1062 pg_parse_json(lex, sem);
1064 return state->tresult;
1068 get_object_start(void *state)
1070 GetState *_state = (GetState *) state;
1071 int lex_level = _state->lex->lex_level;
1073 if (lex_level == 0 && _state->npath == 0)
1076 * Special case: we should match the entire object. We only need this
1077 * at outermost level because at nested levels the match will have
1078 * been started by the outer field or array element callback.
1080 _state->result_start = _state->lex->token_start;
1085 get_object_end(void *state)
1087 GetState *_state = (GetState *) state;
1088 int lex_level = _state->lex->lex_level;
1090 if (lex_level == 0 && _state->npath == 0)
1092 /* Special case: return the entire object */
1093 char *start = _state->result_start;
1094 int len = _state->lex->prev_token_terminator - start;
1096 _state->tresult = cstring_to_text_with_len(start, len);
1101 get_object_field_start(void *state, char *fname, bool isnull)
1103 GetState *_state = (GetState *) state;
1104 bool get_next = false;
1105 int lex_level = _state->lex->lex_level;
1107 if (lex_level <= _state->npath &&
1108 _state->pathok[lex_level - 1] &&
1109 _state->path_names != NULL &&
1110 _state->path_names[lex_level - 1] != NULL &&
1111 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1113 if (lex_level < _state->npath)
1115 /* if not at end of path just mark path ok */
1116 _state->pathok[lex_level] = true;
1120 /* end of path, so we want this value */
1127 /* this object overrides any previous matching object */
1128 _state->tresult = NULL;
1129 _state->result_start = NULL;
1131 if (_state->normalize_results &&
1132 _state->lex->token_type == JSON_TOKEN_STRING)
1134 /* for as_text variants, tell get_scalar to set it for us */
1135 _state->next_scalar = true;
1139 /* for non-as_text variants, just note the json starting point */
1140 _state->result_start = _state->lex->token_start;
1146 get_object_field_end(void *state, char *fname, bool isnull)
1148 GetState *_state = (GetState *) state;
1149 bool get_last = false;
1150 int lex_level = _state->lex->lex_level;
1152 /* same tests as in get_object_field_start */
1153 if (lex_level <= _state->npath &&
1154 _state->pathok[lex_level - 1] &&
1155 _state->path_names != NULL &&
1156 _state->path_names[lex_level - 1] != NULL &&
1157 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1159 if (lex_level < _state->npath)
1161 /* done with this field so reset pathok */
1162 _state->pathok[lex_level] = false;
1166 /* end of path, so we want this value */
1171 /* for as_text scalar case, our work is already done */
1172 if (get_last && _state->result_start != NULL)
1175 * make a text object from the string from the prevously noted json
1176 * start up to the end of the previous token (the lexer is by now
1177 * ahead of us on whatever came after what we're interested in).
1179 if (isnull && _state->normalize_results)
1180 _state->tresult = (text *) NULL;
1183 char *start = _state->result_start;
1184 int len = _state->lex->prev_token_terminator - start;
1186 _state->tresult = cstring_to_text_with_len(start, len);
1189 /* this should be unnecessary but let's do it for cleanliness: */
1190 _state->result_start = NULL;
1195 get_array_start(void *state)
1197 GetState *_state = (GetState *) state;
1198 int lex_level = _state->lex->lex_level;
1200 if (lex_level < _state->npath)
1202 /* Initialize counting of elements in this array */
1203 _state->array_cur_index[lex_level] = -1;
1205 /* INT_MIN value is reserved to represent invalid subscript */
1206 if (_state->path_indexes[lex_level] < 0 &&
1207 _state->path_indexes[lex_level] != INT_MIN)
1209 /* Negative subscript -- convert to positive-wise subscript */
1210 int nelements = json_count_array_elements(_state->lex);
1212 if (-_state->path_indexes[lex_level] <= nelements)
1213 _state->path_indexes[lex_level] += nelements;
1216 else if (lex_level == 0 && _state->npath == 0)
1219 * Special case: we should match the entire array. We only need this
1220 * at the outermost level because at nested levels the match will have
1221 * been started by the outer field or array element callback.
1223 _state->result_start = _state->lex->token_start;
1228 get_array_end(void *state)
1230 GetState *_state = (GetState *) state;
1231 int lex_level = _state->lex->lex_level;
1233 if (lex_level == 0 && _state->npath == 0)
1235 /* Special case: return the entire array */
1236 char *start = _state->result_start;
1237 int len = _state->lex->prev_token_terminator - start;
1239 _state->tresult = cstring_to_text_with_len(start, len);
1244 get_array_element_start(void *state, bool isnull)
1246 GetState *_state = (GetState *) state;
1247 bool get_next = false;
1248 int lex_level = _state->lex->lex_level;
1250 /* Update array element counter */
1251 if (lex_level <= _state->npath)
1252 _state->array_cur_index[lex_level - 1]++;
1254 if (lex_level <= _state->npath &&
1255 _state->pathok[lex_level - 1] &&
1256 _state->path_indexes != NULL &&
1257 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1259 if (lex_level < _state->npath)
1261 /* if not at end of path just mark path ok */
1262 _state->pathok[lex_level] = true;
1266 /* end of path, so we want this value */
1271 /* same logic as for objects */
1274 _state->tresult = NULL;
1275 _state->result_start = NULL;
1277 if (_state->normalize_results &&
1278 _state->lex->token_type == JSON_TOKEN_STRING)
1280 _state->next_scalar = true;
1284 _state->result_start = _state->lex->token_start;
1290 get_array_element_end(void *state, bool isnull)
1292 GetState *_state = (GetState *) state;
1293 bool get_last = false;
1294 int lex_level = _state->lex->lex_level;
1296 /* same tests as in get_array_element_start */
1297 if (lex_level <= _state->npath &&
1298 _state->pathok[lex_level - 1] &&
1299 _state->path_indexes != NULL &&
1300 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1302 if (lex_level < _state->npath)
1304 /* done with this element so reset pathok */
1305 _state->pathok[lex_level] = false;
1309 /* end of path, so we want this value */
1314 /* same logic as for objects */
1315 if (get_last && _state->result_start != NULL)
1317 if (isnull && _state->normalize_results)
1318 _state->tresult = (text *) NULL;
1321 char *start = _state->result_start;
1322 int len = _state->lex->prev_token_terminator - start;
1324 _state->tresult = cstring_to_text_with_len(start, len);
1327 _state->result_start = NULL;
1332 get_scalar(void *state, char *token, JsonTokenType tokentype)
1334 GetState *_state = (GetState *) state;
1335 int lex_level = _state->lex->lex_level;
1337 /* Check for whole-object match */
1338 if (lex_level == 0 && _state->npath == 0)
1340 if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1342 /* we want the de-escaped string */
1343 _state->next_scalar = true;
1345 else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1347 _state->tresult = (text *) NULL;
1352 * This is a bit hokey: we will suppress whitespace after the
1353 * scalar token, but not whitespace before it. Probably not worth
1354 * doing our own space-skipping to avoid that.
1356 char *start = _state->lex->input;
1357 int len = _state->lex->prev_token_terminator - start;
1359 _state->tresult = cstring_to_text_with_len(start, len);
1363 if (_state->next_scalar)
1365 /* a de-escaped text value is wanted, so supply it */
1366 _state->tresult = cstring_to_text(token);
1367 /* make sure the next call to get_scalar doesn't overwrite it */
1368 _state->next_scalar = false;
1373 jsonb_extract_path(PG_FUNCTION_ARGS)
1375 return get_jsonb_path_all(fcinfo, false);
1379 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1381 return get_jsonb_path_all(fcinfo, true);
1385 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1387 Jsonb *jb = PG_GETARG_JSONB_P(0);
1388 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1394 bool have_object = false,
1396 JsonbValue *jbvp = NULL;
1398 JsonbContainer *container;
1401 * If the array contains any null elements, return NULL, on the grounds
1402 * that you'd have gotten NULL if any RHS value were NULL in a nested
1403 * series of applications of the -> operator. (Note: because we also
1404 * return NULL for error cases such as no-such-field, this is true
1405 * regardless of the contents of the rest of the array.)
1407 if (array_contains_nulls(path))
1410 deconstruct_array(path, TEXTOID, -1, false, 'i',
1411 &pathtext, &pathnulls, &npath);
1413 /* Identify whether we have object, array, or scalar at top-level */
1414 container = &jb->root;
1416 if (JB_ROOT_IS_OBJECT(jb))
1418 else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1422 Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
1423 /* Extract the scalar value, if it is what we'll return */
1425 jbvp = getIthJsonbValueFromContainer(container, 0);
1429 * If the array is empty, return the entire LHS object, on the grounds
1430 * that we should do zero field or element extractions. For the
1431 * non-scalar case we can just hand back the object without much work. For
1432 * the scalar case, fall through and deal with the value below the loop.
1433 * (This inconsistency arises because there's no easy way to generate a
1434 * JsonbValue directly for root-level containers.)
1436 if (npath <= 0 && jbvp == NULL)
1440 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1446 /* not text mode - just hand back the jsonb */
1447 PG_RETURN_JSONB_P(jb);
1451 for (i = 0; i < npath; i++)
1455 jbvp = findJsonbValueFromContainerLen(container,
1457 VARDATA(pathtext[i]),
1458 VARSIZE(pathtext[i]) - VARHDRSZ);
1460 else if (have_array)
1464 char *indextext = TextDatumGetCString(pathtext[i]);
1468 lindex = strtol(indextext, &endptr, 10);
1469 if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1470 lindex > INT_MAX || lindex < INT_MIN)
1475 index = (uint32) lindex;
1479 /* Handle negative subscript */
1482 /* Container must be array, but make sure */
1483 if (!JsonContainerIsArray(container))
1484 elog(ERROR, "not a jsonb array");
1486 nelements = JsonContainerSize(container);
1488 if (-lindex > nelements)
1491 index = nelements + lindex;
1494 jbvp = getIthJsonbValueFromContainer(container, index);
1498 /* scalar, extraction yields a null */
1504 else if (i == npath - 1)
1507 if (jbvp->type == jbvBinary)
1509 JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1510 JsonbIteratorToken r;
1512 r = JsonbIteratorNext(&it, &tv, true);
1513 container = (JsonbContainer *) jbvp->val.binary.data;
1514 have_object = r == WJB_BEGIN_OBJECT;
1515 have_array = r == WJB_BEGIN_ARRAY;
1519 have_object = jbvp->type == jbvObject;
1520 have_array = jbvp->type == jbvArray;
1526 /* special-case outputs for string and null values */
1527 if (jbvp->type == jbvString)
1528 PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1529 jbvp->val.string.len));
1530 if (jbvp->type == jbvNull)
1534 res = JsonbValueToJsonb(jbvp);
1538 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1544 /* not text mode - just hand back the jsonb */
1545 PG_RETURN_JSONB_P(res);
1550 * SQL function json_array_length(json) -> int
1553 json_array_length(PG_FUNCTION_ARGS)
1555 text *json = PG_GETARG_TEXT_PP(0);
1557 JsonLexContext *lex;
1560 lex = makeJsonLexContext(json, false);
1561 state = palloc0(sizeof(AlenState));
1562 sem = palloc0(sizeof(JsonSemAction));
1564 /* palloc0 does this for us */
1570 sem->semstate = (void *) state;
1571 sem->object_start = alen_object_start;
1572 sem->scalar = alen_scalar;
1573 sem->array_element_start = alen_array_element_start;
1575 pg_parse_json(lex, sem);
1577 PG_RETURN_INT32(state->count);
1581 jsonb_array_length(PG_FUNCTION_ARGS)
1583 Jsonb *jb = PG_GETARG_JSONB_P(0);
1585 if (JB_ROOT_IS_SCALAR(jb))
1587 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1588 errmsg("cannot get array length of a scalar")));
1589 else if (!JB_ROOT_IS_ARRAY(jb))
1591 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1592 errmsg("cannot get array length of a non-array")));
1594 PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1598 * These next two checks ensure that the json is an array (since it can't be
1599 * a scalar or an object).
1603 alen_object_start(void *state)
1605 AlenState *_state = (AlenState *) state;
1607 /* json structure check */
1608 if (_state->lex->lex_level == 0)
1610 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1611 errmsg("cannot get array length of a non-array")));
1615 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1617 AlenState *_state = (AlenState *) state;
1619 /* json structure check */
1620 if (_state->lex->lex_level == 0)
1622 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1623 errmsg("cannot get array length of a scalar")));
1627 alen_array_element_start(void *state, bool isnull)
1629 AlenState *_state = (AlenState *) state;
1631 /* just count up all the level 1 elements */
1632 if (_state->lex->lex_level == 1)
1637 * SQL function json_each and json_each_text
1639 * decompose a json object into key value pairs.
1641 * Unlike json_object_keys() these SRFs operate in materialize mode,
1642 * stashing results into a Tuplestore object as they go.
1643 * The construction of tuples is done using a temporary memory context
1644 * that is cleared out after each tuple is built.
1647 json_each(PG_FUNCTION_ARGS)
1649 return each_worker(fcinfo, false);
1653 jsonb_each(PG_FUNCTION_ARGS)
1655 return each_worker_jsonb(fcinfo, "jsonb_each", false);
1659 json_each_text(PG_FUNCTION_ARGS)
1661 return each_worker(fcinfo, true);
1665 jsonb_each_text(PG_FUNCTION_ARGS)
1667 return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1671 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1673 Jsonb *jb = PG_GETARG_JSONB_P(0);
1675 Tuplestorestate *tuple_store;
1677 TupleDesc ret_tdesc;
1678 MemoryContext old_cxt,
1680 bool skipNested = false;
1683 JsonbIteratorToken r;
1685 if (!JB_ROOT_IS_OBJECT(jb))
1687 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1688 errmsg("cannot call %s on a non-object",
1691 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1693 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1694 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1695 rsi->expectedDesc == NULL)
1697 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1698 errmsg("set-valued function called in context that "
1699 "cannot accept a set")));
1701 rsi->returnMode = SFRM_Materialize;
1703 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1705 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1706 errmsg("function returning record called in context "
1707 "that cannot accept type record")));
1709 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1711 ret_tdesc = CreateTupleDescCopy(tupdesc);
1712 BlessTupleDesc(ret_tdesc);
1714 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1717 MemoryContextSwitchTo(old_cxt);
1719 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1720 "jsonb_each temporary cxt",
1721 ALLOCSET_DEFAULT_SIZES);
1723 it = JsonbIteratorInit(&jb->root);
1725 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1734 bool nulls[2] = {false, false};
1736 /* Use the tmp context so we can clean up after each tuple is done */
1737 old_cxt = MemoryContextSwitchTo(tmp_cxt);
1739 key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1742 * The next thing the iterator fetches should be the value, no
1743 * matter what shape it is.
1745 r = JsonbIteratorNext(&it, &v, skipNested);
1747 values[0] = PointerGetDatum(key);
1751 if (v.type == jbvNull)
1753 /* a json null is an sql null in text mode */
1755 values[1] = (Datum) NULL;
1761 if (v.type == jbvString)
1763 /* In text mode, scalar strings should be dequoted */
1764 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1768 /* Turn anything else into a json string */
1769 StringInfo jtext = makeStringInfo();
1770 Jsonb *jb = JsonbValueToJsonb(&v);
1772 (void) JsonbToCString(jtext, &jb->root, 0);
1773 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1776 values[1] = PointerGetDatum(sv);
1781 /* Not in text mode, just return the Jsonb */
1782 Jsonb *val = JsonbValueToJsonb(&v);
1784 values[1] = PointerGetDatum(val);
1787 tuple = heap_form_tuple(ret_tdesc, values, nulls);
1789 tuplestore_puttuple(tuple_store, tuple);
1791 /* clean up and switch back */
1792 MemoryContextSwitchTo(old_cxt);
1793 MemoryContextReset(tmp_cxt);
1797 MemoryContextDelete(tmp_cxt);
1799 rsi->setResult = tuple_store;
1800 rsi->setDesc = ret_tdesc;
1807 each_worker(FunctionCallInfo fcinfo, bool as_text)
1809 text *json = PG_GETARG_TEXT_PP(0);
1810 JsonLexContext *lex;
1813 MemoryContext old_cxt;
1817 lex = makeJsonLexContext(json, true);
1818 state = palloc0(sizeof(EachState));
1819 sem = palloc0(sizeof(JsonSemAction));
1821 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1823 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1824 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1825 rsi->expectedDesc == NULL)
1827 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1828 errmsg("set-valued function called in context that "
1829 "cannot accept a set")));
1831 rsi->returnMode = SFRM_Materialize;
1833 (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1835 /* make these in a sufficiently long-lived memory context */
1836 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1838 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1839 BlessTupleDesc(state->ret_tdesc);
1840 state->tuple_store =
1841 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1844 MemoryContextSwitchTo(old_cxt);
1846 sem->semstate = (void *) state;
1847 sem->array_start = each_array_start;
1848 sem->scalar = each_scalar;
1849 sem->object_field_start = each_object_field_start;
1850 sem->object_field_end = each_object_field_end;
1852 state->normalize_results = as_text;
1853 state->next_scalar = false;
1855 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1856 "json_each temporary cxt",
1857 ALLOCSET_DEFAULT_SIZES);
1859 pg_parse_json(lex, sem);
1861 MemoryContextDelete(state->tmp_cxt);
1863 rsi->setResult = state->tuple_store;
1864 rsi->setDesc = state->ret_tdesc;
1871 each_object_field_start(void *state, char *fname, bool isnull)
1873 EachState *_state = (EachState *) state;
1875 /* save a pointer to where the value starts */
1876 if (_state->lex->lex_level == 1)
1879 * next_scalar will be reset in the object_field_end handler, and
1880 * since we know the value is a scalar there is no danger of it being
1881 * on while recursing down the tree.
1883 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1884 _state->next_scalar = true;
1886 _state->result_start = _state->lex->token_start;
1891 each_object_field_end(void *state, char *fname, bool isnull)
1893 EachState *_state = (EachState *) state;
1894 MemoryContext old_cxt;
1899 bool nulls[2] = {false, false};
1901 /* skip over nested objects */
1902 if (_state->lex->lex_level != 1)
1905 /* use the tmp context so we can clean up after each tuple is done */
1906 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1908 values[0] = CStringGetTextDatum(fname);
1910 if (isnull && _state->normalize_results)
1913 values[1] = (Datum) 0;
1915 else if (_state->next_scalar)
1917 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1918 _state->next_scalar = false;
1922 len = _state->lex->prev_token_terminator - _state->result_start;
1923 val = cstring_to_text_with_len(_state->result_start, len);
1924 values[1] = PointerGetDatum(val);
1927 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1929 tuplestore_puttuple(_state->tuple_store, tuple);
1931 /* clean up and switch back */
1932 MemoryContextSwitchTo(old_cxt);
1933 MemoryContextReset(_state->tmp_cxt);
1937 each_array_start(void *state)
1939 EachState *_state = (EachState *) state;
1941 /* json structure check */
1942 if (_state->lex->lex_level == 0)
1944 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1945 errmsg("cannot deconstruct an array as an object")));
1949 each_scalar(void *state, char *token, JsonTokenType tokentype)
1951 EachState *_state = (EachState *) state;
1953 /* json structure check */
1954 if (_state->lex->lex_level == 0)
1956 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1957 errmsg("cannot deconstruct a scalar")));
1959 /* supply de-escaped value if required */
1960 if (_state->next_scalar)
1961 _state->normalized_scalar = token;
1965 * SQL functions json_array_elements and json_array_elements_text
1967 * get the elements from a json array
1969 * a lot of this processing is similar to the json_each* functions
1973 jsonb_array_elements(PG_FUNCTION_ARGS)
1975 return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1979 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1981 return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1985 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1988 Jsonb *jb = PG_GETARG_JSONB_P(0);
1990 Tuplestorestate *tuple_store;
1992 TupleDesc ret_tdesc;
1993 MemoryContext old_cxt,
1995 bool skipNested = false;
1998 JsonbIteratorToken r;
2000 if (JB_ROOT_IS_SCALAR(jb))
2002 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2003 errmsg("cannot extract elements from a scalar")));
2004 else if (!JB_ROOT_IS_ARRAY(jb))
2006 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2007 errmsg("cannot extract elements from an object")));
2009 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2011 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2012 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2013 rsi->expectedDesc == NULL)
2015 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2016 errmsg("set-valued function called in context that "
2017 "cannot accept a set")));
2019 rsi->returnMode = SFRM_Materialize;
2021 /* it's a simple type, so don't use get_call_result_type() */
2022 tupdesc = rsi->expectedDesc;
2024 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2026 ret_tdesc = CreateTupleDescCopy(tupdesc);
2027 BlessTupleDesc(ret_tdesc);
2029 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
2032 MemoryContextSwitchTo(old_cxt);
2034 tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
2035 "jsonb_array_elements temporary cxt",
2036 ALLOCSET_DEFAULT_SIZES);
2038 it = JsonbIteratorInit(&jb->root);
2040 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2048 bool nulls[1] = {false};
2050 /* use the tmp context so we can clean up after each tuple is done */
2051 old_cxt = MemoryContextSwitchTo(tmp_cxt);
2055 Jsonb *val = JsonbValueToJsonb(&v);
2057 values[0] = PointerGetDatum(val);
2061 if (v.type == jbvNull)
2063 /* a json null is an sql null in text mode */
2065 values[0] = (Datum) NULL;
2071 if (v.type == jbvString)
2073 /* in text mode scalar strings should be dequoted */
2074 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2078 /* turn anything else into a json string */
2079 StringInfo jtext = makeStringInfo();
2080 Jsonb *jb = JsonbValueToJsonb(&v);
2082 (void) JsonbToCString(jtext, &jb->root, 0);
2083 sv = cstring_to_text_with_len(jtext->data, jtext->len);
2086 values[0] = PointerGetDatum(sv);
2090 tuple = heap_form_tuple(ret_tdesc, values, nulls);
2092 tuplestore_puttuple(tuple_store, tuple);
2094 /* clean up and switch back */
2095 MemoryContextSwitchTo(old_cxt);
2096 MemoryContextReset(tmp_cxt);
2100 MemoryContextDelete(tmp_cxt);
2102 rsi->setResult = tuple_store;
2103 rsi->setDesc = ret_tdesc;
2109 json_array_elements(PG_FUNCTION_ARGS)
2111 return elements_worker(fcinfo, "json_array_elements", false);
2115 json_array_elements_text(PG_FUNCTION_ARGS)
2117 return elements_worker(fcinfo, "json_array_elements_text", true);
2121 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
2123 text *json = PG_GETARG_TEXT_PP(0);
2125 /* elements only needs escaped strings when as_text */
2126 JsonLexContext *lex = makeJsonLexContext(json, as_text);
2129 MemoryContext old_cxt;
2131 ElementsState *state;
2133 state = palloc0(sizeof(ElementsState));
2134 sem = palloc0(sizeof(JsonSemAction));
2136 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2138 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2139 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2140 rsi->expectedDesc == NULL)
2142 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2143 errmsg("set-valued function called in context that "
2144 "cannot accept a set")));
2146 rsi->returnMode = SFRM_Materialize;
2148 /* it's a simple type, so don't use get_call_result_type() */
2149 tupdesc = rsi->expectedDesc;
2151 /* make these in a sufficiently long-lived memory context */
2152 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2154 state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2155 BlessTupleDesc(state->ret_tdesc);
2156 state->tuple_store =
2157 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
2160 MemoryContextSwitchTo(old_cxt);
2162 sem->semstate = (void *) state;
2163 sem->object_start = elements_object_start;
2164 sem->scalar = elements_scalar;
2165 sem->array_element_start = elements_array_element_start;
2166 sem->array_element_end = elements_array_element_end;
2168 state->function_name = funcname;
2169 state->normalize_results = as_text;
2170 state->next_scalar = false;
2172 state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
2173 "json_array_elements temporary cxt",
2174 ALLOCSET_DEFAULT_SIZES);
2176 pg_parse_json(lex, sem);
2178 MemoryContextDelete(state->tmp_cxt);
2180 rsi->setResult = state->tuple_store;
2181 rsi->setDesc = state->ret_tdesc;
2187 elements_array_element_start(void *state, bool isnull)
2189 ElementsState *_state = (ElementsState *) state;
2191 /* save a pointer to where the value starts */
2192 if (_state->lex->lex_level == 1)
2195 * next_scalar will be reset in the array_element_end handler, and
2196 * since we know the value is a scalar there is no danger of it being
2197 * on while recursing down the tree.
2199 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2200 _state->next_scalar = true;
2202 _state->result_start = _state->lex->token_start;
2207 elements_array_element_end(void *state, bool isnull)
2209 ElementsState *_state = (ElementsState *) state;
2210 MemoryContext old_cxt;
2215 bool nulls[1] = {false};
2217 /* skip over nested objects */
2218 if (_state->lex->lex_level != 1)
2221 /* use the tmp context so we can clean up after each tuple is done */
2222 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2224 if (isnull && _state->normalize_results)
2227 values[0] = (Datum) NULL;
2229 else if (_state->next_scalar)
2231 values[0] = CStringGetTextDatum(_state->normalized_scalar);
2232 _state->next_scalar = false;
2236 len = _state->lex->prev_token_terminator - _state->result_start;
2237 val = cstring_to_text_with_len(_state->result_start, len);
2238 values[0] = PointerGetDatum(val);
2241 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2243 tuplestore_puttuple(_state->tuple_store, tuple);
2245 /* clean up and switch back */
2246 MemoryContextSwitchTo(old_cxt);
2247 MemoryContextReset(_state->tmp_cxt);
2251 elements_object_start(void *state)
2253 ElementsState *_state = (ElementsState *) state;
2255 /* json structure check */
2256 if (_state->lex->lex_level == 0)
2258 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2259 errmsg("cannot call %s on a non-array",
2260 _state->function_name)));
2264 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2266 ElementsState *_state = (ElementsState *) state;
2268 /* json structure check */
2269 if (_state->lex->lex_level == 0)
2271 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2272 errmsg("cannot call %s on a scalar",
2273 _state->function_name)));
2275 /* supply de-escaped value if required */
2276 if (_state->next_scalar)
2277 _state->normalized_scalar = token;
2281 * SQL function json_populate_record
2283 * set fields in a record from the argument json
2285 * Code adapted shamelessly from hstore's populate_record
2286 * which is in turn partly adapted from record_out.
2288 * The json is decomposed into a hash table, in which each
2289 * field in the record is then looked up by name. For jsonb
2290 * we fetch the values direct from the object.
2293 jsonb_populate_record(PG_FUNCTION_ARGS)
2295 return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2299 jsonb_to_record(PG_FUNCTION_ARGS)
2301 return populate_record_worker(fcinfo, "jsonb_to_record", false);
2305 json_populate_record(PG_FUNCTION_ARGS)
2307 return populate_record_worker(fcinfo, "json_populate_record", true);
2311 json_to_record(PG_FUNCTION_ARGS)
2313 return populate_record_worker(fcinfo, "json_to_record", false);
2316 /* helper function for diagnostics */
2318 populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
2324 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2325 errmsg("expected json array"),
2326 errhint("See the value of key \"%s\".", ctx->colname)));
2329 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2330 errmsg("expected json array")));
2334 StringInfoData indices;
2337 initStringInfo(&indices);
2339 Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2341 for (i = 0; i < ndim; i++)
2342 appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2346 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2347 errmsg("expected json array"),
2348 errhint("See the array element %s of key \"%s\".",
2349 indices.data, ctx->colname)));
2352 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2353 errmsg("expected json array"),
2354 errhint("See the array element %s.",
2359 /* set the number of dimensions of the populated array when it becomes known */
2361 populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
2365 Assert(ctx->ndims <= 0);
2368 populate_array_report_expected_array(ctx, ndims);
2371 ctx->dims = palloc(sizeof(int) * ndims);
2372 ctx->sizes = palloc0(sizeof(int) * ndims);
2374 for (i = 0; i < ndims; i++)
2375 ctx->dims[i] = -1; /* dimensions are unknown yet */
2378 /* check the populated subarray dimension */
2380 populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
2382 int dim = ctx->sizes[ndim]; /* current dimension counter */
2384 if (ctx->dims[ndim] == -1)
2385 ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2386 else if (ctx->dims[ndim] != dim)
2388 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2389 errmsg("malformed json array"),
2390 errdetail("Multidimensional arrays must have "
2391 "sub-arrays with matching dimensions.")));
2393 /* reset the current array dimension size counter */
2394 ctx->sizes[ndim] = 0;
2396 /* increment the parent dimension counter if it is a nested sub-array */
2398 ctx->sizes[ndim - 1]++;
2402 populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
2405 bool element_isnull;
2407 /* populate the array element */
2408 element = populate_record_field(ctx->aio->element_info,
2409 ctx->aio->element_type,
2410 ctx->aio->element_typmod,
2411 NULL, ctx->mcxt, PointerGetDatum(NULL),
2412 jsv, &element_isnull);
2414 accumArrayResult(ctx->astate, element, element_isnull,
2415 ctx->aio->element_type, ctx->acxt);
2418 ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2421 /* json object start handler for populate_array_json() */
2423 populate_array_object_start(void *_state)
2425 PopulateArrayState *state = (PopulateArrayState *) _state;
2426 int ndim = state->lex->lex_level;
2428 if (state->ctx->ndims <= 0)
2429 populate_array_assign_ndims(state->ctx, ndim);
2430 else if (ndim < state->ctx->ndims)
2431 populate_array_report_expected_array(state->ctx, ndim);
2434 /* json array end handler for populate_array_json() */
2436 populate_array_array_end(void *_state)
2438 PopulateArrayState *state = (PopulateArrayState *) _state;
2439 PopulateArrayContext *ctx = state->ctx;
2440 int ndim = state->lex->lex_level;
2442 if (ctx->ndims <= 0)
2443 populate_array_assign_ndims(ctx, ndim + 1);
2445 if (ndim < ctx->ndims)
2446 populate_array_check_dimension(ctx, ndim);
2449 /* json array element start handler for populate_array_json() */
2451 populate_array_element_start(void *_state, bool isnull)
2453 PopulateArrayState *state = (PopulateArrayState *) _state;
2454 int ndim = state->lex->lex_level;
2456 if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2458 /* remember current array element start */
2459 state->element_start = state->lex->token_start;
2460 state->element_type = state->lex->token_type;
2461 state->element_scalar = NULL;
2465 /* json array element end handler for populate_array_json() */
2467 populate_array_element_end(void *_state, bool isnull)
2469 PopulateArrayState *state = (PopulateArrayState *) _state;
2470 PopulateArrayContext *ctx = state->ctx;
2471 int ndim = state->lex->lex_level;
2473 Assert(ctx->ndims > 0);
2475 if (ndim == ctx->ndims)
2480 jsv.val.json.type = state->element_type;
2484 Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2485 jsv.val.json.str = NULL;
2486 jsv.val.json.len = 0;
2488 else if (state->element_scalar)
2490 jsv.val.json.str = state->element_scalar;
2491 jsv.val.json.len = -1; /* null-terminated */
2495 jsv.val.json.str = state->element_start;
2496 jsv.val.json.len = (state->lex->prev_token_terminator -
2497 state->element_start) * sizeof(char);
2500 populate_array_element(ctx, ndim, &jsv);
2504 /* json scalar handler for populate_array_json() */
2506 populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
2508 PopulateArrayState *state = (PopulateArrayState *) _state;
2509 PopulateArrayContext *ctx = state->ctx;
2510 int ndim = state->lex->lex_level;
2512 if (ctx->ndims <= 0)
2513 populate_array_assign_ndims(ctx, ndim);
2514 else if (ndim < ctx->ndims)
2515 populate_array_report_expected_array(ctx, ndim);
2517 if (ndim == ctx->ndims)
2519 /* remember the scalar element token */
2520 state->element_scalar = token;
2521 /* element_type must already be set in populate_array_element_start() */
2522 Assert(state->element_type == tokentype);
2526 /* parse a json array and populate array */
2528 populate_array_json(PopulateArrayContext *ctx, char *json, int len)
2530 PopulateArrayState state;
2533 state.lex = makeJsonLexContextCstringLen(json, len, true);
2536 memset(&sem, 0, sizeof(sem));
2537 sem.semstate = (void *) &state;
2538 sem.object_start = populate_array_object_start;
2539 sem.array_end = populate_array_array_end;
2540 sem.array_element_start = populate_array_element_start;
2541 sem.array_element_end = populate_array_element_end;
2542 sem.scalar = populate_array_scalar;
2544 pg_parse_json(state.lex, &sem);
2546 /* number of dimensions should be already known */
2547 Assert(ctx->ndims > 0 && ctx->dims);
2553 * populate_array_dim_jsonb() -- Iterate recursively through jsonb sub-array
2554 * elements and accumulate result using given ArrayBuildState.
2557 populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
2558 JsonbValue *jbv, /* jsonb sub-array */
2559 int ndim) /* current dimension */
2561 JsonbContainer *jbc = jbv->val.binary.data;
2563 JsonbIteratorToken tok;
2567 check_stack_depth();
2569 if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
2570 populate_array_report_expected_array(ctx, ndim - 1);
2572 Assert(!JsonContainerIsScalar(jbc));
2574 it = JsonbIteratorInit(jbc);
2576 tok = JsonbIteratorNext(&it, &val, true);
2577 Assert(tok == WJB_BEGIN_ARRAY);
2579 tok = JsonbIteratorNext(&it, &val, true);
2582 * If the number of dimensions is not yet known and we have found end of
2583 * the array, or the first child element is not an array, then assign the
2584 * number of dimensions now.
2586 if (ctx->ndims <= 0 &&
2587 (tok == WJB_END_ARRAY ||
2589 (val.type != jbvBinary ||
2590 !JsonContainerIsArray(val.val.binary.data)))))
2591 populate_array_assign_ndims(ctx, ndim);
2593 jsv.is_json = false;
2594 jsv.val.jsonb = &val;
2596 /* process all the array elements */
2597 while (tok == WJB_ELEM)
2600 * Recurse only if the dimensions of dimensions is still unknown or if
2601 * it is not the innermost dimension.
2603 if (ctx->ndims > 0 && ndim >= ctx->ndims)
2604 populate_array_element(ctx, ndim, &jsv);
2607 /* populate child sub-array */
2608 populate_array_dim_jsonb(ctx, &val, ndim + 1);
2610 /* number of dimensions should be already known */
2611 Assert(ctx->ndims > 0 && ctx->dims);
2613 populate_array_check_dimension(ctx, ndim);
2616 tok = JsonbIteratorNext(&it, &val, true);
2619 Assert(tok == WJB_END_ARRAY);
2621 /* free iterator, iterating until WJB_DONE */
2622 tok = JsonbIteratorNext(&it, &val, true);
2623 Assert(tok == WJB_DONE && !it);
2626 /* recursively populate an array from json/jsonb */
2628 populate_array(ArrayIOData *aio,
2629 const char *colname,
2633 PopulateArrayContext ctx;
2640 ctx.acxt = CurrentMemoryContext;
2641 ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2642 ctx.colname = colname;
2643 ctx.ndims = 0; /* unknown yet */
2648 populate_array_json(&ctx, jsv->val.json.str,
2649 jsv->val.json.len >= 0 ? jsv->val.json.len
2650 : strlen(jsv->val.json.str));
2653 populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
2654 ctx.dims[0] = ctx.sizes[0];
2657 Assert(ctx.ndims > 0);
2659 lbs = palloc(sizeof(int) * ctx.ndims);
2661 for (i = 0; i < ctx.ndims; i++)
2664 result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2675 JsValueToJsObject(JsValue *jsv, JsObject *jso)
2677 jso->is_json = jsv->is_json;
2681 /* convert plain-text json into a hash table */
2682 jso->val.json_hash =
2683 get_json_object_as_hash(jsv->val.json.str,
2684 jsv->val.json.len >= 0
2686 : strlen(jsv->val.json.str),
2687 "populate_composite");
2691 JsonbValue *jbv = jsv->val.jsonb;
2693 if (jbv->type == jbvBinary &&
2694 JsonContainerIsObject(jbv->val.binary.data))
2696 jso->val.jsonb_cont = jbv->val.binary.data;
2702 is_scalar = IsAJsonbScalar(jbv) ||
2703 (jbv->type == jbvBinary &&
2704 JsonContainerIsScalar(jbv->val.binary.data));
2706 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2708 ? errmsg("cannot call %s on a scalar",
2709 "populate_composite")
2710 : errmsg("cannot call %s on an array",
2711 "populate_composite")));
2716 /* acquire or update cached tuple descriptor for a composite type */
2718 update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
2721 io->tupdesc->tdtypeid != io->base_typid ||
2722 io->tupdesc->tdtypmod != io->base_typmod)
2724 TupleDesc tupdesc = lookup_rowtype_tupdesc(io->base_typid,
2726 MemoryContext oldcxt;
2729 FreeTupleDesc(io->tupdesc);
2731 /* copy tuple desc without constraints into cache memory context */
2732 oldcxt = MemoryContextSwitchTo(mcxt);
2733 io->tupdesc = CreateTupleDescCopy(tupdesc);
2734 MemoryContextSwitchTo(oldcxt);
2736 ReleaseTupleDesc(tupdesc);
2740 /* recursively populate a composite (row type) value from json/jsonb */
2742 populate_composite(CompositeIOData *io,
2744 const char *colname,
2746 HeapTupleHeader defaultval,
2752 /* acquire/update cached tuple descriptor */
2753 update_cached_tupdesc(io, mcxt);
2759 HeapTupleHeader tuple;
2762 /* prepare input value */
2763 JsValueToJsObject(jsv, &jso);
2765 /* populate resulting record tuple */
2766 tuple = populate_record(io->tupdesc, &io->record_io,
2767 defaultval, mcxt, &jso);
2768 result = HeapTupleHeaderGetDatum(tuple);
2774 * If it's domain over composite, check domain constraints. (This should
2775 * probably get refactored so that we can see the TYPECAT value, but for
2776 * now, we can tell by comparing typid to base_typid.)
2778 if (typid != io->base_typid && typid != RECORDOID)
2779 domain_check(result, isnull, typid, &io->domain_info, mcxt);
2784 /* populate non-null scalar value from json/jsonb value */
2786 populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
2794 int len = jsv->val.json.len;
2796 json = jsv->val.json.str;
2799 /* already done the hard work in the json case */
2800 if ((typid == JSONOID || typid == JSONBOID) &&
2801 jsv->val.json.type == JSON_TOKEN_STRING)
2804 * Add quotes around string value (should be already escaped) if
2805 * converting to json/jsonb.
2811 str = palloc(len + sizeof(char) * 3);
2813 memcpy(&str[1], json, len);
2815 str[len + 2] = '\0';
2819 /* Need to copy non-null-terminated string */
2820 str = palloc(len + 1 * sizeof(char));
2821 memcpy(str, json, len);
2825 str = json; /* null-terminated string */
2829 JsonbValue *jbv = jsv->val.jsonb;
2831 if (typid == JSONBOID)
2833 Jsonb *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
2835 return JsonbPGetDatum(jsonb);
2837 /* convert jsonb to string for typio call */
2838 else if (typid == JSONOID && jbv->type != jbvBinary)
2841 * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
2842 * to json string, preserving quotes around top-level strings.
2844 Jsonb *jsonb = JsonbValueToJsonb(jbv);
2846 str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
2848 else if (jbv->type == jbvString) /* quotes are stripped */
2849 str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
2850 else if (jbv->type == jbvBool)
2851 str = pstrdup(jbv->val.boolean ? "true" : "false");
2852 else if (jbv->type == jbvNumeric)
2853 str = DatumGetCString(DirectFunctionCall1(numeric_out,
2854 PointerGetDatum(jbv->val.numeric)));
2855 else if (jbv->type == jbvBinary)
2856 str = JsonbToCString(NULL, jbv->val.binary.data,
2857 jbv->val.binary.len);
2859 elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
2862 res = InputFunctionCall(&io->typiofunc, str, io->typioparam, typmod);
2864 /* free temporary buffer */
2872 populate_domain(DomainIOData *io,
2874 const char *colname,
2885 res = populate_record_field(io->base_io,
2886 io->base_typid, io->base_typmod,
2887 colname, mcxt, PointerGetDatum(NULL),
2892 domain_check(res, isnull, typid, &io->domain_info, mcxt);
2897 /* prepare column metadata cache for the given type */
2899 prepare_column_cache(ColumnIOData *column,
2908 column->typid = typid;
2909 column->typmod = typmod;
2911 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2912 if (!HeapTupleIsValid(tup))
2913 elog(ERROR, "cache lookup failed for type %u", typid);
2915 type = (Form_pg_type) GETSTRUCT(tup);
2917 if (type->typtype == TYPTYPE_DOMAIN)
2920 * We can move directly to the bottom base type; domain_check() will
2921 * take care of checking all constraints for a stack of domains.
2924 int32 base_typmod = typmod;
2926 base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
2927 if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
2929 /* domain over composite has its own code path */
2930 column->typcat = TYPECAT_COMPOSITE_DOMAIN;
2931 column->io.composite.record_io = NULL;
2932 column->io.composite.tupdesc = NULL;
2933 column->io.composite.base_typid = base_typid;
2934 column->io.composite.base_typmod = base_typmod;
2935 column->io.composite.domain_info = NULL;
2939 /* domain over anything else */
2940 column->typcat = TYPECAT_DOMAIN;
2941 column->io.domain.base_typid = base_typid;
2942 column->io.domain.base_typmod = base_typmod;
2943 column->io.domain.base_io =
2944 MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
2945 column->io.domain.domain_info = NULL;
2948 else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
2950 column->typcat = TYPECAT_COMPOSITE;
2951 column->io.composite.record_io = NULL;
2952 column->io.composite.tupdesc = NULL;
2953 column->io.composite.base_typid = typid;
2954 column->io.composite.base_typmod = typmod;
2955 column->io.composite.domain_info = NULL;
2957 else if (type->typlen == -1 && OidIsValid(type->typelem))
2959 column->typcat = TYPECAT_ARRAY;
2960 column->io.array.element_info = MemoryContextAllocZero(mcxt,
2961 sizeof(ColumnIOData));
2962 column->io.array.element_type = type->typelem;
2963 /* array element typemod stored in attribute's typmod */
2964 column->io.array.element_typmod = typmod;
2968 column->typcat = TYPECAT_SCALAR;
2972 /* caller can force us to look up scalar_io info even for non-scalars */
2977 getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
2978 fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
2981 ReleaseSysCache(tup);
2984 /* recursively populate a record field or an array element from a json/jsonb value */
2986 populate_record_field(ColumnIOData *col,
2989 const char *colname,
2997 check_stack_depth();
3000 * Prepare column metadata cache for the given type. Force lookup of the
3001 * scalar_io data so that the json string hack below will work.
3003 if (col->typid != typid || col->typmod != typmod)
3004 prepare_column_cache(col, typid, typmod, mcxt, true);
3006 *isnull = JsValueIsNull(jsv);
3008 typcat = col->typcat;
3010 /* try to convert json string to a non-scalar type through input function */
3011 if (JsValueIsString(jsv) &&
3012 (typcat == TYPECAT_ARRAY ||
3013 typcat == TYPECAT_COMPOSITE ||
3014 typcat == TYPECAT_COMPOSITE_DOMAIN))
3015 typcat = TYPECAT_SCALAR;
3017 /* we must perform domain checks for NULLs, otherwise exit immediately */
3019 typcat != TYPECAT_DOMAIN &&
3020 typcat != TYPECAT_COMPOSITE_DOMAIN)
3025 case TYPECAT_SCALAR:
3026 return populate_scalar(&col->scalar_io, typid, typmod, jsv);
3029 return populate_array(&col->io.array, colname, mcxt, jsv);
3031 case TYPECAT_COMPOSITE:
3032 case TYPECAT_COMPOSITE_DOMAIN:
3033 return populate_composite(&col->io.composite, typid,
3035 DatumGetPointer(defaultval)
3036 ? DatumGetHeapTupleHeader(defaultval)
3040 case TYPECAT_DOMAIN:
3041 return populate_domain(&col->io.domain, typid, colname, mcxt,
3045 elog(ERROR, "unrecognized type category '%c'", typcat);
3050 static RecordIOData *
3051 allocate_record_info(MemoryContext mcxt, int ncolumns)
3053 RecordIOData *data = (RecordIOData *)
3054 MemoryContextAlloc(mcxt,
3055 offsetof(RecordIOData, columns) +
3056 ncolumns * sizeof(ColumnIOData));
3058 data->record_type = InvalidOid;
3059 data->record_typmod = 0;
3060 data->ncolumns = ncolumns;
3061 MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3067 JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
3069 jsv->is_json = obj->is_json;
3073 JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3076 jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3077 jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3079 jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3081 return hashentry != NULL;
3085 jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3086 findJsonbValueFromContainerLen(obj->val.jsonb_cont, JB_FOBJECT,
3087 field, strlen(field));
3089 return jsv->val.jsonb != NULL;
3093 /* populate a record tuple from json/jsonb value */
3094 static HeapTupleHeader
3095 populate_record(TupleDesc tupdesc,
3096 RecordIOData **record_p,
3097 HeapTupleHeader defaultval,
3101 RecordIOData *record = *record_p;
3105 int ncolumns = tupdesc->natts;
3109 * if the input json is empty, we can only skip the rest if we were passed
3110 * in a non-null record, since otherwise there may be issues with domain
3113 if (defaultval && JsObjectIsEmpty(obj))
3116 /* (re)allocate metadata cache */
3117 if (record == NULL ||
3118 record->ncolumns != ncolumns)
3119 *record_p = record = allocate_record_info(mcxt, ncolumns);
3121 /* invalidate metadata cache if the record type has changed */
3122 if (record->record_type != tupdesc->tdtypeid ||
3123 record->record_typmod != tupdesc->tdtypmod)
3125 MemSet(record, 0, offsetof(RecordIOData, columns) +
3126 ncolumns * sizeof(ColumnIOData));
3127 record->record_type = tupdesc->tdtypeid;
3128 record->record_typmod = tupdesc->tdtypmod;
3129 record->ncolumns = ncolumns;
3132 values = (Datum *) palloc(ncolumns * sizeof(Datum));
3133 nulls = (bool *) palloc(ncolumns * sizeof(bool));
3137 HeapTupleData tuple;
3139 /* Build a temporary HeapTuple control structure */
3140 tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
3141 ItemPointerSetInvalid(&(tuple.t_self));
3142 tuple.t_tableOid = InvalidOid;
3143 tuple.t_data = defaultval;
3145 /* Break down the tuple into fields */
3146 heap_deform_tuple(&tuple, tupdesc, values, nulls);
3150 for (i = 0; i < ncolumns; ++i)
3152 values[i] = (Datum) 0;
3157 for (i = 0; i < ncolumns; ++i)
3159 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
3160 char *colname = NameStr(att->attname);
3161 JsValue field = {0};
3164 /* Ignore dropped columns in datatype */
3165 if (att->attisdropped)
3171 found = JsObjectGetField(obj, colname, &field);
3174 * we can't just skip here if the key wasn't found since we might have
3175 * a domain to deal with. If we were passed in a non-null record
3176 * datum, we assume that the existing values are valid (if they're
3177 * not, then it's not our fault), but if we were passed in a null,
3178 * then every field which we don't populate needs to be run through
3179 * the input function just in case it's a domain type.
3181 if (defaultval && !found)
3184 values[i] = populate_record_field(&record->columns[i],
3189 nulls[i] ? (Datum) 0 : values[i],
3194 res = heap_form_tuple(tupdesc, values, nulls);
3203 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
3204 bool have_record_arg)
3206 int json_arg_num = have_record_arg ? 1 : 0;
3207 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
3209 HeapTupleHeader rec;
3212 MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
3213 PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3215 Assert(jtype == JSONOID || jtype == JSONBOID);
3218 * If first time through, identify input/result record type. Note that
3219 * this stanza looks only at fcinfo context, which can't change during the
3220 * query; so we may not be able to fully resolve a RECORD input type yet.
3224 fcinfo->flinfo->fn_extra = cache =
3225 MemoryContextAllocZero(fnmcxt, sizeof(*cache));
3227 if (have_record_arg)
3230 * json{b}_populate_record case: result type will be same as first
3233 cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3234 prepare_column_cache(&cache->c,
3237 if (cache->c.typcat != TYPECAT_COMPOSITE &&
3238 cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3240 (errcode(ERRCODE_DATATYPE_MISMATCH),
3241 errmsg("first argument of %s must be a row type",
3247 * json{b}_to_record case: result type is specified by calling
3248 * query. Here it is syntactically impossible to specify the
3249 * target type as domain-over-composite.
3252 MemoryContext old_cxt;
3254 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3256 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3257 errmsg("function returning record called in context "
3258 "that cannot accept type record"),
3259 errhint("Try calling the function in the FROM clause "
3260 "using a column definition list.")));
3263 cache->argtype = tupdesc->tdtypeid;
3265 /* Save identified tupdesc */
3266 old_cxt = MemoryContextSwitchTo(fnmcxt);
3267 cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3268 cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3269 cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3270 MemoryContextSwitchTo(old_cxt);
3274 /* Collect record arg if we have one */
3275 if (have_record_arg && !PG_ARGISNULL(0))
3277 rec = PG_GETARG_HEAPTUPLEHEADER(0);
3280 * When declared arg type is RECORD, identify actual record type from
3281 * the tuple itself. Note the lookup_rowtype_tupdesc call in
3282 * update_cached_tupdesc will fail if we're unable to do this.
3284 if (cache->argtype == RECORDOID)
3286 cache->c.io.composite.base_typid = HeapTupleHeaderGetTypeId(rec);
3287 cache->c.io.composite.base_typmod = HeapTupleHeaderGetTypMod(rec);
3293 /* If no JSON argument, just return the record (if any) unchanged */
3294 if (PG_ARGISNULL(json_arg_num))
3297 PG_RETURN_POINTER(rec);
3302 jsv.is_json = jtype == JSONOID;
3306 text *json = PG_GETARG_TEXT_PP(json_arg_num);
3308 jsv.val.json.str = VARDATA_ANY(json);
3309 jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3310 jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3311 * populate_composite() */
3315 Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3317 jsv.val.jsonb = &jbv;
3319 /* fill binary jsonb value pointing to jb */
3320 jbv.type = jbvBinary;
3321 jbv.val.binary.data = &jb->root;
3322 jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
3325 rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
3326 NULL, fnmcxt, rec, &jsv, false);
3328 PG_RETURN_DATUM(rettuple);
3332 * get_json_object_as_hash
3334 * decompose a json object into a hash table.
3337 get_json_object_as_hash(char *json, int len, const char *funcname)
3342 JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3345 memset(&ctl, 0, sizeof(ctl));
3346 ctl.keysize = NAMEDATALEN;
3347 ctl.entrysize = sizeof(JsonHashEntry);
3348 ctl.hcxt = CurrentMemoryContext;
3349 tab = hash_create("json object hashtable",
3352 HASH_ELEM | HASH_CONTEXT);
3354 state = palloc0(sizeof(JHashState));
3355 sem = palloc0(sizeof(JsonSemAction));
3357 state->function_name = funcname;
3361 sem->semstate = (void *) state;
3362 sem->array_start = hash_array_start;
3363 sem->scalar = hash_scalar;
3364 sem->object_field_start = hash_object_field_start;
3365 sem->object_field_end = hash_object_field_end;
3367 pg_parse_json(lex, sem);
3373 hash_object_field_start(void *state, char *fname, bool isnull)
3375 JHashState *_state = (JHashState *) state;
3377 if (_state->lex->lex_level > 1)
3380 /* remember token type */
3381 _state->saved_token_type = _state->lex->token_type;
3383 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3384 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
3386 /* remember start position of the whole text of the subobject */
3387 _state->save_json_start = _state->lex->token_start;
3391 /* must be a scalar */
3392 _state->save_json_start = NULL;
3397 hash_object_field_end(void *state, char *fname, bool isnull)
3399 JHashState *_state = (JHashState *) state;
3400 JsonHashEntry *hashentry;
3404 * Ignore nested fields.
3406 if (_state->lex->lex_level > 1)
3410 * Ignore field names >= NAMEDATALEN - they can't match a record field.
3411 * (Note: without this test, the hash code would truncate the string at
3412 * NAMEDATALEN-1, and could then match against a similarly-truncated
3413 * record field name. That would be a reasonable behavior, but this code
3414 * has previously insisted on exact equality, so we keep this behavior.)
3416 if (strlen(fname) >= NAMEDATALEN)
3419 hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3422 * found being true indicates a duplicate. We don't do anything about
3423 * that, a later field with the same name overrides the earlier field.
3426 hashentry->type = _state->saved_token_type;
3427 Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3429 if (_state->save_json_start != NULL)
3431 int len = _state->lex->prev_token_terminator - _state->save_json_start;
3432 char *val = palloc((len + 1) * sizeof(char));
3434 memcpy(val, _state->save_json_start, len);
3436 hashentry->val = val;
3440 /* must have had a scalar instead */
3441 hashentry->val = _state->saved_scalar;
3446 hash_array_start(void *state)
3448 JHashState *_state = (JHashState *) state;
3450 if (_state->lex->lex_level == 0)
3452 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3453 errmsg("cannot call %s on an array", _state->function_name)));
3457 hash_scalar(void *state, char *token, JsonTokenType tokentype)
3459 JHashState *_state = (JHashState *) state;
3461 if (_state->lex->lex_level == 0)
3463 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3464 errmsg("cannot call %s on a scalar", _state->function_name)));
3466 if (_state->lex->lex_level == 1)
3468 _state->saved_scalar = token;
3469 /* saved_token_type must already be set in hash_object_field_start() */
3470 Assert(_state->saved_token_type == tokentype);
3476 * SQL function json_populate_recordset
3478 * set fields in a set of records from the argument json,
3479 * which must be an array of objects.
3481 * similar to json_populate_record, but the tuple-building code
3482 * is pushed down into the semantic action handlers so it's done
3483 * per object in the array.
3486 jsonb_populate_recordset(PG_FUNCTION_ARGS)
3488 return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
3492 jsonb_to_recordset(PG_FUNCTION_ARGS)
3494 return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
3498 json_populate_recordset(PG_FUNCTION_ARGS)
3500 return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
3504 json_to_recordset(PG_FUNCTION_ARGS)
3506 return populate_recordset_worker(fcinfo, "json_to_recordset", false);
3510 populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
3512 PopulateRecordsetCache *cache = state->cache;
3513 HeapTupleHeader tuphead;
3514 HeapTupleData tuple;
3516 /* acquire/update cached tuple descriptor */
3517 update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
3519 /* replace record fields from json */
3520 tuphead = populate_record(cache->c.io.composite.tupdesc,
3521 &cache->c.io.composite.record_io,
3526 /* if it's domain over composite, check domain constraints */
3527 if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
3528 domain_check(HeapTupleHeaderGetDatum(tuphead), false,
3530 &cache->c.io.composite.domain_info,
3533 /* ok, save into tuplestore */
3534 tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
3535 ItemPointerSetInvalid(&(tuple.t_self));
3536 tuple.t_tableOid = InvalidOid;
3537 tuple.t_data = tuphead;
3539 tuplestore_puttuple(state->tuple_store, &tuple);
3543 * common worker for json_populate_recordset() and json_to_recordset()
3546 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
3547 bool have_record_arg)
3549 int json_arg_num = have_record_arg ? 1 : 0;
3550 Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
3552 MemoryContext old_cxt;
3553 HeapTupleHeader rec;
3554 PopulateRecordsetCache *cache = fcinfo->flinfo->fn_extra;
3555 PopulateRecordsetState *state;
3557 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
3559 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
3560 (rsi->allowedModes & SFRM_Materialize) == 0)
3562 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3563 errmsg("set-valued function called in context that "
3564 "cannot accept a set")));
3566 rsi->returnMode = SFRM_Materialize;
3569 * If first time through, identify input/result record type. Note that
3570 * this stanza looks only at fcinfo context, which can't change during the
3571 * query; so we may not be able to fully resolve a RECORD input type yet.
3575 fcinfo->flinfo->fn_extra = cache =
3576 MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
3577 cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
3579 if (have_record_arg)
3582 * json{b}_populate_recordset case: result type will be same as
3585 cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3586 prepare_column_cache(&cache->c,
3588 cache->fn_mcxt, false);
3589 if (cache->c.typcat != TYPECAT_COMPOSITE &&
3590 cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3592 (errcode(ERRCODE_DATATYPE_MISMATCH),
3593 errmsg("first argument of %s must be a row type",
3599 * json{b}_to_recordset case: result type is specified by calling
3600 * query. Here it is syntactically impossible to specify the
3601 * target type as domain-over-composite.
3605 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3607 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3608 errmsg("function returning record called in context "
3609 "that cannot accept type record"),
3610 errhint("Try calling the function in the FROM clause "
3611 "using a column definition list.")));
3614 cache->argtype = tupdesc->tdtypeid;
3616 /* Save identified tupdesc */
3617 old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3618 cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3619 cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3620 cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3621 MemoryContextSwitchTo(old_cxt);
3625 /* Collect record arg if we have one */
3626 if (have_record_arg && !PG_ARGISNULL(0))
3628 rec = PG_GETARG_HEAPTUPLEHEADER(0);
3631 * When declared arg type is RECORD, identify actual record type from
3632 * the tuple itself. Note the lookup_rowtype_tupdesc call in
3633 * update_cached_tupdesc will fail if we're unable to do this.
3635 if (cache->argtype == RECORDOID)
3637 cache->c.io.composite.base_typid = HeapTupleHeaderGetTypeId(rec);
3638 cache->c.io.composite.base_typmod = HeapTupleHeaderGetTypMod(rec);
3644 /* if the json is null send back an empty set */
3645 if (PG_ARGISNULL(json_arg_num))
3648 state = palloc0(sizeof(PopulateRecordsetState));
3650 /* make tuplestore in a sufficiently long-lived memory context */
3651 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
3652 state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
3653 SFRM_Materialize_Random,
3655 MemoryContextSwitchTo(old_cxt);
3657 state->function_name = funcname;
3658 state->cache = cache;
3661 if (jtype == JSONOID)
3663 text *json = PG_GETARG_TEXT_PP(json_arg_num);
3664 JsonLexContext *lex;
3667 sem = palloc0(sizeof(JsonSemAction));
3669 lex = makeJsonLexContext(json, true);
3671 sem->semstate = (void *) state;
3672 sem->array_start = populate_recordset_array_start;
3673 sem->array_element_start = populate_recordset_array_element_start;
3674 sem->scalar = populate_recordset_scalar;
3675 sem->object_field_start = populate_recordset_object_field_start;
3676 sem->object_field_end = populate_recordset_object_field_end;
3677 sem->object_start = populate_recordset_object_start;
3678 sem->object_end = populate_recordset_object_end;
3682 pg_parse_json(lex, sem);
3686 Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3689 bool skipNested = false;
3690 JsonbIteratorToken r;
3692 Assert(jtype == JSONBOID);
3694 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
3696 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3697 errmsg("cannot call %s on a non-array",
3700 it = JsonbIteratorInit(&jb->root);
3702 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
3710 if (v.type != jbvBinary ||
3711 !JsonContainerIsObject(v.val.binary.data))
3713 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3714 errmsg("argument of %s must be an array of objects",
3717 obj.is_json = false;
3718 obj.val.jsonb_cont = v.val.binary.data;
3720 populate_recordset_record(state, &obj);
3725 rsi->setResult = state->tuple_store;
3726 rsi->setDesc = cache->c.io.composite.tupdesc;
3732 populate_recordset_object_start(void *state)
3734 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3735 int lex_level = _state->lex->lex_level;
3738 /* Reject object at top level: we must have an array at level 0 */
3741 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3742 errmsg("cannot call %s on an object",
3743 _state->function_name)));
3745 /* Nested objects require no special processing */
3749 /* Object at level 1: set up a new hash table for this object */
3750 memset(&ctl, 0, sizeof(ctl));
3751 ctl.keysize = NAMEDATALEN;
3752 ctl.entrysize = sizeof(JsonHashEntry);
3753 ctl.hcxt = CurrentMemoryContext;
3754 _state->json_hash = hash_create("json object hashtable",
3757 HASH_ELEM | HASH_CONTEXT);
3761 populate_recordset_object_end(void *state)
3763 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3766 /* Nested objects require no special processing */
3767 if (_state->lex->lex_level > 1)
3771 obj.val.json_hash = _state->json_hash;
3773 /* Otherwise, construct and return a tuple based on this level-1 object */
3774 populate_recordset_record(_state, &obj);
3776 /* Done with hash for this object */
3777 hash_destroy(_state->json_hash);
3778 _state->json_hash = NULL;
3782 populate_recordset_array_element_start(void *state, bool isnull)
3784 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3786 if (_state->lex->lex_level == 1 &&
3787 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
3789 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3790 errmsg("argument of %s must be an array of objects",
3791 _state->function_name)));
3795 populate_recordset_array_start(void *state)
3801 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
3803 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3805 if (_state->lex->lex_level == 0)
3807 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3808 errmsg("cannot call %s on a scalar",
3809 _state->function_name)));
3811 if (_state->lex->lex_level == 2)
3812 _state->saved_scalar = token;
3816 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
3818 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3820 if (_state->lex->lex_level > 2)
3823 _state->saved_token_type = _state->lex->token_type;
3825 if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3826 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
3828 _state->save_json_start = _state->lex->token_start;
3832 _state->save_json_start = NULL;
3837 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
3839 PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3840 JsonHashEntry *hashentry;
3844 * Ignore nested fields.
3846 if (_state->lex->lex_level > 2)
3850 * Ignore field names >= NAMEDATALEN - they can't match a record field.
3851 * (Note: without this test, the hash code would truncate the string at
3852 * NAMEDATALEN-1, and could then match against a similarly-truncated
3853 * record field name. That would be a reasonable behavior, but this code
3854 * has previously insisted on exact equality, so we keep this behavior.)
3856 if (strlen(fname) >= NAMEDATALEN)
3859 hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
3862 * found being true indicates a duplicate. We don't do anything about
3863 * that, a later field with the same name overrides the earlier field.
3866 hashentry->type = _state->saved_token_type;
3867 Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3869 if (_state->save_json_start != NULL)
3871 int len = _state->lex->prev_token_terminator - _state->save_json_start;
3872 char *val = palloc((len + 1) * sizeof(char));
3874 memcpy(val, _state->save_json_start, len);
3876 hashentry->val = val;
3880 /* must have had a scalar instead */
3881 hashentry->val = _state->saved_scalar;
3886 * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3889 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
3890 char *key, uint32 keylen)
3895 k.val.string.val = key;
3896 k.val.string.len = keylen;
3898 return findJsonbValueFromContainer(container, flags, &k);
3902 * Semantic actions for json_strip_nulls.
3904 * Simply repeat the input on the output unless we encounter
3905 * a null object field. State for this is set when the field
3906 * is started and reset when the scalar action (which must be next)
3911 sn_object_start(void *state)
3913 StripnullState *_state = (StripnullState *) state;
3915 appendStringInfoCharMacro(_state->strval, '{');
3919 sn_object_end(void *state)
3921 StripnullState *_state = (StripnullState *) state;
3923 appendStringInfoCharMacro(_state->strval, '}');
3927 sn_array_start(void *state)
3929 StripnullState *_state = (StripnullState *) state;
3931 appendStringInfoCharMacro(_state->strval, '[');
3935 sn_array_end(void *state)
3937 StripnullState *_state = (StripnullState *) state;
3939 appendStringInfoCharMacro(_state->strval, ']');
3943 sn_object_field_start(void *state, char *fname, bool isnull)
3945 StripnullState *_state = (StripnullState *) state;
3950 * The next thing must be a scalar or isnull couldn't be true, so
3951 * there is no danger of this state being carried down into a nested
3952 * object or array. The flag will be reset in the scalar action.
3954 _state->skip_next_null = true;
3958 if (_state->strval->data[_state->strval->len - 1] != '{')
3959 appendStringInfoCharMacro(_state->strval, ',');
3962 * Unfortunately we don't have the quoted and escaped string any more, so
3963 * we have to re-escape it.
3965 escape_json(_state->strval, fname);
3967 appendStringInfoCharMacro(_state->strval, ':');
3971 sn_array_element_start(void *state, bool isnull)
3973 StripnullState *_state = (StripnullState *) state;
3975 if (_state->strval->data[_state->strval->len - 1] != '[')
3976 appendStringInfoCharMacro(_state->strval, ',');
3980 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3982 StripnullState *_state = (StripnullState *) state;
3984 if (_state->skip_next_null)
3986 Assert(tokentype == JSON_TOKEN_NULL);
3987 _state->skip_next_null = false;
3991 if (tokentype == JSON_TOKEN_STRING)
3992 escape_json(_state->strval, token);
3994 appendStringInfoString(_state->strval, token);
3998 * SQL function json_strip_nulls(json) -> json
4001 json_strip_nulls(PG_FUNCTION_ARGS)
4003 text *json = PG_GETARG_TEXT_PP(0);
4004 StripnullState *state;
4005 JsonLexContext *lex;
4008 lex = makeJsonLexContext(json, true);
4009 state = palloc0(sizeof(StripnullState));
4010 sem = palloc0(sizeof(JsonSemAction));
4012 state->strval = makeStringInfo();
4013 state->skip_next_null = false;
4016 sem->semstate = (void *) state;
4017 sem->object_start = sn_object_start;
4018 sem->object_end = sn_object_end;
4019 sem->array_start = sn_array_start;
4020 sem->array_end = sn_array_end;
4021 sem->scalar = sn_scalar;
4022 sem->array_element_start = sn_array_element_start;
4023 sem->object_field_start = sn_object_field_start;
4025 pg_parse_json(lex, sem);
4027 PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
4028 state->strval->len));
4033 * SQL function jsonb_strip_nulls(jsonb) -> jsonb
4036 jsonb_strip_nulls(PG_FUNCTION_ARGS)
4038 Jsonb *jb = PG_GETARG_JSONB_P(0);
4040 JsonbParseState *parseState = NULL;
4041 JsonbValue *res = NULL;
4044 JsonbIteratorToken type;
4045 bool last_was_key = false;
4047 if (JB_ROOT_IS_SCALAR(jb))
4048 PG_RETURN_POINTER(jb);
4050 it = JsonbIteratorInit(&jb->root);
4052 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4054 Assert(!(type == WJB_KEY && last_was_key));
4056 if (type == WJB_KEY)
4058 /* stash the key until we know if it has a null value */
4060 last_was_key = true;
4066 /* if the last element was a key this one can't be */
4067 last_was_key = false;
4069 /* skip this field if value is null */
4070 if (type == WJB_VALUE && v.type == jbvNull)
4073 /* otherwise, do a delayed push of the key */
4074 (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4077 if (type == WJB_VALUE || type == WJB_ELEM)
4078 res = pushJsonbValue(&parseState, type, &v);
4080 res = pushJsonbValue(&parseState, type, NULL);
4083 Assert(res != NULL);
4085 PG_RETURN_POINTER(JsonbValueToJsonb(res));
4089 * Add values from the jsonb to the parse state.
4091 * If the parse state container is an object, the jsonb is pushed as
4092 * a value, not a key.
4094 * This needs to be done using an iterator because pushJsonbValue doesn't
4095 * like getting jbvBinary values, so we can't just push jb as a whole.
4098 addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
4101 JsonbValue *o = &(*jbps)->contVal;
4103 JsonbIteratorToken type;
4105 it = JsonbIteratorInit(&jb->root);
4107 Assert(o->type == jbvArray || o->type == jbvObject);
4109 if (JB_ROOT_IS_SCALAR(jb))
4111 (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4112 (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4117 (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4120 (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4123 elog(ERROR, "unexpected parent of nested structure");
4128 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4130 if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4131 (void) pushJsonbValue(jbps, type, &v);
4133 (void) pushJsonbValue(jbps, type, NULL);
4140 * SQL function jsonb_pretty (jsonb)
4142 * Pretty-printed text for the jsonb
4145 jsonb_pretty(PG_FUNCTION_ARGS)
4147 Jsonb *jb = PG_GETARG_JSONB_P(0);
4148 StringInfo str = makeStringInfo();
4150 JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4152 PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
4156 * SQL function jsonb_concat (jsonb, jsonb)
4158 * function for || operator
4161 jsonb_concat(PG_FUNCTION_ARGS)
4163 Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4164 Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4165 JsonbParseState *state = NULL;
4171 * If one of the jsonb is empty, just return the other if it's not scalar
4172 * and both are of the same kind. If it's a scalar or they are of
4173 * different kinds we need to perform the concatenation even if one is
4176 if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4178 if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4179 PG_RETURN_JSONB_P(jb2);
4180 else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4181 PG_RETURN_JSONB_P(jb1);
4184 it1 = JsonbIteratorInit(&jb1->root);
4185 it2 = JsonbIteratorInit(&jb2->root);
4187 res = IteratorConcat(&it1, &it2, &state);
4189 Assert(res != NULL);
4191 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4196 * SQL function jsonb_delete (jsonb, text)
4198 * return a copy of the jsonb with the indicated item
4202 jsonb_delete(PG_FUNCTION_ARGS)
4204 Jsonb *in = PG_GETARG_JSONB_P(0);
4205 text *key = PG_GETARG_TEXT_PP(1);
4206 char *keyptr = VARDATA_ANY(key);
4207 int keylen = VARSIZE_ANY_EXHDR(key);
4208 JsonbParseState *state = NULL;
4212 bool skipNested = false;
4213 JsonbIteratorToken r;
4215 if (JB_ROOT_IS_SCALAR(in))
4217 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4218 errmsg("cannot delete from scalar")));
4220 if (JB_ROOT_COUNT(in) == 0)
4221 PG_RETURN_JSONB_P(in);
4223 it = JsonbIteratorInit(&in->root);
4225 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4229 if ((r == WJB_ELEM || r == WJB_KEY) &&
4230 (v.type == jbvString && keylen == v.val.string.len &&
4231 memcmp(keyptr, v.val.string.val, keylen) == 0))
4233 /* skip corresponding value as well */
4235 JsonbIteratorNext(&it, &v, true);
4240 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4243 Assert(res != NULL);
4245 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4249 * SQL function jsonb_delete (jsonb, variadic text[])
4251 * return a copy of the jsonb with the indicated items
4255 jsonb_delete_array(PG_FUNCTION_ARGS)
4257 Jsonb *in = PG_GETARG_JSONB_P(0);
4258 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4262 JsonbParseState *state = NULL;
4266 bool skipNested = false;
4267 JsonbIteratorToken r;
4269 if (ARR_NDIM(keys) > 1)
4271 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4272 errmsg("wrong number of array subscripts")));
4274 if (JB_ROOT_IS_SCALAR(in))
4276 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4277 errmsg("cannot delete from scalar")));
4279 if (JB_ROOT_COUNT(in) == 0)
4280 PG_RETURN_JSONB_P(in);
4282 deconstruct_array(keys, TEXTOID, -1, false, 'i',
4283 &keys_elems, &keys_nulls, &keys_len);
4286 PG_RETURN_JSONB_P(in);
4288 it = JsonbIteratorInit(&in->root);
4290 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4294 if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4299 for (i = 0; i < keys_len; i++)
4307 keyptr = VARDATA_ANY(keys_elems[i]);
4308 keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4309 if (keylen == v.val.string.len &&
4310 memcmp(keyptr, v.val.string.val, keylen) == 0)
4318 /* skip corresponding value as well */
4320 JsonbIteratorNext(&it, &v, true);
4326 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4329 Assert(res != NULL);
4331 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4335 * SQL function jsonb_delete (jsonb, int)
4337 * return a copy of the jsonb with the indicated item
4338 * removed. Negative int means count back from the
4342 jsonb_delete_idx(PG_FUNCTION_ARGS)
4344 Jsonb *in = PG_GETARG_JSONB_P(0);
4345 int idx = PG_GETARG_INT32(1);
4346 JsonbParseState *state = NULL;
4352 JsonbIteratorToken r;
4354 if (JB_ROOT_IS_SCALAR(in))
4356 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4357 errmsg("cannot delete from scalar")));
4359 if (JB_ROOT_IS_OBJECT(in))
4361 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4362 errmsg("cannot delete from object using integer index")));
4364 if (JB_ROOT_COUNT(in) == 0)
4365 PG_RETURN_JSONB_P(in);
4367 it = JsonbIteratorInit(&in->root);
4369 r = JsonbIteratorNext(&it, &v, false);
4370 Assert(r == WJB_BEGIN_ARRAY);
4371 n = v.val.array.nElems;
4382 PG_RETURN_JSONB_P(in);
4384 pushJsonbValue(&state, r, NULL);
4386 while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
4394 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4397 Assert(res != NULL);
4399 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4403 * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
4407 jsonb_set(PG_FUNCTION_ARGS)
4409 Jsonb *in = PG_GETARG_JSONB_P(0);
4410 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4411 Jsonb *newval = PG_GETARG_JSONB_P(2);
4412 bool create = PG_GETARG_BOOL(3);
4413 JsonbValue *res = NULL;
4418 JsonbParseState *st = NULL;
4420 if (ARR_NDIM(path) > 1)
4422 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4423 errmsg("wrong number of array subscripts")));
4425 if (JB_ROOT_IS_SCALAR(in))
4427 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4428 errmsg("cannot set path in scalar")));
4430 if (JB_ROOT_COUNT(in) == 0 && !create)
4431 PG_RETURN_JSONB_P(in);
4433 deconstruct_array(path, TEXTOID, -1, false, 'i',
4434 &path_elems, &path_nulls, &path_len);
4437 PG_RETURN_JSONB_P(in);
4439 it = JsonbIteratorInit(&in->root);
4441 res = setPath(&it, path_elems, path_nulls, path_len, &st,
4442 0, newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4444 Assert(res != NULL);
4446 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4451 * SQL function jsonb_delete_path(jsonb, text[])
4454 jsonb_delete_path(PG_FUNCTION_ARGS)
4456 Jsonb *in = PG_GETARG_JSONB_P(0);
4457 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4458 JsonbValue *res = NULL;
4463 JsonbParseState *st = NULL;
4465 if (ARR_NDIM(path) > 1)
4467 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4468 errmsg("wrong number of array subscripts")));
4470 if (JB_ROOT_IS_SCALAR(in))
4472 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4473 errmsg("cannot delete path in scalar")));
4475 if (JB_ROOT_COUNT(in) == 0)
4476 PG_RETURN_JSONB_P(in);
4478 deconstruct_array(path, TEXTOID, -1, false, 'i',
4479 &path_elems, &path_nulls, &path_len);
4482 PG_RETURN_JSONB_P(in);
4484 it = JsonbIteratorInit(&in->root);
4486 res = setPath(&it, path_elems, path_nulls, path_len, &st,
4487 0, NULL, JB_PATH_DELETE);
4489 Assert(res != NULL);
4491 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4495 * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
4499 jsonb_insert(PG_FUNCTION_ARGS)
4501 Jsonb *in = PG_GETARG_JSONB_P(0);
4502 ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4503 Jsonb *newval = PG_GETARG_JSONB_P(2);
4504 bool after = PG_GETARG_BOOL(3);
4505 JsonbValue *res = NULL;
4510 JsonbParseState *st = NULL;
4512 if (ARR_NDIM(path) > 1)
4514 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4515 errmsg("wrong number of array subscripts")));
4517 if (JB_ROOT_IS_SCALAR(in))
4519 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4520 errmsg("cannot set path in scalar")));
4522 deconstruct_array(path, TEXTOID, -1, false, 'i',
4523 &path_elems, &path_nulls, &path_len);
4526 PG_RETURN_JSONB_P(in);
4528 it = JsonbIteratorInit(&in->root);
4530 res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
4531 after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
4533 Assert(res != NULL);
4535 PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
4539 * Iterate over all jsonb objects and merge them into one.
4540 * The logic of this function copied from the same hstore function,
4541 * except the case, when it1 & it2 represents jbvObject.
4542 * In that case we just append the content of it2 to it1 without any
4546 IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
4547 JsonbParseState **state)
4552 JsonbIteratorToken r1,
4557 r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4558 r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4561 * Both elements are objects.
4563 if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4566 * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4567 * (because res will not be finished yet).
4569 pushJsonbValue(state, r1, NULL);
4570 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4571 pushJsonbValue(state, r1, &v1);
4574 * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4575 * (the concatenation will be completed).
4577 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
4578 res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4582 * Both elements are arrays (either can be scalar).
4584 else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4586 pushJsonbValue(state, r1, NULL);
4588 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4590 Assert(r1 == WJB_ELEM);
4591 pushJsonbValue(state, r1, &v1);
4594 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4596 Assert(r2 == WJB_ELEM);
4597 pushJsonbValue(state, WJB_ELEM, &v2);
4600 res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4602 /* have we got array || object or object || array? */
4603 else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4604 (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4607 JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4608 JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4610 bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4612 pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4616 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4617 while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
4618 pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4620 while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
4621 res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4625 while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4626 pushJsonbValue(state, r1, &v1);
4628 pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4629 while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
4630 pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4632 res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4638 * This must be scalar || object or object || scalar, as that's all
4639 * that's left. Both of these make no sense, so error out.
4642 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4643 errmsg("invalid concatenation of jsonb objects")));
4650 * Do most of the heavy work for jsonb_set/jsonb_insert
4652 * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
4654 * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
4655 * we create the new value if the key or array index does not exist.
4657 * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
4658 * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
4660 * All path elements before the last must already exist
4661 * whatever bits in op_type are set, or nothing is done.
4664 setPath(JsonbIterator **it, Datum *path_elems,
4665 bool *path_nulls, int path_len,
4666 JsonbParseState **st, int level, Jsonb *newval, int op_type)
4669 JsonbIteratorToken r;
4672 check_stack_depth();
4674 if (path_nulls[level])
4676 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4677 errmsg("path element at position %d is null",
4680 r = JsonbIteratorNext(it, &v, false);
4684 case WJB_BEGIN_ARRAY:
4685 (void) pushJsonbValue(st, r, NULL);
4686 setPathArray(it, path_elems, path_nulls, path_len, st, level,
4687 newval, v.val.array.nElems, op_type);
4688 r = JsonbIteratorNext(it, &v, false);
4689 Assert(r == WJB_END_ARRAY);
4690 res = pushJsonbValue(st, r, NULL);
4692 case WJB_BEGIN_OBJECT:
4693 (void) pushJsonbValue(st, r, NULL);
4694 setPathObject(it, path_elems, path_nulls, path_len, st, level,
4695 newval, v.val.object.nPairs, op_type);
4696 r = JsonbIteratorNext(it, &v, true);
4697 Assert(r == WJB_END_OBJECT);
4698 res = pushJsonbValue(st, r, NULL);
4702 res = pushJsonbValue(st, r, &v);
4705 elog(ERROR, "unrecognized iterator result: %d", (int) r);
4706 res = NULL; /* keep compiler quiet */
4714 * Object walker for setPath
4717 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4718 int path_len, JsonbParseState **st, int level,
4719 Jsonb *newval, uint32 npairs, int op_type)
4726 if (level >= path_len || path_nulls[level])
4729 /* empty object is a special case for create */
4730 if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
4731 (level == path_len - 1))
4735 newkey.type = jbvString;
4736 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
4737 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
4739 (void) pushJsonbValue(st, WJB_KEY, &newkey);
4740 addJsonbToParseState(st, newval);
4743 for (i = 0; i < npairs; i++)
4745 JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
4747 Assert(r == WJB_KEY);
4750 k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
4751 memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
4752 k.val.string.len) == 0)
4754 if (level == path_len - 1)
4757 * called from jsonb_insert(), it forbids redefining an
4760 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
4762 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4763 errmsg("cannot replace existing key"),
4764 errhint("Try using the function jsonb_set "
4765 "to replace key value.")));
4767 r = JsonbIteratorNext(it, &v, true); /* skip value */
4768 if (!(op_type & JB_PATH_DELETE))
4770 (void) pushJsonbValue(st, WJB_KEY, &k);
4771 addJsonbToParseState(st, newval);
4777 (void) pushJsonbValue(st, r, &k);
4778 setPath(it, path_elems, path_nulls, path_len,
4779 st, level + 1, newval, op_type);
4784 if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
4785 level == path_len - 1 && i == npairs - 1)
4789 newkey.type = jbvString;
4790 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
4791 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
4793 (void) pushJsonbValue(st, WJB_KEY, &newkey);
4794 addJsonbToParseState(st, newval);
4797 (void) pushJsonbValue(st, r, &k);
4798 r = JsonbIteratorNext(it, &v, false);
4799 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4800 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4802 int walking_level = 1;
4804 while (walking_level != 0)
4806 r = JsonbIteratorNext(it, &v, false);
4808 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4810 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4813 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4821 * Array walker for setPath
4824 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4825 int path_len, JsonbParseState **st, int level,
4826 Jsonb *newval, uint32 nelems, int op_type)
4833 /* pick correct index */
4834 if (level < path_len && !path_nulls[level])
4836 char *c = TextDatumGetCString(path_elems[level]);
4841 lindex = strtol(c, &badp, 10);
4842 if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
4845 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
4846 errmsg("path element at position %d is not an integer: \"%s\"",
4861 if (idx > 0 && idx > nelems)
4865 * if we're creating, and idx == INT_MIN, we prepend the new value to the
4866 * array also if the array is empty - in which case we don't really care
4867 * what the idx value is
4870 if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
4871 (op_type & JB_PATH_CREATE_OR_INSERT))
4873 Assert(newval != NULL);
4874 addJsonbToParseState(st, newval);
4878 /* iterate over the array elements */
4879 for (i = 0; i < nelems; i++)
4881 JsonbIteratorToken r;
4883 if (i == idx && level < path_len)
4885 if (level == path_len - 1)
4887 r = JsonbIteratorNext(it, &v, true); /* skip */
4889 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
4890 addJsonbToParseState(st, newval);
4893 * We should keep current value only in case of
4894 * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
4895 * otherwise it should be deleted or replaced
4897 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
4898 (void) pushJsonbValue(st, r, &v);
4900 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
4901 addJsonbToParseState(st, newval);
4906 (void) setPath(it, path_elems, path_nulls, path_len,
4907 st, level + 1, newval, op_type);
4911 r = JsonbIteratorNext(it, &v, false);
4913 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4915 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4917 int walking_level = 1;
4919 while (walking_level != 0)
4921 r = JsonbIteratorNext(it, &v, false);
4923 if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4925 if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4928 (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4932 if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
4933 level == path_len - 1 && i == nelems - 1)
4935 addJsonbToParseState(st, newval);
4942 * Iterate over jsonb string values or elements, and pass them together with an
4943 * iteration state to a specified JsonIterateStringValuesAction.
4946 iterate_jsonb_string_values(Jsonb *jb, void *state, JsonIterateStringValuesAction action)
4950 JsonbIteratorToken type;
4952 it = JsonbIteratorInit(&jb->root);
4954 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4956 if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
4958 action(state, v.val.string.val, v.val.string.len);
4964 * Iterate over json string values or elements, and pass them together with an
4965 * iteration state to a specified JsonIterateStringValuesAction.
4968 iterate_json_string_values(text *json, void *action_state, JsonIterateStringValuesAction action)
4970 JsonLexContext *lex = makeJsonLexContext(json, true);
4971 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
4972 IterateJsonStringValuesState *state = palloc0(sizeof(IterateJsonStringValuesState));
4975 state->action = action;
4976 state->action_state = action_state;
4978 sem->semstate = (void *) state;
4979 sem->scalar = iterate_string_values_scalar;
4981 pg_parse_json(lex, sem);
4985 * An auxiliary function for iterate_json_string_values to invoke a specified
4986 * JsonIterateStringValuesAction.
4989 iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
4991 IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
4993 if (tokentype == JSON_TOKEN_STRING)
4994 _state->action(_state->action_state, token, strlen(token));
4998 * Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
4999 * to every string value or element. Any necessary context for a
5000 * JsonTransformStringValuesAction can be passed in the action_state variable.
5001 * Function returns a copy of an original jsonb object with transformed values.
5004 transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
5005 JsonTransformStringValuesAction transform_action)
5010 JsonbIteratorToken type;
5011 JsonbParseState *st = NULL;
5013 bool is_scalar = false;
5015 it = JsonbIteratorInit(&jsonb->root);
5016 is_scalar = it->isScalar;
5018 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5020 if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
5022 out = transform_action(action_state, v.val.string.val, v.val.string.len);
5023 v.val.string.val = VARDATA_ANY(out);
5024 v.val.string.len = VARSIZE_ANY_EXHDR(out);
5025 res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
5029 res = pushJsonbValue(&st, type, (type == WJB_KEY ||
5030 type == WJB_VALUE ||
5031 type == WJB_ELEM) ? &v : NULL);
5035 if (res->type == jbvArray)
5036 res->val.array.rawScalar = is_scalar;
5038 return JsonbValueToJsonb(res);
5042 * Iterate over a json, and apply a specified JsonTransformStringValuesAction
5043 * to every string value or element. Any necessary context for a
5044 * JsonTransformStringValuesAction can be passed in the action_state variable.
5045 * Function returns a StringInfo, which is a copy of an original json with
5046 * transformed values.
5049 transform_json_string_values(text *json, void *action_state,
5050 JsonTransformStringValuesAction transform_action)
5052 JsonLexContext *lex = makeJsonLexContext(json, true);
5053 JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5054 TransformJsonStringValuesState *state = palloc0(sizeof(TransformJsonStringValuesState));
5057 state->strval = makeStringInfo();
5058 state->action = transform_action;
5059 state->action_state = action_state;
5061 sem->semstate = (void *) state;
5062 sem->scalar = transform_string_values_scalar;
5063 sem->object_start = transform_string_values_object_start;
5064 sem->object_end = transform_string_values_object_end;
5065 sem->array_start = transform_string_values_array_start;
5066 sem->array_end = transform_string_values_array_end;
5067 sem->scalar = transform_string_values_scalar;
5068 sem->array_element_start = transform_string_values_array_element_start;
5069 sem->object_field_start = transform_string_values_object_field_start;
5071 pg_parse_json(lex, sem);
5073 return cstring_to_text_with_len(state->strval->data, state->strval->len);
5077 * Set of auxiliary functions for transform_json_string_values to invoke a
5078 * specified JsonTransformStringValuesAction for all values and left everything
5082 transform_string_values_object_start(void *state)
5084 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5086 appendStringInfoCharMacro(_state->strval, '{');
5090 transform_string_values_object_end(void *state)
5092 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5094 appendStringInfoCharMacro(_state->strval, '}');
5098 transform_string_values_array_start(void *state)
5100 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5102 appendStringInfoCharMacro(_state->strval, '[');
5106 transform_string_values_array_end(void *state)
5108 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5110 appendStringInfoCharMacro(_state->strval, ']');
5114 transform_string_values_object_field_start(void *state, char *fname, bool isnull)
5116 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5118 if (_state->strval->data[_state->strval->len - 1] != '{')
5119 appendStringInfoCharMacro(_state->strval, ',');
5122 * Unfortunately we don't have the quoted and escaped string any more, so
5123 * we have to re-escape it.
5125 escape_json(_state->strval, fname);
5126 appendStringInfoCharMacro(_state->strval, ':');
5130 transform_string_values_array_element_start(void *state, bool isnull)
5132 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5134 if (_state->strval->data[_state->strval->len - 1] != '[')
5135 appendStringInfoCharMacro(_state->strval, ',');
5139 transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
5141 TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
5143 if (tokentype == JSON_TOKEN_STRING)
5145 text *out = _state->action(_state->action_state, token, strlen(token));
5147 escape_json(_state->strval, text_to_cstring(out));
5150 appendStringInfoString(_state->strval, token);