PostgreSQL Source Code  git master
json.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.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/lsyscache.h"
#include "utils/json.h"
#include "utils/jsonapi.h"
#include "utils/typcache.h"
#include "utils/syscache.h"
Include dependency graph for json.c:

Go to the source code of this file.

Data Structures

struct  JsonAggState
 

Macros

#define JSON_ALPHANUMERIC_CHAR(c)
 

Typedefs

typedef struct JsonAggState JsonAggState
 

Enumerations

enum  JsonParseContext {
  JSON_PARSE_VALUE, JSON_PARSE_STRING, JSON_PARSE_ARRAY_START, JSON_PARSE_ARRAY_NEXT,
  JSON_PARSE_OBJECT_START, JSON_PARSE_OBJECT_LABEL, JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_COMMA,
  JSON_PARSE_END
}
 
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 json_lex (JsonLexContext *lex)
 
static void json_lex_string (JsonLexContext *lex)
 
static void json_lex_number (JsonLexContext *lex, char *s, bool *num_err, int *total_len)
 
static void parse_scalar (JsonLexContext *lex, JsonSemAction *sem)
 
static void parse_object_field (JsonLexContext *lex, JsonSemAction *sem)
 
static void parse_object (JsonLexContext *lex, JsonSemAction *sem)
 
static void parse_array_element (JsonLexContext *lex, JsonSemAction *sem)
 
static void parse_array (JsonLexContext *lex, JsonSemAction *sem)
 
static void report_parse_error (JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn()
 
static void report_invalid_token (JsonLexContext *lex) pg_attribute_noreturn()
 
static int report_json_context (JsonLexContext *lex)
 
static char * extract_mb_char (char *s)
 
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)
 
static JsonTokenType lex_peek (JsonLexContext *lex)
 
static bool lex_accept (JsonLexContext *lex, JsonTokenType token, char **lexeme)
 
static void lex_expect (JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
 
bool IsValidJsonNumber (const char *str, int len)
 
Datum json_in (PG_FUNCTION_ARGS)
 
Datum json_out (PG_FUNCTION_ARGS)
 
Datum json_send (PG_FUNCTION_ARGS)
 
Datum json_recv (PG_FUNCTION_ARGS)
 
JsonLexContextmakeJsonLexContext (text *json, bool need_escapes)
 
JsonLexContextmakeJsonLexContextCstringLen (char *json, int len, bool need_escapes)
 
void pg_parse_json (JsonLexContext *lex, JsonSemAction *sem)
 
int json_count_array_elements (JsonLexContext *lex)
 
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)
 

Variables

static JsonSemAction nullSemAction
 

Macro Definition Documentation

◆ JSON_ALPHANUMERIC_CHAR

#define JSON_ALPHANUMERIC_CHAR (   c)
Value:
(((c) >= 'a' && (c) <= 'z') || \
((c) >= 'A' && (c) <= 'Z') || \
((c) >= '0' && (c) <= '9') || \
(c) == '_' || \
IS_HIGHBIT_SET(c))
char * c

Definition at line 180 of file json.c.

Referenced by json_lex(), and json_lex_number().

Typedef Documentation

◆ JsonAggState

typedef struct JsonAggState JsonAggState

Enumeration Type Documentation

◆ JsonParseContext

Enumerator
JSON_PARSE_VALUE 
JSON_PARSE_STRING 
JSON_PARSE_ARRAY_START 
JSON_PARSE_ARRAY_NEXT 
JSON_PARSE_OBJECT_START 
JSON_PARSE_OBJECT_LABEL 
JSON_PARSE_OBJECT_NEXT 
JSON_PARSE_OBJECT_COMMA 
JSON_PARSE_END 

Definition at line 41 of file json.c.

42 {
43  JSON_PARSE_VALUE, /* expecting a value */
44  JSON_PARSE_STRING, /* expecting a string (for a field name) */
45  JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
46  JSON_PARSE_ARRAY_NEXT, /* saw array element, expecting ',' or ']' */
47  JSON_PARSE_OBJECT_START, /* saw '{', expecting label or '}' */
48  JSON_PARSE_OBJECT_LABEL, /* saw object label, expecting ':' */
49  JSON_PARSE_OBJECT_NEXT, /* saw object value, expecting ',' or '}' */
50  JSON_PARSE_OBJECT_COMMA, /* saw object ',', expecting next label */
51  JSON_PARSE_END /* saw the end of a document, expect nothing */
JsonParseContext
Definition: json.c:41

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

55 {
56  JSONTYPE_NULL, /* null, so we didn't bother to identify */
57  JSONTYPE_BOOL, /* boolean (built-in types only) */
58  JSONTYPE_NUMERIC, /* numeric (ditto) */
59  JSONTYPE_DATE, /* we use special formatting for datetimes */
62  JSONTYPE_JSON, /* JSON itself (and JSONB) */
63  JSONTYPE_ARRAY, /* array */
64  JSONTYPE_COMPOSITE, /* composite */
65  JSONTYPE_CAST, /* something with an explicit cast to JSON */
66  JSONTYPE_OTHER /* all else */
JsonTypeCategory
Definition: json.c:54

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

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

Referenced by json_build_array(), and json_build_object().

1842 {
1843  JsonTypeCategory tcategory;
1844  Oid outfuncoid;
1845 
1846  if (val_type == InvalidOid)
1847  ereport(ERROR,
1848  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1849  errmsg("could not determine input data type")));
1850 
1851  if (is_null)
1852  {
1853  tcategory = JSONTYPE_NULL;
1854  outfuncoid = InvalidOid;
1855  }
1856  else
1857  json_categorize_type(val_type,
1858  &tcategory, &outfuncoid);
1859 
1860  datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
1861 }
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
JsonTypeCategory
Definition: json.c:54
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:784
long val
Definition: informix.c:684

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

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

Referenced by array_to_json_internal().

1681 {
1682  int i;
1683  const char *sep;
1684 
1685  Assert(dim < ndims);
1686 
1687  sep = use_line_feeds ? ",\n " : ",";
1688 
1689  appendStringInfoChar(result, '[');
1690 
1691  for (i = 1; i <= dims[dim]; i++)
1692  {
1693  if (i > 1)
1694  appendStringInfoString(result, sep);
1695 
1696  if (dim + 1 == ndims)
1697  {
1698  datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
1699  outfuncoid, false);
1700  (*valcount)++;
1701  }
1702  else
1703  {
1704  /*
1705  * Do we want line feeds on inner dimensions of arrays? For now
1706  * we'll say no.
1707  */
1708  array_dim_to_json(result, dim + 1, ndims, dims, vals, nulls,
1709  valcount, tcategory, outfuncoid, false);
1710  }
1711  }
1712 
1713  appendStringInfoChar(result, ']');
1714 }
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
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:1678
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define Assert(condition)
Definition: c.h:732
int i

◆ array_to_json()

Datum array_to_json ( PG_FUNCTION_ARGS  )

Definition at line 1867 of file json.c.

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

