PostgreSQL Source Code  git master
json.c File Reference
#include "postgres.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/json.h"
#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
Include dependency graph for json.c:

Go to the source code of this file.

Data Structures

struct  JsonUniqueHashEntry
 
struct  JsonUniqueStackEntry
 
struct  JsonUniqueParsingState
 
struct  JsonUniqueBuilderState
 
struct  JsonAggState
 

Typedefs

typedef struct HTABJsonUniqueCheckState
 
typedef struct JsonUniqueHashEntry JsonUniqueHashEntry
 
typedef struct JsonUniqueStackEntry JsonUniqueStackEntry
 
typedef struct JsonUniqueParsingState JsonUniqueParsingState
 
typedef struct JsonUniqueBuilderState JsonUniqueBuilderState
 
typedef struct JsonAggState JsonAggState
 

Functions

static void composite_to_json (Datum composite, StringInfo result, bool use_line_feeds)
 
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)
 
static void array_to_json_internal (Datum array, StringInfo result, bool use_line_feeds)
 
static void datum_to_json_internal (Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
 
static void add_json (Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
 
static textcatenate_stringinfo_string (StringInfo buffer, const char *addon)
 
Datum json_in (PG_FUNCTION_ARGS)
 
Datum json_out (PG_FUNCTION_ARGS)
 
Datum json_send (PG_FUNCTION_ARGS)
 
Datum json_recv (PG_FUNCTION_ARGS)
 
char * JsonEncodeDateTime (char *buf, Datum value, Oid typid, const int *tzp)
 
Datum array_to_json (PG_FUNCTION_ARGS)
 
Datum array_to_json_pretty (PG_FUNCTION_ARGS)
 
Datum row_to_json (PG_FUNCTION_ARGS)
 
Datum row_to_json_pretty (PG_FUNCTION_ARGS)
 
bool to_json_is_immutable (Oid typoid)
 
Datum to_json (PG_FUNCTION_ARGS)
 
Datum datum_to_json (Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
 
static Datum json_agg_transfn_worker (FunctionCallInfo fcinfo, bool absent_on_null)
 
Datum json_agg_transfn (PG_FUNCTION_ARGS)
 
Datum json_agg_strict_transfn (PG_FUNCTION_ARGS)
 
Datum json_agg_finalfn (PG_FUNCTION_ARGS)
 
static uint32 json_unique_hash (const void *key, Size keysize)
 
static int json_unique_hash_match (const void *key1, const void *key2, Size keysize)
 
static void json_unique_check_init (JsonUniqueCheckState *cxt)
 
static void json_unique_builder_init (JsonUniqueBuilderState *cxt)
 
static bool json_unique_check_key (JsonUniqueCheckState *cxt, const char *key, int object_id)
 
static StringInfo json_unique_builder_get_throwawaybuf (JsonUniqueBuilderState *cxt)
 
static Datum json_object_agg_transfn_worker (FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
 
Datum json_object_agg_transfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_strict_transfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_unique_transfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_unique_strict_transfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum json_build_object_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
 
Datum json_build_object (PG_FUNCTION_ARGS)
 
Datum json_build_object_noargs (PG_FUNCTION_ARGS)
 
Datum json_build_array_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
 
Datum json_build_array (PG_FUNCTION_ARGS)
 
Datum json_build_array_noargs (PG_FUNCTION_ARGS)
 
Datum json_object (PG_FUNCTION_ARGS)
 
Datum json_object_two_arg (PG_FUNCTION_ARGS)
 
void escape_json (StringInfo buf, const char *str)
 
static JsonParseErrorType json_unique_object_start (void *_state)
 
static JsonParseErrorType json_unique_object_end (void *_state)
 
static JsonParseErrorType json_unique_object_field_start (void *_state, char *field, bool isnull)
 
bool json_validate (text *json, bool check_unique_keys, bool throw_error)
 
Datum json_typeof (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ JsonAggState

typedef struct JsonAggState JsonAggState

◆ JsonUniqueBuilderState

◆ JsonUniqueCheckState

typedef struct HTAB* JsonUniqueCheckState

Definition at line 39 of file json.c.

◆ JsonUniqueHashEntry

◆ JsonUniqueParsingState

◆ JsonUniqueStackEntry

Function Documentation

◆ add_json()

static void add_json ( Datum  val,
bool  is_null,
StringInfo  result,
Oid  val_type,
bool  key_scalar 
)
static

Definition at line 593 of file json.c.

595 {
596  JsonTypeCategory tcategory;
597  Oid outfuncoid;
598 
599  if (val_type == InvalidOid)
600  ereport(ERROR,
601  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
602  errmsg("could not determine input data type")));
603 
604  if (is_null)
605  {
606  tcategory = JSONTYPE_NULL;
607  outfuncoid = InvalidOid;
608  }
609  else
610  json_categorize_type(val_type, false,
611  &tcategory, &outfuncoid);
612 
613  datum_to_json_internal(val, is_null, result, tcategory, outfuncoid,
614  key_scalar);
615 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
long val
Definition: informix.c:664
static void datum_to_json_internal(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:177
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5897
JsonTypeCategory
Definition: jsonfuncs.h:68
@ JSONTYPE_NULL
Definition: jsonfuncs.h:69
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31

References datum_to_json_internal(), ereport, errcode(), errmsg(), ERROR, InvalidOid, json_categorize_type(), JSONTYPE_NULL, and val.

Referenced by json_build_array_worker(), and json_build_object_worker().

◆ array_dim_to_json()

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 
)
static

Definition at line 422 of file json.c.

425 {
426  int i;
427  const char *sep;
428 
429  Assert(dim < ndims);
430 
431  sep = use_line_feeds ? ",\n " : ",";
432 
433  appendStringInfoChar(result, '[');
434 
435  for (i = 1; i <= dims[dim]; i++)
436  {
437  if (i > 1)
438  appendStringInfoString(result, sep);
439 
440  if (dim + 1 == ndims)
441  {
442  datum_to_json_internal(vals[*valcount], nulls[*valcount],
443  result, tcategory,
444  outfuncoid, false);
445  (*valcount)++;
446  }
447  else
448  {
449  /*
450  * Do we want line feeds on inner dimensions of arrays? For now
451  * we'll say no.
452  */
453  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
454  valcount, tcategory, outfuncoid, false);
455  }
456  }
457 
458  appendStringInfoChar(result, ']');
459 }
int i
Definition: isn.c:73
static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals, bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid, bool use_line_feeds)
Definition: json.c:422
Assert(fmt[strlen(fmt) - 1] !='\n')
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194

References appendStringInfoChar(), appendStringInfoString(), Assert(), datum_to_json_internal(), and i.

Referenced by array_to_json_internal().

◆ array_to_json()

Datum array_to_json ( PG_FUNCTION_ARGS  )

Definition at line 621 of file json.c.

622 {
623  Datum array = PG_GETARG_DATUM(0);
624  StringInfo result;
625 
626  result = makeStringInfo();
627 
628  array_to_json_internal(array, result, false);
629 
631 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:465
uintptr_t Datum
Definition: postgres.h:64
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References array_to_json_internal(), cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, makeStringInfo(), PG_GETARG_DATUM, and PG_RETURN_TEXT_P.

◆ array_to_json_internal()

static void array_to_json_internal ( Datum  array,
StringInfo  result,
bool  use_line_feeds 
)
static

Definition at line 465 of file json.c.

466 {
467  ArrayType *v = DatumGetArrayTypeP(array);
468  Oid element_type = ARR_ELEMTYPE(v);
469  int *dim;
470  int ndim;
471  int nitems;
472  int count = 0;
473  Datum *elements;
474  bool *nulls;
475  int16 typlen;
476  bool typbyval;
477  char typalign;
478  JsonTypeCategory tcategory;
479  Oid outfuncoid;
480 
481  ndim = ARR_NDIM(v);
482  dim = ARR_DIMS(v);
483  nitems = ArrayGetNItems(ndim, dim);
484 
485  if (nitems <= 0)
486  {
487  appendStringInfoString(result, "[]");
488  return;
489  }
490 
491  get_typlenbyvalalign(element_type,
492  &typlen, &typbyval, &typalign);
493 
494  json_categorize_type(element_type, false,
495  &tcategory, &outfuncoid);
496 
497  deconstruct_array(v, element_type, typlen, typbyval,
498  typalign, &elements, &nulls,
499  &nitems);
500 
501  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
502  outfuncoid, use_line_feeds);
503 
504  pfree(elements);
505  pfree(nulls);
506 }
#define ARR_NDIM(a)
Definition: array.h:290
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3612
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
signed short int16
Definition: c.h:480
#define nitems(x)
Definition: indent.h:31
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2227
void pfree(void *pointer)
Definition: mcxt.c:1508
char typalign
Definition: pg_type.h:176

References appendStringInfoString(), ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, array_dim_to_json(), ArrayGetNItems(), DatumGetArrayTypeP, deconstruct_array(), get_typlenbyvalalign(), json_categorize_type(), nitems, pfree(), and typalign.

Referenced by array_to_json(), array_to_json_pretty(), and datum_to_json_internal().

◆ array_to_json_pretty()

Datum array_to_json_pretty ( PG_FUNCTION_ARGS  )

Definition at line 637 of file json.c.

638 {
639  Datum array = PG_GETARG_DATUM(0);
640  bool use_line_feeds = PG_GETARG_BOOL(1);
641  StringInfo result;
642 
643  result = makeStringInfo();
644 
645  array_to_json_internal(array, result, use_line_feeds);
646 
648 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274

References array_to_json_internal(), cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, makeStringInfo(), PG_GETARG_BOOL, PG_GETARG_DATUM, and PG_RETURN_TEXT_P.

◆ catenate_stringinfo_string()

static text * catenate_stringinfo_string ( StringInfo  buffer,
const char *  addon 
)
static

Definition at line 1193 of file json.c.

1194 {
1195  /* custom version of cstring_to_text_with_len */
1196  int buflen = buffer->len;
1197  int addlen = strlen(addon);
1198  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
1199 
1200  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
1201  memcpy(VARDATA(result), buffer->data, buflen);
1202  memcpy(VARDATA(result) + buflen, addon, addlen);
1203 
1204  return result;
1205 }
#define VARHDRSZ
Definition: c.h:679
void * palloc(Size size)
Definition: mcxt.c:1304
Definition: c.h:674
#define VARDATA(PTR)
Definition: varatt.h:278
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References StringInfoData::data, StringInfoData::len, palloc(), SET_VARSIZE, VARDATA, and VARHDRSZ.

Referenced by json_agg_finalfn(), and json_object_agg_finalfn().

◆ composite_to_json()

static void composite_to_json ( Datum  composite,
StringInfo  result,
bool  use_line_feeds 
)
static

Definition at line 512 of file json.c.

513 {
514  HeapTupleHeader td;
515  Oid tupType;
516  int32 tupTypmod;
517  TupleDesc tupdesc;
518  HeapTupleData tmptup,
519  *tuple;
520  int i;
521  bool needsep = false;
522  const char *sep;
523  int seplen;
524 
525  /*
526  * We can avoid expensive strlen() calls by precalculating the separator
527  * length.
528  */
529  sep = use_line_feeds ? ",\n " : ",";
530  seplen = use_line_feeds ? strlen(",\n ") : strlen(",");
531 
532  td = DatumGetHeapTupleHeader(composite);
533 
534  /* Extract rowtype info and find a tupdesc */
535  tupType = HeapTupleHeaderGetTypeId(td);
536  tupTypmod = HeapTupleHeaderGetTypMod(td);
537  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
538 
539  /* Build a temporary HeapTuple control structure */
541  tmptup.t_data = td;
542  tuple = &tmptup;
543 
544  appendStringInfoChar(result, '{');
545 
546  for (i = 0; i < tupdesc->natts; i++)
547  {
548  Datum val;
549  bool isnull;
550  char *attname;
551  JsonTypeCategory tcategory;
552  Oid outfuncoid;
553  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
554 
555  if (att->attisdropped)
556  continue;
557 
558  if (needsep)
559  appendBinaryStringInfo(result, sep, seplen);
560  needsep = true;
561 
562  attname = NameStr(att->attname);
563  escape_json(result, attname);
564  appendStringInfoChar(result, ':');
565 
566  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
567 
568  if (isnull)
569  {
570  tcategory = JSONTYPE_NULL;
571  outfuncoid = InvalidOid;
572  }
573  else
574  json_categorize_type(att->atttypid, false, &tcategory,
575  &outfuncoid);
576 
577  datum_to_json_internal(val, isnull, result, tcategory, outfuncoid,
578  false);
579  }
580 
581  appendStringInfoChar(result, '}');
582  ReleaseTupleDesc(tupdesc);
583 }
#define NameStr(name)
Definition: c.h:733
signed int int32
Definition: c.h:481
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833

References appendBinaryStringInfo(), appendStringInfoChar(), attname, datum_to_json_internal(), DatumGetHeapTupleHeader, escape_json(), heap_getattr(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InvalidOid, json_categorize_type(), JSONTYPE_NULL, lookup_rowtype_tupdesc(), NameStr, TupleDescData::natts, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, TupleDescAttr, and val.

Referenced by datum_to_json_internal(), row_to_json(), and row_to_json_pretty().

◆ datum_to_json()

Datum datum_to_json ( Datum  val,
JsonTypeCategory  tcategory,
Oid  outfuncoid 
)

Definition at line 754 of file json.c.

755 {
756  StringInfo result = makeStringInfo();
757 
758  datum_to_json_internal(val, false, result, tcategory, outfuncoid,
759  false);
760 
761  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
762 }
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322

References cstring_to_text_with_len(), StringInfoData::data, datum_to_json_internal(), StringInfoData::len, makeStringInfo(), PointerGetDatum(), and val.

Referenced by ExecEvalJsonConstructor(), and to_json().

◆ datum_to_json_internal()

static void datum_to_json_internal ( Datum  val,
bool  is_null,
StringInfo  result,
JsonTypeCategory  tcategory,
Oid  outfuncoid,
bool  key_scalar 
)
static

Definition at line 177 of file json.c.

180 {
181  char *outputstr;
182  text *jsontext;
183 
185 
186  /* callers are expected to ensure that null keys are not passed in */
187  Assert(!(key_scalar && is_null));
188 
189  if (is_null)
190  {
191  appendBinaryStringInfo(result, "null", strlen("null"));
192  return;
193  }
194 
195  if (key_scalar &&
196  (tcategory == JSONTYPE_ARRAY ||
197  tcategory == JSONTYPE_COMPOSITE ||
198  tcategory == JSONTYPE_JSON ||
199  tcategory == JSONTYPE_CAST))
200  ereport(ERROR,
201  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
202  errmsg("key value must be scalar, not array, composite, or json")));
203 
204  switch (tcategory)
205  {
206  case JSONTYPE_ARRAY:
207  array_to_json_internal(val, result, false);
208  break;
209  case JSONTYPE_COMPOSITE:
210  composite_to_json(val, result, false);
211  break;
212  case JSONTYPE_BOOL:
213  if (key_scalar)
214  appendStringInfoChar(result, '"');
215  if (DatumGetBool(val))
216  appendBinaryStringInfo(result, "true", strlen("true"));
217  else
218  appendBinaryStringInfo(result, "false", strlen("false"));
219  if (key_scalar)
220  appendStringInfoChar(result, '"');
221  break;
222  case JSONTYPE_NUMERIC:
223  outputstr = OidOutputFunctionCall(outfuncoid, val);
224 
225  /*
226  * Don't quote a non-key if it's a valid JSON number (i.e., not
227  * "Infinity", "-Infinity", or "NaN"). Since we know this is a
228  * numeric data type's output, we simplify and open-code the
229  * validation for better performance.
230  */
231  if (!key_scalar &&
232  ((*outputstr >= '0' && *outputstr <= '9') ||
233  (*outputstr == '-' &&
234  (outputstr[1] >= '0' && outputstr[1] <= '9'))))
235  appendStringInfoString(result, outputstr);
236  else
237  {
238  appendStringInfoChar(result, '"');
239  appendStringInfoString(result, outputstr);
240  appendStringInfoChar(result, '"');
241  }
242  pfree(outputstr);
243  break;
244  case JSONTYPE_DATE:
245  {
246  char buf[MAXDATELEN + 1];
247 
248  JsonEncodeDateTime(buf, val, DATEOID, NULL);
249  appendStringInfoChar(result, '"');
250  appendStringInfoString(result, buf);
251  appendStringInfoChar(result, '"');
252  }
253  break;
254  case JSONTYPE_TIMESTAMP:
255  {
256  char buf[MAXDATELEN + 1];
257 
258  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
259  appendStringInfoChar(result, '"');
260  appendStringInfoString(result, buf);
261  appendStringInfoChar(result, '"');
262  }
263  break;
265  {
266  char buf[MAXDATELEN + 1];
267 
268  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
269  appendStringInfoChar(result, '"');
270  appendStringInfoString(result, buf);
271  appendStringInfoChar(result, '"');
272  }
273  break;
274  case JSONTYPE_JSON:
275  /* JSON and JSONB output will already be escaped */
276  outputstr = OidOutputFunctionCall(outfuncoid, val);
277  appendStringInfoString(result, outputstr);
278  pfree(outputstr);
279  break;
280  case JSONTYPE_CAST:
281  /* outfuncoid refers to a cast function, not an output function */
282  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
283  appendBinaryStringInfo(result, VARDATA_ANY(jsontext),
284  VARSIZE_ANY_EXHDR(jsontext));
285  pfree(jsontext);
286  break;
287  default:
288  outputstr = OidOutputFunctionCall(outfuncoid, val);
289  escape_json(result, outputstr);
290  pfree(outputstr);
291  break;
292  }
293 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:680
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define MAXDATELEN
Definition: datetime.h:200
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:301
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:512
@ JSONTYPE_JSON
Definition: jsonfuncs.h:75
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:73
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:71
@ JSONTYPE_DATE
Definition: jsonfuncs.h:72
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:70
@ JSONTYPE_CAST
Definition: jsonfuncs.h:79
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:78
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:77
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:74
static char * buf
Definition: pg_test_fsync.c:73
void check_stack_depth(void)
Definition: postgres.c:3531
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

References appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), array_to_json_internal(), Assert(), buf, check_stack_depth(), composite_to_json(), DatumGetBool(), DatumGetTextPP, ereport, errcode(), errmsg(), ERROR, escape_json(), JsonEncodeDateTime(), JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_NUMERIC, JSONTYPE_TIMESTAMP, JSONTYPE_TIMESTAMPTZ, MAXDATELEN, OidFunctionCall1, OidOutputFunctionCall(), pfree(), val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by add_json(), array_dim_to_json(), composite_to_json(), datum_to_json(), json_agg_transfn_worker(), and json_object_agg_transfn_worker().

◆ escape_json()

static void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 1549 of file json.c.

1550 {
1551  const char *p;
1552 
1554  for (p = str; *p; p++)
1555  {
1556  switch (*p)
1557  {
1558  case '\b':
1559  appendStringInfoString(buf, "\\b");
1560  break;
1561  case '\f':
1562  appendStringInfoString(buf, "\\f");
1563  break;
1564  case '\n':
1565  appendStringInfoString(buf, "\\n");
1566  break;
1567  case '\r':
1568  appendStringInfoString(buf, "\\r");
1569  break;
1570  case '\t':
1571  appendStringInfoString(buf, "\\t");
1572  break;
1573  case '"':
1574  appendStringInfoString(buf, "\\\"");
1575  break;
1576  case '\\':
1577  appendStringInfoString(buf, "\\\\");
1578  break;
1579  default:
1580  if ((unsigned char) *p < ' ')
1581  appendStringInfo(buf, "\\u%04x", (int) *p);
1582  else
1584  break;
1585  }
1586  }
1588 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204

References appendStringInfo(), appendStringInfoCharMacro, appendStringInfoString(), buf, and generate_unaccent_rules::str.

Referenced by AddFileToBackupManifest(), appendJSONKeyValue(), composite_to_json(), datum_to_json_internal(), escape_yaml(), ExplainDummyGroup(), ExplainOpenGroup(), ExplainProperty(), ExplainPropertyList(), ExplainPropertyListNested(), hstore_to_json(), hstore_to_json_loose(), json_object(), json_object_two_arg(), jsonb_put_escaped_value(), populate_scalar(), printJsonPathItem(), sn_object_field_start(), sn_scalar(), transform_string_values_object_field_start(), transform_string_values_scalar(), and write_jsonlog().

◆ json_agg_finalfn()

Datum json_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 870 of file json.c.

871 {
873 
874  /* cannot be called directly because of internal-type argument */
875  Assert(AggCheckCallContext(fcinfo, NULL));
876 
877  state = PG_ARGISNULL(0) ?
878  NULL :
880 
881  /* NULL result for no rows in, as is standard with aggregates */
882  if (state == NULL)
883  PG_RETURN_NULL();
884 
885  /* Else return state with appropriate array terminator added */
887 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:345
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
Definition: json.c:1193
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4511
Definition: regguts.h:323

References AggCheckCallContext(), Assert(), catenate_stringinfo_string(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_TEXT_P.

◆ json_agg_strict_transfn()

Datum json_agg_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 861 of file json.c.

862 {
863  return json_agg_transfn_worker(fcinfo, true);
864 }
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: json.c:770

References json_agg_transfn_worker().

◆ json_agg_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 852 of file json.c.

853 {
854  return json_agg_transfn_worker(fcinfo, false);
855 }

References json_agg_transfn_worker().

◆ json_agg_transfn_worker()

static Datum json_agg_transfn_worker ( FunctionCallInfo  fcinfo,
bool  absent_on_null 
)
static

Definition at line 770 of file json.c.

771 {
772  MemoryContext aggcontext,
773  oldcontext;
775  Datum val;
776 
777  if (!AggCheckCallContext(fcinfo, &aggcontext))
778  {
779  /* cannot be called directly because of internal-type argument */
780  elog(ERROR, "json_agg_transfn called in non-aggregate context");
781  }
782 
783  if (PG_ARGISNULL(0))
784  {
785  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
786 
787  if (arg_type == InvalidOid)
788  ereport(ERROR,
789  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
790  errmsg("could not determine input data type")));
791 
792  /*
793  * Make this state object in a context where it will persist for the
794  * duration of the aggregate call. MemoryContextSwitchTo is only
795  * needed the first time, as the StringInfo routines make sure they
796  * use the right context to enlarge the object if necessary.
797  */
798  oldcontext = MemoryContextSwitchTo(aggcontext);
799  state = (JsonAggState *) palloc(sizeof(JsonAggState));
800  state->str = makeStringInfo();
801  MemoryContextSwitchTo(oldcontext);
802 
803  appendStringInfoChar(state->str, '[');
804  json_categorize_type(arg_type, false, &state->val_category,
805  &state->val_output_func);
806  }
807  else
808  {
810  }
811 
812  if (absent_on_null && PG_ARGISNULL(1))
814 
815  if (state->str->len > 1)
816  appendStringInfoString(state->str, ", ");
817 
818  /* fast path for NULLs */
819  if (PG_ARGISNULL(1))
820  {
822  InvalidOid, false);
824  }
825 
826  val = PG_GETARG_DATUM(1);
827 
828  /* add some whitespace if structured type and not first item */
829  if (!PG_ARGISNULL(0) && state->str->len > 1 &&
830  (state->val_category == JSONTYPE_ARRAY ||
831  state->val_category == JSONTYPE_COMPOSITE))
832  {
833  appendStringInfoString(state->str, "\n ");
834  }
835 
836  datum_to_json_internal(val, false, state->str, state->val_category,
837  state->val_output_func, false);
838 
839  /*
840  * The transition type for json_agg() is declared to be "internal", which
841  * is a pass-by-value type the same size as a pointer. So we can safely
842  * pass the JsonAggState pointer through nodeAgg.c's machinations.
843  */
845 }
#define elog(elevel,...)
Definition: elog.h:224
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
FmgrInfo * flinfo
Definition: fmgr.h:87

References AggCheckCallContext(), appendStringInfoChar(), appendStringInfoString(), datum_to_json_internal(), elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), JSONTYPE_ARRAY, JSONTYPE_COMPOSITE, JSONTYPE_NULL, makeStringInfo(), MemoryContextSwitchTo(), palloc(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, and val.

Referenced by json_agg_strict_transfn(), and json_agg_transfn().

◆ json_build_array()

Datum json_build_array ( PG_FUNCTION_ARGS  )

Definition at line 1351 of file json.c.

1352 {
1353  Datum *args;
1354  bool *nulls;
1355  Oid *types;
1356 
1357  /* build argument values to build the object */
1358  int nargs = extract_variadic_args(fcinfo, 0, true,
1359  &args, &types, &nulls);
1360 
1361  if (nargs < 0)
1362  PG_RETURN_NULL();
1363 
1364  PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
1365 }
struct typedefs * types
Definition: ecpg.c:29
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1997
Datum json_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: json.c:1321

References generate_unaccent_rules::args, extract_variadic_args(), json_build_array_worker(), PG_RETURN_DATUM, PG_RETURN_NULL, and types.

◆ json_build_array_noargs()

Datum json_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1371 of file json.c.

1372 {
1374 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_build_array_worker()

Datum json_build_array_worker ( int  nargs,
const Datum args,
const bool nulls,
const Oid types,
bool  absent_on_null 
)

Definition at line 1321 of file json.c.

1323 {
1324  int i;
1325  const char *sep = "";
1326  StringInfo result;
1327 
1328  result = makeStringInfo();
1329 
1330  appendStringInfoChar(result, '[');
1331 
1332  for (i = 0; i < nargs; i++)
1333  {
1334  if (absent_on_null && nulls[i])
1335  continue;
1336 
1337  appendStringInfoString(result, sep);
1338  sep = ", ";
1339  add_json(args[i], nulls[i], result, types[i], false);
1340  }
1341 
1342  appendStringInfoChar(result, ']');
1343 
1344  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1345 }
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:593

References add_json(), appendStringInfoChar(), appendStringInfoString(), generate_unaccent_rules::args, cstring_to_text_with_len(), StringInfoData::data, i, StringInfoData::len, makeStringInfo(), PointerGetDatum(), and types.

Referenced by ExecEvalJsonConstructor(), and json_build_array().

◆ json_build_object()

Datum json_build_object ( PG_FUNCTION_ARGS  )

Definition at line 1295 of file json.c.

1296 {
1297  Datum *args;
1298  bool *nulls;
1299  Oid *types;
1300 
1301  /* build argument values to build the object */
1302  int nargs = extract_variadic_args(fcinfo, 0, true,
1303  &args, &types, &nulls);
1304 
1305  if (nargs < 0)
1306  PG_RETURN_NULL();
1307 
1308  PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
1309 }
Datum json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1208

References generate_unaccent_rules::args, extract_variadic_args(), json_build_object_worker(), PG_RETURN_DATUM, PG_RETURN_NULL, and types.

◆ json_build_object_noargs()

Datum json_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1315 of file json.c.

1316 {
1318 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_build_object_worker()

Datum json_build_object_worker ( int  nargs,
const Datum args,
const bool nulls,
const Oid types,
bool  absent_on_null,
bool  unique_keys 
)

Definition at line 1208 of file json.c.

1210 {
1211  int i;
1212  const char *sep = "";
1213  StringInfo result;
1214  JsonUniqueBuilderState unique_check;
1215 
1216  if (nargs % 2 != 0)
1217  ereport(ERROR,
1218  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1219  errmsg("argument list must have even number of elements"),
1220  /* translator: %s is a SQL function name */
1221  errhint("The arguments of %s must consist of alternating keys and values.",
1222  "json_build_object()")));
1223 
1224  result = makeStringInfo();
1225 
1226  appendStringInfoChar(result, '{');
1227 
1228  if (unique_keys)
1229  json_unique_builder_init(&unique_check);
1230 
1231  for (i = 0; i < nargs; i += 2)
1232  {
1233  StringInfo out;
1234  bool skip;
1235  int key_offset;
1236 
1237  /* Skip null values if absent_on_null */
1238  skip = absent_on_null && nulls[i + 1];
1239 
1240  if (skip)
1241  {
1242  /* If key uniqueness check is needed we must save skipped keys */
1243  if (!unique_keys)
1244  continue;
1245 
1246  out = json_unique_builder_get_throwawaybuf(&unique_check);
1247  }
1248  else
1249  {
1250  appendStringInfoString(result, sep);
1251  sep = ", ";
1252  out = result;
1253  }
1254 
1255  /* process key */
1256  if (nulls[i])
1257  ereport(ERROR,
1258  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1259  errmsg("null value not allowed for object key")));
1260 
1261  /* save key offset before appending it */
1262  key_offset = out->len;
1263 
1264  add_json(args[i], false, out, types[i], true);
1265 
1266  if (unique_keys)
1267  {
1268  /* check key uniqueness after key appending */
1269  const char *key = &out->data[key_offset];
1270 
1271  if (!json_unique_check_key(&unique_check.check, key, 0))
1272  ereport(ERROR,
1273  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1274  errmsg("duplicate JSON object key value: %s", key));
1275 
1276  if (skip)
1277  continue;
1278  }
1279 
1280  appendStringInfoString(result, " : ");
1281 
1282  /* process value */
1283  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1284  }
1285 
1286  appendStringInfoChar(result, '}');
1287 
1288  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1289 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
static StringInfo json_unique_builder_get_throwawaybuf(JsonUniqueBuilderState *cxt)
Definition: json.c:969
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
Definition: json.c:949
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Definition: json.c:941
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:108
JsonUniqueCheckState check
Definition: json.c:69

References add_json(), appendStringInfoChar(), appendStringInfoString(), generate_unaccent_rules::args, JsonUniqueBuilderState::check, cstring_to_text_with_len(), StringInfoData::data, ereport, errcode(), errhint(), errmsg(), ERROR, i, json_unique_builder_get_throwawaybuf(), json_unique_builder_init(), json_unique_check_key(), sort-test::key, StringInfoData::len, makeStringInfo(), PointerGetDatum(), skip, and types.

Referenced by ExecEvalJsonConstructor(), and json_build_object().

◆ json_in()

Datum json_in ( PG_FUNCTION_ARGS  )

Definition at line 105 of file json.c.

106 {
107  char *json = PG_GETARG_CSTRING(0);
108  text *result = cstring_to_text(json);
109  JsonLexContext lex;
110 
111  /* validate it */
112  makeJsonLexContext(&lex, result, false);
113  if (!pg_parse_json_or_errsave(&lex, &nullSemAction, fcinfo->context))
114  PG_RETURN_NULL();
115 
116  /* Internal representation is the same as text */
117  PG_RETURN_TEXT_P(result);
118 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
JsonSemAction nullSemAction
Definition: jsonapi.c:57
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:537
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:516
text * cstring_to_text(const char *s)
Definition: varlena.c:184

References cstring_to_text(), makeJsonLexContext(), nullSemAction, PG_GETARG_CSTRING, pg_parse_json_or_errsave(), PG_RETURN_NULL, and PG_RETURN_TEXT_P.

◆ json_object()

Datum json_object ( PG_FUNCTION_ARGS  )

Definition at line 1383 of file json.c.

1384 {
1385  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1386  int ndims = ARR_NDIM(in_array);
1387  StringInfoData result;
1388  Datum *in_datums;
1389  bool *in_nulls;
1390  int in_count,
1391  count,
1392  i;
1393  text *rval;
1394  char *v;
1395 
1396  switch (ndims)
1397  {
1398  case 0:
1400  break;
1401 
1402  case 1:
1403  if ((ARR_DIMS(in_array)[0]) % 2)
1404  ereport(ERROR,
1405  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1406  errmsg("array must have even number of elements")));
1407  break;
1408 
1409  case 2:
1410  if ((ARR_DIMS(in_array)[1]) != 2)
1411  ereport(ERROR,
1412  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1413  errmsg("array must have two columns")));
1414  break;
1415 
1416  default:
1417  ereport(ERROR,
1418  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1419  errmsg("wrong number of array subscripts")));
1420  }
1421 
1422  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1423 
1424  count = in_count / 2;
1425 
1426  initStringInfo(&result);
1427 
1428  appendStringInfoChar(&result, '{');
1429 
1430  for (i = 0; i < count; ++i)
1431  {
1432  if (in_nulls[i * 2])
1433  ereport(ERROR,
1434  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1435  errmsg("null value not allowed for object key")));
1436 
1437  v = TextDatumGetCString(in_datums[i * 2]);
1438  if (i > 0)
1439  appendStringInfoString(&result, ", ");
1440  escape_json(&result, v);
1441  appendStringInfoString(&result, " : ");
1442  pfree(v);
1443  if (in_nulls[i * 2 + 1])
1444  appendStringInfoString(&result, "null");
1445  else
1446  {
1447  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1448  escape_json(&result, v);
1449  pfree(v);
1450  }
1451  }
1452 
1453  appendStringInfoChar(&result, '}');
1454 
1455  pfree(in_datums);
1456  pfree(in_nulls);
1457 
1458  rval = cstring_to_text_with_len(result.data, result.len);
1459  pfree(result.data);
1460 
1461  PG_RETURN_TEXT_P(rval);
1462 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3678
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

References appendStringInfoChar(), appendStringInfoString(), ARR_DIMS, ARR_NDIM, cstring_to_text_with_len(), CStringGetTextDatum, StringInfoData::data, deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, escape_json(), i, initStringInfo(), StringInfoData::len, pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_TEXT_P, and TextDatumGetCString.

◆ json_object_agg_finalfn()

Datum json_object_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1170 of file json.c.

1171 {
1173 
1174  /* cannot be called directly because of internal-type argument */
1175  Assert(AggCheckCallContext(fcinfo, NULL));
1176 
1177  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
1178 
1179  /* NULL result for no rows in, as is standard with aggregates */
1180  if (state == NULL)
1181  PG_RETURN_NULL();
1182 
1183  /* Else return state with appropriate object terminator added */
1185 }

References AggCheckCallContext(), Assert(), catenate_stringinfo_string(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_TEXT_P.

◆ json_object_agg_strict_transfn()

Datum json_object_agg_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1143 of file json.c.

1144 {
1145  return json_object_agg_transfn_worker(fcinfo, true, false);
1146 }
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: json.c:993

References json_object_agg_transfn_worker().

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1134 of file json.c.

1135 {
1136  return json_object_agg_transfn_worker(fcinfo, false, false);
1137 }

References json_object_agg_transfn_worker().

◆ json_object_agg_transfn_worker()

static Datum json_object_agg_transfn_worker ( FunctionCallInfo  fcinfo,
bool  absent_on_null,
bool  unique_keys 
)
static

Definition at line 993 of file json.c.

995 {
996  MemoryContext aggcontext,
997  oldcontext;
999  StringInfo out;
1000  Datum arg;
1001  bool skip;
1002  int key_offset;
1003 
1004  if (!AggCheckCallContext(fcinfo, &aggcontext))
1005  {
1006  /* cannot be called directly because of internal-type argument */
1007  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
1008  }
1009 
1010  if (PG_ARGISNULL(0))
1011  {
1012  Oid arg_type;
1013 
1014  /*
1015  * Make the StringInfo in a context where it will persist for the
1016  * duration of the aggregate call. Switching context is only needed
1017  * for this initial step, as the StringInfo and dynahash routines make
1018  * sure they use the right context to enlarge the object if necessary.
1019  */
1020  oldcontext = MemoryContextSwitchTo(aggcontext);
1021  state = (JsonAggState *) palloc(sizeof(JsonAggState));
1022  state->str = makeStringInfo();
1023  if (unique_keys)
1024  json_unique_builder_init(&state->unique_check);
1025  else
1026  memset(&state->unique_check, 0, sizeof(state->unique_check));
1027  MemoryContextSwitchTo(oldcontext);
1028 
1029  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1030 
1031  if (arg_type == InvalidOid)
1032  ereport(ERROR,
1033  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1034  errmsg("could not determine data type for argument %d", 1)));
1035 
1036  json_categorize_type(arg_type, false, &state->key_category,
1037  &state->key_output_func);
1038 
1039  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1040 
1041  if (arg_type == InvalidOid)
1042  ereport(ERROR,
1043  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1044  errmsg("could not determine data type for argument %d", 2)));
1045 
1046  json_categorize_type(arg_type, false, &state->val_category,
1047  &state->val_output_func);
1048 
1049  appendStringInfoString(state->str, "{ ");
1050  }
1051  else
1052  {
1054  }
1055 
1056  /*
1057  * Note: since json_object_agg() is declared as taking type "any", the
1058  * parser will not do any type conversion on unknown-type literals (that
1059  * is, undecorated strings or NULLs). Such values will arrive here as
1060  * type UNKNOWN, which fortunately does not matter to us, since
1061  * unknownout() works fine.
1062  */
1063 
1064  if (PG_ARGISNULL(1))
1065  ereport(ERROR,
1066  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1067  errmsg("null value not allowed for object key")));
1068 
1069  /* Skip null values if absent_on_null */
1070  skip = absent_on_null && PG_ARGISNULL(2);
1071 
1072  if (skip)
1073  {
1074  /*
1075  * We got a NULL value and we're not storing those; if we're not
1076  * testing key uniqueness, we're done. If we are, use the throwaway
1077  * buffer to store the key name so that we can check it.
1078  */
1079  if (!unique_keys)
1081 
1082  out = json_unique_builder_get_throwawaybuf(&state->unique_check);
1083  }
1084  else
1085  {
1086  out = state->str;
1087 
1088  /*
1089  * Append comma delimiter only if we have already output some fields
1090  * after the initial string "{ ".
1091  */
1092  if (out->len > 2)
1093  appendStringInfoString(out, ", ");
1094  }
1095 
1096  arg = PG_GETARG_DATUM(1);
1097 
1098  key_offset = out->len;
1099 
1100  datum_to_json_internal(arg, false, out, state->key_category,
1101  state->key_output_func, true);
1102 
1103  if (unique_keys)
1104  {
1105  const char *key = &out->data[key_offset];
1106 
1107  if (!json_unique_check_key(&state->unique_check.check, key, 0))
1108  ereport(ERROR,
1109  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1110  errmsg("duplicate JSON object key value: %s", key));
1111 
1112  if (skip)
1114  }
1115 
1116  appendStringInfoString(state->str, " : ");
1117 
1118  if (PG_ARGISNULL(2))
1119  arg = (Datum) 0;
1120  else
1121  arg = PG_GETARG_DATUM(2);
1122 
1124  state->val_category,
1125  state->val_output_func, false);
1126 
1128 }
void * arg

References AggCheckCallContext(), appendStringInfoString(), arg, StringInfoData::data, datum_to_json_internal(), elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), json_unique_builder_get_throwawaybuf(), json_unique_builder_init(), json_unique_check_key(), sort-test::key, StringInfoData::len, makeStringInfo(), MemoryContextSwitchTo(), palloc(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, and skip.

Referenced by json_object_agg_strict_transfn(), json_object_agg_transfn(), json_object_agg_unique_strict_transfn(), and json_object_agg_unique_transfn().

◆ json_object_agg_unique_strict_transfn()

Datum json_object_agg_unique_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1161 of file json.c.

1162 {
1163  return json_object_agg_transfn_worker(fcinfo, true, true);
1164 }

References json_object_agg_transfn_worker().

◆ json_object_agg_unique_transfn()

Datum json_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1152 of file json.c.

1153 {
1154  return json_object_agg_transfn_worker(fcinfo, false, true);
1155 }

References json_object_agg_transfn_worker().

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1471 of file json.c.

1472 {
1473  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1474  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1475  int nkdims = ARR_NDIM(key_array);
1476  int nvdims = ARR_NDIM(val_array);
1477  StringInfoData result;
1478  Datum *key_datums,
1479  *val_datums;
1480  bool *key_nulls,
1481  *val_nulls;
1482  int key_count,
1483  val_count,
1484  i;
1485  text *rval;
1486  char *v;
1487 
1488  if (nkdims > 1 || nkdims != nvdims)
1489  ereport(ERROR,
1490  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1491  errmsg("wrong number of array subscripts")));
1492 
1493  if (nkdims == 0)
1495 
1496  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1497  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1498 
1499  if (key_count != val_count)
1500  ereport(ERROR,
1501  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1502  errmsg("mismatched array dimensions")));
1503 
1504  initStringInfo(&result);
1505 
1506  appendStringInfoChar(&result, '{');
1507 
1508  for (i = 0; i < key_count; ++i)
1509  {
1510  if (key_nulls[i])
1511  ereport(ERROR,
1512  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1513  errmsg("null value not allowed for object key")));
1514 
1515  v = TextDatumGetCString(key_datums[i]);
1516  if (i > 0)
1517  appendStringInfoString(&result, ", ");
1518  escape_json(&result, v);
1519  appendStringInfoString(&result, " : ");
1520  pfree(v);
1521  if (val_nulls[i])
1522  appendStringInfoString(&result, "null");
1523  else
1524  {
1525  v = TextDatumGetCString(val_datums[i]);
1526  escape_json(&result, v);
1527  pfree(v);
1528  }
1529  }
1530 
1531  appendStringInfoChar(&result, '}');
1532 
1533  pfree(key_datums);
1534  pfree(key_nulls);
1535  pfree(val_datums);
1536  pfree(val_nulls);
1537 
1538  rval = cstring_to_text_with_len(result.data, result.len);
1539  pfree(result.data);
1540 
1541  PG_RETURN_TEXT_P(rval);
1542 }

