PostgreSQL Source Code  git master
json.c File Reference
#include "postgres.h"
#include "catalog/pg_type.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  JsonAggState
 

Typedefs

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)
 
Datum to_json (PG_FUNCTION_ARGS)
 
Datum json_agg_transfn (PG_FUNCTION_ARGS)
 
Datum json_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_transfn (PG_FUNCTION_ARGS)
 
Datum json_object_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum json_build_object (PG_FUNCTION_ARGS)
 
Datum json_build_object_noargs (PG_FUNCTION_ARGS)
 
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)
 
Datum json_typeof (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ JsonAggState

typedef struct JsonAggState JsonAggState

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

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

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

639 {
640  JsonTypeCategory tcategory;
641  Oid outfuncoid;
642 
643  if (val_type == InvalidOid)
644  ereport(ERROR,
645  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
646  errmsg("could not determine input data type")));
647 
648  if (is_null)
649  {
650  tcategory = JSONTYPE_NULL;
651  outfuncoid = InvalidOid;
652  }
653  else
654  json_categorize_type(val_type,
655  &tcategory, &outfuncoid);
656 
657  datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
658 }
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:145
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:247
#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(), and json_build_object().

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

478 {
479  int i;
480  const char *sep;
481 
482  Assert(dim < ndims);
483 
484  sep = use_line_feeds ? ",\n " : ",";
485 
486  appendStringInfoChar(result, '[');
487 
488  for (i = 1; i <= dims[dim]; i++)
489  {
490  if (i > 1)
491  appendStringInfoString(result, sep);
492 
493  if (dim + 1 == ndims)
494  {
495  datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
496  outfuncoid, false);
497  (*valcount)++;
498  }
499  else
500  {
501  /*
502  * Do we want line feeds on inner dimensions of arrays? For now
503  * we'll say no.
504  */
505  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
506  valcount, tcategory, outfuncoid, false);
507  }
508  }
509 
510  appendStringInfoChar(result, ']');
511 }
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:475
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 664 of file json.c.

665 {
666  Datum array = PG_GETARG_DATUM(0);
667  StringInfo result;
668 
669  result = makeStringInfo();
670 
671  array_to_json_internal(array, result, false);
672 
674 }
#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:517
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:201

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

518 {
519  ArrayType *v = DatumGetArrayTypeP(array);
520  Oid element_type = ARR_ELEMTYPE(v);
521  int *dim;
522  int ndim;
523  int nitems;
524  int count = 0;
525  Datum *elements;
526  bool *nulls;
527  int16 typlen;
528  bool typbyval;
529  char typalign;
530  JsonTypeCategory tcategory;
531  Oid outfuncoid;
532 
533  ndim = ARR_NDIM(v);
534  dim = ARR_DIMS(v);
535  nitems = ArrayGetNItems(ndim, dim);
536 
537  if (nitems <= 0)
538  {
539  appendStringInfoString(result, "[]");
540  return;
541  }
542 
543  get_typlenbyvalalign(element_type,
544  &typlen, &typbyval, &typalign);
545 
546  json_categorize_type(element_type,
547  &tcategory, &outfuncoid);
548 
549  deconstruct_array(v, element_type, typlen, typbyval,
550  typalign, &elements, &nulls,
551  &nitems);
552 
553  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
554  outfuncoid, use_line_feeds);
555 
556  pfree(elements);
557  pfree(nulls);
558 }
#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:3602
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:477
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2229
void pfree(void *pointer)
Definition: mcxt.c:1436
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 680 of file json.c.

681 {
682  Datum array = PG_GETARG_DATUM(0);
683  bool use_line_feeds = PG_GETARG_BOOL(1);
684  StringInfo result;
685 
686  result = makeStringInfo();
687 
688  array_to_json_internal(array, result, use_line_feeds);
689 
691 }
#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 974 of file json.c.

975 {
976  /* custom version of cstring_to_text_with_len */
977  int buflen = buffer->len;
978  int addlen = strlen(addon);
979  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
980 
981  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
982  memcpy(VARDATA(result), buffer->data, buflen);
983  memcpy(VARDATA(result) + buflen, addon, addlen);
984 
985  return result;
986 }
#define VARHDRSZ
Definition: c.h:676
void * palloc(Size size)
Definition: mcxt.c:1210
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 564 of file json.c.