1868 {
1869  Datum array = PG_GETARG_DATUM(0);
1870  StringInfo result;
1871 
1872  result = makeStringInfo();
1873 
1874  array_to_json_internal(array, result, false);
1875 
1877 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:1720

◆ array_to_json_internal()

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

Definition at line 1720 of file json.c.

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

1721 {
1722  ArrayType *v = DatumGetArrayTypeP(array);
1723  Oid element_type = ARR_ELEMTYPE(v);
1724  int *dim;
1725  int ndim;
1726  int nitems;
1727  int count = 0;
1728  Datum *elements;
1729  bool *nulls;
1730  int16 typlen;
1731  bool typbyval;
1732  char typalign;
1733  JsonTypeCategory tcategory;
1734  Oid outfuncoid;
1735 
1736  ndim = ARR_NDIM(v);
1737  dim = ARR_DIMS(v);
1738  nitems = ArrayGetNItems(ndim, dim);
1739 
1740  if (nitems <= 0)
1741  {
1742  appendStringInfoString(result, "[]");
1743  return;
1744  }
1745 
1746  get_typlenbyvalalign(element_type,
1747  &typlen, &typbyval, &typalign);
1748 
1749  json_categorize_type(element_type,
1750  &tcategory, &outfuncoid);
1751 
1752  deconstruct_array(v, element_type, typlen, typbyval,
1753  typalign, &elements, &nulls,
1754  &nitems);
1755 
1756  array_dim_to_json(result, 0, ndim, dim, elements, nulls, &count, tcategory,
1757  outfuncoid, use_line_feeds);
1758 
1759  pfree(elements);
1760  pfree(nulls);
1761 }
signed short int16
Definition: c.h:345
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
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:1678
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:1056
char typalign
Definition: pg_type.h:170
#define ARR_DIMS(a)
Definition: array.h:282
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
JsonTypeCategory
Definition: json.c:54
uintptr_t Datum
Definition: postgres.h:367
#define ARR_NDIM(a)
Definition: array.h:278
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ array_to_json_pretty()

Datum array_to_json_pretty ( PG_FUNCTION_ARGS  )

Definition at line 1883 of file json.c.

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.

1884 {
1885  Datum array = PG_GETARG_DATUM(0);
1886  bool use_line_feeds = PG_GETARG_BOOL(1);
1887  StringInfo result;
1888 
1889  result = makeStringInfo();
1890 
1891  array_to_json_internal(array, result, use_line_feeds);
1892 
1894 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:1720

◆ catenate_stringinfo_string()

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

Definition at line 2177 of file json.c.

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

Referenced by json_agg_finalfn(), and json_object_agg_finalfn().

2178 {
2179  /* custom version of cstring_to_text_with_len */
2180  int buflen = buffer->len;
2181  int addlen = strlen(addon);
2182  text *result = (text *) palloc(buflen + addlen + VARHDRSZ);
2183 
2184  SET_VARSIZE(result, buflen + addlen + VARHDRSZ);
2185  memcpy(VARDATA(result), buffer->data, buflen);
2186  memcpy(VARDATA(result) + buflen, addon, addlen);
2187 
2188  return result;
2189 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARHDRSZ
Definition: c.h:555
void * palloc(Size size)
Definition: mcxt.c:949
Definition: c.h:549
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ composite_to_json()

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

Definition at line 1767 of file json.c.

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

1768 {
1769  HeapTupleHeader td;
1770  Oid tupType;
1771  int32 tupTypmod;
1772  TupleDesc tupdesc;
1773  HeapTupleData tmptup,
1774  *tuple;
1775  int i;
1776  bool needsep = false;
1777  const char *sep;
1778 
1779  sep = use_line_feeds ? ",\n " : ",";
1780 
1781  td = DatumGetHeapTupleHeader(composite);
1782 
1783  /* Extract rowtype info and find a tupdesc */
1784  tupType = HeapTupleHeaderGetTypeId(td);
1785  tupTypmod = HeapTupleHeaderGetTypMod(td);
1786  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1787 
1788  /* Build a temporary HeapTuple control structure */
1789  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1790  tmptup.t_data = td;
1791  tuple = &tmptup;
1792 
1793  appendStringInfoChar(result, '{');
1794 
1795  for (i = 0; i < tupdesc->natts; i++)
1796  {
1797  Datum val;
1798  bool isnull;
1799  char *attname;
1800  JsonTypeCategory tcategory;
1801  Oid outfuncoid;
1802  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1803 
1804  if (att->attisdropped)
1805  continue;
1806 
1807  if (needsep)
1808  appendStringInfoString(result, sep);
1809  needsep = true;
1810 
1811  attname = NameStr(att->attname);
1812  escape_json(result, attname);
1813  appendStringInfoChar(result, ':');
1814 
1815  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1816 
1817  if (isnull)
1818  {
1819  tcategory = JSONTYPE_NULL;
1820  outfuncoid = InvalidOid;
1821  }
1822  else
1823  json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
1824 
1825  datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
1826  }
1827 
1828  appendStringInfoChar(result, '}');
1829  ReleaseTupleDesc(tupdesc);
1830 }
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1652
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:289
signed int int32
Definition: c.h:346
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:468
NameData attname
Definition: pg_attribute.h:40
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
uint32 t_len
Definition: htup.h:64
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
JsonTypeCategory
Definition: json.c:54
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
uintptr_t Datum
Definition: postgres.h:367
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:458
#define InvalidOid
Definition: postgres_ext.h:36
int i
#define NameStr(name)
Definition: c.h:609
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
long val
Definition: informix.c:684
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:452

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

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

Referenced by add_json(), array_dim_to_json(), composite_to_json(), json_agg_transfn(), json_object_agg_transfn(), and to_json().

1453 {
1454  char *outputstr;
1455  text *jsontext;
1456 
1458 
1459  /* callers are expected to ensure that null keys are not passed in */
1460  Assert(!(key_scalar && is_null));
1461 
1462  if (is_null)
1463  {
1464  appendStringInfoString(result, "null");
1465  return;
1466  }
1467 
1468  if (key_scalar &&
1469  (tcategory == JSONTYPE_ARRAY ||
1470  tcategory == JSONTYPE_COMPOSITE ||
1471  tcategory == JSONTYPE_JSON ||
1472  tcategory == JSONTYPE_CAST))
1473  ereport(ERROR,
1474  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1475  errmsg("key value must be scalar, not array, composite, or json")));
1476 
1477  switch (tcategory)
1478  {
1479  case JSONTYPE_ARRAY:
1480  array_to_json_internal(val, result, false);
1481  break;
1482  case JSONTYPE_COMPOSITE:
1483  composite_to_json(val, result, false);
1484  break;
1485  case JSONTYPE_BOOL:
1486  outputstr = DatumGetBool(val) ? "true" : "false";
1487  if (key_scalar)
1488  escape_json(result, outputstr);
1489  else
1490  appendStringInfoString(result, outputstr);
1491  break;
1492  case JSONTYPE_NUMERIC:
1493  outputstr = OidOutputFunctionCall(outfuncoid, val);
1494 
1495  /*
1496  * Don't call escape_json for a non-key if it's a valid JSON
1497  * number.
1498  */
1499  if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
1500  appendStringInfoString(result, outputstr);
1501  else
1502  escape_json(result, outputstr);
1503  pfree(outputstr);
1504  break;
1505  case JSONTYPE_DATE:
1506  {
1507  char buf[MAXDATELEN + 1];
1508 
1509  JsonEncodeDateTime(buf, val, DATEOID, NULL);
1510  appendStringInfo(result, "\"%s\"", buf);
1511  }
1512  break;
1513  case JSONTYPE_TIMESTAMP:
1514  {
1515  char buf[MAXDATELEN + 1];
1516 
1517  JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
1518  appendStringInfo(result, "\"%s\"", buf);
1519  }
1520  break;
1521  case JSONTYPE_TIMESTAMPTZ:
1522  {
1523  char buf[MAXDATELEN + 1];
1524 
1525  JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
1526  appendStringInfo(result, "\"%s\"", buf);
1527  }
1528  break;
1529  case JSONTYPE_JSON:
1530  /* JSON and JSONB output will already be escaped */
1531  outputstr = OidOutputFunctionCall(outfuncoid, val);
1532  appendStringInfoString(result, outputstr);
1533  pfree(outputstr);
1534  break;
1535  case JSONTYPE_CAST:
1536  /* outfuncoid refers to a cast function, not an output function */
1537  jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
1538  outputstr = text_to_cstring(jsontext);
1539  appendStringInfoString(result, outputstr);
1540  pfree(outputstr);
1541  pfree(jsontext);
1542  break;
1543  default:
1544  outputstr = OidOutputFunctionCall(outfuncoid, val);
1545  escape_json(result, outputstr);
1546  pfree(outputstr);
1547  break;
1548  }
1549 }
#define MAXDATELEN
Definition: datetime.h:201
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:1767
#define DatumGetTextPP(X)
Definition: fmgr.h:286
int errcode(int sqlerrcode)
Definition: elog.c:570
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
bool IsValidJsonNumber(const char *str, int len)
Definition: json.c:193
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:655
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:1557
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
void check_stack_depth(void)
Definition: postgres.c:3262
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
#define Assert(condition)
Definition: c.h:732
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
Definition: json.c:1720
char * text_to_cstring(const text *t)
Definition: varlena.c:204
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1655
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
long val
Definition: informix.c:684

◆ escape_json()

void escape_json ( StringInfo  buf,
const char *  str 
)

Definition at line 2483 of file json.c.

References appendStringInfo(), appendStringInfoCharMacro, and appendStringInfoString().

Referenced by 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(), and transform_string_values_scalar().

2484 {
2485  const char *p;
2486 
2487  appendStringInfoCharMacro(buf, '"');
2488  for (p = str; *p; p++)
2489  {
2490  switch (*p)
2491  {
2492  case '\b':
2493  appendStringInfoString(buf, "\\b");
2494  break;
2495  case '\f':
2496  appendStringInfoString(buf, "\\f");
2497  break;
2498  case '\n':
2499  appendStringInfoString(buf, "\\n");
2500  break;
2501  case '\r':
2502  appendStringInfoString(buf, "\\r");
2503  break;
2504  case '\t':
2505  appendStringInfoString(buf, "\\t");
2506  break;
2507  case '"':
2508  appendStringInfoString(buf, "\\\"");
2509  break;
2510  case '\\':
2511  appendStringInfoString(buf, "\\\\");
2512  break;
2513  default:
2514  if ((unsigned char) *p < ' ')
2515  appendStringInfo(buf, "\\u%04x", (int) *p);
2516  else
2517  appendStringInfoCharMacro(buf, *p);
2518  break;
2519  }
2520  }
2521  appendStringInfoCharMacro(buf, '"');
2522 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:127
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163

◆ extract_mb_char()

static char * extract_mb_char ( char *  s)
static

Definition at line 1327 of file json.c.

References palloc(), and pg_mblen().

Referenced by json_lex_string().

1328 {
1329  char *res;
1330  int len;
1331 
1332  len = pg_mblen(s);
1333  res = palloc(len + 1);
1334  memcpy(res, s, len);
1335  res[len] = '\0';
1336 
1337  return res;
1338 }
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802
void * palloc(Size size)
Definition: mcxt.c:949

◆ IsValidJsonNumber()

bool IsValidJsonNumber ( const char *  str,
int  len 
)

Definition at line 193 of file json.c.

References JsonLexContext::input, JsonLexContext::input_length, json_lex_number(), and unconstify.

Referenced by datum_to_json(), hstore_to_json_loose(), and hstore_to_jsonb_loose().

194 {
195  bool numeric_error;
196  int total_len;
197  JsonLexContext dummy_lex;
198 
199  if (len <= 0)
200  return false;
201 
202  /*
203  * json_lex_number expects a leading '-' to have been eaten already.
204  *
205  * having to cast away the constness of str is ugly, but there's not much
206  * easy alternative.
207  */
208  if (*str == '-')
209  {
210  dummy_lex.input = unconstify(char *, str) +1;
211  dummy_lex.input_length = len - 1;
212  }
213  else
214  {
215  dummy_lex.input = unconstify(char *, str);
216  dummy_lex.input_length = len;
217  }
218 
219  json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
220 
221  return (!numeric_error) && (total_len == dummy_lex.input_length);
222 }
static void json_lex_number(JsonLexContext *lex, char *s, bool *num_err, int *total_len)
Definition: json.c:1028
int input_length
Definition: jsonapi.h:54
#define unconstify(underlying_type, expr)
Definition: c.h:1163
char * input
Definition: jsonapi.h:53

◆ json_agg_finalfn()

Datum json_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 2038 of file json.c.

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

2039 {
2041 
2042  /* cannot be called directly because of internal-type argument */
2043  Assert(AggCheckCallContext(fcinfo, NULL));
2044 
2045  state = PG_ARGISNULL(0) ?
2046  NULL :
2048 
2049  /* NULL result for no rows in, as is standard with aggregates */
2050  if (state == NULL)
2051  PG_RETURN_NULL();
2052 
2053  /* Else return state with appropriate array terminator added */
2055 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
Definition: json.c:2177
StringInfo str
Definition: json.c:71
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define Assert(condition)
Definition: c.h:732
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3572
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_agg_transfn()

Datum json_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1962 of file json.c.

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, JsonAggState::str, val, JsonAggState::val_category, and JsonAggState::val_output_func.

1963 {
1964  MemoryContext aggcontext,
1965  oldcontext;
1967  Datum val;
1968 
1969  if (!AggCheckCallContext(fcinfo, &aggcontext))
1970  {
1971  /* cannot be called directly because of internal-type argument */
1972  elog(ERROR, "json_agg_transfn called in non-aggregate context");
1973  }
1974 
1975  if (PG_ARGISNULL(0))
1976  {
1977  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1978 
1979  if (arg_type == InvalidOid)
1980  ereport(ERROR,
1981  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1982  errmsg("could not determine input data type")));
1983 
1984  /*
1985  * Make this state object in a context where it will persist for the
1986  * duration of the aggregate call. MemoryContextSwitchTo is only
1987  * needed the first time, as the StringInfo routines make sure they
1988  * use the right context to enlarge the object if necessary.
1989  */
1990  oldcontext = MemoryContextSwitchTo(aggcontext);
1991  state = (JsonAggState *) palloc(sizeof(JsonAggState));
1992  state->str = makeStringInfo();
1993  MemoryContextSwitchTo(oldcontext);
1994 
1995  appendStringInfoChar(state->str, '[');
1996  json_categorize_type(arg_type, &state->val_category,
1997  &state->val_output_func);
1998  }
1999  else
2000  {
2001  state = (JsonAggState *) PG_GETARG_POINTER(0);
2002  appendStringInfoString(state->str, ", ");
2003  }
2004 
2005  /* fast path for NULLs */
2006  if (PG_ARGISNULL(1))
2007  {
2008  datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
2009  InvalidOid, false);
2010  PG_RETURN_POINTER(state);
2011  }
2012 
2013  val = PG_GETARG_DATUM(1);
2014 
2015  /* add some whitespace if structured type and not first item */
2016  if (!PG_ARGISNULL(0) &&
2017  (state->val_category == JSONTYPE_ARRAY ||
2018  state->val_category == JSONTYPE_COMPOSITE))
2019  {
2020  appendStringInfoString(state->str, "\n ");
2021  }
2022 
2023  datum_to_json(val, false, state->str, state->val_category,
2024  state->val_output_func, false);
2025 
2026  /*
2027  * The transition type for json_agg() is declared to be "internal", which
2028  * is a pass-by-value type the same size as a pointer. So we can safely
2029  * pass the JsonAggState pointer through nodeAgg.c's machinations.
2030  */
2031  PG_RETURN_POINTER(state);
2032 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:570
Oid val_output_func
Definition: json.c:75
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
StringInfo str
Definition: json.c:71
#define ereport(elevel, rest)
Definition: elog.h:141
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
JsonTypeCategory val_category
Definition: json.c:74
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3572
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
long val
Definition: informix.c:684

◆ json_build_array()

Datum json_build_array ( PG_FUNCTION_ARGS  )

Definition at line 2261 of file json.c.

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.

2262 {
2263  int nargs;
2264  int i;
2265  const char *sep = "";
2266  StringInfo result;
2267  Datum *args;
2268  bool *nulls;
2269  Oid *types;
2270 
2271  /* fetch argument values to build the array */
2272  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
2273 
2274  if (nargs < 0)
2275  PG_RETURN_NULL();
2276 
2277  result = makeStringInfo();
2278 
2279  appendStringInfoChar(result, '[');
2280 
2281  for (i = 0; i < nargs; i++)
2282  {
2283  appendStringInfoString(result, sep);
2284  sep = ", ";
2285  add_json(args[i], nulls[i], result, types[i], false);
2286  }
2287 
2288  appendStringInfoChar(result, ']');
2289 
2291 }
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1464
struct typedefs * types
Definition: ecpg.c:29
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
unsigned int Oid
Definition: postgres_ext.h:31
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
uintptr_t Datum
Definition: postgres.h:367
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:1840
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_build_array_noargs()

Datum json_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 2297 of file json.c.

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

2298 {
2300 }
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361

◆ json_build_object()

Datum json_build_object ( PG_FUNCTION_ARGS  )

Definition at line 2195 of file json.c.

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_NARGS, PG_RETURN_NULL, PG_RETURN_TEXT_P, and types.

2196 {
2197  int nargs = PG_NARGS();
2198  int i;
2199  const char *sep = "";
2200  StringInfo result;
2201  Datum *args;
2202  bool *nulls;
2203  Oid *types;
2204 
2205  /* fetch argument values to build the object */
2206  nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
2207 
2208  if (nargs < 0)
2209  PG_RETURN_NULL();
2210 
2211  if (nargs % 2 != 0)
2212  ereport(ERROR,
2213  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2214  errmsg("argument list must have even number of elements"),
2215  /* translator: %s is a SQL function name */
2216  errhint("The arguments of %s must consist of alternating keys and values.",
2217  "json_build_object()")));
2218 
2219  result = makeStringInfo();
2220 
2221  appendStringInfoChar(result, '{');
2222 
2223  for (i = 0; i < nargs; i += 2)
2224  {
2225  appendStringInfoString(result, sep);
2226  sep = ", ";
2227 
2228  /* process key */
2229  if (nulls[i])
2230  ereport(ERROR,
2231  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2232  errmsg("argument %d cannot be null", i + 1),
2233  errhint("Object keys should be text.")));
2234 
2235  add_json(args[i], false, result, types[i], true);
2236 
2237  appendStringInfoString(result, " : ");
2238 
2239  /* process value */
2240  add_json(args[i + 1], nulls[i + 1], result, types[i + 1], false);
2241  }
2242 
2243  appendStringInfoChar(result, '}');
2244 
2246 }
int errhint(const char *fmt,...)
Definition: elog.c:974
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1464
struct typedefs * types
Definition: ecpg.c:29
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define ereport(elevel, rest)
Definition: elog.h:141
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
uintptr_t Datum
Definition: postgres.h:367
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Definition: json.c:1840
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_NARGS()
Definition: fmgr.h:198
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_build_object_noargs()

Datum json_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 2252 of file json.c.

References cstring_to_text_with_len(), and PG_RETURN_TEXT_P.

2253 {
2255 }
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361

◆ json_categorize_type()

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

Definition at line 1348 of file json.c.

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

1351 {
1352  bool typisvarlena;
1353 
1354  /* Look through any domain */
1355  typoid = getBaseType(typoid);
1356 
1357  *outfuncoid = InvalidOid;
1358 
1359  /*
1360  * We need to get the output function for everything except date and
1361  * timestamp types, array and composite types, booleans, and non-builtin
1362  * types where there's a cast to json.
1363  */
1364 
1365  switch (typoid)
1366  {
1367  case BOOLOID:
1368  *tcategory = JSONTYPE_BOOL;
1369  break;
1370 
1371  case INT2OID:
1372  case INT4OID:
1373  case INT8OID:
1374  case FLOAT4OID:
1375  case FLOAT8OID:
1376  case NUMERICOID:
1377  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
1378  *tcategory = JSONTYPE_NUMERIC;
1379  break;
1380 
1381  case DATEOID:
1382  *tcategory = JSONTYPE_DATE;
1383  break;
1384 
1385  case TIMESTAMPOID:
1386  *tcategory = JSONTYPE_TIMESTAMP;
1387  break;
1388 
1389  case TIMESTAMPTZOID:
1390  *tcategory = JSONTYPE_TIMESTAMPTZ;
1391  break;
1392 
1393  case JSONOID:
1394  case JSONBOID:
1395  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
1396  *tcategory = JSONTYPE_JSON;
1397  break;
1398 
1399  default:
1400  /* Check for arrays and composites */
1401  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
1402  || typoid == RECORDARRAYOID)
1403  *tcategory = JSONTYPE_ARRAY;
1404  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
1405  *tcategory = JSONTYPE_COMPOSITE;
1406  else
1407  {
1408  /* It's probably the general case ... */
1409  *tcategory = JSONTYPE_OTHER;
1410  /* but let's look for a cast to json, if it's not built-in */
1411  if (typoid >= FirstNormalObjectId)
1412  {
1413  Oid castfunc;
1414  CoercionPathType ctype;
1415 
1416  ctype = find_coercion_pathway(JSONOID, typoid,
1418  &castfunc);
1419  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
1420  {
1421  *tcategory = JSONTYPE_CAST;
1422  *outfuncoid = castfunc;
1423  }
1424  else
1425  {
1426  /* non builtin type with no cast */
1427  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
1428  }
1429  }
1430  else
1431  {
1432  /* any other builtin type */
1433  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
1434  }
1435  }
1436  break;
1437  }
1438 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
CoercionPathType
Definition: parse_coerce.h:24
#define FirstNormalObjectId
Definition: transam.h:141
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2433
#define InvalidOid
Definition: postgres_ext.h:36
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2299

◆ json_count_array_elements()

int json_count_array_elements ( JsonLexContext lex)

Definition at line 367 of file json.c.

References JSON_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COMMA, lex_accept(), lex_expect(), JsonLexContext::lex_level, lex_peek(), parse_array_element(), and JsonLexContext::strval.

Referenced by get_array_start().

368 {
369  JsonLexContext copylex;
370  int count;
371 
372  /*
373  * It's safe to do this with a shallow copy because the lexical routines
374  * don't scribble on the input. They do scribble on the other pointers
375  * etc, so doing this with a copy makes that safe.
376  */
377  memcpy(&copylex, lex, sizeof(JsonLexContext));
378  copylex.strval = NULL; /* not interested in values here */
379  copylex.lex_level++;
380 
381  count = 0;
383  if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
384  {
385  do
386  {
387  count++;
389  }
390  while (lex_accept(&copylex, JSON_TOKEN_COMMA, NULL));
391  }
393 
394  return count;
395 }
static void lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: json.c:173
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
int lex_level
Definition: jsonapi.h:59
static void parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:539
StringInfo strval
Definition: jsonapi.h:62
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
static JsonSemAction nullSemAction
Definition: json.c:110

◆ json_in()

Datum json_in ( PG_FUNCTION_ARGS  )

Definition at line 228 of file json.c.

References cstring_to_text(), makeJsonLexContext(), PG_GETARG_CSTRING, pg_parse_json(), and PG_RETURN_TEXT_P.

229 {
230  char *json = PG_GETARG_CSTRING(0);
231  text *result = cstring_to_text(json);
232  JsonLexContext *lex;
233 
234  /* validate it */
235  lex = makeJsonLexContext(result, false);
237 
238  /* Internal representation is the same as text, for now */
239  PG_RETURN_TEXT_P(result);
240 }
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
static JsonSemAction nullSemAction
Definition: json.c:110
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272
Definition: c.h:549

◆ json_lex()

static void json_lex ( JsonLexContext lex)
inlinestatic

Definition at line 614 of file json.c.

References JsonLexContext::input, JsonLexContext::input_length, JSON_ALPHANUMERIC_CHAR, json_lex_number(), json_lex_string(), JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COLON, JSON_TOKEN_COMMA, JSON_TOKEN_END, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_END, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, JsonLexContext::line_number, JsonLexContext::prev_token_terminator, report_invalid_token(), JsonLexContext::token_start, JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by json_typeof(), lex_accept(), and pg_parse_json().

615 {
616  char *s;
617  int len;
618 
619  /* Skip leading whitespace. */
620  s = lex->token_terminator;
621  len = s - lex->input;
622  while (len < lex->input_length &&
623  (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
624  {
625  if (*s == '\n')
626  ++lex->line_number;
627  ++s;
628  ++len;
629  }
630  lex->token_start = s;
631 
632  /* Determine token type. */
633  if (len >= lex->input_length)
634  {
635  lex->token_start = NULL;
637  lex->token_terminator = s;
638  lex->token_type = JSON_TOKEN_END;
639  }
640  else
641  switch (*s)
642  {
643  /* Single-character token, some kind of punctuation mark. */
644  case '{':
646  lex->token_terminator = s + 1;
648  break;
649  case '}':
651  lex->token_terminator = s + 1;
653  break;
654  case '[':
656  lex->token_terminator = s + 1;
658  break;
659  case ']':
661  lex->token_terminator = s + 1;
663  break;
664  case ',':
666  lex->token_terminator = s + 1;
668  break;
669  case ':':
671  lex->token_terminator = s + 1;
673  break;
674  case '"':
675  /* string */
676  json_lex_string(lex);
678  break;
679  case '-':
680  /* Negative number. */
681  json_lex_number(lex, s + 1, NULL, NULL);
683  break;
684  case '0':
685  case '1':
686  case '2':
687  case '3':
688  case '4':
689  case '5':
690  case '6':
691  case '7':
692  case '8':
693  case '9':
694  /* Positive number. */
695  json_lex_number(lex, s, NULL, NULL);
697  break;
698  default:
699  {
700  char *p;
701 
702  /*
703  * We're not dealing with a string, number, legal
704  * punctuation mark, or end of string. The only legal
705  * tokens we might find here are true, false, and null,
706  * but for error reporting purposes we scan until we see a
707  * non-alphanumeric character. That way, we can report
708  * the whole word as an unexpected token, rather than just
709  * some unintuitive prefix thereof.
710  */
711  for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++)
712  /* skip */ ;
713 
714  /*
715  * We got some sort of unexpected punctuation or an
716  * otherwise unexpected character, so just complain about
717  * that one character.
718  */
719  if (p == s)
720  {
722  lex->token_terminator = s + 1;
724  }
725 
726  /*
727  * We've got a real alphanumeric token here. If it
728  * happens to be true, false, or null, all is well. If
729  * not, error out.
730  */
732  lex->token_terminator = p;
733  if (p - s == 4)
734  {
735  if (memcmp(s, "true", 4) == 0)
737  else if (memcmp(s, "null", 4) == 0)
739  else
741  }
742  else if (p - s == 5 && memcmp(s, "false", 5) == 0)
744  else
746 
747  }
748  } /* end of switch */
749 }
int line_number
Definition: jsonapi.h:60
JsonTokenType token_type
Definition: jsonapi.h:58
char * prev_token_terminator
Definition: jsonapi.h:57
#define JSON_ALPHANUMERIC_CHAR(c)
Definition: json.c:180
static void json_lex_number(JsonLexContext *lex, char *s, bool *num_err, int *total_len)
Definition: json.c:1028
int input_length
Definition: jsonapi.h:54
char * token_start
Definition: jsonapi.h:55
char * token_terminator
Definition: jsonapi.h:56
char * input
Definition: jsonapi.h:53
static void json_lex_string(JsonLexContext *lex)
Definition: json.c:755
static void report_invalid_token(JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1233

◆ json_lex_number()

static void json_lex_number ( JsonLexContext lex,
char *  s,
bool num_err,
int *  total_len 
)
inlinestatic

Definition at line 1028 of file json.c.

References error(), JsonLexContext::input, JsonLexContext::input_length, JSON_ALPHANUMERIC_CHAR, JsonLexContext::prev_token_terminator, report_invalid_token(), and JsonLexContext::token_terminator.

Referenced by IsValidJsonNumber(), and json_lex().

1030 {
1031  bool error = false;
1032  int len = s - lex->input;
1033 
1034  /* Part (1): leading sign indicator. */
1035  /* Caller already did this for us; so do nothing. */
1036 
1037  /* Part (2): parse main digit string. */
1038  if (len < lex->input_length && *s == '0')
1039  {
1040  s++;
1041  len++;
1042  }
1043  else if (len < lex->input_length && *s >= '1' && *s <= '9')
1044  {
1045  do
1046  {
1047  s++;
1048  len++;
1049  } while (len < lex->input_length && *s >= '0' && *s <= '9');
1050  }
1051  else
1052  error = true;
1053 
1054  /* Part (3): parse optional decimal portion. */
1055  if (len < lex->input_length && *s == '.')
1056  {
1057  s++;
1058  len++;
1059  if (len == lex->input_length || *s < '0' || *s > '9')
1060  error = true;
1061  else
1062  {
1063  do
1064  {
1065  s++;
1066  len++;
1067  } while (len < lex->input_length && *s >= '0' && *s <= '9');
1068  }
1069  }
1070 
1071  /* Part (4): parse optional exponent. */
1072  if (len < lex->input_length && (*s == 'e' || *s == 'E'))
1073  {
1074  s++;
1075  len++;
1076  if (len < lex->input_length && (*s == '+' || *s == '-'))
1077  {
1078  s++;
1079  len++;
1080  }
1081  if (len == lex->input_length || *s < '0' || *s > '9')
1082  error = true;
1083  else
1084  {
1085  do
1086  {
1087  s++;
1088  len++;
1089  } while (len < lex->input_length && *s >= '0' && *s <= '9');
1090  }
1091  }
1092 
1093  /*
1094  * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
1095  * here should be considered part of the token for error-reporting
1096  * purposes.
1097  */
1098  for (; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*s); s++, len++)
1099  error = true;
1100 
1101  if (total_len != NULL)
1102  *total_len = len;
1103 
1104  if (num_err != NULL)
1105  {
1106  /* let the caller handle any error */
1107  *num_err = error;
1108  }
1109  else
1110  {
1111  /* return token endpoint */
1113  lex->token_terminator = s;
1114  /* handle error if any */
1115  if (error)
1116  report_invalid_token(lex);
1117  }
1118 }
static void error(void)
Definition: sql-dyntest.c:147
char * prev_token_terminator
Definition: jsonapi.h:57
#define JSON_ALPHANUMERIC_CHAR(c)
Definition: json.c:180
int input_length
Definition: jsonapi.h:54
char * token_terminator
Definition: jsonapi.h:56
char * input
Definition: jsonapi.h:53
static void report_invalid_token(JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1233

◆ json_lex_string()

static void json_lex_string ( JsonLexContext lex)
inlinestatic

Definition at line 755 of file json.c.

References appendBinaryStringInfo(), appendStringInfoChar(), Assert, ereport, errcode(), errdetail(), errmsg(), ERROR, extract_mb_char(), GetDatabaseEncoding(), i, JsonLexContext::input, JsonLexContext::input_length, pg_mblen(), PG_UTF8, pg_utf_mblen(), JsonLexContext::prev_token_terminator, report_invalid_token(), report_json_context(), resetStringInfo(), JsonLexContext::strval, JsonLexContext::token_start, JsonLexContext::token_terminator, and unicode_to_utf8().

Referenced by json_lex().

756 {
757  char *s;
758  int len;
759  int hi_surrogate = -1;
760 
761  if (lex->strval != NULL)
762  resetStringInfo(lex->strval);
763 
764  Assert(lex->input_length > 0);
765  s = lex->token_start;
766  len = lex->token_start - lex->input;
767  for (;;)
768  {
769  s++;
770  len++;
771  /* Premature end of the string. */
772  if (len >= lex->input_length)
773  {
774  lex->token_terminator = s;
776  }
777  else if (*s == '"')
778  break;
779  else if ((unsigned char) *s < 32)
780  {
781  /* Per RFC4627, these characters MUST be escaped. */
782  /* Since *s isn't printable, exclude it from the context string */
783  lex->token_terminator = s;
784  ereport(ERROR,
785  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
786  errmsg("invalid input syntax for type %s", "json"),
787  errdetail("Character with value 0x%02x must be escaped.",
788  (unsigned char) *s),
789  report_json_context(lex)));
790  }
791  else if (*s == '\\')
792  {
793  /* OK, we have an escape character. */
794  s++;
795  len++;
796  if (len >= lex->input_length)
797  {
798  lex->token_terminator = s;
800  }
801  else if (*s == 'u')
802  {
803  int i;
804  int ch = 0;
805 
806  for (i = 1; i <= 4; i++)
807  {
808  s++;
809  len++;
810  if (len >= lex->input_length)
811  {
812  lex->token_terminator = s;
814  }
815  else if (*s >= '0' && *s <= '9')
816  ch = (ch * 16) + (*s - '0');
817  else if (*s >= 'a' && *s <= 'f')
818  ch = (ch * 16) + (*s - 'a') + 10;
819  else if (*s >= 'A' && *s <= 'F')
820  ch = (ch * 16) + (*s - 'A') + 10;
821  else
822  {
823  lex->token_terminator = s + pg_mblen(s);
824  ereport(ERROR,
825  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
826  errmsg("invalid input syntax for type %s",
827  "json"),
828  errdetail("\"\\u\" must be followed by four hexadecimal digits."),
829  report_json_context(lex)));
830  }
831  }
832  if (lex->strval != NULL)
833  {
834  char utf8str[5];
835  int utf8len;
836 
837  if (ch >= 0xd800 && ch <= 0xdbff)
838  {
839  if (hi_surrogate != -1)
840  ereport(ERROR,
841  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
842  errmsg("invalid input syntax for type %s",
843  "json"),
844  errdetail("Unicode high surrogate must not follow a high surrogate."),
845  report_json_context(lex)));
846  hi_surrogate = (ch & 0x3ff) << 10;
847  continue;
848  }
849  else if (ch >= 0xdc00 && ch <= 0xdfff)
850  {
851  if (hi_surrogate == -1)
852  ereport(ERROR,
853  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
854  errmsg("invalid input syntax for type %s", "json"),
855  errdetail("Unicode low surrogate must follow a high surrogate."),
856  report_json_context(lex)));
857  ch = 0x10000 + hi_surrogate + (ch & 0x3ff);
858  hi_surrogate = -1;
859  }
860 
861  if (hi_surrogate != -1)
862  ereport(ERROR,
863  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
864  errmsg("invalid input syntax for type %s", "json"),
865  errdetail("Unicode low surrogate must follow a high surrogate."),
866  report_json_context(lex)));
867 
868  /*
869  * For UTF8, replace the escape sequence by the actual
870  * utf8 character in lex->strval. Do this also for other
871  * encodings if the escape designates an ASCII character,
872  * otherwise raise an error.
873  */
874 
875  if (ch == 0)
876  {
877  /* We can't allow this, since our TEXT type doesn't */
878  ereport(ERROR,
879  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
880  errmsg("unsupported Unicode escape sequence"),
881  errdetail("\\u0000 cannot be converted to text."),
882  report_json_context(lex)));
883  }
884  else if (GetDatabaseEncoding() == PG_UTF8)
885  {
886  unicode_to_utf8(ch, (unsigned char *) utf8str);
887  utf8len = pg_utf_mblen((unsigned char *) utf8str);
888  appendBinaryStringInfo(lex->strval, utf8str, utf8len);
889  }
890  else if (ch <= 0x007f)
891  {
892  /*
893  * This is the only way to designate things like a
894  * form feed character in JSON, so it's useful in all
895  * encodings.
896  */
897  appendStringInfoChar(lex->strval, (char) ch);
898  }
899  else
900  {
901  ereport(ERROR,
902  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
903  errmsg("unsupported Unicode escape sequence"),
904  errdetail("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."),
905  report_json_context(lex)));
906  }
907 
908  }
909  }
910  else if (lex->strval != NULL)
911  {
912  if (hi_surrogate != -1)
913  ereport(ERROR,
914  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
915  errmsg("invalid input syntax for type %s",
916  "json"),
917  errdetail("Unicode low surrogate must follow a high surrogate."),
918  report_json_context(lex)));
919 
920  switch (*s)
921  {
922  case '"':
923  case '\\':
924  case '/':
925  appendStringInfoChar(lex->strval, *s);
926  break;
927  case 'b':
928  appendStringInfoChar(lex->strval, '\b');
929  break;
930  case 'f':
931  appendStringInfoChar(lex->strval, '\f');
932  break;
933  case 'n':
934  appendStringInfoChar(lex->strval, '\n');
935  break;
936  case 'r':
937  appendStringInfoChar(lex->strval, '\r');
938  break;
939  case 't':
940  appendStringInfoChar(lex->strval, '\t');
941  break;
942  default:
943  /* Not a valid string escape, so error out. */
944  lex->token_terminator = s + pg_mblen(s);
945  ereport(ERROR,
946  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
947  errmsg("invalid input syntax for type %s",
948  "json"),
949  errdetail("Escape sequence \"\\%s\" is invalid.",
950  extract_mb_char(s)),
951  report_json_context(lex)));
952  }
953  }
954  else if (strchr("\"\\/bfnrt", *s) == NULL)
955  {
956  /*
957  * Simpler processing if we're not bothered about de-escaping
958  *
959  * It's very tempting to remove the strchr() call here and
960  * replace it with a switch statement, but testing so far has
961  * shown it's not a performance win.
962  */
963  lex->token_terminator = s + pg_mblen(s);
964  ereport(ERROR,
965  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
966  errmsg("invalid input syntax for type %s", "json"),
967  errdetail("Escape sequence \"\\%s\" is invalid.",
968  extract_mb_char(s)),
969  report_json_context(lex)));
970  }
971 
972  }
973  else if (lex->strval != NULL)
974  {
975  if (hi_surrogate != -1)
976  ereport(ERROR,
977  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
978  errmsg("invalid input syntax for type %s", "json"),
979  errdetail("Unicode low surrogate must follow a high surrogate."),
980  report_json_context(lex)));
981 
982  appendStringInfoChar(lex->strval, *s);
983  }
984 
985  }
986 
987  if (hi_surrogate != -1)
988  ereport(ERROR,
989  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
990  errmsg("invalid input syntax for type %s", "json"),
991  errdetail("Unicode low surrogate must follow a high surrogate."),
992  report_json_context(lex)));
993 
994  /* Hooray, we found the end of the string! */
996  lex->token_terminator = s + 1;
997 }
unsigned char * unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
Definition: wchar.c:482
char * prev_token_terminator
Definition: jsonapi.h:57
static char * extract_mb_char(char *s)
Definition: json.c:1327
int errcode(int sqlerrcode)
Definition: elog.c:570
int input_length
Definition: jsonapi.h:54
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:860
StringInfo strval
Definition: jsonapi.h:62
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:62
#define ereport(elevel, rest)
Definition: elog.h:141
char * token_start
Definition: jsonapi.h:55
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
char * token_terminator
Definition: jsonapi.h:56
int GetDatabaseEncoding(void)
Definition: mbutils.c:1046
#define Assert(condition)
Definition: c.h:732
char * input
Definition: jsonapi.h:53
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802
int pg_utf_mblen(const unsigned char *s)
Definition: wchar.c:548
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
static void report_invalid_token(JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1233
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:214
static int report_json_context(JsonLexContext *lex)
Definition: json.c:1262

◆ json_object()

Datum json_object ( PG_FUNCTION_ARGS  )

Definition at line 2309 of file json.c.

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.

2310 {
2311  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
2312  int ndims = ARR_NDIM(in_array);
2313  StringInfoData result;
2314  Datum *in_datums;
2315  bool *in_nulls;
2316  int in_count,
2317  count,
2318  i;
2319  text *rval;
2320  char *v;
2321 
2322  switch (ndims)
2323  {
2324  case 0:
2326  break;
2327 
2328  case 1:
2329  if ((ARR_DIMS(in_array)[0]) % 2)
2330  ereport(ERROR,
2331  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2332  errmsg("array must have even number of elements")));
2333  break;
2334 
2335  case 2:
2336  if ((ARR_DIMS(in_array)[1]) != 2)
2337  ereport(ERROR,
2338  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2339  errmsg("array must have two columns")));
2340  break;
2341 
2342  default:
2343  ereport(ERROR,
2344  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2345  errmsg("wrong number of array subscripts")));
2346  }
2347 
2348  deconstruct_array(in_array,
2349  TEXTOID, -1, false, 'i',
2350  &in_datums, &in_nulls, &in_count);
2351 
2352  count = in_count / 2;
2353 
2354  initStringInfo(&result);
2355 
2356  appendStringInfoChar(&result, '{');
2357 
2358  for (i = 0; i < count; ++i)
2359  {
2360  if (in_nulls[i * 2])
2361  ereport(ERROR,
2362  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2363  errmsg("null value not allowed for object key")));
2364 
2365  v = TextDatumGetCString(in_datums[i * 2]);
2366  if (i > 0)
2367  appendStringInfoString(&result, ", ");
2368  escape_json(&result, v);
2369  appendStringInfoString(&result, " : ");
2370  pfree(v);
2371  if (in_nulls[i * 2 + 1])
2372  appendStringInfoString(&result, "null");
2373  else
2374  {
2375  v = TextDatumGetCString(in_datums[i * 2 + 1]);
2376  escape_json(&result, v);
2377  pfree(v);
2378  }
2379  }
2380 
2381  appendStringInfoChar(&result, '}');
2382 
2383  pfree(in_datums);
2384  pfree(in_nulls);
2385 
2386  rval = cstring_to_text_with_len(result.data, result.len);
2387  pfree(result.data);
2388 
2389  PG_RETURN_TEXT_P(rval);
2390 
2391 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define ereport(elevel, rest)
Definition: elog.h:141
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define ARR_NDIM(a)
Definition: array.h:278
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:83
Definition: c.h:549