References appendStringInfoChar(), appendStringInfoString(), ARR_NDIM, cstring_to_text_with_len(), CStringGetTextDatum, StringInfoData::data, deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, escape_json(), i, initStringInfo(), StringInfoData::len, pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_TEXT_P, and TextDatumGetCString.

◆ json_out()

Datum json_out ( PG_FUNCTION_ARGS  )

Definition at line 124 of file json.c.

125 {
126  /* we needn't detoast because text_to_cstring will handle that */
127  Datum txt = PG_GETARG_DATUM(0);
128 
130 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362

References PG_GETARG_DATUM, PG_RETURN_CSTRING, and TextDatumGetCString.

◆ json_recv()

Datum json_recv ( PG_FUNCTION_ARGS  )

Definition at line 150 of file json.c.

151 {
153  char *str;
154  int nbytes;
155  JsonLexContext lex;
156 
157  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
158 
159  /* Validate it. */
161  false);
163 
165 }
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:153
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:46
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
StringInfoData * StringInfo
Definition: stringinfo.h:54

References buf, cstring_to_text_with_len(), GetDatabaseEncoding(), makeJsonLexContextCstringLen(), nullSemAction, PG_GETARG_POINTER, pg_parse_json_or_ereport, PG_RETURN_TEXT_P, pq_getmsgtext(), and generate_unaccent_rules::str.

