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 "parser/parse_coerce.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
 

Enumerations

enum  JsonTypeCategory {
  JSONTYPE_NULL , JSONTYPE_BOOL , JSONTYPE_NUMERIC , JSONTYPE_DATE ,
  JSONTYPE_TIMESTAMP , JSONTYPE_TIMESTAMPTZ , JSONTYPE_JSON , JSONTYPE_ARRAY ,
  JSONTYPE_COMPOSITE , JSONTYPE_CAST , JSONTYPE_OTHER
}
 

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 json_categorize_type (Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
 
static void datum_to_json (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)
 
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 55 of file json.c.

◆ JsonUniqueHashEntry

◆ JsonUniqueParsingState

◆ JsonUniqueStackEntry

Enumeration Type Documentation

◆ JsonTypeCategory

Enumerator
JSONTYPE_NULL 
JSONTYPE_BOOL 
JSONTYPE_NUMERIC 
JSONTYPE_DATE 
JSONTYPE_TIMESTAMP 
JSONTYPE_TIMESTAMPTZ 
JSONTYPE_JSON 
JSONTYPE_ARRAY 
JSONTYPE_COMPOSITE 
JSONTYPE_CAST 
JSONTYPE_OTHER 

Definition at line 32 of file json.c.

33 {
34  JSONTYPE_NULL, /* null, so we didn't bother to identify */
35  JSONTYPE_BOOL, /* boolean (built-in types only) */
36  JSONTYPE_NUMERIC, /* numeric (ditto) */
37  JSONTYPE_DATE, /* we use special formatting for datetimes */
40  JSONTYPE_JSON, /* JSON itself (and JSONB) */
41  JSONTYPE_ARRAY, /* array */
42  JSONTYPE_COMPOSITE, /* composite */
43  JSONTYPE_CAST, /* something with an explicit cast to JSON */
44  JSONTYPE_OTHER /* all else */
JsonTypeCategory
Definition: json.c:33
@ JSONTYPE_JSON
Definition: json.c:40
@ JSONTYPE_NULL
Definition: json.c:34
@ JSONTYPE_TIMESTAMP
Definition: json.c:38
@ JSONTYPE_NUMERIC
Definition: json.c:36
@ JSONTYPE_DATE
Definition: json.c:37
@ JSONTYPE_BOOL
Definition: json.c:35
@ JSONTYPE_OTHER
Definition: json.c:44
@ JSONTYPE_CAST
Definition: json.c:43
@ JSONTYPE_COMPOSITE
Definition: json.c:42
@ JSONTYPE_ARRAY
Definition: json.c:41
@ JSONTYPE_TIMESTAMPTZ
Definition: json.c:39

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

687 {
688  JsonTypeCategory tcategory;
689  Oid outfuncoid;
690 
691  if (val_type == InvalidOid)
692  ereport(ERROR,
693  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
694  errmsg("could not determine input data type")));
695 
696  if (is_null)
697  {
698  tcategory = JSONTYPE_NULL;
699  outfuncoid = InvalidOid;
700  }
701  else
702  json_categorize_type(val_type,
703  &tcategory, &outfuncoid);
704 
705  datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
706 }
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 json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:193
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:295
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31

References datum_to_json(), 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 523 of file json.c.

526 {
527  int i;
528  const char *sep;
529 
530  Assert(dim < ndims);
531 
532  sep = use_line_feeds ? ",\n " : ",";
533 
534  appendStringInfoChar(result, '[');
535 
536  for (i = 1; i <= dims[dim]; i++)
537  {
538  if (i > 1)
539  appendStringInfoString(result, sep);
540 
541  if (dim + 1 == ndims)
542  {
543  datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
544  outfuncoid, false);
545  (*valcount)++;
546  }
547  else
548  {
549  /*
550  * Do we want line feeds on inner dimensions of arrays? For now
551  * we'll say no.
552  */
553  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
554  valcount, tcategory, outfuncoid, false);
555  }
556  }
557 
558  appendStringInfoChar(result, ']');
559 }
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:523
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(), and i.

Referenced by array_to_json_internal().

◆ array_to_json()

Datum array_to_json ( PG_FUNCTION_ARGS  )

Definition at line 712 of file json.c.

713 {
714  Datum array = PG_GETARG_DATUM(0);
715  StringInfo result;
716 
717  result = makeStringInfo();
718 
719  array_to_json_internal(array, result, false);
720 
722 }
#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:565
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 565 of file json.c.

566 {
567  ArrayType *v = DatumGetArrayTypeP(array);
568  Oid element_type = ARR_ELEMTYPE(v);
569  int *dim;
570  int ndim;
571  int nitems;
572  int count = 0;
573  Datum *elements;
574  bool *nulls;
575  int16 typlen;
576  bool typbyval;
577  char typalign;
578  JsonTypeCategory tcategory;
579  Oid outfuncoid;
580 
581  ndim = ARR_NDIM(v);
582  dim = ARR_DIMS(v);
583  nitems = ArrayGetNItems(ndim, dim);
584 
585  if (nitems <= 0)
586  {
587  appendStringInfoString(result, "[]");
588  return;
589  }
590 
591  get_typlenbyvalalign(element_type,
592  &typlen, &typbyval, &typalign);
593 
594  json_categorize_type(element_type,
595  &tcategory, &outfuncoid);
596 
597  deconstruct_array(v, element_type, typlen, typbyval,
598  typalign, &elements, &nulls,
599  &nitems);
600 
601  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
602  outfuncoid, use_line_feeds);
603 
604  pfree(elements);
605  pfree(nulls);
606 }
#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:3599
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:477
#define nitems(x)
Definition: indent.h:31
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2229
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().