565 {
566  HeapTupleHeader td;
567  Oid tupType;
568  int32 tupTypmod;
569  TupleDesc tupdesc;
570  HeapTupleData tmptup,
571  *tuple;
572  int i;
573  bool needsep = false;
574  const char *sep;
575 
576  sep = use_line_feeds ? ",\n " : ",";
577 
578  td = DatumGetHeapTupleHeader(composite);
579 
580  /* Extract rowtype info and find a tupdesc */
581  tupType = HeapTupleHeaderGetTypeId(td);
582  tupTypmod = HeapTupleHeaderGetTypMod(td);
583  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
584 
585  /* Build a temporary HeapTuple control structure */
587  tmptup.t_data = td;
588  tuple = &tmptup;
589 
590  appendStringInfoChar(result, '{');
591 
592  for (i = 0; i < tupdesc->natts; i++)
593  {
594  Datum val;
595  bool isnull;
596  char *attname;
597  JsonTypeCategory tcategory;
598  Oid outfuncoid;
599  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
600 
601  if (att->attisdropped)
602  continue;
603 
604  if (needsep)
605  appendStringInfoString(result, sep);
606  needsep = true;
607 
608  attname = NameStr(att->attname);
609  escape_json(result, attname);
610  appendStringInfoChar(result, ':');
611 
612  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
613 
614  if (isnull)
615  {
616  tcategory = JSONTYPE_NULL;
617  outfuncoid = InvalidOid;
618  }
619  else
620  json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
621 
622  datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
623  }
624 
625  appendStringInfoChar(result, '}');
626  ReleaseTupleDesc(tupdesc);
627 }
#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:1272
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: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 247 of file json.c.

250 {
251  char *outputstr;
252  text *jsontext;
253 
255 
256  /* callers are expected to ensure that null keys are not passed in */
257  Assert(!(key_scalar && is_null));
258 
259  if (is_null)
260  {
261  appendStringInfoString(result, "null");
262  return;
263  }
264 
265  if (key_scalar &&
266  (tcategory == JSONTYPE_ARRAY ||
267  tcategory == JSONTYPE_COMPOSITE ||
268  tcategory == JSONTYPE_JSON ||
269  tcategory == JSONTYPE_CAST))
270  ereport(ERROR,
271  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
272  errmsg("key value must be scalar, not array, composite, or json")));
273 
274  switch (tcategory)
275  {
276  case JSONTYPE_ARRAY:
277  array_to_json_internal(val, result, false);
278  break;
279  case JSONTYPE_COMPOSITE:
280  composite_to_json(val, result, false);
281  break;
282  case JSONTYPE_BOOL:
283  outputstr = DatumGetBool(val) ? "true" : "false";
284  if (key_scalar)
285  escape_json(result, outputstr);
286  else
287  appendStringInfoString(result, outputstr);
288  break;
289  case JSONTYPE_NUMERIC:
290  outputstr = OidOutputFunctionCall(outfuncoid, val);
291 
292  /*
293  * Don't call escape_json for a non-key if it's a valid JSON
294  * number.
295  */
296  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
297  appendStringInfoString(result, outputstr);
298  else
299  escape_json(result, outputstr);
300  pfree(outputstr);
301  break;
302  case JSONTYPE_DATE:
303  {
304  char buf[MAXDATELEN + 1];
305 
306  JsonEncodeDateTime(buf, val, DATEOID, NULL);
307  appendStringInfo(result, "\"%s\"", buf);
308  }
309  break;
310  case JSONTYPE_TIMESTAMP:
311  {
312  char buf[MAXDATELEN + 1];
313 
314  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
315  appendStringInfo(result, "\"%s\"", buf);
316  }
317  break;
319  {
320  char buf[MAXDATELEN + 1];
321 
322  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
323  appendStringInfo(result, "\"%s\"", buf);
324  }
325  break;
326  case JSONTYPE_JSON:
327  /* JSON and JSONB output will already be escaped */
328  outputstr = OidOutputFunctionCall(outfuncoid, val);
329  appendStringInfoString(result, outputstr);
330  pfree(outputstr);
331  break;
332  case JSONTYPE_CAST:
333  /* outfuncoid refers to a cast function, not an output function */
334  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
335  outputstr = text_to_cstring(jsontext);
336  appendStringInfoString(result, outputstr);
337  pfree(outputstr);
338  pfree(jsontext);
339  break;
340  default:
341  outputstr = OidOutputFunctionCall(outfuncoid, val);
342  escape_json(result, outputstr);
343  pfree(outputstr);
344  break;
345  }
346 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1750
#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:354
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:564
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:3454
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:222

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(), json_object_agg_transfn(), and to_json().

