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