PostgreSQL Source Code  git master
json.c File Reference
#include "postgres.h"
#include "access/hash.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  JsonUniqueBuilderState
 
struct  JsonUniqueStackEntry
 
struct  JsonUniqueParsingState
 
struct  JsonAggState
 

Typedefs

typedef struct HTABJsonUniqueCheckState
 
typedef struct JsonUniqueHashEntry JsonUniqueHashEntry
 
typedef struct JsonUniqueBuilderState JsonUniqueBuilderState
 
typedef struct JsonUniqueStackEntry JsonUniqueStackEntry
 
typedef struct JsonUniqueParsingState JsonUniqueParsingState
 
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 (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)
 
void json_categorize_type (Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
 
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)
 
Datum to_json_worker (Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
 
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 bool json_unique_check_key (JsonUniqueCheckState *cxt, const char *key, int object_id)
 
static void json_unique_builder_init (JsonUniqueBuilderState *cxt)
 
static StringInfo json_unique_builder_get_skipped_keys (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 void json_unique_object_start (void *_state)
 
static void json_unique_object_end (void *_state)
 
static void 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 34 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 658 of file json.c.

660 {
661  JsonTypeCategory tcategory;
662  Oid outfuncoid;
663 
664  if (val_type == InvalidOid)
665  ereport(ERROR,
666  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
667  errmsg("could not determine input data type")));
668 
669  if (is_null)
670  {
671  tcategory = JSONTYPE_NULL;
672  outfuncoid = InvalidOid;
673  }
674  else
675  json_categorize_type(val_type,
676  &tcategory, &outfuncoid);
677 
678  datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
679 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
long val
Definition: informix.c:664
void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:166
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:268
JsonTypeCategory
Definition: json.h:20
@ JSONTYPE_NULL
Definition: json.h:21
#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 496 of file json.c.

499 {
500  int i;
501  const char *sep;
502 
503  Assert(dim < ndims);
504 
505  sep = use_line_feeds ? ",\n " : ",";
506 
507  appendStringInfoChar(result, '[');
508 
509  for (i = 1; i <= dims[dim]; i++)
510  {
511  if (i > 1)
512  appendStringInfoString(result, sep);
513 
514  if (dim + 1 == ndims)
515  {
516  datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
517  outfuncoid, false);
518  (*valcount)++;
519  }
520  else
521  {
522  /*
523  * Do we want line feeds on inner dimensions of arrays? For now
524  * we'll say no.
525  */
526  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
527  valcount, tcategory, outfuncoid, false);
528  }
529  }
530 
531  appendStringInfoChar(result, ']');
532 }
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:496
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 685 of file json.c.

686 {
687  Datum array = PG_GETARG_DATUM(0);
688  StringInfo result;
689 
690  result = makeStringInfo();
691 
692  array_to_json_internal(array, result, false);
693 
695 }
#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:538
uintptr_t Datum
Definition: postgres.h:411
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200

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

539 {
540  ArrayType *v = DatumGetArrayTypeP(array);
541  Oid element_type = ARR_ELEMTYPE(v);
542  int *dim;
543  int ndim;
544  int nitems;
545  int count = 0;
546  Datum *elements;
547  bool *nulls;
548  int16 typlen;
549  bool typbyval;
550  char typalign;
551  JsonTypeCategory tcategory;
552  Oid outfuncoid;
553 
554  ndim = ARR_NDIM(v);
555  dim = ARR_DIMS(v);
556  nitems = ArrayGetNItems(ndim, dim);
557 
558  if (nitems <= 0)
559  {
560  appendStringInfoString(result, "[]");
561  return;
562  }
563 
564  get_typlenbyvalalign(element_type,
565  &typlen, &typbyval, &typalign);
566 
567  json_categorize_type(element_type,
568  &tcategory, &outfuncoid);
569 
570  deconstruct_array(v, element_type, typlen, typbyval,
571  typalign, &elements, &nulls,
572  &nitems);
573 
574  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
575  outfuncoid, use_line_feeds);
576 
577  pfree(elements);
578  pfree(nulls);
579 }
#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:3491
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:428
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2228
void pfree(void *pointer)
Definition: mcxt.c:1175
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(), 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 701 of file json.c.

702 {
703  Datum array = PG_GETARG_DATUM(0);
704  bool use_line_feeds = PG_GETARG_BOOL(1);
705  StringInfo result;
706 
707  result = makeStringInfo();
708 
709  array_to_json_internal(array, result, use_line_feeds);
710 
712 }
#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 1223 of file json.c.

1224 {
1225  /* custom version of cstring_to_text_with_len */
1226  int buflen = buffer->len;
1227  int addlen = strlen(addon);
1228  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
1229 
1230  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
1231  memcpy(VARDATA(result), buffer->data, buflen);
1232  memcpy(VARDATA(result) + buflen, addon, addlen);
1233 
1234  return result;
1235 }
#define VARHDRSZ
Definition: c.h:627
void * palloc(Size size)
Definition: mcxt.c:1068
#define VARDATA(PTR)
Definition: postgres.h:315
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
Definition: c.h:622

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

