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, Datum *args, bool *nulls, 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, Datum *args, bool *nulls, 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 569 of file json.c.

571 {
572  JsonTypeCategory tcategory;
573  Oid outfuncoid;
574 
575  if (val_type == InvalidOid)
576  ereport(ERROR,
577  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
578  errmsg("could not determine input data type")));
579 
580  if (is_null)
581  {
582  tcategory = JSONTYPE_NULL;
583  outfuncoid = InvalidOid;
584  }
585  else
586  json_categorize_type(val_type, false,
587  &tcategory, &outfuncoid);
588 
589  datum_to_json_internal(val, is_null, result, tcategory, outfuncoid,
590  key_scalar);
591 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
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:176
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5698
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 404 of file json.c.

407 {
408  int i;
409  const char *sep;
410 
411  Assert(dim < ndims);
412 
413  sep = use_line_feeds ? ",\n " : ",";
414 
415  appendStringInfoChar(result, '[');
416 
417  for (i = 1; i <= dims[dim]; i++)
418  {
419  if (i > 1)
420  appendStringInfoString(result, sep);
421 
422  if (dim + 1 == ndims)
423  {
424  datum_to_json_internal(vals[*valcount], nulls[*valcount],
425  result, tcategory,
426  outfuncoid, false);
427  (*valcount)++;
428  }
429  else
430  {
431  /*
432  * Do we want line feeds on inner dimensions of arrays? For now
433  * we'll say no.
434  */
435  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
436  valcount, tcategory, outfuncoid, false);
437  }
438  }
439 
440  appendStringInfoChar(result, ']');
441 }
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:404
Assert(fmt[strlen(fmt) - 1] !='\n')
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188

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 597 of file json.c.

598 {
599  Datum array = PG_GETARG_DATUM(0);
600  StringInfo result;
601 
602  result = makeStringInfo();
603 
604  array_to_json_internal(array, result, false);
605 
607 }
#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:447
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:194

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 447 of file json.c.

448 {
449  ArrayType *v = DatumGetArrayTypeP(array);
450  Oid element_type = ARR_ELEMTYPE(v);
451  int *dim;
452  int ndim;
453  int nitems;
454  int count = 0;
455  Datum *elements;
456  bool *nulls;
457  int16 typlen;
458  bool typbyval;
459  char typalign;
460  JsonTypeCategory tcategory;
461  Oid outfuncoid;
462 
463  ndim = ARR_NDIM(v);
464  dim = ARR_DIMS(v);
465  nitems = ArrayGetNItems(ndim, dim);
466 
467  if (nitems <= 0)
468  {
469  appendStringInfoString(result, "[]");
470  return;
471  }
472 
473  get_typlenbyvalalign(element_type,
474  &typlen, &typbyval, &typalign);
475 
476  json_categorize_type(element_type, false,
477  &tcategory, &outfuncoid);
478 
479  deconstruct_array(v, element_type, typlen, typbyval,
480  typalign, &elements, &nulls,
481  &nitems);
482 
483  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
484  outfuncoid, use_line_feeds);
485 
486  pfree(elements);
487  pfree(nulls);
488 }
#define ARR_NDIM(a)
Definition: array.h:283
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3578
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:482
#define nitems(x)
Definition: indent.h:31
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2253
void pfree(void *pointer)
Definition: mcxt.c:1456
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 613 of file json.c.

614 {
615  Datum array = PG_GETARG_DATUM(0);
616  bool use_line_feeds = PG_GETARG_BOOL(1);
617  StringInfo result;
618 
619  result = makeStringInfo();
620 
621  array_to_json_internal(array, result, use_line_feeds);
622 
624 }
#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 1169 of file json.c.

1170 {
1171  /* custom version of cstring_to_text_with_len */
1172  int buflen = buffer->len;
1173  int addlen = strlen(addon);
1174  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
1175 
1176  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
1177  memcpy(VARDATA(result), buffer->data, buflen);
1178  memcpy(VARDATA(result) + buflen, addon, addlen);
1179 
1180  return result;
1181 }
#define VARHDRSZ
Definition: c.h:681
void * palloc(Size size)
Definition: mcxt.c:1226
Definition: c.h:676
#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 494 of file json.c.

