1/*-------------------------------------------------------------------------
4 * JSON data type support.
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/adt/json.c
12 *-------------------------------------------------------------------------
28#include "utils/fmgroids.h"
36 * Support for fast key uniqueness checking.
38 * We maintain a hash table of used keys in JSON objects for fast detection
41/* Common context for key uniqueness check */
44/* Hash entry for JsonUniqueCheckState */
52/* Stack element for key uniqueness check during JSON parsing */
59/* Context struct for key uniqueness check during JSON parsing */
69/* Context struct for key uniqueness check during JSON building */
78/* State struct for JSON aggregation */
92 Datum *vals,
bool *nulls,
int *valcount,
101 Oid val_type,
bool key_scalar);
119 /* Internal representation is the same as text */
129 /* we needn't detoast because text_to_cstring will handle that */
171 * Turn a Datum into JSON text, appending the string to "result".
173 * tcategory and outfuncoid are from a previous call to json_categorize_type,
174 * except that if is_null is true then they can be invalid.
176 * If key_scalar is true, the value is being printed as a key, so insist
177 * it's of an acceptable type, and force it to be quoted.
189 /* callers are expected to ensure that null keys are not passed in */
190 Assert(!(key_scalar && is_null));
204 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
205 errmsg(
"key value must be scalar, not array, composite, or json")));
229 * Don't quote a non-key if it's a valid JSON number (i.e., not
230 * "Infinity", "-Infinity", or "NaN"). Since we know this is a
231 * numeric data type's output, we simplify and open-code the
232 * validation for better performance.
235 ((*outputstr >=
'0' && *outputstr <=
'9') ||
236 (*outputstr ==
'-' &&
237 (outputstr[1] >=
'0' && outputstr[1] <=
'9'))))
278 /* JSON and JSONB output will already be escaped */
284 /* outfuncoid refers to a cast function, not an output function */
291 /* special-case text types to save useless palloc/memcpy cycles */
292 if (outfuncoid == F_TEXTOUT || outfuncoid == F_VARCHAROUT ||
293 outfuncoid == F_BPCHAROUT)
306 * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
307 * optionally preallocated buffer 'buf'. Optional 'tzp' determines time-zone
308 * offset (in seconds) in which we want to show timestamptz.
325 /* Same as date_out(), but forcing DateStyle */
343 /* Same as time_out(), but forcing DateStyle */
356 /* Same as timetz_out(), but forcing DateStyle */
368 /* Same as timestamp_out(), but forcing DateStyle */
375 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
376 errmsg(
"timestamp out of range")));
385 const char *tzn = NULL;
390 * If a time zone is specified, we apply the time-zone shift,
391 * convert timestamptz to pg_tm as if it were without a time
392 * zone, and then use the specified time zone for converting
393 * the timestamp into a string.
401 /* Same as timestamptz_out(), but forcing DateStyle */
405 tzp ? NULL : &tzn, NULL) == 0)
408 tm.
tm_isdst = 1;
/* set time-zone presence flag */
414 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
415 errmsg(
"timestamp out of range")));
419 elog(
ERROR,
"unknown jsonb value datetime type oid %u", typid);
427 * Process a single dimension of an array.
428 * If it's the innermost dimension, output the values, otherwise call
429 * ourselves recursively to process the next dimension.
434 Oid outfuncoid,
bool use_line_feeds)
441 sep = use_line_feeds ?
",\n " :
",";
445 for (
i = 1;
i <= dims[dim];
i++)
450 if (dim + 1 == ndims)
460 * Do we want line feeds on inner dimensions of arrays? For now
464 valcount, tcategory, outfuncoid,
false);
472 * Turn an array into JSON.
505 &tcategory, &outfuncoid);
512 outfuncoid, use_line_feeds);
519 * Turn a composite / record into JSON.
531 bool needsep =
false;
536 * We can avoid expensive strlen() calls by precalculating the separator
539 sep = use_line_feeds ?
",\n " :
",";
540 seplen = use_line_feeds ? strlen(
",\n ") : strlen(
",");
544 /* Extract rowtype info and find a tupdesc */
549 /* Build a temporary HeapTuple control structure */
556 for (
i = 0;
i < tupdesc->
natts;
i++)
565 if (att->attisdropped)
596 * Append JSON text for "val" to "result".
598 * This is just a thin wrapper around datum_to_json. If the same type will be
599 * printed many times, avoid using this; better to do the json_categorize_type
604 Oid val_type,
bool key_scalar)
611 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
612 errmsg(
"could not determine input data type")));
621 &tcategory, &outfuncoid);
628 * SQL function array_to_json(row)
644 * SQL function array_to_json(row, prettybool)
661 * SQL function row_to_json(row)
677 * SQL function row_to_json(row, prettybool)
694 * Is the given type immutable when coming out of a JSON context?
696 * At present, datetimes are all considered mutable, because they
697 * depend on timezone. XXX we should also drill down into objects
698 * and arrays, but do not.
722 return false;
/* TODO recurse into elements */
725 return false;
/* TODO recurse into fields */
733 return false;
/* not reached */
737 * SQL function to_json(anyvalue)
749 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
750 errmsg(
"could not determine input data type")));
753 &tcategory, &outfuncoid);
759 * Turn a Datum into JSON text.
761 * tcategory and outfuncoid are from a previous call to json_categorize_type.
775 * json_agg transition function
777 * aggregate input column as a json array value.
789 /* cannot be called directly because of internal-type argument */
790 elog(
ERROR,
"json_agg_transfn called in non-aggregate context");
799 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
800 errmsg(
"could not determine input data type")));
803 * Make this state object in a context where it will persist for the
804 * duration of the aggregate call. MemoryContextSwitchTo is only
805 * needed the first time, as the StringInfo routines make sure they
806 * use the right context to enlarge the object if necessary.
815 &
state->val_output_func);
825 if (
state->str->len > 1)
828 /* fast path for NULLs */
838 /* add some whitespace if structured type and not first item */
847 state->val_output_func,
false);
850 * The transition type for json_agg() is declared to be "internal", which
851 * is a pass-by-value type the same size as a pointer. So we can safely
852 * pass the JsonAggState pointer through nodeAgg.c's machinations.
859 * json_agg aggregate function
868 * json_agg_strict aggregate function
877 * json_agg final function
884 /* cannot be called directly because of internal-type argument */
891 /* NULL result for no rows in, as is standard with aggregates */
895 /* Else return state with appropriate array terminator added */
899/* Functions implementing hash table for key uniqueness check */
927 * Uniqueness detection support.
929 * In order to detect uniqueness during building or parsing of a JSON
930 * object, we maintain a hash table of key names already seen.
937 memset(&
ctl, 0,
sizeof(
ctl));
974 * On-demand initialization of a throwaway StringInfo. This is used to
975 * read a key name that we don't need to store in the output object, for
976 * duplicate key detection when the value is NULL.
991 /* Just reset the string to empty */
998 * json_object_agg transition function.
1000 * aggregate two input columns as a single json object value.
1004 bool absent_on_null,
bool unique_keys)
1016 /* cannot be called directly because of internal-type argument */
1017 elog(
ERROR,
"json_object_agg_transfn called in non-aggregate context");
1025 * Make the StringInfo in a context where it will persist for the
1026 * duration of the aggregate call. Switching context is only needed
1027 * for this initial step, as the StringInfo and dynahash routines make
1028 * sure they use the right context to enlarge the object if necessary.
1036 memset(&
state->unique_check, 0,
sizeof(
state->unique_check));
1043 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1044 errmsg(
"could not determine data type for argument %d", 1)));
1047 &
state->key_output_func);
1053 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1054 errmsg(
"could not determine data type for argument %d", 2)));
1057 &
state->val_output_func);
1067 * Note: since json_object_agg() is declared as taking type "any", the
1068 * parser will not do any type conversion on unknown-type literals (that
1069 * is, undecorated strings or NULLs). Such values will arrive here as
1070 * type UNKNOWN, which fortunately does not matter to us, since
1071 * unknownout() works fine.
1076 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1077 errmsg(
"null value not allowed for object key")));
1079 /* Skip null values if absent_on_null */
1085 * We got a NULL value and we're not storing those; if we're not
1086 * testing key uniqueness, we're done. If we are, use the throwaway
1087 * buffer to store the key name so that we can check it.
1099 * Append comma delimiter only if we have already output some fields
1100 * after the initial string "{ ".
1108 key_offset = out->
len;
1111 state->key_output_func,
true);
1116 * Copy the key first, instead of pointing into the buffer. It will be
1117 * added to the hash table, but the buffer may get reallocated as
1118 * we're appending more data to it. That would invalidate pointers to
1119 * keys in the current buffer.
1122 &out->
data[key_offset]);
1126 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1127 errmsg(
"duplicate JSON object key value: %s",
key));
1141 state->val_category,
1142 state->val_output_func,
false);
1148 * json_object_agg aggregate function
1157 * json_object_agg_strict aggregate function
1166 * json_object_agg_unique aggregate function
1175 * json_object_agg_unique_strict aggregate function
1184 * json_object_agg final function.
1191 /* cannot be called directly because of internal-type argument */
1196 /* NULL result for no rows in, as is standard with aggregates */
1200 /* Else return state with appropriate object terminator added */
1205 * Helper function for aggregates: return given StringInfo's contents plus
1206 * specified trailing string, as a text datum. We need this because aggregate
1207 * final functions are not allowed to modify the aggregate state.
1212 /* custom version of cstring_to_text_with_len */
1213 int buflen = buffer->
len;
1214 int addlen = strlen(addon);
1219 memcpy(
VARDATA(result) + buflen, addon, addlen);
1226 bool absent_on_null,
bool unique_keys)
1229 const char *sep =
"";
1235 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1236 errmsg(
"argument list must have even number of elements"),
1237 /* translator: %s is a SQL function name */
1238 errhint(
"The arguments of %s must consist of alternating keys and values.",
1239 "json_build_object()")));
1248 for (
i = 0;
i < nargs;
i += 2)
1254 /* Skip null values if absent_on_null */
1255 skip = absent_on_null && nulls[
i + 1];
1259 /* If key uniqueness check is needed we must save skipped keys */
1275 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1276 errmsg(
"null value not allowed for object key")));
1278 /* save key offset before appending it */
1279 key_offset = out->
len;
1286 * check key uniqueness after key appending
1288 * Copy the key first, instead of pointing into the buffer. It
1289 * will be added to the hash table, but the buffer may get
1290 * reallocated as we're appending more data to it. That would
1291 * invalidate pointers to keys in the current buffer.
1297 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1298 errmsg(
"duplicate JSON object key value: %s",
key));
1316 * SQL function json_build_object(variadic "any")
1325 /* build argument values to build the object */
1336 * degenerate case of json_build_object where it gets 0 arguments.
1346 bool absent_on_null)
1349 const char *sep =
"";
1356 for (
i = 0;
i < nargs;
i++)
1358 if (absent_on_null && nulls[
i])
1372 * SQL function json_build_array(variadic "any")
1381 /* build argument values to build the object */
1392 * degenerate case of json_build_array where it gets 0 arguments.
1401 * SQL function json_object(text[])
1403 * take a one or two dimensional array of text as key/value pairs
1404 * for a json object.
1428 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1429 errmsg(
"array must have even number of elements")));
1435 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1436 errmsg(
"array must have two columns")));
1441 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1442 errmsg(
"wrong number of array subscripts")));
1447 count = in_count / 2;
1453 for (
i = 0;
i < count; ++
i)
1455 if (in_nulls[
i * 2])
1457 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1458 errmsg(
"null value not allowed for object key")));
1464 if (in_nulls[
i * 2 + 1])
1485 * SQL function json_object(text[], text[])
1487 * take separate key and value arrays of text to construct a json object
1507 if (nkdims > 1 || nkdims != nvdims)
1509 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1510 errmsg(
"wrong number of array subscripts")));
1518 if (key_count != val_count)
1520 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1521 errmsg(
"mismatched array dimensions")));
1527 for (
i = 0;
i < key_count; ++
i)
1531 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1532 errmsg(
"null value not allowed for object key")));
1560 * Inline helper function for escape_json* functions
1589 if ((
unsigned char)
c <
' ')
1599 * Produce a JSON string literal, properly escaping the NUL-terminated
1607 for (; *
str !=
'0円';
str++)
1614 * Define the number of bytes that escape_json_with_len will look ahead in the
1615 * input string before flushing the input string to the destination buffer.
1616 * Looking ahead too far could result in cachelines being evicted that will
1617 * need to be reloaded in order to perform the appendBinaryStringInfo call.
1618 * Smaller values will result in a larger number of calls to
1619 * appendBinaryStringInfo and introduce additional function call overhead.
1620 * Values larger than the size of L1d cache will likely result in worse
1623 #define ESCAPE_JSON_FLUSH_AFTER 512
1626 * escape_json_with_len
1627 * Produce a JSON string literal, properly escaping the possibly not
1628 * NUL-terminated characters in 'str'. 'len' defines the number of bytes
1629 * from 'str' to process.
1639 * Since we know the minimum length we'll need to append, let's just
1640 * enlarge the buffer now rather than incrementally making more space when
1641 * we run out. Add two extra bytes for the enclosing quotes.
1646 * Figure out how many bytes to process using SIMD. Round 'len' down to
1647 * the previous multiple of sizeof(Vector8), assuming that's a power-of-2.
1653 for (
int i = 0, copypos = 0;;)
1656 * To speed this up, try searching sizeof(Vector8) bytes at once for
1657 * special characters that we need to escape. When we find one, we
1658 * fall out of the Vector8 loop and copy the portion we've vector
1659 * searched and then we process sizeof(Vector8) bytes one byte at a
1660 * time. Once done, come back and try doing vector searching again.
1661 * We'll also process any remaining bytes at the tail end of the
1662 * string byte-by-byte. This optimization assumes that most chunks of
1663 * sizeof(Vector8) bytes won't contain any special characters.
1672 * Break on anything less than ' ' or if we find a '"' or '\\'.
1673 * Those need special handling. That's done in the per-byte loop.
1680#ifdef ESCAPE_JSON_FLUSH_AFTER
1683 * Flush what's been checked so far out to the destination buffer
1684 * every so often to avoid having to re-read cachelines when
1685 * escaping large strings.
1696 * Write to the destination up to the point that we've vector searched
1697 * so far. Do this only when switching into per-byte mode rather than
1698 * once every sizeof(Vector8) bytes.
1707 * Per-byte loop for Vector8s containing special chars and for
1708 * processing the tail of the string.
1712 /* check if we've finished */
1722 /* We're not done yet. Try the vector search again. */
1731 * Append 'txt' onto 'buf' and escape using escape_json_with_len.
1733 * This is more efficient than calling text_to_cstring and appending the
1734 * result as that could require an additional palloc and memcpy.
1739 /* must cast away the const, unfortunately */
1748 /* pfree any detoasted values */
1749 if (tunpacked != txt)
1753/* Semantic actions for key uniqueness check */
1763 /* push object entry to stack */
1764 entry =
palloc(
sizeof(*entry));
1767 state->stack = entry;
1781 entry =
state->stack;
1782 state->stack = entry->
parent;
/* pop object from stack */
1796 /* find key collision in the current object */
1800 state->unique =
false;
1802 /* pop all objects entries */
1803 while ((entry =
state->stack))
1811/* Validate JSON text and additionally check key uniqueness */
1822 if (check_unique_keys)
1826 state.id_counter = 0;
1827 state.unique =
true;
1843 return false;
/* invalid json */
1846 if (check_unique_keys && !
state.unique)
1850 (
errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1851 errmsg(
"duplicate JSON object key value")));
1853 return false;
/* not unique keys */
1856 if (check_unique_keys)
1859 return true;
/* ok */
1863 * SQL function json_typeof(json) -> text
1865 * Returns the type of the outermost JSON value as TEXT. Possible types are
1866 * "object", "array", "string", "number", "boolean", and "null".
1868 * Performs a single call to json_lex() to get the first token of the supplied
1869 * value. This initial token uniquely determines the value's type. As our
1870 * input must already have been validated by json_in() or json_recv(), the
1871 * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END,
1872 * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END.
1882 /* Lex exactly one token from the input and check its type. */
#define PG_GETARG_ARRAYTYPE_P(n)
#define DatumGetArrayTypeP(X)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
int ArrayGetNItems(int ndim, const int *dims)
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
void j2date(int jd, int *year, int *month, int *day)
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
void EncodeSpecialTimestamp(Timestamp dt, char *str)
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define unconstify(underlying_type, expr)
#define pg_attribute_always_inline
#define TIMESTAMP_NOT_FINITE(j)
#define POSTGRES_EPOCH_JDATE
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
void EncodeSpecialDate(DateADT dt, char *str)
#define DATE_NOT_FINITE(j)
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
static DateADT DatumGetDateADT(Datum X)
static TimeADT DatumGetTimeADT(Datum X)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
struct varlena * pg_detoast_datum_packed(struct varlena *datum)
char * OidOutputFunctionCall(Oid functionId, Datum val)
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
#define OidFunctionCall1(functionId, arg1)
#define PG_GETARG_TEXT_PP(n)
#define PG_RETURN_BYTEA_P(x)
#define DatumGetHeapTupleHeader(X)
#define DatumGetTextPP(X)
#define PG_GETARG_POINTER(n)
#define PG_RETURN_CSTRING(x)
#define PG_GETARG_DATUM(n)
#define PG_GETARG_CSTRING(n)
#define PG_RETURN_TEXT_P(x)
#define PG_GETARG_BOOL(n)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_POINTER(x)
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
uint32 hash_bytes_uint32(uint32 k)
uint32 hash_bytes(const unsigned char *k, int keylen)
Assert(PointerIsAligned(start, uint64))
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
Datum row_to_json(PG_FUNCTION_ARGS)
struct JsonUniqueStackEntry JsonUniqueStackEntry
static JsonParseErrorType json_unique_object_start(void *_state)
static uint32 json_unique_hash(const void *key, Size keysize)
Datum json_build_object_noargs(PG_FUNCTION_ARGS)
void escape_json_text(StringInfo buf, const text *txt)
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
static int json_unique_hash_match(const void *key1, const void *key2, Size keysize)
static void json_unique_check_init(JsonUniqueCheckState *cxt)
static text * catenate_stringinfo_string(StringInfo buffer, const char *addon)
struct HTAB * JsonUniqueCheckState
Datum json_agg_strict_transfn(PG_FUNCTION_ARGS)
static pg_attribute_always_inline void escape_json_char(StringInfo buf, char c)
struct JsonUniqueBuilderState JsonUniqueBuilderState
Datum json_in(PG_FUNCTION_ARGS)
static StringInfo json_unique_builder_get_throwawaybuf(JsonUniqueBuilderState *cxt)
static bool json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
struct JsonUniqueParsingState JsonUniqueParsingState
Datum json_out(PG_FUNCTION_ARGS)
Datum json_agg_transfn(PG_FUNCTION_ARGS)
Datum to_json(PG_FUNCTION_ARGS)
Datum json_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Datum json_object_agg_finalfn(PG_FUNCTION_ARGS)
Datum row_to_json_pretty(PG_FUNCTION_ARGS)
struct JsonUniqueHashEntry JsonUniqueHashEntry
Datum json_send(PG_FUNCTION_ARGS)
static Datum json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
void escape_json_with_len(StringInfo buf, const char *str, int len)
static void datum_to_json_internal(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Datum array_to_json_pretty(PG_FUNCTION_ARGS)
Datum json_object_agg_unique_transfn(PG_FUNCTION_ARGS)
Datum json_object_two_arg(PG_FUNCTION_ARGS)
Datum json_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
Datum json_build_array_noargs(PG_FUNCTION_ARGS)
Datum json_object_agg_transfn(PG_FUNCTION_ARGS)
Datum array_to_json(PG_FUNCTION_ARGS)
Datum json_object_agg_strict_transfn(PG_FUNCTION_ARGS)
Datum json_build_array(PG_FUNCTION_ARGS)
static void json_unique_builder_init(JsonUniqueBuilderState *cxt)
Datum json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
#define ESCAPE_JSON_FLUSH_AFTER
static void add_json(Datum val, bool is_null, StringInfo result, Oid val_type, bool key_scalar)
Datum json_agg_finalfn(PG_FUNCTION_ARGS)
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)
Datum json_recv(PG_FUNCTION_ARGS)
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
bool json_validate(text *json, bool check_unique_keys, bool throw_error)
Datum json_typeof(PG_FUNCTION_ARGS)
void escape_json(StringInfo buf, const char *str)
struct JsonAggState JsonAggState
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
static Datum json_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Datum json_object(PG_FUNCTION_ARGS)
Datum json_build_object(PG_FUNCTION_ARGS)
bool to_json_is_immutable(Oid typoid)
static JsonParseErrorType json_unique_object_field_start(void *_state, char *field, bool isnull)
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
static JsonParseErrorType json_unique_object_end(void *_state)
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
const JsonSemAction nullSemAction
JsonParseErrorType json_lex(JsonLexContext *lex)
void freeJsonLexContext(JsonLexContext *lex)
@ JSON_TOKEN_OBJECT_START
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext)
#define pg_parse_json_or_ereport(lex, sem)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
char func_volatile(Oid funcid)
int GetDatabaseEncoding(void)
char * MemoryContextStrdup(MemoryContext context, const char *string)
char * pstrdup(const char *in)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
static const struct exclude_list_item skip[]
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
static unsigned hash(unsigned *uv, int n)
static bool vector8_has_le(const Vector8 v, const uint8 c)
static void vector8_load(Vector8 *v, const uint8 *s)
static bool vector8_has(const Vector8 v, const uint8 c)
void check_stack_depth(void)
struct StringInfoData * StringInfo
StringInfo makeStringInfo(void)
void appendStringInfo(StringInfo str, const char *fmt,...)
void enlargeStringInfo(StringInfo str, int needed)
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
#define appendStringInfoCharMacro(str, ch)
JsonUniqueBuilderState unique_check
JsonTypeCategory key_category
JsonTypeCategory val_category
json_struct_action object_start
json_ofield_action object_field_start
json_struct_action object_end
JsonUniqueCheckState check
StringInfoData skipped_keys
JsonUniqueCheckState check
JsonUniqueStackEntry * stack
struct JsonUniqueStackEntry * parent
#define ReleaseTupleDesc(tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
static Timestamp DatumGetTimestamp(Datum X)
static TimestampTz DatumGetTimestampTz(Datum X)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static char * VARDATA(const void *PTR)
static char * VARDATA_ANY(const void *PTR)
static void SET_VARSIZE(void *PTR, Size len)
text * cstring_to_text_with_len(const char *s, int len)
text * cstring_to_text(const char *s)