◆ array_to_json_pretty()

Datum array_to_json_pretty ( PG_FUNCTION_ARGS  )

Definition at line 728 of file json.c.

729 {
730  Datum array = PG_GETARG_DATUM(0);
731  bool use_line_feeds = PG_GETARG_BOOL(1);
732  StringInfo result;
733 
734  result = makeStringInfo();
735 
736  array_to_json_internal(array, result, use_line_feeds);
737 
739 }
#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 1271 of file json.c.

1272 {
1273  /* custom version of cstring_to_text_with_len */
1274  int buflen = buffer->len;
1275  int addlen = strlen(addon);
1276  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
1277 
1278  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
1279  memcpy(VARDATA(result), buffer->data, buflen);
1280  memcpy(VARDATA(result) + buflen, addon, addlen);
1281 
1282  return result;
1283 }
#define VARHDRSZ
Definition: c.h:676
void * palloc(Size size)
Definition: mcxt.c:1226
Definition: c.h:671
#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 612 of file json.c.

613 {
614  HeapTupleHeader td;
615  Oid tupType;
616  int32 tupTypmod;
617  TupleDesc tupdesc;
618  HeapTupleData tmptup,
619  *tuple;
620  int i;
621  bool needsep = false;
622  const char *sep;
623 
624  sep = use_line_feeds ? ",\n " : ",";
625 
626  td = DatumGetHeapTupleHeader(composite);
627 
628  /* Extract rowtype info and find a tupdesc */
629  tupType = HeapTupleHeaderGetTypeId(td);
630  tupTypmod = HeapTupleHeaderGetTypMod(td);
631  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
632 
633  /* Build a temporary HeapTuple control structure */
635  tmptup.t_data = td;
636  tuple = &tmptup;
637 
638  appendStringInfoChar(result, '{');
639 
640  for (i = 0; i < tupdesc->natts; i++)
641  {
642  Datum val;
643  bool isnull;
644  char *attname;
645  JsonTypeCategory tcategory;
646  Oid outfuncoid;
647  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
648 
649  if (att->attisdropped)
650  continue;
651 
652  if (needsep)
653  appendStringInfoString(result, sep);
654  needsep = true;
655 
656  attname = NameStr(att->attname);
657  escape_json(result, attname);
658  appendStringInfoChar(result, ':');
659 
660  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
661 
662  if (isnull)
663  {
664  tcategory = JSONTYPE_NULL;
665  outfuncoid = InvalidOid;
666  }
667  else
668  json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
669 
670  datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
671  }
672 
673  appendStringInfoChar(result, '}');
674  ReleaseTupleDesc(tupdesc);
675 }
#define NameStr(name)
Definition: c.h:730
signed int int32
Definition: c.h:478
#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:1627
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:1824

References appendStringInfoChar(), appendStringInfoString(), attname, datum_to_json(), 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(), row_to_json(), and row_to_json_pretty().

◆ datum_to_json()

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

Definition at line 295 of file json.c.

298 {
299  char *outputstr;
300  text *jsontext;
301 
303 
304  /* callers are expected to ensure that null keys are not passed in */
305  Assert(!(key_scalar && is_null));
306 
307  if (is_null)
308  {
309  appendStringInfoString(result, "null");
310  return;
311  }
312 
313  if (key_scalar &&
314  (tcategory == JSONTYPE_ARRAY ||
315  tcategory == JSONTYPE_COMPOSITE ||
316  tcategory == JSONTYPE_JSON ||
317  tcategory == JSONTYPE_CAST))
318  ereport(ERROR,
319  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
320  errmsg("key value must be scalar, not array, composite, or json")));
321 
322  switch (tcategory)
323  {
324  case JSONTYPE_ARRAY:
325  array_to_json_internal(val, result, false);
326  break;
327  case JSONTYPE_COMPOSITE:
328  composite_to_json(val, result, false);
329  break;
330  case JSONTYPE_BOOL:
331  outputstr = DatumGetBool(val) ? "true" : "false";
332  if (key_scalar)
333  escape_json(result, outputstr);
334  else
335  appendStringInfoString(result, outputstr);
336  break;
337  case JSONTYPE_NUMERIC:
338  outputstr = OidOutputFunctionCall(outfuncoid, val);
339 
340  /*
341  * Don't call escape_json for a non-key if it's a valid JSON
342  * number.
343  */
344  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
345  appendStringInfoString(result, outputstr);
346  else
347  escape_json(result, outputstr);
348  pfree(outputstr);
349  break;
350  case JSONTYPE_DATE:
351  {
352  char buf[MAXDATELEN + 1];
353 
354  JsonEncodeDateTime(buf, val, DATEOID, NULL);
355  appendStringInfo(result, "\"%s\"", buf);
356  }
357  break;
358  case JSONTYPE_TIMESTAMP:
359  {
360  char buf[MAXDATELEN + 1];
361 
362  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
363  appendStringInfo(result, "\"%s\"", buf);
364  }
365  break;
367  {
368  char buf[MAXDATELEN + 1];
369 
370  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
371  appendStringInfo(result, "\"%s\"", buf);
372  }
373  break;
374  case JSONTYPE_JSON:
375  /* JSON and JSONB output will already be escaped */
376  outputstr = OidOutputFunctionCall(outfuncoid, val);
377  appendStringInfoString(result, outputstr);
378  pfree(outputstr);
379  break;
380  case JSONTYPE_CAST:
381  /* outfuncoid refers to a cast function, not an output function */
382  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
383  outputstr = text_to_cstring(jsontext);
384  appendStringInfoString(result, outputstr);
385  pfree(outputstr);
386  pfree(jsontext);
387  break;
388  default:
389  outputstr = OidOutputFunctionCall(outfuncoid, val);
390  escape_json(result, outputstr);
391  pfree(outputstr);
392  break;
393  }
394 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1734
#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:402
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:612
bool IsValidJsonNumber(const char *str, int len)
Definition: jsonapi.c:105
static char * buf
Definition: pg_test_fsync.c:67
void check_stack_depth(void)
Definition: postgres.c:3508
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(), json_agg_transfn_worker(), json_object_agg_transfn_worker(), and to_json().