586 {
587  HeapTupleHeader td;
588  Oid tupType;
589  int32 tupTypmod;
590  TupleDesc tupdesc;
591  HeapTupleData tmptup,
592  *tuple;
593  int i;
594  bool needsep = false;
595  const char *sep;
596 
597  sep = use_line_feeds ? ",\n " : ",";
598 
599  td = DatumGetHeapTupleHeader(composite);
600 
601  /* Extract rowtype info and find a tupdesc */
602  tupType = HeapTupleHeaderGetTypeId(td);
603  tupTypmod = HeapTupleHeaderGetTypMod(td);
604  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
605 
606  /* Build a temporary HeapTuple control structure */
608  tmptup.t_data = td;
609  tuple = &tmptup;
610 
611  appendStringInfoChar(result, '{');
612 
613  for (i = 0; i < tupdesc->natts; i++)
614  {
615  Datum val;
616  bool isnull;
617  char *attname;
618  JsonTypeCategory tcategory;
619  Oid outfuncoid;
620  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
621 
622  if (att->attisdropped)
623  continue;
624 
625  if (needsep)
626  appendStringInfoString(result, sep);
627  needsep = true;
628 
629  attname = NameStr(att->attname);
630  escape_json(result, attname);
631  appendStringInfoChar(result, ':');
632 
633  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
634 
635  if (isnull)
636  {
637  tcategory = JSONTYPE_NULL;
638  outfuncoid = InvalidOid;
639  }
640  else
641  json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
642 
643  datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
644  }
645 
646  appendStringInfoChar(result, '}');
647  ReleaseTupleDesc(tupdesc);
648 }
#define NameStr(name)
Definition: c.h:681
signed int int32
Definition: c.h:429
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:462
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:452
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:446
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1587
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
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(), 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 268 of file json.c.

271 {
272  char *outputstr;
273  text *jsontext;
274 
276 
277  /* callers are expected to ensure that null keys are not passed in */
278  Assert(!(key_scalar && is_null));
279 
280  if (is_null)
281  {
282  appendStringInfoString(result, "null");
283  return;
284  }
285 
286  if (key_scalar &&
287  (tcategory == JSONTYPE_ARRAY ||
288  tcategory == JSONTYPE_COMPOSITE ||
289  tcategory == JSONTYPE_JSON ||
290  tcategory == JSONTYPE_CAST))
291  ereport(ERROR,
292  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
293  errmsg("key value must be scalar, not array, composite, or json")));
294 
295  switch (tcategory)
296  {
297  case JSONTYPE_ARRAY:
298  array_to_json_internal(val, result, false);
299  break;
300  case JSONTYPE_COMPOSITE:
301  composite_to_json(val, result, false);
302  break;
303  case JSONTYPE_BOOL:
304  outputstr = DatumGetBool(val) ? "true" : "false";
305  if (key_scalar)
306  escape_json(result, outputstr);
307  else
308  appendStringInfoString(result, outputstr);
309  break;
310  case JSONTYPE_NUMERIC:
311  outputstr = OidOutputFunctionCall(outfuncoid, val);
312 
313  /*
314  * Don't call escape_json for a non-key if it's a valid JSON
315  * number.
316  */
317  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
318  appendStringInfoString(result, outputstr);
319  else
320  escape_json(result, outputstr);
321  pfree(outputstr);
322  break;
323  case JSONTYPE_DATE:
324  {
325  char buf[MAXDATELEN + 1];
326 
327  JsonEncodeDateTime(buf, val, DATEOID, NULL);
328  appendStringInfo(result, "\"%s\"", buf);
329  }
330  break;
331  case JSONTYPE_TIMESTAMP:
332  {
333  char buf[MAXDATELEN + 1];
334 
335  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
336  appendStringInfo(result, "\"%s\"", buf);
337  }
338  break;
340  {
341  char buf[MAXDATELEN + 1];
342 
343  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
344  appendStringInfo(result, "\"%s\"", buf);
345  }
346  break;
347  case JSONTYPE_JSON:
348  /* JSON and JSONB output will already be escaped */
349  outputstr = OidOutputFunctionCall(outfuncoid, val);
350  appendStringInfoString(result, outputstr);
351  pfree(outputstr);
352  break;
353  case JSONTYPE_CAST:
354  /* outfuncoid refers to a cast function, not an output function */
355  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
356  outputstr = text_to_cstring(jsontext);
357  appendStringInfoString(result, outputstr);
358  pfree(outputstr);
359  pfree(jsontext);
360  break;
361  default:
362  outputstr = OidOutputFunctionCall(outfuncoid, val);
363  escape_json(result, outputstr);
364  pfree(outputstr);
365  break;
366  }
367 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1639
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:669
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define MAXDATELEN
Definition: datetime.h:201
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:375
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:585
@ JSONTYPE_JSON
Definition: json.h:27
@ JSONTYPE_TIMESTAMP
Definition: json.h:25
@ JSONTYPE_NUMERIC
Definition: json.h:23
@ JSONTYPE_DATE
Definition: json.h:24
@ JSONTYPE_BOOL
Definition: json.h:22
@ JSONTYPE_CAST
Definition: json.h:30
@ JSONTYPE_COMPOSITE
Definition: json.h:29
@ JSONTYPE_ARRAY
Definition: json.h:28
@ JSONTYPE_TIMESTAMPTZ
Definition: json.h:26
bool IsValidJsonNumber(const char *str, int len)
Definition: jsonapi.c:104
static char * buf
Definition: pg_test_fsync.c:67
void check_stack_depth(void)
Definition: postgres.c:3500
#define DatumGetBool(X)
Definition: postgres.h:437
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
char * text_to_cstring(const text *t)
Definition: varlena.c:221

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

◆ escape_json()

void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 1587 of file json.c.