◆ json_object_agg_finalfn()

Datum json_object_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 2154 of file json.c.

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

2155 {
2157 
2158  /* cannot be called directly because of internal-type argument */
2159  Assert(AggCheckCallContext(fcinfo, NULL));
2160 
2161  state = PG_ARGISNULL(0) ? NULL : (JsonAggState *) PG_GETARG_POINTER(0);
2162 
2163  /* NULL result for no rows in, as is standard with aggregates */
2164  if (state == NULL)
2165  PG_RETURN_NULL();
2166 
2167  /* Else return state with appropriate object terminator added */
2169 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
Definition: json.c:2177
StringInfo str
Definition: json.c:71
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define Assert(condition)
Definition: c.h:732
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3572
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_object_agg_transfn()

Datum json_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 2063 of file json.c.

References AggCheckCallContext(), appendStringInfoString(), arg, datum_to_json(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), JsonAggState::key_category, JsonAggState::key_output_func, makeStringInfo(), MemoryContextSwitchTo(), palloc(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, JsonAggState::str, JsonAggState::val_category, and JsonAggState::val_output_func.

2064 {
2065  MemoryContext aggcontext,
2066  oldcontext;
2068  Datum arg;
2069 
2070  if (!AggCheckCallContext(fcinfo, &aggcontext))
2071  {
2072  /* cannot be called directly because of internal-type argument */
2073  elog(ERROR, "json_object_agg_transfn called in non-aggregate context");
2074  }
2075 
2076  if (PG_ARGISNULL(0))
2077  {
2078  Oid arg_type;
2079 
2080  /*
2081  * Make the StringInfo in a context where it will persist for the
2082  * duration of the aggregate call. Switching context is only needed
2083  * for this initial step, as the StringInfo routines make sure they
2084  * use the right context to enlarge the object if necessary.
2085  */
2086  oldcontext = MemoryContextSwitchTo(aggcontext);
2087  state = (JsonAggState *) palloc(sizeof(JsonAggState));
2088  state->str = makeStringInfo();
2089  MemoryContextSwitchTo(oldcontext);
2090 
2091  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
2092 
2093  if (arg_type == InvalidOid)
2094  ereport(ERROR,
2095  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2096  errmsg("could not determine data type for argument %d", 1)));
2097 
2098  json_categorize_type(arg_type, &state->key_category,
2099  &state->key_output_func);
2100 
2101  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
2102 
2103  if (arg_type == InvalidOid)
2104  ereport(ERROR,
2105  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2106  errmsg("could not determine data type for argument %d", 2)));
2107 
2108  json_categorize_type(arg_type, &state->val_category,
2109  &state->val_output_func);
2110 
2111  appendStringInfoString(state->str, "{ ");
2112  }
2113  else
2114  {
2115  state = (JsonAggState *) PG_GETARG_POINTER(0);
2116  appendStringInfoString(state->str, ", ");
2117  }
2118 
2119  /*
2120  * Note: since json_object_agg() is declared as taking type "any", the
2121  * parser will not do any type conversion on unknown-type literals (that
2122  * is, undecorated strings or NULLs). Such values will arrive here as
2123  * type UNKNOWN, which fortunately does not matter to us, since
2124  * unknownout() works fine.
2125  */
2126 
2127  if (PG_ARGISNULL(1))
2128  ereport(ERROR,
2129  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2130  errmsg("field name must not be null")));
2131 
2132  arg = PG_GETARG_DATUM(1);
2133 
2134  datum_to_json(arg, false, state->str, state->key_category,
2135  state->key_output_func, true);
2136 
2137  appendStringInfoString(state->str, " : ");
2138 
2139  if (PG_ARGISNULL(2))
2140  arg = (Datum) 0;
2141  else
2142  arg = PG_GETARG_DATUM(2);
2143 
2144  datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
2145  state->val_output_func, false);
2146 
2147  PG_RETURN_POINTER(state);
2148 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:570
Oid val_output_func
Definition: json.c:75
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
Oid key_output_func
Definition: json.c:73
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
StringInfo str
Definition: json.c:71
#define ereport(elevel, rest)
Definition: elog.h:141
JsonTypeCategory key_category
Definition: json.c:72
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
JsonTypeCategory val_category
Definition: json.c:74
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3572
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
void * arg