◆ json_send()

Datum json_send ( PG_FUNCTION_ARGS  )

Definition at line 136 of file json.c.

137 {
138  text *t = PG_GETARG_TEXT_PP(0);
140 
144 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346

References buf, PG_GETARG_TEXT_PP, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendtext(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ json_typeof()

Datum json_typeof ( PG_FUNCTION_ARGS  )

Definition at line 1712 of file json.c.

1713 {
1714  text *json = PG_GETARG_TEXT_PP(0);
1715  JsonLexContext lex;
1716  char *type;
1717  JsonParseErrorType result;
1718 
1719  /* Lex exactly one token from the input and check its type. */
1720  makeJsonLexContext(&lex, json, false);
1721  result = json_lex(&lex);
1722  if (result != JSON_SUCCESS)
1723  json_errsave_error(result, &lex, NULL);
1724 
1725  switch (lex.token_type)
1726  {
1728  type = "object";
1729  break;
1731  type = "array";
1732  break;
1733  case JSON_TOKEN_STRING:
1734  type = "string";
1735  break;
1736  case JSON_TOKEN_NUMBER:
1737  type = "number";
1738  break;
1739  case JSON_TOKEN_TRUE:
1740  case JSON_TOKEN_FALSE:
1741  type = "boolean";
1742  break;
1743  case JSON_TOKEN_NULL:
1744  type = "null";
1745  break;
1746  default:
1747  elog(ERROR, "unexpected json token: %d", lex.token_type);
1748  }
1749 
1751 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:592
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SUCCESS
Definition: jsonapi.h:38
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
Definition: jsonfuncs.c:638
JsonTokenType token_type
Definition: jsonapi.h:86
const char * type

References cstring_to_text(), elog, ERROR, json_errsave_error(), json_lex(), JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, makeJsonLexContext(), PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, JsonLexContext::token_type, and type.

◆ json_unique_builder_get_throwawaybuf()

static StringInfo json_unique_builder_get_throwawaybuf ( JsonUniqueBuilderState cxt)
static

Definition at line 969 of file json.c.

970 {
971  StringInfo out = &cxt->skipped_keys;
972 
973  if (!out->data)
974  {
976 
977  initStringInfo(out);
978  MemoryContextSwitchTo(oldcxt);
979  }
980  else
981  /* Just reset the string to empty */
982  out->len = 0;
983 
984  return out;
985 }
StringInfoData skipped_keys
Definition: json.c:70
MemoryContext mcxt
Definition: json.c:71

References StringInfoData::data, initStringInfo(), StringInfoData::len, JsonUniqueBuilderState::mcxt, MemoryContextSwitchTo(), and JsonUniqueBuilderState::skipped_keys.

Referenced by json_build_object_worker(), and json_object_agg_transfn_worker().

◆ json_unique_builder_init()

static void json_unique_builder_init ( JsonUniqueBuilderState cxt)
static

Definition at line 941 of file json.c.

942 {
944  cxt->mcxt = CurrentMemoryContext;
945  cxt->skipped_keys.data = NULL;
946 }
static void json_unique_check_init(JsonUniqueCheckState *cxt)
Definition: json.c:923
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131

References JsonUniqueBuilderState::check, CurrentMemoryContext, StringInfoData::data, json_unique_check_init(), JsonUniqueBuilderState::mcxt, and JsonUniqueBuilderState::skipped_keys.

Referenced by json_build_object_worker(), and json_object_agg_transfn_worker().

◆ json_unique_check_init()

static void json_unique_check_init ( JsonUniqueCheckState cxt)
static

Definition at line 923 of file json.c.

924 {
925  HASHCTL ctl;
926 
927  memset(&ctl, 0, sizeof(ctl));
928  ctl.keysize = sizeof(JsonUniqueHashEntry);
929  ctl.entrysize = sizeof(JsonUniqueHashEntry);
931  ctl.hash = json_unique_hash;
933 
934  *cxt = hash_create("json object hashtable",
935  32,
936  &ctl,
938 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#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 uint32 json_unique_hash(const void *key, Size keysize)
Definition: json.c:891
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
Definition: json.c:902
struct JsonUniqueHashEntry JsonUniqueHashEntry
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

References CurrentMemoryContext, HASHCTL::entrysize, HASHCTL::hash, HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_FUNCTION, HASHCTL::hcxt, json_unique_hash(), json_unique_hash_match(), HASHCTL::keysize, and HASHCTL::match.

Referenced by json_unique_builder_init(), and json_validate().

◆ json_unique_check_key()

static bool json_unique_check_key ( JsonUniqueCheckState cxt,
const char *  key,
int  object_id 
)
static

Definition at line 949 of file json.c.

950 {
951  JsonUniqueHashEntry entry;
952  bool found;
953 
954  entry.key = key;
955  entry.key_len = strlen(key);
956  entry.object_id = object_id;
957 
958  (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
959 
960  return !found;
961 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_ENTER
Definition: hsearch.h:114
const char * key
Definition: json.c:44

References HASH_ENTER, hash_search(), JsonUniqueHashEntry::key, sort-test::key, JsonUniqueHashEntry::key_len, and JsonUniqueHashEntry::object_id.

Referenced by json_build_object_worker(), json_object_agg_transfn_worker(), and json_unique_object_field_start().

◆ json_unique_hash()

static uint32 json_unique_hash ( const void *  key,
Size  keysize 
)
static

Definition at line 891 of file json.c.

892 {
893  const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
895 
896  hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
897 
898  return DatumGetUInt32(hash);
899 }
unsigned int uint32
Definition: c.h:493
uint32 hash_bytes_uint32(uint32 k)
Definition: hashfn.c:610
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition: hashfn.c:146
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715

References DatumGetUInt32(), hash(), hash_bytes(), hash_bytes_uint32(), JsonUniqueHashEntry::key, sort-test::key, JsonUniqueHashEntry::key_len, and JsonUniqueHashEntry::object_id.

Referenced by json_unique_check_init().

◆ json_unique_hash_match()

static int json_unique_hash_match ( const void *  key1,
const void *  key2,
Size  keysize 
)
static

Definition at line 902 of file json.c.

903 {
904  const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
905  const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
906 
907  if (entry1->object_id != entry2->object_id)
908  return entry1->object_id > entry2->object_id ? 1 : -1;
909 
910  if (entry1->key_len != entry2->key_len)
911  return entry1->key_len > entry2->key_len ? 1 : -1;
912 
913  return strncmp(entry1->key, entry2->key, entry1->key_len);
914 }

References JsonUniqueHashEntry::key, JsonUniqueHashEntry::key_len, and JsonUniqueHashEntry::object_id.

Referenced by json_unique_check_init().

◆ json_unique_object_end()

static JsonParseErrorType json_unique_object_end ( void *  _state)
static

Definition at line 1610 of file json.c.

1611 {
1612  JsonUniqueParsingState *state = _state;
1613  JsonUniqueStackEntry *entry;
1614 
1615  if (!state->unique)
1616  return JSON_SUCCESS;
1617 
1618  entry = state->stack;
1619  state->stack = entry->parent; /* pop object from stack */
1620  pfree(entry);
1621  return JSON_SUCCESS;
1622 }
struct JsonUniqueStackEntry * parent
Definition: json.c:52

References JSON_SUCCESS, JsonUniqueStackEntry::parent, and pfree().

Referenced by json_validate().

◆ json_unique_object_field_start()

static JsonParseErrorType json_unique_object_field_start ( void *  _state,
char *  field,
bool  isnull 
)
static

Definition at line 1625 of file json.c.

1626 {
1627  JsonUniqueParsingState *state = _state;
1628  JsonUniqueStackEntry *entry;
1629 
1630  if (!state->unique)
1631  return JSON_SUCCESS;
1632 
1633  /* find key collision in the current object */
1634  if (json_unique_check_key(&state->check, field, state->stack->object_id))
1635  return JSON_SUCCESS;
1636 
1637  state->unique = false;
1638 
1639  /* pop all objects entries */
1640  while ((entry = state->stack))
1641  {
1642  state->stack = entry->parent;
1643  pfree(entry);
1644  }
1645  return JSON_SUCCESS;
1646 }

References JSON_SUCCESS, json_unique_check_key(), JsonUniqueStackEntry::parent, and pfree().

Referenced by json_validate().

◆ json_unique_object_start()

static JsonParseErrorType json_unique_object_start ( void *  _state)
static

Definition at line 1592 of file json.c.

1593 {
1594  JsonUniqueParsingState *state = _state;
1595  JsonUniqueStackEntry *entry;
1596 
1597  if (!state->unique)
1598  return JSON_SUCCESS;
1599 
1600  /* push object entry to stack */
1601  entry = palloc(sizeof(*entry));
1602  entry->object_id = state->id_counter++;
1603  entry->parent = state->stack;
1604  state->stack = entry;
1605 
1606  return JSON_SUCCESS;
1607 }

References JSON_SUCCESS, JsonUniqueStackEntry::object_id, palloc(), and JsonUniqueStackEntry::parent.

Referenced by json_validate().

◆ json_validate()

bool json_validate ( text json,
bool  check_unique_keys,
bool  throw_error 
)

Definition at line 1650 of file json.c.

1651 {
1652  JsonLexContext lex;
1653  JsonSemAction uniqueSemAction = {0};
1655  JsonParseErrorType result;
1656 
1657  makeJsonLexContext(&lex, json, check_unique_keys);
1658 
1659  if (check_unique_keys)
1660  {
1661  state.lex = &lex;
1662  state.stack = NULL;
1663  state.id_counter = 0;
1664  state.unique = true;
1665  json_unique_check_init(&state.check);
1666 
1667  uniqueSemAction.semstate = &state;
1668  uniqueSemAction.object_start = json_unique_object_start;
1670  uniqueSemAction.object_end = json_unique_object_end;
1671  }
1672 
1673  result = pg_parse_json(&lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
1674 
1675  if (result != JSON_SUCCESS)
1676  {
1677  if (throw_error)
1678  json_errsave_error(result, &lex, NULL);
1679 
1680  return false; /* invalid json */
1681  }
1682 
1683  if (check_unique_keys && !state.unique)
1684  {
1685  if (throw_error)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1688  errmsg("duplicate JSON object key value")));
1689 
1690  return false; /* not unique keys */
1691  }
1692 
1693  if (check_unique_keys)
1694  freeJsonLexContext(&lex);
1695 
1696  return true; /* ok */
1697 }
static JsonParseErrorType json_unique_object_start(void *_state)
Definition: json.c:1592
static JsonParseErrorType json_unique_object_field_start(void *_state, char *field, bool isnull)
Definition: json.c:1625
static JsonParseErrorType json_unique_object_end(void *_state)
Definition: json.c:1610
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:209
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:186
json_struct_action object_start
Definition: jsonapi.h:121
json_ofield_action object_field_start
Definition: jsonapi.h:125
void * semstate
Definition: jsonapi.h:120
json_struct_action object_end
Definition: jsonapi.h:122

References ereport, errcode(), errmsg(), ERROR, freeJsonLexContext(), json_errsave_error(), JSON_SUCCESS, json_unique_check_init(), json_unique_object_end(), json_unique_object_field_start(), json_unique_object_start(), makeJsonLexContext(), nullSemAction, JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, pg_parse_json(), and JsonSemAction::semstate.

Referenced by ExecEvalJsonConstructor(), and ExecEvalJsonIsPredicate().

◆ JsonEncodeDateTime()

char* JsonEncodeDateTime ( char *  buf,
Datum  value,
Oid  typid,
const int *  tzp 
)

Definition at line 301 of file json.c.

302 {
303  if (!buf)
304  buf = palloc(MAXDATELEN + 1);
305 
306  switch (typid)
307  {
308  case DATEOID:
309  {
310  DateADT date;
311  struct pg_tm tm;
312 
314 
315  /* Same as date_out(), but forcing DateStyle */
316  if (DATE_NOT_FINITE(date))
318  else
319  {
321  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
323  }
324  }
325  break;
326  case TIMEOID:
327  {
328  TimeADT time = DatumGetTimeADT(value);
329  struct pg_tm tt,
330  *tm = &tt;
331  fsec_t fsec;
332 
333  /* Same as time_out(), but forcing DateStyle */
334  time2tm(time, tm, &fsec);
335  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
336  }
337  break;
338  case TIMETZOID:
339  {
341  struct pg_tm tt,
342  *tm = &tt;
343  fsec_t fsec;
344  int tz;
345 
346  /* Same as timetz_out(), but forcing DateStyle */
347  timetz2tm(time, tm, &fsec, &tz);
348  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
349  }
350  break;
351  case TIMESTAMPOID:
352  {
354  struct pg_tm tm;
355  fsec_t fsec;
356 
358  /* Same as timestamp_out(), but forcing DateStyle */
361  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
362  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
363  else
364  ereport(ERROR,
365  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
366  errmsg("timestamp out of range")));
367  }
368  break;
369  case TIMESTAMPTZOID:
370  {
372  struct pg_tm tm;
373  int tz;
374  fsec_t fsec;
375  const char *tzn = NULL;
376 
378 
379  /*
380  * If a time zone is specified, we apply the time-zone shift,
381  * convert timestamptz to pg_tm as if it were without a time
382  * zone, and then use the specified time zone for converting
383  * the timestamp into a string.
384  */
385  if (tzp)
386  {
387  tz = *tzp;
389  }
390 
391  /* Same as timestamptz_out(), but forcing DateStyle */
394  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
395  tzp ? NULL : &tzn, NULL) == 0)
396  {
397  if (tzp)
398  tm.tm_isdst = 1; /* set time-zone presence flag */
399 
400  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
401  }
402  else
403  ereport(ERROR,
404  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
405  errmsg("timestamp out of range")));
406  }
407  break;
408  default:
409  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
410  return NULL;
411  }
412 
413  return buf;
414 }
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4301
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:311
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4331
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4216
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1596
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1901
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define USECS_PER_SEC
Definition: timestamp.h:134
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2403
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1488
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:294
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
static TimeADT DatumGetTimeADT(Datum X)
Definition: date.h:60
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition: date.h:66
int64 TimeADT
Definition: date.h:25
static struct @150 value
static struct pg_tm tm
Definition: localtime.c:104
#define USE_XSD_DATES
Definition: miscadmin.h:238
long date
Definition: pgtypes_date.h:9
int64 timestamp
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
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
static TimestampTz DatumGetTimestampTz(Datum X)
Definition: timestamp.h:34

References buf, DATE_NOT_FINITE, DatumGetDateADT(), DatumGetTimeADT(), DatumGetTimestamp(), DatumGetTimestampTz(), DatumGetTimeTzADTP(), elog, EncodeDateOnly(), EncodeDateTime(), EncodeSpecialDate(), EncodeSpecialTimestamp(), EncodeTimeOnly(), ereport, errcode(), errmsg(), ERROR, j2date(), MAXDATELEN, palloc(), POSTGRES_EPOCH_JDATE, time2tm(), timestamp2tm(), TIMESTAMP_NOT_FINITE, timetz2tm(), tm, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, USE_XSD_DATES, USECS_PER_SEC, and value.

Referenced by convertJsonbScalar(), datum_to_json_internal(), and datum_to_jsonb_internal().

◆ row_to_json()

Datum row_to_json ( PG_FUNCTION_ARGS  )

Definition at line 654 of file json.c.

655 {
656  Datum array = PG_GETARG_DATUM(0);
657  StringInfo result;
658 
659  result = makeStringInfo();
660 
661  composite_to_json(array, result, false);
662 
664 }

References composite_to_json(), cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, makeStringInfo(), PG_GETARG_DATUM, and PG_RETURN_TEXT_P.

◆ row_to_json_pretty()

Datum row_to_json_pretty ( PG_FUNCTION_ARGS  )

Definition at line 670 of file json.c.

671 {
672  Datum array = PG_GETARG_DATUM(0);
673  bool use_line_feeds = PG_GETARG_BOOL(1);
674  StringInfo result;
675 
676  result = makeStringInfo();
677 
678  composite_to_json(array, result, use_line_feeds);
679 
681 }

References composite_to_json(), cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, makeStringInfo(), PG_GETARG_BOOL, PG_GETARG_DATUM, and PG_RETURN_TEXT_P.

◆ to_json()

Datum to_json ( PG_FUNCTION_ARGS  )

Definition at line 730 of file json.c.

731 {
733  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
734  JsonTypeCategory tcategory;
735  Oid outfuncoid;
736 
737  if (val_type == InvalidOid)
738  ereport(ERROR,
739  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
740  errmsg("could not determine input data type")));
741 
742  json_categorize_type(val_type, false,
743  &tcategory, &outfuncoid);
744 
745  PG_RETURN_DATUM(datum_to_json(val, tcategory, outfuncoid));
746 }
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:754

References datum_to_json(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), PG_GETARG_DATUM, PG_RETURN_DATUM, and val.

◆ to_json_is_immutable()

bool to_json_is_immutable ( Oid  typoid)

Definition at line 691 of file json.c.

692 {
693  JsonTypeCategory tcategory;
694  Oid outfuncoid;
695 
696  json_categorize_type(typoid, false, &tcategory, &outfuncoid);
697 
698  switch (tcategory)
699  {
700  case JSONTYPE_BOOL:
701  case JSONTYPE_JSON:
702  case JSONTYPE_JSONB:
703  case JSONTYPE_NULL:
704  return true;
705 
706  case JSONTYPE_DATE:
707  case JSONTYPE_TIMESTAMP:
709  return false;
710 
711  case JSONTYPE_ARRAY:
712  return false; /* TODO recurse into elements */
713 
714  case JSONTYPE_COMPOSITE:
715  return false; /* TODO recurse into fields */
716 
717  case JSONTYPE_NUMERIC:
718  case JSONTYPE_CAST:
719  case JSONTYPE_OTHER:
720  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
721  }
722 
723  return false; /* not reached */
724 }
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:80
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:76
char func_volatile(Oid funcid)
Definition: lsyscache.c:1758

References func_volatile(), json_categorize_type(), JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_JSONB, JSONTYPE_NULL, JSONTYPE_NUMERIC, JSONTYPE_OTHER, JSONTYPE_TIMESTAMP, and JSONTYPE_TIMESTAMPTZ.

Referenced by contain_mutable_functions_walker().