1588 {
1589  const char *p;
1590 
1592  for (p = str; *p; p++)
1593  {
1594  switch (*p)
1595  {
1596  case '\b':
1597  appendStringInfoString(buf, "\\b");
1598  break;
1599  case '\f':
1600  appendStringInfoString(buf, "\\f");
1601  break;
1602  case '\n':
1603  appendStringInfoString(buf, "\\n");
1604  break;
1605  case '\r':
1606  appendStringInfoString(buf, "\\r");
1607  break;
1608  case '\t':
1609  appendStringInfoString(buf, "\\t");
1610  break;
1611  case '"':
1612  appendStringInfoString(buf, "\\\"");
1613  break;
1614  case '\\':
1615  appendStringInfoString(buf, "\\\\");
1616  break;
1617  default:
1618  if ((unsigned char) *p < ' ')
1619  appendStringInfo(buf, "\\u%04x", (int) *p);
1620  else
1622  break;
1623  }
1624  }
1626 }
#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(), transformJsonTableColumn(), and write_jsonlog().

◆ json_agg_finalfn()

Datum json_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 917 of file json.c.

918 {
920 
921  /* cannot be called directly because of internal-type argument */
922  Assert(AggCheckCallContext(fcinfo, NULL));
923 
924  state = PG_ARGISNULL(0) ?
925  NULL :
927 
928  /* NULL result for no rows in, as is standard with aggregates */
929  if (state == NULL)
930  PG_RETURN_NULL();
931 
932  /* Else return state with appropriate array terminator added */
934 }
#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:1223
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4487
Definition: regguts.h:318

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

909 {
910  return json_agg_transfn_worker(fcinfo, true);
911 }
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: json.c:817

References json_agg_transfn_worker().

◆ json_agg_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 899 of file json.c.

900 {
901  return json_agg_transfn_worker(fcinfo, false);
902 }

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

818 {
819  MemoryContext aggcontext,
820  oldcontext;
822  Datum val;
823 
824  if (!AggCheckCallContext(fcinfo, &aggcontext))
825  {
826  /* cannot be called directly because of internal-type argument */
827  elog(ERROR, "json_agg_transfn called in non-aggregate context");
828  }
829 
830  if (PG_ARGISNULL(0))
831  {
832  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
833 
834  if (arg_type == InvalidOid)
835  ereport(ERROR,
836  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
837  errmsg("could not determine input data type")));
838 
839  /*
840  * Make this state object in a context where it will persist for the
841  * duration of the aggregate call. MemoryContextSwitchTo is only
842  * needed the first time, as the StringInfo routines make sure they
843  * use the right context to enlarge the object if necessary.
844  */
845  oldcontext = MemoryContextSwitchTo(aggcontext);
846  state = (JsonAggState *) palloc(sizeof(JsonAggState));
847  state->str = makeStringInfo();
848  MemoryContextSwitchTo(oldcontext);
849 
850  appendStringInfoChar(state->str, '[');
851  json_categorize_type(arg_type, &state->val_category,
852  &state->val_output_func);
853  }
854  else
855  {
857  }
858 
859  if (absent_on_null && PG_ARGISNULL(1))
861 
862  if (state->str->len > 1)
863  appendStringInfoString(state->str, ", ");
864 
865  /* fast path for NULLs */
866  if (PG_ARGISNULL(1))
867  {
868  datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
869  InvalidOid, false);
871  }
872 
873  val = PG_GETARG_DATUM(1);
874 
875  /* add some whitespace if structured type and not first item */
876  if (!PG_ARGISNULL(0) && state->str->len > 1 &&
877  (state->val_category == JSONTYPE_ARRAY ||
878  state->val_category == JSONTYPE_COMPOSITE))
879  {
880  appendStringInfoString(state->str, "\n ");
881  }
882 
883  datum_to_json(val, false, state->str, state->val_category,
884  state->val_output_func, false);
885 
886  /*
887  * The transition type for json_agg() is declared to be "internal", which
888  * is a pass-by-value type the same size as a pointer. So we can safely
889  * pass the JsonAggState pointer through nodeAgg.c's machinations.
890  */
892 }
#define elog(elevel,...)
Definition: elog.h:218
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1786
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
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 1382 of file json.c.

1383 {
1384  Datum *args;
1385  bool *nulls;
1386  Oid *types;
1387 
1388  /* build argument values to build the object */
1389  int nargs = extract_variadic_args(fcinfo, 0, true,
1390  &args, &types, &nulls);
1391 
1392  if (nargs < 0)
1393  PG_RETURN_NULL();
1394 
1395  PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
1396 }
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:1976
Datum json_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null)
Definition: json.c:1352

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

1403 {
1405 }

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

1354 {
1355  int i;
1356  const char *sep = "";
1357  StringInfo result;
1358 
1359  result = makeStringInfo();
1360 
1361  appendStringInfoChar(result, '[');
1362 
1363  for (i = 0; i < nargs; i++)
1364  {
1365  if (absent_on_null && nulls[i])
1366  continue;
1367 
1368  appendStringInfoString(result, sep);
1369  sep = ", ";
1370  add_json(args[i], nulls[i], result, types[i], false);
1371  }
1372 
1373  appendStringInfoChar(result, ']');
1374 
1375  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1376 }
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:658
#define PointerGetDatum(X)
Definition: postgres.h:600

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

1327 {
1328  Datum *args;
1329  bool *nulls;
1330  Oid *types;
1331 
1332  /* build argument values to build the object */
1333  int nargs = extract_variadic_args(fcinfo, 0, true,
1334  &args, &types, &nulls);
1335 
1336  if (nargs < 0)
1337  PG_RETURN_NULL();
1338 
1339  PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
1340 }
Datum json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1238

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

1347 {
1349 }

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

