]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/jsonfuncs.c
Introduce convenience macros to hide JsonbContainer header accesses better.
[postgresql] / src / backend / utils / adt / jsonfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * jsonfuncs.c
4  *              Functions to process JSON data types.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        src/backend/utils/adt/jsonfuncs.c
11  *
12  *-------------------------------------------------------------------------
13  */
14
15 #include "postgres.h"
16
17 #include <limits.h>
18
19 #include "access/htup_details.h"
20 #include "catalog/pg_type.h"
21 #include "fmgr.h"
22 #include "funcapi.h"
23 #include "lib/stringinfo.h"
24 #include "mb/pg_wchar.h"
25 #include "miscadmin.h"
26 #include "utils/array.h"
27 #include "utils/builtins.h"
28 #include "utils/hsearch.h"
29 #include "utils/json.h"
30 #include "utils/jsonapi.h"
31 #include "utils/jsonb.h"
32 #include "utils/lsyscache.h"
33 #include "utils/memutils.h"
34 #include "utils/typcache.h"
35
36 /* Operations available for setPath */
37 #define JB_PATH_CREATE                                  0x0001
38 #define JB_PATH_DELETE                                  0x0002
39 #define JB_PATH_REPLACE                                 0x0004
40 #define JB_PATH_INSERT_BEFORE                   0x0008
41 #define JB_PATH_INSERT_AFTER                    0x0010
42 #define JB_PATH_CREATE_OR_INSERT \
43         (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
44
45 /* state for json_object_keys */
46 typedef struct OkeysState
47 {
48         JsonLexContext *lex;
49         char      **result;
50         int                     result_size;
51         int                     result_count;
52         int                     sent_count;
53 } OkeysState;
54
55 /* state for json_get* functions */
56 typedef struct GetState
57 {
58         JsonLexContext *lex;
59         text       *tresult;
60         char       *result_start;
61         bool            normalize_results;
62         bool            next_scalar;
63         int                     npath;                  /* length of each path-related array */
64         char      **path_names;         /* field name(s) being sought */
65         int                *path_indexes;       /* array index(es) being sought */
66         bool       *pathok;                     /* is path matched to current depth? */
67         int                *array_cur_index;    /* current element index at each path level */
68 } GetState;
69
70 /* state for json_array_length */
71 typedef struct AlenState
72 {
73         JsonLexContext *lex;
74         int                     count;
75 } AlenState;
76
77 /* state for json_each */
78 typedef struct EachState
79 {
80         JsonLexContext *lex;
81         Tuplestorestate *tuple_store;
82         TupleDesc       ret_tdesc;
83         MemoryContext tmp_cxt;
84         char       *result_start;
85         bool            normalize_results;
86         bool            next_scalar;
87         char       *normalized_scalar;
88 } EachState;
89
90 /* state for json_array_elements */
91 typedef struct ElementsState
92 {
93         JsonLexContext *lex;
94         const char *function_name;
95         Tuplestorestate *tuple_store;
96         TupleDesc       ret_tdesc;
97         MemoryContext tmp_cxt;
98         char       *result_start;
99         bool            normalize_results;
100         bool            next_scalar;
101         char       *normalized_scalar;
102 } ElementsState;
103
104 /* state for get_json_object_as_hash */
105 typedef struct JhashState
106 {
107         JsonLexContext *lex;
108         const char *function_name;
109         HTAB       *hash;
110         char       *saved_scalar;
111         char       *save_json_start;
112 } JHashState;
113
114 /* hashtable element */
115 typedef struct JsonHashEntry
116 {
117         char            fname[NAMEDATALEN];             /* hash key (MUST BE FIRST) */
118         char       *val;
119         char       *json;
120         bool            isnull;
121 } JsonHashEntry;
122
123 /* these two are stolen from hstore / record_out, used in populate_record* */
124 typedef struct ColumnIOData
125 {
126         Oid                     column_type;
127         Oid                     typiofunc;
128         Oid                     typioparam;
129         FmgrInfo        proc;
130 } ColumnIOData;
131
132 typedef struct RecordIOData
133 {
134         Oid                     record_type;
135         int32           record_typmod;
136         int                     ncolumns;
137         ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
138 } RecordIOData;
139
140 /* state for populate_recordset */
141 typedef struct PopulateRecordsetState
142 {
143         JsonLexContext *lex;
144         const char *function_name;
145         HTAB       *json_hash;
146         char       *saved_scalar;
147         char       *save_json_start;
148         Tuplestorestate *tuple_store;
149         TupleDesc       ret_tdesc;
150         HeapTupleHeader rec;
151         RecordIOData *my_extra;
152         MemoryContext fn_mcxt;          /* used to stash IO funcs */
153 } PopulateRecordsetState;
154
155 /* state for json_strip_nulls */
156 typedef struct StripnullState
157 {
158         JsonLexContext *lex;
159         StringInfo      strval;
160         bool            skip_next_null;
161 } StripnullState;
162
163 /* semantic action functions for json_object_keys */
164 static void okeys_object_field_start(void *state, char *fname, bool isnull);
165 static void okeys_array_start(void *state);
166 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
167
168 /* semantic action functions for json_get* functions */
169 static void get_object_start(void *state);
170 static void get_object_end(void *state);
171 static void get_object_field_start(void *state, char *fname, bool isnull);
172 static void get_object_field_end(void *state, char *fname, bool isnull);
173 static void get_array_start(void *state);
174 static void get_array_end(void *state);
175 static void get_array_element_start(void *state, bool isnull);
176 static void get_array_element_end(void *state, bool isnull);
177 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
178
179 /* common worker function for json getter functions */
180 static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
181 static text *get_worker(text *json, char **tpath, int *ipath, int npath,
182                    bool normalize_results);
183 static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
184
185 /* semantic action functions for json_array_length */
186 static void alen_object_start(void *state);
187 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
188 static void alen_array_element_start(void *state, bool isnull);
189
190 /* common workers for json{b}_each* functions */
191 static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
192 static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
193                                   bool as_text);
194
195 /* semantic action functions for json_each */
196 static void each_object_field_start(void *state, char *fname, bool isnull);
197 static void each_object_field_end(void *state, char *fname, bool isnull);
198 static void each_array_start(void *state);
199 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
200
201 /* common workers for json{b}_array_elements_* functions */
202 static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
203                                 bool as_text);
204 static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
205                                           bool as_text);
206
207 /* semantic action functions for json_array_elements */
208 static void elements_object_start(void *state);
209 static void elements_array_element_start(void *state, bool isnull);
210 static void elements_array_element_end(void *state, bool isnull);
211 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
212
213 /* turn a json object into a hash table */
214 static HTAB *get_json_object_as_hash(text *json, const char *funcname);
215
216 /* common worker for populate_record and to_record */
217 static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
218                                            bool have_record_arg);
219
220 /* semantic action functions for get_json_object_as_hash */
221 static void hash_object_field_start(void *state, char *fname, bool isnull);
222 static void hash_object_field_end(void *state, char *fname, bool isnull);
223 static void hash_array_start(void *state);
224 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
225
226 /* semantic action functions for populate_recordset */
227 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
228 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
229 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
230 static void populate_recordset_object_start(void *state);
231 static void populate_recordset_object_end(void *state);
232 static void populate_recordset_array_start(void *state);
233 static void populate_recordset_array_element_start(void *state, bool isnull);
234
235 /* semantic action functions for json_strip_nulls */
236 static void sn_object_start(void *state);
237 static void sn_object_end(void *state);
238 static void sn_array_start(void *state);
239 static void sn_array_end(void *state);
240 static void sn_object_field_start(void *state, char *fname, bool isnull);
241 static void sn_array_element_start(void *state, bool isnull);
242 static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
243
244 /* Turn a jsonb object into a record */
245 static void make_row_from_rec_and_jsonb(Jsonb *element,
246                                                         PopulateRecordsetState *state);
247
248 /* worker function for populate_recordset and to_recordset */
249 static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
250                                                   bool have_record_arg);
251
252 /* Worker that takes care of common setup for us */
253 static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
254                                                            uint32 flags,
255                                                            char *key,
256                                                            uint32 keylen);
257
258 /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
259 static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
260                            JsonbParseState **state);
261 static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
262                 bool *path_nulls, int path_len,
263                 JsonbParseState **st, int level, Jsonb *newval,
264                 int op_type);
265 static void setPathObject(JsonbIterator **it, Datum *path_elems,
266                           bool *path_nulls, int path_len, JsonbParseState **st,
267                           int level,
268                           Jsonb *newval, uint32 npairs, int op_type);
269 static void setPathArray(JsonbIterator **it, Datum *path_elems,
270                          bool *path_nulls, int path_len, JsonbParseState **st,
271                          int level, Jsonb *newval, uint32 nelems, int op_type);
272 static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
273
274
275 /*
276  * SQL function json_object_keys
277  *
278  * Returns the set of keys for the object argument.
279  *
280  * This SRF operates in value-per-call mode. It processes the
281  * object during the first call, and the keys are simply stashed
282  * in an array, whose size is expanded as necessary. This is probably
283  * safe enough for a list of keys of a single object, since they are
284  * limited in size to NAMEDATALEN and the number of keys is unlikely to
285  * be so huge that it has major memory implications.
286  */
287 Datum
288 jsonb_object_keys(PG_FUNCTION_ARGS)
289 {
290         FuncCallContext *funcctx;
291         OkeysState *state;
292         int                     i;
293
294         if (SRF_IS_FIRSTCALL())
295         {
296                 MemoryContext oldcontext;
297                 Jsonb      *jb = PG_GETARG_JSONB(0);
298                 bool            skipNested = false;
299                 JsonbIterator *it;
300                 JsonbValue      v;
301                 JsonbIteratorToken r;
302
303                 if (JB_ROOT_IS_SCALAR(jb))
304                         ereport(ERROR,
305                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306                                          errmsg("cannot call %s on a scalar",
307                                                         "jsonb_object_keys")));
308                 else if (JB_ROOT_IS_ARRAY(jb))
309                         ereport(ERROR,
310                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
311                                          errmsg("cannot call %s on an array",
312                                                         "jsonb_object_keys")));
313
314                 funcctx = SRF_FIRSTCALL_INIT();
315                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
316
317                 state = palloc(sizeof(OkeysState));
318
319                 state->result_size = JB_ROOT_COUNT(jb);
320                 state->result_count = 0;
321                 state->sent_count = 0;
322                 state->result = palloc(state->result_size * sizeof(char *));
323
324                 it = JsonbIteratorInit(&jb->root);
325
326                 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
327                 {
328                         skipNested = true;
329
330                         if (r == WJB_KEY)
331                         {
332                                 char       *cstr;
333
334                                 cstr = palloc(v.val.string.len + 1 * sizeof(char));
335                                 memcpy(cstr, v.val.string.val, v.val.string.len);
336                                 cstr[v.val.string.len] = '\0';
337                                 state->result[state->result_count++] = cstr;
338                         }
339                 }
340
341                 MemoryContextSwitchTo(oldcontext);
342                 funcctx->user_fctx = (void *) state;
343         }
344
345         funcctx = SRF_PERCALL_SETUP();
346         state = (OkeysState *) funcctx->user_fctx;
347
348         if (state->sent_count < state->result_count)
349         {
350                 char       *nxt = state->result[state->sent_count++];
351
352                 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
353         }
354
355         /* cleanup to reduce or eliminate memory leaks */
356         for (i = 0; i < state->result_count; i++)
357                 pfree(state->result[i]);
358         pfree(state->result);
359         pfree(state);
360
361         SRF_RETURN_DONE(funcctx);
362 }
363
364
365 Datum
366 json_object_keys(PG_FUNCTION_ARGS)
367 {
368         FuncCallContext *funcctx;
369         OkeysState *state;
370         int                     i;
371
372         if (SRF_IS_FIRSTCALL())
373         {
374                 text       *json = PG_GETARG_TEXT_P(0);
375                 JsonLexContext *lex = makeJsonLexContext(json, true);
376                 JsonSemAction *sem;
377                 MemoryContext oldcontext;
378
379                 funcctx = SRF_FIRSTCALL_INIT();
380                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
381
382                 state = palloc(sizeof(OkeysState));
383                 sem = palloc0(sizeof(JsonSemAction));
384
385                 state->lex = lex;
386                 state->result_size = 256;
387                 state->result_count = 0;
388                 state->sent_count = 0;
389                 state->result = palloc(256 * sizeof(char *));
390
391                 sem->semstate = (void *) state;
392                 sem->array_start = okeys_array_start;
393                 sem->scalar = okeys_scalar;
394                 sem->object_field_start = okeys_object_field_start;
395                 /* remainder are all NULL, courtesy of palloc0 above */
396
397                 pg_parse_json(lex, sem);
398                 /* keys are now in state->result */
399
400                 pfree(lex->strval->data);
401                 pfree(lex->strval);
402                 pfree(lex);
403                 pfree(sem);
404
405                 MemoryContextSwitchTo(oldcontext);
406                 funcctx->user_fctx = (void *) state;
407         }
408
409         funcctx = SRF_PERCALL_SETUP();
410         state = (OkeysState *) funcctx->user_fctx;
411
412         if (state->sent_count < state->result_count)
413         {
414                 char       *nxt = state->result[state->sent_count++];
415
416                 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
417         }
418
419         /* cleanup to reduce or eliminate memory leaks */
420         for (i = 0; i < state->result_count; i++)
421                 pfree(state->result[i]);
422         pfree(state->result);
423         pfree(state);
424
425         SRF_RETURN_DONE(funcctx);
426 }
427
428 static void
429 okeys_object_field_start(void *state, char *fname, bool isnull)
430 {
431         OkeysState *_state = (OkeysState *) state;
432
433         /* only collecting keys for the top level object */
434         if (_state->lex->lex_level != 1)
435                 return;
436
437         /* enlarge result array if necessary */
438         if (_state->result_count >= _state->result_size)
439         {
440                 _state->result_size *= 2;
441                 _state->result = (char **)
442                         repalloc(_state->result, sizeof(char *) * _state->result_size);
443         }
444
445         /* save a copy of the field name */
446         _state->result[_state->result_count++] = pstrdup(fname);
447 }
448
449 static void
450 okeys_array_start(void *state)
451 {
452         OkeysState *_state = (OkeysState *) state;
453
454         /* top level must be a json object */
455         if (_state->lex->lex_level == 0)
456                 ereport(ERROR,
457                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
458                                  errmsg("cannot call %s on an array",
459                                                 "json_object_keys")));
460 }
461
462 static void
463 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
464 {
465         OkeysState *_state = (OkeysState *) state;
466
467         /* top level must be a json object */
468         if (_state->lex->lex_level == 0)
469                 ereport(ERROR,
470                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
471                                  errmsg("cannot call %s on a scalar",
472                                                 "json_object_keys")));
473 }
474
475 /*
476  * json and jsonb getter functions
477  * these implement the -> ->> #> and #>> operators
478  * and the json{b?}_extract_path*(json, text, ...) functions
479  */
480
481
482 Datum
483 json_object_field(PG_FUNCTION_ARGS)
484 {
485         text       *json = PG_GETARG_TEXT_P(0);
486         text       *fname = PG_GETARG_TEXT_PP(1);
487         char       *fnamestr = text_to_cstring(fname);
488         text       *result;
489
490         result = get_worker(json, &fnamestr, NULL, 1, false);
491
492         if (result != NULL)
493                 PG_RETURN_TEXT_P(result);
494         else
495                 PG_RETURN_NULL();
496 }
497
498 Datum
499 jsonb_object_field(PG_FUNCTION_ARGS)
500 {
501         Jsonb      *jb = PG_GETARG_JSONB(0);
502         text       *key = PG_GETARG_TEXT_PP(1);
503         JsonbValue *v;
504
505         if (!JB_ROOT_IS_OBJECT(jb))
506                 PG_RETURN_NULL();
507
508         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
509                                                                            VARDATA_ANY(key),
510                                                                            VARSIZE_ANY_EXHDR(key));
511
512         if (v != NULL)
513                 PG_RETURN_JSONB(JsonbValueToJsonb(v));
514
515         PG_RETURN_NULL();
516 }
517
518 Datum
519 json_object_field_text(PG_FUNCTION_ARGS)
520 {
521         text       *json = PG_GETARG_TEXT_P(0);
522         text       *fname = PG_GETARG_TEXT_PP(1);
523         char       *fnamestr = text_to_cstring(fname);
524         text       *result;
525
526         result = get_worker(json, &fnamestr, NULL, 1, true);
527
528         if (result != NULL)
529                 PG_RETURN_TEXT_P(result);
530         else
531                 PG_RETURN_NULL();
532 }
533
534 Datum
535 jsonb_object_field_text(PG_FUNCTION_ARGS)
536 {
537         Jsonb      *jb = PG_GETARG_JSONB(0);
538         text       *key = PG_GETARG_TEXT_PP(1);
539         JsonbValue *v;
540
541         if (!JB_ROOT_IS_OBJECT(jb))
542                 PG_RETURN_NULL();
543
544         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
545                                                                            VARDATA_ANY(key),
546                                                                            VARSIZE_ANY_EXHDR(key));
547
548         if (v != NULL)
549         {
550                 text       *result = NULL;
551
552                 switch (v->type)
553                 {
554                         case jbvNull:
555                                 break;
556                         case jbvBool:
557                                 result = cstring_to_text(v->val.boolean ? "true" : "false");
558                                 break;
559                         case jbvString:
560                                 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
561                                 break;
562                         case jbvNumeric:
563                                 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
564                                                                                   PointerGetDatum(v->val.numeric))));
565                                 break;
566                         case jbvBinary:
567                                 {
568                                         StringInfo      jtext = makeStringInfo();
569
570                                         (void) JsonbToCString(jtext, v->val.binary.data, -1);
571                                         result = cstring_to_text_with_len(jtext->data, jtext->len);
572                                 }
573                                 break;
574                         default:
575                                 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
576                 }
577
578                 if (result)
579                         PG_RETURN_TEXT_P(result);
580         }
581
582         PG_RETURN_NULL();
583 }
584
585 Datum
586 json_array_element(PG_FUNCTION_ARGS)
587 {
588         text       *json = PG_GETARG_TEXT_P(0);
589         int                     element = PG_GETARG_INT32(1);
590         text       *result;
591
592         result = get_worker(json, NULL, &element, 1, false);
593
594         if (result != NULL)
595                 PG_RETURN_TEXT_P(result);
596         else
597                 PG_RETURN_NULL();
598 }
599
600 Datum
601 jsonb_array_element(PG_FUNCTION_ARGS)
602 {
603         Jsonb      *jb = PG_GETARG_JSONB(0);
604         int                     element = PG_GETARG_INT32(1);
605         JsonbValue *v;
606
607         if (!JB_ROOT_IS_ARRAY(jb))
608                 PG_RETURN_NULL();
609
610         /* Handle negative subscript */
611         if (element < 0)
612         {
613                 uint32          nelements = JB_ROOT_COUNT(jb);
614
615                 if (-element > nelements)
616                         PG_RETURN_NULL();
617                 else
618                         element += nelements;
619         }
620
621         v = getIthJsonbValueFromContainer(&jb->root, element);
622         if (v != NULL)
623                 PG_RETURN_JSONB(JsonbValueToJsonb(v));
624
625         PG_RETURN_NULL();
626 }
627
628 Datum
629 json_array_element_text(PG_FUNCTION_ARGS)
630 {
631         text       *json = PG_GETARG_TEXT_P(0);
632         int                     element = PG_GETARG_INT32(1);
633         text       *result;
634
635         result = get_worker(json, NULL, &element, 1, true);
636
637         if (result != NULL)
638                 PG_RETURN_TEXT_P(result);
639         else
640                 PG_RETURN_NULL();
641 }
642
643 Datum
644 jsonb_array_element_text(PG_FUNCTION_ARGS)
645 {
646         Jsonb      *jb = PG_GETARG_JSONB(0);
647         int                     element = PG_GETARG_INT32(1);
648         JsonbValue *v;
649
650         if (!JB_ROOT_IS_ARRAY(jb))
651                 PG_RETURN_NULL();
652
653         /* Handle negative subscript */
654         if (element < 0)
655         {
656                 uint32          nelements = JB_ROOT_COUNT(jb);
657
658                 if (-element > nelements)
659                         PG_RETURN_NULL();
660                 else
661                         element += nelements;
662         }
663
664         v = getIthJsonbValueFromContainer(&jb->root, element);
665         if (v != NULL)
666         {
667                 text       *result = NULL;
668
669                 switch (v->type)
670                 {
671                         case jbvNull:
672                                 break;
673                         case jbvBool:
674                                 result = cstring_to_text(v->val.boolean ? "true" : "false");
675                                 break;
676                         case jbvString:
677                                 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
678                                 break;
679                         case jbvNumeric:
680                                 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
681                                                                                   PointerGetDatum(v->val.numeric))));
682                                 break;
683                         case jbvBinary:
684                                 {
685                                         StringInfo      jtext = makeStringInfo();
686
687                                         (void) JsonbToCString(jtext, v->val.binary.data, -1);
688                                         result = cstring_to_text_with_len(jtext->data, jtext->len);
689                                 }
690                                 break;
691                         default:
692                                 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
693                 }
694
695                 if (result)
696                         PG_RETURN_TEXT_P(result);
697         }
698
699         PG_RETURN_NULL();
700 }
701
702 Datum
703 json_extract_path(PG_FUNCTION_ARGS)
704 {
705         return get_path_all(fcinfo, false);
706 }
707
708 Datum
709 json_extract_path_text(PG_FUNCTION_ARGS)
710 {
711         return get_path_all(fcinfo, true);
712 }
713
714 /*
715  * common routine for extract_path functions
716  */
717 static Datum
718 get_path_all(FunctionCallInfo fcinfo, bool as_text)
719 {
720         text       *json = PG_GETARG_TEXT_P(0);
721         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
722         text       *result;
723         Datum      *pathtext;
724         bool       *pathnulls;
725         int                     npath;
726         char      **tpath;
727         int                *ipath;
728         int                     i;
729
730         /*
731          * If the array contains any null elements, return NULL, on the grounds
732          * that you'd have gotten NULL if any RHS value were NULL in a nested
733          * series of applications of the -> operator.  (Note: because we also
734          * return NULL for error cases such as no-such-field, this is true
735          * regardless of the contents of the rest of the array.)
736          */
737         if (array_contains_nulls(path))
738                 PG_RETURN_NULL();
739
740         deconstruct_array(path, TEXTOID, -1, false, 'i',
741                                           &pathtext, &pathnulls, &npath);
742
743         tpath = palloc(npath * sizeof(char *));
744         ipath = palloc(npath * sizeof(int));
745
746         for (i = 0; i < npath; i++)
747         {
748                 Assert(!pathnulls[i]);
749                 tpath[i] = TextDatumGetCString(pathtext[i]);
750
751                 /*
752                  * we have no idea at this stage what structure the document is so
753                  * just convert anything in the path that we can to an integer and set
754                  * all the other integers to INT_MIN which will never match.
755                  */
756                 if (*tpath[i] != '\0')
757                 {
758                         long            ind;
759                         char       *endptr;
760
761                         errno = 0;
762                         ind = strtol(tpath[i], &endptr, 10);
763                         if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
764                                 ipath[i] = (int) ind;
765                         else
766                                 ipath[i] = INT_MIN;
767                 }
768                 else
769                         ipath[i] = INT_MIN;
770         }
771
772         result = get_worker(json, tpath, ipath, npath, as_text);
773
774         if (result != NULL)
775                 PG_RETURN_TEXT_P(result);
776         else
777                 PG_RETURN_NULL();
778 }
779
780 /*
781  * get_worker
782  *
783  * common worker for all the json getter functions
784  *
785  * json: JSON object (in text form)
786  * tpath[]: field name(s) to extract
787  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
788  * npath: length of tpath[] and/or ipath[]
789  * normalize_results: true to de-escape string and null scalars
790  *
791  * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
792  * field is not to be matched at that nesting level.  Similarly, ipath can
793  * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
794  * not to be matched at that nesting level (a json datum should never be
795  * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
796  */
797 static text *
798 get_worker(text *json,
799                    char **tpath,
800                    int *ipath,
801                    int npath,
802                    bool normalize_results)
803 {
804         JsonLexContext *lex = makeJsonLexContext(json, true);
805         JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
806         GetState   *state = palloc0(sizeof(GetState));
807
808         Assert(npath >= 0);
809
810         state->lex = lex;
811         /* is it "_as_text" variant? */
812         state->normalize_results = normalize_results;
813         state->npath = npath;
814         state->path_names = tpath;
815         state->path_indexes = ipath;
816         state->pathok = palloc0(sizeof(bool) * npath);
817         state->array_cur_index = palloc(sizeof(int) * npath);
818
819         if (npath > 0)
820                 state->pathok[0] = true;
821
822         sem->semstate = (void *) state;
823
824         /*
825          * Not all variants need all the semantic routines. Only set the ones that
826          * are actually needed for maximum efficiency.
827          */
828         sem->scalar = get_scalar;
829         if (npath == 0)
830         {
831                 sem->object_start = get_object_start;
832                 sem->object_end = get_object_end;
833                 sem->array_start = get_array_start;
834                 sem->array_end = get_array_end;
835         }
836         if (tpath != NULL)
837         {
838                 sem->object_field_start = get_object_field_start;
839                 sem->object_field_end = get_object_field_end;
840         }
841         if (ipath != NULL)
842         {
843                 sem->array_start = get_array_start;
844                 sem->array_element_start = get_array_element_start;
845                 sem->array_element_end = get_array_element_end;
846         }
847
848         pg_parse_json(lex, sem);
849
850         return state->tresult;
851 }
852
853 static void
854 get_object_start(void *state)
855 {
856         GetState   *_state = (GetState *) state;
857         int                     lex_level = _state->lex->lex_level;
858
859         if (lex_level == 0 && _state->npath == 0)
860         {
861                 /*
862                  * Special case: we should match the entire object.  We only need this
863                  * at outermost level because at nested levels the match will have
864                  * been started by the outer field or array element callback.
865                  */
866                 _state->result_start = _state->lex->token_start;
867         }
868 }
869
870 static void
871 get_object_end(void *state)
872 {
873         GetState   *_state = (GetState *) state;
874         int                     lex_level = _state->lex->lex_level;
875
876         if (lex_level == 0 && _state->npath == 0)
877         {
878                 /* Special case: return the entire object */
879                 char       *start = _state->result_start;
880                 int                     len = _state->lex->prev_token_terminator - start;
881
882                 _state->tresult = cstring_to_text_with_len(start, len);
883         }
884 }
885
886 static void
887 get_object_field_start(void *state, char *fname, bool isnull)
888 {
889         GetState   *_state = (GetState *) state;
890         bool            get_next = false;
891         int                     lex_level = _state->lex->lex_level;
892
893         if (lex_level <= _state->npath &&
894                 _state->pathok[lex_level - 1] &&
895                 _state->path_names != NULL &&
896                 _state->path_names[lex_level - 1] != NULL &&
897                 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
898         {
899                 if (lex_level < _state->npath)
900                 {
901                         /* if not at end of path just mark path ok */
902                         _state->pathok[lex_level] = true;
903                 }
904                 else
905                 {
906                         /* end of path, so we want this value */
907                         get_next = true;
908                 }
909         }
910
911         if (get_next)
912         {
913                 /* this object overrides any previous matching object */
914                 _state->tresult = NULL;
915                 _state->result_start = NULL;
916
917                 if (_state->normalize_results &&
918                         _state->lex->token_type == JSON_TOKEN_STRING)
919                 {
920                         /* for as_text variants, tell get_scalar to set it for us */
921                         _state->next_scalar = true;
922                 }
923                 else
924                 {
925                         /* for non-as_text variants, just note the json starting point */
926                         _state->result_start = _state->lex->token_start;
927                 }
928         }
929 }
930
931 static void
932 get_object_field_end(void *state, char *fname, bool isnull)
933 {
934         GetState   *_state = (GetState *) state;
935         bool            get_last = false;
936         int                     lex_level = _state->lex->lex_level;
937
938         /* same tests as in get_object_field_start */
939         if (lex_level <= _state->npath &&
940                 _state->pathok[lex_level - 1] &&
941                 _state->path_names != NULL &&
942                 _state->path_names[lex_level - 1] != NULL &&
943                 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
944         {
945                 if (lex_level < _state->npath)
946                 {
947                         /* done with this field so reset pathok */
948                         _state->pathok[lex_level] = false;
949                 }
950                 else
951                 {
952                         /* end of path, so we want this value */
953                         get_last = true;
954                 }
955         }
956
957         /* for as_text scalar case, our work is already done */
958         if (get_last && _state->result_start != NULL)
959         {
960                 /*
961                  * make a text object from the string from the prevously noted json
962                  * start up to the end of the previous token (the lexer is by now
963                  * ahead of us on whatever came after what we're interested in).
964                  */
965                 if (isnull && _state->normalize_results)
966                         _state->tresult = (text *) NULL;
967                 else
968                 {
969                         char       *start = _state->result_start;
970                         int                     len = _state->lex->prev_token_terminator - start;
971
972                         _state->tresult = cstring_to_text_with_len(start, len);
973                 }
974
975                 /* this should be unnecessary but let's do it for cleanliness: */
976                 _state->result_start = NULL;
977         }
978 }
979
980 static void
981 get_array_start(void *state)
982 {
983         GetState   *_state = (GetState *) state;
984         int                     lex_level = _state->lex->lex_level;
985
986         if (lex_level < _state->npath)
987         {
988                 /* Initialize counting of elements in this array */
989                 _state->array_cur_index[lex_level] = -1;
990
991                 /* INT_MIN value is reserved to represent invalid subscript */
992                 if (_state->path_indexes[lex_level] < 0 &&
993                         _state->path_indexes[lex_level] != INT_MIN)
994                 {
995                         /* Negative subscript -- convert to positive-wise subscript */
996                         int                     nelements = json_count_array_elements(_state->lex);
997
998                         if (-_state->path_indexes[lex_level] <= nelements)
999                                 _state->path_indexes[lex_level] += nelements;
1000                 }
1001         }
1002         else if (lex_level == 0 && _state->npath == 0)
1003         {
1004                 /*
1005                  * Special case: we should match the entire array.  We only need this
1006                  * at the outermost level because at nested levels the match will have
1007                  * been started by the outer field or array element callback.
1008                  */
1009                 _state->result_start = _state->lex->token_start;
1010         }
1011 }
1012
1013 static void
1014 get_array_end(void *state)
1015 {
1016         GetState   *_state = (GetState *) state;
1017         int                     lex_level = _state->lex->lex_level;
1018
1019         if (lex_level == 0 && _state->npath == 0)
1020         {
1021                 /* Special case: return the entire array */
1022                 char       *start = _state->result_start;
1023                 int                     len = _state->lex->prev_token_terminator - start;
1024
1025                 _state->tresult = cstring_to_text_with_len(start, len);
1026         }
1027 }
1028
1029 static void
1030 get_array_element_start(void *state, bool isnull)
1031 {
1032         GetState   *_state = (GetState *) state;
1033         bool            get_next = false;
1034         int                     lex_level = _state->lex->lex_level;
1035
1036         /* Update array element counter */
1037         if (lex_level <= _state->npath)
1038                 _state->array_cur_index[lex_level - 1]++;
1039
1040         if (lex_level <= _state->npath &&
1041                 _state->pathok[lex_level - 1] &&
1042                 _state->path_indexes != NULL &&
1043                 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1044         {
1045                 if (lex_level < _state->npath)
1046                 {
1047                         /* if not at end of path just mark path ok */
1048                         _state->pathok[lex_level] = true;
1049                 }
1050                 else
1051                 {
1052                         /* end of path, so we want this value */
1053                         get_next = true;
1054                 }
1055         }
1056
1057         /* same logic as for objects */
1058         if (get_next)
1059         {
1060                 _state->tresult = NULL;
1061                 _state->result_start = NULL;
1062
1063                 if (_state->normalize_results &&
1064                         _state->lex->token_type == JSON_TOKEN_STRING)
1065                 {
1066                         _state->next_scalar = true;
1067                 }
1068                 else
1069                 {
1070                         _state->result_start = _state->lex->token_start;
1071                 }
1072         }
1073 }
1074
1075 static void
1076 get_array_element_end(void *state, bool isnull)
1077 {
1078         GetState   *_state = (GetState *) state;
1079         bool            get_last = false;
1080         int                     lex_level = _state->lex->lex_level;
1081
1082         /* same tests as in get_array_element_start */
1083         if (lex_level <= _state->npath &&
1084                 _state->pathok[lex_level - 1] &&
1085                 _state->path_indexes != NULL &&
1086                 _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1087         {
1088                 if (lex_level < _state->npath)
1089                 {
1090                         /* done with this element so reset pathok */
1091                         _state->pathok[lex_level] = false;
1092                 }
1093                 else
1094                 {
1095                         /* end of path, so we want this value */
1096                         get_last = true;
1097                 }
1098         }
1099
1100         /* same logic as for objects */
1101         if (get_last && _state->result_start != NULL)
1102         {
1103                 if (isnull && _state->normalize_results)
1104                         _state->tresult = (text *) NULL;
1105                 else
1106                 {
1107                         char       *start = _state->result_start;
1108                         int                     len = _state->lex->prev_token_terminator - start;
1109
1110                         _state->tresult = cstring_to_text_with_len(start, len);
1111                 }
1112
1113                 _state->result_start = NULL;
1114         }
1115 }
1116
1117 static void
1118 get_scalar(void *state, char *token, JsonTokenType tokentype)
1119 {
1120         GetState   *_state = (GetState *) state;
1121         int                     lex_level = _state->lex->lex_level;
1122
1123         /* Check for whole-object match */
1124         if (lex_level == 0 && _state->npath == 0)
1125         {
1126                 if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1127                 {
1128                         /* we want the de-escaped string */
1129                         _state->next_scalar = true;
1130                 }
1131                 else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1132                 {
1133                         _state->tresult = (text *) NULL;
1134                 }
1135                 else
1136                 {
1137                         /*
1138                          * This is a bit hokey: we will suppress whitespace after the
1139                          * scalar token, but not whitespace before it.  Probably not worth
1140                          * doing our own space-skipping to avoid that.
1141                          */
1142                         char       *start = _state->lex->input;
1143                         int                     len = _state->lex->prev_token_terminator - start;
1144
1145                         _state->tresult = cstring_to_text_with_len(start, len);
1146                 }
1147         }
1148
1149         if (_state->next_scalar)
1150         {
1151                 /* a de-escaped text value is wanted, so supply it */
1152                 _state->tresult = cstring_to_text(token);
1153                 /* make sure the next call to get_scalar doesn't overwrite it */
1154                 _state->next_scalar = false;
1155         }
1156 }
1157
1158 Datum
1159 jsonb_extract_path(PG_FUNCTION_ARGS)
1160 {
1161         return get_jsonb_path_all(fcinfo, false);
1162 }
1163
1164 Datum
1165 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1166 {
1167         return get_jsonb_path_all(fcinfo, true);
1168 }
1169
1170 static Datum
1171 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1172 {
1173         Jsonb      *jb = PG_GETARG_JSONB(0);
1174         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
1175         Jsonb      *res;
1176         Datum      *pathtext;
1177         bool       *pathnulls;
1178         int                     npath;
1179         int                     i;
1180         bool            have_object = false,
1181                                 have_array = false;
1182         JsonbValue *jbvp = NULL;
1183         JsonbValue      tv;
1184         JsonbContainer *container;
1185
1186         /*
1187          * If the array contains any null elements, return NULL, on the grounds
1188          * that you'd have gotten NULL if any RHS value were NULL in a nested
1189          * series of applications of the -> operator.  (Note: because we also
1190          * return NULL for error cases such as no-such-field, this is true
1191          * regardless of the contents of the rest of the array.)
1192          */
1193         if (array_contains_nulls(path))
1194                 PG_RETURN_NULL();
1195
1196         deconstruct_array(path, TEXTOID, -1, false, 'i',
1197                                           &pathtext, &pathnulls, &npath);
1198
1199         /* Identify whether we have object, array, or scalar at top-level */
1200         container = &jb->root;
1201
1202         if (JB_ROOT_IS_OBJECT(jb))
1203                 have_object = true;
1204         else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1205                 have_array = true;
1206         else
1207         {
1208                 Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
1209                 /* Extract the scalar value, if it is what we'll return */
1210                 if (npath <= 0)
1211                         jbvp = getIthJsonbValueFromContainer(container, 0);
1212         }
1213
1214         /*
1215          * If the array is empty, return the entire LHS object, on the grounds
1216          * that we should do zero field or element extractions.  For the
1217          * non-scalar case we can just hand back the object without much work. For
1218          * the scalar case, fall through and deal with the value below the loop.
1219          * (This inconsistency arises because there's no easy way to generate a
1220          * JsonbValue directly for root-level containers.)
1221          */
1222         if (npath <= 0 && jbvp == NULL)
1223         {
1224                 if (as_text)
1225                 {
1226                         PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1227                                                                                                                         container,
1228                                                                                                                         VARSIZE(jb))));
1229                 }
1230                 else
1231                 {
1232                         /* not text mode - just hand back the jsonb */
1233                         PG_RETURN_JSONB(jb);
1234                 }
1235         }
1236
1237         for (i = 0; i < npath; i++)
1238         {
1239                 if (have_object)
1240                 {
1241                         jbvp = findJsonbValueFromContainerLen(container,
1242                                                                                                   JB_FOBJECT,
1243                                                                                                   VARDATA_ANY(pathtext[i]),
1244                                                                                          VARSIZE_ANY_EXHDR(pathtext[i]));
1245                 }
1246                 else if (have_array)
1247                 {
1248                         long            lindex;
1249                         uint32          index;
1250                         char       *indextext = TextDatumGetCString(pathtext[i]);
1251                         char       *endptr;
1252
1253                         errno = 0;
1254                         lindex = strtol(indextext, &endptr, 10);
1255                         if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1256                                 lindex > INT_MAX || lindex < INT_MIN)
1257                                 PG_RETURN_NULL();
1258
1259                         if (lindex >= 0)
1260                         {
1261                                 index = (uint32) lindex;
1262                         }
1263                         else
1264                         {
1265                                 /* Handle negative subscript */
1266                                 uint32          nelements;
1267
1268                                 /* Container must be array, but make sure */
1269                                 if (!JsonContainerIsArray(container))
1270                                         elog(ERROR, "not a jsonb array");
1271
1272                                 nelements = JsonContainerSize(container);
1273
1274                                 if (-lindex > nelements)
1275                                         PG_RETURN_NULL();
1276                                 else
1277                                         index = nelements + lindex;
1278                         }
1279
1280                         jbvp = getIthJsonbValueFromContainer(container, index);
1281                 }
1282                 else
1283                 {
1284                         /* scalar, extraction yields a null */
1285                         PG_RETURN_NULL();
1286                 }
1287
1288                 if (jbvp == NULL)
1289                         PG_RETURN_NULL();
1290                 else if (i == npath - 1)
1291                         break;
1292
1293                 if (jbvp->type == jbvBinary)
1294                 {
1295                         JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1296                         JsonbIteratorToken r;
1297
1298                         r = JsonbIteratorNext(&it, &tv, true);
1299                         container = (JsonbContainer *) jbvp->val.binary.data;
1300                         have_object = r == WJB_BEGIN_OBJECT;
1301                         have_array = r == WJB_BEGIN_ARRAY;
1302                 }
1303                 else
1304                 {
1305                         have_object = jbvp->type == jbvObject;
1306                         have_array = jbvp->type == jbvArray;
1307                 }
1308         }
1309
1310         if (as_text)
1311         {
1312                 /* special-case outputs for string and null values */
1313                 if (jbvp->type == jbvString)
1314                         PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1315                                                                                                           jbvp->val.string.len));
1316                 if (jbvp->type == jbvNull)
1317                         PG_RETURN_NULL();
1318         }
1319
1320         res = JsonbValueToJsonb(jbvp);
1321
1322         if (as_text)
1323         {
1324                 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1325                                                                                                                 &res->root,
1326                                                                                                                 VARSIZE(res))));
1327         }
1328         else
1329         {
1330                 /* not text mode - just hand back the jsonb */
1331                 PG_RETURN_JSONB(res);
1332         }
1333 }
1334
1335 /*
1336  * SQL function json_array_length(json) -> int
1337  */
1338 Datum
1339 json_array_length(PG_FUNCTION_ARGS)
1340 {
1341         text       *json = PG_GETARG_TEXT_P(0);
1342         AlenState  *state;
1343         JsonLexContext *lex;
1344         JsonSemAction *sem;
1345
1346         lex = makeJsonLexContext(json, false);
1347         state = palloc0(sizeof(AlenState));
1348         sem = palloc0(sizeof(JsonSemAction));
1349
1350         /* palloc0 does this for us */
1351 #if 0
1352         state->count = 0;
1353 #endif
1354         state->lex = lex;
1355
1356         sem->semstate = (void *) state;
1357         sem->object_start = alen_object_start;
1358         sem->scalar = alen_scalar;
1359         sem->array_element_start = alen_array_element_start;
1360
1361         pg_parse_json(lex, sem);
1362
1363         PG_RETURN_INT32(state->count);
1364 }
1365
1366 Datum
1367 jsonb_array_length(PG_FUNCTION_ARGS)
1368 {
1369         Jsonb      *jb = PG_GETARG_JSONB(0);
1370
1371         if (JB_ROOT_IS_SCALAR(jb))
1372                 ereport(ERROR,
1373                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1374                                  errmsg("cannot get array length of a scalar")));
1375         else if (!JB_ROOT_IS_ARRAY(jb))
1376                 ereport(ERROR,
1377                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1378                                  errmsg("cannot get array length of a non-array")));
1379
1380         PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1381 }
1382
1383 /*
1384  * These next two checks ensure that the json is an array (since it can't be
1385  * a scalar or an object).
1386  */
1387
1388 static void
1389 alen_object_start(void *state)
1390 {
1391         AlenState  *_state = (AlenState *) state;
1392
1393         /* json structure check */
1394         if (_state->lex->lex_level == 0)
1395                 ereport(ERROR,
1396                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1397                                  errmsg("cannot get array length of a non-array")));
1398 }
1399
1400 static void
1401 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1402 {
1403         AlenState  *_state = (AlenState *) state;
1404
1405         /* json structure check */
1406         if (_state->lex->lex_level == 0)
1407                 ereport(ERROR,
1408                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1409                                  errmsg("cannot get array length of a scalar")));
1410 }
1411
1412 static void
1413 alen_array_element_start(void *state, bool isnull)
1414 {
1415         AlenState  *_state = (AlenState *) state;
1416
1417         /* just count up all the level 1 elements */
1418         if (_state->lex->lex_level == 1)
1419                 _state->count++;
1420 }
1421
1422 /*
1423  * SQL function json_each and json_each_text
1424  *
1425  * decompose a json object into key value pairs.
1426  *
1427  * Unlike json_object_keys() these SRFs operate in materialize mode,
1428  * stashing results into a Tuplestore object as they go.
1429  * The construction of tuples is done using a temporary memory context
1430  * that is cleared out after each tuple is built.
1431  */
1432 Datum
1433 json_each(PG_FUNCTION_ARGS)
1434 {
1435         return each_worker(fcinfo, false);
1436 }
1437
1438 Datum
1439 jsonb_each(PG_FUNCTION_ARGS)
1440 {
1441         return each_worker_jsonb(fcinfo, "jsonb_each", false);
1442 }
1443
1444 Datum
1445 json_each_text(PG_FUNCTION_ARGS)
1446 {
1447         return each_worker(fcinfo, true);
1448 }
1449
1450 Datum
1451 jsonb_each_text(PG_FUNCTION_ARGS)
1452 {
1453         return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1454 }
1455
1456 static Datum
1457 each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1458 {
1459         Jsonb      *jb = PG_GETARG_JSONB(0);
1460         ReturnSetInfo *rsi;
1461         Tuplestorestate *tuple_store;
1462         TupleDesc       tupdesc;
1463         TupleDesc       ret_tdesc;
1464         MemoryContext old_cxt,
1465                                 tmp_cxt;
1466         bool            skipNested = false;
1467         JsonbIterator *it;
1468         JsonbValue      v;
1469         JsonbIteratorToken r;
1470
1471         if (!JB_ROOT_IS_OBJECT(jb))
1472                 ereport(ERROR,
1473                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1474                                  errmsg("cannot call %s on a non-object",
1475                                                 funcname)));
1476
1477         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1478
1479         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1480                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1481                 rsi->expectedDesc == NULL)
1482                 ereport(ERROR,
1483                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1484                                  errmsg("set-valued function called in context that "
1485                                                 "cannot accept a set")));
1486
1487         rsi->returnMode = SFRM_Materialize;
1488
1489         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1490                 ereport(ERROR,
1491                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1492                                  errmsg("function returning record called in context "
1493                                                 "that cannot accept type record")));
1494
1495         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1496
1497         ret_tdesc = CreateTupleDescCopy(tupdesc);
1498         BlessTupleDesc(ret_tdesc);
1499         tuple_store =
1500                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1501                                                           false, work_mem);
1502
1503         MemoryContextSwitchTo(old_cxt);
1504
1505         tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1506                                                                         "jsonb_each temporary cxt",
1507                                                                         ALLOCSET_DEFAULT_SIZES);
1508
1509         it = JsonbIteratorInit(&jb->root);
1510
1511         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1512         {
1513                 skipNested = true;
1514
1515                 if (r == WJB_KEY)
1516                 {
1517                         text       *key;
1518                         HeapTuple       tuple;
1519                         Datum           values[2];
1520                         bool            nulls[2] = {false, false};
1521
1522                         /* Use the tmp context so we can clean up after each tuple is done */
1523                         old_cxt = MemoryContextSwitchTo(tmp_cxt);
1524
1525                         key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1526
1527                         /*
1528                          * The next thing the iterator fetches should be the value, no
1529                          * matter what shape it is.
1530                          */
1531                         r = JsonbIteratorNext(&it, &v, skipNested);
1532
1533                         values[0] = PointerGetDatum(key);
1534
1535                         if (as_text)
1536                         {
1537                                 if (v.type == jbvNull)
1538                                 {
1539                                         /* a json null is an sql null in text mode */
1540                                         nulls[1] = true;
1541                                         values[1] = (Datum) NULL;
1542                                 }
1543                                 else
1544                                 {
1545                                         text       *sv;
1546
1547                                         if (v.type == jbvString)
1548                                         {
1549                                                 /* In text mode, scalar strings should be dequoted */
1550                                                 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1551                                         }
1552                                         else
1553                                         {
1554                                                 /* Turn anything else into a json string */
1555                                                 StringInfo      jtext = makeStringInfo();
1556                                                 Jsonb      *jb = JsonbValueToJsonb(&v);
1557
1558                                                 (void) JsonbToCString(jtext, &jb->root, 0);
1559                                                 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1560                                         }
1561
1562                                         values[1] = PointerGetDatum(sv);
1563                                 }
1564                         }
1565                         else
1566                         {
1567                                 /* Not in text mode, just return the Jsonb */
1568                                 Jsonb      *val = JsonbValueToJsonb(&v);
1569
1570                                 values[1] = PointerGetDatum(val);
1571                         }
1572
1573                         tuple = heap_form_tuple(ret_tdesc, values, nulls);
1574
1575                         tuplestore_puttuple(tuple_store, tuple);
1576
1577                         /* clean up and switch back */
1578                         MemoryContextSwitchTo(old_cxt);
1579                         MemoryContextReset(tmp_cxt);
1580                 }
1581         }
1582
1583         MemoryContextDelete(tmp_cxt);
1584
1585         rsi->setResult = tuple_store;
1586         rsi->setDesc = ret_tdesc;
1587
1588         PG_RETURN_NULL();
1589 }
1590
1591
1592 static Datum
1593 each_worker(FunctionCallInfo fcinfo, bool as_text)
1594 {
1595         text       *json = PG_GETARG_TEXT_P(0);
1596         JsonLexContext *lex;
1597         JsonSemAction *sem;
1598         ReturnSetInfo *rsi;
1599         MemoryContext old_cxt;
1600         TupleDesc       tupdesc;
1601         EachState  *state;
1602
1603         lex = makeJsonLexContext(json, true);
1604         state = palloc0(sizeof(EachState));
1605         sem = palloc0(sizeof(JsonSemAction));
1606
1607         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1608
1609         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1610                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1611                 rsi->expectedDesc == NULL)
1612                 ereport(ERROR,
1613                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1614                                  errmsg("set-valued function called in context that "
1615                                                 "cannot accept a set")));
1616
1617         rsi->returnMode = SFRM_Materialize;
1618
1619         (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1620
1621         /* make these in a sufficiently long-lived memory context */
1622         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1623
1624         state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1625         BlessTupleDesc(state->ret_tdesc);
1626         state->tuple_store =
1627                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1628                                                           false, work_mem);
1629
1630         MemoryContextSwitchTo(old_cxt);
1631
1632         sem->semstate = (void *) state;
1633         sem->array_start = each_array_start;
1634         sem->scalar = each_scalar;
1635         sem->object_field_start = each_object_field_start;
1636         sem->object_field_end = each_object_field_end;
1637
1638         state->normalize_results = as_text;
1639         state->next_scalar = false;
1640         state->lex = lex;
1641         state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1642                                                                                    "json_each temporary cxt",
1643                                                                                    ALLOCSET_DEFAULT_SIZES);
1644
1645         pg_parse_json(lex, sem);
1646
1647         MemoryContextDelete(state->tmp_cxt);
1648
1649         rsi->setResult = state->tuple_store;
1650         rsi->setDesc = state->ret_tdesc;
1651
1652         PG_RETURN_NULL();
1653 }
1654
1655
1656 static void
1657 each_object_field_start(void *state, char *fname, bool isnull)
1658 {
1659         EachState  *_state = (EachState *) state;
1660
1661         /* save a pointer to where the value starts */
1662         if (_state->lex->lex_level == 1)
1663         {
1664                 /*
1665                  * next_scalar will be reset in the object_field_end handler, and
1666                  * since we know the value is a scalar there is no danger of it being
1667                  * on while recursing down the tree.
1668                  */
1669                 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1670                         _state->next_scalar = true;
1671                 else
1672                         _state->result_start = _state->lex->token_start;
1673         }
1674 }
1675
1676 static void
1677 each_object_field_end(void *state, char *fname, bool isnull)
1678 {
1679         EachState  *_state = (EachState *) state;
1680         MemoryContext old_cxt;
1681         int                     len;
1682         text       *val;
1683         HeapTuple       tuple;
1684         Datum           values[2];
1685         bool            nulls[2] = {false, false};
1686
1687         /* skip over nested objects */
1688         if (_state->lex->lex_level != 1)
1689                 return;
1690
1691         /* use the tmp context so we can clean up after each tuple is done */
1692         old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1693
1694         values[0] = CStringGetTextDatum(fname);
1695
1696         if (isnull && _state->normalize_results)
1697         {
1698                 nulls[1] = true;
1699                 values[1] = (Datum) 0;
1700         }
1701         else if (_state->next_scalar)
1702         {
1703                 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1704                 _state->next_scalar = false;
1705         }
1706         else
1707         {
1708                 len = _state->lex->prev_token_terminator - _state->result_start;
1709                 val = cstring_to_text_with_len(_state->result_start, len);
1710                 values[1] = PointerGetDatum(val);
1711         }
1712
1713         tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1714
1715         tuplestore_puttuple(_state->tuple_store, tuple);
1716
1717         /* clean up and switch back */
1718         MemoryContextSwitchTo(old_cxt);
1719         MemoryContextReset(_state->tmp_cxt);
1720 }
1721
1722 static void
1723 each_array_start(void *state)
1724 {
1725         EachState  *_state = (EachState *) state;
1726
1727         /* json structure check */
1728         if (_state->lex->lex_level == 0)
1729                 ereport(ERROR,
1730                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1731                                  errmsg("cannot deconstruct an array as an object")));
1732 }
1733
1734 static void
1735 each_scalar(void *state, char *token, JsonTokenType tokentype)
1736 {
1737         EachState  *_state = (EachState *) state;
1738
1739         /* json structure check */
1740         if (_state->lex->lex_level == 0)
1741                 ereport(ERROR,
1742                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1743                                  errmsg("cannot deconstruct a scalar")));
1744
1745         /* supply de-escaped value if required */
1746         if (_state->next_scalar)
1747                 _state->normalized_scalar = token;
1748 }
1749
1750 /*
1751  * SQL functions json_array_elements and json_array_elements_text
1752  *
1753  * get the elements from a json array
1754  *
1755  * a lot of this processing is similar to the json_each* functions
1756  */
1757
1758 Datum
1759 jsonb_array_elements(PG_FUNCTION_ARGS)
1760 {
1761         return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1762 }
1763
1764 Datum
1765 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1766 {
1767         return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1768 }
1769
1770 static Datum
1771 elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
1772                                           bool as_text)
1773 {
1774         Jsonb      *jb = PG_GETARG_JSONB(0);
1775         ReturnSetInfo *rsi;
1776         Tuplestorestate *tuple_store;
1777         TupleDesc       tupdesc;
1778         TupleDesc       ret_tdesc;
1779         MemoryContext old_cxt,
1780                                 tmp_cxt;
1781         bool            skipNested = false;
1782         JsonbIterator *it;
1783         JsonbValue      v;
1784         JsonbIteratorToken r;
1785
1786         if (JB_ROOT_IS_SCALAR(jb))
1787                 ereport(ERROR,
1788                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1789                                  errmsg("cannot extract elements from a scalar")));
1790         else if (!JB_ROOT_IS_ARRAY(jb))
1791                 ereport(ERROR,
1792                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1793                                  errmsg("cannot extract elements from an object")));
1794
1795         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1796
1797         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1798                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1799                 rsi->expectedDesc == NULL)
1800                 ereport(ERROR,
1801                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1802                                  errmsg("set-valued function called in context that "
1803                                                 "cannot accept a set")));
1804
1805         rsi->returnMode = SFRM_Materialize;
1806
1807         /* it's a simple type, so don't use get_call_result_type() */
1808         tupdesc = rsi->expectedDesc;
1809
1810         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1811
1812         ret_tdesc = CreateTupleDescCopy(tupdesc);
1813         BlessTupleDesc(ret_tdesc);
1814         tuple_store =
1815                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1816                                                           false, work_mem);
1817
1818         MemoryContextSwitchTo(old_cxt);
1819
1820         tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1821                                                                         "jsonb_array_elements temporary cxt",
1822                                                                         ALLOCSET_DEFAULT_SIZES);
1823
1824         it = JsonbIteratorInit(&jb->root);
1825
1826         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1827         {
1828                 skipNested = true;
1829
1830                 if (r == WJB_ELEM)
1831                 {
1832                         HeapTuple       tuple;
1833                         Datum           values[1];
1834                         bool            nulls[1] = {false};
1835
1836                         /* use the tmp context so we can clean up after each tuple is done */
1837                         old_cxt = MemoryContextSwitchTo(tmp_cxt);
1838
1839                         if (!as_text)
1840                         {
1841                                 Jsonb      *val = JsonbValueToJsonb(&v);
1842
1843                                 values[0] = PointerGetDatum(val);
1844                         }
1845                         else
1846                         {
1847                                 if (v.type == jbvNull)
1848                                 {
1849                                         /* a json null is an sql null in text mode */
1850                                         nulls[0] = true;
1851                                         values[0] = (Datum) NULL;
1852                                 }
1853                                 else
1854                                 {
1855                                         text       *sv;
1856
1857                                         if (v.type == jbvString)
1858                                         {
1859                                                 /* in text mode scalar strings should be dequoted */
1860                                                 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1861                                         }
1862                                         else
1863                                         {
1864                                                 /* turn anything else into a json string */
1865                                                 StringInfo      jtext = makeStringInfo();
1866                                                 Jsonb      *jb = JsonbValueToJsonb(&v);
1867
1868                                                 (void) JsonbToCString(jtext, &jb->root, 0);
1869                                                 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1870                                         }
1871
1872                                         values[0] = PointerGetDatum(sv);
1873                                 }
1874                         }
1875
1876                         tuple = heap_form_tuple(ret_tdesc, values, nulls);
1877
1878                         tuplestore_puttuple(tuple_store, tuple);
1879
1880                         /* clean up and switch back */
1881                         MemoryContextSwitchTo(old_cxt);
1882                         MemoryContextReset(tmp_cxt);
1883                 }
1884         }
1885
1886         MemoryContextDelete(tmp_cxt);
1887
1888         rsi->setResult = tuple_store;
1889         rsi->setDesc = ret_tdesc;
1890
1891         PG_RETURN_NULL();
1892 }
1893
1894 Datum
1895 json_array_elements(PG_FUNCTION_ARGS)
1896 {
1897         return elements_worker(fcinfo, "json_array_elements", false);
1898 }
1899
1900 Datum
1901 json_array_elements_text(PG_FUNCTION_ARGS)
1902 {
1903         return elements_worker(fcinfo, "json_array_elements_text", true);
1904 }
1905
1906 static Datum
1907 elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
1908 {
1909         text       *json = PG_GETARG_TEXT_P(0);
1910
1911         /* elements only needs escaped strings when as_text */
1912         JsonLexContext *lex = makeJsonLexContext(json, as_text);
1913         JsonSemAction *sem;
1914         ReturnSetInfo *rsi;
1915         MemoryContext old_cxt;
1916         TupleDesc       tupdesc;
1917         ElementsState *state;
1918
1919         state = palloc0(sizeof(ElementsState));
1920         sem = palloc0(sizeof(JsonSemAction));
1921
1922         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1923
1924         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1925                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1926                 rsi->expectedDesc == NULL)
1927                 ereport(ERROR,
1928                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1929                                  errmsg("set-valued function called in context that "
1930                                                 "cannot accept a set")));
1931
1932         rsi->returnMode = SFRM_Materialize;
1933
1934         /* it's a simple type, so don't use get_call_result_type() */
1935         tupdesc = rsi->expectedDesc;
1936
1937         /* make these in a sufficiently long-lived memory context */
1938         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1939
1940         state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1941         BlessTupleDesc(state->ret_tdesc);
1942         state->tuple_store =
1943                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1944                                                           false, work_mem);
1945
1946         MemoryContextSwitchTo(old_cxt);
1947
1948         sem->semstate = (void *) state;
1949         sem->object_start = elements_object_start;
1950         sem->scalar = elements_scalar;
1951         sem->array_element_start = elements_array_element_start;
1952         sem->array_element_end = elements_array_element_end;
1953
1954         state->function_name = funcname;
1955         state->normalize_results = as_text;
1956         state->next_scalar = false;
1957         state->lex = lex;
1958         state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1959                                                                                  "json_array_elements temporary cxt",
1960                                                                                    ALLOCSET_DEFAULT_SIZES);
1961
1962         pg_parse_json(lex, sem);
1963
1964         MemoryContextDelete(state->tmp_cxt);
1965
1966         rsi->setResult = state->tuple_store;
1967         rsi->setDesc = state->ret_tdesc;
1968
1969         PG_RETURN_NULL();
1970 }
1971
1972 static void
1973 elements_array_element_start(void *state, bool isnull)
1974 {
1975         ElementsState *_state = (ElementsState *) state;
1976
1977         /* save a pointer to where the value starts */
1978         if (_state->lex->lex_level == 1)
1979         {
1980                 /*
1981                  * next_scalar will be reset in the array_element_end handler, and
1982                  * since we know the value is a scalar there is no danger of it being
1983                  * on while recursing down the tree.
1984                  */
1985                 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1986                         _state->next_scalar = true;
1987                 else
1988                         _state->result_start = _state->lex->token_start;
1989         }
1990 }
1991
1992 static void
1993 elements_array_element_end(void *state, bool isnull)
1994 {
1995         ElementsState *_state = (ElementsState *) state;
1996         MemoryContext old_cxt;
1997         int                     len;
1998         text       *val;
1999         HeapTuple       tuple;
2000         Datum           values[1];
2001         bool            nulls[1] = {false};
2002
2003         /* skip over nested objects */
2004         if (_state->lex->lex_level != 1)
2005                 return;
2006
2007         /* use the tmp context so we can clean up after each tuple is done */
2008         old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2009
2010         if (isnull && _state->normalize_results)
2011         {
2012                 nulls[0] = true;
2013                 values[0] = (Datum) NULL;
2014         }
2015         else if (_state->next_scalar)
2016         {
2017                 values[0] = CStringGetTextDatum(_state->normalized_scalar);
2018                 _state->next_scalar = false;
2019         }
2020         else
2021         {
2022                 len = _state->lex->prev_token_terminator - _state->result_start;
2023                 val = cstring_to_text_with_len(_state->result_start, len);
2024                 values[0] = PointerGetDatum(val);
2025         }
2026
2027         tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2028
2029         tuplestore_puttuple(_state->tuple_store, tuple);
2030
2031         /* clean up and switch back */
2032         MemoryContextSwitchTo(old_cxt);
2033         MemoryContextReset(_state->tmp_cxt);
2034 }
2035
2036 static void
2037 elements_object_start(void *state)
2038 {
2039         ElementsState *_state = (ElementsState *) state;
2040
2041         /* json structure check */
2042         if (_state->lex->lex_level == 0)
2043                 ereport(ERROR,
2044                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2045                                  errmsg("cannot call %s on a non-array",
2046                                                 _state->function_name)));
2047 }
2048
2049 static void
2050 elements_scalar(void *state, char *token, JsonTokenType tokentype)
2051 {
2052         ElementsState *_state = (ElementsState *) state;
2053
2054         /* json structure check */
2055         if (_state->lex->lex_level == 0)
2056                 ereport(ERROR,
2057                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2058                                  errmsg("cannot call %s on a scalar",
2059                                                 _state->function_name)));
2060
2061         /* supply de-escaped value if required */
2062         if (_state->next_scalar)
2063                 _state->normalized_scalar = token;
2064 }
2065
2066 /*
2067  * SQL function json_populate_record
2068  *
2069  * set fields in a record from the argument json
2070  *
2071  * Code adapted shamelessly from hstore's populate_record
2072  * which is in turn partly adapted from record_out.
2073  *
2074  * The json is decomposed into a hash table, in which each
2075  * field in the record is then looked up by name. For jsonb
2076  * we fetch the values direct from the object.
2077  */
2078 Datum
2079 jsonb_populate_record(PG_FUNCTION_ARGS)
2080 {
2081         return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2082 }
2083
2084 Datum
2085 jsonb_to_record(PG_FUNCTION_ARGS)
2086 {
2087         return populate_record_worker(fcinfo, "jsonb_to_record", false);
2088 }
2089
2090 Datum
2091 json_populate_record(PG_FUNCTION_ARGS)
2092 {
2093         return populate_record_worker(fcinfo, "json_populate_record", true);
2094 }
2095
2096 Datum
2097 json_to_record(PG_FUNCTION_ARGS)
2098 {
2099         return populate_record_worker(fcinfo, "json_to_record", false);
2100 }
2101
2102 static Datum
2103 populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
2104                                            bool have_record_arg)
2105 {
2106         int                     json_arg_num = have_record_arg ? 1 : 0;
2107         Oid                     jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2108         text       *json;
2109         Jsonb      *jb = NULL;
2110         HTAB       *json_hash = NULL;
2111         HeapTupleHeader rec = NULL;
2112         Oid                     tupType = InvalidOid;
2113         int32           tupTypmod = -1;
2114         TupleDesc       tupdesc;
2115         HeapTupleData tuple;
2116         HeapTuple       rettuple;
2117         RecordIOData *my_extra;
2118         int                     ncolumns;
2119         int                     i;
2120         Datum      *values;
2121         bool       *nulls;
2122
2123         Assert(jtype == JSONOID || jtype == JSONBOID);
2124
2125         if (have_record_arg)
2126         {
2127                 Oid                     argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2128
2129                 if (!type_is_rowtype(argtype))
2130                         ereport(ERROR,
2131                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2132                                          errmsg("first argument of %s must be a row type",
2133                                                         funcname)));
2134
2135                 if (PG_ARGISNULL(0))
2136                 {
2137                         if (PG_ARGISNULL(1))
2138                                 PG_RETURN_NULL();
2139
2140                         /*
2141                          * have no tuple to look at, so the only source of type info is
2142                          * the argtype. The lookup_rowtype_tupdesc call below will error
2143                          * out if we don't have a known composite type oid here.
2144                          */
2145                         tupType = argtype;
2146                         tupTypmod = -1;
2147                 }
2148                 else
2149                 {
2150                         rec = PG_GETARG_HEAPTUPLEHEADER(0);
2151
2152                         if (PG_ARGISNULL(1))
2153                                 PG_RETURN_POINTER(rec);
2154
2155                         /* Extract type info from the tuple itself */
2156                         tupType = HeapTupleHeaderGetTypeId(rec);
2157                         tupTypmod = HeapTupleHeaderGetTypMod(rec);
2158                 }
2159
2160                 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2161         }
2162         else
2163         {
2164                 /* json{b}_to_record case */
2165                 if (PG_ARGISNULL(0))
2166                         PG_RETURN_NULL();
2167
2168                 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2169                         ereport(ERROR,
2170                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2171                                          errmsg("function returning record called in context "
2172                                                         "that cannot accept type record"),
2173                                          errhint("Try calling the function in the FROM clause "
2174                                                          "using a column definition list.")));
2175         }
2176
2177         if (jtype == JSONOID)
2178         {
2179                 /* just get the text */
2180                 json = PG_GETARG_TEXT_P(json_arg_num);
2181
2182                 json_hash = get_json_object_as_hash(json, funcname);
2183
2184                 /*
2185                  * if the input json is empty, we can only skip the rest if we were
2186                  * passed in a non-null record, since otherwise there may be issues
2187                  * with domain nulls.
2188                  */
2189                 if (hash_get_num_entries(json_hash) == 0 && rec)
2190                 {
2191                         hash_destroy(json_hash);
2192                         ReleaseTupleDesc(tupdesc);
2193                         PG_RETURN_POINTER(rec);
2194                 }
2195         }
2196         else
2197         {
2198                 jb = PG_GETARG_JSONB(json_arg_num);
2199
2200                 /* same logic as for json */
2201                 if (JB_ROOT_COUNT(jb) == 0 && rec)
2202                 {
2203                         ReleaseTupleDesc(tupdesc);
2204                         PG_RETURN_POINTER(rec);
2205                 }
2206         }
2207
2208         ncolumns = tupdesc->natts;
2209
2210         if (rec)
2211         {
2212                 /* Build a temporary HeapTuple control structure */
2213                 tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2214                 ItemPointerSetInvalid(&(tuple.t_self));
2215                 tuple.t_tableOid = InvalidOid;
2216                 tuple.t_data = rec;
2217         }
2218
2219         /*
2220          * We arrange to look up the needed I/O info just once per series of
2221          * calls, assuming the record type doesn't change underneath us.
2222          */
2223         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2224         if (my_extra == NULL ||
2225                 my_extra->ncolumns != ncolumns)
2226         {
2227                 fcinfo->flinfo->fn_extra =
2228                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2229                                                            offsetof(RecordIOData, columns) +
2230                                                            ncolumns * sizeof(ColumnIOData));
2231                 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2232                 my_extra->record_type = InvalidOid;
2233                 my_extra->record_typmod = 0;
2234                 my_extra->ncolumns = ncolumns;
2235                 MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2236         }
2237
2238         if (have_record_arg && (my_extra->record_type != tupType ||
2239                                                         my_extra->record_typmod != tupTypmod))
2240         {
2241                 MemSet(my_extra, 0,
2242                            offsetof(RecordIOData, columns) +
2243                            ncolumns * sizeof(ColumnIOData));
2244                 my_extra->record_type = tupType;
2245                 my_extra->record_typmod = tupTypmod;
2246                 my_extra->ncolumns = ncolumns;
2247         }
2248
2249         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2250         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2251
2252         if (rec)
2253         {
2254                 /* Break down the tuple into fields */
2255                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2256         }
2257         else
2258         {
2259                 for (i = 0; i < ncolumns; ++i)
2260                 {
2261                         values[i] = (Datum) 0;
2262                         nulls[i] = true;
2263                 }
2264         }
2265
2266         for (i = 0; i < ncolumns; ++i)
2267         {
2268                 ColumnIOData *column_info = &my_extra->columns[i];
2269                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2270                 JsonbValue *v = NULL;
2271                 JsonHashEntry *hashentry = NULL;
2272
2273                 /* Ignore dropped columns in datatype */
2274                 if (tupdesc->attrs[i]->attisdropped)
2275                 {
2276                         nulls[i] = true;
2277                         continue;
2278                 }
2279
2280                 if (jtype == JSONOID)
2281                 {
2282                         hashentry = hash_search(json_hash,
2283                                                                         NameStr(tupdesc->attrs[i]->attname),
2284                                                                         HASH_FIND, NULL);
2285                 }
2286                 else
2287                 {
2288                         char       *key = NameStr(tupdesc->attrs[i]->attname);
2289
2290                         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
2291                                                                                            strlen(key));
2292                 }
2293
2294                 /*
2295                  * we can't just skip here if the key wasn't found since we might have
2296                  * a domain to deal with. If we were passed in a non-null record
2297                  * datum, we assume that the existing values are valid (if they're
2298                  * not, then it's not our fault), but if we were passed in a null,
2299                  * then every field which we don't populate needs to be run through
2300                  * the input function just in case it's a domain type.
2301                  */
2302                 if (((jtype == JSONOID && hashentry == NULL) ||
2303                          (jtype == JSONBOID && v == NULL)) && rec)
2304                         continue;
2305
2306                 /*
2307                  * Prepare to convert the column value from text
2308                  */
2309                 if (column_info->column_type != column_type)
2310                 {
2311                         getTypeInputInfo(column_type,
2312                                                          &column_info->typiofunc,
2313                                                          &column_info->typioparam);
2314                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2315                                                   fcinfo->flinfo->fn_mcxt);
2316                         column_info->column_type = column_type;
2317                 }
2318                 if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2319                         (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2320                 {
2321                         /*
2322                          * need InputFunctionCall to happen even for nulls, so that domain
2323                          * checks are done
2324                          */
2325                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2326                                                                                   column_info->typioparam,
2327                                                                                   tupdesc->attrs[i]->atttypmod);
2328                         nulls[i] = true;
2329                 }
2330                 else
2331                 {
2332                         char       *s = NULL;
2333
2334                         if (jtype == JSONOID)
2335                         {
2336                                 /* already done the hard work in the json case */
2337                                 s = hashentry->val;
2338                         }
2339                         else
2340                         {
2341                                 if (v->type == jbvString)
2342                                         s = pnstrdup(v->val.string.val, v->val.string.len);
2343                                 else if (v->type == jbvBool)
2344                                         s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2345                                 else if (v->type == jbvNumeric)
2346                                         s = DatumGetCString(DirectFunctionCall1(numeric_out,
2347                                                                                    PointerGetDatum(v->val.numeric)));
2348                                 else if (v->type == jbvBinary)
2349                                         s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2350                                 else
2351                                         elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2352                         }
2353
2354                         values[i] = InputFunctionCall(&column_info->proc, s,
2355                                                                                   column_info->typioparam,
2356                                                                                   tupdesc->attrs[i]->atttypmod);
2357                         nulls[i] = false;
2358                 }
2359         }
2360
2361         rettuple = heap_form_tuple(tupdesc, values, nulls);
2362
2363         ReleaseTupleDesc(tupdesc);
2364
2365         if (json_hash)
2366                 hash_destroy(json_hash);
2367
2368         PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
2369 }
2370
2371 /*
2372  * get_json_object_as_hash
2373  *
2374  * decompose a json object into a hash table.
2375  */
2376 static HTAB *
2377 get_json_object_as_hash(text *json, const char *funcname)
2378 {
2379         HASHCTL         ctl;
2380         HTAB       *tab;
2381         JHashState *state;
2382         JsonLexContext *lex = makeJsonLexContext(json, true);
2383         JsonSemAction *sem;
2384
2385         memset(&ctl, 0, sizeof(ctl));
2386         ctl.keysize = NAMEDATALEN;
2387         ctl.entrysize = sizeof(JsonHashEntry);
2388         ctl.hcxt = CurrentMemoryContext;
2389         tab = hash_create("json object hashtable",
2390                                           100,
2391                                           &ctl,
2392                                           HASH_ELEM | HASH_CONTEXT);
2393
2394         state = palloc0(sizeof(JHashState));
2395         sem = palloc0(sizeof(JsonSemAction));
2396
2397         state->function_name = funcname;
2398         state->hash = tab;
2399         state->lex = lex;
2400
2401         sem->semstate = (void *) state;
2402         sem->array_start = hash_array_start;
2403         sem->scalar = hash_scalar;
2404         sem->object_field_start = hash_object_field_start;
2405         sem->object_field_end = hash_object_field_end;
2406
2407         pg_parse_json(lex, sem);
2408
2409         return tab;
2410 }
2411
2412 static void
2413 hash_object_field_start(void *state, char *fname, bool isnull)
2414 {
2415         JHashState *_state = (JHashState *) state;
2416
2417         if (_state->lex->lex_level > 1)
2418                 return;
2419
2420         if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2421                 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2422         {
2423                 /* remember start position of the whole text of the subobject */
2424                 _state->save_json_start = _state->lex->token_start;
2425         }
2426         else
2427         {
2428                 /* must be a scalar */
2429                 _state->save_json_start = NULL;
2430         }
2431 }
2432
2433 static void
2434 hash_object_field_end(void *state, char *fname, bool isnull)
2435 {
2436         JHashState *_state = (JHashState *) state;
2437         JsonHashEntry *hashentry;
2438         bool            found;
2439
2440         /*
2441          * Ignore nested fields.
2442          */
2443         if (_state->lex->lex_level > 1)
2444                 return;
2445
2446         /*
2447          * Ignore field names >= NAMEDATALEN - they can't match a record field.
2448          * (Note: without this test, the hash code would truncate the string at
2449          * NAMEDATALEN-1, and could then match against a similarly-truncated
2450          * record field name.  That would be a reasonable behavior, but this code
2451          * has previously insisted on exact equality, so we keep this behavior.)
2452          */
2453         if (strlen(fname) >= NAMEDATALEN)
2454                 return;
2455
2456         hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2457
2458         /*
2459          * found being true indicates a duplicate. We don't do anything about
2460          * that, a later field with the same name overrides the earlier field.
2461          */
2462
2463         hashentry->isnull = isnull;
2464         if (_state->save_json_start != NULL)
2465         {
2466                 int                     len = _state->lex->prev_token_terminator - _state->save_json_start;
2467                 char       *val = palloc((len + 1) * sizeof(char));
2468
2469                 memcpy(val, _state->save_json_start, len);
2470                 val[len] = '\0';
2471                 hashentry->val = val;
2472         }
2473         else
2474         {
2475                 /* must have had a scalar instead */
2476                 hashentry->val = _state->saved_scalar;
2477         }
2478 }
2479
2480 static void
2481 hash_array_start(void *state)
2482 {
2483         JHashState *_state = (JHashState *) state;
2484
2485         if (_state->lex->lex_level == 0)
2486                 ereport(ERROR,
2487                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2488                            errmsg("cannot call %s on an array", _state->function_name)));
2489 }
2490
2491 static void
2492 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2493 {
2494         JHashState *_state = (JHashState *) state;
2495
2496         if (_state->lex->lex_level == 0)
2497                 ereport(ERROR,
2498                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2499                            errmsg("cannot call %s on a scalar", _state->function_name)));
2500
2501         if (_state->lex->lex_level == 1)
2502                 _state->saved_scalar = token;
2503 }
2504
2505
2506 /*
2507  * SQL function json_populate_recordset
2508  *
2509  * set fields in a set of records from the argument json,
2510  * which must be an array of objects.
2511  *
2512  * similar to json_populate_record, but the tuple-building code
2513  * is pushed down into the semantic action handlers so it's done
2514  * per object in the array.
2515  */
2516 Datum
2517 jsonb_populate_recordset(PG_FUNCTION_ARGS)
2518 {
2519         return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2520 }
2521
2522 Datum
2523 jsonb_to_recordset(PG_FUNCTION_ARGS)
2524 {
2525         return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2526 }
2527
2528 Datum
2529 json_populate_recordset(PG_FUNCTION_ARGS)
2530 {
2531         return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2532 }
2533
2534 Datum
2535 json_to_recordset(PG_FUNCTION_ARGS)
2536 {
2537         return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2538 }
2539
2540 static void
2541 make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
2542 {
2543         Datum      *values;
2544         bool       *nulls;
2545         int                     i;
2546         RecordIOData *my_extra = state->my_extra;
2547         int                     ncolumns = my_extra->ncolumns;
2548         TupleDesc       tupdesc = state->ret_tdesc;
2549         HeapTupleHeader rec = state->rec;
2550         HeapTuple       rettuple;
2551
2552         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2553         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2554
2555         if (state->rec)
2556         {
2557                 HeapTupleData tuple;
2558
2559                 /* Build a temporary HeapTuple control structure */
2560                 tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2561                 ItemPointerSetInvalid(&(tuple.t_self));
2562                 tuple.t_tableOid = InvalidOid;
2563                 tuple.t_data = state->rec;
2564
2565                 /* Break down the tuple into fields */
2566                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2567         }
2568         else
2569         {
2570                 for (i = 0; i < ncolumns; ++i)
2571                 {
2572                         values[i] = (Datum) 0;
2573                         nulls[i] = true;
2574                 }
2575         }
2576
2577         for (i = 0; i < ncolumns; ++i)
2578         {
2579                 ColumnIOData *column_info = &my_extra->columns[i];
2580                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2581                 JsonbValue *v = NULL;
2582                 char       *key;
2583
2584                 /* Ignore dropped columns in datatype */
2585                 if (tupdesc->attrs[i]->attisdropped)
2586                 {
2587                         nulls[i] = true;
2588                         continue;
2589                 }
2590
2591                 key = NameStr(tupdesc->attrs[i]->attname);
2592
2593                 v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
2594                                                                                    key, strlen(key));
2595
2596                 /*
2597                  * We can't just skip here if the key wasn't found since we might have
2598                  * a domain to deal with. If we were passed in a non-null record
2599                  * datum, we assume that the existing values are valid (if they're
2600                  * not, then it's not our fault), but if we were passed in a null,
2601                  * then every field which we don't populate needs to be run through
2602                  * the input function just in case it's a domain type.
2603                  */
2604                 if (v == NULL && rec)
2605                         continue;
2606
2607                 /*
2608                  * Prepare to convert the column value from text
2609                  */
2610                 if (column_info->column_type != column_type)
2611                 {
2612                         getTypeInputInfo(column_type,
2613                                                          &column_info->typiofunc,
2614                                                          &column_info->typioparam);
2615                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2616                                                   state->fn_mcxt);
2617                         column_info->column_type = column_type;
2618                 }
2619                 if (v == NULL || v->type == jbvNull)
2620                 {
2621                         /*
2622                          * Need InputFunctionCall to happen even for nulls, so that domain
2623                          * checks are done
2624                          */
2625                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2626                                                                                   column_info->typioparam,
2627                                                                                   tupdesc->attrs[i]->atttypmod);
2628                         nulls[i] = true;
2629                 }
2630                 else
2631                 {
2632                         char       *s = NULL;
2633
2634                         if (v->type == jbvString)
2635                                 s = pnstrdup(v->val.string.val, v->val.string.len);
2636                         else if (v->type == jbvBool)
2637                                 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2638                         else if (v->type == jbvNumeric)
2639                                 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2640                                                                                    PointerGetDatum(v->val.numeric)));
2641                         else if (v->type == jbvBinary)
2642                                 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2643                         else
2644                                 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
2645
2646                         values[i] = InputFunctionCall(&column_info->proc, s,
2647                                                                                   column_info->typioparam,
2648                                                                                   tupdesc->attrs[i]->atttypmod);
2649                         nulls[i] = false;
2650                 }
2651         }
2652
2653         rettuple = heap_form_tuple(tupdesc, values, nulls);
2654
2655         tuplestore_puttuple(state->tuple_store, rettuple);
2656 }
2657
2658 /*
2659  * common worker for json_populate_recordset() and json_to_recordset()
2660  */
2661 static Datum
2662 populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
2663                                                   bool have_record_arg)
2664 {
2665         int                     json_arg_num = have_record_arg ? 1 : 0;
2666         Oid                     jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2667         ReturnSetInfo *rsi;
2668         MemoryContext old_cxt;
2669         Oid                     tupType;
2670         int32           tupTypmod;
2671         HeapTupleHeader rec;
2672         TupleDesc       tupdesc;
2673         RecordIOData *my_extra;
2674         int                     ncolumns;
2675         PopulateRecordsetState *state;
2676
2677         if (have_record_arg)
2678         {
2679                 Oid                     argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2680
2681                 if (!type_is_rowtype(argtype))
2682                         ereport(ERROR,
2683                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2684                                          errmsg("first argument of %s must be a row type",
2685                                                         funcname)));
2686         }
2687
2688         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2689
2690         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2691                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2692                 rsi->expectedDesc == NULL)
2693                 ereport(ERROR,
2694                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2695                                  errmsg("set-valued function called in context that "
2696                                                 "cannot accept a set")));
2697
2698         rsi->returnMode = SFRM_Materialize;
2699
2700         /*
2701          * get the tupdesc from the result set info - it must be a record type
2702          * because we already checked that arg1 is a record type, or we're in a
2703          * to_record function which returns a setof record.
2704          */
2705         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2706                 ereport(ERROR,
2707                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2708                                  errmsg("function returning record called in context "
2709                                                 "that cannot accept type record")));
2710
2711         /* if the json is null send back an empty set */
2712         if (PG_ARGISNULL(json_arg_num))
2713                 PG_RETURN_NULL();
2714
2715         if (!have_record_arg || PG_ARGISNULL(0))
2716                 rec = NULL;
2717         else
2718                 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2719
2720         tupType = tupdesc->tdtypeid;
2721         tupTypmod = tupdesc->tdtypmod;
2722         ncolumns = tupdesc->natts;
2723
2724         /*
2725          * We arrange to look up the needed I/O info just once per series of
2726          * calls, assuming the record type doesn't change underneath us.
2727          */
2728         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2729         if (my_extra == NULL ||
2730                 my_extra->ncolumns != ncolumns)
2731         {
2732                 fcinfo->flinfo->fn_extra =
2733                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2734                                                            offsetof(RecordIOData, columns) +
2735                                                            ncolumns * sizeof(ColumnIOData));
2736                 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2737                 my_extra->record_type = InvalidOid;
2738                 my_extra->record_typmod = 0;
2739         }
2740
2741         if (my_extra->record_type != tupType ||
2742                 my_extra->record_typmod != tupTypmod)
2743         {
2744                 MemSet(my_extra, 0,
2745                            offsetof(RecordIOData, columns) +
2746                            ncolumns * sizeof(ColumnIOData));
2747                 my_extra->record_type = tupType;
2748                 my_extra->record_typmod = tupTypmod;
2749                 my_extra->ncolumns = ncolumns;
2750         }
2751
2752         state = palloc0(sizeof(PopulateRecordsetState));
2753
2754         /* make these in a sufficiently long-lived memory context */
2755         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2756         state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2757         BlessTupleDesc(state->ret_tdesc);
2758         state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
2759                                                                                            SFRM_Materialize_Random,
2760                                                                                            false, work_mem);
2761         MemoryContextSwitchTo(old_cxt);
2762
2763         state->function_name = funcname;
2764         state->my_extra = my_extra;
2765         state->rec = rec;
2766         state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2767
2768         if (jtype == JSONOID)
2769         {
2770                 text       *json = PG_GETARG_TEXT_P(json_arg_num);
2771                 JsonLexContext *lex;
2772                 JsonSemAction *sem;
2773
2774                 sem = palloc0(sizeof(JsonSemAction));
2775
2776                 lex = makeJsonLexContext(json, true);
2777
2778                 sem->semstate = (void *) state;
2779                 sem->array_start = populate_recordset_array_start;
2780                 sem->array_element_start = populate_recordset_array_element_start;
2781                 sem->scalar = populate_recordset_scalar;
2782                 sem->object_field_start = populate_recordset_object_field_start;
2783                 sem->object_field_end = populate_recordset_object_field_end;
2784                 sem->object_start = populate_recordset_object_start;
2785                 sem->object_end = populate_recordset_object_end;
2786
2787                 state->lex = lex;
2788
2789                 pg_parse_json(lex, sem);
2790         }
2791         else
2792         {
2793                 Jsonb      *jb = PG_GETARG_JSONB(json_arg_num);
2794                 JsonbIterator *it;
2795                 JsonbValue      v;
2796                 bool            skipNested = false;
2797                 JsonbIteratorToken r;
2798
2799                 Assert(jtype == JSONBOID);
2800
2801                 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2802                         ereport(ERROR,
2803                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2804                                          errmsg("cannot call %s on a non-array",
2805                                                         funcname)));
2806
2807                 it = JsonbIteratorInit(&jb->root);
2808
2809                 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2810                 {
2811                         skipNested = true;
2812
2813                         if (r == WJB_ELEM)
2814                         {
2815                                 Jsonb      *element = JsonbValueToJsonb(&v);
2816
2817                                 if (!JB_ROOT_IS_OBJECT(element))
2818                                         ereport(ERROR,
2819                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2820                                                  errmsg("argument of %s must be an array of objects",
2821                                                                 funcname)));
2822                                 make_row_from_rec_and_jsonb(element, state);
2823                         }
2824                 }
2825         }
2826
2827         rsi->setResult = state->tuple_store;
2828         rsi->setDesc = state->ret_tdesc;
2829
2830         PG_RETURN_NULL();
2831 }
2832
2833 static void
2834 populate_recordset_object_start(void *state)
2835 {
2836         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2837         int                     lex_level = _state->lex->lex_level;
2838         HASHCTL         ctl;
2839
2840         /* Reject object at top level: we must have an array at level 0 */
2841         if (lex_level == 0)
2842                 ereport(ERROR,
2843                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2844                                  errmsg("cannot call %s on an object",
2845                                                 _state->function_name)));
2846
2847         /* Nested objects require no special processing */
2848         if (lex_level > 1)
2849                 return;
2850
2851         /* Object at level 1: set up a new hash table for this object */
2852         memset(&ctl, 0, sizeof(ctl));
2853         ctl.keysize = NAMEDATALEN;
2854         ctl.entrysize = sizeof(JsonHashEntry);
2855         ctl.hcxt = CurrentMemoryContext;
2856         _state->json_hash = hash_create("json object hashtable",
2857                                                                         100,
2858                                                                         &ctl,
2859                                                                         HASH_ELEM | HASH_CONTEXT);
2860 }
2861
2862 static void
2863 populate_recordset_object_end(void *state)
2864 {
2865         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2866         HTAB       *json_hash = _state->json_hash;
2867         Datum      *values;
2868         bool       *nulls;
2869         int                     i;
2870         RecordIOData *my_extra = _state->my_extra;
2871         int                     ncolumns = my_extra->ncolumns;
2872         TupleDesc       tupdesc = _state->ret_tdesc;
2873         JsonHashEntry *hashentry;
2874         HeapTupleHeader rec = _state->rec;
2875         HeapTuple       rettuple;
2876
2877         /* Nested objects require no special processing */
2878         if (_state->lex->lex_level > 1)
2879                 return;
2880
2881         /* Otherwise, construct and return a tuple based on this level-1 object */
2882         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2883         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2884
2885         if (_state->rec)
2886         {
2887                 HeapTupleData tuple;
2888
2889                 /* Build a temporary HeapTuple control structure */
2890                 tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2891                 ItemPointerSetInvalid(&(tuple.t_self));
2892                 tuple.t_tableOid = InvalidOid;
2893                 tuple.t_data = _state->rec;
2894
2895                 /* Break down the tuple into fields */
2896                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2897         }
2898         else
2899         {
2900                 for (i = 0; i < ncolumns; ++i)
2901                 {
2902                         values[i] = (Datum) 0;
2903                         nulls[i] = true;
2904                 }
2905         }
2906
2907         for (i = 0; i < ncolumns; ++i)
2908         {
2909                 ColumnIOData *column_info = &my_extra->columns[i];
2910                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2911                 char       *value;
2912
2913                 /* Ignore dropped columns in datatype */
2914                 if (tupdesc->attrs[i]->attisdropped)
2915                 {
2916                         nulls[i] = true;
2917                         continue;
2918                 }
2919
2920                 hashentry = hash_search(json_hash,
2921                                                                 NameStr(tupdesc->attrs[i]->attname),
2922                                                                 HASH_FIND, NULL);
2923
2924                 /*
2925                  * we can't just skip here if the key wasn't found since we might have
2926                  * a domain to deal with. If we were passed in a non-null record
2927                  * datum, we assume that the existing values are valid (if they're
2928                  * not, then it's not our fault), but if we were passed in a null,
2929                  * then every field which we don't populate needs to be run through
2930                  * the input function just in case it's a domain type.
2931                  */
2932                 if (hashentry == NULL && rec)
2933                         continue;
2934
2935                 /*
2936                  * Prepare to convert the column value from text
2937                  */
2938                 if (column_info->column_type != column_type)
2939                 {
2940                         getTypeInputInfo(column_type,
2941                                                          &column_info->typiofunc,
2942                                                          &column_info->typioparam);
2943                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2944                                                   _state->fn_mcxt);
2945                         column_info->column_type = column_type;
2946                 }
2947                 if (hashentry == NULL || hashentry->isnull)
2948                 {
2949                         /*
2950                          * need InputFunctionCall to happen even for nulls, so that domain
2951                          * checks are done
2952                          */
2953                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2954                                                                                   column_info->typioparam,
2955                                                                                   tupdesc->attrs[i]->atttypmod);
2956                         nulls[i] = true;
2957                 }
2958                 else
2959                 {
2960                         value = hashentry->val;
2961
2962                         values[i] = InputFunctionCall(&column_info->proc, value,
2963                                                                                   column_info->typioparam,
2964                                                                                   tupdesc->attrs[i]->atttypmod);
2965                         nulls[i] = false;
2966                 }
2967         }
2968
2969         rettuple = heap_form_tuple(tupdesc, values, nulls);
2970
2971         tuplestore_puttuple(_state->tuple_store, rettuple);
2972
2973         /* Done with hash for this object */
2974         hash_destroy(json_hash);
2975         _state->json_hash = NULL;
2976 }
2977
2978 static void
2979 populate_recordset_array_element_start(void *state, bool isnull)
2980 {
2981         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2982
2983         if (_state->lex->lex_level == 1 &&
2984                 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
2985                 ereport(ERROR,
2986                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2987                                  errmsg("argument of %s must be an array of objects",
2988                                                 _state->function_name)));
2989 }
2990
2991 static void
2992 populate_recordset_array_start(void *state)
2993 {
2994         /* nothing to do */
2995 }
2996
2997 static void
2998 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
2999 {
3000         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3001
3002         if (_state->lex->lex_level == 0)
3003                 ereport(ERROR,
3004                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3005                                  errmsg("cannot call %s on a scalar",
3006                                                 _state->function_name)));
3007
3008         if (_state->lex->lex_level == 2)
3009                 _state->saved_scalar = token;
3010 }
3011
3012 static void
3013 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
3014 {
3015         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3016
3017         if (_state->lex->lex_level > 2)
3018                 return;
3019
3020         if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3021                 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
3022         {
3023                 _state->save_json_start = _state->lex->token_start;
3024         }
3025         else
3026         {
3027                 _state->save_json_start = NULL;
3028         }
3029 }
3030
3031 static void
3032 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
3033 {
3034         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
3035         JsonHashEntry *hashentry;
3036         bool            found;
3037
3038         /*
3039          * Ignore nested fields.
3040          */
3041         if (_state->lex->lex_level > 2)
3042                 return;
3043
3044         /*
3045          * Ignore field names >= NAMEDATALEN - they can't match a record field.
3046          * (Note: without this test, the hash code would truncate the string at
3047          * NAMEDATALEN-1, and could then match against a similarly-truncated
3048          * record field name.  That would be a reasonable behavior, but this code
3049          * has previously insisted on exact equality, so we keep this behavior.)
3050          */
3051         if (strlen(fname) >= NAMEDATALEN)
3052                 return;
3053
3054         hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
3055
3056         /*
3057          * found being true indicates a duplicate. We don't do anything about
3058          * that, a later field with the same name overrides the earlier field.
3059          */
3060
3061         hashentry->isnull = isnull;
3062         if (_state->save_json_start != NULL)
3063         {
3064                 int                     len = _state->lex->prev_token_terminator - _state->save_json_start;
3065                 char       *val = palloc((len + 1) * sizeof(char));
3066
3067                 memcpy(val, _state->save_json_start, len);
3068                 val[len] = '\0';
3069                 hashentry->val = val;
3070         }
3071         else
3072         {
3073                 /* must have had a scalar instead */
3074                 hashentry->val = _state->saved_scalar;
3075         }
3076 }
3077
3078 /*
3079  * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3080  */
3081 static JsonbValue *
3082 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
3083                                                            char *key, uint32 keylen)
3084 {
3085         JsonbValue      k;
3086
3087         k.type = jbvString;
3088         k.val.string.val = key;
3089         k.val.string.len = keylen;
3090
3091         return findJsonbValueFromContainer(container, flags, &k);
3092 }
3093
3094 /*
3095  * Semantic actions for json_strip_nulls.
3096  *
3097  * Simply repeat the input on the output unless we encounter
3098  * a null object field. State for this is set when the field
3099  * is started and reset when the scalar action (which must be next)
3100  * is called.
3101  */
3102
3103 static void
3104 sn_object_start(void *state)
3105 {
3106         StripnullState *_state = (StripnullState *) state;
3107
3108         appendStringInfoCharMacro(_state->strval, '{');
3109 }
3110
3111 static void
3112 sn_object_end(void *state)
3113 {
3114         StripnullState *_state = (StripnullState *) state;
3115
3116         appendStringInfoCharMacro(_state->strval, '}');
3117 }
3118
3119 static void
3120 sn_array_start(void *state)
3121 {
3122         StripnullState *_state = (StripnullState *) state;
3123
3124         appendStringInfoCharMacro(_state->strval, '[');
3125 }
3126
3127 static void
3128 sn_array_end(void *state)
3129 {
3130         StripnullState *_state = (StripnullState *) state;
3131
3132         appendStringInfoCharMacro(_state->strval, ']');
3133 }
3134
3135 static void
3136 sn_object_field_start(void *state, char *fname, bool isnull)
3137 {
3138         StripnullState *_state = (StripnullState *) state;
3139
3140         if (isnull)
3141         {
3142                 /*
3143                  * The next thing must be a scalar or isnull couldn't be true, so
3144                  * there is no danger of this state being carried down into a nested
3145                  * object or array. The flag will be reset in the scalar action.
3146                  */
3147                 _state->skip_next_null = true;
3148                 return;
3149         }
3150
3151         if (_state->strval->data[_state->strval->len - 1] != '{')
3152                 appendStringInfoCharMacro(_state->strval, ',');
3153
3154         /*
3155          * Unfortunately we don't have the quoted and escaped string any more, so
3156          * we have to re-escape it.
3157          */
3158         escape_json(_state->strval, fname);
3159
3160         appendStringInfoCharMacro(_state->strval, ':');
3161 }
3162
3163 static void
3164 sn_array_element_start(void *state, bool isnull)
3165 {
3166         StripnullState *_state = (StripnullState *) state;
3167
3168         if (_state->strval->data[_state->strval->len - 1] != '[')
3169                 appendStringInfoCharMacro(_state->strval, ',');
3170 }
3171
3172 static void
3173 sn_scalar(void *state, char *token, JsonTokenType tokentype)
3174 {
3175         StripnullState *_state = (StripnullState *) state;
3176
3177         if (_state->skip_next_null)
3178         {
3179                 Assert(tokentype == JSON_TOKEN_NULL);
3180                 _state->skip_next_null = false;
3181                 return;
3182         }
3183
3184         if (tokentype == JSON_TOKEN_STRING)
3185                 escape_json(_state->strval, token);
3186         else
3187                 appendStringInfoString(_state->strval, token);
3188 }
3189
3190 /*
3191  * SQL function json_strip_nulls(json) -> json
3192  */
3193 Datum
3194 json_strip_nulls(PG_FUNCTION_ARGS)
3195 {
3196         text       *json = PG_GETARG_TEXT_P(0);
3197         StripnullState *state;
3198         JsonLexContext *lex;
3199         JsonSemAction *sem;
3200
3201         lex = makeJsonLexContext(json, true);
3202         state = palloc0(sizeof(StripnullState));
3203         sem = palloc0(sizeof(JsonSemAction));
3204
3205         state->strval = makeStringInfo();
3206         state->skip_next_null = false;
3207         state->lex = lex;
3208
3209         sem->semstate = (void *) state;
3210         sem->object_start = sn_object_start;
3211         sem->object_end = sn_object_end;
3212         sem->array_start = sn_array_start;
3213         sem->array_end = sn_array_end;
3214         sem->scalar = sn_scalar;
3215         sem->array_element_start = sn_array_element_start;
3216         sem->object_field_start = sn_object_field_start;
3217
3218         pg_parse_json(lex, sem);
3219
3220         PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
3221                                                                                           state->strval->len));
3222
3223 }
3224
3225 /*
3226  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
3227  */
3228 Datum
3229 jsonb_strip_nulls(PG_FUNCTION_ARGS)
3230 {
3231         Jsonb      *jb = PG_GETARG_JSONB(0);
3232         JsonbIterator *it;
3233         JsonbParseState *parseState = NULL;
3234         JsonbValue *res = NULL;
3235         JsonbValue      v,
3236                                 k;
3237         JsonbIteratorToken type;
3238         bool            last_was_key = false;
3239
3240         if (JB_ROOT_IS_SCALAR(jb))
3241                 PG_RETURN_POINTER(jb);
3242
3243         it = JsonbIteratorInit(&jb->root);
3244
3245         while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3246         {
3247                 Assert(!(type == WJB_KEY && last_was_key));
3248
3249                 if (type == WJB_KEY)
3250                 {
3251                         /* stash the key until we know if it has a null value */
3252                         k = v;
3253                         last_was_key = true;
3254                         continue;
3255                 }
3256
3257                 if (last_was_key)
3258                 {
3259                         /* if the last element was a key this one can't be */
3260                         last_was_key = false;
3261
3262                         /* skip this field if value is null */
3263                         if (type == WJB_VALUE && v.type == jbvNull)
3264                                 continue;
3265
3266                         /* otherwise, do a delayed push of the key */
3267                         (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3268                 }
3269
3270                 if (type == WJB_VALUE || type == WJB_ELEM)
3271                         res = pushJsonbValue(&parseState, type, &v);
3272                 else
3273                         res = pushJsonbValue(&parseState, type, NULL);
3274         }
3275
3276         Assert(res != NULL);
3277
3278         PG_RETURN_POINTER(JsonbValueToJsonb(res));
3279 }
3280
3281 /*
3282  * Add values from the jsonb to the parse state.
3283  *
3284  * If the parse state container is an object, the jsonb is pushed as
3285  * a value, not a key.
3286  *
3287  * This needs to be done using an iterator because pushJsonbValue doesn't
3288  * like getting jbvBinary values, so we can't just push jb as a whole.
3289  */
3290 static void
3291 addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
3292 {
3293         JsonbIterator *it;
3294         JsonbValue *o = &(*jbps)->contVal;
3295         JsonbValue      v;
3296         JsonbIteratorToken type;
3297
3298         it = JsonbIteratorInit(&jb->root);
3299
3300         Assert(o->type == jbvArray || o->type == jbvObject);
3301
3302         if (JB_ROOT_IS_SCALAR(jb))
3303         {
3304                 (void) JsonbIteratorNext(&it, &v, false);               /* skip array header */
3305                 (void) JsonbIteratorNext(&it, &v, false);               /* fetch scalar value */
3306
3307                 switch (o->type)
3308                 {
3309                         case jbvArray:
3310                                 (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3311                                 break;
3312                         case jbvObject:
3313                                 (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3314                                 break;
3315                         default:
3316                                 elog(ERROR, "unexpected parent of nested structure");
3317                 }
3318         }
3319         else
3320         {
3321                 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3322                 {
3323                         if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3324                                 (void) pushJsonbValue(jbps, type, &v);
3325                         else
3326                                 (void) pushJsonbValue(jbps, type, NULL);
3327                 }
3328         }
3329
3330 }
3331
3332 /*
3333  * SQL function jsonb_pretty (jsonb)
3334  *
3335  * Pretty-printed text for the jsonb
3336  */
3337 Datum
3338 jsonb_pretty(PG_FUNCTION_ARGS)
3339 {
3340         Jsonb      *jb = PG_GETARG_JSONB(0);
3341         StringInfo      str = makeStringInfo();
3342
3343         JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3344
3345         PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
3346 }
3347
3348 /*
3349  * SQL function jsonb_concat (jsonb, jsonb)
3350  *
3351  * function for || operator
3352  */
3353 Datum
3354 jsonb_concat(PG_FUNCTION_ARGS)
3355 {
3356         Jsonb      *jb1 = PG_GETARG_JSONB(0);
3357         Jsonb      *jb2 = PG_GETARG_JSONB(1);
3358         JsonbParseState *state = NULL;
3359         JsonbValue *res;
3360         JsonbIterator *it1,
3361                            *it2;
3362
3363         /*
3364          * If one of the jsonb is empty, just return the other if it's not scalar
3365          * and both are of the same kind.  If it's a scalar or they are of
3366          * different kinds we need to perform the concatenation even if one is
3367          * empty.
3368          */
3369         if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
3370         {
3371                 if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
3372                         PG_RETURN_JSONB(jb2);
3373                 else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
3374                         PG_RETURN_JSONB(jb1);
3375         }
3376
3377         it1 = JsonbIteratorInit(&jb1->root);
3378         it2 = JsonbIteratorInit(&jb2->root);
3379
3380         res = IteratorConcat(&it1, &it2, &state);
3381
3382         Assert(res != NULL);
3383
3384         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3385 }
3386
3387
3388 /*
3389  * SQL function jsonb_delete (jsonb, text)
3390  *
3391  * return a copy of the jsonb with the indicated item
3392  * removed.
3393  */
3394 Datum
3395 jsonb_delete(PG_FUNCTION_ARGS)
3396 {
3397         Jsonb      *in = PG_GETARG_JSONB(0);
3398         text       *key = PG_GETARG_TEXT_PP(1);
3399         char       *keyptr = VARDATA_ANY(key);
3400         int                     keylen = VARSIZE_ANY_EXHDR(key);
3401         JsonbParseState *state = NULL;
3402         JsonbIterator *it;
3403         JsonbValue      v,
3404                            *res = NULL;
3405         bool            skipNested = false;
3406         JsonbIteratorToken r;
3407
3408         if (JB_ROOT_IS_SCALAR(in))
3409                 ereport(ERROR,
3410                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3411                                  errmsg("cannot delete from scalar")));
3412
3413         if (JB_ROOT_COUNT(in) == 0)
3414                 PG_RETURN_JSONB(in);
3415
3416         it = JsonbIteratorInit(&in->root);
3417
3418         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3419         {
3420                 skipNested = true;
3421
3422                 if ((r == WJB_ELEM || r == WJB_KEY) &&
3423                         (v.type == jbvString && keylen == v.val.string.len &&
3424                          memcmp(keyptr, v.val.string.val, keylen) == 0))
3425                 {
3426                         /* skip corresponding value as well */
3427                         if (r == WJB_KEY)
3428                                 JsonbIteratorNext(&it, &v, true);
3429
3430                         continue;
3431                 }
3432
3433                 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3434         }
3435
3436         Assert(res != NULL);
3437
3438         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3439 }
3440
3441 /*
3442  * SQL function jsonb_delete (jsonb, variadic text[])
3443  *
3444  * return a copy of the jsonb with the indicated items
3445  * removed.
3446  */
3447 Datum
3448 jsonb_delete_array(PG_FUNCTION_ARGS)
3449 {
3450         Jsonb      *in = PG_GETARG_JSONB(0);
3451         ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
3452         Datum      *keys_elems;
3453         bool       *keys_nulls;
3454         int                     keys_len;
3455         JsonbParseState *state = NULL;
3456         JsonbIterator *it;
3457         JsonbValue      v,
3458                            *res = NULL;
3459         bool            skipNested = false;
3460         JsonbIteratorToken r;
3461
3462         if (ARR_NDIM(keys) > 1)
3463                 ereport(ERROR,
3464                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3465                                  errmsg("wrong number of array subscripts")));
3466
3467         if (JB_ROOT_IS_SCALAR(in))
3468                 ereport(ERROR,
3469                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3470                                  errmsg("cannot delete from scalar")));
3471
3472         if (JB_ROOT_COUNT(in) == 0)
3473                 PG_RETURN_JSONB(in);
3474
3475         deconstruct_array(keys, TEXTOID, -1, false, 'i',
3476                                           &keys_elems, &keys_nulls, &keys_len);
3477
3478         if (keys_len == 0)
3479                 PG_RETURN_JSONB(in);
3480
3481         it = JsonbIteratorInit(&in->root);
3482
3483         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3484         {
3485                 skipNested = true;
3486
3487                 if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
3488                 {
3489                         int                     i;
3490                         bool            found = false;
3491
3492                         for (i = 0; i < keys_len; i++)
3493                         {
3494                                 char       *keyptr;
3495                                 int                     keylen;
3496
3497                                 if (keys_nulls[i])
3498                                         continue;
3499
3500                                 keyptr = VARDATA_ANY(keys_elems[i]);
3501                                 keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
3502                                 if (keylen == v.val.string.len &&
3503                                         memcmp(keyptr, v.val.string.val, keylen) == 0)
3504                                 {
3505                                         found = true;
3506                                         break;
3507                                 }
3508                         }
3509                         if (found)
3510                         {
3511                                 /* skip corresponding value as well */
3512                                 if (r == WJB_KEY)
3513                                         JsonbIteratorNext(&it, &v, true);
3514
3515                                 continue;
3516                         }
3517                 }
3518
3519                 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3520         }
3521
3522         Assert(res != NULL);
3523
3524         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3525 }
3526
3527 /*
3528  * SQL function jsonb_delete (jsonb, int)
3529  *
3530  * return a copy of the jsonb with the indicated item
3531  * removed. Negative int means count back from the
3532  * end of the items.
3533  */
3534 Datum
3535 jsonb_delete_idx(PG_FUNCTION_ARGS)
3536 {
3537         Jsonb      *in = PG_GETARG_JSONB(0);
3538         int                     idx = PG_GETARG_INT32(1);
3539         JsonbParseState *state = NULL;
3540         JsonbIterator *it;
3541         uint32          i = 0,
3542                                 n;
3543         JsonbValue      v,
3544                            *res = NULL;
3545         JsonbIteratorToken r;
3546
3547         if (JB_ROOT_IS_SCALAR(in))
3548                 ereport(ERROR,
3549                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3550                                  errmsg("cannot delete from scalar")));
3551
3552         if (JB_ROOT_IS_OBJECT(in))
3553                 ereport(ERROR,
3554                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3555                                  errmsg("cannot delete from object using integer index")));
3556
3557         if (JB_ROOT_COUNT(in) == 0)
3558                 PG_RETURN_JSONB(in);
3559
3560         it = JsonbIteratorInit(&in->root);
3561
3562         r = JsonbIteratorNext(&it, &v, false);
3563         Assert(r == WJB_BEGIN_ARRAY);
3564         n = v.val.array.nElems;
3565
3566         if (idx < 0)
3567         {
3568                 if (-idx > n)
3569                         idx = n;
3570                 else
3571                         idx = n + idx;
3572         }
3573
3574         if (idx >= n)
3575                 PG_RETURN_JSONB(in);
3576
3577         pushJsonbValue(&state, r, NULL);
3578
3579         while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3580         {
3581                 if (r == WJB_ELEM)
3582                 {
3583                         if (i++ == idx)
3584                                 continue;
3585                 }
3586
3587                 res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3588         }
3589
3590         Assert(res != NULL);
3591
3592         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3593 }
3594
3595 /*
3596  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
3597  *
3598  */
3599 Datum
3600 jsonb_set(PG_FUNCTION_ARGS)
3601 {
3602         Jsonb      *in = PG_GETARG_JSONB(0);
3603         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
3604         Jsonb      *newval = PG_GETARG_JSONB(2);
3605         bool            create = PG_GETARG_BOOL(3);
3606         JsonbValue *res = NULL;
3607         Datum      *path_elems;
3608         bool       *path_nulls;
3609         int                     path_len;
3610         JsonbIterator *it;
3611         JsonbParseState *st = NULL;
3612
3613         if (ARR_NDIM(path) > 1)
3614                 ereport(ERROR,
3615                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3616                                  errmsg("wrong number of array subscripts")));
3617
3618         if (JB_ROOT_IS_SCALAR(in))
3619                 ereport(ERROR,
3620                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3621                                  errmsg("cannot set path in scalar")));
3622
3623         if (JB_ROOT_COUNT(in) == 0 && !create)
3624                 PG_RETURN_JSONB(in);
3625
3626         deconstruct_array(path, TEXTOID, -1, false, 'i',
3627                                           &path_elems, &path_nulls, &path_len);
3628
3629         if (path_len == 0)
3630                 PG_RETURN_JSONB(in);
3631
3632         it = JsonbIteratorInit(&in->root);
3633
3634         res = setPath(&it, path_elems, path_nulls, path_len, &st,
3635                                   0, newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
3636
3637         Assert(res != NULL);
3638
3639         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3640 }
3641
3642
3643 /*
3644  * SQL function jsonb_delete_path(jsonb, text[])
3645  */
3646 Datum
3647 jsonb_delete_path(PG_FUNCTION_ARGS)
3648 {
3649         Jsonb      *in = PG_GETARG_JSONB(0);
3650         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
3651         JsonbValue *res = NULL;
3652         Datum      *path_elems;
3653         bool       *path_nulls;
3654         int                     path_len;
3655         JsonbIterator *it;
3656         JsonbParseState *st = NULL;
3657
3658         if (ARR_NDIM(path) > 1)
3659                 ereport(ERROR,
3660                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3661                                  errmsg("wrong number of array subscripts")));
3662
3663         if (JB_ROOT_IS_SCALAR(in))
3664                 ereport(ERROR,
3665                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3666                                  errmsg("cannot delete path in scalar")));
3667
3668         if (JB_ROOT_COUNT(in) == 0)
3669                 PG_RETURN_JSONB(in);
3670
3671         deconstruct_array(path, TEXTOID, -1, false, 'i',
3672                                           &path_elems, &path_nulls, &path_len);
3673
3674         if (path_len == 0)
3675                 PG_RETURN_JSONB(in);
3676
3677         it = JsonbIteratorInit(&in->root);
3678
3679         res = setPath(&it, path_elems, path_nulls, path_len, &st,
3680                                   0, NULL, JB_PATH_DELETE);
3681
3682         Assert(res != NULL);
3683
3684         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3685 }
3686
3687 /*
3688  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
3689  *
3690  */
3691 Datum
3692 jsonb_insert(PG_FUNCTION_ARGS)
3693 {
3694         Jsonb      *in = PG_GETARG_JSONB(0);
3695         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
3696         Jsonb      *newval = PG_GETARG_JSONB(2);
3697         bool            after = PG_GETARG_BOOL(3);
3698         JsonbValue *res = NULL;
3699         Datum      *path_elems;
3700         bool       *path_nulls;
3701         int                     path_len;
3702         JsonbIterator *it;
3703         JsonbParseState *st = NULL;
3704
3705         if (ARR_NDIM(path) > 1)
3706                 ereport(ERROR,
3707                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3708                                  errmsg("wrong number of array subscripts")));
3709
3710         if (JB_ROOT_IS_SCALAR(in))
3711                 ereport(ERROR,
3712                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3713                                  errmsg("cannot set path in scalar")));
3714
3715         deconstruct_array(path, TEXTOID, -1, false, 'i',
3716                                           &path_elems, &path_nulls, &path_len);
3717
3718         if (path_len == 0)
3719                 PG_RETURN_JSONB(in);
3720
3721         it = JsonbIteratorInit(&in->root);
3722
3723         res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
3724                                   after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
3725
3726         Assert(res != NULL);
3727
3728         PG_RETURN_JSONB(JsonbValueToJsonb(res));
3729 }
3730
3731 /*
3732  * Iterate over all jsonb objects and merge them into one.
3733  * The logic of this function copied from the same hstore function,
3734  * except the case, when it1 & it2 represents jbvObject.
3735  * In that case we just append the content of it2 to it1 without any
3736  * verifications.
3737  */
3738 static JsonbValue *
3739 IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3740                            JsonbParseState **state)
3741 {
3742         JsonbValue      v1,
3743                                 v2,
3744                            *res = NULL;
3745         JsonbIteratorToken r1,
3746                                 r2,
3747                                 rk1,
3748                                 rk2;
3749
3750         r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3751         r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3752
3753         /*
3754          * Both elements are objects.
3755          */
3756         if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3757         {
3758                 /*
3759                  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3760                  * (because res will not be finished yet).
3761                  */
3762                 pushJsonbValue(state, r1, NULL);
3763                 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3764                         pushJsonbValue(state, r1, &v1);
3765
3766                 /*
3767                  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3768                  * (the concatenation will be completed).
3769                  */
3770                 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3771                         res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3772         }
3773
3774         /*
3775          * Both elements are arrays (either can be scalar).
3776          */
3777         else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3778         {
3779                 pushJsonbValue(state, r1, NULL);
3780
3781                 while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3782                 {
3783                         Assert(r1 == WJB_ELEM);
3784                         pushJsonbValue(state, r1, &v1);
3785                 }
3786
3787                 while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
3788                 {
3789                         Assert(r2 == WJB_ELEM);
3790                         pushJsonbValue(state, WJB_ELEM, &v2);
3791                 }
3792
3793                 res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
3794         }
3795         /* have we got array || object or object || array? */
3796         else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3797                          (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3798         {
3799
3800                 JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3801                 JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3802
3803                 bool            prepend = (rk1 == WJB_BEGIN_OBJECT);
3804
3805                 pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
3806
3807                 if (prepend)
3808                 {
3809                         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3810                         while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3811                                 pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
3812
3813                         while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3814                                 res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
3815                 }
3816                 else
3817                 {
3818                         while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3819                                 pushJsonbValue(state, r1, &v1);
3820
3821                         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3822                         while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3823                                 pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3824
3825                         res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3826                 }
3827         }
3828         else
3829         {
3830                 /*
3831                  * This must be scalar || object or object || scalar, as that's all
3832                  * that's left. Both of these make no sense, so error out.
3833                  */
3834                 ereport(ERROR,
3835                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3836                                  errmsg("invalid concatenation of jsonb objects")));
3837         }
3838
3839         return res;
3840 }
3841
3842 /*
3843  * Do most of the heavy work for jsonb_set/jsonb_insert
3844  *
3845  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
3846  *
3847  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
3848  * we create the new value if the key or array index does not exist.
3849  *
3850  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
3851  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
3852  *
3853  * All path elements before the last must already exist
3854  * whatever bits in op_type are set, or nothing is done.
3855  */
3856 static JsonbValue *
3857 setPath(JsonbIterator **it, Datum *path_elems,
3858                 bool *path_nulls, int path_len,
3859                 JsonbParseState **st, int level, Jsonb *newval, int op_type)
3860 {
3861         JsonbValue      v;
3862         JsonbIteratorToken r;
3863         JsonbValue *res;
3864
3865         check_stack_depth();
3866
3867         if (path_nulls[level])
3868                 ereport(ERROR,
3869                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3870                                  errmsg("path element at position %d is null",
3871                                                 level + 1)));
3872
3873         r = JsonbIteratorNext(it, &v, false);
3874
3875         switch (r)
3876         {
3877                 case WJB_BEGIN_ARRAY:
3878                         (void) pushJsonbValue(st, r, NULL);
3879                         setPathArray(it, path_elems, path_nulls, path_len, st, level,
3880                                                  newval, v.val.array.nElems, op_type);
3881                         r = JsonbIteratorNext(it, &v, false);
3882                         Assert(r == WJB_END_ARRAY);
3883                         res = pushJsonbValue(st, r, NULL);
3884                         break;
3885                 case WJB_BEGIN_OBJECT:
3886                         (void) pushJsonbValue(st, r, NULL);
3887                         setPathObject(it, path_elems, path_nulls, path_len, st, level,
3888                                                   newval, v.val.object.nPairs, op_type);
3889                         r = JsonbIteratorNext(it, &v, true);
3890                         Assert(r == WJB_END_OBJECT);
3891                         res = pushJsonbValue(st, r, NULL);
3892                         break;
3893                 case WJB_ELEM:
3894                 case WJB_VALUE:
3895                         res = pushJsonbValue(st, r, &v);
3896                         break;
3897                 default:
3898                         elog(ERROR, "unrecognized iterator result: %d", (int) r);
3899                         res = NULL;                     /* keep compiler quiet */
3900                         break;
3901         }
3902
3903         return res;
3904 }
3905
3906 /*
3907  * Object walker for setPath
3908  */
3909 static void
3910 setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
3911                           int path_len, JsonbParseState **st, int level,
3912                           Jsonb *newval, uint32 npairs, int op_type)
3913 {
3914         JsonbValue      v;
3915         int                     i;
3916         JsonbValue      k;
3917         bool            done = false;
3918
3919         if (level >= path_len || path_nulls[level])
3920                 done = true;
3921
3922         /* empty object is a special case for create */
3923         if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
3924                 (level == path_len - 1))
3925         {
3926                 JsonbValue      newkey;
3927
3928                 newkey.type = jbvString;
3929                 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3930                 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3931
3932                 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3933                 addJsonbToParseState(st, newval);
3934         }
3935
3936         for (i = 0; i < npairs; i++)
3937         {
3938                 JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
3939
3940                 Assert(r == WJB_KEY);
3941
3942                 if (!done &&
3943                         k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
3944                         memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
3945                                    k.val.string.len) == 0)
3946                 {
3947                         if (level == path_len - 1)
3948                         {
3949                                 /*
3950                                  * called from jsonb_insert(), it forbids redefining an
3951                                  * existing value
3952                                  */
3953                                 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
3954                                         ereport(ERROR,
3955                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3956                                                          errmsg("cannot replace existing key"),
3957                                                          errhint("Try using the function jsonb_set "
3958                                                                          "to replace key value.")));
3959
3960                                 r = JsonbIteratorNext(it, &v, true);    /* skip value */
3961                                 if (!(op_type & JB_PATH_DELETE))
3962                                 {
3963                                         (void) pushJsonbValue(st, WJB_KEY, &k);
3964                                         addJsonbToParseState(st, newval);
3965                                 }
3966                                 done = true;
3967                         }
3968                         else
3969                         {
3970                                 (void) pushJsonbValue(st, r, &k);
3971                                 setPath(it, path_elems, path_nulls, path_len,
3972                                                 st, level + 1, newval, op_type);
3973                         }
3974                 }
3975                 else
3976                 {
3977                         if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
3978                                 level == path_len - 1 && i == npairs - 1)
3979                         {
3980                                 JsonbValue      newkey;
3981
3982                                 newkey.type = jbvString;
3983                                 newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
3984                                 newkey.val.string.val = VARDATA_ANY(path_elems[level]);
3985
3986                                 (void) pushJsonbValue(st, WJB_KEY, &newkey);
3987                                 addJsonbToParseState(st, newval);
3988                         }
3989
3990                         (void) pushJsonbValue(st, r, &k);
3991                         r = JsonbIteratorNext(it, &v, false);
3992                         (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3993                         if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
3994                         {
3995                                 int                     walking_level = 1;
3996
3997                                 while (walking_level != 0)
3998                                 {
3999                                         r = JsonbIteratorNext(it, &v, false);
4000
4001                                         if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4002                                                 ++walking_level;
4003                                         if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4004                                                 --walking_level;
4005
4006                                         (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4007                                 }
4008                         }
4009                 }
4010         }
4011 }
4012
4013 /*
4014  * Array walker for setPath
4015  */
4016 static void
4017 setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4018                          int path_len, JsonbParseState **st, int level,
4019                          Jsonb *newval, uint32 nelems, int op_type)
4020 {
4021         JsonbValue      v;
4022         int                     idx,
4023                                 i;
4024         bool            done = false;
4025
4026         /* pick correct index */
4027         if (level < path_len && !path_nulls[level])
4028         {
4029                 char       *c = TextDatumGetCString(path_elems[level]);
4030                 long            lindex;
4031                 char       *badp;
4032
4033                 errno = 0;
4034                 lindex = strtol(c, &badp, 10);
4035                 if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
4036                         lindex < INT_MIN)
4037                         ereport(ERROR,
4038                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
4039                           errmsg("path element at position %d is not an integer: \"%s\"",
4040                                          level + 1, c)));
4041                 idx = lindex;
4042         }
4043         else
4044                 idx = nelems;
4045
4046         if (idx < 0)
4047         {
4048                 if (-idx > nelems)
4049                         idx = INT_MIN;
4050                 else
4051                         idx = nelems + idx;
4052         }
4053
4054         if (idx > 0 && idx > nelems)
4055                 idx = nelems;
4056
4057         /*
4058          * if we're creating, and idx == INT_MIN, we prepend the new value to the
4059          * array also if the array is empty - in which case we don't really care
4060          * what the idx value is
4061          */
4062
4063         if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
4064                 (op_type & JB_PATH_CREATE_OR_INSERT))
4065         {
4066                 Assert(newval != NULL);
4067                 addJsonbToParseState(st, newval);
4068                 done = true;
4069         }
4070
4071         /* iterate over the array elements */
4072         for (i = 0; i < nelems; i++)
4073         {
4074                 JsonbIteratorToken r;
4075
4076                 if (i == idx && level < path_len)
4077                 {
4078                         if (level == path_len - 1)
4079                         {
4080                                 r = JsonbIteratorNext(it, &v, true);    /* skip */
4081
4082                                 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
4083                                         addJsonbToParseState(st, newval);
4084
4085                                 /*
4086                                  * We should keep current value only in case of
4087                                  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
4088                                  * otherwise it should be deleted or replaced
4089                                  */
4090                                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
4091                                         (void) pushJsonbValue(st, r, &v);
4092
4093                                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
4094                                         addJsonbToParseState(st, newval);
4095
4096                                 done = true;
4097                         }
4098                         else
4099                                 (void) setPath(it, path_elems, path_nulls, path_len,
4100                                                            st, level + 1, newval, op_type);
4101                 }
4102                 else
4103                 {
4104                         r = JsonbIteratorNext(it, &v, false);
4105
4106                         (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4107
4108                         if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4109                         {
4110                                 int                     walking_level = 1;
4111
4112                                 while (walking_level != 0)
4113                                 {
4114                                         r = JsonbIteratorNext(it, &v, false);
4115
4116                                         if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
4117                                                 ++walking_level;
4118                                         if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
4119                                                 --walking_level;
4120
4121                                         (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4122                                 }
4123                         }
4124
4125                         if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
4126                                 level == path_len - 1 && i == nelems - 1)
4127                         {
4128                                 addJsonbToParseState(st, newval);
4129                         }
4130                 }
4131         }
4132 }