◆ escape_json()

void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 1272 of file json.c.

1273 {
1274  const char *p;
1275 
1277  for (p = str; *p; p++)
1278  {
1279  switch (*p)
1280  {
1281  case '\b':
1282  appendStringInfoString(buf, "\\b");
1283  break;
1284  case '\f':
1285  appendStringInfoString(buf, "\\f");
1286  break;
1287  case '\n':
1288  appendStringInfoString(buf, "\\n");
1289  break;
1290  case '\r':
1291  appendStringInfoString(buf, "\\r");
1292  break;
1293  case '\t':
1294  appendStringInfoString(buf, "\\t");
1295  break;
1296  case '"':
1297  appendStringInfoString(buf, "\\\"");
1298  break;
1299  case '\\':
1300  appendStringInfoString(buf, "\\\\");
1301  break;
1302  default:
1303  if ((unsigned char) *p < ' ')
1304  appendStringInfo(buf, "\\u%04x", (int) *p);
1305  else
1307  break;
1308  }
1309  }
1311 }
#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 835 of file json.c.

836 {
838 
839  /* cannot be called directly because of internal-type argument */
840  Assert(AggCheckCallContext(fcinfo, NULL));
841 
842  state = PG_ARGISNULL(0) ?
843  NULL :
845 
846  /* NULL result for no rows in, as is standard with aggregates */
847  if (state == NULL)
848  PG_RETURN_NULL();
849 
850  /* Else return state with appropriate array terminator added */
852 }
#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:974
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4513
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_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 759 of file json.c.

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

References AggCheckCallContext(), appendStringInfoChar(), appendStringInfoString(), datum_to_json(), elog(), ereport, errcode(), errmsg(), ERROR, 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.

◆ json_build_array()

Datum json_build_array ( PG_FUNCTION_ARGS  )

Definition at line 1058 of file json.c.

1059 {
1060  int nargs;
1061  int i;
1062  const char *sep = "";
1063  StringInfo result;
1064  Datum *args;
1065  bool *nulls;
1066  Oid *types;
1067 
1068  /* fetch argument values to build the array */
1069  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
1070 
1071  if (nargs < 0)
1072  PG_RETURN_NULL();
1073 
1074  result = makeStringInfo();
1075 
1076  appendStringInfoChar(result, '[');
1077 
1078  for (i = 0; i < nargs; i++)
1079  {
1080  appendStringInfoString(result, sep);
1081  sep = ", ";
1082  add_json(args[i], nulls[i], result, types[i], false);
1083  }
1084 
1085  appendStringInfoChar(result, ']');
1086 
1088 }
struct typedefs * types
Definition: ecpg.c:29
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2006
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:637

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

◆ json_build_array_noargs()

Datum json_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1094 of file json.c.

