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