◆ escape_json()

void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 1627 of file json.c.

1628 {
1629  const char *p;
1630 
1632  for (p = str; *p; p++)
1633  {
1634  switch (*p)
1635  {
1636  case '\b':
1637  appendStringInfoString(buf, "\\b");
1638  break;
1639  case '\f':
1640  appendStringInfoString(buf, "\\f");
1641  break;
1642  case '\n':
1643  appendStringInfoString(buf, "\\n");
1644  break;
1645  case '\r':
1646  appendStringInfoString(buf, "\\r");
1647  break;
1648  case '\t':
1649  appendStringInfoString(buf, "\\t");
1650  break;
1651  case '"':
1652  appendStringInfoString(buf, "\\\"");
1653  break;
1654  case '\\':
1655  appendStringInfoString(buf, "\\\\");
1656  break;
1657  default:
1658  if ((unsigned char) *p < ' ')
1659  appendStringInfo(buf, "\\u%04x", (int) *p);
1660  else
1662  break;
1663  }
1664  }
1666 }
#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(), 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 949 of file json.c.

950 {
952 
953  /* cannot be called directly because of internal-type argument */
954  Assert(AggCheckCallContext(fcinfo, NULL));
955 
956  state = PG_ARGISNULL(0) ?
957  NULL :
959 
960  /* NULL result for no rows in, as is standard with aggregates */
961  if (state == NULL)
962  PG_RETURN_NULL();
963 
964  /* Else return state with appropriate array terminator added */
966 }
#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:1271
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 940 of file json.c.

941 {
942  return json_agg_transfn_worker(fcinfo, true);
943 }
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: json.c:849

References json_agg_transfn_worker().

◆ json_agg_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 931 of file json.c.

932 {
933  return json_agg_transfn_worker(fcinfo, false);
934 }

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

850 {
851  MemoryContext aggcontext,
852  oldcontext;
854  Datum val;
855 
856  if (!AggCheckCallContext(fcinfo, &aggcontext))
857  {
858  /* cannot be called directly because of internal-type argument */
859  elog(ERROR, "json_agg_transfn called in non-aggregate context");
860  }
861 
862  if (PG_ARGISNULL(0))
863  {
864  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
865 
866  if (arg_type == InvalidOid)
867  ereport(ERROR,
868  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
869  errmsg("could not determine input data type")));
870 
871  /*
872  * Make this state object in a context where it will persist for the
873  * duration of the aggregate call. MemoryContextSwitchTo is only
874  * needed the first time, as the StringInfo routines make sure they
875  * use the right context to enlarge the object if necessary.
876  */
877  oldcontext = MemoryContextSwitchTo(aggcontext);
878  state = (JsonAggState *) palloc(sizeof(JsonAggState));
879  state->str = makeStringInfo();
880  MemoryContextSwitchTo(oldcontext);
881 
882  appendStringInfoChar(state->str, '[');
883  json_categorize_type(arg_type, &state->val_category,
884  &state->val_output_func);
885  }
886  else
887  {
889  }
890 
891  if (absent_on_null && PG_ARGISNULL(1))
893 
894  if (state->str->len > 1)
895  appendStringInfoString(state->str, ", ");
896 
897  /* fast path for NULLs */
898  if (PG_ARGISNULL(1))
899  {
900  datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
901  InvalidOid, false);
903  }
904 
905  val = PG_GETARG_DATUM(1);
906 
907  /* add some whitespace if structured type and not first item */
908  if (!PG_ARGISNULL(0) && state->str->len > 1 &&
909  (state->val_category == JSONTYPE_ARRAY ||
910  state->val_category == JSONTYPE_COMPOSITE))
911  {
912  appendStringInfoString(state->str, "\n ");
913  }
914 
915  datum_to_json(val, false, state->str, state->val_category,
916  state->val_output_func, false);
917 
918  /*
919  * The transition type for json_agg() is declared to be "internal", which
920  * is a pass-by-value type the same size as a pointer. So we can safely
921  * pass the JsonAggState pointer through nodeAgg.c's machinations.
922  */
924 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1881
#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(), 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 1429 of file json.c.

1430 {
1431  Datum *args;
1432  bool *nulls;
1433  Oid *types;
1434 
1435  /* build argument values to build the object */
1436  int nargs = extract_variadic_args(fcinfo, 0, true,
1437  &args, &types, &nulls);
1438 
1439  if (nargs < 0)
1440  PG_RETURN_NULL();
1441 
1442  PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
1443 }
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:1399

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

1450 {
1452 }

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

1401 {
1402  int i;
1403  const char *sep = "";
1404  StringInfo result;
1405 
1406  result = makeStringInfo();
1407 
1408  appendStringInfoChar(result, '[');
1409 
1410  for (i = 0; i < nargs; i++)
1411  {
1412  if (absent_on_null && nulls[i])
1413  continue;
1414 
1415  appendStringInfoString(result, sep);
1416  sep = ", ";
1417  add_json(args[i], nulls[i], result, types[i], false);
1418  }
1419 
1420  appendStringInfoChar(result, ']');
1421 
1422  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1423 }
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:685
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322

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

