mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Revert SQL/JSON features
The reverts the following and makes some associated cleanups:
commit f79b803dc: Common SQL/JSON clauses
commit f4fb45d15: SQL/JSON constructors
commit 5f0adec25: Make STRING an unreserved_keyword.
commit 33a377608: IS JSON predicate
commit 1a36bc9db: SQL/JSON query functions
commit 606948b05: SQL JSON functions
commit 49082c2cc: RETURNING clause for JSON() and JSON_SCALAR()
commit 4e34747c8: JSON_TABLE
commit fadb48b00: PLAN clauses for JSON_TABLE
commit 2ef6f11b0: Reduce running time of jsonb_sqljson test
commit 14d3f24fa: Further improve jsonb_sqljson parallel test
commit a6baa4bad: Documentation for SQL/JSON features
commit b46bcf7a4: Improve readability of SQL/JSON documentation.
commit 112fdb352: Fix finalization for json_objectagg and friends
commit fcdb35c32: Fix transformJsonBehavior
commit 4cd8717af: Improve a couple of sql/json error messages
commit f7a605f63: Small cleanups in SQL/JSON code
commit 9c3d25e17: Fix JSON_OBJECTAGG uniquefying bug
commit a79153b7a: Claim SQL standard compliance for SQL/JSON features
commit a1e7616d6: Rework SQL/JSON documentation
commit 8d9f9634e: Fix errors in copyfuncs/equalfuncs support for JSON node types.
commit 3c633f32b: Only allow returning string types or bytea from json_serialize
commit 67b26703b: expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.
The release notes are also adjusted.
Backpatch to release 15.
Discussion: https://postgr.es/m/40d2c882-bcac-19a9-754d-4299e1d87ac7@postgresql.org
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "access/htup_details.h"
|
||||
#include "access/transam.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "funcapi.h"
|
||||
#include "libpq/pqformat.h"
|
||||
@@ -34,9 +33,25 @@ typedef struct JsonbInState
|
||||
{
|
||||
JsonbParseState *parseState;
|
||||
JsonbValue *res;
|
||||
bool unique_keys;
|
||||
} JsonbInState;
|
||||
|
||||
/* unlike with json categories, we need to treat json and jsonb differently */
|
||||
typedef enum /* type categories for datum_to_jsonb */
|
||||
{
|
||||
JSONBTYPE_NULL, /* null, so we didn't bother to identify */
|
||||
JSONBTYPE_BOOL, /* boolean (built-in types only) */
|
||||
JSONBTYPE_NUMERIC, /* numeric (ditto) */
|
||||
JSONBTYPE_DATE, /* we use special formatting for datetimes */
|
||||
JSONBTYPE_TIMESTAMP, /* we use special formatting for timestamp */
|
||||
JSONBTYPE_TIMESTAMPTZ, /* ... and timestamptz */
|
||||
JSONBTYPE_JSON, /* JSON */
|
||||
JSONBTYPE_JSONB, /* JSONB */
|
||||
JSONBTYPE_ARRAY, /* array */
|
||||
JSONBTYPE_COMPOSITE, /* composite */
|
||||
JSONBTYPE_JSONCAST, /* something with an explicit cast to JSON */
|
||||
JSONBTYPE_OTHER /* all else */
|
||||
} JsonbTypeCategory;
|
||||
|
||||
typedef struct JsonbAggState
|
||||
{
|
||||
JsonbInState *res;
|
||||
@@ -46,7 +61,7 @@ typedef struct JsonbAggState
|
||||
Oid val_output_func;
|
||||
} JsonbAggState;
|
||||
|
||||
static inline Datum jsonb_from_cstring(char *json, int len, bool unique_keys);
|
||||
static inline Datum jsonb_from_cstring(char *json, int len);
|
||||
static size_t checkStringLen(size_t len);
|
||||
static void jsonb_in_object_start(void *pstate);
|
||||
static void jsonb_in_object_end(void *pstate);
|
||||
@@ -55,11 +70,17 @@ static void jsonb_in_array_end(void *pstate);
|
||||
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
|
||||
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
|
||||
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
|
||||
static void jsonb_categorize_type(Oid typoid,
|
||||
JsonbTypeCategory *tcategory,
|
||||
Oid *outfuncoid);
|
||||
static void composite_to_jsonb(Datum composite, JsonbInState *result);
|
||||
static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims,
|
||||
Datum *vals, bool *nulls, int *valcount,
|
||||
JsonbTypeCategory tcategory, Oid outfuncoid);
|
||||
static void array_to_jsonb_internal(Datum array, JsonbInState *result);
|
||||
static void jsonb_categorize_type(Oid typoid,
|
||||
JsonbTypeCategory *tcategory,
|
||||
Oid *outfuncoid);
|
||||
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
JsonbTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar);
|
||||
@@ -77,7 +98,7 @@ jsonb_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *json = PG_GETARG_CSTRING(0);
|
||||
|
||||
return jsonb_from_cstring(json, strlen(json), false);
|
||||
return jsonb_from_cstring(json, strlen(json));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,7 +122,7 @@ jsonb_recv(PG_FUNCTION_ARGS)
|
||||
else
|
||||
elog(ERROR, "unsupported jsonb version number %d", version);
|
||||
|
||||
return jsonb_from_cstring(str, nbytes, false);
|
||||
return jsonb_from_cstring(str, nbytes);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -142,14 +163,6 @@ jsonb_send(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
Datum
|
||||
jsonb_from_text(text *js, bool unique_keys)
|
||||
{
|
||||
return jsonb_from_cstring(VARDATA_ANY(js),
|
||||
VARSIZE_ANY_EXHDR(js),
|
||||
unique_keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the type name of a jsonb container.
|
||||
*/
|
||||
@@ -240,7 +253,7 @@ jsonb_typeof(PG_FUNCTION_ARGS)
|
||||
* Uses the json parser (with hooks) to construct a jsonb.
|
||||
*/
|
||||
static inline Datum
|
||||
jsonb_from_cstring(char *json, int len, bool unique_keys)
|
||||
jsonb_from_cstring(char *json, int len)
|
||||
{
|
||||
JsonLexContext *lex;
|
||||
JsonbInState state;
|
||||
@@ -250,8 +263,6 @@ jsonb_from_cstring(char *json, int len, bool unique_keys)
|
||||
memset(&sem, 0, sizeof(sem));
|
||||
lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
|
||||
|
||||
state.unique_keys = unique_keys;
|
||||
|
||||
sem.semstate = (void *) &state;
|
||||
|
||||
sem.object_start = jsonb_in_object_start;
|
||||
@@ -286,7 +297,6 @@ jsonb_in_object_start(void *pstate)
|
||||
JsonbInState *_state = (JsonbInState *) pstate;
|
||||
|
||||
_state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
|
||||
_state->parseState->unique_keys = _state->unique_keys;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -609,7 +619,7 @@ add_indent(StringInfo out, bool indent, int level)
|
||||
* output function OID. If the returned category is JSONBTYPE_JSONCAST,
|
||||
* we return the OID of the relevant cast function instead.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
jsonb_categorize_type(Oid typoid,
|
||||
JsonbTypeCategory *tcategory,
|
||||
Oid *outfuncoid)
|
||||
@@ -1115,51 +1125,6 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
|
||||
}
|
||||
|
||||
Datum
|
||||
to_jsonb_worker(Datum val, JsonbTypeCategory tcategory, Oid outfuncoid)
|
||||
{
|
||||
JsonbInState result;
|
||||
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
|
||||
|
||||
return JsonbPGetDatum(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
bool
|
||||
to_jsonb_is_immutable(Oid typoid)
|
||||
{
|
||||
JsonbTypeCategory tcategory;
|
||||
Oid outfuncoid;
|
||||
|
||||
jsonb_categorize_type(typoid, &tcategory, &outfuncoid);
|
||||
|
||||
switch (tcategory)
|
||||
{
|
||||
case JSONBTYPE_BOOL:
|
||||
case JSONBTYPE_JSON:
|
||||
case JSONBTYPE_JSONB:
|
||||
return true;
|
||||
|
||||
case JSONBTYPE_DATE:
|
||||
case JSONBTYPE_TIMESTAMP:
|
||||
case JSONBTYPE_TIMESTAMPTZ:
|
||||
return false;
|
||||
|
||||
case JSONBTYPE_ARRAY:
|
||||
return false; /* TODO recurse into elements */
|
||||
|
||||
case JSONBTYPE_COMPOSITE:
|
||||
return false; /* TODO recurse into fields */
|
||||
|
||||
case JSONBTYPE_NUMERIC:
|
||||
case JSONBTYPE_JSONCAST:
|
||||
default:
|
||||
return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function to_jsonb(anyvalue)
|
||||
*/
|
||||
@@ -1168,6 +1133,7 @@ to_jsonb(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum val = PG_GETARG_DATUM(0);
|
||||
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||
JsonbInState result;
|
||||
JsonbTypeCategory tcategory;
|
||||
Oid outfuncoid;
|
||||
|
||||
@@ -1179,15 +1145,31 @@ to_jsonb(PG_FUNCTION_ARGS)
|
||||
jsonb_categorize_type(val_type,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
PG_RETURN_DATUM(to_jsonb_worker(val, tcategory, outfuncoid));
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
|
||||
|
||||
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function jsonb_build_object(variadic "any")
|
||||
*/
|
||||
Datum
|
||||
jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
|
||||
bool absent_on_null, bool unique_keys)
|
||||
jsonb_build_object(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int nargs;
|
||||
int i;
|
||||
JsonbInState result;
|
||||
Datum *args;
|
||||
bool *nulls;
|
||||
Oid *types;
|
||||
|
||||
/* build argument values to build the object */
|
||||
nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
|
||||
|
||||
if (nargs < 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
if (nargs % 2 != 0)
|
||||
ereport(ERROR,
|
||||
@@ -1200,26 +1182,15 @@ jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
|
||||
result.parseState->unique_keys = unique_keys;
|
||||
result.parseState->skip_nulls = absent_on_null;
|
||||
|
||||
for (i = 0; i < nargs; i += 2)
|
||||
{
|
||||
/* process key */
|
||||
bool skip;
|
||||
|
||||
if (nulls[i])
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("argument %d: key must not be null", i + 1)));
|
||||
|
||||
/* skip null values if absent_on_null */
|
||||
skip = absent_on_null && nulls[i + 1];
|
||||
|
||||
/* we need to save skipped keys for the key uniqueness check */
|
||||
if (skip && !unique_keys)
|
||||
continue;
|
||||
|
||||
add_jsonb(args[i], false, &result, types[i], true);
|
||||
|
||||
/* process value */
|
||||
@@ -1228,27 +1199,7 @@ jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
|
||||
|
||||
return JsonbPGetDatum(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function jsonb_build_object(variadic "any")
|
||||
*/
|
||||
Datum
|
||||
jsonb_build_object(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum *args;
|
||||
bool *nulls;
|
||||
Oid *types;
|
||||
|
||||
/* build argument values to build the object */
|
||||
int nargs = extract_variadic_args(fcinfo, 0, true,
|
||||
&args, &types, &nulls);
|
||||
|
||||
if (nargs < 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
|
||||
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1267,50 +1218,36 @@ jsonb_build_object_noargs(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
Datum
|
||||
jsonb_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
|
||||
bool absent_on_null)
|
||||
{
|
||||
int i;
|
||||
JsonbInState result;
|
||||
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if (absent_on_null && nulls[i])
|
||||
continue;
|
||||
|
||||
add_jsonb(args[i], nulls[i], &result, types[i], false);
|
||||
}
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
|
||||
|
||||
return JsonbPGetDatum(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function jsonb_build_array(variadic "any")
|
||||
*/
|
||||
Datum
|
||||
jsonb_build_array(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int nargs;
|
||||
int i;
|
||||
JsonbInState result;
|
||||
Datum *args;
|
||||
bool *nulls;
|
||||
Oid *types;
|
||||
|
||||
/* build argument values to build the object */
|
||||
int nargs = extract_variadic_args(fcinfo, 0, true,
|
||||
&args, &types, &nulls);
|
||||
/* build argument values to build the array */
|
||||
nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
|
||||
|
||||
if (nargs < 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
|
||||
}
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
add_jsonb(args[i], nulls[i], &result, types[i], false);
|
||||
|
||||
result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
|
||||
|
||||
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
/*
|
||||
* degenerate case of jsonb_build_array where it gets 0 arguments.
|
||||
@@ -1545,8 +1482,6 @@ clone_parse_state(JsonbParseState *state)
|
||||
{
|
||||
ocursor->contVal = icursor->contVal;
|
||||
ocursor->size = icursor->size;
|
||||
ocursor->unique_keys = icursor->unique_keys;
|
||||
ocursor->skip_nulls = icursor->skip_nulls;
|
||||
icursor = icursor->next;
|
||||
if (icursor == NULL)
|
||||
break;
|
||||
@@ -1558,8 +1493,12 @@ clone_parse_state(JsonbParseState *state)
|
||||
return result;
|
||||
}
|
||||
|
||||
static Datum
|
||||
jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
|
||||
/*
|
||||
* jsonb_agg aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_agg_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
MemoryContext oldcontext,
|
||||
aggcontext;
|
||||
@@ -1607,9 +1546,6 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
result = state->res;
|
||||
}
|
||||
|
||||
if (absent_on_null && PG_ARGISNULL(1))
|
||||
PG_RETURN_POINTER(state);
|
||||
|
||||
/* turn the argument into jsonb in the normal function context */
|
||||
|
||||
val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
|
||||
@@ -1679,24 +1615,6 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
PG_RETURN_POINTER(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_agg aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_agg_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_agg_transfn_worker(fcinfo, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_agg_strict aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_agg_strict_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_agg_transfn_worker(fcinfo, true);
|
||||
}
|
||||
|
||||
Datum
|
||||
jsonb_agg_finalfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -1729,9 +1647,11 @@ jsonb_agg_finalfn(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_POINTER(out);
|
||||
}
|
||||
|
||||
static Datum
|
||||
jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
bool absent_on_null, bool unique_keys)
|
||||
/*
|
||||
* jsonb_object_agg aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
MemoryContext oldcontext,
|
||||
aggcontext;
|
||||
@@ -1745,7 +1665,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
*jbval;
|
||||
JsonbValue v;
|
||||
JsonbIteratorToken type;
|
||||
bool skip;
|
||||
|
||||
if (!AggCheckCallContext(fcinfo, &aggcontext))
|
||||
{
|
||||
@@ -1765,9 +1684,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
state->res = result;
|
||||
result->res = pushJsonbValue(&result->parseState,
|
||||
WJB_BEGIN_OBJECT, NULL);
|
||||
result->parseState->unique_keys = unique_keys;
|
||||
result->parseState->skip_nulls = absent_on_null;
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
|
||||
@@ -1803,15 +1719,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("field name must not be null")));
|
||||
|
||||
/*
|
||||
* Skip null values if absent_on_null unless key uniqueness check is
|
||||
* needed (because we must save keys in this case).
|
||||
*/
|
||||
skip = absent_on_null && PG_ARGISNULL(2);
|
||||
|
||||
if (skip && !unique_keys)
|
||||
PG_RETURN_POINTER(state);
|
||||
|
||||
val = PG_GETARG_DATUM(1);
|
||||
|
||||
memset(&elem, 0, sizeof(JsonbInState));
|
||||
@@ -1867,16 +1774,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
}
|
||||
result->res = pushJsonbValue(&result->parseState,
|
||||
WJB_KEY, &v);
|
||||
|
||||
if (skip)
|
||||
{
|
||||
v.type = jbvNull;
|
||||
result->res = pushJsonbValue(&result->parseState,
|
||||
WJB_VALUE, &v);
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
PG_RETURN_POINTER(state);
|
||||
}
|
||||
|
||||
break;
|
||||
case WJB_END_ARRAY:
|
||||
break;
|
||||
@@ -1949,43 +1846,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
PG_RETURN_POINTER(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_object_agg aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_object_agg_transfn_worker(fcinfo, false, false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* jsonb_object_agg_strict aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_object_agg_strict_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_object_agg_transfn_worker(fcinfo, true, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_object_agg_unique aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_object_agg_unique_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_object_agg_transfn_worker(fcinfo, false, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_object_agg_unique_strict aggregate function
|
||||
*/
|
||||
Datum
|
||||
jsonb_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return jsonb_object_agg_transfn_worker(fcinfo, true, true);
|
||||
}
|
||||
|
||||
Datum
|
||||
jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -2217,65 +2077,3 @@ jsonb_float8(PG_FUNCTION_ARGS)
|
||||
|
||||
PG_RETURN_DATUM(retValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct an empty array jsonb.
|
||||
*/
|
||||
Jsonb *
|
||||
JsonbMakeEmptyArray(void)
|
||||
{
|
||||
JsonbValue jbv;
|
||||
|
||||
jbv.type = jbvArray;
|
||||
jbv.val.array.elems = NULL;
|
||||
jbv.val.array.nElems = 0;
|
||||
jbv.val.array.rawScalar = false;
|
||||
|
||||
return JsonbValueToJsonb(&jbv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct an empty object jsonb.
|
||||
*/
|
||||
Jsonb *
|
||||
JsonbMakeEmptyObject(void)
|
||||
{
|
||||
JsonbValue jbv;
|
||||
|
||||
jbv.type = jbvObject;
|
||||
jbv.val.object.pairs = NULL;
|
||||
jbv.val.object.nPairs = 0;
|
||||
|
||||
return JsonbValueToJsonb(&jbv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert jsonb to a C-string stripping quotes from scalar strings.
|
||||
*/
|
||||
char *
|
||||
JsonbUnquote(Jsonb *jb)
|
||||
{
|
||||
if (JB_ROOT_IS_SCALAR(jb))
|
||||
{
|
||||
JsonbValue v;
|
||||
|
||||
(void) JsonbExtractScalar(&jb->root, &v);
|
||||
|
||||
if (v.type == jbvString)
|
||||
return pnstrdup(v.val.string.val, v.val.string.len);
|
||||
else if (v.type == jbvBool)
|
||||
return pstrdup(v.val.boolean ? "true" : "false");
|
||||
else if (v.type == jbvNumeric)
|
||||
return DatumGetCString(DirectFunctionCall1(numeric_out,
|
||||
PointerGetDatum(v.val.numeric)));
|
||||
else if (v.type == jbvNull)
|
||||
return pstrdup("null");
|
||||
else
|
||||
{
|
||||
elog(ERROR, "unrecognized jsonb value type %d", v.type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user