PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
jsonfuncs.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * jsonfuncs.c
4  * Functions to process JSON data type.
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/jsonapi.h"
31 #include "utils/lsyscache.h"
32 #include "utils/memutils.h"
33 #include "utils/typcache.h"
34 
35 /* semantic action functions for json_object_keys */
36 static void okeys_object_field_start(void *state, char *fname, bool isnull);
37 static void okeys_array_start(void *state);
38 static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
39 
40 /* semantic action functions for json_get* functions */
41 static void get_object_start(void *state);
42 static void get_object_field_start(void *state, char *fname, bool isnull);
43 static void get_object_field_end(void *state, char *fname, bool isnull);
44 static void get_array_start(void *state);
45 static void get_array_element_start(void *state, bool isnull);
46 static void get_array_element_end(void *state, bool isnull);
47 static void get_scalar(void *state, char *token, JsonTokenType tokentype);
48 
49 /* common worker function for json getter functions */
50 static inline Datum get_path_all(PG_FUNCTION_ARGS, bool as_text);
51 static inline text *get_worker(text *json, char *field, int elem_index,
52  char **tpath, int *ipath, int npath,
53  bool normalize_results);
54 
55 /* semantic action functions for json_array_length */
56 static void alen_object_start(void *state);
57 static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
58 static void alen_array_element_start(void *state, bool isnull);
59 
60 /* common worker for json_each* functions */
61 static inline Datum each_worker(PG_FUNCTION_ARGS, bool as_text);
62 
63 /* semantic action functions for json_each */
64 static void each_object_field_start(void *state, char *fname, bool isnull);
65 static void each_object_field_end(void *state, char *fname, bool isnull);
66 static void each_array_start(void *state);
67 static void each_scalar(void *state, char *token, JsonTokenType tokentype);
68 
69 /* semantic action functions for json_array_elements */
70 static void elements_object_start(void *state);
71 static void elements_array_element_start(void *state, bool isnull);
72 static void elements_array_element_end(void *state, bool isnull);
73 static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
74 
75 /* turn a json object into a hash table */
76 static HTAB *get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text);
77 
78 /* common worker for populate_record and to_record */
80  bool have_record_arg);
81 
82 /* semantic action functions for get_json_object_as_hash */
83 static void hash_object_field_start(void *state, char *fname, bool isnull);
84 static void hash_object_field_end(void *state, char *fname, bool isnull);
85 static void hash_array_start(void *state);
86 static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
87 
88 /* semantic action functions for populate_recordset */
89 static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
90 static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
91 static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
92 static void populate_recordset_object_start(void *state);
93 static void populate_recordset_object_end(void *state);
94 static void populate_recordset_array_start(void *state);
95 static void populate_recordset_array_element_start(void *state, bool isnull);
96 
97 /* worker function for populate_recordset and to_recordset */
99  bool have_record_arg);
100 
101 /* search type classification for json_get* functions */
102 typedef enum
103 {
107 } JsonSearch;
108 
109 /* state for json_object_keys */
110 typedef struct OkeysState
111 {
113  char **result;
117 } OkeysState;
118 
119 /* state for json_get* functions */
120 typedef struct GetState
121 {
126  char *search_term;
132  char **path;
133  int npath;
134  char **current_path;
135  bool *pathok;
138 } GetState;
139 
140 /* state for json_array_length */
141 typedef struct AlenState
142 {
144  int count;
145 } AlenState;
146 
147 /* state for json_each */
148 typedef struct EachState
149 {
158 } EachState;
159 
160 /* state for json_array_elements */
161 typedef struct ElementsState
162 {
168 } ElementsState;
169 
170 /* state for get_json_object_as_hash */
171 typedef struct JhashState
172 {
179 } JHashState;
180 
181 /* used to build the hashtable */
182 typedef struct JsonHashEntry
183 {
185  char *val;
186  char *json;
187  bool isnull;
188 } JsonHashEntry;
189 
190 /* these two are stolen from hstore / record_out, used in populate_record* */
191 typedef struct ColumnIOData
192 {
194  Oid typiofunc;
195  Oid typioparam;
196  FmgrInfo proc;
197 } ColumnIOData;
198 
199 typedef struct RecordIOData
200 {
203  int ncolumns;
204  ColumnIOData columns[1]; /* VARIABLE LENGTH ARRAY */
205 } RecordIOData;
206 
207 /* state for populate_recordset */
209 {
219  MemoryContext fn_mcxt; /* used to stash IO funcs */
221 
222 /*
223  * SQL function json_object-keys
224  *
225  * Returns the set of keys for the object argument.
226  *
227  * This SRF operates in value-per-call mode. It processes the
228  * object during the first call, and the keys are simply stashed
229  * in an array, whise size is expanded as necessary. This is probably
230  * safe enough for a list of keys of a single object, since they are
231  * limited in size to NAMEDATALEN and the number of keys is unlikely to
232  * be so huge that it has major memory implications.
233  */
234 
235 
236 Datum
238 {
239  FuncCallContext *funcctx;
240  OkeysState *state;
241  int i;
242 
243  if (SRF_IS_FIRSTCALL())
244  {
245  text *json = PG_GETARG_TEXT_P(0);
246  JsonLexContext *lex = makeJsonLexContext(json, true);
247  JsonSemAction *sem;
248 
249  MemoryContext oldcontext;
250 
251  funcctx = SRF_FIRSTCALL_INIT();
252  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
253 
254  state = palloc(sizeof(OkeysState));
255  sem = palloc0(sizeof(JsonSemAction));
256 
257  state->lex = lex;
258  state->result_size = 256;
259  state->result_count = 0;
260  state->sent_count = 0;
261  state->result = palloc(256 * sizeof(char *));
262 
263  sem->semstate = (void *) state;
265  sem->scalar = okeys_scalar;
267  /* remainder are all NULL, courtesy of palloc0 above */
268 
269  pg_parse_json(lex, sem);
270  /* keys are now in state->result */
271 
272  pfree(lex->strval->data);
273  pfree(lex->strval);
274  pfree(lex);
275  pfree(sem);
276 
277  MemoryContextSwitchTo(oldcontext);
278  funcctx->user_fctx = (void *) state;
279 
280  }
281 
282  funcctx = SRF_PERCALL_SETUP();
283  state = (OkeysState *) funcctx->user_fctx;
284 
285  if (state->sent_count < state->result_count)
286  {
287  char *nxt = state->result[state->sent_count++];
288 
289  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
290  }
291 
292  /* cleanup to reduce or eliminate memory leaks */
293  for (i = 0; i < state->result_count; i++)
294  pfree(state->result[i]);
295  pfree(state->result);
296  pfree(state);
297 
298  SRF_RETURN_DONE(funcctx);
299 }
300 
301 static void
302 okeys_object_field_start(void *state, char *fname, bool isnull)
303 {
304  OkeysState *_state = (OkeysState *) state;
305 
306  /* only collecting keys for the top level object */
307  if (_state->lex->lex_level != 1)
308  return;
309 
310  /* enlarge result array if necessary */
311  if (_state->result_count >= _state->result_size)
312  {
313  _state->result_size *= 2;
314  _state->result =
315  repalloc(_state->result, sizeof(char *) * _state->result_size);
316  }
317 
318  /* save a copy of the field name */
319  _state->result[_state->result_count++] = pstrdup(fname);
320 }
321 
322 static void
324 {
325  OkeysState *_state = (OkeysState *) state;
326 
327  /* top level must be a json object */
328  if (_state->lex->lex_level == 0)
329  ereport(ERROR,
330  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
331  errmsg("cannot call json_object_keys on an array")));
332 }
333 
334 static void
335 okeys_scalar(void *state, char *token, JsonTokenType tokentype)
336 {
337  OkeysState *_state = (OkeysState *) state;
338 
339  /* top level must be a json object */
340  if (_state->lex->lex_level == 0)
341  ereport(ERROR,
342  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
343  errmsg("cannot call json_object_keys on a scalar")));
344 }
345 
346 /*
347  * json getter functions
348  * these implement the -> ->> #> and #>> operators
349  * and the json_extract_path*(json, text, ...) functions
350  */
351 
352 
353 Datum
355 {
356  text *json = PG_GETARG_TEXT_P(0);
357  text *result;
358  text *fname = PG_GETARG_TEXT_P(1);
359  char *fnamestr = text_to_cstring(fname);
360 
361  result = get_worker(json, fnamestr, -1, NULL, NULL, -1, false);
362 
363  if (result != NULL)
364  PG_RETURN_TEXT_P(result);
365  else
366  PG_RETURN_NULL();
367 }
368 
369 Datum
371 {
372  text *json = PG_GETARG_TEXT_P(0);
373  text *result;
374  text *fname = PG_GETARG_TEXT_P(1);
375  char *fnamestr = text_to_cstring(fname);
376 
377  result = get_worker(json, fnamestr, -1, NULL, NULL, -1, true);
378 
379  if (result != NULL)
380  PG_RETURN_TEXT_P(result);
381  else
382  PG_RETURN_NULL();
383 }
384 
385 Datum
387 {
388  text *json = PG_GETARG_TEXT_P(0);
389  text *result;
390  int element = PG_GETARG_INT32(1);
391 
392  result = get_worker(json, NULL, element, NULL, NULL, -1, false);
393 
394  if (result != NULL)
395  PG_RETURN_TEXT_P(result);
396  else
397  PG_RETURN_NULL();
398 }
399 
400 Datum
402 {
403  text *json = PG_GETARG_TEXT_P(0);
404  text *result;
405  int element = PG_GETARG_INT32(1);
406 
407  result = get_worker(json, NULL, element, NULL, NULL, -1, true);
408 
409  if (result != NULL)
410  PG_RETURN_TEXT_P(result);
411  else
412  PG_RETURN_NULL();
413 }
414 
415 Datum
417 {
418  return get_path_all(fcinfo, false);
419 }
420 
421 Datum
423 {
424  return get_path_all(fcinfo, true);
425 }
426 
427 /*
428  * common routine for extract_path functions
429  */
430 static inline Datum
432 {
433  text *json = PG_GETARG_TEXT_P(0);
434  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
435  text *result;
436  Datum *pathtext;
437  bool *pathnulls;
438  int npath;
439  char **tpath;
440  int *ipath;
441  int i;
442  long ind;
443  char *endptr;
444 
445  if (array_contains_nulls(path))
446  ereport(ERROR,
447  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
448  errmsg("cannot call function with null path elements")));
449 
450 
451  deconstruct_array(path, TEXTOID, -1, false, 'i',
452  &pathtext, &pathnulls, &npath);
453 
454  tpath = palloc(npath * sizeof(char *));
455  ipath = palloc(npath * sizeof(int));
456 
457 
458  for (i = 0; i < npath; i++)
459  {
460  tpath[i] = TextDatumGetCString(pathtext[i]);
461  if (*tpath[i] == '\0')
462  ereport(
463  ERROR,
464  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
465  errmsg("cannot call function with empty path elements")));
466 
467  /*
468  * we have no idea at this stage what structure the document is so
469  * just convert anything in the path that we can to an integer and set
470  * all the other integers to -1 which will never match.
471  */
472  ind = strtol(tpath[i], &endptr, 10);
473  if (*endptr == '\0' && ind <= INT_MAX && ind >= 0)
474  ipath[i] = (int) ind;
475  else
476  ipath[i] = -1;
477  }
478 
479 
480  result = get_worker(json, NULL, -1, tpath, ipath, npath, as_text);
481 
482  if (result != NULL)
483  PG_RETURN_TEXT_P(result);
484  else
485  PG_RETURN_NULL();
486 }
487 
488 /*
489  * get_worker
490  *
491  * common worker for all the json getter functions
492  */
493 static inline text *
495  char *field,
496  int elem_index,
497  char **tpath,
498  int *ipath,
499  int npath,
500  bool normalize_results)
501 {
502  GetState *state;
503  JsonLexContext *lex = makeJsonLexContext(json, true);
504  JsonSemAction *sem;
505 
506  /* only allowed to use one of these */
507  Assert(elem_index < 0 || (tpath == NULL && ipath == NULL && field == NULL));
508  Assert(tpath == NULL || field == NULL);
509 
510  state = palloc0(sizeof(GetState));
511  sem = palloc0(sizeof(JsonSemAction));
512 
513  state->lex = lex;
514  /* is it "_as_text" variant? */
515  state->normalize_results = normalize_results;
516  if (field != NULL)
517  {
518  /* single text argument */
520  state->search_term = field;
521  }
522  else if (tpath != NULL)
523  {
524  /* path array argument */
525  state->search_type = JSON_SEARCH_PATH;
526  state->path = tpath;
527  state->npath = npath;
528  state->current_path = palloc(sizeof(char *) * npath);
529  state->pathok = palloc0(sizeof(bool) * npath);
530  state->pathok[0] = true;
531  state->array_level_index = palloc(sizeof(int) * npath);
532  state->path_level_index = ipath;
533 
534  }
535  else
536  {
537  /* single integer argument */
539  state->search_index = elem_index;
540  state->array_index = -1;
541  }
542 
543  sem->semstate = (void *) state;
544 
545  /*
546  * Not all variants need all the semantic routines. only set the ones
547  * that are actually needed for maximum efficiency.
548  */
551  sem->scalar = get_scalar;
552  if (field != NULL || tpath != NULL)
553  {
556  }
557  if (field == NULL)
558  {
561  }
562 
563  pg_parse_json(lex, sem);
564 
565  return state->tresult;
566 }
567 
568 static void
570 {
571  GetState *_state = (GetState *) state;
572 
573  /* json structure check */
574  if (_state->lex->lex_level == 0 && _state->search_type == JSON_SEARCH_ARRAY)
575  ereport(ERROR,
576  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
577  errmsg("cannot extract array element from a non-array")));
578 }
579 
580 static void
581 get_object_field_start(void *state, char *fname, bool isnull)
582 {
583  GetState *_state = (GetState *) state;
584  bool get_next = false;
585  int lex_level = _state->lex->lex_level;
586 
587  if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
588  strcmp(fname, _state->search_term) == 0)
589  {
590 
591  _state->tresult = NULL;
592  _state->result_start = NULL;
593  get_next = true;
594  }
595  else if (_state->search_type == JSON_SEARCH_PATH &&
596  lex_level <= _state->npath &&
597  _state->pathok[_state->lex->lex_level - 1] &&
598  strcmp(fname, _state->path[lex_level - 1]) == 0)
599  {
600  /* path search, path so far is ok, and we have a match */
601 
602  /* this object overrides any previous matching object */
603 
604  _state->tresult = NULL;
605  _state->result_start = NULL;
606 
607  /* if not at end of path just mark path ok */
608  if (lex_level < _state->npath)
609  _state->pathok[lex_level] = true;
610 
611  /* end of path, so we want this value */
612  if (lex_level == _state->npath)
613  get_next = true;
614  }
615 
616  if (get_next)
617  {
618  if (_state->normalize_results &&
619  _state->lex->token_type == JSON_TOKEN_STRING)
620  {
621  /* for as_text variants, tell get_scalar to set it for us */
622  _state->next_scalar = true;
623  }
624  else
625  {
626  /* for non-as_text variants, just note the json starting point */
627  _state->result_start = _state->lex->token_start;
628  }
629  }
630 }
631 
632 static void
633 get_object_field_end(void *state, char *fname, bool isnull)
634 {
635  GetState *_state = (GetState *) state;
636  bool get_last = false;
637  int lex_level = _state->lex->lex_level;
638 
639 
640  /* same tests as in get_object_field_start, mutatis mutandis */
641  if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
642  strcmp(fname, _state->search_term) == 0)
643  {
644  get_last = true;
645  }
646  else if (_state->search_type == JSON_SEARCH_PATH &&
647  lex_level <= _state->npath &&
648  _state->pathok[lex_level - 1] &&
649  strcmp(fname, _state->path[lex_level - 1]) == 0)
650  {
651  /* done with this field so reset pathok */
652  if (lex_level < _state->npath)
653  _state->pathok[lex_level] = false;
654 
655  if (lex_level == _state->npath)
656  get_last = true;
657  }
658 
659  /* for as_test variants our work is already done */
660  if (get_last && _state->result_start != NULL)
661  {
662  /*
663  * make a text object from the string from the prevously noted json
664  * start up to the end of the previous token (the lexer is by now
665  * ahead of us on whatevere came after what we're interested in).
666  */
667  int len = _state->lex->prev_token_terminator - _state->result_start;
668 
669  if (isnull && _state->normalize_results)
670  _state->tresult = (text *) NULL;
671  else
672  _state->tresult = cstring_to_text_with_len(_state->result_start, len);
673  }
674 
675  /*
676  * don't need to reset _state->result_start b/c we're only returning one
677  * datum, the conditions should not occur more than once, and this lets us
678  * check cheaply that they don't (see object_field_start() )
679  */
680 }
681 
682 static void
684 {
685  GetState *_state = (GetState *) state;
686  int lex_level = _state->lex->lex_level;
687 
688  /* json structure check */
689  if (lex_level == 0 && _state->search_type == JSON_SEARCH_OBJECT)
690  ereport(ERROR,
691  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
692  errmsg("cannot extract field from a non-object")));
693 
694  /*
695  * initialize array count for this nesting level Note: the lex_level seen
696  * by array_start is one less than that seen by the elements of the array.
697  */
698  if (_state->search_type == JSON_SEARCH_PATH &&
699  lex_level < _state->npath)
700  _state->array_level_index[lex_level] = -1;
701 }
702 
703 static void
704 get_array_element_start(void *state, bool isnull)
705 {
706  GetState *_state = (GetState *) state;
707  bool get_next = false;
708  int lex_level = _state->lex->lex_level;
709 
710  if (lex_level == 1 && _state->search_type == JSON_SEARCH_ARRAY)
711  {
712  /* single integer search */
713  _state->array_index++;
714  if (_state->array_index == _state->search_index)
715  get_next = true;
716  }
717  else if (_state->search_type == JSON_SEARCH_PATH &&
718  lex_level <= _state->npath &&
719  _state->pathok[lex_level - 1])
720  {
721  /*
722  * path search, path so far is ok
723  *
724  * increment the array counter. no point doing this if we already know
725  * the path is bad.
726  *
727  * then check if we have a match.
728  */
729 
730  if (++_state->array_level_index[lex_level - 1] ==
731  _state->path_level_index[lex_level - 1])
732  {
733  if (lex_level == _state->npath)
734  {
735  /* match and at end of path, so get value */
736  get_next = true;
737  }
738  else
739  {
740  /* not at end of path just mark path ok */
741  _state->pathok[lex_level] = true;
742  }
743  }
744 
745  }
746 
747  /* same logic as for objects */
748  if (get_next)
749  {
750  if (_state->normalize_results &&
751  _state->lex->token_type == JSON_TOKEN_STRING)
752  {
753  _state->next_scalar = true;
754  }
755  else
756  {
757  _state->result_start = _state->lex->token_start;
758  }
759  }
760 }
761 
762 static void
763 get_array_element_end(void *state, bool isnull)
764 {
765  GetState *_state = (GetState *) state;
766  bool get_last = false;
767  int lex_level = _state->lex->lex_level;
768 
769  /* same logic as in get_object_end, modified for arrays */
770 
771  if (lex_level == 1 && _state->search_type == JSON_SEARCH_ARRAY &&
772  _state->array_index == _state->search_index)
773  {
774  get_last = true;
775  }
776  else if (_state->search_type == JSON_SEARCH_PATH &&
777  lex_level <= _state->npath &&
778  _state->pathok[lex_level - 1] &&
779  _state->array_level_index[lex_level - 1] ==
780  _state->path_level_index[lex_level - 1])
781  {
782  /* done with this element so reset pathok */
783  if (lex_level < _state->npath)
784  _state->pathok[lex_level] = false;
785 
786  if (lex_level == _state->npath)
787  get_last = true;
788  }
789  if (get_last && _state->result_start != NULL)
790  {
791  int len = _state->lex->prev_token_terminator - _state->result_start;
792 
793  if (isnull && _state->normalize_results)
794  _state->tresult = (text *) NULL;
795  else
796  _state->tresult = cstring_to_text_with_len(_state->result_start, len);
797  }
798 }
799 
800 static void
801 get_scalar(void *state, char *token, JsonTokenType tokentype)
802 {
803  GetState *_state = (GetState *) state;
804 
805  if (_state->lex->lex_level == 0 && _state->search_type != JSON_SEARCH_PATH)
806  ereport(ERROR,
807  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
808  errmsg("cannot extract element from a scalar")));
809  if (_state->next_scalar)
810  {
811  /* a de-escaped text value is wanted, so supply it */
812  _state->tresult = cstring_to_text(token);
813  /* make sure the next call to get_scalar doesn't overwrite it */
814  _state->next_scalar = false;
815  }
816 
817 }
818 
819 /*
820  * SQL function json_array_length(json) -> int
821  */
822 Datum
824 {
825  text *json = PG_GETARG_TEXT_P(0);
826 
827  AlenState *state;
828  JsonLexContext *lex = makeJsonLexContext(json, false);
829  JsonSemAction *sem;
830 
831  state = palloc0(sizeof(AlenState));
832  sem = palloc0(sizeof(JsonSemAction));
833 
834  /* palloc0 does this for us */
835 #if 0
836  state->count = 0;
837 #endif
838  state->lex = lex;
839 
840  sem->semstate = (void *) state;
842  sem->scalar = alen_scalar;
844 
845  pg_parse_json(lex, sem);
846 
847  PG_RETURN_INT32(state->count);
848 }
849 
850 /*
851  * These next two check ensure that the json is an array (since it can't be
852  * a scalar or an object).
853  */
854 
855 static void
857 {
858  AlenState *_state = (AlenState *) state;
859 
860  /* json structure check */
861  if (_state->lex->lex_level == 0)
862  ereport(ERROR,
863  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
864  errmsg("cannot get array length of a non-array")));
865 }
866 
867 static void
868 alen_scalar(void *state, char *token, JsonTokenType tokentype)
869 {
870  AlenState *_state = (AlenState *) state;
871 
872  /* json structure check */
873  if (_state->lex->lex_level == 0)
874  ereport(ERROR,
875  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
876  errmsg("cannot get array length of a scalar")));
877 }
878 
879 static void
880 alen_array_element_start(void *state, bool isnull)
881 {
882  AlenState *_state = (AlenState *) state;
883 
884  /* just count up all the level 1 elements */
885  if (_state->lex->lex_level == 1)
886  _state->count++;
887 }
888 
889 /*
890  * SQL function json_each and json_each_text
891  *
892  * decompose a json object into key value pairs.
893  *
894  * Unlike json_object_keys() these SRFs operate in materialize mode,
895  * stashing results into a Tuplestore object as they go.
896  * The construction of tuples is done using a temporary memory context
897  * that is cleared out after each tuple is built.
898  */
899 Datum
901 {
902  return each_worker(fcinfo, false);
903 }
904 
905 Datum
907 {
908  return each_worker(fcinfo, true);
909 }
910 
911 static inline Datum
913 {
914  text *json = PG_GETARG_TEXT_P(0);
915  JsonLexContext *lex = makeJsonLexContext(json, true);
916  JsonSemAction *sem;
917  ReturnSetInfo *rsi;
918  MemoryContext old_cxt;
919  TupleDesc tupdesc;
920  EachState *state;
921 
922  state = palloc0(sizeof(EachState));
923  sem = palloc0(sizeof(JsonSemAction));
924 
925  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
926 
927  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
928  (rsi->allowedModes & SFRM_Materialize) == 0 ||
929  rsi->expectedDesc == NULL)
930  ereport(ERROR,
931  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
932  errmsg("set-valued function called in context that "
933  "cannot accept a set")));
934 
935 
937 
938  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
939 
940  /* make these in a sufficiently long-lived memory context */
942 
943  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
944  BlessTupleDesc(state->ret_tdesc);
945  state->tuple_store =
947  false, work_mem);
948 
949  MemoryContextSwitchTo(old_cxt);
950 
951  sem->semstate = (void *) state;
953  sem->scalar = each_scalar;
956 
957  state->normalize_results = as_text;
958  state->next_scalar = false;
959 
960  state->lex = lex;
962  "json_each temporary cxt",
966 
967  pg_parse_json(lex, sem);
968 
969  rsi->setResult = state->tuple_store;
970  rsi->setDesc = state->ret_tdesc;
971 
972  PG_RETURN_NULL();
973 }
974 
975 
976 static void
977 each_object_field_start(void *state, char *fname, bool isnull)
978 {
979  EachState *_state = (EachState *) state;
980 
981  /* save a pointer to where the value starts */
982  if (_state->lex->lex_level == 1)
983  {
984  /*
985  * next_scalar will be reset in the object_field_end handler, and
986  * since we know the value is a scalar there is no danger of it being
987  * on while recursing down the tree.
988  */
989  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
990  _state->next_scalar = true;
991  else
992  _state->result_start = _state->lex->token_start;
993  }
994 }
995 
996 static void
997 each_object_field_end(void *state, char *fname, bool isnull)
998 {
999  EachState *_state = (EachState *) state;
1000  MemoryContext old_cxt;
1001  int len;
1002  text *val;
1003  HeapTuple tuple;
1004  Datum values[2];
1005  bool nulls[2] = {false, false};
1006 
1007  /* skip over nested objects */
1008  if (_state->lex->lex_level != 1)
1009  return;
1010 
1011  /* use the tmp context so we can clean up after each tuple is done */
1012  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1013 
1014  values[0] = CStringGetTextDatum(fname);
1015 
1016  if (isnull && _state->normalize_results)
1017  {
1018  nulls[1] = true;
1019  values[1] = (Datum) NULL;
1020  }
1021  else if (_state->next_scalar)
1022  {
1023  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1024  _state->next_scalar = false;
1025  }
1026  else
1027  {
1028  len = _state->lex->prev_token_terminator - _state->result_start;
1029  val = cstring_to_text_with_len(_state->result_start, len);
1030  values[1] = PointerGetDatum(val);
1031  }
1032 
1033 
1034  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1035 
1036  tuplestore_puttuple(_state->tuple_store, tuple);
1037 
1038  /* clean up and switch back */
1039  MemoryContextSwitchTo(old_cxt);
1040  MemoryContextReset(_state->tmp_cxt);
1041 }
1042 
1043 static void
1045 {
1046  EachState *_state = (EachState *) state;
1047 
1048  /* json structure check */
1049  if (_state->lex->lex_level == 0)
1050  ereport(ERROR,
1051  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1052  errmsg("cannot deconstruct an array as an object")));
1053 }
1054 
1055 static void
1056 each_scalar(void *state, char *token, JsonTokenType tokentype)
1057 {
1058  EachState *_state = (EachState *) state;
1059 
1060  /* json structure check */
1061  if (_state->lex->lex_level == 0)
1062  ereport(ERROR,
1063  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1064  errmsg("cannot deconstruct a scalar")));
1065 
1066  /* supply de-escaped value if required */
1067  if (_state->next_scalar)
1068  _state->normalized_scalar = token;
1069 }
1070 
1071 /*
1072  * SQL function json_array_elements
1073  *
1074  * get the elements from a json array
1075  *
1076  * a lot of this processing is similar to the json_each* functions
1077  */
1078 Datum
1080 {
1081  text *json = PG_GETARG_TEXT_P(0);
1082 
1083  /* elements doesn't need any escaped strings, so use false here */
1084  JsonLexContext *lex = makeJsonLexContext(json, false);
1085  JsonSemAction *sem;
1086  ReturnSetInfo *rsi;
1087  MemoryContext old_cxt;
1088  TupleDesc tupdesc;
1090 
1091  state = palloc0(sizeof(ElementsState));
1092  sem = palloc0(sizeof(JsonSemAction));
1093 
1094  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1095 
1096  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1097  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1098  rsi->expectedDesc == NULL)
1099  ereport(ERROR,
1100  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1101  errmsg("set-valued function called in context that "
1102  "cannot accept a set")));
1103 
1104 
1106 
1107  /* it's a simple type, so don't use get_call_result_type() */
1108  tupdesc = rsi->expectedDesc;
1109 
1110  /* make these in a sufficiently long-lived memory context */
1112 
1113  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1114  BlessTupleDesc(state->ret_tdesc);
1115  state->tuple_store =
1117  false, work_mem);
1118 
1119  MemoryContextSwitchTo(old_cxt);
1120 
1121  sem->semstate = (void *) state;
1123  sem->scalar = elements_scalar;
1126 
1127  state->lex = lex;
1129  "json_array_elements temporary cxt",
1133 
1134  pg_parse_json(lex, sem);
1135 
1136  rsi->setResult = state->tuple_store;
1137  rsi->setDesc = state->ret_tdesc;
1138 
1139  PG_RETURN_NULL();
1140 }
1141 
1142 static void
1144 {
1145  ElementsState *_state = (ElementsState *) state;
1146 
1147  /* save a pointer to where the value starts */
1148  if (_state->lex->lex_level == 1)
1149  _state->result_start = _state->lex->token_start;
1150 }
1151 
1152 static void
1154 {
1155  ElementsState *_state = (ElementsState *) state;
1156  MemoryContext old_cxt;
1157  int len;
1158  text *val;
1159  HeapTuple tuple;
1160  Datum values[1];
1161  static bool nulls[1] = {false};
1162 
1163  /* skip over nested objects */
1164  if (_state->lex->lex_level != 1)
1165  return;
1166 
1167  /* use the tmp context so we can clean up after each tuple is done */
1168  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1169 
1170  len = _state->lex->prev_token_terminator - _state->result_start;
1171  val = cstring_to_text_with_len(_state->result_start, len);
1172 
1173  values[0] = PointerGetDatum(val);
1174 
1175  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1176 
1177  tuplestore_puttuple(_state->tuple_store, tuple);
1178 
1179  /* clean up and switch back */
1180  MemoryContextSwitchTo(old_cxt);
1181  MemoryContextReset(_state->tmp_cxt);
1182 }
1183 
1184 static void
1186 {
1187  ElementsState *_state = (ElementsState *) state;
1188 
1189  /* json structure check */
1190  if (_state->lex->lex_level == 0)
1191  ereport(ERROR,
1192  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1193  errmsg("cannot call json_array_elements on a non-array")));
1194 }
1195 
1196 static void
1197 elements_scalar(void *state, char *token, JsonTokenType tokentype)
1198 {
1199  ElementsState *_state = (ElementsState *) state;
1200 
1201  /* json structure check */
1202  if (_state->lex->lex_level == 0)
1203  ereport(ERROR,
1204  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1205  errmsg("cannot call json_array_elements on a scalar")));
1206 
1207  /*
1208  * json_array_elements always returns json, so there's no need to think
1209  * about de-escaped values here.
1210  */
1211 }
1212 
1213 /*
1214  * SQL function json_populate_record
1215  *
1216  * set fields in a record from the argument json
1217  *
1218  * Code adapted shamelessly from hstore's populate_record
1219  * which is in turn partly adapted from record_out.
1220  *
1221  * The json is decomposed into a hash table, in which each
1222  * field in the record is then looked up by name.
1223  */
1224 Datum
1226 {
1227  return populate_record_worker(fcinfo, true);
1228 }
1229 
1230 Datum
1232 {
1233  return populate_record_worker(fcinfo, false);
1234 }
1235 
1236 static inline Datum
1238 {
1239  text *json;
1240  bool use_json_as_text;
1241  HTAB *json_hash;
1242  HeapTupleHeader rec = NULL;
1243  Oid tupType;
1244  int32 tupTypmod;
1245  TupleDesc tupdesc;
1246  HeapTupleData tuple;
1247  HeapTuple rettuple;
1248  RecordIOData *my_extra;
1249  int ncolumns;
1250  int i;
1251  Datum *values;
1252  bool *nulls;
1253  char fname[NAMEDATALEN];
1254  JsonHashEntry *hashentry;
1255 
1256  if (have_record_arg)
1257  {
1258  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
1259 
1260  use_json_as_text = PG_ARGISNULL(2) ? false : PG_GETARG_BOOL(2);
1261 
1262  if (!type_is_rowtype(argtype))
1263  ereport(ERROR,
1264  (errcode(ERRCODE_DATATYPE_MISMATCH),
1265  errmsg("first argument of json_populate_record must be a row type")));
1266 
1267  if (PG_ARGISNULL(0))
1268  {
1269  if (PG_ARGISNULL(1))
1270  PG_RETURN_NULL();
1271 
1272  /*
1273  * have no tuple to look at, so the only source of type info is
1274  * the argtype. The lookup_rowtype_tupdesc call below will error
1275  * out if we don't have a known composite type oid here.
1276  */
1277  tupType = argtype;
1278  tupTypmod = -1;
1279  }
1280  else
1281  {
1282  rec = PG_GETARG_HEAPTUPLEHEADER(0);
1283 
1284  if (PG_ARGISNULL(1))
1285  PG_RETURN_POINTER(rec);
1286 
1287  /* Extract type info from the tuple itself */
1288  tupType = HeapTupleHeaderGetTypeId(rec);
1289  tupTypmod = HeapTupleHeaderGetTypMod(rec);
1290  }
1291 
1292  json = PG_GETARG_TEXT_P(1);
1293  }
1294  else
1295  {
1296  /* json_to_record case */
1297 
1298  use_json_as_text = PG_ARGISNULL(1) ? false : PG_GETARG_BOOL(1);
1299 
1300  if (PG_ARGISNULL(0))
1301  PG_RETURN_NULL();
1302 
1303  json = PG_GETARG_TEXT_P(0);
1304 
1305  get_call_result_type(fcinfo, NULL, &tupdesc);
1306  }
1307 
1308  json_hash = get_json_object_as_hash(json, "json_populate_record",
1309  use_json_as_text);
1310 
1311  if (have_record_arg)
1312  {
1313  /*
1314  * if the input json is empty, we can only skip the rest if we were
1315  * passed in a non-null record, since otherwise there may be issues
1316  * with domain nulls.
1317  */
1318  if (hash_get_num_entries(json_hash) == 0 && rec)
1319  PG_RETURN_POINTER(rec);
1320 
1321 
1322  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1323  }
1324 
1325  ncolumns = tupdesc->natts;
1326 
1327  if (rec)
1328  {
1329  /* Build a temporary HeapTuple control structure */
1330  tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
1331  ItemPointerSetInvalid(&(tuple.t_self));
1332  tuple.t_tableOid = InvalidOid;
1333  tuple.t_data = rec;
1334  }
1335 
1336  /*
1337  * We arrange to look up the needed I/O info just once per series of
1338  * calls, assuming the record type doesn't change underneath us.
1339  */
1340  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1341  if (my_extra == NULL ||
1342  my_extra->ncolumns != ncolumns)
1343  {
1344  fcinfo->flinfo->fn_extra =
1345  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1346  sizeof(RecordIOData) - sizeof(ColumnIOData)
1347  + ncolumns * sizeof(ColumnIOData));
1348  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1349  my_extra->record_type = InvalidOid;
1350  my_extra->record_typmod = 0;
1351  }
1352 
1353  if (have_record_arg && (my_extra->record_type != tupType ||
1354  my_extra->record_typmod != tupTypmod))
1355  {
1356  MemSet(my_extra, 0,
1357  sizeof(RecordIOData) - sizeof(ColumnIOData)
1358  + ncolumns * sizeof(ColumnIOData));
1359  my_extra->record_type = tupType;
1360  my_extra->record_typmod = tupTypmod;
1361  my_extra->ncolumns = ncolumns;
1362  }
1363 
1364  values = (Datum *) palloc(ncolumns * sizeof(Datum));
1365  nulls = (bool *) palloc(ncolumns * sizeof(bool));
1366 
1367  if (rec)
1368  {
1369  /* Break down the tuple into fields */
1370  heap_deform_tuple(&tuple, tupdesc, values, nulls);
1371  }
1372  else
1373  {
1374  for (i = 0; i < ncolumns; ++i)
1375  {
1376  values[i] = (Datum) 0;
1377  nulls[i] = true;
1378  }
1379  }
1380 
1381  for (i = 0; i < ncolumns; ++i)
1382  {
1383  ColumnIOData *column_info = &my_extra->columns[i];
1384  Oid column_type = tupdesc->attrs[i]->atttypid;
1385  char *value;
1386 
1387  /* Ignore dropped columns in datatype */
1388  if (tupdesc->attrs[i]->attisdropped)
1389  {
1390  nulls[i] = true;
1391  continue;
1392  }
1393 
1394  memset(fname, 0, NAMEDATALEN);
1395  strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
1396  hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
1397 
1398  /*
1399  * we can't just skip here if the key wasn't found since we might have
1400  * a domain to deal with. If we were passed in a non-null record
1401  * datum, we assume that the existing values are valid (if they're
1402  * not, then it's not our fault), but if we were passed in a null,
1403  * then every field which we don't populate needs to be run through
1404  * the input function just in case it's a domain type.
1405  */
1406  if (hashentry == NULL && rec)
1407  continue;
1408 
1409  /*
1410  * Prepare to convert the column value from text
1411  */
1412  if (column_info->column_type != column_type)
1413  {
1414  getTypeInputInfo(column_type,
1415  &column_info->typiofunc,
1416  &column_info->typioparam);
1417  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
1418  fcinfo->flinfo->fn_mcxt);
1419  column_info->column_type = column_type;
1420  }
1421  if (hashentry == NULL || hashentry->isnull)
1422  {
1423  /*
1424  * need InputFunctionCall to happen even for nulls, so that domain
1425  * checks are done
1426  */
1427  values[i] = InputFunctionCall(&column_info->proc, NULL,
1428  column_info->typioparam,
1429  tupdesc->attrs[i]->atttypmod);
1430  nulls[i] = true;
1431  }
1432  else
1433  {
1434  value = hashentry->val;
1435 
1436  values[i] = InputFunctionCall(&column_info->proc, value,
1437  column_info->typioparam,
1438  tupdesc->attrs[i]->atttypmod);
1439  nulls[i] = false;
1440  }
1441  }
1442 
1443  rettuple = heap_form_tuple(tupdesc, values, nulls);
1444 
1445  ReleaseTupleDesc(tupdesc);
1446 
1448 }
1449 
1450 /*
1451  * get_json_object_as_hash
1452  *
1453  * decompose a json object into a hash table.
1454  *
1455  * Currently doesn't allow anything but a flat object. Should this
1456  * change?
1457  *
1458  * funcname argument allows caller to pass in its name for use in
1459  * error messages.
1460  */
1461 static HTAB *
1462 get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text)
1463 {
1464  HASHCTL ctl;
1465  HTAB *tab;
1466  JHashState *state;
1467  JsonLexContext *lex = makeJsonLexContext(json, true);
1468  JsonSemAction *sem;
1469 
1470  memset(&ctl, 0, sizeof(ctl));
1471  ctl.keysize = NAMEDATALEN;
1472  ctl.entrysize = sizeof(JsonHashEntry);
1473  ctl.hcxt = CurrentMemoryContext;
1474  tab = hash_create("json object hashtable",
1475  100,
1476  &ctl,
1478 
1479  state = palloc0(sizeof(JHashState));
1480  sem = palloc0(sizeof(JsonSemAction));
1481 
1482  state->function_name = funcname;
1483  state->hash = tab;
1484  state->lex = lex;
1485  state->use_json_as_text = use_json_as_text;
1486 
1487  sem->semstate = (void *) state;
1489  sem->scalar = hash_scalar;
1492 
1493  pg_parse_json(lex, sem);
1494 
1495  return tab;
1496 }
1497 
1498 static void
1499 hash_object_field_start(void *state, char *fname, bool isnull)
1500 {
1501  JHashState *_state = (JHashState *) state;
1502 
1503  if (_state->lex->lex_level > 1)
1504  return;
1505 
1506  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
1508  {
1509  if (!_state->use_json_as_text)
1510  ereport(ERROR,
1511  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1512  errmsg("cannot call %s on a nested object",
1513  _state->function_name)));
1514  _state->save_json_start = _state->lex->token_start;
1515  }
1516  else
1517  {
1518  /* must be a scalar */
1519  _state->save_json_start = NULL;
1520  }
1521 }
1522 
1523 static void
1524 hash_object_field_end(void *state, char *fname, bool isnull)
1525 {
1526  JHashState *_state = (JHashState *) state;
1527  JsonHashEntry *hashentry;
1528  bool found;
1529  char name[NAMEDATALEN];
1530 
1531  /*
1532  * ignore field names >= NAMEDATALEN - they can't match a record field
1533  * ignore nested fields.
1534  */
1535  if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
1536  return;
1537 
1538  memset(name, 0, NAMEDATALEN);
1539  strncpy(name, fname, NAMEDATALEN);
1540 
1541  hashentry = hash_search(_state->hash, name, HASH_ENTER, &found);
1542 
1543  /*
1544  * found being true indicates a duplicate. We don't do anything about
1545  * that, a later field with the same name overrides the earlier field.
1546  */
1547 
1548  hashentry->isnull = isnull;
1549  if (_state->save_json_start != NULL)
1550  {
1551  int len = _state->lex->prev_token_terminator - _state->save_json_start;
1552  char *val = palloc((len + 1) * sizeof(char));
1553 
1554  memcpy(val, _state->save_json_start, len);
1555  val[len] = '\0';
1556  hashentry->val = val;
1557  }
1558  else
1559  {
1560  /* must have had a scalar instead */
1561  hashentry->val = _state->saved_scalar;
1562  }
1563 }
1564 
1565 static void
1567 {
1568  JHashState *_state = (JHashState *) state;
1569 
1570  if (_state->lex->lex_level == 0)
1571  ereport(ERROR,
1572  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1573  errmsg("cannot call %s on an array", _state->function_name)));
1574 }
1575 
1576 static void
1577 hash_scalar(void *state, char *token, JsonTokenType tokentype)
1578 {
1579  JHashState *_state = (JHashState *) state;
1580 
1581  if (_state->lex->lex_level == 0)
1582  ereport(ERROR,
1583  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1584  errmsg("cannot call %s on a scalar", _state->function_name)));
1585 
1586  if (_state->lex->lex_level == 1)
1587  _state->saved_scalar = token;
1588 }
1589 
1590 
1591 /*
1592  * SQL function json_populate_recordset
1593  *
1594  * set fields in a set of records from the argument json,
1595  * which must be an array of objects.
1596  *
1597  * similar to json_populate_record, but the tuple-building code
1598  * is pushed down into the semantic action handlers so it's done
1599  * per object in the array.
1600  */
1601 Datum
1603 {
1604  return populate_recordset_worker(fcinfo, true);
1605 }
1606 
1607 Datum
1609 {
1610  return populate_recordset_worker(fcinfo, false);
1611 }
1612 
1613 /*
1614  * common worker for json_populate_recordset() and json_to_recordset()
1615  */
1616 static inline Datum
1618 {
1619  Oid argtype;
1620  text *json;
1621  bool use_json_as_text;
1622  ReturnSetInfo *rsi;
1623  MemoryContext old_cxt;
1624  Oid tupType;
1625  int32 tupTypmod;
1626  HeapTupleHeader rec;
1627  TupleDesc tupdesc;
1628  RecordIOData *my_extra;
1629  int ncolumns;
1630  JsonLexContext *lex;
1631  JsonSemAction *sem;
1633 
1634  if (have_record_arg)
1635  {
1636  argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
1637 
1638  use_json_as_text = PG_ARGISNULL(2) ? false : PG_GETARG_BOOL(2);
1639 
1640  if (!type_is_rowtype(argtype))
1641  ereport(ERROR,
1642  (errcode(ERRCODE_DATATYPE_MISMATCH),
1643  errmsg("first argument of json_populate_recordset must be a row type")));
1644  }
1645  else
1646  {
1647  argtype = InvalidOid;
1648 
1649  use_json_as_text = PG_ARGISNULL(1) ? false : PG_GETARG_BOOL(1);
1650  }
1651 
1652  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1653 
1654  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1655  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1656  rsi->expectedDesc == NULL)
1657  ereport(ERROR,
1658  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1659  errmsg("set-valued function called in context that "
1660  "cannot accept a set")));
1661 
1662 
1664 
1665  /*
1666  * get the tupdesc from the result set info - it must be a record type
1667  * because we already checked that arg1 is a record type.
1668  */
1669  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1670 
1671  state = palloc0(sizeof(PopulateRecordsetState));
1672  sem = palloc0(sizeof(JsonSemAction));
1673 
1674 
1675  /* make these in a sufficiently long-lived memory context */
1677 
1678  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1679  BlessTupleDesc(state->ret_tdesc);
1680  state->tuple_store =
1682  false, work_mem);
1683 
1684  MemoryContextSwitchTo(old_cxt);
1685 
1686  /* if the json is null send back an empty set */
1687  if (have_record_arg)
1688  {
1689  if (PG_ARGISNULL(1))
1690  PG_RETURN_NULL();
1691 
1692  json = PG_GETARG_TEXT_P(1);
1693 
1694  if (PG_ARGISNULL(0))
1695  rec = NULL;
1696  else
1697  rec = PG_GETARG_HEAPTUPLEHEADER(0);
1698  }
1699  else
1700  {
1701  if (PG_ARGISNULL(0))
1702  PG_RETURN_NULL();
1703 
1704  json = PG_GETARG_TEXT_P(0);
1705 
1706  rec = NULL;
1707  }
1708 
1709  tupType = tupdesc->tdtypeid;
1710  tupTypmod = tupdesc->tdtypmod;
1711  ncolumns = tupdesc->natts;
1712 
1713  lex = makeJsonLexContext(json, true);
1714 
1715  /*
1716  * We arrange to look up the needed I/O info just once per series of
1717  * calls, assuming the record type doesn't change underneath us.
1718  */
1719  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1720  if (my_extra == NULL ||
1721  my_extra->ncolumns != ncolumns)
1722  {
1723  fcinfo->flinfo->fn_extra =
1724  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1725  sizeof(RecordIOData) - sizeof(ColumnIOData)
1726  + ncolumns * sizeof(ColumnIOData));
1727  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1728  my_extra->record_type = InvalidOid;
1729  my_extra->record_typmod = 0;
1730  }
1731 
1732  if (my_extra->record_type != tupType ||
1733  my_extra->record_typmod != tupTypmod)
1734  {
1735  MemSet(my_extra, 0,
1736  sizeof(RecordIOData) - sizeof(ColumnIOData)
1737  + ncolumns * sizeof(ColumnIOData));
1738  my_extra->record_type = tupType;
1739  my_extra->record_typmod = tupTypmod;
1740  my_extra->ncolumns = ncolumns;
1741  }
1742 
1743  sem->semstate = (void *) state;
1751 
1752  state->lex = lex;
1753 
1754  state->my_extra = my_extra;
1755  state->rec = rec;
1756  state->use_json_as_text = use_json_as_text;
1757  state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
1758 
1759  pg_parse_json(lex, sem);
1760 
1761  rsi->setResult = state->tuple_store;
1762  rsi->setDesc = state->ret_tdesc;
1763 
1764  PG_RETURN_NULL();
1765 
1766 }
1767 
1768 static void
1770 {
1771  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1772  int lex_level = _state->lex->lex_level;
1773  HASHCTL ctl;
1774 
1775  if (lex_level == 0)
1776  ereport(ERROR,
1777  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1778  errmsg("cannot call json_populate_recordset on an object")));
1779  else if (lex_level > 1 && !_state->use_json_as_text)
1780  ereport(ERROR,
1781  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1782  errmsg("cannot call json_populate_recordset with nested objects")));
1783 
1784  /* set up a new hash for this entry */
1785  memset(&ctl, 0, sizeof(ctl));
1786  ctl.keysize = NAMEDATALEN;
1787  ctl.entrysize = sizeof(JsonHashEntry);
1788  ctl.hcxt = CurrentMemoryContext;
1789  _state->json_hash = hash_create("json object hashtable",
1790  100,
1791  &ctl,
1793 }
1794 
1795 static void
1797 {
1798  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1799  HTAB *json_hash = _state->json_hash;
1800  Datum *values;
1801  bool *nulls;
1802  char fname[NAMEDATALEN];
1803  int i;
1804  RecordIOData *my_extra = _state->my_extra;
1805  int ncolumns = my_extra->ncolumns;
1806  TupleDesc tupdesc = _state->ret_tdesc;
1807  JsonHashEntry *hashentry;
1808  HeapTupleHeader rec = _state->rec;
1809  HeapTuple rettuple;
1810 
1811  if (_state->lex->lex_level > 1)
1812  return;
1813 
1814  values = (Datum *) palloc(ncolumns * sizeof(Datum));
1815  nulls = (bool *) palloc(ncolumns * sizeof(bool));
1816 
1817  if (_state->rec)
1818  {
1819  HeapTupleData tuple;
1820 
1821  /* Build a temporary HeapTuple control structure */
1822  tuple.t_len = HeapTupleHeaderGetDatumLength(_state->rec);
1823  ItemPointerSetInvalid(&(tuple.t_self));
1824  tuple.t_tableOid = InvalidOid;
1825  tuple.t_data = _state->rec;
1826 
1827  /* Break down the tuple into fields */
1828  heap_deform_tuple(&tuple, tupdesc, values, nulls);
1829  }
1830  else
1831  {
1832  for (i = 0; i < ncolumns; ++i)
1833  {
1834  values[i] = (Datum) 0;
1835  nulls[i] = true;
1836  }
1837  }
1838 
1839  for (i = 0; i < ncolumns; ++i)
1840  {
1841  ColumnIOData *column_info = &my_extra->columns[i];
1842  Oid column_type = tupdesc->attrs[i]->atttypid;
1843  char *value;
1844 
1845  /* Ignore dropped columns in datatype */
1846  if (tupdesc->attrs[i]->attisdropped)
1847  {
1848  nulls[i] = true;
1849  continue;
1850  }
1851 
1852  memset(fname, 0, NAMEDATALEN);
1853  strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
1854  hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
1855 
1856  /*
1857  * we can't just skip here if the key wasn't found since we might have
1858  * a domain to deal with. If we were passed in a non-null record
1859  * datum, we assume that the existing values are valid (if they're
1860  * not, then it's not our fault), but if we were passed in a null,
1861  * then every field which we don't populate needs to be run through
1862  * the input function just in case it's a domain type.
1863  */
1864  if (hashentry == NULL && rec)
1865  continue;
1866 
1867  /*
1868  * Prepare to convert the column value from text
1869  */
1870  if (column_info->column_type != column_type)
1871  {
1872  getTypeInputInfo(column_type,
1873  &column_info->typiofunc,
1874  &column_info->typioparam);
1875  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
1876  _state->fn_mcxt);
1877  column_info->column_type = column_type;
1878  }
1879  if (hashentry == NULL || hashentry->isnull)
1880  {
1881  /*
1882  * need InputFunctionCall to happen even for nulls, so that domain
1883  * checks are done
1884  */
1885  values[i] = InputFunctionCall(&column_info->proc, NULL,
1886  column_info->typioparam,
1887  tupdesc->attrs[i]->atttypmod);
1888  nulls[i] = true;
1889  }
1890  else
1891  {
1892  value = hashentry->val;
1893 
1894  values[i] = InputFunctionCall(&column_info->proc, value,
1895  column_info->typioparam,
1896  tupdesc->attrs[i]->atttypmod);
1897  nulls[i] = false;
1898  }
1899  }
1900 
1901  rettuple = heap_form_tuple(tupdesc, values, nulls);
1902 
1903  tuplestore_puttuple(_state->tuple_store, rettuple);
1904 
1905  hash_destroy(json_hash);
1906 }
1907 
1908 static void
1910 {
1911  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1912 
1913  if (_state->lex->lex_level == 1 &&
1915  ereport(ERROR,
1916  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1917  errmsg("must call json_populate_recordset on an array of objects")));
1918 }
1919 
1920 static void
1922 {
1923  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1924 
1925  if (_state->lex->lex_level != 0 && !_state->use_json_as_text)
1926  ereport(ERROR,
1927  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1928  errmsg("cannot call json_populate_recordset with nested arrays")));
1929 }
1930 
1931 static void
1932 populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
1933 {
1934  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1935 
1936  if (_state->lex->lex_level == 0)
1937  ereport(ERROR,
1938  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1939  errmsg("cannot call json_populate_recordset on a scalar")));
1940 
1941  if (_state->lex->lex_level == 2)
1942  _state->saved_scalar = token;
1943 }
1944 
1945 static void
1946 populate_recordset_object_field_start(void *state, char *fname, bool isnull)
1947 {
1948  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1949 
1950  if (_state->lex->lex_level > 2)
1951  return;
1952 
1953  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
1955  {
1956  if (!_state->use_json_as_text)
1957  ereport(ERROR,
1958  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1959  errmsg("cannot call json_populate_recordset on a nested object")));
1960  _state->save_json_start = _state->lex->token_start;
1961  }
1962  else
1963  {
1964  _state->save_json_start = NULL;
1965  }
1966 }
1967 
1968 static void
1969 populate_recordset_object_field_end(void *state, char *fname, bool isnull)
1970 {
1971  PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
1972  JsonHashEntry *hashentry;
1973  bool found;
1974  char name[NAMEDATALEN];
1975 
1976  /*
1977  * ignore field names >= NAMEDATALEN - they can't match a record field
1978  * ignore nested fields.
1979  */
1980  if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
1981  return;
1982 
1983  memset(name, 0, NAMEDATALEN);
1984  strncpy(name, fname, NAMEDATALEN);
1985 
1986  hashentry = hash_search(_state->json_hash, name, HASH_ENTER, &found);
1987 
1988  /*
1989  * found being true indicates a duplicate. We don't do anything about
1990  * that, a later field with the same name overrides the earlier field.
1991  */
1992 
1993  hashentry->isnull = isnull;
1994  if (_state->save_json_start != NULL)
1995  {
1996  int len = _state->lex->prev_token_terminator - _state->save_json_start;
1997  char *val = palloc((len + 1) * sizeof(char));
1998 
1999  memcpy(val, _state->save_json_start, len);
2000  val[len] = '\0';
2001  hashentry->val = val;
2002  }
2003  else
2004  {
2005  /* must have had a scalar instead */
2006  hashentry->val = _state->saved_scalar;
2007  }
2008 }