1240 {
1241  int i;
1242  const char *sep = "";
1243  StringInfo result;
1244  JsonUniqueBuilderState unique_check;
1245 
1246  if (nargs % 2 != 0)
1247  ereport(ERROR,
1248  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1249  errmsg("argument list must have even number of elements"),
1250  /* translator: %s is a SQL function name */
1251  errhint("The arguments of %s must consist of alternating keys and values.",
1252  "json_build_object()")));
1253 
1254  result = makeStringInfo();
1255 
1256  appendStringInfoChar(result, '{');
1257 
1258  if (unique_keys)
1259  json_unique_builder_init(&unique_check);
1260 
1261  for (i = 0; i < nargs; i += 2)
1262  {
1263  StringInfo out;
1264  bool skip;
1265  int key_offset;
1266 
1267  /* Skip null values if absent_on_null */
1268  skip = absent_on_null && nulls[i + 1];
1269 
1270  if (skip)
1271  {
1272  /* If key uniqueness check is needed we must save skipped keys */
1273  if (!unique_keys)
1274  continue;
1275 
1276  out = json_unique_builder_get_skipped_keys(&unique_check);
1277  }
1278  else
1279  {
1280  appendStringInfoString(result, sep);
1281  sep = ", ";
1282  out = result;
1283  }
1284 
1285  /* process key */
1286  if (nulls[i])
1287  ereport(ERROR,
1288  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1289  errmsg("argument %d cannot be null", i + 1),
1290  errhint("Object keys should be text.")));
1291 
1292  /* save key offset before key appending */
1293  key_offset = out->len;
1294 
1295  add_json(args[i], false, out, types[i], true);
1296 
1297  if (unique_keys)
1298  {
1299  /* check key uniqueness after key appending */
1300  const char *key = &out->data[key_offset];
1301 
1302  if (!json_unique_check_key(&unique_check.check, key, 0))
1303  ereport(ERROR,
1304  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1305  errmsg("duplicate JSON key %s", key)));
1306 
1307  if (skip)
1308  continue;
1309  }
1310 
1311  appendStringInfoString(result, " : ");
1312 
1313  /* process value */
1314  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1315  }
1316 
1317  appendStringInfoChar(result, '}');
1318 
1319  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
1320 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
Definition: json.c:983
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Definition: json.c:998
static StringInfo json_unique_builder_get_skipped_keys(JsonUniqueBuilderState *cxt)
Definition: json.c:1007
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:116
JsonUniqueCheckState check
Definition: json.c:47

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

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

Definition at line 166 of file json.c.

169 {
170  bool typisvarlena;
171 
172  /* Look through any domain */
173  typoid = getBaseType(typoid);
174 
175  *outfuncoid = InvalidOid;
176 
177  /*
178  * We need to get the output function for everything except date and
179  * timestamp types, array and composite types, booleans, and non-builtin
180  * types where there's a cast to json.
181  */
182 
183  switch (typoid)
184  {
185  case BOOLOID:
186  *tcategory = JSONTYPE_BOOL;
187  break;
188 
189  case INT2OID:
190  case INT4OID:
191  case INT8OID:
192  case FLOAT4OID:
193  case FLOAT8OID:
194  case NUMERICOID:
195  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
196  *tcategory = JSONTYPE_NUMERIC;
197  break;
198 
199  case DATEOID:
200  *tcategory = JSONTYPE_DATE;
201  break;
202 
203  case TIMESTAMPOID:
204  *tcategory = JSONTYPE_TIMESTAMP;
205  break;
206 
207  case TIMESTAMPTZOID:
208  *tcategory = JSONTYPE_TIMESTAMPTZ;
209  break;
210 
211  case JSONOID:
212  case JSONBOID:
213  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
214  *tcategory = JSONTYPE_JSON;
215  break;
216 
217  default:
218  /* Check for arrays and composites */
219  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
220  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
221  *tcategory = JSONTYPE_ARRAY;
222  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
223  *tcategory = JSONTYPE_COMPOSITE;
224  else
225  {
226  /* It's probably the general case ... */
227  *tcategory = JSONTYPE_OTHER;
228  /* but let's look for a cast to json, if it's not built-in */
229  if (typoid >= FirstNormalObjectId)
230  {
231  Oid castfunc;
232  CoercionPathType ctype;
233 
234  ctype = find_coercion_pathway(JSONOID, typoid,
236  &castfunc);
237  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
238  {
239  *tcategory = JSONTYPE_CAST;
240  *outfuncoid = castfunc;
241  }
242  else
243  {
244  /* non builtin type with no cast */
245  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
246  }
247  }
248  else
249  {
250  /* any other builtin type */
251  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
252  }
253  }
254  break;
255  }
256 }
#define OidIsValid(objectId)
Definition: c.h:710
@ JSONTYPE_OTHER
Definition: json.h:31
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2716
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2612
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2478
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:475
#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(), ExecInitExprRec(), 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 98 of file json.c.