1374 {
1375  Datum *args;
1376  bool *nulls;
1377  Oid *types;
1378 
1379  /* build argument values to build the object */
1380  int nargs = extract_variadic_args(fcinfo, 0, true,
1381  &args, &types, &nulls);
1382 
1383  if (nargs < 0)
1384  PG_RETURN_NULL();
1385 
1386  PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
1387 }
Datum json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1286

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

1394 {
1396 }

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

1288 {
1289  int i;
1290  const char *sep = "";
1291  StringInfo result;
1292  JsonUniqueBuilderState unique_check;
1293 
1294  if (nargs % 2 != 0)
1295  ereport(ERROR,
1296  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1297  errmsg("argument list must have even number of elements"),
1298  /* translator: %s is a SQL function name */
1299  errhint("The arguments of %s must consist of alternating keys and values.",
1300  "json_build_object()")));
1301 
1302  result = makeStringInfo();
1303 
1304  appendStringInfoChar(result, '{');
1305 
1306  if (unique_keys)
1307  json_unique_builder_init(&unique_check);
1308 
1309  for (i = 0; i < nargs; i += 2)
1310  {
1311  StringInfo out;
1312  bool skip;
1313  int key_offset;
1314 
1315  /* Skip null values if absent_on_null */
1316  skip = absent_on_null && nulls[i + 1];
1317 
1318  if (skip)
1319  {
1320  /* If key uniqueness check is needed we must save skipped keys */
1321  if (!unique_keys)
1322  continue;
1323 
1324  out = json_unique_builder_get_throwawaybuf(&unique_check);
1325  }
1326  else
1327  {
1328  appendStringInfoString(result, sep);
1329  sep = ", ";
1330  out = result;
1331  }
1332 
1333  /* process key */
1334  if (nulls[i])
1335  ereport(ERROR,
1336  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1337  errmsg("null value not allowed for object key")));
1338 
1339  /* save key offset before appending it */
1340  key_offset = out->len;
1341 
1342  add_json(args[i], false, out, types[i], true);
1343 
1344  if (unique_keys)
1345  {
1346  /* check key uniqueness after key appending */
1347  const char *key = &out->data[key_offset];
1348 
1349  if (!json_unique_check_key(&unique_check.check, key, 0))
1350  ereport(ERROR,
1351  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1352  errmsg("duplicate JSON key %s", key));
1353 
1354  if (skip)
1355  continue;
1356  }
1357 
1358  appendStringInfoString(result, " : ");
1359 
1360  /* process value */
1361  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1362  }
1363 
1364  appendStringInfoChar(result, '}');
1365 
1366  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1367 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
static StringInfo json_unique_builder_get_throwawaybuf(JsonUniqueBuilderState *cxt)
Definition: json.c:1048
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
Definition: json.c:1028
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Definition: json.c:1020
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:116
JsonUniqueCheckState check
Definition: json.c:85

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

static void json_categorize_type ( Oid  typoid,
JsonTypeCategory tcategory,
Oid outfuncoid 
)
static

Definition at line 193 of file json.c.

196 {
197  bool typisvarlena;
198 
199  /* Look through any domain */
200  typoid = getBaseType(typoid);
201 
202  *outfuncoid = InvalidOid;
203 
204  /*
205  * We need to get the output function for everything except date and
206  * timestamp types, array and composite types, booleans, and non-builtin
207  * types where there's a cast to json.
208  */
209 
210  switch (typoid)
211  {
212  case BOOLOID:
213  *tcategory = JSONTYPE_BOOL;
214  break;
215 
216  case INT2OID:
217  case INT4OID:
218  case INT8OID:
219  case FLOAT4OID:
220  case FLOAT8OID:
221  case NUMERICOID:
222  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
223  *tcategory = JSONTYPE_NUMERIC;
224  break;
225 
226  case DATEOID:
227  *tcategory = JSONTYPE_DATE;
228  break;
229 
230  case TIMESTAMPOID:
231  *tcategory = JSONTYPE_TIMESTAMP;
232  break;
233 
234  case TIMESTAMPTZOID:
235  *tcategory = JSONTYPE_TIMESTAMPTZ;
236  break;
237 
238  case JSONOID:
239  case JSONBOID:
240  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
241  *tcategory = JSONTYPE_JSON;
242  break;
243 
244  default:
245  /* Check for arrays and composites */
246  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
247  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
248  *tcategory = JSONTYPE_ARRAY;
249  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
250  *tcategory = JSONTYPE_COMPOSITE;
251  else
252  {
253  /* It's probably the general case ... */
254  *tcategory = JSONTYPE_OTHER;
255  /* but let's look for a cast to json, if it's not built-in */
256  if (typoid >= FirstNormalObjectId)
257  {
258  Oid castfunc;
259  CoercionPathType ctype;
260 
261  ctype = find_coercion_pathway(JSONOID, typoid,
263  &castfunc);
264  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
265  {
266  *tcategory = JSONTYPE_CAST;
267  *outfuncoid = castfunc;
268  }
269  else
270  {
271  /* non builtin type with no cast */
272  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
273  }
274  }
275  else
276  {
277  /* any other builtin type */
278  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
279  }
280  }
281  break;
282  }
283 }
#define OidIsValid(objectId)
Definition: c.h:759
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2717
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2613
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2865
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2479
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
CoercionPathType
Definition: parse_coerce.h:25
@ COERCION_PATH_FUNC
Definition: parse_coerce.h:27
@ COERCION_EXPLICIT
Definition: primnodes.h:644
#define FirstNormalObjectId
Definition: transam.h:197