◆ json_object_two_arg()

Datum json_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 2400 of file json.c.

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.

2401 {
2402  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
2403  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
2404  int nkdims = ARR_NDIM(key_array);
2405  int nvdims = ARR_NDIM(val_array);
2406  StringInfoData result;
2407  Datum *key_datums,
2408  *val_datums;
2409  bool *key_nulls,
2410  *val_nulls;
2411  int key_count,
2412  val_count,
2413  i;
2414  text *rval;
2415  char *v;
2416 
2417  if (nkdims > 1 || nkdims != nvdims)
2418  ereport(ERROR,
2419  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2420  errmsg("wrong number of array subscripts")));
2421 
2422  if (nkdims == 0)
2424 
2425  deconstruct_array(key_array,
2426  TEXTOID, -1, false, 'i',
2427  &key_datums, &key_nulls, &key_count);
2428 
2429  deconstruct_array(val_array,
2430  TEXTOID, -1, false, 'i',
2431  &val_datums, &val_nulls, &val_count);
2432 
2433  if (key_count != val_count)
2434  ereport(ERROR,
2435  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2436  errmsg("mismatched array dimensions")));
2437 
2438  initStringInfo(&result);
2439 
2440  appendStringInfoChar(&result, '{');
2441 
2442  for (i = 0; i < key_count; ++i)
2443  {
2444  if (key_nulls[i])
2445  ereport(ERROR,
2446  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2447  errmsg("null value not allowed for object key")));
2448 
2449  v = TextDatumGetCString(key_datums[i]);
2450  if (i > 0)
2451  appendStringInfoString(&result, ", ");
2452  escape_json(&result, v);
2453  appendStringInfoString(&result, " : ");
2454  pfree(v);
2455  if (val_nulls[i])
2456  appendStringInfoString(&result, "null");
2457  else
2458  {
2459  v = TextDatumGetCString(val_datums[i]);
2460  escape_json(&result, v);
2461  pfree(v);
2462  }
2463  }
2464 
2465  appendStringInfoChar(&result, '}');
2466 
2467  pfree(key_datums);
2468  pfree(key_nulls);
2469  pfree(val_datums);
2470  pfree(val_nulls);
2471 
2472  rval = cstring_to_text_with_len(result.data, result.len);
2473  pfree(result.data);
2474 
2475  PG_RETURN_TEXT_P(rval);
2476 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define ereport(elevel, rest)
Definition: elog.h:141
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define ARR_NDIM(a)
Definition: array.h:278
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:83
Definition: c.h:549

