28#include "utils/fmgroids.h"
92 const Datum *vals,
const bool *nulls,
int *valcount,
101 Oid val_type,
bool key_scalar);
190 Assert(!(key_scalar && is_null));
204 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
205 errmsg(
"key value must be scalar, not array, composite, or json")));
235 ((*outputstr >=
'0' && *outputstr <=
'9') ||
236 (*outputstr ==
'-' &&
237 (outputstr[1] >=
'0' && outputstr[1] <=
'9'))))
292 if (outfuncoid == F_TEXTOUT || outfuncoid == F_VARCHAROUT ||
293 outfuncoid == F_BPCHAROUT)
375 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
376 errmsg(
"timestamp out of range")));
385 const char *tzn = NULL;
405 tzp ? NULL : &tzn, NULL) == 0)
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);
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)
464 valcount, tcategory, outfuncoid,
false);
505 &tcategory, &outfuncoid);
512 outfuncoid, use_line_feeds);
531 bool needsep =
false;
539 sep = use_line_feeds ?
",\n " :
",";
540 seplen = use_line_feeds ? strlen(
",\n ") : strlen(
",");
556 for (
i = 0;
i < tupdesc->
natts;
i++)
565 if (att->attisdropped)
604 Oid val_type,
bool key_scalar)
611 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
612 errmsg(
"could not determine input data type")));
621 &tcategory, &outfuncoid);
749 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
750 errmsg(
"could not determine input data type")));
753 &tcategory, &outfuncoid);
791 elog(
ERROR,
"json_agg_transfn called in non-aggregate context");
800 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
801 errmsg(
"could not determine input data type")));
816 &
state->val_output_func);
826 if (
state->str->len > 1)
848 state->val_output_func,
false);
938 memset(&
ctl, 0,
sizeof(
ctl));
1005 bool absent_on_null,
bool unique_keys)
1018 elog(
ERROR,
"json_object_agg_transfn called in non-aggregate context");
1037 memset(&
state->unique_check, 0,
sizeof(
state->unique_check));
1044 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1045 errmsg(
"could not determine data type for argument %d", 1)));
1048 &
state->key_output_func);
1054 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1055 errmsg(
"could not determine data type for argument %d", 2)));
1058 &
state->val_output_func);
1077 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1078 errmsg(
"null value not allowed for object key")));
1109 key_offset = out->
len;
1112 state->key_output_func,
true);
1123 &out->
data[key_offset]);
1127 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1128 errmsg(
"duplicate JSON object key value: %s",
key));
1142 state->val_category,
1143 state->val_output_func,
false);
1214 int buflen = buffer->
len;
1215 int addlen = strlen(addon);
1220 memcpy(
VARDATA(result) + buflen, addon, addlen);
1227 bool absent_on_null,
bool unique_keys)
1230 const char *sep =
"";
1236 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1237 errmsg(
"argument list must have even number of elements"),
1239 errhint(
"The arguments of %s must consist of alternating keys and values.",
1240 "json_build_object()")));
1249 for (
i = 0;
i < nargs;
i += 2)
1256 skip = absent_on_null && nulls[
i + 1];
1276 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1277 errmsg(
"null value not allowed for object key")));
1280 key_offset = out->
len;
1298 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1299 errmsg(
"duplicate JSON object key value: %s",
key));
1347 bool absent_on_null)
1350 const char *sep =
"";
1357 for (
i = 0;
i < nargs;
i++)
1359 if (absent_on_null && nulls[
i])
1429 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1430 errmsg(
"array must have even number of elements")));
1436 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1437 errmsg(
"array must have two columns")));
1442 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1443 errmsg(
"wrong number of array subscripts")));
1448 count = in_count / 2;
1454 for (
i = 0;
i < count; ++
i)
1456 if (in_nulls[
i * 2])
1458 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1459 errmsg(
"null value not allowed for object key")));
1465 if (in_nulls[
i * 2 + 1])
1508 if (nkdims > 1 || nkdims != nvdims)
1510 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1511 errmsg(
"wrong number of array subscripts")));
1519 if (key_count != val_count)
1521 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1522 errmsg(
"mismatched array dimensions")));
1528 for (
i = 0;
i < key_count; ++
i)
1532 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1533 errmsg(
"null value not allowed for object key")));
1590 if ((
unsigned char)
c <
' ')
1608 for (; *
str !=
'\0';
str++)
1624#define ESCAPE_JSON_FLUSH_AFTER 512
1654 for (
int i = 0, copypos = 0;;)
1681#ifdef ESCAPE_JSON_FLUSH_AFTER
1750 if (tunpacked != txt)
1765 entry =
palloc(
sizeof(*entry));
1768 state->stack = entry;
1782 entry =
state->stack;
1801 state->unique =
false;
1804 while ((entry =
state->stack))
1823 if (check_unique_keys)
1827 state.id_counter = 0;
1828 state.unique =
true;
1847 if (check_unique_keys && !
state.unique)
1851 (
errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1852 errmsg(
"duplicate JSON object key value")));
1857 if (check_unique_keys)
#define PG_GETARG_ARRAYTYPE_P(n)
#define DatumGetArrayTypeP(X)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, 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)
static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, const Datum *vals, const bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid, bool use_line_feeds)
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)
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)