PostgreSQL Source Code  git master
json.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * json.c
4  * JSON data type support.
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/json.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "catalog/pg_proc.h"
17 #include "catalog/pg_type.h"
18 #include "common/hashfn.h"
19 #include "funcapi.h"
20 #include "libpq/pqformat.h"
21 #include "miscadmin.h"
22 #include "utils/array.h"
23 #include "utils/builtins.h"
24 #include "utils/date.h"
25 #include "utils/datetime.h"
26 #include "utils/json.h"
27 #include "utils/jsonfuncs.h"
28 #include "utils/lsyscache.h"
29 #include "utils/typcache.h"
30 
31 
32 /*
33  * Support for fast key uniqueness checking.
34  *
35  * We maintain a hash table of used keys in JSON objects for fast detection
36  * of duplicates.
37  */
38 /* Common context for key uniqueness check */
39 typedef struct HTAB *JsonUniqueCheckState; /* hash table for key names */
40 
41 /* Hash entry for JsonUniqueCheckState */
42 typedef struct JsonUniqueHashEntry
43 {
44  const char *key;
45  int key_len;
46  int object_id;
48 
49 /* Stack element for key uniqueness check during JSON parsing */
50 typedef struct JsonUniqueStackEntry
51 {
53  int object_id;
55 
56 /* Context struct for key uniqueness check during JSON parsing */
57 typedef struct JsonUniqueParsingState
58 {
63  bool unique;
65 
66 /* Context struct for key uniqueness check during JSON building */
67 typedef struct JsonUniqueBuilderState
68 {
69  JsonUniqueCheckState check; /* unique check */
70  StringInfoData skipped_keys; /* skipped keys with NULL values */
71  MemoryContext mcxt; /* context for saving skipped keys */
73 
74 
75 /* State struct for JSON aggregation */
76 typedef struct JsonAggState
77 {
85 
86 static void composite_to_json(Datum composite, StringInfo result,
87  bool use_line_feeds);
88 static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
89  Datum *vals, bool *nulls, int *valcount,
90  JsonTypeCategory tcategory, Oid outfuncoid,
91  bool use_line_feeds);
92 static void array_to_json_internal(Datum array, StringInfo result,
93  bool use_line_feeds);
94 static void datum_to_json_internal(Datum val, bool is_null, StringInfo result,
95  JsonTypeCategory tcategory, Oid outfuncoid,
96  bool key_scalar);
97 static void add_json(Datum val, bool is_null, StringInfo result,
98  Oid val_type, bool key_scalar);
99 static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
100 
101 /*
102  * Input.
103  */
104 Datum
106 {
107  char *json = PG_GETARG_CSTRING(0);
108  text *result = cstring_to_text(json);
109  JsonLexContext lex;
110 
111  /* validate it */
112  makeJsonLexContext(&lex, result, false);
113  if (!pg_parse_json_or_errsave(&lex, &nullSemAction, fcinfo->context))
114  PG_RETURN_NULL();
115 
116  /* Internal representation is the same as text */
117  PG_RETURN_TEXT_P(result);
118 }
119 
120 /*
121  * Output.
122  */
123 Datum
125 {
126  /* we needn't detoast because text_to_cstring will handle that */
127  Datum txt = PG_GETARG_DATUM(0);
128 
130 }
131 
132 /*
133  * Binary send.
134  */
135 Datum
137 {
138  text *t = PG_GETARG_TEXT_PP(0);
140 
144 }
145 
146 /*
147  * Binary receive.
148  */
149 Datum
151 {
153  char *str;
154  int nbytes;
155  JsonLexContext lex;
156 
157  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
158 
159  /* Validate it. */
161  false);
163 
165 }
166 
167 /*
168  * Turn a Datum into JSON text, appending the string to "result".
169  *
170  * tcategory and outfuncoid are from a previous call to json_categorize_type,
171  * except that if is_null is true then they can be invalid.
172  *
173  * If key_scalar is true, the value is being printed as a key, so insist
174  * it's of an acceptable type, and force it to be quoted.
175  */
176 static void
178  JsonTypeCategory tcategory, Oid outfuncoid,
179  bool key_scalar)
180 {
181  char *outputstr;
182  text *jsontext;
183 
185 
186  /* callers are expected to ensure that null keys are not passed in */
187  Assert(!(key_scalar && is_null));
188 
189  if (is_null)
190  {
191  appendBinaryStringInfo(result, "null", strlen("null"));
192  return;
193  }
194 
195  if (key_scalar &&
196  (tcategory == JSONTYPE_ARRAY ||
197  tcategory == JSONTYPE_COMPOSITE ||
198  tcategory == JSONTYPE_JSON ||
199  tcategory == JSONTYPE_CAST))
200  ereport(ERROR,
201  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
202  errmsg("key value must be scalar, not array, composite, or json")));
203 
204  switch (tcategory)
205  {
206  case JSONTYPE_ARRAY:
207  array_to_json_internal(val, result, false);
208  break;
209  case JSONTYPE_COMPOSITE:
210  composite_to_json(val, result, false);
211  break;
212  case JSONTYPE_BOOL:
213  if (key_scalar)
214  appendStringInfoChar(result, '"');
215  if (DatumGetBool(val))
216  appendBinaryStringInfo(result, "true", strlen("true"));
217  else
218  appendBinaryStringInfo(result, "false", strlen("false"));
219  if (key_scalar)
220  appendStringInfoChar(result, '"');
221  break;
222  case JSONTYPE_NUMERIC:
223  outputstr = OidOutputFunctionCall(outfuncoid, val);
224 
225  /*
226  * Don't quote a non-key if it's a valid JSON number (i.e., not
227  * "Infinity", "-Infinity", or "NaN"). Since we know this is a
228  * numeric data type's output, we simplify and open-code the
229  * validation for better performance.
230  */
231  if (!key_scalar &&
232  ((*outputstr >= '0' && *outputstr <= '9') ||
233  (*outputstr == '-' &&
234  (outputstr[1] >= '0' && outputstr[1] <= '9'))))
235  appendStringInfoString(result, outputstr);
236  else
237  {
238  appendStringInfoChar(result, '"');
239  appendStringInfoString(result, outputstr);
240  appendStringInfoChar(result, '"');
241  }
242  pfree(outputstr);
243  break;
244  case JSONTYPE_DATE:
245  {
246  char buf[MAXDATELEN + 1];
247 
248  JsonEncodeDateTime(buf, val, DATEOID, NULL);
249  appendStringInfoChar(result, '"');
250  appendStringInfoString(result, buf);
251  appendStringInfoChar(result, '"');
252  }
253  break;
254  case JSONTYPE_TIMESTAMP:
255  {
256  char buf[MAXDATELEN + 1];
257 
258  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
259  appendStringInfoChar(result, '"');
260  appendStringInfoString(result, buf);
261  appendStringInfoChar(result, '"');
262  }
263  break;
265  {
266  char buf[MAXDATELEN + 1];
267 
268  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
269  appendStringInfoChar(result, '"');
270  appendStringInfoString(result, buf);
271  appendStringInfoChar(result, '"');
272  }
273  break;
274  case JSONTYPE_JSON:
275  /* JSON and JSONB output will already be escaped */
276  outputstr = OidOutputFunctionCall(outfuncoid, val);
277  appendStringInfoString(result, outputstr);
278  pfree(outputstr);
279  break;
280  case JSONTYPE_CAST:
281  /* outfuncoid refers to a cast function, not an output function */
282  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
283  appendBinaryStringInfo(result, VARDATA_ANY(jsontext),
284  VARSIZE_ANY_EXHDR(jsontext));
285  pfree(jsontext);
286  break;
287  default:
288  outputstr = OidOutputFunctionCall(outfuncoid, val);
289  escape_json(result, outputstr);
290  pfree(outputstr);
291  break;
292  }
293 }
294 
295 /*
296  * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
297  * optionally preallocated buffer 'buf'. Optional 'tzp' determines time-zone
298  * offset (in seconds) in which we want to show timestamptz.
299  */
300 char *
301 JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
302 {
303  if (!buf)
304  buf = palloc(MAXDATELEN + 1);
305 
306  switch (typid)
307  {
308  case DATEOID:
309  {
310  DateADT date;
311  struct pg_tm tm;
312 
314 
315  /* Same as date_out(), but forcing DateStyle */
316  if (DATE_NOT_FINITE(date))
318  else
319  {
321  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
323  }
324  }
325  break;
326  case TIMEOID:
327  {
328  TimeADT time = DatumGetTimeADT(value);
329  struct pg_tm tt,
330  *tm = &tt;
331  fsec_t fsec;
332 
333  /* Same as time_out(), but forcing DateStyle */
334  time2tm(time, tm, &fsec);
335  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
336  }
337  break;
338  case TIMETZOID:
339  {
341  struct pg_tm tt,
342  *tm = &tt;
343  fsec_t fsec;
344  int tz;
345 
346  /* Same as timetz_out(), but forcing DateStyle */
347  timetz2tm(time, tm, &fsec, &tz);
348  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
349  }
350  break;
351  case TIMESTAMPOID:
352  {
354  struct pg_tm tm;
355  fsec_t fsec;
356 
358  /* Same as timestamp_out(), but forcing DateStyle */
361  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
362  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
363  else
364  ereport(ERROR,
365  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
366  errmsg("timestamp out of range")));
367  }
368  break;
369  case TIMESTAMPTZOID:
370  {
372  struct pg_tm tm;
373  int tz;
374  fsec_t fsec;
375  const char *tzn = NULL;
376 
378 
379  /*
380  * If a time zone is specified, we apply the time-zone shift,
381  * convert timestamptz to pg_tm as if it were without a time
382  * zone, and then use the specified time zone for converting
383  * the timestamp into a string.
384  */
385  if (tzp)
386  {
387  tz = *tzp;
389  }
390 
391  /* Same as timestamptz_out(), but forcing DateStyle */
394  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
395  tzp ? NULL : &tzn, NULL) == 0)
396  {
397  if (tzp)
398  tm.tm_isdst = 1; /* set time-zone presence flag */
399 
400  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
401  }
402  else
403  ereport(ERROR,
404  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
405  errmsg("timestamp out of range")));
406  }
407  break;
408  default:
409  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
410  return NULL;
411  }
412 
413  return buf;
414 }
415 
416 /*
417  * Process a single dimension of an array.
418  * If it's the innermost dimension, output the values, otherwise call
419  * ourselves recursively to process the next dimension.
420  */
421 static void
422 array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals,
423  bool *nulls, int *valcount, JsonTypeCategory tcategory,
424  Oid outfuncoid, bool use_line_feeds)
425 {
426  int i;
427  const char *sep;
428 
429  Assert(dim < ndims);
430 
431  sep = use_line_feeds ? ",\n " : ",";
432 
433  appendStringInfoChar(result, '[');
434 
435  for (i = 1; i <= dims[dim]; i++)
436  {
437  if (i > 1)
438  appendStringInfoString(result, sep);
439 
440  if (dim + 1 == ndims)
441  {
442  datum_to_json_internal(vals[*valcount], nulls[*valcount],
443  result, tcategory,
444  outfuncoid, false);
445  (*valcount)++;
446  }
447  else
448  {
449  /*
450  * Do we want line feeds on inner dimensions of arrays? For now
451  * we'll say no.
452  */
453  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
454  valcount, tcategory, outfuncoid, false);
455  }
456  }
457 
458  appendStringInfoChar(result, ']');
459 }
460 
461 /*
462  * Turn an array into JSON.
463  */
464 static void
465 array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
466 {
467  ArrayType *v = DatumGetArrayTypeP(array);
468  Oid element_type = ARR_ELEMTYPE(v);
469  int *dim;
470  int ndim;
471  int nitems;
472  int count = 0;
473  Datum *elements;
474  bool *nulls;
475  int16 typlen;
476  bool typbyval;
477  char typalign;
478  JsonTypeCategory tcategory;
479  Oid outfuncoid;
480 
481  ndim = ARR_NDIM(v);
482  dim = ARR_DIMS(v);
483  nitems = ArrayGetNItems(ndim, dim);
484 
485  if (nitems <= 0)
486  {
487  appendStringInfoString(result, "[]");
488  return;
489  }
490 
491  get_typlenbyvalalign(element_type,
492  &typlen, &typbyval, &typalign);
493 
494  json_categorize_type(element_type, false,
495  &tcategory, &outfuncoid);
496 
497  deconstruct_array(v, element_type, typlen, typbyval,
498  typalign, &elements, &nulls,
499  &nitems);
500 
501  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
502  outfuncoid, use_line_feeds);
503 
504  pfree(elements);
505  pfree(nulls);
506 }
507 
508 /*
509  * Turn a composite / record into JSON.
510  */
511 static void
512 composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
513 {
514  HeapTupleHeader td;
515  Oid tupType;
516  int32 tupTypmod;
517  TupleDesc tupdesc;
518  HeapTupleData tmptup,
519  *tuple;
520  int i;
521  bool needsep = false;
522  const char *sep;
523  int seplen;
524 
525  /*
526  * We can avoid expensive strlen() calls by precalculating the separator
527  * length.
528  */
529  sep = use_line_feeds ? ",\n " : ",";
530  seplen = use_line_feeds ? strlen(",\n ") : strlen(",");
531 
532  td = DatumGetHeapTupleHeader(composite);
533 
534  /* Extract rowtype info and find a tupdesc */
535  tupType = HeapTupleHeaderGetTypeId(td);
536  tupTypmod = HeapTupleHeaderGetTypMod(td);
537  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
538 
539  /* Build a temporary HeapTuple control structure */
541  tmptup.t_data = td;
542  tuple = &tmptup;
543 
544  appendStringInfoChar(result, '{');
545 
546  for (i = 0; i < tupdesc->natts; i++)
547  {
548  Datum val;
549  bool isnull;
550  char *attname;
551  JsonTypeCategory tcategory;
552  Oid outfuncoid;
553  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
554 
555  if (att->attisdropped)
556  continue;
557 
558  if (needsep)
559  appendBinaryStringInfo(result, sep, seplen);
560  needsep = true;
561 
562  attname = NameStr(att->attname);
563  escape_json(result, attname);
564  appendStringInfoChar(result, ':');
565 
566  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
567 
568  if (isnull)
569  {
570  tcategory = JSONTYPE_NULL;
571  outfuncoid = InvalidOid;
572  }
573  else
574  json_categorize_type(att->atttypid, false, &tcategory,
575  &outfuncoid);
576 
577  datum_to_json_internal(val, isnull, result, tcategory, outfuncoid,
578  false);
579  }
580 
581  appendStringInfoChar(result, '}');
582  ReleaseTupleDesc(tupdesc);
583 }
584 
585 /*
586  * Append JSON text for "val" to "result".
587  *
588  * This is just a thin wrapper around datum_to_json. If the same type will be
589  * printed many times, avoid using this; better to do the json_categorize_type
590  * lookups only once.
591  */
592 static void
593 add_json(Datum val, bool is_null, StringInfo result,
594  Oid val_type, bool key_scalar)
595 {
596  JsonTypeCategory tcategory;
597  Oid outfuncoid;
598 
599  if (val_type == InvalidOid)
600  ereport(ERROR,
601  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
602  errmsg("could not determine input data type")));
603 
604  if (is_null)
605  {
606  tcategory = JSONTYPE_NULL;
607  outfuncoid = InvalidOid;
608  }
609  else
610  json_categorize_type(val_type, false,
611  &tcategory, &outfuncoid);
612 
613  datum_to_json_internal(val, is_null, result, tcategory, outfuncoid,
614  key_scalar);
615 }
616 
617 /*
618  * SQL function array_to_json(row)
619  */
620 Datum
622 {
623  Datum array = PG_GETARG_DATUM(0);
624  StringInfo result;
625 
626  result = makeStringInfo();
627 
628  array_to_json_internal(array, result, false);
629 
631 }
632 
633 /*
634  * SQL function array_to_json(row, prettybool)
635  */
636 Datum
638 {
639  Datum array = PG_GETARG_DATUM(0);
640  bool use_line_feeds = PG_GETARG_BOOL(1);
641  StringInfo result;
642 
643  result = makeStringInfo();
644 
645  array_to_json_internal(array, result, use_line_feeds);
646 
648 }
649 
650 /*
651  * SQL function row_to_json(row)
652  */
653 Datum
655 {
656  Datum array = PG_GETARG_DATUM(0);
657  StringInfo result;
658 
659  result = makeStringInfo();
660 
661  composite_to_json(array, result, false);
662 
664 }
665 
666 /*
667  * SQL function row_to_json(row, prettybool)
668  */
669 Datum
671 {
672  Datum array = PG_GETARG_DATUM(0);
673  bool use_line_feeds = PG_GETARG_BOOL(1);
674  StringInfo result;
675 
676  result = makeStringInfo();
677 
678  composite_to_json(array, result, use_line_feeds);
679 
681 }
682 
683 /*
684  * Is the given type immutable when coming out of a JSON context?
685  *
686  * At present, datetimes are all considered mutable, because they
687  * depend on timezone. XXX we should also drill down into objects
688  * and arrays, but do not.
689  */
690 bool
692 {
693  JsonTypeCategory tcategory;
694  Oid outfuncoid;
695 
696  json_categorize_type(typoid, false, &tcategory, &outfuncoid);
697 
698  switch (tcategory)
699  {
700  case JSONTYPE_BOOL:
701  case JSONTYPE_JSON:
702  case JSONTYPE_JSONB:
703  case JSONTYPE_NULL:
704  return true;
705 
706  case JSONTYPE_DATE:
707  case JSONTYPE_TIMESTAMP:
709  return false;
710 
711  case JSONTYPE_ARRAY:
712  return false; /* TODO recurse into elements */
713 
714  case JSONTYPE_COMPOSITE:
715  return false; /* TODO recurse into fields */
716 
717  case JSONTYPE_NUMERIC:
718  case JSONTYPE_CAST:
719  case JSONTYPE_OTHER:
720  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
721  }
722 
723  return false; /* not reached */
724 }
725 
726 /*
727  * SQL function to_json(anyvalue)
728  */
729 Datum
731 {
733  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
734  JsonTypeCategory tcategory;
735  Oid outfuncoid;
736 
737  if (val_type == InvalidOid)
738  ereport(ERROR,
739  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
740  errmsg("could not determine input data type")));
741 
742  json_categorize_type(val_type, false,
743  &tcategory, &outfuncoid);
744 
745  PG_RETURN_DATUM(datum_to_json(val, tcategory, outfuncoid));
746 }
747 
748 /*
749  * Turn a Datum into JSON text.
750  *
751  * tcategory and outfuncoid are from a previous call to json_categorize_type.
752  */
753 Datum
754 datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
755 {
756  StringInfo result = makeStringInfo();
757 
758  datum_to_json_internal(val, false, result, tcategory, outfuncoid,
759  false);
760 
761  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
762 }
763 
764 /*
765  * json_agg transition function
766  *
767  * aggregate input column as a json array value.
768  */
769 static Datum
770 json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
771 {
772  MemoryContext aggcontext,
773  oldcontext;
775  Datum val;
776 
777  if (!AggCheckCallContext(fcinfo, &aggcontext))
778  {
779  /* cannot be called directly because of internal-type argument */
780  elog(ERROR, "json_agg_transfn called in non-aggregate context");
781  }
782 
783  if (PG_ARGISNULL(0))
784  {
785  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
786 
787  if (arg_type == InvalidOid)
788  ereport(ERROR,
789  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
790  errmsg("could not determine input data type")));
791 
792  /*
793  * Make this state object in a context where it will persist for the
794  * duration of the aggregate call. MemoryContextSwitchTo is only
795  * needed the first time, as the StringInfo routines make sure they
796  * use the right context to enlarge the object if necessary.
797  */
798  oldcontext = MemoryContextSwitchTo(aggcontext);
799  state = (JsonAggState *) palloc(sizeof(JsonAggState));
800  state->str = makeStringInfo();
801  MemoryContextSwitchTo(oldcontext);
802 
803  appendStringInfoChar(state->str, '[');
804  json_categorize_type(arg_type, false, &state->val_category,
805  &state->val_output_func);
806  }
807  else
808  {
810  }
811 
812  if (absent_on_null && PG_ARGISNULL(1))
814 
815  if (state->str->len > 1)
816  appendStringInfoString(state->str, ", ");
817 
818  /* fast path for NULLs */
819  if (PG_ARGISNULL(1))
820  {
822  InvalidOid, false);
824  }
825 
826  val = PG_GETARG_DATUM(1);
827 
828  /* add some whitespace if structured type and not first item */
829  if (!PG_ARGISNULL(0) && state->str->len > 1 &&
830  (state->val_category == JSONTYPE_ARRAY ||
831  state->val_category == JSONTYPE_COMPOSITE))
832  {
833  appendStringInfoString(state->str, "\n ");
834  }
835 
836  datum_to_json_internal(val, false, state->str, state->val_category,
837  state->val_output_func, false);
838 
839  /*
840  * The transition type for json_agg() is declared to be "internal", which
841  * is a pass-by-value type the same size as a pointer. So we can safely
842  * pass the JsonAggState pointer through nodeAgg.c's machinations.
843  */
845 }
846 
847 
848 /*
849  * json_agg aggregate function
850  */
851 Datum
853 {
854  return json_agg_transfn_worker(fcinfo, false);
855 }
856 
857 /*
858  * json_agg_strict aggregate function
859  */
860 Datum
862 {
863  return json_agg_transfn_worker(fcinfo, true);
864 }
865 
866 /*
867  * json_agg final function
868  */
869 Datum
871 {
873 
874  /* cannot be called directly because of internal-type argument */
875  Assert(AggCheckCallContext(fcinfo, NULL));
876 
877  state = PG_ARGISNULL(0) ?
878  NULL :
880 
881  /* NULL result for no rows in, as is standard with aggregates */
882  if (state == NULL)
883  PG_RETURN_NULL();
884 
885  /* Else return state with appropriate array terminator added */
887 }
888 
889 /* Functions implementing hash table for key uniqueness check */
890 static uint32
891 json_unique_hash(const void *key, Size keysize)
892 {
893  const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
895 
896  hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
897 
898  return DatumGetUInt32(hash);
899 }
900 
901 static int
902 json_unique_hash_match(const void *key1, const void *key2, Size keysize)
903 {
904  const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
905  const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
906 
907  if (entry1->object_id != entry2->object_id)
908  return entry1->object_id > entry2->object_id ? 1 : -1;
909 
910  if (entry1->key_len != entry2->key_len)
911  return entry1->key_len > entry2->key_len ? 1 : -1;
912 
913  return strncmp(entry1->key, entry2->key, entry1->key_len);
914 }
915 
916 /*
917  * Uniqueness detection support.
918  *
919  * In order to detect uniqueness during building or parsing of a JSON
920  * object, we maintain a hash table of key names already seen.
921  */
922 static void
924 {
925  HASHCTL ctl;
926 
927  memset(&ctl, 0, sizeof(ctl));
928  ctl.keysize = sizeof(JsonUniqueHashEntry);
929  ctl.entrysize = sizeof(JsonUniqueHashEntry);
930  ctl.hcxt = CurrentMemoryContext;
931  ctl.hash = json_unique_hash;
932  ctl.match = json_unique_hash_match;
933 
934  *cxt = hash_create("json object hashtable",
935  32,
936  &ctl,
938 }
939 
940 static void
942 {
944  cxt->mcxt = CurrentMemoryContext;
945  cxt->skipped_keys.data = NULL;
946 }
947 
948 static bool
949 json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
950 {
951  JsonUniqueHashEntry entry;
952  bool found;
953 
954  entry.key = key;
955  entry.key_len = strlen(key);
956  entry.object_id = object_id;
957 
958  (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
959 
960  return !found;
961 }
962 
963 /*
964  * On-demand initialization of a throwaway StringInfo. This is used to
965  * read a key name that we don't need to store in the output object, for
966  * duplicate key detection when the value is NULL.
967  */
968 static StringInfo
970 {
971  StringInfo out = &cxt->skipped_keys;
972 
973  if (!out->data)
974  {
976 
977  initStringInfo(out);
978  MemoryContextSwitchTo(oldcxt);
979  }
980  else
981  /* Just reset the string to empty */
982  out->len = 0;
983 
984  return out;
985 }
986 
987 /*
988  * json_object_agg transition function.
989  *
990  * aggregate two input columns as a single json object value.
991  */
992 static Datum
994  bool absent_on_null, bool unique_keys)
995 {
996  MemoryContext aggcontext,
997  oldcontext;
999  StringInfo out;
1000  Datum arg;
1001  bool skip;
1002  int key_offset;
1003 
1004  if (!AggCheckCallContext(fcinfo, &aggcontext))
1005  {
1006  /* cannot be called directly because of internal-type argument */
1007  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
1008  }
1009 
1010  if (PG_ARGISNULL(0))
1011  {
1012  Oid arg_type;
1013 
1014  /*
1015  * Make the StringInfo in a context where it will persist for the
1016  * duration of the aggregate call. Switching context is only needed
1017  * for this initial step, as the StringInfo and dynahash routines make
1018  * sure they use the right context to enlarge the object if necessary.
1019  */
1020  oldcontext = MemoryContextSwitchTo(aggcontext);
1021  state = (JsonAggState *) palloc(sizeof(JsonAggState));
1022  state->str = makeStringInfo();
1023  if (unique_keys)
1024  json_unique_builder_init(&state->unique_check);
1025  else
1026  memset(&state->unique_check, 0, sizeof(state->unique_check));
1027  MemoryContextSwitchTo(oldcontext);
1028 
1029  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1030 
1031  if (arg_type == InvalidOid)
1032  ereport(ERROR,
1033  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1034  errmsg("could not determine data type for argument %d", 1)));
1035 
1036  json_categorize_type(arg_type, false, &state->key_category,
1037  &state->key_output_func);
1038 
1039  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1040 
1041  if (arg_type == InvalidOid)
1042  ereport(ERROR,
1043  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1044  errmsg("could not determine data type for argument %d", 2)));
1045 
1046  json_categorize_type(arg_type, false, &state->val_category,
1047  &state->val_output_func);
1048 
1049  appendStringInfoString(state->str, "{ ");
1050  }
1051  else
1052  {
1054  }
1055 
1056  /*
1057  * Note: since json_object_agg() is declared as taking type "any", the
1058  * parser will not do any type conversion on unknown-type literals (that
1059  * is, undecorated strings or NULLs). Such values will arrive here as
1060  * type UNKNOWN, which fortunately does not matter to us, since
1061  * unknownout() works fine.
1062  */
1063 
1064  if (PG_ARGISNULL(1))
1065  ereport(ERROR,
1066  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1067  errmsg("null value not allowed for object key")));
1068 
1069  /* Skip null values if absent_on_null */
1070  skip = absent_on_null && PG_ARGISNULL(2);
1071 
1072  if (skip)
1073  {
1074  /*
1075  * We got a NULL value and we're not storing those; if we're not
1076  * testing key uniqueness, we're done. If we are, use the throwaway
1077  * buffer to store the key name so that we can check it.
1078  */
1079  if (!unique_keys)
1081 
1082  out = json_unique_builder_get_throwawaybuf(&state->unique_check);
1083  }
1084  else
1085  {
1086  out = state->str;
1087 
1088  /*
1089  * Append comma delimiter only if we have already output some fields
1090  * after the initial string "{ ".
1091  */
1092  if (out->len > 2)
1093  appendStringInfoString(out, ", ");
1094  }
1095 
1096  arg = PG_GETARG_DATUM(1);
1097 
1098  key_offset = out->len;
1099 
1100  datum_to_json_internal(arg, false, out, state->key_category,
1101  state->key_output_func, true);
1102 
1103  if (unique_keys)
1104  {
1105  const char *key = &out->data[key_offset];
1106 
1107  if (!json_unique_check_key(&state->unique_check.check, key, 0))
1108  ereport(ERROR,
1109  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1110  errmsg("duplicate JSON object key value: %s", key));
1111 
1112  if (skip)
1114  }
1115 
1116  appendStringInfoString(state->str, " : ");
1117 
1118  if (PG_ARGISNULL(2))
1119  arg = (Datum) 0;
1120  else
1121  arg = PG_GETARG_DATUM(2);
1122 
1124  state->val_category,
1125  state->val_output_func, false);
1126 
1128 }
1129 
1130 /*
1131  * json_object_agg aggregate function
1132  */
1133 Datum
1135 {
1136  return json_object_agg_transfn_worker(fcinfo, false, false);
1137 }
1138 
1139 /*
1140  * json_object_agg_strict aggregate function
1141  */
1142 Datum
1144 {
1145  return json_object_agg_transfn_worker(fcinfo, true, false);
1146 }
1147 
1148 /*
1149  * json_object_agg_unique aggregate function
1150  */
1151 Datum
1153 {
1154  return json_object_agg_transfn_worker(fcinfo, false, true);
1155 }
1156 
1157 /*
1158  * json_object_agg_unique_strict aggregate function
1159  */
1160 Datum
1162 {
1163  return json_object_agg_transfn_worker(fcinfo, true, true);
1164 }
1165 
1166 /*
1167  * json_object_agg final function.
1168  */
1169 Datum
1171 {
1173 
1174  /* cannot be called directly because of internal-type argument */
1175  Assert(AggCheckCallContext(fcinfo, NULL));
1176 
1177  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
1178 
1179  /* NULL result for no rows in, as is standard with aggregates */
1180  if (state == NULL)
1181  PG_RETURN_NULL();
1182 
1183  /* Else return state with appropriate object terminator added */
1185 }
1186 
1187 /*
1188  * Helper function for aggregates: return given StringInfo's contents plus
1189  * specified trailing string, as a text datum. We need this because aggregate
1190  * final functions are not allowed to modify the aggregate state.
1191  */
1192 static text *
1193 catenate_stringinfo_string(StringInfo buffer, const char *addon)
1194 {
1195  /* custom version of cstring_to_text_with_len */
1196  int buflen = buffer->len;
1197  int addlen = strlen(addon);
1198  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
1199 
1200  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
1201  memcpy(VARDATA(result), buffer->data, buflen);
1202  memcpy(VARDATA(result) + buflen, addon, addlen);
1203 
1204  return result;
1205 }
1206 
1207 Datum
1208 json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types,
1209  bool absent_on_null, bool unique_keys)
1210 {
1211  int i;
1212  const char *sep = "";
1213  StringInfo result;
1214  JsonUniqueBuilderState unique_check;
1215 
1216  if (nargs % 2 != 0)
1217  ereport(ERROR,
1218  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1219  errmsg("argument list must have even number of elements"),
1220  /* translator: %s is a SQL function name */
1221  errhint("The arguments of %s must consist of alternating keys and values.",
1222  "json_build_object()")));
1223 
1224  result = makeStringInfo();
1225 
1226  appendStringInfoChar(result, '{');
1227 
1228  if (unique_keys)
1229  json_unique_builder_init(&unique_check);
1230 
1231  for (i = 0; i < nargs; i += 2)
1232  {
1233  StringInfo out;
1234  bool skip;
1235  int key_offset;
1236 
1237  /* Skip null values if absent_on_null */
1238  skip = absent_on_null && nulls[i + 1];
1239 
1240  if (skip)
1241  {
1242  /* If key uniqueness check is needed we must save skipped keys */
1243  if (!unique_keys)
1244  continue;
1245 
1246  out = json_unique_builder_get_throwawaybuf(&unique_check);
1247  }
1248  else
1249  {
1250  appendStringInfoString(result, sep);
1251  sep = ", ";
1252  out = result;
1253  }
1254 
1255  /* process key */
1256  if (nulls[i])
1257  ereport(ERROR,
1258  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1259  errmsg("null value not allowed for object key")));
1260 
1261  /* save key offset before appending it */
1262  key_offset = out->len;
1263 
1264  add_json(args[i], false, out, types[i], true);
1265 
1266  if (unique_keys)
1267  {
1268  /* check key uniqueness after key appending */
1269  const char *key = &out->data[key_offset];
1270 
1271  if (!json_unique_check_key(&unique_check.check, key, 0))
1272  ereport(ERROR,
1273  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1274  errmsg("duplicate JSON object key value: %s", key));
1275 
1276  if (skip)
1277  continue;
1278  }
1279 
1280  appendStringInfoString(result, " : ");
1281 
1282  /* process value */
1283  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1284  }
1285 
1286  appendStringInfoChar(result, '}');
1287 
1288  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1289 }
1290 
1291 /*
1292  * SQL function json_build_object(variadic "any")
1293  */
1294 Datum
1296 {
1297  Datum *args;
1298  bool *nulls;
1299  Oid *types;
1300 
1301  /* build argument values to build the object */
1302  int nargs = extract_variadic_args(fcinfo, 0, true,
1303  &args, &types, &nulls);
1304 
1305  if (nargs < 0)
1306  PG_RETURN_NULL();
1307 
1308  PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
1309 }
1310 
1311 /*
1312  * degenerate case of json_build_object where it gets 0 arguments.
1313  */
1314 Datum
1316 {
1318 }
1319 
1320 Datum
1321 json_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types,
1322  bool absent_on_null)
1323 {
1324  int i;
1325  const char *sep = "";
1326  StringInfo result;
1327 
1328  result = makeStringInfo();
1329 
1330  appendStringInfoChar(result, '[');
1331 
1332  for (i = 0; i < nargs; i++)
1333  {
1334  if (absent_on_null && nulls[i])
1335  continue;
1336 
1337  appendStringInfoString(result, sep);
1338  sep = ", ";
1339  add_json(args[i], nulls[i], result, types[i], false);
1340  }
1341 
1342  appendStringInfoChar(result, ']');
1343 
1344  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1345 }
1346 
1347 /*
1348  * SQL function json_build_array(variadic "any")
1349  */
1350 Datum
1352 {
1353  Datum *args;
1354  bool *nulls;
1355  Oid *types;
1356 
1357  /* build argument values to build the object */
1358  int nargs = extract_variadic_args(fcinfo, 0, true,
1359  &args, &types, &nulls);
1360 
1361  if (nargs < 0)
1362  PG_RETURN_NULL();
1363 
1364  PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
1365 }
1366 
1367 /*
1368  * degenerate case of json_build_array where it gets 0 arguments.
1369  */
1370 Datum
1372 {
1374 }
1375 
1376 /*
1377  * SQL function json_object(text[])
1378  *
1379  * take a one or two dimensional array of text as key/value pairs
1380  * for a json object.
1381  */
1382 Datum
1384 {
1385  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1386  int ndims = ARR_NDIM(in_array);
1387  StringInfoData result;
1388  Datum *in_datums;
1389  bool *in_nulls;
1390  int in_count,
1391  count,
1392  i;
1393  text *rval;
1394  char *v;
1395 
1396  switch (ndims)
1397  {
1398  case 0:
1400  break;
1401 
1402  case 1:
1403  if ((ARR_DIMS(in_array)[0]) % 2)
1404  ereport(ERROR,
1405  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1406  errmsg("array must have even number of elements")));
1407  break;
1408 
1409  case 2:
1410  if ((ARR_DIMS(in_array)[1]) != 2)
1411  ereport(ERROR,
1412  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1413  errmsg("array must have two columns")));
1414  break;
1415 
1416  default:
1417  ereport(ERROR,
1418  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1419  errmsg("wrong number of array subscripts")));
1420  }
1421 
1422  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1423 
1424  count = in_count / 2;
1425 
1426  initStringInfo(&result);
1427 
1428  appendStringInfoChar(&result, '{');
1429 
1430  for (i = 0; i < count; ++i)
1431  {
1432  if (in_nulls[i * 2])
1433  ereport(ERROR,
1434  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1435  errmsg("null value not allowed for object key")));
1436 
1437  v = TextDatumGetCString(in_datums[i * 2]);
1438  if (i > 0)
1439  appendStringInfoString(&result, ", ");
1440  escape_json(&result, v);
1441  appendStringInfoString(&result, " : ");
1442  pfree(v);
1443  if (in_nulls[i * 2 + 1])
1444  appendStringInfoString(&result, "null");
1445  else
1446  {
1447  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1448  escape_json(&result, v);
1449  pfree(v);
1450  }
1451  }
1452 
1453  appendStringInfoChar(&result, '}');
1454 
1455  pfree(in_datums);
1456  pfree(in_nulls);
1457 
1458  rval = cstring_to_text_with_len(result.data, result.len);
1459  pfree(result.data);
1460 
1461  PG_RETURN_TEXT_P(rval);
1462 }
1463 
1464 /*
1465  * SQL function json_object(text[], text[])
1466  *
1467  * take separate key and value arrays of text to construct a json object
1468  * pairwise.
1469  */
1470 Datum
1472 {
1473  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1474  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1475  int nkdims = ARR_NDIM(key_array);
1476  int nvdims = ARR_NDIM(val_array);
1477  StringInfoData result;
1478  Datum *key_datums,
1479  *val_datums;
1480  bool *key_nulls,
1481  *val_nulls;
1482  int key_count,
1483  val_count,
1484  i;
1485  text *rval;
1486  char *v;
1487 
1488  if (nkdims > 1 || nkdims != nvdims)
1489  ereport(ERROR,
1490  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1491  errmsg("wrong number of array subscripts")));
1492 
1493  if (nkdims == 0)
1495 
1496  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1497  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1498 
1499  if (key_count != val_count)
1500  ereport(ERROR,
1501  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1502  errmsg("mismatched array dimensions")));
1503 
1504  initStringInfo(&result);
1505 
1506  appendStringInfoChar(&result, '{');
1507 
1508  for (i = 0; i < key_count; ++i)
1509  {
1510  if (key_nulls[i])
1511  ereport(ERROR,
1512  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1513  errmsg("null value not allowed for object key")));
1514 
1515  v = TextDatumGetCString(key_datums[i]);
1516  if (i > 0)
1517  appendStringInfoString(&result, ", ");
1518  escape_json(&result, v);
1519  appendStringInfoString(&result, " : ");
1520  pfree(v);
1521  if (val_nulls[i])
1522  appendStringInfoString(&result, "null");
1523  else
1524  {
1525  v = TextDatumGetCString(val_datums[i]);
1526  escape_json(&result, v);
1527  pfree(v);
1528  }
1529  }
1530 
1531  appendStringInfoChar(&result, '}');
1532 
1533  pfree(key_datums);
1534  pfree(key_nulls);
1535  pfree(val_datums);
1536  pfree(val_nulls);
1537 
1538  rval = cstring_to_text_with_len(result.data, result.len);
1539  pfree(result.data);
1540 
1541  PG_RETURN_TEXT_P(rval);
1542 }
1543 
1544 
1545 /*
1546  * Produce a JSON string literal, properly escaping characters in the text.
1547  */
1548 void
1550 {
1551  const char *p;
1552 
1554  for (p = str; *p; p++)
1555  {
1556  switch (*p)
1557  {
1558  case '\b':
1559  appendStringInfoString(buf, "\\b");
1560  break;
1561  case '\f':
1562  appendStringInfoString(buf, "\\f");
1563  break;
1564  case '\n':
1565  appendStringInfoString(buf, "\\n");
1566  break;
1567  case '\r':
1568  appendStringInfoString(buf, "\\r");
1569  break;
1570  case '\t':
1571  appendStringInfoString(buf, "\\t");
1572  break;
1573  case '"':
1574  appendStringInfoString(buf, "\\\"");
1575  break;
1576  case '\\':
1577  appendStringInfoString(buf, "\\\\");
1578  break;
1579  default:
1580  if ((unsigned char) *p < ' ')
1581  appendStringInfo(buf, "\\u%04x", (int) *p);
1582  else
1584  break;
1585  }
1586  }
1588 }
1589 
1590 /* Semantic actions for key uniqueness check */
1591 static JsonParseErrorType
1593 {
1594  JsonUniqueParsingState *state = _state;
1595  JsonUniqueStackEntry *entry;
1596 
1597  if (!state->unique)
1598  return JSON_SUCCESS;
1599 
1600  /* push object entry to stack */
1601  entry = palloc(sizeof(*entry));
1602  entry->object_id = state->id_counter++;
1603  entry->parent = state->stack;
1604  state->stack = entry;
1605 
1606  return JSON_SUCCESS;
1607 }
1608 
1609 static JsonParseErrorType
1611 {
1612  JsonUniqueParsingState *state = _state;
1613  JsonUniqueStackEntry *entry;
1614 
1615  if (!state->unique)
1616  return JSON_SUCCESS;
1617 
1618  entry = state->stack;
1619  state->stack = entry->parent; /* pop object from stack */
1620  pfree(entry);
1621  return JSON_SUCCESS;
1622 }
1623 
1624 static JsonParseErrorType
1625 json_unique_object_field_start(void *_state, char *field, bool isnull)
1626 {
1627  JsonUniqueParsingState *state = _state;
1628  JsonUniqueStackEntry *entry;
1629 
1630  if (!state->unique)
1631  return JSON_SUCCESS;
1632 
1633  /* find key collision in the current object */
1634  if (json_unique_check_key(&state->check, field, state->stack->object_id))
1635  return JSON_SUCCESS;
1636 
1637  state->unique = false;
1638 
1639  /* pop all objects entries */
1640  while ((entry = state->stack))
1641  {
1642  state->stack = entry->parent;
1643  pfree(entry);
1644  }
1645  return JSON_SUCCESS;
1646 }
1647 
1648 /* Validate JSON text and additionally check key uniqueness */
1649 bool
1650 json_validate(text *json, bool check_unique_keys, bool throw_error)
1651 {
1652  JsonLexContext lex;
1653  JsonSemAction uniqueSemAction = {0};
1655  JsonParseErrorType result;
1656 
1657  makeJsonLexContext(&lex, json, check_unique_keys);
1658 
1659  if (check_unique_keys)
1660  {
1661  state.lex = &lex;
1662  state.stack = NULL;
1663  state.id_counter = 0;
1664  state.unique = true;
1665  json_unique_check_init(&state.check);
1666 
1667  uniqueSemAction.semstate = &state;
1668  uniqueSemAction.object_start = json_unique_object_start;
1670  uniqueSemAction.object_end = json_unique_object_end;
1671  }
1672 
1673  result = pg_parse_json(&lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
1674 
1675  if (result != JSON_SUCCESS)
1676  {
1677  if (throw_error)
1678  json_errsave_error(result, &lex, NULL);
1679 
1680  return false; /* invalid json */
1681  }
1682 
1683  if (check_unique_keys && !state.unique)
1684  {
1685  if (throw_error)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1688  errmsg("duplicate JSON object key value")));
1689 
1690  return false; /* not unique keys */
1691  }
1692 
1693  if (check_unique_keys)
1694  freeJsonLexContext(&lex);
1695 
1696  return true; /* ok */
1697 }
1698 
1699 /*
1700  * SQL function json_typeof(json) -> text
1701  *
1702  * Returns the type of the outermost JSON value as TEXT. Possible types are
1703  * "object", "array", "string", "number", "boolean", and "null".
1704  *
1705  * Performs a single call to json_lex() to get the first token of the supplied
1706  * value. This initial token uniquely determines the value's type. As our
1707  * input must already have been validated by json_in() or json_recv(), the
1708  * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END,
1709  * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END.
1710  */
1711 Datum
1713 {
1714  text *json = PG_GETARG_TEXT_PP(0);
1715  JsonLexContext lex;
1716  char *type;
1717  JsonParseErrorType result;
1718 
1719  /* Lex exactly one token from the input and check its type. */
1720  makeJsonLexContext(&lex, json, false);
1721  result = json_lex(&lex);
1722  if (result != JSON_SUCCESS)
1723  json_errsave_error(result, &lex, NULL);
1724 
1725  switch (lex.token_type)
1726  {
1728  type = "object";
1729  break;
1731  type = "array";
1732  break;
1733  case JSON_TOKEN_STRING:
1734  type = "string";
1735  break;
1736  case JSON_TOKEN_NUMBER:
1737  type = "number";
1738  break;
1739  case JSON_TOKEN_TRUE:
1740  case JSON_TOKEN_FALSE:
1741  type = "boolean";
1742  break;
1743  case JSON_TOKEN_NULL:
1744  type = "null";
1745  break;
1746  default:
1747  elog(ERROR, "unexpected json token: %d", lex.token_type);
1748  }
1749 
1751 }
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3612
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3678
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4301
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:311
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4331
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4216
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1596
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1901
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:746
unsigned int uint32
Definition: c.h:506
signed short int16
Definition: c.h:493
signed int int32
Definition: c.h:494
#define VARHDRSZ
Definition: c.h:692
#define Assert(condition)
Definition: c.h:858
size_t Size
Definition: c.h:605
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define USECS_PER_SEC
Definition: timestamp.h:134
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2403
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1488
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:294
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
static TimeADT DatumGetTimeADT(Datum X)
Definition: date.h:60
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition: date.h:66
int64 TimeADT
Definition: date.h:25
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
struct typedefs * types
Definition: ecpg.c:29
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:680
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2005
uint32 hash_bytes_uint32(uint32 k)
Definition: hashfn.c:610
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition: hashfn.c:146
const char * str
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_COMPARE
Definition: hsearch.h:99
#define HASH_FUNCTION
Definition: hsearch.h:98
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
#define MAXDATELEN
Definition: datetime.h:200
#define nitems(x)
Definition: indent.h:31
long val
Definition: informix.c:670
static struct @155 value
int i
Definition: isn.c:73
Datum row_to_json(PG_FUNCTION_ARGS)
Definition: json.c:654
struct JsonUniqueStackEntry JsonUniqueStackEntry
static JsonParseErrorType json_unique_object_start(void *_state)
Definition: json.c:1592
static uint32 json_unique_hash(const void *key, Size keysize)
Definition: json.c:891
Datum json_build_object_noargs(PG_FUNCTION_ARGS)
Definition: json.c:1315
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
Definition: json.c:902
static void json_unique_check_init(JsonUniqueCheckState *cxt)
Definition: json.c:923
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
Definition: json.c:1193
struct HTAB * JsonUniqueCheckState
Definition: json.c:39
Datum json_agg_strict_transfn(PG_FUNCTION_ARGS)
Definition: json.c:861
struct JsonUniqueBuilderState JsonUniqueBuilderState
Datum json_in(PG_FUNCTION_ARGS)
Definition: json.c:105
static StringInfo json_unique_builder_get_throwawaybuf(JsonUniqueBuilderState *cxt)
Definition: json.c:969
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
Definition: json.c:949
struct JsonUniqueParsingState JsonUniqueParsingState
Datum json_out(PG_FUNCTION_ARGS)
Definition: json.c:124
Datum json_agg_transfn(PG_FUNCTION_ARGS)
Definition: json.c:852
Datum to_json(PG_FUNCTION_ARGS)
Definition: json.c:730
Datum json_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: json.c:1321
Datum json_object_agg_finalfn(PG_FUNCTION_ARGS)
Definition: json.c:1170
Datum row_to_json_pretty(PG_FUNCTION_ARGS)
Definition: json.c:670
struct JsonUniqueHashEntry JsonUniqueHashEntry
Datum json_send(PG_FUNCTION_ARGS)
Definition: json.c:136
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: json.c:770
static void datum_to_json_internal(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:177
Datum array_to_json_pretty(PG_FUNCTION_ARGS)
Definition: json.c:637
Datum json_object_agg_unique_transfn(PG_FUNCTION_ARGS)
Definition: json.c:1152
Datum json_object_two_arg(PG_FUNCTION_ARGS)
Definition: json.c:1471
Datum json_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
Definition: json.c:1161
Datum json_build_array_noargs(PG_FUNCTION_ARGS)
Definition: json.c:1371
Datum json_object_agg_transfn(PG_FUNCTION_ARGS)
Definition: json.c:1134
Datum array_to_json(PG_FUNCTION_ARGS)
Definition: json.c:621
Datum json_object_agg_strict_transfn(PG_FUNCTION_ARGS)
Definition: json.c:1143
Datum json_build_array(PG_FUNCTION_ARGS)
Definition: json.c:1351
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Definition: json.c:941
Datum json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1208
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:593
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:301
Datum json_agg_finalfn(PG_FUNCTION_ARGS)
Definition: json.c:870
static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals, bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid, bool use_line_feeds)
Definition: json.c:422
Datum json_recv(PG_FUNCTION_ARGS)
Definition: json.c:150
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:754
bool json_validate(text *json, bool check_unique_keys, bool throw_error)
Definition: json.c:1650
Datum json_typeof(PG_FUNCTION_ARGS)
Definition: json.c:1712
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
struct JsonAggState JsonAggState
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:512
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: json.c:993
Datum json_object(PG_FUNCTION_ARGS)
Definition: json.c:1383
Datum json_build_object(PG_FUNCTION_ARGS)
Definition: json.c:1295
bool to_json_is_immutable(Oid typoid)
Definition: json.c:691
static JsonParseErrorType json_unique_object_field_start(void *_state, char *field, bool isnull)
Definition: json.c:1625
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:465
static JsonParseErrorType json_unique_object_end(void *_state)
Definition: json.c:1610
JsonSemAction nullSemAction
Definition: jsonapi.c:224
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:521
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:1308
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:326
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:482
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SUCCESS
Definition: jsonapi.h:38
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:537
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:516
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5953
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
Definition: jsonfuncs.c:638
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_NULL
Definition: jsonfuncs.h:70
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
static struct pg_tm tm
Definition: localtime.c:104
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
char func_volatile(Oid funcid)
Definition: lsyscache.c:1780
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
void pfree(void *pointer)
Definition: mcxt.c:1520
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * palloc(Size size)
Definition: mcxt.c:1316
#define USE_XSD_DATES
Definition: miscadmin.h:238
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4511
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
void * arg
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:108
static char * buf
Definition: pg_test_fsync.c:73
char typalign
Definition: pg_type.h:176
long date
Definition: pgtypes_date.h:9
int64 timestamp
void check_stack_depth(void)
Definition: postgres.c:3531
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
MemoryContextSwitchTo(old_ctx)
tree ctl
Definition: radixtree.h:1851
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
FmgrInfo * flinfo
Definition: fmgr.h:87
Definition: dynahash.c:220
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
JsonUniqueBuilderState unique_check
Definition: json.c:83
JsonTypeCategory key_category
Definition: json.c:79
Oid val_output_func
Definition: json.c:82
StringInfo str
Definition: json.c:78
Oid key_output_func
Definition: json.c:80
JsonTypeCategory val_category
Definition: json.c:81
JsonTokenType token_type
Definition: jsonapi.h:98
json_struct_action object_start
Definition: jsonapi.h:135
json_ofield_action object_field_start
Definition: jsonapi.h:139
void * semstate
Definition: jsonapi.h:134
json_struct_action object_end
Definition: jsonapi.h:136
JsonUniqueCheckState check
Definition: json.c:69
StringInfoData skipped_keys
Definition: json.c:70
MemoryContext mcxt
Definition: json.c:71
const char * key
Definition: json.c:44
JsonUniqueCheckState check
Definition: json.c:60
JsonUniqueStackEntry * stack
Definition: json.c:61
JsonLexContext * lex
Definition: json.c:59
struct JsonUniqueStackEntry * parent
Definition: json.c:52
Definition: date.h:28
Definition: pgtime.h:35
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_isdst
Definition: pgtime.h:44
int tm_year
Definition: pgtime.h:41
Definition: regguts.h:323
Definition: c.h:687
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
static TimestampTz DatumGetTimestampTz(Datum X)
Definition: timestamp.h:34
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type