References COERCION_EXPLICIT, COERCION_PATH_FUNC, find_coercion_pathway(), FirstNormalObjectId, get_element_type(), getBaseType(), getTypeOutputInfo(), InvalidOid, JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_NUMERIC, JSONTYPE_OTHER, JSONTYPE_TIMESTAMP, JSONTYPE_TIMESTAMPTZ, OidIsValid, and type_is_rowtype().

Referenced by add_json(), array_to_json_internal(), composite_to_json(), json_agg_transfn_worker(), json_object_agg_transfn_worker(), to_json(), and to_json_is_immutable().

◆ json_in()

Datum json_in ( PG_FUNCTION_ARGS  )

Definition at line 124 of file json.c.

125 {
126  char *json = PG_GETARG_CSTRING(0);
127  text *result = cstring_to_text(json);
128  JsonLexContext *lex;
129 
130  /* validate it */
131  lex = makeJsonLexContext(result, false);
132  if (!pg_parse_json_or_errsave(lex, &nullSemAction, fcinfo->context))
133  PG_RETURN_NULL();
134 
135  /* Internal representation is the same as text */
136  PG_RETURN_TEXT_P(result);
137 }
#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:528
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:507
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 1461 of file json.c.

1462 {
1463  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1464  int ndims = ARR_NDIM(in_array);
1465  StringInfoData result;
1466  Datum *in_datums;
1467  bool *in_nulls;
1468  int in_count,
1469  count,
1470  i;
1471  text *rval;
1472  char *v;
1473 
1474  switch (ndims)
1475  {
1476  case 0:
1478  break;
1479 
1480  case 1:
1481  if ((ARR_DIMS(in_array)[0]) % 2)
1482  ereport(ERROR,
1483  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1484  errmsg("array must have even number of elements")));
1485  break;
1486 
1487  case 2:
1488  if ((ARR_DIMS(in_array)[1]) != 2)
1489  ereport(ERROR,
1490  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1491  errmsg("array must have two columns")));
1492  break;
1493 
1494  default:
1495  ereport(ERROR,
1496  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1497  errmsg("wrong number of array subscripts")));
1498  }
1499 
1500  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1501 
1502  count = in_count / 2;
1503 
1504  initStringInfo(&result);
1505 
1506  appendStringInfoChar(&result, '{');
1507 
1508  for (i = 0; i < count; ++i)
1509  {
1510  if (in_nulls[i * 2])
1511  ereport(ERROR,
1512  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1513  errmsg("null value not allowed for object key")));
1514 
1515  v = TextDatumGetCString(in_datums[i * 2]);
1516  if (i > 0)
1517  appendStringInfoString(&result, ", ");
1518  escape_json(&result, v);
1519  appendStringInfoString(&result, " : ");
1520  pfree(v);
1521  if (in_nulls[i * 2 + 1])
1522  appendStringInfoString(&result, "null");
1523  else
1524  {
1525  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1526  escape_json(&result, v);
1527  pfree(v);
1528  }
1529  }
1530 
1531  appendStringInfoChar(&result, '}');
1532 
1533  pfree(in_datums);
1534  pfree(in_nulls);
1535 
1536  rval = cstring_to_text_with_len(result.data, result.len);
1537  pfree(result.data);
1538 
1539  PG_RETURN_TEXT_P(rval);
1540 }
#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:3665
#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 1248 of file json.c.

1249 {
1251 
1252  /* cannot be called directly because of internal-type argument */
1253  Assert(AggCheckCallContext(fcinfo, NULL));
1254 
1255  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
1256 
1257  /* NULL result for no rows in, as is standard with aggregates */
1258  if (state == NULL)
1259  PG_RETURN_NULL();
1260 
1261  /* Else return state with appropriate object terminator added */
1263 }

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

1222 {
1223  return json_object_agg_transfn_worker(fcinfo, true, false);
1224 }
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: json.c:1072

References json_object_agg_transfn_worker().

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1212 of file json.c.

1213 {
1214  return json_object_agg_transfn_worker(fcinfo, false, false);
1215 }

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