1095 {
1097 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_build_object()

Datum json_build_object ( PG_FUNCTION_ARGS  )

Definition at line 992 of file json.c.

993 {
994  int nargs;
995  int i;
996  const char *sep = "";
997  StringInfo result;
998  Datum *args;
999  bool *nulls;
1000  Oid *types;
1001 
1002  /* fetch argument values to build the object */
1003  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
1004 
1005  if (nargs < 0)
1006  PG_RETURN_NULL();
1007 
1008  if (nargs % 2 != 0)
1009  ereport(ERROR,
1010  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1011  errmsg("argument list must have even number of elements"),
1012  /* translator: %s is a SQL function name */
1013  errhint("The arguments of %s must consist of alternating keys and values.",
1014  "json_build_object()")));
1015 
1016  result = makeStringInfo();
1017 
1018  appendStringInfoChar(result, '{');
1019 
1020  for (i = 0; i < nargs; i += 2)
1021  {
1022  appendStringInfoString(result, sep);
1023  sep = ", ";
1024 
1025  /* process key */
1026  if (nulls[i])
1027  ereport(ERROR,
1028  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1029  errmsg("argument %d cannot be null", i + 1),
1030  errhint("Object keys should be text.")));
1031 
1032  add_json(args[i], false, result, types[i], true);
1033 
1034  appendStringInfoString(result, " : ");
1035 
1036  /* process value */
1037  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
1038  }
1039 
1040  appendStringInfoChar(result, '}');
1041 
1043 }
int errhint(const char *fmt,...)
Definition: elog.c:1316

References add_json(), appendStringInfoChar(), appendStringInfoString(), generate_unaccent_rules::args, cstring_to_text_with_len(), StringInfoData::data, ereport, errcode(), errhint(), errmsg(), ERROR, extract_variadic_args(), i, StringInfoData::len, makeStringInfo(), PG_RETURN_NULL, PG_RETURN_TEXT_P, and types.

◆ json_build_object_noargs()

Datum json_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1049 of file json.c.

1050 {
1052 }

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

◆ json_categorize_type()

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

Definition at line 145 of file json.c.

148 {
149  bool typisvarlena;
150 
151  /* Look through any domain */
152  typoid = getBaseType(typoid);
153 
154  *outfuncoid = InvalidOid;
155 
156  /*
157  * We need to get the output function for everything except date and
158  * timestamp types, array and composite types, booleans, and non-builtin
159  * types where there's a cast to json.
160  */
161 
162  switch (typoid)
163  {
164  case BOOLOID:
165  *tcategory = JSONTYPE_BOOL;
166  break;
167 
168  case INT2OID:
169  case INT4OID:
170  case INT8OID:
171  case FLOAT4OID:
172  case FLOAT8OID:
173  case NUMERICOID:
174  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
175  *tcategory = JSONTYPE_NUMERIC;
176  break;
177 
178  case DATEOID:
179  *tcategory = JSONTYPE_DATE;
180  break;
181 
182  case TIMESTAMPOID:
183  *tcategory = JSONTYPE_TIMESTAMP;
184  break;
185 
186  case TIMESTAMPTZOID:
187  *tcategory = JSONTYPE_TIMESTAMPTZ;
188  break;
189 
190  case JSONOID:
191  case JSONBOID:
192  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
193  *tcategory = JSONTYPE_JSON;
194  break;
195 
196  default:
197  /* Check for arrays and composites */
198  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
199  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
200  *tcategory = JSONTYPE_ARRAY;
201  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
202  *tcategory = JSONTYPE_COMPOSITE;
203  else
204  {
205  /* It's probably the general case ... */
206  *tcategory = JSONTYPE_OTHER;
207  /* but let's look for a cast to json, if it's not built-in */
208  if (typoid >= FirstNormalObjectId)
209  {
210  Oid castfunc;
211  CoercionPathType ctype;
212 
213  ctype = find_coercion_pathway(JSONOID, typoid,
215  &castfunc);
216  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
217  {
218  *tcategory = JSONTYPE_CAST;
219  *outfuncoid = castfunc;
220  }
221  else
222  {
223  /* non builtin type with no cast */
224  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
225  }
226  }
227  else
228  {
229  /* any other builtin type */
230  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
231  }
232  }
233  break;
234  }
235 }
#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:609
#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(), json_object_agg_transfn(), and to_json().

◆ json_in()

Datum json_in ( PG_FUNCTION_ARGS  )

Definition at line 76 of file json.c.

77 {
78  char *json = PG_GETARG_CSTRING(0);
79  text *result = cstring_to_text(json);
80  JsonLexContext *lex;
81 
82  /* validate it */
83  lex = makeJsonLexContext(result, false);
84  if (!pg_parse_json_or_errsave(lex, &nullSemAction, fcinfo->context))
86 
87  /* Internal representation is the same as text */
88  PG_RETURN_TEXT_P(result);
89 }
#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:189

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