495 {
496  HeapTupleHeader td;
497  Oid tupType;
498  int32 tupTypmod;
499  TupleDesc tupdesc;
500  HeapTupleData tmptup,
501  *tuple;
502  int i;
503  bool needsep = false;
504  const char *sep;
505 
506  sep = use_line_feeds ? ",\n " : ",";
507 
508  td = DatumGetHeapTupleHeader(composite);
509 
510  /* Extract rowtype info and find a tupdesc */
511  tupType = HeapTupleHeaderGetTypeId(td);
512  tupTypmod = HeapTupleHeaderGetTypMod(td);
513  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
514 
515  /* Build a temporary HeapTuple control structure */
517  tmptup.t_data = td;
518  tuple = &tmptup;
519 
520  appendStringInfoChar(result, '{');
521 
522  for (i = 0; i < tupdesc->natts; i++)
523  {
524  Datum val;
525  bool isnull;
526  char *attname;
527  JsonTypeCategory tcategory;
528  Oid outfuncoid;
529  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
530 
531  if (att->attisdropped)
532  continue;
533 
534  if (needsep)
535  appendStringInfoString(result, sep);
536  needsep = true;
537 
538  attname = NameStr(att->attname);
539  escape_json(result, attname);
540  appendStringInfoChar(result, ':');
541 
542  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
543 
544  if (isnull)
545  {
546  tcategory = JSONTYPE_NULL;
547  outfuncoid = InvalidOid;
548  }
549  else
550  json_categorize_type(att->atttypid, false, &tcategory,
551  &outfuncoid);
552 
553  datum_to_json_internal(val, isnull, result, tcategory, outfuncoid,
554  false);
555  }
556 
557  appendStringInfoChar(result, '}');
558  ReleaseTupleDesc(tupdesc);
559 }
#define NameStr(name)
Definition: c.h:735
signed int int32
Definition: c.h:483
#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:1525
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
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:1830

References appendStringInfoChar(), appendStringInfoString(), 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 730 of file json.c.

731 {
732  StringInfo result = makeStringInfo();
733 
734  datum_to_json_internal(val, false, result, tcategory, outfuncoid,
735  false);
736 
737  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
738 }
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 176 of file json.c.

179 {
180  char *outputstr;
181  text *jsontext;
182 
184 
185  /* callers are expected to ensure that null keys are not passed in */
186  Assert(!(key_scalar && is_null));
187 
188  if (is_null)
189  {
190  appendStringInfoString(result, "null");
191  return;
192  }
193 
194  if (key_scalar &&
195  (tcategory == JSONTYPE_ARRAY ||
196  tcategory == JSONTYPE_COMPOSITE ||
197  tcategory == JSONTYPE_JSON ||
198  tcategory == JSONTYPE_CAST))
199  ereport(ERROR,
200  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
201  errmsg("key value must be scalar, not array, composite, or json")));
202 
203  switch (tcategory)
204  {
205  case JSONTYPE_ARRAY:
206  array_to_json_internal(val, result, false);
207  break;
208  case JSONTYPE_COMPOSITE:
209  composite_to_json(val, result, false);
210  break;
211  case JSONTYPE_BOOL:
212  outputstr = DatumGetBool(val) ? "true" : "false";
213  if (key_scalar)
214  escape_json(result, outputstr);
215  else
216  appendStringInfoString(result, outputstr);
217  break;
218  case JSONTYPE_NUMERIC:
219  outputstr = OidOutputFunctionCall(outfuncoid, val);
220 
221  /*
222  * Don't call escape_json for a non-key if it's a valid JSON
223  * number.
224  */
225  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
226  appendStringInfoString(result, outputstr);
227  else
228  escape_json(result, outputstr);
229  pfree(outputstr);
230  break;
231  case JSONTYPE_DATE:
232  {
233  char buf[MAXDATELEN + 1];
234 
235  JsonEncodeDateTime(buf, val, DATEOID, NULL);
236  appendStringInfo(result, "\"%s\"", buf);
237  }
238  break;
239  case JSONTYPE_TIMESTAMP:
240  {
241  char buf[MAXDATELEN + 1];
242 
243  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
244  appendStringInfo(result, "\"%s\"", buf);
245  }
246  break;
248  {
249  char buf[MAXDATELEN + 1];
250 
251  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
252  appendStringInfo(result, "\"%s\"", buf);
253  }
254  break;
255  case JSONTYPE_JSON:
256  /* JSON and JSONB output will already be escaped */
257  outputstr = OidOutputFunctionCall(outfuncoid, val);
258  appendStringInfoString(result, outputstr);
259  pfree(outputstr);
260  break;
261  case JSONTYPE_CAST:
262  /* outfuncoid refers to a cast function, not an output function */
263  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
264  outputstr = text_to_cstring(jsontext);
265  appendStringInfoString(result, outputstr);
266  pfree(outputstr);
267  pfree(jsontext);
268  break;
269  default:
270  outputstr = OidOutputFunctionCall(outfuncoid, val);
271  escape_json(result, outputstr);
272  pfree(outputstr);
273  break;
274  }
275 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1746
#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:283
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:494
bool IsValidJsonNumber(const char *str, int len)
Definition: jsonapi.c:105
@ 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:67
void check_stack_depth(void)
Definition: postgres.c:3523
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
char * text_to_cstring(const text *t)
Definition: varlena.c:215

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

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