1074 {
1075  MemoryContext aggcontext,
1076  oldcontext;
1078  StringInfo out;
1079  Datum arg;
1080  bool skip;
1081  int key_offset;
1082 
1083  if (!AggCheckCallContext(fcinfo, &aggcontext))
1084  {
1085  /* cannot be called directly because of internal-type argument */
1086  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
1087  }
1088 
1089  if (PG_ARGISNULL(0))
1090  {
1091  Oid arg_type;
1092 
1093  /*
1094  * Make the StringInfo in a context where it will persist for the
1095  * duration of the aggregate call. Switching context is only needed
1096  * for this initial step, as the StringInfo and dynahash routines make
1097  * sure they use the right context to enlarge the object if necessary.
1098  */
1099  oldcontext = MemoryContextSwitchTo(aggcontext);
1100  state = (JsonAggState *) palloc(sizeof(JsonAggState));
1101  state->str = makeStringInfo();
1102  if (unique_keys)
1103  json_unique_builder_init(&state->unique_check);
1104  else
1105  memset(&state->unique_check, 0, sizeof(state->unique_check));
1106  MemoryContextSwitchTo(oldcontext);
1107 
1108  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1109 
1110  if (arg_type == InvalidOid)
1111  ereport(ERROR,
1112  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1113  errmsg("could not determine data type for argument %d", 1)));
1114 
1115  json_categorize_type(arg_type, &state->key_category,
1116  &state->key_output_func);
1117 
1118  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1119 
1120  if (arg_type == InvalidOid)
1121  ereport(ERROR,
1122  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1123  errmsg("could not determine data type for argument %d", 2)));
1124 
1125  json_categorize_type(arg_type, &state->val_category,
1126  &state->val_output_func);
1127 
1128  appendStringInfoString(state->str, "{ ");
1129  }
1130  else
1131  {
1133  }
1134 
1135  /*
1136  * Note: since json_object_agg() is declared as taking type "any", the
1137  * parser will not do any type conversion on unknown-type literals (that
1138  * is, undecorated strings or NULLs). Such values will arrive here as
1139  * type UNKNOWN, which fortunately does not matter to us, since
1140  * unknownout() works fine.
1141  */
1142 
1143  if (PG_ARGISNULL(1))
1144  ereport(ERROR,
1145  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1146  errmsg("null value not allowed for object key")));
1147 
1148  /* Skip null values if absent_on_null */
1149  skip = absent_on_null && PG_ARGISNULL(2);
1150 
1151  if (skip)
1152  {
1153  /*
1154  * We got a NULL value and we're not storing those; if we're not
1155  * testing key uniqueness, we're done. If we are, use the throwaway
1156  * buffer to store the key name so that we can check it.
1157  */
1158  if (!unique_keys)
1160 
1161  out = json_unique_builder_get_throwawaybuf(&state->unique_check);
1162  }
1163  else
1164  {
1165  out = state->str;
1166 
1167  /*
1168  * Append comma delimiter only if we have already output some fields
1169  * after the initial string "{ ".
1170  */
1171  if (out->len > 2)
1172  appendStringInfoString(out, ", ");
1173  }
1174 
1175  arg = PG_GETARG_DATUM(1);
1176 
1177  key_offset = out->len;
1178 
1179  datum_to_json(arg, false, out, state->key_category,
1180  state->key_output_func, true);
1181 
1182  if (unique_keys)
1183  {
1184  const char *key = &out->data[key_offset];
1185 
1186  if (!json_unique_check_key(&state->unique_check.check, key, 0))
1187  ereport(ERROR,
1188  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1189  errmsg("duplicate JSON key %s", key));
1190 
1191  if (skip)
1193  }
1194 
1195  appendStringInfoString(state->str, " : ");
1196 
1197  if (PG_ARGISNULL(2))
1198  arg = (Datum) 0;
1199  else
1200  arg = PG_GETARG_DATUM(2);
1201 
1202  datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
1203  state->val_output_func, false);
1204 
1206 }
void * arg

References AggCheckCallContext(), appendStringInfoString(), arg, StringInfoData::data, datum_to_json(), 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 1239 of file json.c.

1240 {
1241  return json_object_agg_transfn_worker(fcinfo, true, true);
1242 }

References json_object_agg_transfn_worker().

◆ json_object_agg_unique_transfn()

Datum json_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1230 of file json.c.

1231 {
1232  return json_object_agg_transfn_worker(fcinfo, false, true);
1233 }

References json_object_agg_transfn_worker().

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1549 of file json.c.

1550 {
1551  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1552  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1553  int nkdims = ARR_NDIM(key_array);
1554  int nvdims = ARR_NDIM(val_array);
1555  StringInfoData result;
1556  Datum *key_datums,
1557  *val_datums;
1558  bool *key_nulls,
1559  *val_nulls;
1560  int key_count,
1561  val_count,
1562  i;
1563  text *rval;
1564  char *v;
1565 
1566  if (nkdims > 1 || nkdims != nvdims)
1567  ereport(ERROR,
1568  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1569  errmsg("wrong number of array subscripts")));
1570 
1571  if (nkdims == 0)
1573 
1574  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1575  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1576 
1577  if (key_count != val_count)
1578  ereport(ERROR,
1579  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1580  errmsg("mismatched array dimensions")));
1581 
1582  initStringInfo(&result);
1583 
1584  appendStringInfoChar(&result, '{');
1585 
1586  for (i = 0; i < key_count; ++i)
1587  {
1588  if (key_nulls[i])
1589  ereport(ERROR,
1590  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1591  errmsg("null value not allowed for object key")));
1592 
1593  v = TextDatumGetCString(key_datums[i]);
1594  if (i > 0)
1595  appendStringInfoString(&result, ", ");
1596  escape_json(&result, v);
1597  appendStringInfoString(&result, " : ");
1598  pfree(v);
1599  if (val_nulls[i])
1600  appendStringInfoString(&result, "null");
1601  else
1602  {
1603  v = TextDatumGetCString(val_datums[i]);
1604  escape_json(&result, v);
1605  pfree(v);
1606  }
1607  }
1608 
1609  appendStringInfoChar(&result, '}');
1610 
1611  pfree(key_datums);
1612  pfree(key_nulls);
1613  pfree(val_datums);
1614  pfree(val_nulls);
1615 
1616  rval = cstring_to_text_with_len(result.data, result.len);
1617  pfree(result.data);
1618 
1619  PG_RETURN_TEXT_P(rval);
1620 }

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

144 {
145  /* we needn't detoast because text_to_cstring will handle that */
146  Datum txt = PG_GETARG_DATUM(0);
147 
149 }
#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 169 of file json.c.

170 {
172  char *str;
173  int nbytes;
174  JsonLexContext *lex;
175 
176  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
177 
178  /* Validate it. */
179  lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false);
181 
183 }
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 155 of file json.c.

156 {
157  text *t = PG_GETARG_TEXT_PP(0);
159 
163 }
#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 1785 of file json.c.