1107 {
1108  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1109  int ndims = ARR_NDIM(in_array);
1110  StringInfoData result;
1111  Datum *in_datums;
1112  bool *in_nulls;
1113  int in_count,
1114  count,
1115  i;
1116  text *rval;
1117  char *v;
1118 
1119  switch (ndims)
1120  {
1121  case 0:
1123  break;
1124 
1125  case 1:
1126  if ((ARR_DIMS(in_array)[0]) % 2)
1127  ereport(ERROR,
1128  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1129  errmsg("array must have even number of elements")));
1130  break;
1131 
1132  case 2:
1133  if ((ARR_DIMS(in_array)[1]) != 2)
1134  ereport(ERROR,
1135  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1136  errmsg("array must have two columns")));
1137  break;
1138 
1139  default:
1140  ereport(ERROR,
1141  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1142  errmsg("wrong number of array subscripts")));
1143  }
1144 
1145  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1146 
1147  count = in_count / 2;
1148 
1149  initStringInfo(&result);
1150 
1151  appendStringInfoChar(&result, '{');
1152 
1153  for (i = 0; i < count; ++i)
1154  {
1155  if (in_nulls[i * 2])
1156  ereport(ERROR,
1157  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1158  errmsg("null value not allowed for object key")));
1159 
1160  v = TextDatumGetCString(in_datums[i * 2]);
1161  if (i > 0)
1162  appendStringInfoString(&result, ", ");
1163  escape_json(&result, v);
1164  appendStringInfoString(&result, " : ");
1165  pfree(v);
1166  if (in_nulls[i * 2 + 1])
1167  appendStringInfoString(&result, "null");
1168  else
1169  {
1170  v = TextDatumGetCString(in_datums[i * 2 + 1]);
1171  escape_json(&result, v);
1172  pfree(v);
1173  }
1174  }
1175 
1176  appendStringInfoChar(&result, '}');
1177 
1178  pfree(in_datums);
1179  pfree(in_nulls);
1180 
1181  rval = cstring_to_text_with_len(result.data, result.len);
1182  pfree(result.data);
1183 
1184  PG_RETURN_TEXT_P(rval);
1185 }
#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:3668
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
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 951 of file json.c.

952 {
954 
955  /* cannot be called directly because of internal-type argument */
956  Assert(AggCheckCallContext(fcinfo, NULL));
957 
958  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
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 object terminator added */
966 }

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

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 860 of file json.c.

861 {
862  MemoryContext aggcontext,
863  oldcontext;
865  Datum arg;
866 
867  if (!AggCheckCallContext(fcinfo, &aggcontext))
868  {
869  /* cannot be called directly because of internal-type argument */
870  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
871  }
872 
873  if (PG_ARGISNULL(0))
874  {
875  Oid arg_type;
876 
877  /*
878  * Make the StringInfo in a context where it will persist for the
879  * duration of the aggregate call. Switching context is only needed
880  * for this initial step, as the StringInfo routines make sure they
881  * use the right context to enlarge the object if necessary.
882  */
883  oldcontext = MemoryContextSwitchTo(aggcontext);
884  state = (JsonAggState *) palloc(sizeof(JsonAggState));
885  state->str = makeStringInfo();
886  MemoryContextSwitchTo(oldcontext);
887 
888  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
889 
890  if (arg_type == InvalidOid)
891  ereport(ERROR,
892  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
893  errmsg("could not determine data type for argument %d", 1)));
894 
895  json_categorize_type(arg_type, &state->key_category,
896  &state->key_output_func);
897 
898  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
899 
900  if (arg_type == InvalidOid)
901  ereport(ERROR,
902  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
903  errmsg("could not determine data type for argument %d", 2)));
904 
905  json_categorize_type(arg_type, &state->val_category,
906  &state->val_output_func);
907 
908  appendStringInfoString(state->str, "{ ");
909  }
910  else
911  {
913  appendStringInfoString(state->str, ", ");
914  }
915 
916  /*
917  * Note: since json_object_agg() is declared as taking type "any", the
918  * parser will not do any type conversion on unknown-type literals (that
919  * is, undecorated strings or NULLs). Such values will arrive here as
920  * type UNKNOWN, which fortunately does not matter to us, since
921  * unknownout() works fine.
922  */
923 
924  if (PG_ARGISNULL(1))
925  ereport(ERROR,
926  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
927  errmsg("field name must not be null")));
928 
929  arg = PG_GETARG_DATUM(1);
930 
931  datum_to_json(arg, false, state->str, state->key_category,
932  state->key_output_func, true);
933 
934  appendStringInfoString(state->str, " : ");
935 
936  if (PG_ARGISNULL(2))
937  arg = (Datum) 0;
938  else
939  arg = PG_GETARG_DATUM(2);
940 
941  datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
942  state->val_output_func, false);
943 
945 }
void * arg