◆ json_out()

Datum json_out ( PG_FUNCTION_ARGS  )

Definition at line 246 of file json.c.

References PG_GETARG_DATUM, PG_RETURN_CSTRING, and TextDatumGetCString.

247 {
248  /* we needn't detoast because text_to_cstring will handle that */
249  Datum txt = PG_GETARG_DATUM(0);
250 
252 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352

◆ json_recv()

Datum json_recv ( PG_FUNCTION_ARGS  )

Definition at line 272 of file json.c.

References buf, cstring_to_text_with_len(), StringInfoData::cursor, StringInfoData::len, makeJsonLexContextCstringLen(), PG_GETARG_POINTER, pg_parse_json(), PG_RETURN_TEXT_P, pq_getmsgtext(), and JsonAggState::str.

273 {
275  char *str;
276  int nbytes;
277  JsonLexContext *lex;
278 
279  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
280 
281  /* Validate it. */
282  lex = makeJsonLexContextCstringLen(str, nbytes, false);
284 
286 }
StringInfoData * StringInfo
Definition: stringinfo.h:43
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
static char * buf
Definition: pg_test_fsync.c:68
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
Definition: json.c:309
static JsonSemAction nullSemAction
Definition: json.c:110

◆ json_send()

Datum json_send ( PG_FUNCTION_ARGS  )

Definition at line 258 of file json.c.

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

259 {
260  text *t = PG_GETARG_TEXT_PP(0);
262 
263  pq_begintypsend(&buf);
266 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
static char * buf
Definition: pg_test_fsync.c:68
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
Definition: c.h:549

◆ json_typeof()

Datum json_typeof ( PG_FUNCTION_ARGS  )

Definition at line 2537 of file json.c.

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

2538 {
2539  text *json;
2540 
2541  JsonLexContext *lex;
2542  JsonTokenType tok;
2543  char *type;
2544 
2545  json = PG_GETARG_TEXT_PP(0);
2546  lex = makeJsonLexContext(json, false);
2547 
2548  /* Lex exactly one token from the input and check its type. */
2549  json_lex(lex);
2550  tok = lex_peek(lex);
2551  switch (tok)
2552  {
2554  type = "object";
2555  break;
2557  type = "array";
2558  break;
2559  case JSON_TOKEN_STRING:
2560  type = "string";
2561  break;
2562  case JSON_TOKEN_NUMBER:
2563  type = "number";
2564  break;
2565  case JSON_TOKEN_TRUE:
2566  case JSON_TOKEN_FALSE:
2567  type = "boolean";
2568  break;
2569  case JSON_TOKEN_NULL:
2570  type = "null";
2571  break;
2572  default:
2573  elog(ERROR, "unexpected json token: %d", tok);
2574  }
2575 
2577 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
#define ERROR
Definition: elog.h:43
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
static void json_lex(JsonLexContext *lex)
Definition: json.c:614
#define elog(elevel,...)
Definition: elog.h:226
Definition: c.h:549
JsonTokenType
Definition: jsonapi.h:20

◆ JsonEncodeDateTime()

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

Definition at line 1557 of file json.c.

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, and USECS_PER_SEC.

Referenced by convertJsonbScalar(), datum_to_json(), and datum_to_jsonb().

1558 {
1559  if (!buf)
1560  buf = palloc(MAXDATELEN + 1);
1561 
1562  switch (typid)
1563  {
1564  case DATEOID:
1565  {
1566  DateADT date;
1567  struct pg_tm tm;
1568 
1569  date = DatumGetDateADT(value);
1570 
1571  /* Same as date_out(), but forcing DateStyle */
1572  if (DATE_NOT_FINITE(date))
1573  EncodeSpecialDate(date, buf);
1574  else
1575  {
1577  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
1579  }
1580  }
1581  break;
1582  case TIMEOID:
1583  {
1584  TimeADT time = DatumGetTimeADT(value);
1585  struct pg_tm tt,
1586  *tm = &tt;
1587  fsec_t fsec;
1588 
1589  /* Same as time_out(), but forcing DateStyle */
1590  time2tm(time, tm, &fsec);
1591  EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
1592  }
1593  break;
1594  case TIMETZOID:
1595  {
1597  struct pg_tm tt,
1598  *tm = &tt;
1599  fsec_t fsec;
1600  int tz;
1601 
1602  /* Same as timetz_out(), but forcing DateStyle */
1603  timetz2tm(time, tm, &fsec, &tz);
1604  EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
1605  }
1606  break;
1607  case TIMESTAMPOID:
1608  {
1610  struct pg_tm tm;
1611  fsec_t fsec;
1612 
1613  timestamp = DatumGetTimestamp(value);
1614  /* Same as timestamp_out(), but forcing DateStyle */
1615  if (TIMESTAMP_NOT_FINITE(timestamp))
1616  EncodeSpecialTimestamp(timestamp, buf);
1617  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
1618  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
1619  else
1620  ereport(ERROR,
1621  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1622  errmsg("timestamp out of range")));
1623  }
1624  break;
1625  case TIMESTAMPTZOID:
1626  {
1628  struct pg_tm tm;
1629  int tz;
1630  fsec_t fsec;
1631  const char *tzn = NULL;
1632 
1633  timestamp = DatumGetTimestampTz(value);
1634 
1635  /*
1636  * If a time zone is specified, we apply the time-zone shift,
1637  * convert timestamptz to pg_tm as if it were without a time
1638  * zone, and then use the specified time zone for converting
1639  * the timestamp into a string.
1640  */
1641  if (tzp)
1642  {
1643  tz = *tzp;
1644  timestamp -= (TimestampTz) tz * USECS_PER_SEC;
1645  }
1646 
1647  /* Same as timestamptz_out(), but forcing DateStyle */
1648  if (TIMESTAMP_NOT_FINITE(timestamp))
1649  EncodeSpecialTimestamp(timestamp, buf);
1650  else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
1651  tzp ? NULL : &tzn, NULL) == 0)
1652  {
1653  if (tzp)
1654  tm.tm_isdst = 1; /* set time-zone presence flag */
1655 
1656  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
1657  }
1658  else
1659  ereport(ERROR,
1660  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1661  errmsg("timestamp out of range")));
1662  }
1663  break;
1664  default:
1665  elog(ERROR, "unknown jsonb value datetime type oid %d", typid);
1666  return NULL;
1667  }
1668 
1669  return buf;
1670 }
#define MAXDATELEN
Definition: datetime.h:201
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3858
#define DatumGetDateADT(X)
Definition: date.h:53
int tm_isdst
Definition: pgtime.h:35
#define USECS_PER_SEC
Definition: timestamp.h:94
int32 DateADT
Definition: date.h:23
int64 timestamp
int64 TimestampTz
Definition: timestamp.h:39
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
#define DatumGetTimeTzADTP(X)
Definition: date.h:55
static struct @145 value
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:3943
int errcode(int sqlerrcode)
Definition: elog.c:570
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1273
long date
Definition: pgtypes_date.h:9
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1536
Definition: pgtime.h:25
static struct pg_tm tm
Definition: localtime.c:108
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
#define ERROR
Definition: elog.h:43
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int tm_mday
Definition: pgtime.h:30
static char * buf
Definition: pg_test_fsync.c:68
int tm_mon
Definition: pgtime.h:31
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:3973
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:284
int32 fsec_t
Definition: timestamp.h:41
int64 TimeADT
Definition: date.h:25
#define ereport(elevel, rest)
Definition: elog.h:141
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:295
int64 Timestamp
Definition: timestamp.h:38
#define DatumGetTimeADT(X)
Definition: date.h:54
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2146
#define USE_XSD_DATES
Definition: miscadmin.h:217
int tm_year
Definition: pgtime.h:32
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
Definition: date.h:27
#define DatumGetTimestamp(X)
Definition: timestamp.h:27