99 {
100  char *json = PG_GETARG_CSTRING(0);
101  text *result = cstring_to_text(json);
102  JsonLexContext *lex;
103 
104  /* validate it */
105  lex = makeJsonLexContext(result, false);
107 
108  /* Internal representation is the same as text, for now */
109  PG_RETURN_TEXT_P(result);
110 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
JsonSemAction nullSemAction
Definition: jsonapi.c:56
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
text * cstring_to_text(const char *s)
Definition: varlena.c:188

References cstring_to_text(), makeJsonLexContext(), nullSemAction, PG_GETARG_CSTRING, pg_parse_json_or_ereport(), and PG_RETURN_TEXT_P.

◆ json_object()

Datum json_object ( PG_FUNCTION_ARGS  )

Definition at line 1414 of file json.c.

1415 {
1416  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1417  int ndims = ARR_NDIM(in_array);
1418  StringInfoData result;
1419  Datum *in_datums;
1420  bool *in_nulls;
1421  int in_count,
1422  count,
1423  i;
1424  text *rval;
1425  char *v;
1426 
1427  switch (ndims)
1428  {
1429  case 0:
1431  break;
1432 
1433  case 1:
1434  if ((ARR_DIMS(in_array)[0]) % 2)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1437  errmsg("array must have even number of elements")));
1438  break;
1439 
1440  case 2:
1441  if ((ARR_DIMS(in_array)[1]) != 2)
1442  ereport(ERROR,
1443  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1444  errmsg("array must have two columns")));
1445  break;
1446 
1447  default:
1448  ereport(ERROR,
1449  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1450  errmsg("wrong number of array subscripts")));
1451  }
1452 
1453  deconstruct_array(in_array,
1454  TEXTOID, -1, false, TYPALIGN_INT,
1455  &in_datums, &in_nulls, &in_count);
1456 
1457  count = in_count / 2;
1458 
1459  initStringInfo(&result);
1460 
1461  appendStringInfoChar(&result, '{');
1462 
1463  for (i = 0; i < count; ++i)
1464  {
1465  if (in_nulls[i * 2])
1466  ereport(ERROR,
1467  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1468  errmsg("null value not allowed for object key")));
1469 
1470  v = TextDatumGetCString(in_datums[i * 2]);
1471  if (i > 0)
1472  appendStringInfoString(&result, ", ");
1473  escape_json(&result, v);
1474  appendStringInfoString(&result, " : ");
1475  pfree(v);
1476  if (in_nulls[i * 2 + 1])
1477  appendStringInfoString(&result, "null");
1478  else
1479  {
1480  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1481  escape_json(&result, v);
1482  pfree(v);
1483  }
1484  }
1485 
1486  appendStringInfoChar(&result, '}');
1487 
1488  pfree(in_datums);
1489  pfree(in_nulls);
1490 
1491  rval = cstring_to_text_with_len(result.data, result.len);
1492  pfree(result.data);
1493 
1494  PG_RETURN_TEXT_P(rval);
1495 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define CStringGetTextDatum(s)
Definition: builtins.h:85
#define TextDatumGetCString(d)
Definition: builtins.h:86
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(), 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 1200 of file json.c.

1201 {
1203 
1204  /* cannot be called directly because of internal-type argument */
1205  Assert(AggCheckCallContext(fcinfo, NULL));
1206 
1207  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
1208 
1209  /* NULL result for no rows in, as is standard with aggregates */
1210  if (state == NULL)
1211  PG_RETURN_NULL();
1212 
1213  /* Else return state with appropriate object terminator added */
1215 }

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

1174 {
1175  return json_object_agg_transfn_worker(fcinfo, true, false);
1176 }
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: json.c:1028

References json_object_agg_transfn_worker().

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1164 of file json.c.

1165 {
1166  return json_object_agg_transfn_worker(fcinfo, false, false);
1167 }

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

1030 {
1031  MemoryContext aggcontext,
1032  oldcontext;
1034  StringInfo out;
1035  Datum arg;
1036  bool skip;
1037  int key_offset;
1038 
1039  if (!AggCheckCallContext(fcinfo, &aggcontext))
1040  {
1041  /* cannot be called directly because of internal-type argument */
1042  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
1043  }
1044 
1045  if (PG_ARGISNULL(0))
1046  {
1047  Oid arg_type;
1048 
1049  /*
1050  * Make the StringInfo in a context where it will persist for the
1051  * duration of the aggregate call. Switching context is only needed
1052  * for this initial step, as the StringInfo routines make sure they
1053  * use the right context to enlarge the object if necessary.
1054  */
1055  oldcontext = MemoryContextSwitchTo(aggcontext);
1056  state = (JsonAggState *) palloc(sizeof(JsonAggState));
1057  state->str = makeStringInfo();
1058  if (unique_keys)
1059  json_unique_builder_init(&state->unique_check);
1060  else
1061  memset(&state->unique_check, 0, sizeof(state->unique_check));
1062  MemoryContextSwitchTo(oldcontext);
1063 
1064  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1065 
1066  if (arg_type == InvalidOid)
1067  ereport(ERROR,
1068  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1069  errmsg("could not determine data type for argument %d", 1)));
1070 
1071  json_categorize_type(arg_type, &state->key_category,
1072  &state->key_output_func);
1073 
1074  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1075 
1076  if (arg_type == InvalidOid)
1077  ereport(ERROR,
1078  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1079  errmsg("could not determine data type for argument %d", 2)));
1080 
1081  json_categorize_type(arg_type, &state->val_category,
1082  &state->val_output_func);
1083 
1084  appendStringInfoString(state->str, "{ ");
1085  }
1086  else
1087  {
1089  }
1090 
1091  /*
1092  * Note: since json_object_agg() is declared as taking type "any", the
1093  * parser will not do any type conversion on unknown-type literals (that
1094  * is, undecorated strings or NULLs). Such values will arrive here as
1095  * type UNKNOWN, which fortunately does not matter to us, since
1096  * unknownout() works fine.
1097  */
1098 
1099  if (PG_ARGISNULL(1))
1100  ereport(ERROR,
1101  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1102  errmsg("field name must not be null")));
1103 
1104  /* Skip null values if absent_on_null */
1105  skip = absent_on_null && PG_ARGISNULL(2);
1106 
1107  if (skip)
1108  {
1109  /* If key uniqueness check is needed we must save skipped keys */
1110  if (!unique_keys)
1112 
1113  out = json_unique_builder_get_skipped_keys(&state->unique_check);
1114  }
1115  else
1116  {
1117  out = state->str;
1118 
1119  /*
1120  * Append comma delimiter only if we have already outputted some
1121  * fields after the initial string "{ ".
1122  */
1123  if (out->len > 2)
1124  appendStringInfoString(out, ", ");
1125  }
1126 
1127  arg = PG_GETARG_DATUM(1);
1128 
1129  key_offset = out->len;
1130 
1131  datum_to_json(arg, false, out, state->key_category,
1132  state->key_output_func, true);
1133 
1134  if (unique_keys)
1135  {
1136  const char *key = &out->data[key_offset];
1137 
1138  if (!json_unique_check_key(&state->unique_check.check, key, 0))
1139  ereport(ERROR,
1140  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1141  errmsg("duplicate JSON key %s", key)));
1142 
1143  if (skip)
1145  }
1146 
1147  appendStringInfoString(state->str, " : ");
1148 
1149  if (PG_ARGISNULL(2))
1150  arg = (Datum) 0;
1151  else
1152  arg = PG_GETARG_DATUM(2);
1153 
1154  datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
1155  state->val_output_func, false);
1156 
1158 }
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_skipped_keys(), 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 1191 of file json.c.