void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 1525 of file json.c.

1526 {
1527  const char *p;
1528 
1530  for (p = str; *p; p++)
1531  {
1532  switch (*p)
1533  {
1534  case '\b':
1535  appendStringInfoString(buf, "\\b");
1536  break;
1537  case '\f':
1538  appendStringInfoString(buf, "\\f");
1539  break;
1540  case '\n':
1541  appendStringInfoString(buf, "\\n");
1542  break;
1543  case '\r':
1544  appendStringInfoString(buf, "\\r");
1545  break;
1546  case '\t':
1547  appendStringInfoString(buf, "\\t");
1548  break;
1549  case '"':
1550  appendStringInfoString(buf, "\\\"");
1551  break;
1552  case '\\':
1553  appendStringInfoString(buf, "\\\\");
1554  break;
1555  default:
1556  if ((unsigned char) *p < ' ')
1557  appendStringInfo(buf, "\\u%04x", (int) *p);
1558  else
1560  break;
1561  }
1562  }
1564 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128

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 846 of file json.c.

847 {
849 
850  /* cannot be called directly because of internal-type argument */
851  Assert(AggCheckCallContext(fcinfo, NULL));
852 
853  state = PG_ARGISNULL(0) ?
854  NULL :
856 
857  /* NULL result for no rows in, as is standard with aggregates */
858  if (state == NULL)
859  PG_RETURN_NULL();
860 
861  /* Else return state with appropriate array terminator added */
863 }
#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:1169
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4522
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 837 of file json.c.

838 {
839  return json_agg_transfn_worker(fcinfo, true);
840 }
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: json.c:746

References json_agg_transfn_worker().

◆ json_agg_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 828 of file json.c.

829 {
830  return json_agg_transfn_worker(fcinfo, false);
831 }

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 746 of file json.c.

747 {
748  MemoryContext aggcontext,
749  oldcontext;
751  Datum val;
752 
753  if (!AggCheckCallContext(fcinfo, &aggcontext))
754  {
755  /* cannot be called directly because of internal-type argument */
756  elog(ERROR, "json_agg_transfn called in non-aggregate context");
757  }
758 
759  if (PG_ARGISNULL(0))
760  {
761  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
762 
763  if (arg_type == InvalidOid)
764  ereport(ERROR,
765  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
766  errmsg("could not determine input data type")));
767 
768  /*
769  * Make this state object in a context where it will persist for the
770  * duration of the aggregate call. MemoryContextSwitchTo is only
771  * needed the first time, as the StringInfo routines make sure they
772  * use the right context to enlarge the object if necessary.
773  */
774  oldcontext = MemoryContextSwitchTo(aggcontext);
775  state = (JsonAggState *) palloc(sizeof(JsonAggState));
776  state->str = makeStringInfo();
777  MemoryContextSwitchTo(oldcontext);
778 
779  appendStringInfoChar(state->str, '[');
780  json_categorize_type(arg_type, false, &state->val_category,
781  &state->val_output_func);
782  }
783  else
784  {
786  }
787 
788  if (absent_on_null && PG_ARGISNULL(1))
790 
791  if (state->str->len > 1)
792  appendStringInfoString(state->str, ", ");
793 
794  /* fast path for NULLs */
795  if (PG_ARGISNULL(1))
796  {
798  InvalidOid, false);
800  }
801 
802  val = PG_GETARG_DATUM(1);
803 
804  /* add some whitespace if structured type and not first item */
805  if (!PG_ARGISNULL(0) && state->str->len > 1 &&
806  (state->val_category == JSONTYPE_ARRAY ||
807  state->val_category == JSONTYPE_COMPOSITE))
808  {
809  appendStringInfoString(state->str, "\n ");
810  }
811 
812  datum_to_json_internal(val, false, state->str, state->val_category,
813  state->val_output_func, false);
814 
815  /*
816  * The transition type for json_agg() is declared to be "internal", which
817  * is a pass-by-value type the same size as a pointer. So we can safely
818  * pass the JsonAggState pointer through nodeAgg.c's machinations.
819  */
821 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1893
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
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 1327 of file json.c.

