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-2020, 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_type.h"
17 #include "funcapi.h"
18 #include "libpq/pqformat.h"
19 #include "miscadmin.h"
20 #include "parser/parse_coerce.h"
21 #include "utils/array.h"
22 #include "utils/builtins.h"
23 #include "utils/date.h"
24 #include "utils/datetime.h"
25 #include "utils/json.h"
26 #include "utils/jsonfuncs.h"
27 #include "utils/lsyscache.h"
28 #include "utils/typcache.h"
29 
30 typedef enum /* type categories for datum_to_json */
31 {
32  JSONTYPE_NULL, /* null, so we didn't bother to identify */
33  JSONTYPE_BOOL, /* boolean (built-in types only) */
34  JSONTYPE_NUMERIC, /* numeric (ditto) */
35  JSONTYPE_DATE, /* we use special formatting for datetimes */
38  JSONTYPE_JSON, /* JSON itself (and JSONB) */
39  JSONTYPE_ARRAY, /* array */
40  JSONTYPE_COMPOSITE, /* composite */
41  JSONTYPE_CAST, /* something with an explicit cast to JSON */
42  JSONTYPE_OTHER /* all else */
44 
45 typedef struct JsonAggState
46 {
52 } JsonAggState;
53 
54 static void composite_to_json(Datum composite, StringInfo result,
55  bool use_line_feeds);
56 static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
57  Datum *vals, bool *nulls, int *valcount,
58  JsonTypeCategory tcategory, Oid outfuncoid,
59  bool use_line_feeds);
60 static void array_to_json_internal(Datum array, StringInfo result,
61  bool use_line_feeds);
62 static void json_categorize_type(Oid typoid,
63  JsonTypeCategory *tcategory,
64  Oid *outfuncoid);
65 static void datum_to_json(Datum val, bool is_null, StringInfo result,
66  JsonTypeCategory tcategory, Oid outfuncoid,
67  bool key_scalar);
68 static void add_json(Datum val, bool is_null, StringInfo result,
69  Oid val_type, bool key_scalar);
70 static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
71 
72 /*
73  * Input.
74  */
75 Datum
77 {
78  char *json = PG_GETARG_CSTRING(0);
79  text *result = cstring_to_text(json);
80  JsonLexContext *lex;
81 
82  /* validate it */
83  lex = makeJsonLexContext(result, false);
85 
86  /* Internal representation is the same as text, for now */
87  PG_RETURN_TEXT_P(result);
88 }
89 
90 /*
91  * Output.
92  */
93 Datum
95 {
96  /* we needn't detoast because text_to_cstring will handle that */
97  Datum txt = PG_GETARG_DATUM(0);
98 
100 }
101 
102 /*
103  * Binary send.
104  */
105 Datum
107 {
108  text *t = PG_GETARG_TEXT_PP(0);
110 
111  pq_begintypsend(&buf);
114 }
115 
116 /*
117  * Binary receive.
118  */
119 Datum
121 {
123  char *str;
124  int nbytes;
125  JsonLexContext *lex;
126 
127  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
128 
129  /* Validate it. */
130  lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false);
132 
134 }
135 
136 /*
137  * Determine how we want to print values of a given type in datum_to_json.
138  *
139  * Given the datatype OID, return its JsonTypeCategory, as well as the type's
140  * output function OID. If the returned category is JSONTYPE_CAST, we
141  * return the OID of the type->JSON cast function instead.
142  */
143 static void
145  JsonTypeCategory *tcategory,
146  Oid *outfuncoid)
147 {
148  bool typisvarlena;
149 
150  /* Look through any domain */
151  typoid = getBaseType(typoid);
152 
153  *outfuncoid = InvalidOid;
154 
155  /*
156  * We need to get the output function for everything except date and
157  * timestamp types, array and composite types, booleans, and non-builtin
158  * types where there's a cast to json.
159  */
160 
161  switch (typoid)
162  {
163  case BOOLOID:
164  *tcategory = JSONTYPE_BOOL;
165  break;
166 
167  case INT2OID:
168  case INT4OID:
169  case INT8OID:
170  case FLOAT4OID:
171  case FLOAT8OID:
172  case NUMERICOID:
173  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
174  *tcategory = JSONTYPE_NUMERIC;
175  break;
176 
177  case DATEOID:
178  *tcategory = JSONTYPE_DATE;
179  break;
180 
181  case TIMESTAMPOID:
182  *tcategory = JSONTYPE_TIMESTAMP;
183  break;
184 
185  case TIMESTAMPTZOID:
186  *tcategory = JSONTYPE_TIMESTAMPTZ;
187  break;
188 
189  case JSONOID:
190  case JSONBOID:
191  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
192  *tcategory = JSONTYPE_JSON;
193  break;
194 
195  default:
196  /* Check for arrays and composites */
197  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
198  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
199  *tcategory = JSONTYPE_ARRAY;
200  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
201  *tcategory = JSONTYPE_COMPOSITE;
202  else
203  {
204  /* It's probably the general case ... */
205  *tcategory = JSONTYPE_OTHER;
206  /* but let's look for a cast to json, if it's not built-in */
207  if (typoid >= FirstNormalObjectId)
208  {
209  Oid castfunc;
210  CoercionPathType ctype;
211 
212  ctype = find_coercion_pathway(JSONOID, typoid,
214  &castfunc);
215  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
216  {
217  *tcategory = JSONTYPE_CAST;
218  *outfuncoid = castfunc;
219  }
220  else
221  {
222  /* non builtin type with no cast */
223  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
224  }
225  }
226  else
227  {
228  /* any other builtin type */
229  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
230  }
231  }
232  break;
233  }
234 }
235 
236 /*
237  * Turn a Datum into JSON text, appending the string to "result".
238  *
239  * tcategory and outfuncoid are from a previous call to json_categorize_type,
240  * except that if is_null is true then they can be invalid.
241  *
242  * If key_scalar is true, the value is being printed as a key, so insist
243  * it's of an acceptable type, and force it to be quoted.
244  */
245 static void
246 datum_to_json(Datum val, bool is_null, StringInfo result,
247  JsonTypeCategory tcategory, Oid outfuncoid,
248  bool key_scalar)
249 {
250  char *outputstr;
251  text *jsontext;
252 
254 
255  /* callers are expected to ensure that null keys are not passed in */
256  Assert(!(key_scalar && is_null));
257 
258  if (is_null)
259  {
260  appendStringInfoString(result, "null");
261  return;
262  }
263 
264  if (key_scalar &&
265  (tcategory == JSONTYPE_ARRAY ||
266  tcategory == JSONTYPE_COMPOSITE ||
267  tcategory == JSONTYPE_JSON ||
268  tcategory == JSONTYPE_CAST))
269  ereport(ERROR,
270  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
271  errmsg("key value must be scalar, not array, composite, or json")));
272 
273  switch (tcategory)
274  {
275  case JSONTYPE_ARRAY:
276  array_to_json_internal(val, result, false);
277  break;
278  case JSONTYPE_COMPOSITE:
279  composite_to_json(val, result, false);
280  break;
281  case JSONTYPE_BOOL:
282  outputstr = DatumGetBool(val) ? "true" : "false";
283  if (key_scalar)
284  escape_json(result, outputstr);
285  else
286  appendStringInfoString(result, outputstr);
287  break;
288  case JSONTYPE_NUMERIC:
289  outputstr = OidOutputFunctionCall(outfuncoid, val);
290 
291  /*
292  * Don't call escape_json for a non-key if it's a valid JSON
293  * number.
294  */
295  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
296  appendStringInfoString(result, outputstr);
297  else
298  escape_json(result, outputstr);
299  pfree(outputstr);
300  break;
301  case JSONTYPE_DATE:
302  {
303  char buf[MAXDATELEN + 1];
304 
305  JsonEncodeDateTime(buf, val, DATEOID, NULL);
306  appendStringInfo(result, "\"%s\"", buf);
307  }
308  break;
309  case JSONTYPE_TIMESTAMP:
310  {
311  char buf[MAXDATELEN + 1];
312 
313  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
314  appendStringInfo(result, "\"%s\"", buf);
315  }
316  break;
318  {
319  char buf[MAXDATELEN + 1];
320 
321  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
322  appendStringInfo(result, "\"%s\"", buf);
323  }
324  break;
325  case JSONTYPE_JSON:
326  /* JSON and JSONB output will already be escaped */
327  outputstr = OidOutputFunctionCall(outfuncoid, val);
328  appendStringInfoString(result, outputstr);
329  pfree(outputstr);
330  break;
331  case JSONTYPE_CAST:
332  /* outfuncoid refers to a cast function, not an output function */
333  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
334  outputstr = text_to_cstring(jsontext);
335  appendStringInfoString(result, outputstr);
336  pfree(outputstr);
337  pfree(jsontext);
338  break;
339  default:
340  outputstr = OidOutputFunctionCall(outfuncoid, val);
341  escape_json(result, outputstr);
342  pfree(outputstr);
343  break;
344  }
345 }
346 
347 /*
348  * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
349  * optionally preallocated buffer 'buf'. Optional 'tzp' determines time-zone
350  * offset (in seconds) in which we want to show timestamptz.
351  */
352 char *
353 JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
354 {
355  if (!buf)
356  buf = palloc(MAXDATELEN + 1);
357 
358  switch (typid)
359  {
360  case DATEOID:
361  {
362  DateADT date;
363  struct pg_tm tm;
364 
365  date = DatumGetDateADT(value);
366 
367  /* Same as date_out(), but forcing DateStyle */
368  if (DATE_NOT_FINITE(date))
369  EncodeSpecialDate(date, buf);
370  else
371  {
373  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
374  EncodeDateOnly(&tm, USE_XSD_DATES, buf);
375  }
376  }
377  break;
378  case TIMEOID:
379  {
380  TimeADT time = DatumGetTimeADT(value);
381  struct pg_tm tt,
382  *tm = &tt;
383  fsec_t fsec;
384 
385  /* Same as time_out(), but forcing DateStyle */
386  time2tm(time, tm, &fsec);
387  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
388  }
389  break;
390  case TIMETZOID:
391  {
392  TimeTzADT *time = DatumGetTimeTzADTP(value);
393  struct pg_tm tt,
394  *tm = &tt;
395  fsec_t fsec;
396  int tz;
397 
398  /* Same as timetz_out(), but forcing DateStyle */
399  timetz2tm(time, tm, &fsec, &tz);
400  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
401  }
402  break;
403  case TIMESTAMPOID:
404  {
406  struct pg_tm tm;
407  fsec_t fsec;
408 
409  timestamp = DatumGetTimestamp(value);
410  /* Same as timestamp_out(), but forcing DateStyle */
411  if (TIMESTAMP_NOT_FINITE(timestamp))
412  EncodeSpecialTimestamp(timestamp, buf);
413  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
414  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
415  else
416  ereport(ERROR,
417  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
418  errmsg("timestamp out of range")));
419  }
420  break;
421  case TIMESTAMPTZOID:
422  {
424  struct pg_tm tm;
425  int tz;
426  fsec_t fsec;
427  const char *tzn = NULL;
428 
429  timestamp = DatumGetTimestampTz(value);
430 
431  /*
432  * If a time zone is specified, we apply the time-zone shift,
433  * convert timestamptz to pg_tm as if it were without a time
434  * zone, and then use the specified time zone for converting
435  * the timestamp into a string.
436  */
437  if (tzp)
438  {
439  tz = *tzp;
440  timestamp -= (TimestampTz) tz * USECS_PER_SEC;
441  }
442 
443  /* Same as timestamptz_out(), but forcing DateStyle */
444  if (TIMESTAMP_NOT_FINITE(timestamp))
445  EncodeSpecialTimestamp(timestamp, buf);
446  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
447  tzp ? NULL : &tzn, NULL) == 0)
448  {
449  if (tzp)
450  tm.tm_isdst = 1; /* set time-zone presence flag */
451 
452  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
453  }
454  else
455  ereport(ERROR,
456  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
457  errmsg("timestamp out of range")));
458  }
459  break;
460  default:
461  elog(ERROR, "unknown jsonb value datetime type oid %d", typid);
462  return NULL;
463  }
464 
465  return buf;
466 }
467 
468 /*
469  * Process a single dimension of an array.
470  * If it's the innermost dimension, output the values, otherwise call
471  * ourselves recursively to process the next dimension.
472  */
473 static void
474 array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals,
475  bool *nulls, int *valcount, JsonTypeCategory tcategory,
476  Oid outfuncoid, bool use_line_feeds)
477 {
478  int i;
479  const char *sep;
480 
481  Assert(dim < ndims);
482 
483  sep = use_line_feeds ? ",\n " : ",";
484 
485  appendStringInfoChar(result, '[');
486 
487  for (i = 1; i <= dims[dim]; i++)
488  {
489  if (i > 1)
490  appendStringInfoString(result, sep);
491 
492  if (dim + 1 == ndims)
493  {
494  datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
495  outfuncoid, false);
496  (*valcount)++;
497  }
498  else
499  {
500  /*
501  * Do we want line feeds on inner dimensions of arrays? For now
502  * we'll say no.
503  */
504  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
505  valcount, tcategory, outfuncoid, false);
506  }
507  }
508 
509  appendStringInfoChar(result, ']');
510 }
511 
512 /*
513  * Turn an array into JSON.
514  */
515 static void
516 array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
517 {
518  ArrayType *v = DatumGetArrayTypeP(array);
519  Oid element_type = ARR_ELEMTYPE(v);
520  int *dim;
521  int ndim;
522  int nitems;
523  int count = 0;
524  Datum *elements;
525  bool *nulls;
526  int16 typlen;
527  bool typbyval;
528  char typalign;
529  JsonTypeCategory tcategory;
530  Oid outfuncoid;
531 
532  ndim = ARR_NDIM(v);
533  dim = ARR_DIMS(v);
534  nitems = ArrayGetNItems(ndim, dim);
535 
536  if (nitems <= 0)
537  {
538  appendStringInfoString(result, "[]");
539  return;
540  }
541 
542  get_typlenbyvalalign(element_type,
543  &typlen, &typbyval, &typalign);
544 
545  json_categorize_type(element_type,
546  &tcategory, &outfuncoid);
547 
548  deconstruct_array(v, element_type, typlen, typbyval,
549  typalign, &elements, &nulls,
550  &nitems);
551 
552  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
553  outfuncoid, use_line_feeds);
554 
555  pfree(elements);
556  pfree(nulls);
557 }
558 
559 /*
560  * Turn a composite / record into JSON.
561  */
562 static void
563 composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
564 {
565  HeapTupleHeader td;
566  Oid tupType;
567  int32 tupTypmod;
568  TupleDesc tupdesc;
569  HeapTupleData tmptup,
570  *tuple;
571  int i;
572  bool needsep = false;
573  const char *sep;
574 
575  sep = use_line_feeds ? ",\n " : ",";
576 
577  td = DatumGetHeapTupleHeader(composite);
578 
579  /* Extract rowtype info and find a tupdesc */
580  tupType = HeapTupleHeaderGetTypeId(td);
581  tupTypmod = HeapTupleHeaderGetTypMod(td);
582  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
583 
584  /* Build a temporary HeapTuple control structure */
586  tmptup.t_data = td;
587  tuple = &tmptup;
588 
589  appendStringInfoChar(result, '{');
590 
591  for (i = 0; i < tupdesc->natts; i++)
592  {
593  Datum val;
594  bool isnull;
595  char *attname;
596  JsonTypeCategory tcategory;
597  Oid outfuncoid;
598  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
599 
600  if (att->attisdropped)
601  continue;
602 
603  if (needsep)
604  appendStringInfoString(result, sep);
605  needsep = true;
606 
607  attname = NameStr(att->attname);
608  escape_json(result, attname);
609  appendStringInfoChar(result, ':');
610 
611  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
612 
613  if (isnull)
614  {
615  tcategory = JSONTYPE_NULL;
616  outfuncoid = InvalidOid;
617  }
618  else
619  json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
620 
621  datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
622  }
623 
624  appendStringInfoChar(result, '}');
625  ReleaseTupleDesc(tupdesc);
626 }
627 
628 /*
629  * Append JSON text for "val" to "result".
630  *
631  * This is just a thin wrapper around datum_to_json. If the same type will be
632  * printed many times, avoid using this; better to do the json_categorize_type
633  * lookups only once.
634  */
635 static void
636 add_json(Datum val, bool is_null, StringInfo result,
637  Oid val_type, bool key_scalar)
638 {
639  JsonTypeCategory tcategory;
640  Oid outfuncoid;
641 
642  if (val_type == InvalidOid)
643  ereport(ERROR,
644  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
645  errmsg("could not determine input data type")));
646 
647  if (is_null)
648  {
649  tcategory = JSONTYPE_NULL;
650  outfuncoid = InvalidOid;
651  }
652  else
653  json_categorize_type(val_type,
654  &tcategory, &outfuncoid);
655 
656  datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
657 }
658 
659 /*
660  * SQL function array_to_json(row)
661  */
662 Datum
664 {
665  Datum array = PG_GETARG_DATUM(0);
666  StringInfo result;
667 
668  result = makeStringInfo();
669 
670  array_to_json_internal(array, result, false);
671 
673 }
674 
675 /*
676  * SQL function array_to_json(row, prettybool)
677  */
678 Datum
680 {
681  Datum array = PG_GETARG_DATUM(0);
682  bool use_line_feeds = PG_GETARG_BOOL(1);
683  StringInfo result;
684 
685  result = makeStringInfo();
686 
687  array_to_json_internal(array, result, use_line_feeds);
688 
690 }
691 
692 /*
693  * SQL function row_to_json(row)
694  */
695 Datum
697 {
698  Datum array = PG_GETARG_DATUM(0);
699  StringInfo result;
700 
701  result = makeStringInfo();
702 
703  composite_to_json(array, result, false);
704 
706 }
707 
708 /*
709  * SQL function row_to_json(row, prettybool)
710  */
711 Datum
713 {
714  Datum array = PG_GETARG_DATUM(0);
715  bool use_line_feeds = PG_GETARG_BOOL(1);
716  StringInfo result;
717 
718  result = makeStringInfo();
719 
720  composite_to_json(array, result, use_line_feeds);
721 
723 }
724 
725 /*
726  * SQL function to_json(anyvalue)
727  */
728 Datum
730 {
732  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
733  StringInfo result;
734  JsonTypeCategory tcategory;
735  Oid outfuncoid;
736 
737  if (val_type == InvalidOid)
738  ereport(ERROR,
739  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
740  errmsg("could not determine input data type")));
741 
742  json_categorize_type(val_type,
743  &tcategory, &outfuncoid);
744 
745  result = makeStringInfo();
746 
747  datum_to_json(val, false, result, tcategory, outfuncoid, false);
748 
750 }
751 
752 /*
753  * json_agg transition function
754  *
755  * aggregate input column as a json array value.
756  */
757 Datum
759 {
760  MemoryContext aggcontext,
761  oldcontext;
763  Datum val;
764 
765  if (!AggCheckCallContext(fcinfo, &aggcontext))
766  {
767  /* cannot be called directly because of internal-type argument */
768  elog(ERROR, "json_agg_transfn called in non-aggregate context");
769  }
770 
771  if (PG_ARGISNULL(0))
772  {
773  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
774 
775  if (arg_type == InvalidOid)
776  ereport(ERROR,
777  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
778  errmsg("could not determine input data type")));
779 
780  /*
781  * Make this state object in a context where it will persist for the
782  * duration of the aggregate call. MemoryContextSwitchTo is only
783  * needed the first time, as the StringInfo routines make sure they
784  * use the right context to enlarge the object if necessary.
785  */
786  oldcontext = MemoryContextSwitchTo(aggcontext);
787  state = (JsonAggState *) palloc(sizeof(JsonAggState));
788  state->str = makeStringInfo();
789  MemoryContextSwitchTo(oldcontext);
790 
791  appendStringInfoChar(state->str, '[');
792  json_categorize_type(arg_type, &state->val_category,
793  &state->val_output_func);
794  }
795  else
796  {
797  state = (JsonAggState *) PG_GETARG_POINTER(0);
798  appendStringInfoString(state->str, ", ");
799  }
800 
801  /* fast path for NULLs */
802  if (PG_ARGISNULL(1))
803  {
804  datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
805  InvalidOid, false);
806  PG_RETURN_POINTER(state);
807  }
808 
809  val = PG_GETARG_DATUM(1);
810 
811  /* add some whitespace if structured type and not first item */
812  if (!PG_ARGISNULL(0) &&
813  (state->val_category == JSONTYPE_ARRAY ||
814  state->val_category == JSONTYPE_COMPOSITE))
815  {
816  appendStringInfoString(state->str, "\n ");
817  }
818 
819  datum_to_json(val, false, state->str, state->val_category,
820  state->val_output_func, false);
821 
822  /*
823  * The transition type for json_agg() is declared to be "internal", which
824  * is a pass-by-value type the same size as a pointer. So we can safely
825  * pass the JsonAggState pointer through nodeAgg.c's machinations.
826  */
827  PG_RETURN_POINTER(state);
828 }
829 
830 /*
831  * json_agg final function
832  */
833 Datum
835 {
837 
838  /* cannot be called directly because of internal-type argument */
839  Assert(AggCheckCallContext(fcinfo, NULL));
840 
841  state = PG_ARGISNULL(0) ?
842  NULL :
844 
845  /* NULL result for no rows in, as is standard with aggregates */
846  if (state == NULL)
847  PG_RETURN_NULL();
848 
849  /* Else return state with appropriate array terminator added */
851 }
852 
853 /*
854  * json_object_agg transition function.
855  *
856  * aggregate two input columns as a single json object value.
857  */
858 Datum
860 {
861  MemoryContext aggcontext,
862  oldcontext;
864  Datum arg;
865 
866  if (!AggCheckCallContext(fcinfo, &aggcontext))
867  {
868  /* cannot be called directly because of internal-type argument */
869  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
870  }
871 
872  if (PG_ARGISNULL(0))
873  {
874  Oid arg_type;
875 
876  /*
877  * Make the StringInfo in a context where it will persist for the
878  * duration of the aggregate call. Switching context is only needed
879  * for this initial step, as the StringInfo routines make sure they
880  * use the right context to enlarge the object if necessary.
881  */
882  oldcontext = MemoryContextSwitchTo(aggcontext);
883  state = (JsonAggState *) palloc(sizeof(JsonAggState));
884  state->str = makeStringInfo();
885  MemoryContextSwitchTo(oldcontext);
886 
887  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
888 
889  if (arg_type == InvalidOid)
890  ereport(ERROR,
891  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
892  errmsg("could not determine data type for argument %d", 1)));
893 
894  json_categorize_type(arg_type, &state->key_category,
895  &state->key_output_func);
896 
897  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
898 
899  if (arg_type == InvalidOid)
900  ereport(ERROR,
901  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
902  errmsg("could not determine data type for argument %d", 2)));
903 
904  json_categorize_type(arg_type, &state->val_category,
905  &state->val_output_func);
906 
907  appendStringInfoString(state->str, "{ ");
908  }
909  else
910  {
911  state = (JsonAggState *) PG_GETARG_POINTER(0);
912  appendStringInfoString(state->str, ", ");
913  }
914 
915  /*
916  * Note: since json_object_agg() is declared as taking type "any", the
917  * parser will not do any type conversion on unknown-type literals (that
918  * is, undecorated strings or NULLs). Such values will arrive here as
919  * type UNKNOWN, which fortunately does not matter to us, since
920  * unknownout() works fine.
921  */
922 
923  if (PG_ARGISNULL(1))
924  ereport(ERROR,
925  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
926  errmsg("field name must not be null")));
927 
928  arg = PG_GETARG_DATUM(1);
929 
930  datum_to_json(arg, false, state->str, state->key_category,
931  state->key_output_func, true);
932 
933  appendStringInfoString(state->str, " : ");
934 
935  if (PG_ARGISNULL(2))
936  arg = (Datum) 0;
937  else
938  arg = PG_GETARG_DATUM(2);
939 
940  datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
941  state->val_output_func, false);
942 
943  PG_RETURN_POINTER(state);
944 }
945 
946 /*
947  * json_object_agg final function.
948  */
949 Datum
951 {
953 
954  /* cannot be called directly because of internal-type argument */
955  Assert(AggCheckCallContext(fcinfo, NULL));
956 
957  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
958 
959  /* NULL result for no rows in, as is standard with aggregates */
960  if (state == NULL)
961  PG_RETURN_NULL();
962 
963  /* Else return state with appropriate object terminator added */
965 }
966 
967 /*
968  * Helper function for aggregates: return given StringInfo's contents plus
969  * specified trailing string, as a text datum. We need this because aggregate
970  * final functions are not allowed to modify the aggregate state.
971  */
972 static text *
973 catenate_stringinfo_string(StringInfo buffer, const char *addon)
974 {
975  /* custom version of cstring_to_text_with_len */
976  int buflen = buffer->len;
977  int addlen = strlen(addon);
978  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
979 
980  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
981  memcpy(VARDATA(result), buffer->data, buflen);
982  memcpy(VARDATA(result) + buflen, addon, addlen);
983 
984  return result;
985 }
986 
987 /*
988  * SQL function json_build_object(variadic "any")
989  */
990 Datum
992 {
993  int nargs = PG_NARGS();
994  int i;
995  const char *sep = "";
996  StringInfo result;
997  Datum *args;
998  bool *nulls;
999  Oid *types;
1000 
1001  /* fetch argument values to build the object */
1002  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
1003 
1004  if (nargs < 0)
1005  PG_RETURN_NULL();
1006 
1007  if (nargs % 2 != 0)
1008  ereport(ERROR,
1009  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1010  errmsg("argument list must have even number of elements"),
1011  /* translator: %s is a SQL function name */
1012  errhint("The arguments of %s must consist of alternating keys and values.",
1013  "json_build_object()")));
1014 
1015  result = makeStringInfo();
1016 
1017  appendStringInfoChar(result, '{');
1018 
1019  for (i = 0; i < nargs; i += 2)
1020  {
1021  appendStringInfoString(result, sep);
1022  sep = ", ";
1023 
1024  /* process key */
1025  if (nulls[i])
1026  ereport(ERROR,
1027  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1028  errmsg("argument %d cannot be null", i + 1),
1029  errhint("Object keys should be text.")));
1030 
1031  add_json(args[i], false, result, types[i], true);
1032 
1033  appendStringInfoString(result, " : ");
1034 
1035  /* process value */
1036  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1037  }
1038 
1039  appendStringInfoChar(result, '}');
1040 
1042 }
1043 
1044 /*
1045  * degenerate case of json_build_object where it gets 0 arguments.
1046  */
1047 Datum
1049 {
1051 }
1052 
1053 /*
1054  * SQL function json_build_array(variadic "any")
1055  */
1056 Datum
1058 {
1059  int nargs;
1060  int i;
1061  const char *sep = "";
1062  StringInfo result;
1063  Datum *args;
1064  bool *nulls;
1065  Oid *types;
1066 
1067  /* fetch argument values to build the array */
1068  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
1069 
1070  if (nargs < 0)
1071  PG_RETURN_NULL();
1072 
1073  result = makeStringInfo();
1074 
1075  appendStringInfoChar(result, '[');
1076 
1077  for (i = 0; i < nargs; i++)
1078  {
1079  appendStringInfoString(result, sep);
1080  sep = ", ";
1081  add_json(args[i], nulls[i], result, types[i], false);
1082  }
1083 
1084  appendStringInfoChar(result, ']');
1085 
1087 }
1088 
1089 /*
1090  * degenerate case of json_build_array where it gets 0 arguments.
1091  */
1092 Datum
1094 {
1096 }
1097 
1098 /*
1099  * SQL function json_object(text[])
1100  *
1101  * take a one or two dimensional array of text as key/value pairs
1102  * for a json object.
1103  */
1104 Datum
1106 {
1107  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1108  int ndims = ARR_NDIM(in_array);
1109  StringInfoData result;
1110  Datum *in_datums;
1111  bool *in_nulls;
1112  int in_count,
1113  count,
1114  i;
1115  text *rval;
1116  char *v;
1117 
1118  switch (ndims)
1119  {
1120  case 0:
1122  break;
1123 
1124  case 1:
1125  if ((ARR_DIMS(in_array)[0]) % 2)
1126  ereport(ERROR,
1127  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1128  errmsg("array must have even number of elements")));
1129  break;
1130 
1131  case 2:
1132  if ((ARR_DIMS(in_array)[1]) != 2)
1133  ereport(ERROR,
1134  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1135  errmsg("array must have two columns")));
1136  break;
1137 
1138  default:
1139  ereport(ERROR,
1140  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1141  errmsg("wrong number of array subscripts")));
1142  }
1143 
1144  deconstruct_array(in_array,
1145  TEXTOID, -1, false, TYPALIGN_INT,
1146  &in_datums, &in_nulls, &in_count);
1147 
1148  count = in_count / 2;
1149 
1150  initStringInfo(&result);
1151 
1152  appendStringInfoChar(&result, '{');
1153 
1154  for (i = 0; i < count; ++i)
1155  {
1156  if (in_nulls[i * 2])
1157  ereport(ERROR,
1158  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1159  errmsg("null value not allowed for object key")));
1160 
1161  v = TextDatumGetCString(in_datums[i * 2]);
1162  if (i > 0)
1163  appendStringInfoString(&result, ", ");
1164  escape_json(&result, v);
1165  appendStringInfoString(&result, " : ");
1166  pfree(v);
1167  if (in_nulls[i * 2 + 1])
1168  appendStringInfoString(&result, "null");
1169  else
1170  {
1171  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1172  escape_json(&result, v);
1173  pfree(v);
1174  }
1175  }
1176 
1177  appendStringInfoChar(&result, '}');
1178 
1179  pfree(in_datums);
1180  pfree(in_nulls);
1181 
1182  rval = cstring_to_text_with_len(result.data, result.len);
1183  pfree(result.data);
1184 
1185  PG_RETURN_TEXT_P(rval);
1186 
1187 }
1188 
1189 /*
1190  * SQL function json_object(text[], text[])
1191  *
1192  * take separate key and value arrays of text to construct a json object
1193  * pairwise.
1194  */
1195 Datum
1197 {
1198  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1199  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1200  int nkdims = ARR_NDIM(key_array);
1201  int nvdims = ARR_NDIM(val_array);
1202  StringInfoData result;
1203  Datum *key_datums,
1204  *val_datums;
1205  bool *key_nulls,
1206  *val_nulls;
1207  int key_count,
1208  val_count,
1209  i;
1210  text *rval;
1211  char *v;
1212 
1213  if (nkdims > 1 || nkdims != nvdims)
1214  ereport(ERROR,
1215  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1216  errmsg("wrong number of array subscripts")));
1217 
1218  if (nkdims == 0)
1220 
1221  deconstruct_array(key_array,
1222  TEXTOID, -1, false, TYPALIGN_INT,
1223  &key_datums, &key_nulls, &key_count);
1224 
1225  deconstruct_array(val_array,
1226  TEXTOID, -1, false, TYPALIGN_INT,
1227  &val_datums, &val_nulls, &val_count);
1228 
1229  if (key_count != val_count)
1230  ereport(ERROR,
1231  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1232  errmsg("mismatched array dimensions")));
1233 
1234  initStringInfo(&result);
1235 
1236  appendStringInfoChar(&result, '{');
1237 
1238  for (i = 0; i < key_count; ++i)
1239  {
1240  if (key_nulls[i])
1241  ereport(ERROR,
1242  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1243  errmsg("null value not allowed for object key")));
1244 
1245  v = TextDatumGetCString(key_datums[i]);
1246  if (i > 0)
1247  appendStringInfoString(&result, ", ");
1248  escape_json(&result, v);
1249  appendStringInfoString(&result, " : ");
1250  pfree(v);
1251  if (val_nulls[i])
1252  appendStringInfoString(&result, "null");
1253  else
1254  {
1255  v = TextDatumGetCString(val_datums[i]);
1256  escape_json(&result, v);
1257  pfree(v);
1258  }
1259  }
1260 
1261  appendStringInfoChar(&result, '}');
1262 
1263  pfree(key_datums);
1264  pfree(key_nulls);
1265  pfree(val_datums);
1266  pfree(val_nulls);
1267 
1268  rval = cstring_to_text_with_len(result.data, result.len);
1269  pfree(result.data);
1270 
1271  PG_RETURN_TEXT_P(rval);
1272 }
1273 
1274 
1275 /*
1276  * Produce a JSON string literal, properly escaping characters in the text.
1277  */
1278 void
1280 {
1281  const char *p;
1282 
1283  appendStringInfoCharMacro(buf, '"');
1284  for (p = str; *p; p++)
1285  {
1286  switch (*p)
1287  {
1288  case '\b':
1289  appendStringInfoString(buf, "\\b");
1290  break;
1291  case '\f':
1292  appendStringInfoString(buf, "\\f");
1293  break;
1294  case '\n':
1295  appendStringInfoString(buf, "\\n");
1296  break;
1297  case '\r':
1298  appendStringInfoString(buf, "\\r");
1299  break;
1300  case '\t':
1301  appendStringInfoString(buf, "\\t");
1302  break;
1303  case '"':
1304  appendStringInfoString(buf, "\\\"");
1305  break;
1306  case '\\':
1307  appendStringInfoString(buf, "\\\\");
1308  break;
1309  default:
1310  if ((unsigned char) *p < ' ')
1311  appendStringInfo(buf, "\\u%04x", (int) *p);
1312  else
1313  appendStringInfoCharMacro(buf, *p);
1314  break;
1315  }
1316  }
1317  appendStringInfoCharMacro(buf, '"');
1318 }
1319 
1320 /*
1321  * SQL function json_typeof(json) -> text
1322  *
1323  * Returns the type of the outermost JSON value as TEXT. Possible types are
1324  * "object", "array", "string", "number", "boolean", and "null".
1325  *
1326  * Performs a single call to json_lex() to get the first token of the supplied
1327  * value. This initial token uniquely determines the value's type. As our
1328  * input must already have been validated by json_in() or json_recv(), the
1329  * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END,
1330  * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END.
1331  */
1332 Datum
1334 {
1335  text *json;
1336 
1337  JsonLexContext *lex;
1338  JsonTokenType tok;
1339  char *type;
1340  JsonParseErrorType result;
1341 
1342  json = PG_GETARG_TEXT_PP(0);
1343  lex = makeJsonLexContext(json, false);
1344 
1345  /* Lex exactly one token from the input and check its type. */
1346  result = json_lex(lex);
1347  if (result != JSON_SUCCESS)
1348  json_ereport_error(result, lex);
1349  tok = lex->token_type;
1350  switch (tok)
1351  {
1353  type = "object";
1354  break;
1356  type = "array";
1357  break;
1358  case JSON_TOKEN_STRING:
1359  type = "string";
1360  break;
1361  case JSON_TOKEN_NUMBER:
1362  type = "number";
1363  break;
1364  case JSON_TOKEN_TRUE:
1365  case JSON_TOKEN_FALSE:
1366  type = "boolean";
1367  break;
1368  case JSON_TOKEN_NULL:
1369  type = "null";
1370  break;
1371  default:
1372  elog(ERROR, "unexpected json token: %d", tok);
1373  }
1374 
1376 }
#define MAXDATELEN
Definition: datetime.h:201
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3855
signed short int16
Definition: c.h:354
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Datum to_json(PG_FUNCTION_ARGS)
Definition: json.c:729
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:246
#define DatumGetDateADT(X)
Definition: date.h:53
int errhint(const char *fmt,...)
Definition: elog.c:1071
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2700
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define VARDATA(PTR)
Definition: postgres.h:302
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1727
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1710
struct typedefs * types
Definition: ecpg.c:29
Datum json_object_two_arg(PG_FUNCTION_ARGS)
Definition: json.c:1196
int tm_isdst
Definition: pgtime.h:35
#define USECS_PER_SEC
Definition: timestamp.h:94
int32 DateADT
Definition: date.h:23
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:144
int64 timestamp
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2552
int64 TimestampTz
Definition: timestamp.h:39
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2075
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:563
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define VARHDRSZ
Definition: c.h:561
#define DatumGetTextPP(X)
Definition: fmgr.h:286
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:474
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
#define DatumGetTimeTzADTP(X)
Definition: date.h:55
Datum json_in(PG_FUNCTION_ARGS)
Definition: json.c:76
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
StringInfoData * StringInfo
Definition: stringinfo.h:44
JsonTokenType token_type
Definition: jsonapi.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum json_agg_finalfn(PG_FUNCTION_ARGS)
Definition: json.c:834
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:3940
Datum array_to_json_pretty(PG_FUNCTION_ARGS)
Definition: json.c:679
int errcode(int sqlerrcode)
Definition: elog.c:610
Oid val_output_func
Definition: json.c:51
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1281
JsonSemAction nullSemAction
Definition: jsonapi.c:67
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
long date
Definition: pgtypes_date.h:9
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1536
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
Definition: pgtime.h:25
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:289
CoercionPathType
Definition: parse_coerce.h:24
#define FirstNormalObjectId
Definition: transam.h:141
signed int int32
Definition: c.h:355
struct JsonAggState JsonAggState
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
static struct pg_tm tm
Definition: localtime.c:108
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:468
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
Definition: json.c:973
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
void pfree(void *pointer)
Definition: mcxt.c:1056
char typalign
Definition: pg_type.h:170
Datum json_build_object_noargs(PG_FUNCTION_ARGS)
Definition: json.c:1048
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid key_output_func
Definition: json.c:49
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1802
Datum array_to_json(PG_FUNCTION_ARGS)
Definition: json.c:663
#define ARR_DIMS(a)
Definition: array.h:282
Datum json_build_object(PG_FUNCTION_ARGS)
Definition: json.c:991
#define DATE_NOT_FINITE(j)
Definition: date.h:43
Datum row_to_json_pretty(PG_FUNCTION_ARGS)
Definition: json.c:712
Datum json_typeof(PG_FUNCTION_ARGS)
Definition: json.c:1333
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:653
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:353
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:155
uint32 t_len
Definition: htup.h:64
int tm_mday
Definition: pgtime.h:30
static char * buf
Definition: pg_test_fsync.c:67
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
StringInfo str
Definition: json.c:47
int tm_mon
Definition: pgtime.h:31
void check_stack_depth(void)
Definition: postgres.c:3292
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28
#define DatumGetBool(X)
Definition: postgres.h:393
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:3970
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:284
int32 fsec_t
Definition: timestamp.h:41
int64 TimeADT
Definition: date.h:25
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2459
JsonTypeCategory
Definition: json.c:30
bool IsValidJsonNumber(const char *str, int len)
Definition: jsonapi.c:115
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
JsonTypeCategory key_category
Definition: json.c:48
int64 Timestamp
Definition: timestamp.h:38
Datum json_object(PG_FUNCTION_ARGS)
Definition: json.c:1105
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
Datum json_object_agg_finalfn(PG_FUNCTION_ARGS)
Definition: json.c:950
#define DatumGetTimeADT(X)
Definition: date.h:54
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2154
JsonParseErrorType
Definition: jsonapi.h:36
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:458
Datum json_out(PG_FUNCTION_ARGS)
Definition: json.c:94
#define InvalidOid
Definition: postgres_ext.h:36
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:144
Datum json_object_agg_transfn(PG_FUNCTION_ARGS)
Definition: json.c:859
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:636
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
JsonTypeCategory val_category
Definition: json.c:50
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4661
Datum json_recv(PG_FUNCTION_ARGS)
Definition: json.c:120
#define PG_NARGS()
Definition: fmgr.h:198
#define ARR_NDIM(a)
Definition: array.h:278
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:516
Datum json_agg_transfn(PG_FUNCTION_ARGS)
Definition: json.c:758
void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonfuncs.c:607
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
char * text_to_cstring(const text *t)
Definition: varlena.c:204
Datum json_build_array_noargs(PG_FUNCTION_ARGS)
Definition: json.c:1093
#define USE_XSD_DATES
Definition: miscadmin.h:217
int tm_year
Definition: pgtime.h:32
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1655
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
Datum json_build_array(PG_FUNCTION_ARGS)
Definition: json.c:1057
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
#define elog(elevel,...)
Definition: elog.h:214
int i
#define NameStr(name)
Definition: c.h:615
#define CStringGetTextDatum(s)
Definition: builtins.h:87
void * arg
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272
Definition: c.h:555
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Datum row_to_json(PG_FUNCTION_ARGS)
Definition: json.c:696
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2325
Definition: date.h:27
#define ARR_ELEMTYPE(a)
Definition: array.h:280
long val
Definition: informix.c:664
#define PG_RETURN_NULL()
Definition: fmgr.h:335
Datum json_send(PG_FUNCTION_ARGS)
Definition: json.c:106
JsonTokenType
Definition: jsonapi.h:19
#define DatumGetTimestamp(X)
Definition: timestamp.h:27
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:452
#define DatumGetArrayTypeP(X)
Definition: array.h:249