]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/jsonfuncs.c
Fix handling of nested JSON objects in json_populate_recordset and friends.
[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-2014, 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 "fmgr.h"
20 #include "funcapi.h"
21 #include "miscadmin.h"
22 #include "access/htup_details.h"
23 #include "catalog/pg_type.h"
24 #include "lib/stringinfo.h"
25 #include "mb/pg_wchar.h"
26 #include "utils/array.h"
27 #include "utils/builtins.h"
28 #include "utils/hsearch.h"
29 #include "utils/json.h"
30 #include "utils/jsonb.h"
31 #include "utils/jsonapi.h"
32 #include "utils/lsyscache.h"
33 #include "utils/memutils.h"
34 #include "utils/typcache.h"
35
36 /* semantic action functions for json_object_keys */
37 static void okeys_object_field_start(void *state, char *fname, bool isnull);
38 static void okeys_array_start(void *state);
39 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
40
41 /* semantic action functions for json_get* functions */
42 static void get_object_start(void *state);
43 static void get_object_field_start(void *state, char *fname, bool isnull);
44 static void get_object_field_end(void *state, char *fname, bool isnull);
45 static void get_array_start(void *state);
46 static void get_array_element_start(void *state, bool isnull);
47 static void get_array_element_end(void *state, bool isnull);
48 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
49
50 /* common worker function for json getter functions */
51 static inline Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
52 static inline text *get_worker(text *json, char *field, int elem_index,
53                    char **tpath, int *ipath, int npath,
54                    bool normalize_results);
55 static inline Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
56
57 /* semantic action functions for json_array_length */
58 static void alen_object_start(void *state);
59 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
60 static void alen_array_element_start(void *state, bool isnull);
61
62 /* common workers for json{b}_each* functions */
63 static inline Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
64 static inline Datum each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
65
66 /* semantic action functions for json_each */
67 static void each_object_field_start(void *state, char *fname, bool isnull);
68 static void each_object_field_end(void *state, char *fname, bool isnull);
69 static void each_array_start(void *state);
70 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
71
72 /* common workers for json{b}_array_elements_* functions */
73 static inline Datum elements_worker(FunctionCallInfo fcinfo, bool as_text);
74 static inline Datum elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
75
76 /* semantic action functions for json_array_elements */
77 static void elements_object_start(void *state);
78 static void elements_array_element_start(void *state, bool isnull);
79 static void elements_array_element_end(void *state, bool isnull);
80 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
81
82 /* turn a json object into a hash table */
83 static HTAB *get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text);
84
85 /* common worker for populate_record and to_record */
86 static inline Datum populate_record_worker(FunctionCallInfo fcinfo,
87                                            bool have_record_arg);
88
89 /* semantic action functions for get_json_object_as_hash */
90 static void hash_object_field_start(void *state, char *fname, bool isnull);
91 static void hash_object_field_end(void *state, char *fname, bool isnull);
92 static void hash_array_start(void *state);
93 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
94
95 /* semantic action functions for populate_recordset */
96 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
97 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
98 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
99 static void populate_recordset_object_start(void *state);
100 static void populate_recordset_object_end(void *state);
101 static void populate_recordset_array_start(void *state);
102 static void populate_recordset_array_element_start(void *state, bool isnull);
103
104 /* worker function for populate_recordset and to_recordset */
105 static inline Datum populate_recordset_worker(FunctionCallInfo fcinfo,
106                                                   bool have_record_arg);
107
108 /* Worker that takes care of common setup for us */
109 static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
110                                                                  uint32 flags,
111                                                                  char *key,
112                                                                  uint32 keylen);
113
114 /* search type classification for json_get* functions */
115 typedef enum
116 {
117         JSON_SEARCH_OBJECT = 1,
118         JSON_SEARCH_ARRAY,
119         JSON_SEARCH_PATH
120 } JsonSearch;
121
122 /* state for json_object_keys */
123 typedef struct OkeysState
124 {
125         JsonLexContext *lex;
126         char      **result;
127         int                     result_size;
128         int                     result_count;
129         int                     sent_count;
130 } OkeysState;
131
132 /* state for json_get* functions */
133 typedef struct GetState
134 {
135         JsonLexContext *lex;
136         JsonSearch      search_type;
137         int                     search_index;
138         int                     array_index;
139         char       *search_term;
140         char       *result_start;
141         text       *tresult;
142         bool            result_is_null;
143         bool            normalize_results;
144         bool            next_scalar;
145         char      **path;
146         int                     npath;
147         char      **current_path;
148         bool       *pathok;
149         int                *array_level_index;
150         int                *path_level_index;
151 } GetState;
152
153 /* state for json_array_length */
154 typedef struct AlenState
155 {
156         JsonLexContext *lex;
157         int                     count;
158 } AlenState;
159
160 /* state for json_each */
161 typedef struct EachState
162 {
163         JsonLexContext *lex;
164         Tuplestorestate *tuple_store;
165         TupleDesc       ret_tdesc;
166         MemoryContext tmp_cxt;
167         char       *result_start;
168         bool            normalize_results;
169         bool            next_scalar;
170         char       *normalized_scalar;
171 } EachState;
172
173 /* state for json_array_elements */
174 typedef struct ElementsState
175 {
176         JsonLexContext *lex;
177         Tuplestorestate *tuple_store;
178         TupleDesc       ret_tdesc;
179         MemoryContext tmp_cxt;
180         char       *result_start;
181         bool            normalize_results;
182         bool            next_scalar;
183         char       *normalized_scalar;
184 } ElementsState;
185
186 /* state for get_json_object_as_hash */
187 typedef struct JhashState
188 {
189         JsonLexContext *lex;
190         HTAB       *hash;
191         char       *saved_scalar;
192         char       *save_json_start;
193         bool            use_json_as_text;
194         char       *function_name;
195 } JHashState;
196
197 /* used to build the hashtable */
198 typedef struct JsonHashEntry
199 {
200         char            fname[NAMEDATALEN];
201         char       *val;
202         char       *json;
203         bool            isnull;
204 } JsonHashEntry;
205
206 /* these two are stolen from hstore / record_out, used in populate_record* */
207 typedef struct ColumnIOData
208 {
209         Oid                     column_type;
210         Oid                     typiofunc;
211         Oid                     typioparam;
212         FmgrInfo        proc;
213 } ColumnIOData;
214
215 typedef struct RecordIOData
216 {
217         Oid                     record_type;
218         int32           record_typmod;
219         int                     ncolumns;
220         ColumnIOData columns[1];        /* VARIABLE LENGTH ARRAY */
221 } RecordIOData;
222
223 /* state for populate_recordset */
224 typedef struct PopulateRecordsetState
225 {
226         JsonLexContext *lex;
227         HTAB       *json_hash;
228         char       *saved_scalar;
229         char       *save_json_start;
230         bool            use_json_as_text;
231         Tuplestorestate *tuple_store;
232         TupleDesc       ret_tdesc;
233         HeapTupleHeader rec;
234         RecordIOData *my_extra;
235         MemoryContext fn_mcxt;          /* used to stash IO funcs */
236 } PopulateRecordsetState;
237
238 /* Turn a jsonb object into a record */
239 static void make_row_from_rec_and_jsonb(Jsonb *element,
240                                                         PopulateRecordsetState *state);
241
242 /*
243  * SQL function json_object_keys
244  *
245  * Returns the set of keys for the object argument.
246  *
247  * This SRF operates in value-per-call mode. It processes the
248  * object during the first call, and the keys are simply stashed
249  * in an array, whose size is expanded as necessary. This is probably
250  * safe enough for a list of keys of a single object, since they are
251  * limited in size to NAMEDATALEN and the number of keys is unlikely to
252  * be so huge that it has major memory implications.
253  */
254 Datum
255 jsonb_object_keys(PG_FUNCTION_ARGS)
256 {
257         FuncCallContext *funcctx;
258         OkeysState *state;
259         int                     i;
260
261         if (SRF_IS_FIRSTCALL())
262         {
263                 MemoryContext oldcontext;
264                 Jsonb      *jb = PG_GETARG_JSONB(0);
265                 bool            skipNested = false;
266                 JsonbIterator *it;
267                 JsonbValue      v;
268                 int                     r;
269
270                 if (JB_ROOT_IS_SCALAR(jb))
271                         ereport(ERROR,
272                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
273                                          errmsg("cannot call jsonb_object_keys on a scalar")));
274                 else if (JB_ROOT_IS_ARRAY(jb))
275                         ereport(ERROR,
276                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
277                                          errmsg("cannot call jsonb_object_keys on an array")));
278
279                 funcctx = SRF_FIRSTCALL_INIT();
280                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
281
282                 state = palloc(sizeof(OkeysState));
283
284                 state->result_size = JB_ROOT_COUNT(jb);
285                 state->result_count = 0;
286                 state->sent_count = 0;
287                 state->result = palloc(state->result_size * sizeof(char *));
288
289                 it = JsonbIteratorInit(&jb->root);
290
291                 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
292                 {
293                         skipNested = true;
294
295                         if (r == WJB_KEY)
296                         {
297                                 char       *cstr;
298
299                                 cstr = palloc(v.val.string.len + 1 * sizeof(char));
300                                 memcpy(cstr, v.val.string.val, v.val.string.len);
301                                 cstr[v.val.string.len] = '\0';
302                                 state->result[state->result_count++] = cstr;
303                         }
304                 }
305
306
307                 MemoryContextSwitchTo(oldcontext);
308                 funcctx->user_fctx = (void *) state;
309
310         }
311
312         funcctx = SRF_PERCALL_SETUP();
313         state = (OkeysState *) funcctx->user_fctx;
314
315         if (state->sent_count < state->result_count)
316         {
317                 char       *nxt = state->result[state->sent_count++];
318
319                 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
320         }
321
322         /* cleanup to reduce or eliminate memory leaks */
323         for (i = 0; i < state->result_count; i++)
324                 pfree(state->result[i]);
325         pfree(state->result);
326         pfree(state);
327
328         SRF_RETURN_DONE(funcctx);
329 }
330
331
332 Datum
333 json_object_keys(PG_FUNCTION_ARGS)
334 {
335         FuncCallContext *funcctx;
336         OkeysState *state;
337         int                     i;
338
339         if (SRF_IS_FIRSTCALL())
340         {
341                 text       *json = PG_GETARG_TEXT_P(0);
342                 JsonLexContext *lex = makeJsonLexContext(json, true);
343                 JsonSemAction *sem;
344
345                 MemoryContext oldcontext;
346
347                 funcctx = SRF_FIRSTCALL_INIT();
348                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
349
350                 state = palloc(sizeof(OkeysState));
351                 sem = palloc0(sizeof(JsonSemAction));
352
353                 state->lex = lex;
354                 state->result_size = 256;
355                 state->result_count = 0;
356                 state->sent_count = 0;
357                 state->result = palloc(256 * sizeof(char *));
358
359                 sem->semstate = (void *) state;
360                 sem->array_start = okeys_array_start;
361                 sem->scalar = okeys_scalar;
362                 sem->object_field_start = okeys_object_field_start;
363                 /* remainder are all NULL, courtesy of palloc0 above */
364
365                 pg_parse_json(lex, sem);
366                 /* keys are now in state->result */
367
368                 pfree(lex->strval->data);
369                 pfree(lex->strval);
370                 pfree(lex);
371                 pfree(sem);
372
373                 MemoryContextSwitchTo(oldcontext);
374                 funcctx->user_fctx = (void *) state;
375
376         }
377
378         funcctx = SRF_PERCALL_SETUP();
379         state = (OkeysState *) funcctx->user_fctx;
380
381         if (state->sent_count < state->result_count)
382         {
383                 char       *nxt = state->result[state->sent_count++];
384
385                 SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
386         }
387
388         /* cleanup to reduce or eliminate memory leaks */
389         for (i = 0; i < state->result_count; i++)
390                 pfree(state->result[i]);
391         pfree(state->result);
392         pfree(state);
393
394         SRF_RETURN_DONE(funcctx);
395 }
396
397 static void
398 okeys_object_field_start(void *state, char *fname, bool isnull)
399 {
400         OkeysState *_state = (OkeysState *) state;
401
402         /* only collecting keys for the top level object */
403         if (_state->lex->lex_level != 1)
404                 return;
405
406         /* enlarge result array if necessary */
407         if (_state->result_count >= _state->result_size)
408         {
409                 _state->result_size *= 2;
410                 _state->result =
411                         repalloc(_state->result, sizeof(char *) * _state->result_size);
412         }
413
414         /* save a copy of the field name */
415         _state->result[_state->result_count++] = pstrdup(fname);
416 }
417
418 static void
419 okeys_array_start(void *state)
420 {
421         OkeysState *_state = (OkeysState *) state;
422
423         /* top level must be a json object */
424         if (_state->lex->lex_level == 0)
425                 ereport(ERROR,
426                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
427                                  errmsg("cannot call json_object_keys on an array")));
428 }
429
430 static void
431 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
432 {
433         OkeysState *_state = (OkeysState *) state;
434
435         /* top level must be a json object */
436         if (_state->lex->lex_level == 0)
437                 ereport(ERROR,
438                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
439                                  errmsg("cannot call json_object_keys on a scalar")));
440 }
441
442 /*
443  * json and jsonb getter functions
444  * these implement the -> ->> #> and #>> operators
445  * and the json{b?}_extract_path*(json, text, ...) functions
446  */
447
448
449 Datum
450 json_object_field(PG_FUNCTION_ARGS)
451 {
452         text       *json = PG_GETARG_TEXT_P(0);
453         text       *result;
454         text       *fname = PG_GETARG_TEXT_P(1);
455         char       *fnamestr = text_to_cstring(fname);
456
457         result = get_worker(json, fnamestr, -1, NULL, NULL, -1, false);
458
459         if (result != NULL)
460                 PG_RETURN_TEXT_P(result);
461         else
462                 PG_RETURN_NULL();
463 }
464
465 Datum
466 jsonb_object_field(PG_FUNCTION_ARGS)
467 {
468         Jsonb      *jb = PG_GETARG_JSONB(0);
469         text       *key = PG_GETARG_TEXT_PP(1);
470         JsonbValue *v;
471
472         if (JB_ROOT_IS_SCALAR(jb))
473                 ereport(ERROR,
474                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
475                                  errmsg("cannot call jsonb_object_field (jsonb -> text operator) on a scalar")));
476         else if (JB_ROOT_IS_ARRAY(jb))
477                 ereport(ERROR,
478                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
479                                  errmsg("cannot call jsonb_object_field (jsonb -> text operator) on an array")));
480
481         Assert(JB_ROOT_IS_OBJECT(jb));
482
483         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
484                                                                            VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
485
486         if (v != NULL)
487                 PG_RETURN_JSONB(JsonbValueToJsonb(v));
488
489         PG_RETURN_NULL();
490 }
491
492 Datum
493 json_object_field_text(PG_FUNCTION_ARGS)
494 {
495         text       *json = PG_GETARG_TEXT_P(0);
496         text       *result;
497         text       *fname = PG_GETARG_TEXT_P(1);
498         char       *fnamestr = text_to_cstring(fname);
499
500         result = get_worker(json, fnamestr, -1, NULL, NULL, -1, true);
501
502         if (result != NULL)
503                 PG_RETURN_TEXT_P(result);
504         else
505                 PG_RETURN_NULL();
506 }
507
508 Datum
509 jsonb_object_field_text(PG_FUNCTION_ARGS)
510 {
511         Jsonb      *jb = PG_GETARG_JSONB(0);
512         text       *key = PG_GETARG_TEXT_PP(1);
513         JsonbValue *v;
514
515         if (JB_ROOT_IS_SCALAR(jb))
516                 ereport(ERROR,
517                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
518                                  errmsg("cannot call jsonb_object_field_text (jsonb ->> text operator) on a scalar")));
519         else if (JB_ROOT_IS_ARRAY(jb))
520                 ereport(ERROR,
521                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
522                                  errmsg("cannot call jsonb_object_field_text (jsonb ->> text operator) on an array")));
523
524         Assert(JB_ROOT_IS_OBJECT(jb));
525
526         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
527                                                                            VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
528
529         if (v != NULL)
530         {
531                 text       *result = NULL;
532
533                 switch(v->type)
534                 {
535                         case jbvNull:
536                                 break;
537                         case jbvBool:
538                                 result = cstring_to_text(v->val.boolean ? "true" : "false");
539                                 break;
540                         case jbvString:
541                                 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
542                                 break;
543                         case jbvNumeric:
544                                 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
545                                                                                                                                                          PointerGetDatum(v->val.numeric))));
546                                 break;
547                         case jbvBinary:
548                                 {
549                                         StringInfo  jtext = makeStringInfo();
550
551                                         (void) JsonbToCString(jtext, v->val.binary.data, -1);
552                                         result = cstring_to_text_with_len(jtext->data, jtext->len);
553                                 }
554                                 break;
555                         default:
556                                 elog(ERROR, "Wrong jsonb type: %d", v->type);
557                 }
558
559                 if (result)
560                         PG_RETURN_TEXT_P(result);
561         }
562
563         PG_RETURN_NULL();
564 }
565
566 Datum
567 json_array_element(PG_FUNCTION_ARGS)
568 {
569         text       *json = PG_GETARG_TEXT_P(0);
570         text       *result;
571         int                     element = PG_GETARG_INT32(1);
572
573         result = get_worker(json, NULL, element, NULL, NULL, -1, false);
574
575         if (result != NULL)
576                 PG_RETURN_TEXT_P(result);
577         else
578                 PG_RETURN_NULL();
579 }
580
581 Datum
582 jsonb_array_element(PG_FUNCTION_ARGS)
583 {
584         Jsonb      *jb = PG_GETARG_JSONB(0);
585         int                     element = PG_GETARG_INT32(1);
586         JsonbValue *v;
587
588         if (JB_ROOT_IS_SCALAR(jb))
589                 ereport(ERROR,
590                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
591                                  errmsg("cannot call jsonb_array_element (jsonb -> int operator) on a scalar")));
592         else if (JB_ROOT_IS_OBJECT(jb))
593                 ereport(ERROR,
594                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
595                                  errmsg("cannot call jsonb_array_element (jsonb -> int operator) on an object")));
596
597         Assert(JB_ROOT_IS_ARRAY(jb));
598
599         v = getIthJsonbValueFromContainer(&jb->root, element);
600         if (v != NULL)
601                 PG_RETURN_JSONB(JsonbValueToJsonb(v));
602
603         PG_RETURN_NULL();
604 }
605
606 Datum
607 json_array_element_text(PG_FUNCTION_ARGS)
608 {
609         text       *json = PG_GETARG_TEXT_P(0);
610         text       *result;
611         int                     element = PG_GETARG_INT32(1);
612
613         result = get_worker(json, NULL, element, NULL, NULL, -1, true);
614
615         if (result != NULL)
616                 PG_RETURN_TEXT_P(result);
617         else
618                 PG_RETURN_NULL();
619 }
620
621 Datum
622 jsonb_array_element_text(PG_FUNCTION_ARGS)
623 {
624         Jsonb      *jb = PG_GETARG_JSONB(0);
625         int                     element = PG_GETARG_INT32(1);
626         JsonbValue *v;
627
628         if (JB_ROOT_IS_SCALAR(jb))
629                 ereport(ERROR,
630                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
631                                  errmsg("cannot call jsonb_array_element_text on a scalar")));
632         else if (JB_ROOT_IS_OBJECT(jb))
633                 ereport(ERROR,
634                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
635                            errmsg("cannot call jsonb_array_element_text on an object")));
636
637         Assert(JB_ROOT_IS_ARRAY(jb));
638
639         v = getIthJsonbValueFromContainer(&jb->root, element);
640         if (v != NULL)
641         {
642                 text       *result = NULL;
643
644                 switch(v->type)
645                 {
646                         case jbvNull:
647                                 break;
648                         case jbvBool:
649                                 result = cstring_to_text(v->val.boolean ? "true" : "false");
650                                 break;
651                         case jbvString:
652                                 result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
653                                 break;
654                         case jbvNumeric:
655                                 result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
656                                                                                         PointerGetDatum(v->val.numeric))));
657                                 break;
658                         case jbvBinary:
659                                 {
660                                         StringInfo  jtext = makeStringInfo();
661
662                                         (void) JsonbToCString(jtext, v->val.binary.data, -1);
663                                         result = cstring_to_text_with_len(jtext->data, jtext->len);
664                                 }
665                                 break;
666                         default:
667                                 elog(ERROR, "Wrong jsonb type: %d", v->type);
668                 }
669
670                 if (result)
671                         PG_RETURN_TEXT_P(result);
672         }
673
674         PG_RETURN_NULL();
675 }
676
677 Datum
678 json_extract_path(PG_FUNCTION_ARGS)
679 {
680         return get_path_all(fcinfo, false);
681 }
682
683 Datum
684 json_extract_path_text(PG_FUNCTION_ARGS)
685 {
686         return get_path_all(fcinfo, true);
687 }
688
689 /*
690  * common routine for extract_path functions
691  */
692 static inline Datum
693 get_path_all(FunctionCallInfo fcinfo, bool as_text)
694 {
695         text       *json;
696         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
697         text       *result;
698         Datum      *pathtext;
699         bool       *pathnulls;
700         int                     npath;
701         char      **tpath;
702         int                *ipath;
703         int                     i;
704         long            ind;
705         char       *endptr;
706
707         json = PG_GETARG_TEXT_P(0);
708
709         if (array_contains_nulls(path))
710                 ereport(ERROR,
711                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
712                                  errmsg("cannot call function with null path elements")));
713
714
715         deconstruct_array(path, TEXTOID, -1, false, 'i',
716                                           &pathtext, &pathnulls, &npath);
717
718         tpath = palloc(npath * sizeof(char *));
719         ipath = palloc(npath * sizeof(int));
720
721
722         for (i = 0; i < npath; i++)
723         {
724                 tpath[i] = TextDatumGetCString(pathtext[i]);
725                 if (*tpath[i] == '\0')
726                         ereport(
727                                         ERROR,
728                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
729                                    errmsg("cannot call function with empty path elements")));
730
731                 /*
732                  * we have no idea at this stage what structure the document is so
733                  * just convert anything in the path that we can to an integer and set
734                  * all the other integers to -1 which will never match.
735                  */
736                 ind = strtol(tpath[i], &endptr, 10);
737                 if (*endptr == '\0' && ind <= INT_MAX && ind >= 0)
738                         ipath[i] = (int) ind;
739                 else
740                         ipath[i] = -1;
741         }
742
743
744         result = get_worker(json, NULL, -1, tpath, ipath, npath, as_text);
745
746         if (result != NULL)
747                 PG_RETURN_TEXT_P(result);
748         else
749                 /* null is NULL, regardless */
750                 PG_RETURN_NULL();
751 }
752
753 /*
754  * get_worker
755  *
756  * common worker for all the json getter functions
757  */
758 static inline text *
759 get_worker(text *json,
760                    char *field,
761                    int elem_index,
762                    char **tpath,
763                    int *ipath,
764                    int npath,
765                    bool normalize_results)
766 {
767         GetState   *state;
768         JsonLexContext *lex = makeJsonLexContext(json, true);
769         JsonSemAction *sem;
770
771         /* only allowed to use one of these */
772         Assert(elem_index < 0 || (tpath == NULL && ipath == NULL && field == NULL));
773         Assert(tpath == NULL || field == NULL);
774
775         state = palloc0(sizeof(GetState));
776         sem = palloc0(sizeof(JsonSemAction));
777
778         state->lex = lex;
779         /* is it "_as_text" variant? */
780         state->normalize_results = normalize_results;
781         if (field != NULL)
782         {
783                 /* single text argument */
784                 state->search_type = JSON_SEARCH_OBJECT;
785                 state->search_term = field;
786         }
787         else if (tpath != NULL)
788         {
789                 /* path array argument */
790                 state->search_type = JSON_SEARCH_PATH;
791                 state->path = tpath;
792                 state->npath = npath;
793                 state->current_path = palloc(sizeof(char *) * npath);
794                 state->pathok = palloc0(sizeof(bool) * npath);
795                 state->pathok[0] = true;
796                 state->array_level_index = palloc(sizeof(int) * npath);
797                 state->path_level_index = ipath;
798
799         }
800         else
801         {
802                 /* single integer argument */
803                 state->search_type = JSON_SEARCH_ARRAY;
804                 state->search_index = elem_index;
805                 state->array_index = -1;
806         }
807
808         sem->semstate = (void *) state;
809
810         /*
811          * Not all      variants need all the semantic routines. only set the ones
812          * that are actually needed for maximum efficiency.
813          */
814         sem->object_start = get_object_start;
815         sem->array_start = get_array_start;
816         sem->scalar = get_scalar;
817         if (field != NULL || tpath != NULL)
818         {
819                 sem->object_field_start = get_object_field_start;
820                 sem->object_field_end = get_object_field_end;
821         }
822         if (field == NULL)
823         {
824                 sem->array_element_start = get_array_element_start;
825                 sem->array_element_end = get_array_element_end;
826         }
827
828         pg_parse_json(lex, sem);
829
830         return state->tresult;
831 }
832
833 static void
834 get_object_start(void *state)
835 {
836         GetState   *_state = (GetState *) state;
837
838         /* json structure check */
839         if (_state->lex->lex_level == 0 && _state->search_type == JSON_SEARCH_ARRAY)
840                 ereport(ERROR,
841                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
842                                  errmsg("cannot extract array element from a non-array")));
843 }
844
845 static void
846 get_object_field_start(void *state, char *fname, bool isnull)
847 {
848         GetState   *_state = (GetState *) state;
849         bool            get_next = false;
850         int                     lex_level = _state->lex->lex_level;
851
852         if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
853                 strcmp(fname, _state->search_term) == 0)
854         {
855
856                 _state->tresult = NULL;
857                 _state->result_start = NULL;
858                 get_next = true;
859         }
860         else if (_state->search_type == JSON_SEARCH_PATH &&
861                          lex_level <= _state->npath &&
862                          _state->pathok[_state->lex->lex_level - 1] &&
863                          strcmp(fname, _state->path[lex_level - 1]) == 0)
864         {
865                 /* path search, path so far is ok,      and we have a match */
866
867                 /* this object overrides any previous matching object */
868
869                 _state->tresult = NULL;
870                 _state->result_start = NULL;
871
872                 /* if not at end of path just mark path ok */
873                 if (lex_level < _state->npath)
874                         _state->pathok[lex_level] = true;
875
876                 /* end of path, so we want this value */
877                 if (lex_level == _state->npath)
878                         get_next = true;
879         }
880
881         if (get_next)
882         {
883                 if (_state->normalize_results &&
884                         _state->lex->token_type == JSON_TOKEN_STRING)
885                 {
886                         /* for as_text variants, tell get_scalar to set it for us */
887                         _state->next_scalar = true;
888                 }
889                 else
890                 {
891                         /* for non-as_text variants, just note the json starting point */
892                         _state->result_start = _state->lex->token_start;
893                 }
894         }
895 }
896
897 static void
898 get_object_field_end(void *state, char *fname, bool isnull)
899 {
900         GetState   *_state = (GetState *) state;
901         bool            get_last = false;
902         int                     lex_level = _state->lex->lex_level;
903
904
905         /* same tests as in get_object_field_start, mutatis mutandis */
906         if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
907                 strcmp(fname, _state->search_term) == 0)
908         {
909                 get_last = true;
910         }
911         else if (_state->search_type == JSON_SEARCH_PATH &&
912                          lex_level <= _state->npath &&
913                          _state->pathok[lex_level - 1] &&
914                          strcmp(fname, _state->path[lex_level - 1]) == 0)
915         {
916                 /* done with this field so reset pathok */
917                 if (lex_level < _state->npath)
918                         _state->pathok[lex_level] = false;
919
920                 if (lex_level == _state->npath)
921                         get_last = true;
922         }
923
924         /* for as_test variants our work is already done */
925         if (get_last && _state->result_start != NULL)
926         {
927                 /*
928                  * make a text object from the string from the prevously noted json
929                  * start up to the end of the previous token (the lexer is by now
930                  * ahead of us on whatever came after what we're interested in).
931                  */
932                 int                     len = _state->lex->prev_token_terminator - _state->result_start;
933
934                 if (isnull && _state->normalize_results)
935                         _state->tresult = (text *) NULL;
936                 else
937                         _state->tresult = cstring_to_text_with_len(_state->result_start, len);
938         }
939
940         /*
941          * don't need to reset _state->result_start b/c we're only returning one
942          * datum, the conditions should not occur more than once, and this lets us
943          * check cheaply that they don't (see object_field_start() )
944          */
945 }
946
947 static void
948 get_array_start(void *state)
949 {
950         GetState   *_state = (GetState *) state;
951         int                     lex_level = _state->lex->lex_level;
952
953         /* json structure check */
954         if (lex_level == 0 && _state->search_type == JSON_SEARCH_OBJECT)
955                 ereport(ERROR,
956                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
957                                  errmsg("cannot extract field from a non-object")));
958
959         /*
960          * initialize array count for this nesting level Note: the lex_level seen
961          * by array_start is one less than that seen by the elements of the array.
962          */
963         if (_state->search_type == JSON_SEARCH_PATH &&
964                 lex_level < _state->npath)
965                 _state->array_level_index[lex_level] = -1;
966 }
967
968 static void
969 get_array_element_start(void *state, bool isnull)
970 {
971         GetState   *_state = (GetState *) state;
972         bool            get_next = false;
973         int                     lex_level = _state->lex->lex_level;
974
975         if (lex_level == 1 && _state->search_type == JSON_SEARCH_ARRAY)
976         {
977                 /* single integer search */
978                 _state->array_index++;
979                 if (_state->array_index == _state->search_index)
980                         get_next = true;
981         }
982         else if (_state->search_type == JSON_SEARCH_PATH &&
983                          lex_level <= _state->npath &&
984                          _state->pathok[lex_level - 1])
985         {
986                 /*
987                  * path search, path so far is ok
988                  *
989                  * increment the array counter. no point doing this if we already know
990                  * the path is bad.
991                  *
992                  * then check if we have a match.
993                  */
994
995                 if (++_state->array_level_index[lex_level - 1] ==
996                         _state->path_level_index[lex_level - 1])
997                 {
998                         if (lex_level == _state->npath)
999                         {
1000                                 /* match and at end of path, so get value */
1001                                 get_next = true;
1002                         }
1003                         else
1004                         {
1005                                 /* not at end of path just mark path ok */
1006                                 _state->pathok[lex_level] = true;
1007                         }
1008                 }
1009
1010         }
1011
1012         /* same logic as for objects */
1013         if (get_next)
1014         {
1015                 if (_state->normalize_results &&
1016                         _state->lex->token_type == JSON_TOKEN_STRING)
1017                 {
1018                         _state->next_scalar = true;
1019                 }
1020                 else
1021                 {
1022                         _state->result_start = _state->lex->token_start;
1023                 }
1024         }
1025 }
1026
1027 static void
1028 get_array_element_end(void *state, bool isnull)
1029 {
1030         GetState   *_state = (GetState *) state;
1031         bool            get_last = false;
1032         int                     lex_level = _state->lex->lex_level;
1033
1034         /* same logic as in get_object_end, modified for arrays */
1035
1036         if (lex_level == 1 && _state->search_type == JSON_SEARCH_ARRAY &&
1037                 _state->array_index == _state->search_index)
1038         {
1039                 get_last = true;
1040         }
1041         else if (_state->search_type == JSON_SEARCH_PATH &&
1042                          lex_level <= _state->npath &&
1043                          _state->pathok[lex_level - 1] &&
1044                          _state->array_level_index[lex_level - 1] ==
1045                          _state->path_level_index[lex_level - 1])
1046         {
1047                 /* done with this element so reset pathok */
1048                 if (lex_level < _state->npath)
1049                         _state->pathok[lex_level] = false;
1050
1051                 if (lex_level == _state->npath)
1052                         get_last = true;
1053         }
1054         if (get_last && _state->result_start != NULL)
1055         {
1056                 int                     len = _state->lex->prev_token_terminator - _state->result_start;
1057
1058                 if (isnull && _state->normalize_results)
1059                         _state->tresult = (text *) NULL;
1060                 else
1061                         _state->tresult = cstring_to_text_with_len(_state->result_start, len);
1062         }
1063 }
1064
1065 static void
1066 get_scalar(void *state, char *token, JsonTokenType tokentype)
1067 {
1068         GetState   *_state = (GetState *) state;
1069
1070         if (_state->lex->lex_level == 0 && _state->search_type != JSON_SEARCH_PATH)
1071                 ereport(ERROR,
1072                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1073                                  errmsg("cannot extract element from a scalar")));
1074         if (_state->next_scalar)
1075         {
1076                 /* a de-escaped text value is wanted, so supply it */
1077                 _state->tresult = cstring_to_text(token);
1078                 /* make sure the next call to get_scalar doesn't overwrite it */
1079                 _state->next_scalar = false;
1080         }
1081
1082 }
1083
1084 Datum
1085 jsonb_extract_path(PG_FUNCTION_ARGS)
1086 {
1087         return get_jsonb_path_all(fcinfo, false);
1088 }
1089
1090 Datum
1091 jsonb_extract_path_text(PG_FUNCTION_ARGS)
1092 {
1093         return get_jsonb_path_all(fcinfo, true);
1094 }
1095
1096 static inline Datum
1097 get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1098 {
1099         Jsonb      *jb = PG_GETARG_JSONB(0);
1100         ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
1101         Datum      *pathtext;
1102         bool       *pathnulls;
1103         int                     npath;
1104         int                     i;
1105         Jsonb      *res;
1106         bool            have_object = false,
1107                                 have_array = false;
1108         JsonbValue *jbvp = NULL;
1109         JsonbValue      tv;
1110         JsonbContainer *container;
1111
1112         if (array_contains_nulls(path))
1113                 ereport(ERROR,
1114                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1115                                  errmsg("cannot call function with null path elements")));
1116
1117         deconstruct_array(path, TEXTOID, -1, false, 'i',
1118                                           &pathtext, &pathnulls, &npath);
1119
1120         if (JB_ROOT_IS_OBJECT(jb))
1121                 have_object = true;
1122         else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1123                 have_array = true;
1124
1125         container = &jb->root;
1126
1127         for (i = 0; i < npath; i++)
1128         {
1129                 if (have_object)
1130                 {
1131                         jbvp = findJsonbValueFromContainerLen(container,
1132                                                                                                   JB_FOBJECT,
1133                                                                                                   VARDATA_ANY(pathtext[i]),
1134                                                                                          VARSIZE_ANY_EXHDR(pathtext[i]));
1135                 }
1136                 else if (have_array)
1137                 {
1138                         long            lindex;
1139                         uint32          index;
1140                         char       *indextext = TextDatumGetCString(pathtext[i]);
1141                         char       *endptr;
1142
1143                         lindex = strtol(indextext, &endptr, 10);
1144                         if (*endptr != '\0' || lindex > INT_MAX || lindex < 0)
1145                                 PG_RETURN_NULL();
1146                         index = (uint32) lindex;
1147                         jbvp = getIthJsonbValueFromContainer(container, index);
1148                 }
1149                 else
1150                 {
1151                         if (i == 0)
1152                                 ereport(ERROR,
1153                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1154                                                  errmsg("cannot call extract path from a scalar")));
1155                         PG_RETURN_NULL();
1156                 }
1157
1158                 if (jbvp == NULL)
1159                         PG_RETURN_NULL();
1160                 else if (i == npath - 1)
1161                         break;
1162
1163                 if (jbvp->type == jbvBinary)
1164                 {
1165                         JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1166                         int                     r;
1167
1168                         r = JsonbIteratorNext(&it, &tv, true);
1169                         container = (JsonbContainer *) jbvp->val.binary.data;
1170                         have_object = r == WJB_BEGIN_OBJECT;
1171                         have_array = r == WJB_BEGIN_ARRAY;
1172                 }
1173                 else
1174                 {
1175                         have_object = jbvp->type == jbvObject;
1176                         have_array = jbvp->type == jbvArray;
1177                 }
1178         }
1179
1180         if (as_text)
1181         {
1182                 if (jbvp->type == jbvString)
1183                         PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val, jbvp->val.string.len));
1184                 else if (jbvp->type == jbvNull)
1185                         PG_RETURN_NULL();
1186         }
1187
1188         res = JsonbValueToJsonb(jbvp);
1189
1190         if (as_text)
1191         {
1192                 PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1193                                                                                                                 &res->root,
1194                                                                                                                 VARSIZE(res))));
1195         }
1196         else
1197         {
1198                 /* not text mode - just hand back the jsonb */
1199                 PG_RETURN_JSONB(res);
1200         }
1201 }
1202
1203 /*
1204  * SQL function json_array_length(json) -> int
1205  */
1206 Datum
1207 json_array_length(PG_FUNCTION_ARGS)
1208 {
1209         text       *json;
1210
1211         AlenState  *state;
1212         JsonLexContext *lex;
1213         JsonSemAction *sem;
1214
1215         json = PG_GETARG_TEXT_P(0);
1216         lex = makeJsonLexContext(json, false);
1217         state = palloc0(sizeof(AlenState));
1218         sem = palloc0(sizeof(JsonSemAction));
1219
1220         /* palloc0 does this for us */
1221 #if 0
1222         state->count = 0;
1223 #endif
1224         state->lex = lex;
1225
1226         sem->semstate = (void *) state;
1227         sem->object_start = alen_object_start;
1228         sem->scalar = alen_scalar;
1229         sem->array_element_start = alen_array_element_start;
1230
1231         pg_parse_json(lex, sem);
1232
1233         PG_RETURN_INT32(state->count);
1234 }
1235
1236 Datum
1237 jsonb_array_length(PG_FUNCTION_ARGS)
1238 {
1239         Jsonb      *jb = PG_GETARG_JSONB(0);
1240
1241         if (JB_ROOT_IS_SCALAR(jb))
1242                 ereport(ERROR,
1243                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1244                                  errmsg("cannot get array length of a scalar")));
1245         else if (!JB_ROOT_IS_ARRAY(jb))
1246                 ereport(ERROR,
1247                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1248                                  errmsg("cannot get array length of a non-array")));
1249
1250         PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1251 }
1252
1253 /*
1254  * These next two check ensure that the json is an array (since it can't be
1255  * a scalar or an object).
1256  */
1257
1258 static void
1259 alen_object_start(void *state)
1260 {
1261         AlenState  *_state = (AlenState *) state;
1262
1263         /* json structure check */
1264         if (_state->lex->lex_level == 0)
1265                 ereport(ERROR,
1266                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1267                                  errmsg("cannot get array length of a non-array")));
1268 }
1269
1270 static void
1271 alen_scalar(void *state, char *token, JsonTokenType tokentype)
1272 {
1273         AlenState  *_state = (AlenState *) state;
1274
1275         /* json structure check */
1276         if (_state->lex->lex_level == 0)
1277                 ereport(ERROR,
1278                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1279                                  errmsg("cannot get array length of a scalar")));
1280 }
1281
1282 static void
1283 alen_array_element_start(void *state, bool isnull)
1284 {
1285         AlenState  *_state = (AlenState *) state;
1286
1287         /* just count up all the level 1 elements */
1288         if (_state->lex->lex_level == 1)
1289                 _state->count++;
1290 }
1291
1292 /*
1293  * SQL function json_each and json_each_text
1294  *
1295  * decompose a json object into key value pairs.
1296  *
1297  * Unlike json_object_keys() these SRFs operate in materialize mode,
1298  * stashing results into a Tuplestore object as they go.
1299  * The construction of tuples is done using a temporary memory context
1300  * that is cleared out after each tuple is built.
1301  */
1302 Datum
1303 json_each(PG_FUNCTION_ARGS)
1304 {
1305         return each_worker(fcinfo, false);
1306 }
1307
1308 Datum
1309 jsonb_each(PG_FUNCTION_ARGS)
1310 {
1311         return each_worker_jsonb(fcinfo, false);
1312 }
1313
1314 Datum
1315 json_each_text(PG_FUNCTION_ARGS)
1316 {
1317         return each_worker(fcinfo, true);
1318 }
1319
1320 Datum
1321 jsonb_each_text(PG_FUNCTION_ARGS)
1322 {
1323         return each_worker_jsonb(fcinfo, true);
1324 }
1325
1326 static inline Datum
1327 each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
1328 {
1329         Jsonb      *jb = PG_GETARG_JSONB(0);
1330         ReturnSetInfo *rsi;
1331         Tuplestorestate *tuple_store;
1332         TupleDesc       tupdesc;
1333         TupleDesc       ret_tdesc;
1334         MemoryContext old_cxt,
1335                                 tmp_cxt;
1336         bool            skipNested = false;
1337         JsonbIterator *it;
1338         JsonbValue      v;
1339         int                     r;
1340
1341         if (!JB_ROOT_IS_OBJECT(jb))
1342                 ereport(ERROR,
1343                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1344                                  errmsg("cannot call jsonb_each%s on a non-object",
1345                                                 as_text ? "_text" : "")));
1346
1347         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1348
1349         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1350                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1351                 rsi->expectedDesc == NULL)
1352                 ereport(ERROR,
1353                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1354                                  errmsg("set-valued function called in context that "
1355                                                 "cannot accept a set")));
1356
1357
1358         rsi->returnMode = SFRM_Materialize;
1359
1360         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1361                 ereport(ERROR,
1362                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1363                                  errmsg("function returning record called in context "
1364                                                 "that cannot accept type record")));
1365
1366         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1367
1368         ret_tdesc = CreateTupleDescCopy(tupdesc);
1369         BlessTupleDesc(ret_tdesc);
1370         tuple_store =
1371                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1372                                                           false, work_mem);
1373
1374         MemoryContextSwitchTo(old_cxt);
1375
1376         tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1377                                                                         "jsonb_each temporary cxt",
1378                                                                         ALLOCSET_DEFAULT_MINSIZE,
1379                                                                         ALLOCSET_DEFAULT_INITSIZE,
1380                                                                         ALLOCSET_DEFAULT_MAXSIZE);
1381
1382
1383         it = JsonbIteratorInit(&jb->root);
1384
1385         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1386         {
1387                 skipNested = true;
1388
1389                 if (r == WJB_KEY)
1390                 {
1391                         text       *key;
1392                         HeapTuple       tuple;
1393                         Datum           values[2];
1394                         bool            nulls[2] = {false, false};
1395
1396                         /* Use the tmp context so we can clean up after each tuple is done */
1397                         old_cxt = MemoryContextSwitchTo(tmp_cxt);
1398
1399                         key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1400
1401                         /*
1402                          * The next thing the iterator fetches should be the value, no
1403                          * matter what shape it is.
1404                          */
1405                         r = JsonbIteratorNext(&it, &v, skipNested);
1406
1407                         values[0] = PointerGetDatum(key);
1408
1409                         if (as_text)
1410                         {
1411                                 if (v.type == jbvNull)
1412                                 {
1413                                         /* a json null is an sql null in text mode */
1414                                         nulls[1] = true;
1415                                         values[1] = (Datum) NULL;
1416                                 }
1417                                 else
1418                                 {
1419                                         text       *sv;
1420
1421                                         if (v.type == jbvString)
1422                                         {
1423                                                 /* In text mode, scalar strings should be dequoted */
1424                                                 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1425                                         }
1426                                         else
1427                                         {
1428                                                 /* Turn anything else into a json string */
1429                                                 StringInfo      jtext = makeStringInfo();
1430                                                 Jsonb      *jb = JsonbValueToJsonb(&v);
1431
1432                                                 (void) JsonbToCString(jtext, &jb->root, 0);
1433                                                 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1434                                         }
1435
1436                                         values[1] = PointerGetDatum(sv);
1437                                 }
1438                         }
1439                         else
1440                         {
1441                                 /* Not in text mode, just return the Jsonb */
1442                                 Jsonb      *val = JsonbValueToJsonb(&v);
1443
1444                                 values[1] = PointerGetDatum(val);
1445                         }
1446
1447                         tuple = heap_form_tuple(ret_tdesc, values, nulls);
1448
1449                         tuplestore_puttuple(tuple_store, tuple);
1450
1451                         /* clean up and switch back */
1452                         MemoryContextSwitchTo(old_cxt);
1453                         MemoryContextReset(tmp_cxt);
1454                 }
1455         }
1456
1457         MemoryContextDelete(tmp_cxt);
1458
1459         rsi->setResult = tuple_store;
1460         rsi->setDesc = ret_tdesc;
1461
1462         PG_RETURN_NULL();
1463 }
1464
1465
1466 static inline Datum
1467 each_worker(FunctionCallInfo fcinfo, bool as_text)
1468 {
1469         text       *json;
1470         JsonLexContext *lex;
1471         JsonSemAction *sem;
1472         ReturnSetInfo *rsi;
1473         MemoryContext old_cxt;
1474         TupleDesc       tupdesc;
1475         EachState  *state;
1476
1477         json = PG_GETARG_TEXT_P(0);
1478
1479         lex = makeJsonLexContext(json, true);
1480         state = palloc0(sizeof(EachState));
1481         sem = palloc0(sizeof(JsonSemAction));
1482
1483         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1484
1485         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1486                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1487                 rsi->expectedDesc == NULL)
1488                 ereport(ERROR,
1489                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1490                                  errmsg("set-valued function called in context that "
1491                                                 "cannot accept a set")));
1492
1493
1494         rsi->returnMode = SFRM_Materialize;
1495
1496         (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1497
1498         /* make these in a sufficiently long-lived memory context */
1499         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1500
1501         state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1502         BlessTupleDesc(state->ret_tdesc);
1503         state->tuple_store =
1504                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1505                                                           false, work_mem);
1506
1507         MemoryContextSwitchTo(old_cxt);
1508
1509         sem->semstate = (void *) state;
1510         sem->array_start = each_array_start;
1511         sem->scalar = each_scalar;
1512         sem->object_field_start = each_object_field_start;
1513         sem->object_field_end = each_object_field_end;
1514
1515         state->normalize_results = as_text;
1516         state->next_scalar = false;
1517
1518         state->lex = lex;
1519         state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1520                                                                                    "json_each temporary cxt",
1521                                                                                    ALLOCSET_DEFAULT_MINSIZE,
1522                                                                                    ALLOCSET_DEFAULT_INITSIZE,
1523                                                                                    ALLOCSET_DEFAULT_MAXSIZE);
1524
1525         pg_parse_json(lex, sem);
1526
1527         MemoryContextDelete(state->tmp_cxt);
1528
1529         rsi->setResult = state->tuple_store;
1530         rsi->setDesc = state->ret_tdesc;
1531
1532         PG_RETURN_NULL();
1533 }
1534
1535
1536 static void
1537 each_object_field_start(void *state, char *fname, bool isnull)
1538 {
1539         EachState  *_state = (EachState *) state;
1540
1541         /* save a pointer to where the value starts */
1542         if (_state->lex->lex_level == 1)
1543         {
1544                 /*
1545                  * next_scalar will be reset in the object_field_end handler, and
1546                  * since we know the value is a scalar there is no danger of it being
1547                  * on while recursing down the tree.
1548                  */
1549                 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1550                         _state->next_scalar = true;
1551                 else
1552                         _state->result_start = _state->lex->token_start;
1553         }
1554 }
1555
1556 static void
1557 each_object_field_end(void *state, char *fname, bool isnull)
1558 {
1559         EachState  *_state = (EachState *) state;
1560         MemoryContext old_cxt;
1561         int                     len;
1562         text       *val;
1563         HeapTuple       tuple;
1564         Datum           values[2];
1565         bool            nulls[2] = {false, false};
1566
1567         /* skip over nested objects */
1568         if (_state->lex->lex_level != 1)
1569                 return;
1570
1571         /* use the tmp context so we can clean up after each tuple is done */
1572         old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1573
1574         values[0] = CStringGetTextDatum(fname);
1575
1576         if (isnull && _state->normalize_results)
1577         {
1578                 nulls[1] = true;
1579                 values[1] = (Datum) NULL;
1580         }
1581         else if (_state->next_scalar)
1582         {
1583                 values[1] = CStringGetTextDatum(_state->normalized_scalar);
1584                 _state->next_scalar = false;
1585         }
1586         else
1587         {
1588                 len = _state->lex->prev_token_terminator - _state->result_start;
1589                 val = cstring_to_text_with_len(_state->result_start, len);
1590                 values[1] = PointerGetDatum(val);
1591         }
1592
1593
1594         tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1595
1596         tuplestore_puttuple(_state->tuple_store, tuple);
1597
1598         /* clean up and switch back */
1599         MemoryContextSwitchTo(old_cxt);
1600         MemoryContextReset(_state->tmp_cxt);
1601 }
1602
1603 static void
1604 each_array_start(void *state)
1605 {
1606         EachState  *_state = (EachState *) state;
1607
1608         /* json structure check */
1609         if (_state->lex->lex_level == 0)
1610                 ereport(ERROR,
1611                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1612                                  errmsg("cannot deconstruct an array as an object")));
1613 }
1614
1615 static void
1616 each_scalar(void *state, char *token, JsonTokenType tokentype)
1617 {
1618         EachState  *_state = (EachState *) state;
1619
1620         /* json structure check */
1621         if (_state->lex->lex_level == 0)
1622                 ereport(ERROR,
1623                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1624                                  errmsg("cannot deconstruct a scalar")));
1625
1626         /* supply de-escaped value if required */
1627         if (_state->next_scalar)
1628                 _state->normalized_scalar = token;
1629 }
1630
1631 /*
1632  * SQL functions json_array_elements and json_array_elements_text
1633  *
1634  * get the elements from a json array
1635  *
1636  * a lot of this processing is similar to the json_each* functions
1637  */
1638
1639 Datum
1640 jsonb_array_elements(PG_FUNCTION_ARGS)
1641 {
1642         return elements_worker_jsonb(fcinfo, false);
1643 }
1644
1645 Datum
1646 jsonb_array_elements_text(PG_FUNCTION_ARGS)
1647 {
1648         return elements_worker_jsonb(fcinfo, true);
1649 }
1650
1651 static inline Datum
1652 elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
1653 {
1654         Jsonb      *jb = PG_GETARG_JSONB(0);
1655         ReturnSetInfo *rsi;
1656         Tuplestorestate *tuple_store;
1657         TupleDesc       tupdesc;
1658         TupleDesc       ret_tdesc;
1659         MemoryContext old_cxt,
1660                                 tmp_cxt;
1661         bool            skipNested = false;
1662         JsonbIterator *it;
1663         JsonbValue      v;
1664         int                     r;
1665
1666         if (JB_ROOT_IS_SCALAR(jb))
1667                 ereport(ERROR,
1668                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1669                                  errmsg("cannot extract elements from a scalar")));
1670         else if (!JB_ROOT_IS_ARRAY(jb))
1671                 ereport(ERROR,
1672                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1673                                  errmsg("cannot extract elements from an object")));
1674
1675         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1676
1677         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1678                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1679                 rsi->expectedDesc == NULL)
1680                 ereport(ERROR,
1681                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1682                                  errmsg("set-valued function called in context that "
1683                                                 "cannot accept a set")));
1684
1685
1686         rsi->returnMode = SFRM_Materialize;
1687
1688         /* it's a simple type, so don't use get_call_result_type() */
1689         tupdesc = rsi->expectedDesc;
1690
1691         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1692
1693         ret_tdesc = CreateTupleDescCopy(tupdesc);
1694         BlessTupleDesc(ret_tdesc);
1695         tuple_store =
1696                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1697                                                           false, work_mem);
1698
1699         MemoryContextSwitchTo(old_cxt);
1700
1701         tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1702                                                                         "jsonb_each temporary cxt",
1703                                                                         ALLOCSET_DEFAULT_MINSIZE,
1704                                                                         ALLOCSET_DEFAULT_INITSIZE,
1705                                                                         ALLOCSET_DEFAULT_MAXSIZE);
1706
1707
1708         it = JsonbIteratorInit(&jb->root);
1709
1710         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1711         {
1712                 skipNested = true;
1713
1714                 if (r == WJB_ELEM)
1715                 {
1716                         HeapTuple       tuple;
1717                         Datum           values[1];
1718                         bool            nulls[1] = {false};
1719
1720                         /* use the tmp context so we can clean up after each tuple is done */
1721                         old_cxt = MemoryContextSwitchTo(tmp_cxt);
1722
1723                         if (!as_text)
1724                         {
1725                                 Jsonb      *val = JsonbValueToJsonb(&v);
1726
1727                                 values[0] = PointerGetDatum(val);
1728                         }
1729                         else
1730                         {
1731                                 if (v.type == jbvNull)
1732                                 {
1733                                         /* a json null is an sql null in text mode */
1734                                         nulls[0] = true;
1735                                         values[0] = (Datum) NULL;
1736                                 }
1737                                 else
1738                                 {
1739                                         text       *sv;
1740
1741                                         if (v.type == jbvString)
1742                                         {
1743                                                 /* in text mode scalar strings should be dequoted */
1744                                                 sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1745                                         }
1746                                         else
1747                                         {
1748                                                 /* turn anything else into a json string */
1749                                                 StringInfo      jtext = makeStringInfo();
1750                                                 Jsonb      *jb = JsonbValueToJsonb(&v);
1751
1752                                                 (void) JsonbToCString(jtext, &jb->root, 0);
1753                                                 sv = cstring_to_text_with_len(jtext->data, jtext->len);
1754                                         }
1755
1756                                         values[0] = PointerGetDatum(sv);
1757                                 }
1758                         }
1759
1760                         tuple = heap_form_tuple(ret_tdesc, values, nulls);
1761
1762                         tuplestore_puttuple(tuple_store, tuple);
1763
1764                         /* clean up and switch back */
1765                         MemoryContextSwitchTo(old_cxt);
1766                         MemoryContextReset(tmp_cxt);
1767                 }
1768         }
1769
1770         MemoryContextDelete(tmp_cxt);
1771
1772         rsi->setResult = tuple_store;
1773         rsi->setDesc = ret_tdesc;
1774
1775         PG_RETURN_NULL();
1776 }
1777
1778 Datum
1779 json_array_elements(PG_FUNCTION_ARGS)
1780 {
1781         return elements_worker(fcinfo, false);
1782 }
1783
1784 Datum
1785 json_array_elements_text(PG_FUNCTION_ARGS)
1786 {
1787         return elements_worker(fcinfo, true);
1788 }
1789
1790 static inline Datum
1791 elements_worker(FunctionCallInfo fcinfo, bool as_text)
1792 {
1793         text       *json = PG_GETARG_TEXT_P(0);
1794
1795         /* elements only needs escaped strings when as_text */
1796         JsonLexContext *lex = makeJsonLexContext(json, as_text);
1797         JsonSemAction *sem;
1798         ReturnSetInfo *rsi;
1799         MemoryContext old_cxt;
1800         TupleDesc       tupdesc;
1801         ElementsState *state;
1802
1803         state = palloc0(sizeof(ElementsState));
1804         sem = palloc0(sizeof(JsonSemAction));
1805
1806         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1807
1808         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1809                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
1810                 rsi->expectedDesc == NULL)
1811                 ereport(ERROR,
1812                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1813                                  errmsg("set-valued function called in context that "
1814                                                 "cannot accept a set")));
1815
1816
1817         rsi->returnMode = SFRM_Materialize;
1818
1819         /* it's a simple type, so don't use get_call_result_type() */
1820         tupdesc = rsi->expectedDesc;
1821
1822         /* make these in a sufficiently long-lived memory context */
1823         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1824
1825         state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1826         BlessTupleDesc(state->ret_tdesc);
1827         state->tuple_store =
1828                 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
1829                                                           false, work_mem);
1830
1831         MemoryContextSwitchTo(old_cxt);
1832
1833         sem->semstate = (void *) state;
1834         sem->object_start = elements_object_start;
1835         sem->scalar = elements_scalar;
1836         sem->array_element_start = elements_array_element_start;
1837         sem->array_element_end = elements_array_element_end;
1838
1839         state->normalize_results = as_text;
1840         state->next_scalar = false;
1841
1842         state->lex = lex;
1843         state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
1844                                                                                  "json_array_elements temporary cxt",
1845                                                                                    ALLOCSET_DEFAULT_MINSIZE,
1846                                                                                    ALLOCSET_DEFAULT_INITSIZE,
1847                                                                                    ALLOCSET_DEFAULT_MAXSIZE);
1848
1849         pg_parse_json(lex, sem);
1850
1851         MemoryContextDelete(state->tmp_cxt);
1852
1853         rsi->setResult = state->tuple_store;
1854         rsi->setDesc = state->ret_tdesc;
1855
1856         PG_RETURN_NULL();
1857 }
1858
1859 static void
1860 elements_array_element_start(void *state, bool isnull)
1861 {
1862         ElementsState *_state = (ElementsState *) state;
1863
1864         /* save a pointer to where the value starts */
1865         if (_state->lex->lex_level == 1)
1866         {
1867                 /*
1868                  * next_scalar will be reset in the array_element_end handler, and
1869                  * since we know the value is a scalar there is no danger of it being
1870                  * on while recursing down the tree.
1871                  */
1872                 if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1873                         _state->next_scalar = true;
1874                 else
1875                         _state->result_start = _state->lex->token_start;
1876         }
1877 }
1878
1879 static void
1880 elements_array_element_end(void *state, bool isnull)
1881 {
1882         ElementsState *_state = (ElementsState *) state;
1883         MemoryContext old_cxt;
1884         int                     len;
1885         text       *val;
1886         HeapTuple       tuple;
1887         Datum           values[1];
1888         bool            nulls[1] = {false};
1889
1890         /* skip over nested objects */
1891         if (_state->lex->lex_level != 1)
1892                 return;
1893
1894         /* use the tmp context so we can clean up after each tuple is done */
1895         old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1896
1897         if (isnull && _state->normalize_results)
1898         {
1899                 nulls[0] = true;
1900                 values[0] = (Datum) NULL;
1901         }
1902         else if (_state->next_scalar)
1903         {
1904                 values[0] = CStringGetTextDatum(_state->normalized_scalar);
1905                 _state->next_scalar = false;
1906         }
1907         else
1908         {
1909                 len = _state->lex->prev_token_terminator - _state->result_start;
1910                 val = cstring_to_text_with_len(_state->result_start, len);
1911                 values[0] = PointerGetDatum(val);
1912         }
1913
1914
1915         tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1916
1917         tuplestore_puttuple(_state->tuple_store, tuple);
1918
1919         /* clean up and switch back */
1920         MemoryContextSwitchTo(old_cxt);
1921         MemoryContextReset(_state->tmp_cxt);
1922 }
1923
1924 static void
1925 elements_object_start(void *state)
1926 {
1927         ElementsState *_state = (ElementsState *) state;
1928
1929         /* json structure check */
1930         if (_state->lex->lex_level == 0)
1931                 ereport(ERROR,
1932                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1933                                  errmsg("cannot call json_array_elements on a non-array")));
1934 }
1935
1936 static void
1937 elements_scalar(void *state, char *token, JsonTokenType tokentype)
1938 {
1939         ElementsState *_state = (ElementsState *) state;
1940
1941         /* json structure check */
1942         if (_state->lex->lex_level == 0)
1943                 ereport(ERROR,
1944                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1945                                  errmsg("cannot call json_array_elements on a scalar")));
1946
1947         /* supply de-escaped value if required */
1948         if (_state->next_scalar)
1949                 _state->normalized_scalar = token;
1950 }
1951
1952 /*
1953  * SQL function json_populate_record
1954  *
1955  * set fields in a record from the argument json
1956  *
1957  * Code adapted shamelessly from hstore's populate_record
1958  * which is in turn partly adapted from record_out.
1959  *
1960  * The json is decomposed into a hash table, in which each
1961  * field in the record is then looked up by name. For jsonb
1962  * we fetch the values direct from the object.
1963  */
1964 Datum
1965 jsonb_populate_record(PG_FUNCTION_ARGS)
1966 {
1967         return populate_record_worker(fcinfo, true);
1968 }
1969
1970 Datum
1971 jsonb_to_record(PG_FUNCTION_ARGS)
1972 {
1973         return populate_record_worker(fcinfo, false);
1974 }
1975
1976 Datum
1977 json_populate_record(PG_FUNCTION_ARGS)
1978 {
1979         return populate_record_worker(fcinfo, true);
1980 }
1981
1982 Datum
1983 json_to_record(PG_FUNCTION_ARGS)
1984 {
1985         return populate_record_worker(fcinfo, false);
1986 }
1987
1988 static inline Datum
1989 populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
1990 {
1991         int                     json_arg_num = have_record_arg ? 1 : 0;
1992         Oid                     jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
1993         text       *json;
1994         Jsonb      *jb = NULL;
1995         bool            use_json_as_text;
1996         HTAB       *json_hash = NULL;
1997         HeapTupleHeader rec = NULL;
1998         Oid                     tupType = InvalidOid;
1999         int32           tupTypmod = -1;
2000         TupleDesc       tupdesc;
2001         HeapTupleData tuple;
2002         HeapTuple       rettuple;
2003         RecordIOData *my_extra;
2004         int                     ncolumns;
2005         int                     i;
2006         Datum      *values;
2007         bool       *nulls;
2008
2009         Assert(jtype == JSONOID || jtype == JSONBOID);
2010
2011         use_json_as_text = PG_ARGISNULL(json_arg_num + 1) ? false :
2012                 PG_GETARG_BOOL(json_arg_num + 1);
2013
2014         if (have_record_arg)
2015         {
2016                 Oid                     argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2017
2018                 if (!type_is_rowtype(argtype))
2019                         ereport(ERROR,
2020                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2021                                          errmsg("first argument of json%s_populate_record must be a row type", jtype == JSONBOID ? "b" : "")));
2022
2023                 if (PG_ARGISNULL(0))
2024                 {
2025                         if (PG_ARGISNULL(1))
2026                                 PG_RETURN_NULL();
2027
2028                         /*
2029                          * have no tuple to look at, so the only source of type info is
2030                          * the argtype. The lookup_rowtype_tupdesc call below will error
2031                          * out if we don't have a known composite type oid here.
2032                          */
2033                         tupType = argtype;
2034                         tupTypmod = -1;
2035                 }
2036                 else
2037                 {
2038                         rec = PG_GETARG_HEAPTUPLEHEADER(0);
2039
2040                         if (PG_ARGISNULL(1))
2041                                 PG_RETURN_POINTER(rec);
2042
2043                         /* Extract type info from the tuple itself */
2044                         tupType = HeapTupleHeaderGetTypeId(rec);
2045                         tupTypmod = HeapTupleHeaderGetTypMod(rec);
2046                 }
2047
2048                 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2049         }
2050         else
2051         {                                                       /* json{b}_to_record case */
2052
2053                 if (PG_ARGISNULL(0))
2054                         PG_RETURN_NULL();
2055
2056                 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2057                         ereport(ERROR,
2058                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2059                                          errmsg("function returning record called in context "
2060                                                         "that cannot accept type record"),
2061                                          errhint("Try calling the function in the FROM clause "
2062                                                          "using a column definition list.")));
2063         }
2064
2065         if (jtype == JSONOID)
2066         {
2067                 /* just get the text */
2068                 json = PG_GETARG_TEXT_P(json_arg_num);
2069
2070                 json_hash = get_json_object_as_hash(json, "json_populate_record", use_json_as_text);
2071
2072                 /*
2073                  * if the input json is empty, we can only skip the rest if we were
2074                  * passed in a non-null record, since otherwise there may be issues
2075                  * with domain nulls.
2076                  */
2077                 if (hash_get_num_entries(json_hash) == 0 && rec)
2078                 {
2079                         hash_destroy(json_hash);
2080                         PG_RETURN_POINTER(rec);
2081                 }
2082         }
2083         else
2084         {
2085                 jb = PG_GETARG_JSONB(json_arg_num);
2086
2087                 /* same logic as for json */
2088                 if (!have_record_arg && rec)
2089                         PG_RETURN_POINTER(rec);
2090         }
2091
2092         ncolumns = tupdesc->natts;
2093
2094         if (rec)
2095         {
2096                 /* Build a temporary HeapTuple control structure */
2097                 tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
2098                 ItemPointerSetInvalid(&(tuple.t_self));
2099                 tuple.t_tableOid = InvalidOid;
2100                 tuple.t_data = rec;
2101         }
2102
2103         /*
2104          * We arrange to look up the needed I/O info just once per series of
2105          * calls, assuming the record type doesn't change underneath us.
2106          */
2107         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2108         if (my_extra == NULL ||
2109                 my_extra->ncolumns != ncolumns)
2110         {
2111                 fcinfo->flinfo->fn_extra =
2112                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2113                                                            sizeof(RecordIOData) - sizeof(ColumnIOData)
2114                                                            + ncolumns * sizeof(ColumnIOData));
2115                 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2116                 my_extra->record_type = InvalidOid;
2117                 my_extra->record_typmod = 0;
2118                 my_extra->ncolumns = ncolumns;
2119                 MemSet(my_extra->columns, 0, sizeof(ColumnIOData) * ncolumns);
2120         }
2121
2122         if (have_record_arg && (my_extra->record_type != tupType ||
2123                                                         my_extra->record_typmod != tupTypmod))
2124         {
2125                 MemSet(my_extra, 0,
2126                            sizeof(RecordIOData) - sizeof(ColumnIOData)
2127                            + ncolumns * sizeof(ColumnIOData));
2128                 my_extra->record_type = tupType;
2129                 my_extra->record_typmod = tupTypmod;
2130                 my_extra->ncolumns = ncolumns;
2131         }
2132
2133         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2134         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2135
2136         if (rec)
2137         {
2138                 /* Break down the tuple into fields */
2139                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2140         }
2141         else
2142         {
2143                 for (i = 0; i < ncolumns; ++i)
2144                 {
2145                         values[i] = (Datum) 0;
2146                         nulls[i] = true;
2147                 }
2148         }
2149
2150         for (i = 0; i < ncolumns; ++i)
2151         {
2152                 ColumnIOData *column_info = &my_extra->columns[i];
2153                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2154                 JsonbValue *v = NULL;
2155                 char            fname[NAMEDATALEN];
2156                 JsonHashEntry *hashentry = NULL;
2157
2158                 /* Ignore dropped columns in datatype */
2159                 if (tupdesc->attrs[i]->attisdropped)
2160                 {
2161                         nulls[i] = true;
2162                         continue;
2163                 }
2164
2165                 if (jtype == JSONOID)
2166                 {
2167
2168                         memset(fname, 0, NAMEDATALEN);
2169                         strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
2170                         hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
2171                 }
2172                 else
2173                 {
2174                         char       *key = NameStr(tupdesc->attrs[i]->attname);
2175
2176                         v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
2177                                                                                            strlen(key));
2178                 }
2179
2180                 /*
2181                  * we can't just skip here if the key wasn't found since we might have
2182                  * a domain to deal with. If we were passed in a non-null record
2183                  * datum, we assume that the existing values are valid (if they're
2184                  * not, then it's not our fault), but if we were passed in a null,
2185                  * then every field which we don't populate needs to be run through
2186                  * the input function just in case it's a domain type.
2187                  */
2188                 if (((jtype == JSONOID && hashentry == NULL) ||
2189                          (jtype == JSONBOID && v == NULL)) && rec)
2190                         continue;
2191
2192                 /*
2193                  * Prepare to convert the column value from text
2194                  */
2195                 if (column_info->column_type != column_type)
2196                 {
2197                         getTypeInputInfo(column_type,
2198                                                          &column_info->typiofunc,
2199                                                          &column_info->typioparam);
2200                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2201                                                   fcinfo->flinfo->fn_mcxt);
2202                         column_info->column_type = column_type;
2203                 }
2204                 if ((jtype == JSONOID && (hashentry == NULL || hashentry->isnull)) ||
2205                         (jtype == JSONBOID && (v == NULL || v->type == jbvNull)))
2206                 {
2207                         /*
2208                          * need InputFunctionCall to happen even for nulls, so that domain
2209                          * checks are done
2210                          */
2211                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2212                                                                                   column_info->typioparam,
2213                                                                                   tupdesc->attrs[i]->atttypmod);
2214                         nulls[i] = true;
2215                 }
2216                 else
2217                 {
2218                         char       *s = NULL;
2219
2220                         if (jtype == JSONOID)
2221                         {
2222                                 /* already done the hard work in the json case */
2223                                 s = hashentry->val;
2224                         }
2225                         else
2226                         {
2227                                 if (v->type == jbvString)
2228                                         s = pnstrdup(v->val.string.val, v->val.string.len);
2229                                 else if (v->type == jbvBool)
2230                                         s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2231                                 else if (v->type == jbvNumeric)
2232                                         s = DatumGetCString(DirectFunctionCall1(numeric_out,
2233                                                                                    PointerGetDatum(v->val.numeric)));
2234                                 else if (!use_json_as_text)
2235                                         ereport(ERROR,
2236                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2237                                                          errmsg("cannot populate with a nested object unless use_json_as_text is true")));
2238                                 else if (v->type == jbvBinary)
2239                                         s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2240                                 else
2241                                         elog(ERROR, "invalid jsonb type");
2242                         }
2243
2244                         values[i] = InputFunctionCall(&column_info->proc, s,
2245                                                                                   column_info->typioparam,
2246                                                                                   tupdesc->attrs[i]->atttypmod);
2247                         nulls[i] = false;
2248                 }
2249         }
2250
2251         rettuple = heap_form_tuple(tupdesc, values, nulls);
2252
2253         ReleaseTupleDesc(tupdesc);
2254
2255         if (json_hash)
2256                 hash_destroy(json_hash);
2257
2258         PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
2259 }
2260
2261 /*
2262  * get_json_object_as_hash
2263  *
2264  * decompose a json object into a hash table.
2265  *
2266  * Currently doesn't allow anything but a flat object. Should this
2267  * change?
2268  *
2269  * funcname argument allows caller to pass in its name for use in
2270  * error messages.
2271  */
2272 static HTAB *
2273 get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text)
2274 {
2275         HASHCTL         ctl;
2276         HTAB       *tab;
2277         JHashState *state;
2278         JsonLexContext *lex = makeJsonLexContext(json, true);
2279         JsonSemAction *sem;
2280
2281         memset(&ctl, 0, sizeof(ctl));
2282         ctl.keysize = NAMEDATALEN;
2283         ctl.entrysize = sizeof(JsonHashEntry);
2284         ctl.hcxt = CurrentMemoryContext;
2285         tab = hash_create("json object hashtable",
2286                                           100,
2287                                           &ctl,
2288                                           HASH_ELEM | HASH_CONTEXT);
2289
2290         state = palloc0(sizeof(JHashState));
2291         sem = palloc0(sizeof(JsonSemAction));
2292
2293         state->function_name = funcname;
2294         state->hash = tab;
2295         state->lex = lex;
2296         state->use_json_as_text = use_json_as_text;
2297
2298         sem->semstate = (void *) state;
2299         sem->array_start = hash_array_start;
2300         sem->scalar = hash_scalar;
2301         sem->object_field_start = hash_object_field_start;
2302         sem->object_field_end = hash_object_field_end;
2303
2304         pg_parse_json(lex, sem);
2305
2306         return tab;
2307 }
2308
2309 static void
2310 hash_object_field_start(void *state, char *fname, bool isnull)
2311 {
2312         JHashState *_state = (JHashState *) state;
2313
2314         if (_state->lex->lex_level > 1)
2315                 return;
2316
2317         if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2318                 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2319         {
2320                 if (!_state->use_json_as_text)
2321                         ereport(ERROR,
2322                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2323                                          errmsg("cannot call %s on a nested object",
2324                                                         _state->function_name)));
2325                 _state->save_json_start = _state->lex->token_start;
2326         }
2327         else
2328         {
2329                 /* must be a scalar */
2330                 _state->save_json_start = NULL;
2331         }
2332 }
2333
2334 static void
2335 hash_object_field_end(void *state, char *fname, bool isnull)
2336 {
2337         JHashState *_state = (JHashState *) state;
2338         JsonHashEntry *hashentry;
2339         bool            found;
2340         char            name[NAMEDATALEN];
2341
2342         /*
2343          * ignore field names >= NAMEDATALEN - they can't match a record field
2344          * ignore nested fields.
2345          */
2346         if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
2347                 return;
2348
2349         memset(name, 0, NAMEDATALEN);
2350         strncpy(name, fname, NAMEDATALEN);
2351
2352         hashentry = hash_search(_state->hash, name, HASH_ENTER, &found);
2353
2354         /*
2355          * found being true indicates a duplicate. We don't do anything about
2356          * that, a later field with the same name overrides the earlier field.
2357          */
2358
2359         hashentry->isnull = isnull;
2360         if (_state->save_json_start != NULL)
2361         {
2362                 int                     len = _state->lex->prev_token_terminator - _state->save_json_start;
2363                 char       *val = palloc((len + 1) * sizeof(char));
2364
2365                 memcpy(val, _state->save_json_start, len);
2366                 val[len] = '\0';
2367                 hashentry->val = val;
2368         }
2369         else
2370         {
2371                 /* must have had a scalar instead */
2372                 hashentry->val = _state->saved_scalar;
2373         }
2374 }
2375
2376 static void
2377 hash_array_start(void *state)
2378 {
2379         JHashState *_state = (JHashState *) state;
2380
2381         if (_state->lex->lex_level == 0)
2382                 ereport(ERROR,
2383                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2384                            errmsg("cannot call %s on an array", _state->function_name)));
2385 }
2386
2387 static void
2388 hash_scalar(void *state, char *token, JsonTokenType tokentype)
2389 {
2390         JHashState *_state = (JHashState *) state;
2391
2392         if (_state->lex->lex_level == 0)
2393                 ereport(ERROR,
2394                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2395                            errmsg("cannot call %s on a scalar", _state->function_name)));
2396
2397         if (_state->lex->lex_level == 1)
2398                 _state->saved_scalar = token;
2399 }
2400
2401
2402 /*
2403  * SQL function json_populate_recordset
2404  *
2405  * set fields in a set of records from the argument json,
2406  * which must be an array of objects.
2407  *
2408  * similar to json_populate_record, but the tuple-building code
2409  * is pushed down into the semantic action handlers so it's done
2410  * per object in the array.
2411  */
2412 Datum
2413 jsonb_populate_recordset(PG_FUNCTION_ARGS)
2414 {
2415         return populate_recordset_worker(fcinfo, true);
2416 }
2417
2418 Datum
2419 jsonb_to_recordset(PG_FUNCTION_ARGS)
2420 {
2421         return populate_recordset_worker(fcinfo, false);
2422 }
2423
2424 Datum
2425 json_populate_recordset(PG_FUNCTION_ARGS)
2426 {
2427         return populate_recordset_worker(fcinfo, true);
2428 }
2429
2430 Datum
2431 json_to_recordset(PG_FUNCTION_ARGS)
2432 {
2433         return populate_recordset_worker(fcinfo, false);
2434 }
2435
2436 static void
2437 make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
2438 {
2439         Datum      *values;
2440         bool       *nulls;
2441         int                     i;
2442         RecordIOData *my_extra = state->my_extra;
2443         int                     ncolumns = my_extra->ncolumns;
2444         TupleDesc       tupdesc = state->ret_tdesc;
2445         HeapTupleHeader rec = state->rec;
2446         HeapTuple       rettuple;
2447
2448         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2449         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2450
2451         if (state->rec)
2452         {
2453                 HeapTupleData tuple;
2454
2455                 /* Build a temporary HeapTuple control structure */
2456                 tuple.t_len = HeapTupleHeaderGetDatumLength(state->rec);
2457                 ItemPointerSetInvalid(&(tuple.t_self));
2458                 tuple.t_tableOid = InvalidOid;
2459                 tuple.t_data = state->rec;
2460
2461                 /* Break down the tuple into fields */
2462                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2463         }
2464         else
2465         {
2466                 for (i = 0; i < ncolumns; ++i)
2467                 {
2468                         values[i] = (Datum) 0;
2469                         nulls[i] = true;
2470                 }
2471         }
2472
2473         for (i = 0; i < ncolumns; ++i)
2474         {
2475                 ColumnIOData *column_info = &my_extra->columns[i];
2476                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2477                 JsonbValue *v = NULL;
2478                 char       *key;
2479
2480                 /* Ignore dropped columns in datatype */
2481                 if (tupdesc->attrs[i]->attisdropped)
2482                 {
2483                         nulls[i] = true;
2484                         continue;
2485                 }
2486
2487                 key = NameStr(tupdesc->attrs[i]->attname);
2488
2489                 v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
2490                                                                                    key, strlen(key));
2491
2492                 /*
2493                  * We can't just skip here if the key wasn't found since we might have
2494                  * a domain to deal with. If we were passed in a non-null record
2495                  * datum, we assume that the existing values are valid (if they're
2496                  * not, then it's not our fault), but if we were passed in a null,
2497                  * then every field which we don't populate needs to be run through
2498                  * the input function just in case it's a domain type.
2499                  */
2500                 if (v == NULL && rec)
2501                         continue;
2502
2503                 /*
2504                  * Prepare to convert the column value from text
2505                  */
2506                 if (column_info->column_type != column_type)
2507                 {
2508                         getTypeInputInfo(column_type,
2509                                                          &column_info->typiofunc,
2510                                                          &column_info->typioparam);
2511                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2512                                                   state->fn_mcxt);
2513                         column_info->column_type = column_type;
2514                 }
2515                 if (v == NULL || v->type == jbvNull)
2516                 {
2517                         /*
2518                          * Need InputFunctionCall to happen even for nulls, so that domain
2519                          * checks are done
2520                          */
2521                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2522                                                                                   column_info->typioparam,
2523                                                                                   tupdesc->attrs[i]->atttypmod);
2524                         nulls[i] = true;
2525                 }
2526                 else
2527                 {
2528                         char       *s = NULL;
2529
2530                         if (v->type == jbvString)
2531                                 s = pnstrdup(v->val.string.val, v->val.string.len);
2532                         else if (v->type == jbvBool)
2533                                 s = pnstrdup((v->val.boolean) ? "t" : "f", 1);
2534                         else if (v->type == jbvNumeric)
2535                                 s = DatumGetCString(DirectFunctionCall1(numeric_out,
2536                                                                                    PointerGetDatum(v->val.numeric)));
2537                         else if (!state->use_json_as_text)
2538                                 ereport(ERROR,
2539                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2540                                                  errmsg("cannot populate with a nested object unless use_json_as_text is true")));
2541                         else if (v->type == jbvBinary)
2542                                 s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
2543                         else
2544                                 elog(ERROR, "invalid jsonb type");
2545
2546                         values[i] = InputFunctionCall(&column_info->proc, s,
2547                                                                                   column_info->typioparam,
2548                                                                                   tupdesc->attrs[i]->atttypmod);
2549                         nulls[i] = false;
2550                 }
2551         }
2552
2553         rettuple = heap_form_tuple(tupdesc, values, nulls);
2554
2555         tuplestore_puttuple(state->tuple_store, rettuple);
2556 }
2557
2558 /*
2559  * common worker for json_populate_recordset() and json_to_recordset()
2560  */
2561 static inline Datum
2562 populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
2563 {
2564         int                     json_arg_num = have_record_arg ? 1 : 0;
2565         Oid                     jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2566         bool            use_json_as_text;
2567         ReturnSetInfo *rsi;
2568         MemoryContext old_cxt;
2569         Oid                     tupType;
2570         int32           tupTypmod;
2571         HeapTupleHeader rec;
2572         TupleDesc       tupdesc;
2573         RecordIOData *my_extra;
2574         int                     ncolumns;
2575         PopulateRecordsetState *state;
2576
2577         use_json_as_text = PG_ARGISNULL(json_arg_num + 1) ? false : PG_GETARG_BOOL(json_arg_num + 1);
2578
2579         if (have_record_arg)
2580         {
2581                 Oid                     argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
2582
2583                 if (!type_is_rowtype(argtype))
2584                         ereport(ERROR,
2585                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2586                                          errmsg("first argument must be a row type")));
2587         }
2588
2589         rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2590
2591         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2592                 (rsi->allowedModes & SFRM_Materialize) == 0 ||
2593                 rsi->expectedDesc == NULL)
2594                 ereport(ERROR,
2595                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2596                                  errmsg("set-valued function called in context that "
2597                                                 "cannot accept a set")));
2598
2599
2600         rsi->returnMode = SFRM_Materialize;
2601
2602         /*
2603          * get the tupdesc from the result set info - it must be a record type
2604          * because we already checked that arg1 is a record type, or we're in a
2605          * to_record function which returns a setof record.
2606          */
2607         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2608                 ereport(ERROR,
2609                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2610                                  errmsg("function returning record called in context "
2611                                                 "that cannot accept type record")));
2612
2613         /* if the json is null send back an empty set */
2614         if (PG_ARGISNULL(json_arg_num))
2615                 PG_RETURN_NULL();
2616
2617         if (!have_record_arg || PG_ARGISNULL(0))
2618                 rec = NULL;
2619         else
2620                 rec = PG_GETARG_HEAPTUPLEHEADER(0);
2621
2622         tupType = tupdesc->tdtypeid;
2623         tupTypmod = tupdesc->tdtypmod;
2624         ncolumns = tupdesc->natts;
2625
2626         /*
2627          * We arrange to look up the needed I/O info just once per series of
2628          * calls, assuming the record type doesn't change underneath us.
2629          */
2630         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2631         if (my_extra == NULL ||
2632                 my_extra->ncolumns != ncolumns)
2633         {
2634                 fcinfo->flinfo->fn_extra =
2635                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2636                                                            sizeof(RecordIOData) - sizeof(ColumnIOData)
2637                                                            + ncolumns * sizeof(ColumnIOData));
2638                 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
2639                 my_extra->record_type = InvalidOid;
2640                 my_extra->record_typmod = 0;
2641         }
2642
2643         if (my_extra->record_type != tupType ||
2644                 my_extra->record_typmod != tupTypmod)
2645         {
2646                 MemSet(my_extra, 0,
2647                            sizeof(RecordIOData) - sizeof(ColumnIOData)
2648                            + ncolumns * sizeof(ColumnIOData));
2649                 my_extra->record_type = tupType;
2650                 my_extra->record_typmod = tupTypmod;
2651                 my_extra->ncolumns = ncolumns;
2652         }
2653
2654         state = palloc0(sizeof(PopulateRecordsetState));
2655
2656         /* make these in a sufficiently long-lived memory context */
2657         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
2658         state->ret_tdesc = CreateTupleDescCopy(tupdesc);;
2659         BlessTupleDesc(state->ret_tdesc);
2660         state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
2661                                                                                            SFRM_Materialize_Random,
2662                                                                                            false, work_mem);
2663         MemoryContextSwitchTo(old_cxt);
2664
2665         state->my_extra = my_extra;
2666         state->rec = rec;
2667         state->use_json_as_text = use_json_as_text;
2668         state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
2669
2670         if (jtype == JSONOID)
2671         {
2672                 text       *json = PG_GETARG_TEXT_P(have_record_arg ? 1 : 0);
2673                 JsonLexContext *lex;
2674                 JsonSemAction *sem;
2675
2676                 sem = palloc0(sizeof(JsonSemAction));
2677
2678                 lex = makeJsonLexContext(json, true);
2679
2680                 sem->semstate = (void *) state;
2681                 sem->array_start = populate_recordset_array_start;
2682                 sem->array_element_start = populate_recordset_array_element_start;
2683                 sem->scalar = populate_recordset_scalar;
2684                 sem->object_field_start = populate_recordset_object_field_start;
2685                 sem->object_field_end = populate_recordset_object_field_end;
2686                 sem->object_start = populate_recordset_object_start;
2687                 sem->object_end = populate_recordset_object_end;
2688
2689                 state->lex = lex;
2690
2691                 pg_parse_json(lex, sem);
2692
2693         }
2694         else
2695         {
2696                 Jsonb      *jb;
2697                 JsonbIterator *it;
2698                 JsonbValue      v;
2699                 bool            skipNested = false;
2700                 int                     r;
2701
2702                 Assert(jtype == JSONBOID);
2703                 jb = PG_GETARG_JSONB(have_record_arg ? 1 : 0);
2704
2705                 if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
2706                         ereport(ERROR,
2707                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2708                            errmsg("cannot call jsonb_populate_recordset on non-array")));
2709
2710                 it = JsonbIteratorInit(&jb->root);
2711
2712                 while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2713                 {
2714                         skipNested = true;
2715
2716                         if (r == WJB_ELEM)
2717                         {
2718                                 Jsonb      *element = JsonbValueToJsonb(&v);
2719
2720                                 if (!JB_ROOT_IS_OBJECT(element))
2721                                         ereport(ERROR,
2722                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2723                                                          errmsg("jsonb_populate_recordset argument must be an array of objects")));
2724                                 make_row_from_rec_and_jsonb(element, state);
2725                         }
2726                 }
2727         }
2728
2729         rsi->setResult = state->tuple_store;
2730         rsi->setDesc = state->ret_tdesc;
2731
2732         PG_RETURN_NULL();
2733
2734 }
2735
2736 static void
2737 populate_recordset_object_start(void *state)
2738 {
2739         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2740         int                     lex_level = _state->lex->lex_level;
2741         HASHCTL         ctl;
2742
2743         /* Reject object at top level: we must have an array at level 0 */
2744         if (lex_level == 0)
2745                 ereport(ERROR,
2746                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2747                                  errmsg("cannot call json_populate_recordset on an object")));
2748
2749         /* Nested objects, if allowed, require no special processing */
2750         if (lex_level > 1)
2751         {
2752                 if (!_state->use_json_as_text)
2753                         ereport(ERROR,
2754                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2755                                          errmsg("cannot call json_populate_recordset with nested objects")));
2756                 return;
2757         }
2758
2759         /* Object at level 1: set up a new hash table for this object */
2760         memset(&ctl, 0, sizeof(ctl));
2761         ctl.keysize = NAMEDATALEN;
2762         ctl.entrysize = sizeof(JsonHashEntry);
2763         ctl.hcxt = CurrentMemoryContext;
2764         _state->json_hash = hash_create("json object hashtable",
2765                                                                         100,
2766                                                                         &ctl,
2767                                                                         HASH_ELEM | HASH_CONTEXT);
2768 }
2769
2770 static void
2771 populate_recordset_object_end(void *state)
2772 {
2773         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2774         HTAB       *json_hash = _state->json_hash;
2775         Datum      *values;
2776         bool       *nulls;
2777         char            fname[NAMEDATALEN];
2778         int                     i;
2779         RecordIOData *my_extra = _state->my_extra;
2780         int                     ncolumns = my_extra->ncolumns;
2781         TupleDesc       tupdesc = _state->ret_tdesc;
2782         JsonHashEntry *hashentry;
2783         HeapTupleHeader rec = _state->rec;
2784         HeapTuple       rettuple;
2785
2786         /* Nested objects require no special processing */
2787         if (_state->lex->lex_level > 1)
2788                 return;
2789
2790         /* Otherwise, construct and return a tuple based on this level-1 object */
2791         values = (Datum *) palloc(ncolumns * sizeof(Datum));
2792         nulls = (bool *) palloc(ncolumns * sizeof(bool));
2793
2794         if (_state->rec)
2795         {
2796                 HeapTupleData tuple;
2797
2798                 /* Build a temporary HeapTuple control structure */
2799                 tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
2800                 ItemPointerSetInvalid(&(tuple.t_self));
2801                 tuple.t_tableOid = InvalidOid;
2802                 tuple.t_data = _state->rec;
2803
2804                 /* Break down the tuple into fields */
2805                 heap_deform_tuple(&tuple, tupdesc, values, nulls);
2806         }
2807         else
2808         {
2809                 for (i = 0; i < ncolumns; ++i)
2810                 {
2811                         values[i] = (Datum) 0;
2812                         nulls[i] = true;
2813                 }
2814         }
2815
2816         for (i = 0; i < ncolumns; ++i)
2817         {
2818                 ColumnIOData *column_info = &my_extra->columns[i];
2819                 Oid                     column_type = tupdesc->attrs[i]->atttypid;
2820                 char       *value;
2821
2822                 /* Ignore dropped columns in datatype */
2823                 if (tupdesc->attrs[i]->attisdropped)
2824                 {
2825                         nulls[i] = true;
2826                         continue;
2827                 }
2828
2829                 memset(fname, 0, NAMEDATALEN);
2830                 strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
2831                 hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
2832
2833                 /*
2834                  * we can't just skip here if the key wasn't found since we might have
2835                  * a domain to deal with. If we were passed in a non-null record
2836                  * datum, we assume that the existing values are valid (if they're
2837                  * not, then it's not our fault), but if we were passed in a null,
2838                  * then every field which we don't populate needs to be run through
2839                  * the input function just in case it's a domain type.
2840                  */
2841                 if (hashentry == NULL && rec)
2842                         continue;
2843
2844                 /*
2845                  * Prepare to convert the column value from text
2846                  */
2847                 if (column_info->column_type != column_type)
2848                 {
2849                         getTypeInputInfo(column_type,
2850                                                          &column_info->typiofunc,
2851                                                          &column_info->typioparam);
2852                         fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
2853                                                   _state->fn_mcxt);
2854                         column_info->column_type = column_type;
2855                 }
2856                 if (hashentry == NULL || hashentry->isnull)
2857                 {
2858                         /*
2859                          * need InputFunctionCall to happen even for nulls, so that domain
2860                          * checks are done
2861                          */
2862                         values[i] = InputFunctionCall(&column_info->proc, NULL,
2863                                                                                   column_info->typioparam,
2864                                                                                   tupdesc->attrs[i]->atttypmod);
2865                         nulls[i] = true;
2866                 }
2867                 else
2868                 {
2869                         value = hashentry->val;
2870
2871                         values[i] = InputFunctionCall(&column_info->proc, value,
2872                                                                                   column_info->typioparam,
2873                                                                                   tupdesc->attrs[i]->atttypmod);
2874                         nulls[i] = false;
2875                 }
2876         }
2877
2878         rettuple = heap_form_tuple(tupdesc, values, nulls);
2879
2880         tuplestore_puttuple(_state->tuple_store, rettuple);
2881
2882         /* Done with hash for this object */
2883         hash_destroy(json_hash);
2884         _state->json_hash = NULL;
2885 }
2886
2887 static void
2888 populate_recordset_array_element_start(void *state, bool isnull)
2889 {
2890         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2891
2892         if (_state->lex->lex_level == 1 &&
2893                 _state->lex->token_type != JSON_TOKEN_OBJECT_START)
2894                 ereport(ERROR,
2895                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2896                 errmsg("must call json_populate_recordset on an array of objects")));
2897 }
2898
2899 static void
2900 populate_recordset_array_start(void *state)
2901 {
2902         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2903
2904         if (_state->lex->lex_level != 0 && !_state->use_json_as_text)
2905                 ereport(ERROR,
2906                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2907                   errmsg("cannot call json_populate_recordset with nested arrays")));
2908 }
2909
2910 static void
2911 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
2912 {
2913         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2914
2915         if (_state->lex->lex_level == 0)
2916                 ereport(ERROR,
2917                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2918                                  errmsg("cannot call json_populate_recordset on a scalar")));
2919
2920         if (_state->lex->lex_level == 2)
2921                 _state->saved_scalar = token;
2922 }
2923
2924 static void
2925 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
2926 {
2927         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2928
2929         if (_state->lex->lex_level > 2)
2930                 return;
2931
2932         if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2933                 _state->lex->token_type == JSON_TOKEN_OBJECT_START)
2934         {
2935                 if (!_state->use_json_as_text)
2936                         ereport(ERROR,
2937                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2938                                          errmsg("cannot call json_populate_recordset on a nested object")));
2939                 _state->save_json_start = _state->lex->token_start;
2940         }
2941         else
2942         {
2943                 _state->save_json_start = NULL;
2944         }
2945 }
2946
2947 static void
2948 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
2949 {
2950         PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2951         JsonHashEntry *hashentry;
2952         bool            found;
2953         char            name[NAMEDATALEN];
2954
2955         /*
2956          * ignore field names >= NAMEDATALEN - they can't match a record field
2957          * ignore nested fields.
2958          */
2959         if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
2960                 return;
2961
2962         memset(name, 0, NAMEDATALEN);
2963         strncpy(name, fname, NAMEDATALEN);
2964
2965         hashentry = hash_search(_state->json_hash, name, HASH_ENTER, &found);
2966
2967         /*
2968          * found being true indicates a duplicate. We don't do anything about
2969          * that, a later field with the same name overrides the earlier field.
2970          */
2971
2972         hashentry->isnull = isnull;
2973         if (_state->save_json_start != NULL)
2974         {
2975                 int                     len = _state->lex->prev_token_terminator - _state->save_json_start;
2976                 char       *val = palloc((len + 1) * sizeof(char));
2977
2978                 memcpy(val, _state->save_json_start, len);
2979                 val[len] = '\0';
2980                 hashentry->val = val;
2981         }
2982         else
2983         {
2984                 /* must have had a scalar instead */
2985                 hashentry->val = _state->saved_scalar;
2986         }
2987 }
2988
2989 /*
2990  * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
2991  */
2992 static JsonbValue *
2993 findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
2994                                                            char *key, uint32 keylen)
2995 {
2996         JsonbValue      k;
2997
2998         k.type = jbvString;
2999         k.val.string.val = key;
3000         k.val.string.len = keylen;
3001
3002         return findJsonbValueFromContainer(container, flags, &k);
3003 }