1328 {
1329  Datum *args;
1330  bool *nulls;
1331  Oid *types;
1332 
1333  /* build argument values to build the object */
1334  int nargs = extract_variadic_args(fcinfo, 0, true,
1335  &args, &types, &nulls);
1336 
1337  if (nargs < 0)
1338  PG_RETURN_NULL();
1339 
1340  PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
1341 }
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, Datum *args, bool *nulls, Oid *types, bool absent_on_null)
Definition: json.c:1297

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 1347 of file json.c.

1348 {
1350 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_build_array_worker()

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

Definition at line 1297 of file json.c.

1299 {
1300  int i;
1301  const char *sep = "";
1302  StringInfo result;
1303 
1304  result = makeStringInfo();
1305 
1306  appendStringInfoChar(result, '[');
1307 
1308  for (i = 0; i < nargs; i++)
1309  {
1310  if (absent_on_null && nulls[i])
1311  continue;
1312 
1313  appendStringInfoString(result, sep);
1314  sep = ", ";
1315  add_json(args[i], nulls[i], result, types[i], false);
1316  }
1317 
1318  appendStringInfoChar(result, ']');
1319 
1320  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1321 }
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:569

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 1271 of file json.c.

1272 {
1273  Datum *args;
1274  bool *nulls;
1275  Oid *types;
1276 
1277  /* build argument values to build the object */
1278  int nargs = extract_variadic_args(fcinfo, 0, true,
1279  &args, &types, &nulls);
1280 
1281  if (nargs < 0)
1282  PG_RETURN_NULL();
1283 
1284  PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
1285 }
Datum json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1184

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 1291 of file json.c.

1292 {
1294 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_build_object_worker()

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

Definition at line 1184 of file json.c.

1186 {
1187  int i;
1188  const char *sep = "";
1189  StringInfo result;
1190  JsonUniqueBuilderState unique_check;
1191 
1192  if (nargs % 2 != 0)
1193  ereport(ERROR,
1194  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1195  errmsg("argument list must have even number of elements"),
1196  /* translator: %s is a SQL function name */
1197  errhint("The arguments of %s must consist of alternating keys and values.",
1198  "json_build_object()")));
1199 
1200  result = makeStringInfo();
1201 
1202  appendStringInfoChar(result, '{');
1203 
1204  if (unique_keys)
1205  json_unique_builder_init(&unique_check);
1206 
1207  for (i = 0; i < nargs; i += 2)
1208  {
1209  StringInfo out;
1210  bool skip;
1211  int key_offset;
1212 
1213  /* Skip null values if absent_on_null */
1214  skip = absent_on_null && nulls[i + 1];
1215 
1216  if (skip)
1217  {
1218  /* If key uniqueness check is needed we must save skipped keys */
1219  if (!unique_keys)
1220  continue;
1221 
1222  out = json_unique_builder_get_throwawaybuf(&unique_check);
1223  }
1224  else
1225  {
1226  appendStringInfoString(result, sep);
1227  sep = ", ";
1228  out = result;
1229  }
1230 
1231  /* process key */
1232  if (nulls[i])
1233  ereport(ERROR,
1234  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1235  errmsg("null value not allowed for object key")));
1236 
1237  /* save key offset before appending it */
1238  key_offset = out->len;
1239 
1240  add_json(args[i], false, out, types[i], true);
1241 
1242  if (unique_keys)
1243  {
1244  /* check key uniqueness after key appending */
1245  const char *key = &out->data[key_offset];
1246 
1247  if (!json_unique_check_key(&unique_check.check, key, 0))
1248  ereport(ERROR,
1249  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1250  errmsg("duplicate JSON object key value: %s", key));
1251 
1252  if (skip)
1253  continue;
1254  }
1255 
1256  appendStringInfoString(result, " : ");
1257 
1258  /* process value */
1259  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1260  }
1261 
1262  appendStringInfoChar(result, '}');
1263 
1264  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1265 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
static StringInfo json_unique_builder_get_throwawaybuf(JsonUniqueBuilderState *cxt)
Definition: json.c:945
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
Definition: json.c:925
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Definition: json.c:917
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  lex = makeJsonLexContext(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(text *json, bool need_escapes)
Definition: jsonfuncs.c:529
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:508
text * cstring_to_text(const char *s)
Definition: varlena.c:182

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 1359 of file json.c.

1360 {
1361  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1362  int ndims = ARR_NDIM(in_array);
1363  StringInfoData result;
1364  Datum *in_datums;
1365  bool *in_nulls;
1366  int in_count,
1367  count,
1368  i;
1369  text *rval;
1370  char *v;
1371 
1372  switch (ndims)
1373  {
1374  case 0:
1376  break;
1377 
1378  case 1:
1379  if ((ARR_DIMS(in_array)[0]) % 2)
1380  ereport(ERROR,
1381  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1382  errmsg("array must have even number of elements")));
1383  break;
1384 
1385  case 2:
1386  if ((ARR_DIMS(in_array)[1]) != 2)
1387  ereport(ERROR,
1388  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1389  errmsg("array must have two columns")));
1390  break;
1391 
1392  default:
1393  ereport(ERROR,
1394  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1395  errmsg("wrong number of array subscripts")));
1396  }
1397 
1398  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1399 
1400  count = in_count / 2;
1401 
1402  initStringInfo(&result);
1403 
1404  appendStringInfoChar(&result, '{');
1405 
1406  for (i = 0; i < count; ++i)
1407  {
1408  if (in_nulls[i * 2])
1409  ereport(ERROR,
1410  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1411  errmsg("null value not allowed for object key")));
1412 
1413  v = TextDatumGetCString(in_datums[i * 2]);
1414  if (i > 0)
1415  appendStringInfoString(&result, ", ");
1416  escape_json(&result, v);
1417  appendStringInfoString(&result, " : ");
1418  pfree(v);
1419  if (in_nulls[i * 2 + 1])
1420  appendStringInfoString(&result, "null");
1421  else
1422  {
1423  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1424  escape_json(&result, v);
1425  pfree(v);
1426  }
1427  }
1428 
1429  appendStringInfoChar(&result, '}');
1430 
1431  pfree(in_datums);
1432  pfree(in_nulls);
1433 
1434  rval = cstring_to_text_with_len(result.data, result.len);
1435  pfree(result.data);
1436 
1437  PG_RETURN_TEXT_P(rval);
1438 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3644
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define TextDatumGetCString(d)
Definition: builtins.h:95
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 1146 of file json.c.