1192 {
1193  return json_object_agg_transfn_worker(fcinfo, true, true);
1194 }

References json_object_agg_transfn_worker().

◆ json_object_agg_unique_transfn()

Datum json_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1182 of file json.c.

1183 {
1184  return json_object_agg_transfn_worker(fcinfo, false, true);
1185 }

References json_object_agg_transfn_worker().

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1504 of file json.c.

1505 {
1506  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1507  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1508  int nkdims = ARR_NDIM(key_array);
1509  int nvdims = ARR_NDIM(val_array);
1510  StringInfoData result;
1511  Datum *key_datums,
1512  *val_datums;
1513  bool *key_nulls,
1514  *val_nulls;
1515  int key_count,
1516  val_count,
1517  i;
1518  text *rval;
1519  char *v;
1520 
1521  if (nkdims > 1 || nkdims != nvdims)
1522  ereport(ERROR,
1523  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1524  errmsg("wrong number of array subscripts")));
1525 
1526  if (nkdims == 0)
1528 
1529  deconstruct_array(key_array,
1530  TEXTOID, -1, false, TYPALIGN_INT,
1531  &key_datums, &key_nulls, &key_count);
1532 
1533  deconstruct_array(val_array,
1534  TEXTOID, -1, false, TYPALIGN_INT,
1535  &val_datums, &val_nulls, &val_count);
1536 
1537  if (key_count != val_count)
1538  ereport(ERROR,
1539  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1540  errmsg("mismatched array dimensions")));
1541 
1542  initStringInfo(&result);
1543 
1544  appendStringInfoChar(&result, '{');
1545 
1546  for (i = 0; i < key_count; ++i)
1547  {
1548  if (key_nulls[i])
1549  ereport(ERROR,
1550  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1551  errmsg("null value not allowed for object key")));
1552 
1553  v = TextDatumGetCString(key_datums[i]);
1554  if (i > 0)
1555  appendStringInfoString(&result, ", ");
1556  escape_json(&result, v);
1557  appendStringInfoString(&result, " : ");
1558  pfree(v);
1559  if (val_nulls[i])
1560  appendStringInfoString(&result, "null");
1561  else
1562  {
1563  v = TextDatumGetCString(val_datums[i]);
1564  escape_json(&result, v);
1565  pfree(v);
1566  }
1567  }
1568 
1569  appendStringInfoChar(&result, '}');
1570 
1571  pfree(key_datums);
1572  pfree(key_nulls);
1573  pfree(val_datums);
1574  pfree(val_nulls);
1575 
1576  rval = cstring_to_text_with_len(result.data, result.len);
1577  pfree(result.data);
1578 
1579  PG_RETURN_TEXT_P(rval);
1580 }

References appendStringInfoChar(), appendStringInfoString(), ARR_NDIM, cstring_to_text_with_len(), CStringGetTextDatum, StringInfoData::data, deconstruct_array(), 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 116 of file json.c.

117 {
118  /* we needn't detoast because text_to_cstring will handle that */
119  Datum txt = PG_GETARG_DATUM(0);
120 
122 }
#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 142 of file json.c.

143 {
145  char *str;
146  int nbytes;
147  JsonLexContext *lex;
148 
149  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
150 
151  /* Validate it. */
152  lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false);
154 
156 }
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:144
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
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 128 of file json.c.