References AggCheckCallContext(), appendStringInfoString(), arg, datum_to_json(), elog(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), makeStringInfo(), MemoryContextSwitchTo(), palloc(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1194 of file json.c.

1195 {
1196  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1197  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1198  int nkdims = ARR_NDIM(key_array);
1199  int nvdims = ARR_NDIM(val_array);
1200  StringInfoData result;
1201  Datum *key_datums,
1202  *val_datums;
1203  bool *key_nulls,
1204  *val_nulls;
1205  int key_count,
1206  val_count,
1207  i;
1208  text *rval;
1209  char *v;
1210 
1211  if (nkdims > 1 || nkdims != nvdims)
1212  ereport(ERROR,
1213  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1214  errmsg("wrong number of array subscripts")));
1215 
1216  if (nkdims == 0)
1218 
1219  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1220  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1221 
1222  if (key_count != val_count)
1223  ereport(ERROR,
1224  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1225  errmsg("mismatched array dimensions")));
1226 
1227  initStringInfo(&result);
1228 
1229  appendStringInfoChar(&result, '{');
1230 
1231  for (i = 0; i < key_count; ++i)
1232  {
1233  if (key_nulls[i])
1234  ereport(ERROR,
1235  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1236  errmsg("null value not allowed for object key")));
1237 
1238  v = TextDatumGetCString(key_datums[i]);
1239  if (i > 0)
1240  appendStringInfoString(&result, ", ");
1241  escape_json(&result, v);
1242  appendStringInfoString(&result, " : ");
1243  pfree(v);
1244  if (val_nulls[i])
1245  appendStringInfoString(&result, "null");
1246  else
1247  {
1248  v = TextDatumGetCString(val_datums[i]);
1249  escape_json(&result, v);
1250  pfree(v);
1251  }
1252  }
1253 
1254  appendStringInfoChar(&result, '}');
1255 
1256  pfree(key_datums);
1257  pfree(key_nulls);
1258  pfree(val_datums);
1259  pfree(val_nulls);
1260 
1261  rval = cstring_to_text_with_len(result.data, result.len);
1262  pfree(result.data);
1263 
1264  PG_RETURN_TEXT_P(rval);
1265 }

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

96 {
97  /* we needn't detoast because text_to_cstring will handle that */
98  Datum txt = PG_GETARG_DATUM(0);
99 
101 }
#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 121 of file json.c.

122 {
124  char *str;
125  int nbytes;
126  JsonLexContext *lex;
127 
128  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
129 
130  /* Validate it. */
131  lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false);
133 
135 }
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 107 of file json.c.

108 {
109  text *t = PG_GETARG_TEXT_PP(0);
111 
115 }
#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 1326 of file json.c.

1327 {
1328  text *json;
1329 
1330  JsonLexContext *lex;
1331  JsonTokenType tok;
1332  char *type;
1333  JsonParseErrorType result;
1334 
1335  json = PG_GETARG_TEXT_PP(0);
1336  lex = makeJsonLexContext(json, false);
1337 
1338  /* Lex exactly one token from the input and check its type. */
1339  result = json_lex(lex);
1340  if (result != JSON_SUCCESS)
1341  json_errsave_error(result, lex, NULL);
1342  tok = lex->token_type;
1343  switch (tok)
1344  {
1346  type = "object";
1347  break;
1349  type = "array";
1350  break;
1351  case JSON_TOKEN_STRING:
1352  type = "string";
1353  break;
1354  case JSON_TOKEN_NUMBER:
1355  type = "number";
1356  break;
1357  case JSON_TOKEN_TRUE:
1358  case JSON_TOKEN_FALSE:
1359  type = "boolean";
1360  break;
1361  case JSON_TOKEN_NULL:
1362  type = "null";
1363  break;
1364  default:
1365  elog(ERROR, "unexpected json token: %d", tok);
1366  }
1367 
1369 }
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.