◆ lex_accept()

static bool lex_accept ( JsonLexContext lex,
JsonTokenType  token,
char **  lexeme 
)
inlinestatic

Definition at line 139 of file json.c.

References StringInfoData::data, json_lex(), JSON_TOKEN_STRING, palloc(), pstrdup(), JsonLexContext::strval, JsonLexContext::token_start, JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by json_count_array_elements(), lex_expect(), parse_array(), parse_object(), parse_object_field(), and parse_scalar().

140 {
141  if (lex->token_type == token)
142  {
143  if (lexeme != NULL)
144  {
145  if (lex->token_type == JSON_TOKEN_STRING)
146  {
147  if (lex->strval != NULL)
148  *lexeme = pstrdup(lex->strval->data);
149  }
150  else
151  {
152  int len = (lex->token_terminator - lex->token_start);
153  char *tokstr = palloc(len + 1);
154 
155  memcpy(tokstr, lex->token_start, len);
156  tokstr[len] = '\0';
157  *lexeme = tokstr;
158  }
159  }
160  json_lex(lex);
161  return true;
162  }
163  return false;
164 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
JsonTokenType token_type
Definition: jsonapi.h:58
StringInfo strval
Definition: jsonapi.h:62
char * token_start
Definition: jsonapi.h:55
char * token_terminator
Definition: jsonapi.h:56
static void json_lex(JsonLexContext *lex)
Definition: json.c:614
void * palloc(Size size)
Definition: mcxt.c:949

◆ lex_expect()

static void lex_expect ( JsonParseContext  ctx,
JsonLexContext lex,
JsonTokenType  token 
)
inlinestatic

Definition at line 173 of file json.c.

References lex_accept(), and report_parse_error().

Referenced by json_count_array_elements(), parse_array(), parse_object(), parse_object_field(), and pg_parse_json().

174 {
175  if (!lex_accept(lex, token, NULL))
176  report_parse_error(ctx, lex);
177 }
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
static void report_parse_error(JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1126

◆ lex_peek()

static JsonTokenType lex_peek ( JsonLexContext lex)
inlinestatic

Definition at line 124 of file json.c.

References JsonLexContext::token_type.

Referenced by json_count_array_elements(), json_typeof(), parse_array(), parse_array_element(), parse_object(), parse_object_field(), parse_scalar(), and pg_parse_json().

125 {
126  return lex->token_type;
127 }
JsonTokenType token_type
Definition: jsonapi.h:58

◆ makeJsonLexContext()

JsonLexContext* makeJsonLexContext ( text json,
bool  need_escapes 
)

Definition at line 301 of file json.c.

References makeJsonLexContextCstringLen(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by datum_to_jsonb(), each_worker(), elements_worker(), get_worker(), iterate_json_values(), json_array_length(), json_in(), json_object_keys(), json_strip_nulls(), json_typeof(), populate_recordset_worker(), and transform_json_string_values().

302 {
304  VARSIZE_ANY_EXHDR(json),
305  need_escapes);
306 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
Definition: json.c:309
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341

◆ makeJsonLexContextCstringLen()

JsonLexContext* makeJsonLexContextCstringLen ( char *  json,
int  len,
bool  need_escapes 
)

Definition at line 309 of file json.c.

References JsonLexContext::input, JsonLexContext::input_length, JsonLexContext::line_number, JsonLexContext::line_start, makeStringInfo(), palloc0(), JsonLexContext::strval, and JsonLexContext::token_terminator.

Referenced by get_json_object_as_hash(), json_recv(), jsonb_from_cstring(), makeJsonLexContext(), and populate_array_json().

310 {
311  JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
312 
313  lex->input = lex->token_terminator = lex->line_start = json;
314  lex->line_number = 1;
315  lex->input_length = len;
316  if (need_escapes)
317  lex->strval = makeStringInfo();
318  return lex;
319 }
int line_number
Definition: jsonapi.h:60
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
char * line_start
Definition: jsonapi.h:61
int input_length
Definition: jsonapi.h:54
StringInfo strval
Definition: jsonapi.h:62
void * palloc0(Size size)
Definition: mcxt.c:980
char * token_terminator
Definition: jsonapi.h:56
char * input
Definition: jsonapi.h:53

◆ parse_array()

static void parse_array ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 570 of file json.c.

References JsonSemAction::array_end, JsonSemAction::array_start, check_stack_depth(), JSON_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COMMA, lex_accept(), lex_expect(), JsonLexContext::lex_level, lex_peek(), parse_array_element(), and JsonSemAction::semstate.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

571 {
572  /*
573  * an array is a possibly empty sequence of array elements, separated by
574  * commas and surrounded by square brackets.
575  */
576  json_struct_action astart = sem->array_start;
577  json_struct_action aend = sem->array_end;
578 
580 
581  if (astart != NULL)
582  (*astart) (sem->semstate);
583 
584  /*
585  * Data inside an array is at a higher nesting level than the array
586  * itself. Note that we increment this after we call the semantic routine
587  * for the array start and restore it before we call the routine for the
588  * array end.
589  */
590  lex->lex_level++;
591 
593  if (lex_peek(lex) != JSON_TOKEN_ARRAY_END)
594  {
595 
596  parse_array_element(lex, sem);
597 
598  while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
599  parse_array_element(lex, sem);
600  }
601 
603 
604  lex->lex_level--;
605 
606  if (aend != NULL)
607  (*aend) (sem->semstate);
608 }
json_struct_action array_end
Definition: jsonapi.h:88
static void lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: json.c:173
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
int lex_level
Definition: jsonapi.h:59
void check_stack_depth(void)
Definition: postgres.c:3262
static void parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:539
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
json_struct_action array_start
Definition: jsonapi.h:87
void(* json_struct_action)(void *state)
Definition: jsonapi.h:65
void * semstate
Definition: jsonapi.h:84

◆ parse_array_element()

static void parse_array_element ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 539 of file json.c.

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JSON_TOKEN_ARRAY_START, JSON_TOKEN_NULL, JSON_TOKEN_OBJECT_START, lex_peek(), parse_array(), parse_object(), parse_scalar(), and JsonSemAction::semstate.

Referenced by json_count_array_elements(), and parse_array().

540 {
543  JsonTokenType tok = lex_peek(lex);
544 
545  bool isnull;
546 
547  isnull = tok == JSON_TOKEN_NULL;
548 
549  if (astart != NULL)
550  (*astart) (sem->semstate, isnull);
551 
552  /* an array element is any object, array or scalar */
553  switch (tok)
554  {
556  parse_object(lex, sem);
557  break;
559  parse_array(lex, sem);
560  break;
561  default:
562  parse_scalar(lex, sem);
563  }
564 
565  if (aend != NULL)
566  (*aend) (sem->semstate, isnull);
567 }
static void parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:570
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:407
void(* json_aelem_action)(void *state, bool isnull)
Definition: jsonapi.h:67
void * semstate
Definition: jsonapi.h:84
static void parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:489
json_aelem_action array_element_end
Definition: jsonapi.h:92
JsonTokenType
Definition: jsonapi.h:20

◆ parse_object()

static void parse_object ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 489 of file json.c.

References check_stack_depth(), JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_START, JSON_TOKEN_COMMA, JSON_TOKEN_OBJECT_END, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, lex_accept(), lex_expect(), JsonLexContext::lex_level, lex_peek(), JsonSemAction::object_end, JsonSemAction::object_start, parse_object_field(), report_parse_error(), and JsonSemAction::semstate.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

490 {
491  /*
492  * an object is a possibly empty sequence of object fields, separated by
493  * commas and surrounded by curly braces.
494  */
495  json_struct_action ostart = sem->object_start;
496  json_struct_action oend = sem->object_end;
497  JsonTokenType tok;
498 
500 
501  if (ostart != NULL)
502  (*ostart) (sem->semstate);
503 
504  /*
505  * Data inside an object is at a higher nesting level than the object
506  * itself. Note that we increment this after we call the semantic routine
507  * for the object start and restore it before we call the routine for the
508  * object end.
509  */
510  lex->lex_level++;
511 
512  /* we know this will succeed, just clearing the token */
514 
515  tok = lex_peek(lex);
516  switch (tok)
517  {
518  case JSON_TOKEN_STRING:
519  parse_object_field(lex, sem);
520  while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
521  parse_object_field(lex, sem);
522  break;
524  break;
525  default:
526  /* case of an invalid initial token inside the object */
528  }
529 
531 
532  lex->lex_level--;
533 
534  if (oend != NULL)
535  (*oend) (sem->semstate);
536 }
json_struct_action object_end
Definition: jsonapi.h:86
json_struct_action object_start
Definition: jsonapi.h:85
static void lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: json.c:173
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
int lex_level
Definition: jsonapi.h:59
void check_stack_depth(void)
Definition: postgres.c:3262
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
static void report_parse_error(JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1126
void(* json_struct_action)(void *state)
Definition: jsonapi.h:65
static void parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:443
void * semstate
Definition: jsonapi.h:84
JsonTokenType
Definition: jsonapi.h:20

◆ parse_object_field()

static void parse_object_field ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 443 of file json.c.

References JSON_PARSE_OBJECT_LABEL, JSON_PARSE_STRING, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COLON, JSON_TOKEN_NULL, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, lex_accept(), lex_expect(), lex_peek(), JsonSemAction::object_field_end, JsonSemAction::object_field_start, parse_array(), parse_object(), parse_scalar(), report_parse_error(), and JsonSemAction::semstate.

Referenced by parse_object().

444 {
445  /*
446  * An object field is "fieldname" : value where value can be a scalar,
447  * object or array. Note: in user-facing docs and error messages, we
448  * generally call a field name a "key".
449  */
450 
451  char *fname = NULL; /* keep compiler quiet */
454  bool isnull;
455  char **fnameaddr = NULL;
456  JsonTokenType tok;
457 
458  if (ostart != NULL || oend != NULL)
459  fnameaddr = &fname;
460 
461  if (!lex_accept(lex, JSON_TOKEN_STRING, fnameaddr))
463 
465 
466  tok = lex_peek(lex);
467  isnull = tok == JSON_TOKEN_NULL;
468 
469  if (ostart != NULL)
470  (*ostart) (sem->semstate, fname, isnull);
471 
472  switch (tok)
473  {
475  parse_object(lex, sem);
476  break;
478  parse_array(lex, sem);
479  break;
480  default:
481  parse_scalar(lex, sem);
482  }
483 
484  if (oend != NULL)
485  (*oend) (sem->semstate, fname, isnull);
486 }
static void lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: json.c:173
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
void(* json_ofield_action)(void *state, char *fname, bool isnull)
Definition: jsonapi.h:66
static void parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:570
json_ofield_action object_field_end
Definition: jsonapi.h:90
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
static void report_parse_error(JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1126
static void parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:407
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:489
JsonTokenType
Definition: jsonapi.h:20

◆ parse_scalar()

static void parse_scalar ( JsonLexContext lex,
JsonSemAction sem 
)
inlinestatic

Definition at line 407 of file json.c.

References JSON_PARSE_VALUE, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, lex_accept(), lex_peek(), report_parse_error(), JsonSemAction::scalar, JsonSemAction::semstate, and val.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

408 {
409  char *val = NULL;
410  json_scalar_action sfunc = sem->scalar;
411  char **valaddr;
412  JsonTokenType tok = lex_peek(lex);
413 
414  valaddr = sfunc == NULL ? NULL : &val;
415 
416  /* a scalar must be a string, a number, true, false, or null */
417  switch (tok)
418  {
419  case JSON_TOKEN_TRUE:
420  lex_accept(lex, JSON_TOKEN_TRUE, valaddr);
421  break;
422  case JSON_TOKEN_FALSE:
423  lex_accept(lex, JSON_TOKEN_FALSE, valaddr);
424  break;
425  case JSON_TOKEN_NULL:
426  lex_accept(lex, JSON_TOKEN_NULL, valaddr);
427  break;
428  case JSON_TOKEN_NUMBER:
429  lex_accept(lex, JSON_TOKEN_NUMBER, valaddr);
430  break;
431  case JSON_TOKEN_STRING:
432  lex_accept(lex, JSON_TOKEN_STRING, valaddr);
433  break;
434  default:
436  }
437 
438  if (sfunc != NULL)
439  (*sfunc) (sem->semstate, val, tok);
440 }
void(* json_scalar_action)(void *state, char *token, JsonTokenType tokentype)
Definition: jsonapi.h:68
json_scalar_action scalar
Definition: jsonapi.h:93
static bool lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
Definition: json.c:139
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
static void report_parse_error(JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn()
Definition: json.c:1126
void * semstate
Definition: jsonapi.h:84
long val
Definition: informix.c:684
JsonTokenType
Definition: jsonapi.h:20

◆ pg_parse_json()

void pg_parse_json ( JsonLexContext lex,
JsonSemAction sem 
)

Definition at line 332 of file json.c.

References json_lex(), JSON_PARSE_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_END, JSON_TOKEN_OBJECT_START, lex_expect(), lex_peek(), parse_array(), parse_object(), and parse_scalar().

Referenced by datum_to_jsonb(), each_worker(), elements_worker(), get_json_object_as_hash(), get_worker(), iterate_json_values(), json_array_length(), json_in(), json_object_keys(), json_recv(), json_strip_nulls(), jsonb_from_cstring(), populate_array_json(), populate_recordset_worker(), and transform_json_string_values().

333 {
334  JsonTokenType tok;
335 
336  /* get the initial token */
337  json_lex(lex);
338 
339  tok = lex_peek(lex);
340 
341  /* parse by recursive descent */
342  switch (tok)
343  {
345  parse_object(lex, sem);
346  break;
348  parse_array(lex, sem);
349  break;
350  default:
351  parse_scalar(lex, sem); /* json can be a bare scalar */
352  }
353 
355 
356 }
static void lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: json.c:173
static void parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:570
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: json.c:124
static void json_lex(JsonLexContext *lex)
Definition: json.c:614
static void parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:407
static void parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:489
JsonTokenType
Definition: jsonapi.h:20

◆ report_invalid_token()

static void report_invalid_token ( JsonLexContext lex)
static

Definition at line 1233 of file json.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, palloc(), report_json_context(), JsonLexContext::token_start, and JsonLexContext::token_terminator.

Referenced by json_lex(), json_lex_number(), and json_lex_string().

1234 {
1235  char *token;
1236  int toklen;
1237 
1238  /* Separate out the offending token. */
1239  toklen = lex->token_terminator - lex->token_start;
1240  token = palloc(toklen + 1);
1241  memcpy(token, lex->token_start, toklen);
1242  token[toklen] = '\0';
1243 
1244  ereport(ERROR,
1245  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1246  errmsg("invalid input syntax for type %s", "json"),
1247  errdetail("Token \"%s\" is invalid.", token),
1248  report_json_context(lex)));
1249 }
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:860
#define ereport(elevel, rest)
Definition: elog.h:141
char * token_start
Definition: jsonapi.h:55
char * token_terminator
Definition: jsonapi.h:56
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
static int report_json_context(JsonLexContext *lex)
Definition: json.c:1262

◆ report_json_context()

static int report_json_context ( JsonLexContext lex)
static

Definition at line 1262 of file json.c.

References errcontext, JsonLexContext::input, JsonLexContext::input_length, IS_HIGHBIT_SET, JSON_TOKEN_END, palloc(), pg_mblen(), JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by json_lex_string(), report_invalid_token(), and report_parse_error().

1263 {
1264  const char *context_start;
1265  const char *context_end;
1266  const char *line_start;
1267  int line_number;
1268  char *ctxt;
1269  int ctxtlen;
1270  const char *prefix;
1271  const char *suffix;
1272 
1273  /* Choose boundaries for the part of the input we will display */
1274  context_start = lex->input;
1275  context_end = lex->token_terminator;
1276  line_start = context_start;
1277  line_number = 1;
1278  for (;;)
1279  {
1280  /* Always advance over newlines */
1281  if (context_start < context_end && *context_start == '\n')
1282  {
1283  context_start++;
1284  line_start = context_start;
1285  line_number++;
1286  continue;
1287  }
1288  /* Otherwise, done as soon as we are close enough to context_end */
1289  if (context_end - context_start < 50)
1290  break;
1291  /* Advance to next multibyte character */
1292  if (IS_HIGHBIT_SET(*context_start))
1293  context_start += pg_mblen(context_start);
1294  else
1295  context_start++;
1296  }
1297 
1298  /*
1299  * We add "..." to indicate that the excerpt doesn't start at the
1300  * beginning of the line ... but if we're within 3 characters of the
1301  * beginning of the line, we might as well just show the whole line.
1302  */
1303  if (context_start - line_start <= 3)
1304  context_start = line_start;
1305 
1306  /* Get a null-terminated copy of the data to present */
1307  ctxtlen = context_end - context_start;
1308  ctxt = palloc(ctxtlen + 1);
1309  memcpy(ctxt, context_start, ctxtlen);
1310  ctxt[ctxtlen] = '\0';
1311 
1312  /*
1313  * Show the context, prefixing "..." if not starting at start of line, and
1314  * suffixing "..." if not ending at end of line.
1315  */
1316  prefix = (context_start > line_start) ? "..." : "";
1317  suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : "";
1318 
1319  return errcontext("JSON data, line %d: %s%s%s",
1320  line_number, prefix, ctxt, suffix);
1321 }
JsonTokenType token_type
Definition: jsonapi.h:58
int input_length
Definition: jsonapi.h:54
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1075
char * token_terminator
Definition: jsonapi.h:56
char * input
Definition: jsonapi.h:53
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802
void * palloc(Size size)
Definition: mcxt.c:949
#define errcontext
Definition: elog.h:183

◆ report_parse_error()

static void report_parse_error ( JsonParseContext  ctx,
JsonLexContext lex 
)
static

Definition at line 1126 of file json.c.

References elog, ereport, errcode(), errdetail(), errmsg(), ERROR, JSON_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_PARSE_END, JSON_PARSE_OBJECT_COMMA, JSON_PARSE_OBJECT_LABEL, JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_START, JSON_PARSE_STRING, JSON_PARSE_VALUE, JSON_TOKEN_END, palloc(), report_json_context(), JsonLexContext::token_start, JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by lex_expect(), parse_object(), parse_object_field(), and parse_scalar().

1127 {
1128  char *token;
1129  int toklen;
1130 
1131  /* Handle case where the input ended prematurely. */
1132  if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
1133  ereport(ERROR,
1134  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1135  errmsg("invalid input syntax for type %s", "json"),
1136  errdetail("The input string ended unexpectedly."),
1137  report_json_context(lex)));
1138 
1139  /* Separate out the current token. */
1140  toklen = lex->token_terminator - lex->token_start;
1141  token = palloc(toklen + 1);
1142  memcpy(token, lex->token_start, toklen);
1143  token[toklen] = '\0';
1144 
1145  /* Complain, with the appropriate detail message. */
1146  if (ctx == JSON_PARSE_END)
1147  ereport(ERROR,
1148  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1149  errmsg("invalid input syntax for type %s", "json"),
1150  errdetail("Expected end of input, but found \"%s\".",
1151  token),
1152  report_json_context(lex)));
1153  else
1154  {
1155  switch (ctx)
1156  {
1157  case JSON_PARSE_VALUE:
1158  ereport(ERROR,
1159  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1160  errmsg("invalid input syntax for type %s", "json"),
1161  errdetail("Expected JSON value, but found \"%s\".",
1162  token),
1163  report_json_context(lex)));
1164  break;
1165  case JSON_PARSE_STRING:
1166  ereport(ERROR,
1167  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1168  errmsg("invalid input syntax for type %s", "json"),
1169  errdetail("Expected string, but found \"%s\".",
1170  token),
1171  report_json_context(lex)));
1172  break;
1174  ereport(ERROR,
1175  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1176  errmsg("invalid input syntax for type %s", "json"),
1177  errdetail("Expected array element or \"]\", but found \"%s\".",
1178  token),
1179  report_json_context(lex)));
1180  break;
1181  case JSON_PARSE_ARRAY_NEXT:
1182  ereport(ERROR,
1183  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1184  errmsg("invalid input syntax for type %s", "json"),
1185  errdetail("Expected \",\" or \"]\", but found \"%s\".",
1186  token),
1187  report_json_context(lex)));
1188  break;
1190  ereport(ERROR,
1191  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1192  errmsg("invalid input syntax for type %s", "json"),
1193  errdetail("Expected string or \"}\", but found \"%s\".",
1194  token),
1195  report_json_context(lex)));
1196  break;
1198  ereport(ERROR,
1199  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1200  errmsg("invalid input syntax for type %s", "json"),
1201  errdetail("Expected \":\", but found \"%s\".",
1202  token),
1203  report_json_context(lex)));
1204  break;
1206  ereport(ERROR,
1207  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1208  errmsg("invalid input syntax for type %s", "json"),
1209  errdetail("Expected \",\" or \"}\", but found \"%s\".",
1210  token),
1211  report_json_context(lex)));
1212  break;
1214  ereport(ERROR,
1215  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1216  errmsg("invalid input syntax for type %s", "json"),
1217  errdetail("Expected string, but found \"%s\".",
1218  token),
1219  report_json_context(lex)));
1220  break;
1221  default:
1222  elog(ERROR, "unexpected json parse state: %d", ctx);
1223  }
1224  }
1225 }
JsonTokenType token_type
Definition: jsonapi.h:58
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:860
#define ereport(elevel, rest)
Definition: elog.h:141
char * token_start
Definition: jsonapi.h:55
char * token_terminator
Definition: jsonapi.h:56
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
static int report_json_context(JsonLexContext *lex)
Definition: json.c:1262