1786 {
1787  text *json = PG_GETARG_TEXT_PP(0);
1788  JsonLexContext *lex = makeJsonLexContext(json, false);
1789  char *type;
1790  JsonTokenType tok;
1791  JsonParseErrorType result;
1792 
1793  /* Lex exactly one token from the input and check its type. */
1794  result = json_lex(lex);
1795  if (result != JSON_SUCCESS)
1796  json_errsave_error(result, lex, NULL);
1797  tok = lex->token_type;
1798 
1799  switch (tok)
1800  {
1802  type = "object";
1803  break;
1805  type = "array";
1806  break;
1807  case JSON_TOKEN_STRING:
1808  type = "string";
1809  break;
1810  case JSON_TOKEN_NUMBER:
1811  type = "number";
1812  break;
1813  case JSON_TOKEN_TRUE:
1814  case JSON_TOKEN_FALSE:
1815  type = "boolean";
1816  break;
1817  case JSON_TOKEN_NULL:
1818  type = "null";
1819  break;
1820  default:
1821  elog(ERROR, "unexpected json token: %d", tok);
1822  }
1823 
1825 }
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:628
JsonTokenType token_type
Definition: jsonapi.h:82

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 generate_unaccent_rules::type.

◆ json_unique_builder_get_throwawaybuf()

static StringInfo json_unique_builder_get_throwawaybuf ( JsonUniqueBuilderState cxt)
static

Definition at line 1048 of file json.c.

1049 {
1050  StringInfo out = &cxt->skipped_keys;
1051 
1052  if (!out->data)
1053  {
1054  MemoryContext oldcxt = MemoryContextSwitchTo(cxt->mcxt);
1055 
1056  initStringInfo(out);
1057  MemoryContextSwitchTo(oldcxt);
1058  }
1059  else
1060  /* Just reset the string to empty */
1061  out->len = 0;
1062 
1063  return out;
1064 }
StringInfoData skipped_keys
Definition: json.c:86
MemoryContext mcxt
Definition: json.c:87

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

1021 {
1023  cxt->mcxt = CurrentMemoryContext;
1024  cxt->skipped_keys.data = NULL;
1025 }
static void json_unique_check_init(JsonUniqueCheckState *cxt)
Definition: json.c:1002
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 1002 of file json.c.

1003 {
1004  HASHCTL ctl;
1005 
1006  memset(&ctl, 0, sizeof(ctl));
1007  ctl.keysize = sizeof(JsonUniqueHashEntry);
1008  ctl.entrysize = sizeof(JsonUniqueHashEntry);
1009  ctl.hcxt = CurrentMemoryContext;
1010  ctl.hash = json_unique_hash;
1012 
1013  *cxt = hash_create("json object hashtable",
1014  32,
1015  &ctl,
1017 }
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:970
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
Definition: json.c:981
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 1028 of file json.c.

1029 {
1030  JsonUniqueHashEntry entry;
1031  bool found;
1032 
1033  entry.key = key;
1034  entry.key_len = strlen(key);
1035  entry.object_id = object_id;
1036 
1037  (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
1038 
1039  return !found;
1040 }
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:60

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

971 {
972  const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
974 
975  hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
976 
977  return DatumGetUInt32(hash);
978 }
unsigned int uint32
Definition: c.h:490
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 981 of file json.c.

982 {
983  const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
984  const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
985 
986  if (entry1->object_id != entry2->object_id)
987  return entry1->object_id > entry2->object_id ? 1 : -1;
988 
989  if (entry1->key_len != entry2->key_len)
990  return entry1->key_len > entry2->key_len ? 1 : -1;
991 
992  return strncmp(entry1->key, entry2->key, entry1->key_len);
993 }

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

1689 {
1690  JsonUniqueParsingState *state = _state;
1691  JsonUniqueStackEntry *entry;
1692 
1693  if (!state->unique)
1694  return JSON_SUCCESS;
1695 
1696  entry = state->stack;
1697  state->stack = entry->parent; /* pop object from stack */
1698  pfree(entry);
1699  return JSON_SUCCESS;
1700 }
struct JsonUniqueStackEntry * parent
Definition: json.c:68

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

1704 {
1705  JsonUniqueParsingState *state = _state;
1706  JsonUniqueStackEntry *entry;
1707 
1708  if (!state->unique)
1709  return JSON_SUCCESS;
1710 
1711  /* find key collision in the current object */
1712  if (json_unique_check_key(&state->check, field, state->stack->object_id))
1713  return JSON_SUCCESS;
1714 
1715  state->unique = false;
1716 
1717  /* pop all objects entries */
1718  while ((entry = state->stack))
1719  {
1720  state->stack = entry->parent;
1721  pfree(entry);
1722  }
1723  return JSON_SUCCESS;
1724 }

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

1671 {
1672  JsonUniqueParsingState *state = _state;
1673  JsonUniqueStackEntry *entry;
1674 
1675  if (!state->unique)
1676  return JSON_SUCCESS;
1677 
1678  /* push object entry to stack */
1679  entry = palloc(sizeof(*entry));
1680  entry->object_id = state->id_counter++;
1681  entry->parent = state->stack;
1682  state->stack = entry;
1683 
1684  return JSON_SUCCESS;
1685 }

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

1729 {
1730  JsonLexContext *lex = makeJsonLexContext(json, check_unique_keys);
1731  JsonSemAction uniqueSemAction = {0};
1733  JsonParseErrorType result;
1734 
1735  if (check_unique_keys)
1736  {
1737  state.lex = lex;
1738  state.stack = NULL;
1739  state.id_counter = 0;
1740  state.unique = true;
1741  json_unique_check_init(&state.check);
1742 
1743  uniqueSemAction.semstate = &state;
1744  uniqueSemAction.object_start = json_unique_object_start;
1746  uniqueSemAction.object_end = json_unique_object_end;
1747  }
1748 
1749  result = pg_parse_json(lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
1750 
1751  if (result != JSON_SUCCESS)
1752  {
1753  if (throw_error)
1754  json_errsave_error(result, lex, NULL);
1755 
1756  return false; /* invalid json */
1757  }
1758 
1759  if (check_unique_keys && !state.unique)
1760  {
1761  if (throw_error)
1762  ereport(ERROR,
1763  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1764  errmsg("duplicate JSON object key value")));
1765 
1766  return false; /* not unique keys */
1767  }
1768 
1769  return true; /* ok */
1770 }
static JsonParseErrorType json_unique_object_start(void *_state)
Definition: json.c:1670
static JsonParseErrorType json_unique_object_field_start(void *_state, char *field, bool isnull)
Definition: json.c:1703
static JsonParseErrorType json_unique_object_end(void *_state)
Definition: json.c:1688
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 ExecEvalJsonIsPredicate().

◆ JsonEncodeDateTime()

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

Definition at line 402 of file json.c.

403 {
404  if (!buf)
405  buf = palloc(MAXDATELEN + 1);
406 
407  switch (typid)
408  {
409  case DATEOID:
410  {
411  DateADT date;
412  struct pg_tm tm;
413 
415 
416  /* Same as date_out(), but forcing DateStyle */
417  if (DATE_NOT_FINITE(date))
419  else
420  {
422  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
424  }
425  }
426  break;
427  case TIMEOID:
428  {
429  TimeADT time = DatumGetTimeADT(value);
430  struct pg_tm tt,
431  *tm = &tt;
432  fsec_t fsec;
433 
434  /* Same as time_out(), but forcing DateStyle */
435  time2tm(time, tm, &fsec);
436  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
437  }
438  break;
439  case TIMETZOID:
440  {
442  struct pg_tm tt,
443  *tm = &tt;
444  fsec_t fsec;
445  int tz;
446 
447  /* Same as timetz_out(), but forcing DateStyle */
448  timetz2tm(time, tm, &fsec, &tz);
449  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
450  }
451  break;
452  case TIMESTAMPOID:
453  {
455  struct pg_tm tm;
456  fsec_t fsec;
457 
459  /* Same as timestamp_out(), but forcing DateStyle */
462  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
463  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
464  else
465  ereport(ERROR,
466  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
467  errmsg("timestamp out of range")));
468  }
469  break;
470  case TIMESTAMPTZOID:
471  {
473  struct pg_tm tm;
474  int tz;
475  fsec_t fsec;
476  const char *tzn = NULL;
477 
479 
480  /*
481  * If a time zone is specified, we apply the time-zone shift,
482  * convert timestamptz to pg_tm as if it were without a time
483  * zone, and then use the specified time zone for converting
484  * the timestamp into a string.
485  */
486  if (tzp)
487  {
488  tz = *tzp;
490  }
491 
492  /* Same as timestamptz_out(), but forcing DateStyle */
495  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
496  tzp ? NULL : &tzn, NULL) == 0)
497  {
498  if (tzp)
499  tm.tm_isdst = 1; /* set time-zone presence flag */
500 
501  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
502  }
503  else
504  ereport(ERROR,
505  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
506  errmsg("timestamp out of range")));
507  }
508  break;
509  default:
510  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
511  return NULL;
512  }
513 
514  return buf;
515 }
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4187
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:313
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4217
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4102
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1536
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
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 @147 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(), and datum_to_jsonb().