129 {
130  text *t = PG_GETARG_TEXT_PP(0);
132 
136 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348

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

1742 {
1743  text *json = PG_GETARG_TEXT_PP(0);
1744  char *type;
1745  JsonTokenType tok;
1746 
1747  /* Lex exactly one token from the input and check its type. */
1748  tok = json_get_first_token(json, true);
1749 
1750  switch (tok)
1751  {
1753  type = "object";
1754  break;
1756  type = "array";
1757  break;
1758  case JSON_TOKEN_STRING:
1759  type = "string";
1760  break;
1761  case JSON_TOKEN_NUMBER:
1762  type = "number";
1763  break;
1764  case JSON_TOKEN_TRUE:
1765  case JSON_TOKEN_FALSE:
1766  type = "boolean";
1767  break;
1768  case JSON_TOKEN_NULL:
1769  type = "null";
1770  break;
1771  default:
1772  elog(ERROR, "unexpected json token: %d", tok);
1773  }
1774 
1776 }
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
JsonTokenType json_get_first_token(text *json, bool throw_error)
Definition: jsonfuncs.c:5577

References cstring_to_text(), elog, ERROR, json_get_first_token(), JSON_TOKEN_ARRAY_START, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, and generate_unaccent_rules::type.

◆ json_unique_builder_get_skipped_keys()

static StringInfo json_unique_builder_get_skipped_keys ( JsonUniqueBuilderState cxt)
static

Definition at line 1007 of file json.c.

1008 {
1009  StringInfo out = &cxt->skipped_keys;
1010 
1011  if (!out->data)
1012  {
1013  MemoryContext oldcxt = MemoryContextSwitchTo(cxt->mcxt);
1014 
1015  initStringInfo(out);
1016  MemoryContextSwitchTo(oldcxt);
1017  }
1018 
1019  return out;
1020 }
StringInfoData skipped_keys
Definition: json.c:48
MemoryContext mcxt
Definition: json.c:49

References StringInfoData::data, initStringInfo(), 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 998 of file json.c.

999 {
1001  cxt->mcxt = CurrentMemoryContext;
1002  cxt->skipped_keys.data = NULL;
1003 }
static void json_unique_check_init(JsonUniqueCheckState *cxt)
Definition: json.c:965
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42

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

966 {
967  HASHCTL ctl;
968 
969  memset(&ctl, 0, sizeof(ctl));
970  ctl.keysize = sizeof(JsonUniqueHashEntry);
971  ctl.entrysize = sizeof(JsonUniqueHashEntry);
973  ctl.hash = json_unique_hash;
975 
976  *cxt = hash_create("json object hashtable",
977  32,
978  &ctl,
980 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#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:938
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
Definition: json.c:949
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 983 of file json.c.

984 {
985  JsonUniqueHashEntry entry;
986  bool found;
987 
988  entry.key = key;
989  entry.key_len = strlen(key);
990  entry.object_id = object_id;
991 
992  (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
993 
994  return !found;
995 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
@ HASH_ENTER
Definition: hsearch.h:114
const char * key
Definition: json.c:39

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

939 {
940  const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
942 
943  hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
944 
945  return DatumGetUInt32(hash);
946 }
unsigned int uint32
Definition: c.h:441
uint32 hash_bytes_uint32(uint32 k)
Definition: hashfn.c:610
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition: hashfn.c:146
#define DatumGetUInt32(X)
Definition: postgres.h:530
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 949 of file json.c.

950 {
951  const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
952  const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
953 
954  if (entry1->object_id != entry2->object_id)
955  return entry1->object_id > entry2->object_id ? 1 : -1;
956 
957  if (entry1->key_len != entry2->key_len)
958  return entry1->key_len > entry2->key_len ? 1 : -1;
959 
960  return strncmp(entry1->key, entry2->key, entry1->key_len);
961 }

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

Referenced by json_unique_check_init().

◆ json_unique_object_end()

static void json_unique_object_end ( void *  _state)
static

Definition at line 1646 of file json.c.

1647 {
1648  JsonUniqueParsingState *state = _state;
1649  JsonUniqueStackEntry *entry;
1650 
1651  if (!state->unique)
1652  return;
1653 
1654  entry = state->stack;
1655  state->stack = entry->parent; /* pop object from stack */
1656  pfree(entry);
1657 }
struct JsonUniqueStackEntry * parent
Definition: json.c:55

References JsonUniqueStackEntry::parent, and pfree().

Referenced by json_validate().

◆ json_unique_object_field_start()

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

Definition at line 1660 of file json.c.

1661 {
1662  JsonUniqueParsingState *state = _state;
1663  JsonUniqueStackEntry *entry;
1664 
1665  if (!state->unique)
1666  return;
1667 
1668  /* find key collision in the current object */
1669  if (json_unique_check_key(&state->check, field, state->stack->object_id))
1670  return;
1671 
1672  state->unique = false;
1673 
1674  /* pop all objects entries */
1675  while ((entry = state->stack))
1676  {
1677  state->stack = entry->parent;
1678  pfree(entry);
1679  }
1680 }

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

Referenced by json_validate().

◆ json_unique_object_start()

static void json_unique_object_start ( void *  _state)
static

Definition at line 1630 of file json.c.

1631 {
1632  JsonUniqueParsingState *state = _state;
1633  JsonUniqueStackEntry *entry;
1634 
1635  if (!state->unique)
1636  return;
1637 
1638  /* push object entry to stack */
1639  entry = palloc(sizeof(*entry));
1640  entry->object_id = state->id_counter++;
1641  entry->parent = state->stack;
1642  state->stack = entry;
1643 }

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

1685 {
1686  JsonLexContext *lex = makeJsonLexContext(json, check_unique_keys);
1687  JsonSemAction uniqueSemAction = {0};
1689  JsonParseErrorType result;
1690 
1691  if (check_unique_keys)
1692  {
1693  state.lex = lex;
1694  state.stack = NULL;
1695  state.id_counter = 0;
1696  state.unique = true;
1697  json_unique_check_init(&state.check);
1698 
1699  uniqueSemAction.semstate = &state;
1700  uniqueSemAction.object_start = json_unique_object_start;
1702  uniqueSemAction.object_end = json_unique_object_end;
1703  }
1704 
1705  result = pg_parse_json(lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
1706 
1707  if (result != JSON_SUCCESS)
1708  {
1709  if (throw_error)
1710  json_ereport_error(result, lex);
1711 
1712  return false; /* invalid json */
1713  }
1714 
1715  if (check_unique_keys && !state.unique)
1716  {
1717  if (throw_error)
1718  ereport(ERROR,
1719  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1720  errmsg("duplicate JSON object key value")));
1721 
1722  return false; /* not unique keys */
1723  }
1724 
1725  return true; /* ok */
1726 }
static void json_unique_object_start(void *_state)
Definition: json.c:1630
static void json_unique_object_field_start(void *_state, char *field, bool isnull)
Definition: json.c:1660
static void json_unique_object_end(void *_state)
Definition: json.c:1646
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:168
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SUCCESS
Definition: jsonapi.h:38
void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonfuncs.c:611
json_struct_action object_start
Definition: jsonapi.h:107
json_ofield_action object_field_start
Definition: jsonapi.h:111
void * semstate
Definition: jsonapi.h:106
json_struct_action object_end
Definition: jsonapi.h:108

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

376 {
377  if (!buf)
378  buf = palloc(MAXDATELEN + 1);
379 
380  switch (typid)
381  {
382  case DATEOID:
383  {
384  DateADT date;
385  struct pg_tm tm;
386 
388 
389  /* Same as date_out(), but forcing DateStyle */
390  if (DATE_NOT_FINITE(date))
392  else
393  {
395  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
397  }
398  }
399  break;
400  case TIMEOID:
401  {
402  TimeADT time = DatumGetTimeADT(value);
403  struct pg_tm tt,
404  *tm = &tt;
405  fsec_t fsec;
406 
407  /* Same as time_out(), but forcing DateStyle */
408  time2tm(time, tm, &fsec);
409  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
410  }
411  break;
412  case TIMETZOID:
413  {
415  struct pg_tm tt,
416  *tm = &tt;
417  fsec_t fsec;
418  int tz;
419 
420  /* Same as timetz_out(), but forcing DateStyle */
421  timetz2tm(time, tm, &fsec, &tz);
422  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
423  }
424  break;
425  case TIMESTAMPOID:
426  {
428  struct pg_tm tm;
429  fsec_t fsec;
430 
432  /* Same as timestamp_out(), but forcing DateStyle */
435  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
436  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
437  else
438  ereport(ERROR,
439  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
440  errmsg("timestamp out of range")));
441  }
442  break;
443  case TIMESTAMPTZOID:
444  {
446  struct pg_tm tm;
447  int tz;
448  fsec_t fsec;
449  const char *tzn = NULL;
450 
452 
453  /*
454  * If a time zone is specified, we apply the time-zone shift,
455  * convert timestamptz to pg_tm as if it were without a time
456  * zone, and then use the specified time zone for converting
457  * the timestamp into a string.
458  */
459  if (tzp)
460  {
461  tz = *tzp;
463  }
464 
465  /* Same as timestamptz_out(), but forcing DateStyle */
468  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
469  tzp ? NULL : &tzn, NULL) == 0)
470  {
471  if (tzp)
472  tm.tm_isdst = 1; /* set time-zone presence flag */
473 
474  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
475  }
476  else
477  ereport(ERROR,
478  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
479  errmsg("timestamp out of range")));
480  }
481  break;
482  default:
483  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
484  return NULL;
485  }
486 
487  return buf;
488 }
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4228
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:309
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4258
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4143
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1527
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1816
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define USECS_PER_SEC
Definition: timestamp.h:133
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:161
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:202
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2377
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1476
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:287
#define DATE_NOT_FINITE(j)
Definition: date.h:43
#define DatumGetTimeTzADTP(X)
Definition: date.h:55
int32 DateADT
Definition: date.h:23
#define DatumGetTimeADT(X)
Definition: date.h:54
int64 TimeADT
Definition: date.h:25
#define DatumGetDateADT(X)
Definition: date.h:53
static struct @151 value
static struct pg_tm tm
Definition: localtime.c:102
#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
#define DatumGetTimestamp(X)
Definition: timestamp.h:27
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28

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

719 {
720  Datum array = PG_GETARG_DATUM(0);
721  StringInfo result;
722 
723  result = makeStringInfo();
724 
725  composite_to_json(array, result, false);
726 
728 }

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

735 {
736  Datum array = PG_GETARG_DATUM(0);
737  bool use_line_feeds = PG_GETARG_BOOL(1);
738  StringInfo result;
739 
740  result = makeStringInfo();
741 
742  composite_to_json(array, result, use_line_feeds);
743 
745 }

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

794 {
796  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
797  JsonTypeCategory tcategory;
798  Oid outfuncoid;
799 
800  if (val_type == InvalidOid)
801  ereport(ERROR,
802  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
803  errmsg("could not determine input data type")));
804 
805  json_categorize_type(val_type,
806  &tcategory, &outfuncoid);
807 
808  PG_RETURN_DATUM(to_json_worker(val, tcategory, outfuncoid));
809 }
Datum to_json_worker(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:748

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

◆ to_json_is_immutable()

bool to_json_is_immutable ( Oid  typoid)

Definition at line 758 of file json.c.

759 {
760  JsonTypeCategory tcategory;
761  Oid outfuncoid;
762 
763  json_categorize_type(typoid, &tcategory, &outfuncoid);
764 
765  switch (tcategory)
766  {
767  case JSONTYPE_BOOL:
768  case JSONTYPE_JSON:
769  return true;
770 
771  case JSONTYPE_DATE:
772  case JSONTYPE_TIMESTAMP:
774  return false;
775 
776  case JSONTYPE_ARRAY:
777  return false; /* TODO recurse into elements */
778 
779  case JSONTYPE_COMPOSITE:
780  return false; /* TODO recurse into fields */
781 
782  case JSONTYPE_NUMERIC:
783  case JSONTYPE_CAST:
784  default:
785  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
786  }
787 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1761

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

Referenced by contain_mutable_functions_walker().

◆ to_json_worker()

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

Definition at line 748 of file json.c.

749 {
750  StringInfo result = makeStringInfo();
751 
752  datum_to_json(val, false, result, tcategory, outfuncoid, false);
753 
754  return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
755 }

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

Referenced by ExecEvalJsonConstructor(), and to_json().