◆ row_to_json()

Datum row_to_json ( PG_FUNCTION_ARGS  )

Definition at line 1900 of file json.c.

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

1901 {
1902  Datum array = PG_GETARG_DATUM(0);
1903  StringInfo result;
1904 
1905  result = makeStringInfo();
1906 
1907  composite_to_json(array, result, false);
1908 
1910 }
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:1767
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361

◆ row_to_json_pretty()

Datum row_to_json_pretty ( PG_FUNCTION_ARGS  )

Definition at line 1916 of file json.c.

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.

1917 {
1918  Datum array = PG_GETARG_DATUM(0);
1919  bool use_line_feeds = PG_GETARG_BOOL(1);
1920  StringInfo result;
1921 
1922  result = makeStringInfo();
1923 
1924  composite_to_json(array, result, use_line_feeds);
1925 
1927 }
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
Definition: json.c:1767
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361

◆ to_json()

Datum to_json ( PG_FUNCTION_ARGS  )

Definition at line 1933 of file json.c.

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.

1934 {
1935  Datum val = PG_GETARG_DATUM(0);
1936  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1937  StringInfo result;
1938  JsonTypeCategory tcategory;
1939  Oid outfuncoid;
1940 
1941  if (val_type == InvalidOid)
1942  ereport(ERROR,
1943  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1944  errmsg("could not determine input data type")));
1945 
1946  json_categorize_type(val_type,
1947  &tcategory, &outfuncoid);
1948 
1949  result = makeStringInfo();
1950 
1951  datum_to_json(val, false, result, tcategory, outfuncoid, false);
1952 
1954 }
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: json.c:1450
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:1348
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
JsonTypeCategory
Definition: json.c:54
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
int errmsg(const char *fmt,...)
Definition: elog.c:784
long val
Definition: informix.c:684

Variable Documentation

◆ nullSemAction

JsonSemAction nullSemAction
static
Initial value:
=
{
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL
}

Definition at line 110 of file json.c.