◆ row_to_json()

Datum row_to_json ( PG_FUNCTION_ARGS  )

Definition at line 745 of file json.c.

746 {
747  Datum array = PG_GETARG_DATUM(0);
748  StringInfo result;
749 
750  result = makeStringInfo();
751 
752  composite_to_json(array, result, false);
753 
755 }

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

762 {
763  Datum array = PG_GETARG_DATUM(0);
764  bool use_line_feeds = PG_GETARG_BOOL(1);
765  StringInfo result;
766 
767  result = makeStringInfo();
768 
769  composite_to_json(array, result, use_line_feeds);
770 
772 }

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

821 {
823  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
824  StringInfo result;
825  JsonTypeCategory tcategory;
826  Oid outfuncoid;
827 
828  if (val_type == InvalidOid)
829  ereport(ERROR,
830  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
831  errmsg("could not determine input data type")));
832 
833  json_categorize_type(val_type,
834  &tcategory, &outfuncoid);
835 
836  result = makeStringInfo();
837 
838  datum_to_json(val, false, result, tcategory, outfuncoid, false);
839 
841 }

References cstring_to_text_with_len(), StringInfoData::data, datum_to_json(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), StringInfoData::len, makeStringInfo(), PG_GETARG_DATUM, PG_RETURN_TEXT_P, and val.

◆ to_json_is_immutable()

bool to_json_is_immutable ( Oid  typoid)

Definition at line 782 of file json.c.

783 {
784  JsonTypeCategory tcategory;
785  Oid outfuncoid;
786 
787  json_categorize_type(typoid, &tcategory, &outfuncoid);
788 
789  switch (tcategory)
790  {
791  case JSONTYPE_BOOL:
792  case JSONTYPE_JSON:
793  case JSONTYPE_NULL:
794  return true;
795 
796  case JSONTYPE_DATE:
797  case JSONTYPE_TIMESTAMP:
799  return false;
800 
801  case JSONTYPE_ARRAY:
802  return false; /* TODO recurse into elements */
803 
804  case JSONTYPE_COMPOSITE:
805  return false; /* TODO recurse into fields */
806 
807  case JSONTYPE_NUMERIC:
808  case JSONTYPE_CAST:
809  case JSONTYPE_OTHER:
810  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
811  }
812 
813  return false; /* not reached */
814 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1762

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

Referenced by contain_mutable_functions_walker().