1147 {
1149 
1150  /* cannot be called directly because of internal-type argument */
1151  Assert(AggCheckCallContext(fcinfo, NULL));
1152 
1153  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
1154 
1155  /* NULL result for no rows in, as is standard with aggregates */
1156  if (state == NULL)
1157  PG_RETURN_NULL();
1158 
1159  /* Else return state with appropriate object terminator added */
1161 }

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 1119 of file json.c.

1120 {
1121  return json_object_agg_transfn_worker(fcinfo, true, false);
1122 }
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: json.c:969

References json_object_agg_transfn_worker().

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1110 of file json.c.

1111 {
1112  return json_object_agg_transfn_worker(fcinfo, false, false);
1113 }

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 969 of file json.c.

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

1138 {
1139  return json_object_agg_transfn_worker(fcinfo, true, true);
1140 }

References json_object_agg_transfn_worker().

◆ json_object_agg_unique_transfn()

Datum json_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1128 of file json.c.

1129 {
1130  return json_object_agg_transfn_worker(fcinfo, false, true);
1131 }

References json_object_agg_transfn_worker().

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1447 of file json.c.

1448 {
1449  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1450  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1451  int nkdims = ARR_NDIM(key_array);
1452  int nvdims = ARR_NDIM(val_array);
1453  StringInfoData result;
1454  Datum *key_datums,
1455  *val_datums;
1456  bool *key_nulls,
1457  *val_nulls;
1458  int key_count,
1459  val_count,
1460  i;
1461  text *rval;
1462  char *v;
1463 
1464  if (nkdims > 1 || nkdims != nvdims)
1465  ereport(ERROR,
1466  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1467  errmsg("wrong number of array subscripts")));
1468 
1469  if (nkdims == 0)
1471 
1472  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1473  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1474 
1475  if (key_count != val_count)
1476  ereport(ERROR,
1477  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1478  errmsg("mismatched array dimensions")));
1479 
1480  initStringInfo(&result);
1481 
1482  appendStringInfoChar(&result, '{');
1483 
1484  for (i = 0; i < key_count; ++i)
1485  {
1486  if (key_nulls[i])
1487  ereport(ERROR,
1488  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1489  errmsg("null value not allowed for object key")));
1490 
1491  v = TextDatumGetCString(key_datums[i]);
1492  if (i > 0)
1493  appendStringInfoString(&result, ", ");
1494  escape_json(&result, v);
1495  appendStringInfoString(&result, " : ");
1496  pfree(v);
1497  if (val_nulls[i])
1498  appendStringInfoString(&result, "null");
1499  else
1500  {
1501  v = TextDatumGetCString(val_datums[i]);
1502  escape_json(&result, v);
1503  pfree(v);
1504  }
1505  }
1506 
1507  appendStringInfoChar(&result, '}');
1508 
1509  pfree(key_datums);
1510  pfree(key_nulls);
1511  pfree(val_datums);
1512  pfree(val_nulls);
1513 
1514  rval = cstring_to_text_with_len(result.data, result.len);
1515  pfree(result.data);
1516 
1517  PG_RETURN_TEXT_P(rval);
1518 }

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. */
160  lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false);
162 
164 }
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:145
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:46
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:549
StringInfoData * StringInfo
Definition: stringinfo.h:44

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:175
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:329
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:349
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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 1683 of file json.c.