◆ JsonEncodeDateTime()

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

Definition at line 354 of file json.c.

355 {
356  if (!buf)
357  buf = palloc(MAXDATELEN + 1);
358 
359  switch (typid)
360  {
361  case DATEOID:
362  {
363  DateADT date;
364  struct pg_tm tm;
365 
367 
368  /* Same as date_out(), but forcing DateStyle */
369  if (DATE_NOT_FINITE(date))
371  else
372  {
374  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
376  }
377  }
378  break;
379  case TIMEOID:
380  {
381  TimeADT time = DatumGetTimeADT(value);
382  struct pg_tm tt,
383  *tm = &tt;
384  fsec_t fsec;
385 
386  /* Same as time_out(), but forcing DateStyle */
387  time2tm(time, tm, &fsec);
388  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
389  }
390  break;
391  case TIMETZOID:
392  {
394  struct pg_tm tt,
395  *tm = &tt;
396  fsec_t fsec;
397  int tz;
398 
399  /* Same as timetz_out(), but forcing DateStyle */
400  timetz2tm(time, tm, &fsec, &tz);
401  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
402  }
403  break;
404  case TIMESTAMPOID:
405  {
407  struct pg_tm tm;
408  fsec_t fsec;
409 
411  /* Same as timestamp_out(), but forcing DateStyle */
414  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
415  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
416  else
417  ereport(ERROR,
418  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
419  errmsg("timestamp out of range")));
420  }
421  break;
422  case TIMESTAMPTZOID:
423  {
425  struct pg_tm tm;
426  int tz;
427  fsec_t fsec;
428  const char *tzn = NULL;
429 
431 
432  /*
433  * If a time zone is specified, we apply the time-zone shift,
434  * convert timestamptz to pg_tm as if it were without a time
435  * zone, and then use the specified time zone for converting
436  * the timestamp into a string.
437  */
438  if (tzp)
439  {
440  tz = *tzp;
442  }
443 
444  /* Same as timestamptz_out(), but forcing DateStyle */
447  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
448  tzp ? NULL : &tzn, NULL) == 0)
449  {
450  if (tzp)
451  tm.tm_isdst = 1; /* set time-zone presence flag */
452 
453  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
454  }
455  else
456  ereport(ERROR,
457  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
458  errmsg("timestamp out of range")));
459  }
460  break;
461  default:
462  elog(ERROR, "unknown jsonb value datetime type oid %u", typid);
463  return NULL;
464  }
465 
466  return buf;
467 }
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4263
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:312
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4293
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4178
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1538
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1841
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:2403
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1496
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:292
#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 @143 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 697 of file json.c.

698 {
699  Datum array = PG_GETARG_DATUM(0);
700  StringInfo result;
701 
702  result = makeStringInfo();
703 
704  composite_to_json(array, result, false);
705 
707 }

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

714 {
715  Datum array = PG_GETARG_DATUM(0);
716  bool use_line_feeds = PG_GETARG_BOOL(1);
717  StringInfo result;
718 
719  result = makeStringInfo();
720 
721  composite_to_json(array, result, use_line_feeds);
722 
724 }

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

◆ to_json()

Datum to_json ( PG_FUNCTION_ARGS  )

Definition at line 730 of file json.c.

731 {
733  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
734  StringInfo result;
735  JsonTypeCategory tcategory;
736  Oid outfuncoid;
737 
738  if (val_type == InvalidOid)
739  ereport(ERROR,
740  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
741  errmsg("could not determine input data type")));
742 
743  json_categorize_type(val_type,
744  &tcategory, &outfuncoid);
745 
746  result = makeStringInfo();
747 
748  datum_to_json(val, false, result, tcategory, outfuncoid, false);
749 
751 }

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.