1684 {
1685  text *json = PG_GETARG_TEXT_PP(0);
1686  JsonLexContext *lex = makeJsonLexContext(json, false);
1687  char *type;
1688  JsonTokenType tok;
1689  JsonParseErrorType result;
1690 
1691  /* Lex exactly one token from the input and check its type. */
1692  result = json_lex(lex);
1693  if (result != JSON_SUCCESS)
1694  json_errsave_error(result, lex, NULL);
1695  tok = lex->token_type;
1696 
1697  switch (tok)
1698  {
1700  type = "object";
1701  break;
1703  type = "array";
1704  break;
1705  case JSON_TOKEN_STRING:
1706  type = "string";
1707  break;
1708  case JSON_TOKEN_NUMBER:
1709  type = "number";
1710  break;
1711  case JSON_TOKEN_TRUE:
1712  case JSON_TOKEN_FALSE:
1713  type = "boolean";
1714  break;
1715  case JSON_TOKEN_NULL:
1716  type = "null";
1717  break;
1718  default:
1719  elog(ERROR, "unexpected json token: %d", tok);
1720  }
1721 
1723 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:552
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SUCCESS
Definition: jsonapi.h:38
JsonTokenType
Definition: jsonapi.h:20
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
Definition: jsonfuncs.c:629
JsonTokenType token_type
Definition: jsonapi.h:82
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 945 of file json.c.

946 {
947  StringInfo out = &cxt->skipped_keys;
948 
949  if (!out->data)
950  {
952 
953  initStringInfo(out);
954  MemoryContextSwitchTo(oldcxt);
955  }
956  else
957  /* Just reset the string to empty */
958  out->len = 0;
959 
960  return out;
961 }
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 917 of file json.c.

918 {
920  cxt->mcxt = CurrentMemoryContext;
921  cxt->skipped_keys.data = NULL;
922 }
static void json_unique_check_init(JsonUniqueCheckState *cxt)
Definition: json.c:899
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135

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 899 of file json.c.

900 {
901  HASHCTL ctl;
902 
903  memset(&ctl, 0, sizeof(ctl));
904  ctl.keysize = sizeof(JsonUniqueHashEntry);
905  ctl.entrysize = sizeof(JsonUniqueHashEntry);
907  ctl.hash = json_unique_hash;
909 
910  *cxt = hash_create("json object hashtable",
911  32,
912  &ctl,
914 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#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:867
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
Definition: json.c:878
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 925 of file json.c.

926 {
927  JsonUniqueHashEntry entry;
928  bool found;
929 
930  entry.key = key;
931  entry.key_len = strlen(key);
932  entry.object_id = object_id;
933 
934  (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
935 
936  return !found;
937 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
@ 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 867 of file json.c.

868 {
869  const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
871 
872  hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
873 
874  return DatumGetUInt32(hash);
875 }
unsigned int uint32
Definition: c.h:495
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 878 of file json.c.

879 {
880  const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
881  const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
882 
883  if (entry1->object_id != entry2->object_id)
884  return entry1->object_id > entry2->object_id ? 1 : -1;
885 
886  if (entry1->key_len != entry2->key_len)
887  return entry1->key_len > entry2->key_len ? 1 : -1;
888 
889  return strncmp(entry1->key, entry2->key, entry1->key_len);
890 }

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 1586 of file json.c.

1587 {
1588  JsonUniqueParsingState *state = _state;
1589  JsonUniqueStackEntry *entry;
1590 
1591  if (!state->unique)
1592  return JSON_SUCCESS;
1593 
1594  entry = state->stack;
1595  state->stack = entry->parent; /* pop object from stack */
1596  pfree(entry);
1597  return JSON_SUCCESS;
1598 }
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 1601 of file json.c.

1602 {
1603  JsonUniqueParsingState *state = _state;
1604  JsonUniqueStackEntry *entry;
1605 
1606  if (!state->unique)
1607  return JSON_SUCCESS;
1608 
1609  /* find key collision in the current object */
1610  if (json_unique_check_key(&state->check, field, state->stack->object_id))
1611  return JSON_SUCCESS;
1612 
1613  state->unique = false;
1614 
1615  /* pop all objects entries */
1616  while ((entry = state->stack))
1617  {
1618  state->stack = entry->parent;
1619  pfree(entry);
1620  }
1621  return JSON_SUCCESS;
1622 }

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 1568 of file json.c.

1569 {
1570  JsonUniqueParsingState *state = _state;
1571  JsonUniqueStackEntry *entry;
1572 
1573  if (!state->unique)
1574  return JSON_SUCCESS;
1575 
1576  /* push object entry to stack */
1577  entry = palloc(sizeof(*entry));
1578  entry->object_id = state->id_counter++;
1579  entry->parent = state->stack;
1580  state->stack = entry;
1581 
1582  return JSON_SUCCESS;
1583 }

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 1626 of file json.c.

1627 {
1628  JsonLexContext *lex = makeJsonLexContext(json, check_unique_keys);
1629  JsonSemAction uniqueSemAction = {0};
1631  JsonParseErrorType result;
1632 
1633  if (check_unique_keys)
1634  {
1635  state.lex = lex;
1636  state.stack = NULL;
1637  state.id_counter = 0;
1638  state.unique = true;
1639  json_unique_check_init(&state.check);
1640 
1641  uniqueSemAction.semstate = &state;
1642  uniqueSemAction.object_start = json_unique_object_start;
1644  uniqueSemAction.object_end = json_unique_object_end;
1645  }
1646 
1647  result = pg_parse_json(lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
1648 
1649  if (result != JSON_SUCCESS)
1650  {
1651  if (throw_error)
1652  json_errsave_error(result, lex, NULL);
1653 
1654  return false; /* invalid json */
1655  }
1656 
1657  if (check_unique_keys && !state.unique)
1658  {
1659  if (throw_error)
1660  ereport(ERROR,
1661  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1662  errmsg("duplicate JSON object key value")));
1663 
1664  return false; /* not unique keys */
1665  }
1666 
1667  return true; /* ok */
1668 }
static JsonParseErrorType json_unique_object_start(void *_state)
Definition: json.c:1568
static JsonParseErrorType json_unique_object_field_start(void *_state, char *field, bool isnull)
Definition: json.c:1601
static JsonParseErrorType json_unique_object_end(void *_state)
Definition: json.c:1586
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:169
json_struct_action object_start
Definition: jsonapi.h:115
json_ofield_action object_field_start
Definition: jsonapi.h:119
void * semstate
Definition: jsonapi.h:114
json_struct_action object_end
Definition: jsonapi.h:116

References ereport, errcode(), errmsg(), ERROR, 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 283 of file json.c.

284 {
285  if (!buf)
286  buf = palloc(MAXDATELEN + 1);
287 
288  switch (typid)
289  {
290  case DATEOID:
291  {
292  DateADT date;
293  struct pg_tm tm;
294 
296 
297  /* Same as date_out(), but forcing DateStyle */
298  if (DATE_NOT_FINITE(date))
300  else
301  {
303  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
305  }
306  }
307  break;
308  case TIMEOID:
309  {
310  TimeADT time = DatumGetTimeADT(value);
311  struct pg_tm tt,
312  *tm = &tt;
313  fsec_t fsec;
314 
315  /* Same as time_out(), but forcing DateStyle */
316  time2tm(time, tm, &fsec);
317  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
318  }
319  break;
320  case TIMETZOID:
321  {
323  struct pg_tm tt,
324  *tm = &tt;
325  fsec_t fsec;
326  int tz;
327 
328  /* Same as timetz_out(), but forcing DateStyle */
329  timetz2tm(time, tm, &fsec, &tz);
330  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
331  }
332  break;
333  case TIMESTAMPOID:
334  {
336  struct pg_tm tm;
337  fsec_t fsec;
338 
340  /* Same as timestamp_out(), but forcing DateStyle */
343  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
344  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
345  else
346  ereport(ERROR,
347  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
348  errmsg("timestamp out of range")));
349  }
350  break;
351  case TIMESTAMPTZOID:
352  {
354  struct pg_tm tm;
355  int tz;
356  fsec_t fsec;
357  const char *tzn = NULL;
358 
360 
361  /*
362  * If a time zone is specified, we apply the time-zone shift,
363  * convert timestamptz to pg_tm as if it were without a time
364  * zone, and then use the specified time zone for converting
365  * the timestamp into a string.
366  */
367  if (tzp)
368  {
369  tz = *tzp;
371  }
372 
373  /* Same as timestamptz_out(), but forcing DateStyle */
376  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
377  tzp ? NULL : &tzn, NULL) == 0)
378  {
379  if (tzp)
380  tm.tm_isdst = 1; /* set time-zone presence flag */
381 
382  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
383  }
384  else
385  ereport(ERROR,
386  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
387  errmsg("timestamp out of range")));
388  }
389  break;
390  default:
391  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
392  return NULL;
393  }
394 
395  return buf;
396 }
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4201
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:313
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4231
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4116
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1536
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define USECS_PER_SEC
Definition: timestamp.h:133
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:168
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2394
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1487
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:293
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
static TimeADT DatumGetTimeADT(Datum X)
Definition: date.h:60
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition: date.h:66
int64 TimeADT
Definition: date.h:25
static struct @148 value
static struct pg_tm tm
Definition: localtime.c:104
#define USE_XSD_DATES
Definition: miscadmin.h:233
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 630 of file json.c.

631 {
632  Datum array = PG_GETARG_DATUM(0);
633  StringInfo result;
634 
635  result = makeStringInfo();
636 
637  composite_to_json(array, result, false);
638 
640 }

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 646 of file json.c.

647 {
648  Datum array = PG_GETARG_DATUM(0);
649  bool use_line_feeds = PG_GETARG_BOOL(1);
650  StringInfo result;
651 
652  result = makeStringInfo();
653 
654  composite_to_json(array, result, use_line_feeds);
655 
657 }

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 706 of file json.c.

707 {
709  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
710  JsonTypeCategory tcategory;
711  Oid outfuncoid;
712 
713  if (val_type == InvalidOid)
714  ereport(ERROR,
715  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
716  errmsg("could not determine input data type")));
717 
718  json_categorize_type(val_type, false,
719  &tcategory, &outfuncoid);
720 
721  PG_RETURN_DATUM(datum_to_json(val, tcategory, outfuncoid));
722 }
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:730

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 667 of file json.c.

668 {
669  JsonTypeCategory tcategory;
670  Oid outfuncoid;
671 
672  json_categorize_type(typoid, false, &tcategory, &outfuncoid);
673 
674  switch (tcategory)
675  {
676  case JSONTYPE_BOOL:
677  case JSONTYPE_JSON:
678  case JSONTYPE_JSONB:
679  case JSONTYPE_NULL:
680  return true;
681 
682  case JSONTYPE_DATE:
683  case JSONTYPE_TIMESTAMP:
685  return false;
686 
687  case JSONTYPE_ARRAY:
688  return false; /* TODO recurse into elements */
689 
690  case JSONTYPE_COMPOSITE:
691  return false; /* TODO recurse into fields */
692 
693  case JSONTYPE_NUMERIC:
694  case JSONTYPE_CAST:
695  case JSONTYPE_OTHER:
696  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
697  }
698 
699  return false; /* not reached */
700 }
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:80
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:76
char func_volatile(Oid funcid)
Definition: lsyscache.c:1784

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().