mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Unify JSON categorize type API and export for external use
This essentially removes the JsonbTypeCategory enum and jsonb_categorize_type() and integrates any jsonb-specific logic that was in jsonb_categorize_type() into json_categorize_type(), now moved to jsonfuncs.c. The remaining JsonTypeCategory enum and json_categorize_type() cover the needs of the callers in both json.c and jsonb.c. json_categorize_type() has grown a new parameter named is_jsonb for callers to engage the jsonb-specific behavior of json_categorize_type(). One notable change in the now exported API of json_categorize_type() is that it now always returns *outfuncoid even though a caller may have no need currently to see one. This is in preparation of later commits to implement additional SQL/JSON functions. Co-authored-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
This commit is contained in:
@ -19,7 +19,6 @@
|
||||
#include "funcapi.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "miscadmin.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/date.h"
|
||||
@ -29,21 +28,6 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/typcache.h"
|
||||
|
||||
typedef enum /* type categories for datum_to_json */
|
||||
{
|
||||
JSONTYPE_NULL, /* null, so we didn't bother to identify */
|
||||
JSONTYPE_BOOL, /* boolean (built-in types only) */
|
||||
JSONTYPE_NUMERIC, /* numeric (ditto) */
|
||||
JSONTYPE_DATE, /* we use special formatting for datetimes */
|
||||
JSONTYPE_TIMESTAMP,
|
||||
JSONTYPE_TIMESTAMPTZ,
|
||||
JSONTYPE_JSON, /* JSON itself (and JSONB) */
|
||||
JSONTYPE_ARRAY, /* array */
|
||||
JSONTYPE_COMPOSITE, /* composite */
|
||||
JSONTYPE_CAST, /* something with an explicit cast to JSON */
|
||||
JSONTYPE_OTHER /* all else */
|
||||
} JsonTypeCategory;
|
||||
|
||||
|
||||
/*
|
||||
* Support for fast key uniqueness checking.
|
||||
@ -107,9 +91,6 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
|
||||
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);
|
||||
@ -182,106 +163,6 @@ json_recv(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_TEXT_P(cstring_to_text_with_len(str, nbytes));
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine how we want to print values of a given type in datum_to_json.
|
||||
*
|
||||
* Given the datatype OID, return its JsonTypeCategory, as well as the type's
|
||||
* output function OID. If the returned category is JSONTYPE_CAST, we
|
||||
* return the OID of the type->JSON cast function instead.
|
||||
*/
|
||||
static void
|
||||
json_categorize_type(Oid typoid,
|
||||
JsonTypeCategory *tcategory,
|
||||
Oid *outfuncoid)
|
||||
{
|
||||
bool typisvarlena;
|
||||
|
||||
/* Look through any domain */
|
||||
typoid = getBaseType(typoid);
|
||||
|
||||
*outfuncoid = InvalidOid;
|
||||
|
||||
/*
|
||||
* We need to get the output function for everything except date and
|
||||
* timestamp types, array and composite types, booleans, and non-builtin
|
||||
* types where there's a cast to json.
|
||||
*/
|
||||
|
||||
switch (typoid)
|
||||
{
|
||||
case BOOLOID:
|
||||
*tcategory = JSONTYPE_BOOL;
|
||||
break;
|
||||
|
||||
case INT2OID:
|
||||
case INT4OID:
|
||||
case INT8OID:
|
||||
case FLOAT4OID:
|
||||
case FLOAT8OID:
|
||||
case NUMERICOID:
|
||||
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
|
||||
*tcategory = JSONTYPE_NUMERIC;
|
||||
break;
|
||||
|
||||
case DATEOID:
|
||||
*tcategory = JSONTYPE_DATE;
|
||||
break;
|
||||
|
||||
case TIMESTAMPOID:
|
||||
*tcategory = JSONTYPE_TIMESTAMP;
|
||||
break;
|
||||
|
||||
case TIMESTAMPTZOID:
|
||||
*tcategory = JSONTYPE_TIMESTAMPTZ;
|
||||
break;
|
||||
|
||||
case JSONOID:
|
||||
case JSONBOID:
|
||||
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
|
||||
*tcategory = JSONTYPE_JSON;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for arrays and composites */
|
||||
if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
|
||||
|| typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
|
||||
*tcategory = JSONTYPE_ARRAY;
|
||||
else if (type_is_rowtype(typoid)) /* includes RECORDOID */
|
||||
*tcategory = JSONTYPE_COMPOSITE;
|
||||
else
|
||||
{
|
||||
/* It's probably the general case ... */
|
||||
*tcategory = JSONTYPE_OTHER;
|
||||
/* but let's look for a cast to json, if it's not built-in */
|
||||
if (typoid >= FirstNormalObjectId)
|
||||
{
|
||||
Oid castfunc;
|
||||
CoercionPathType ctype;
|
||||
|
||||
ctype = find_coercion_pathway(JSONOID, typoid,
|
||||
COERCION_EXPLICIT,
|
||||
&castfunc);
|
||||
if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
|
||||
{
|
||||
*tcategory = JSONTYPE_CAST;
|
||||
*outfuncoid = castfunc;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* non builtin type with no cast */
|
||||
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* any other builtin type */
|
||||
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn a Datum into JSON text, appending the string to "result".
|
||||
*
|
||||
@ -591,7 +472,7 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
|
||||
get_typlenbyvalalign(element_type,
|
||||
&typlen, &typbyval, &typalign);
|
||||
|
||||
json_categorize_type(element_type,
|
||||
json_categorize_type(element_type, false,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
deconstruct_array(v, element_type, typlen, typbyval,
|
||||
@ -665,7 +546,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
||||
outfuncoid = InvalidOid;
|
||||
}
|
||||
else
|
||||
json_categorize_type(att->atttypid, &tcategory, &outfuncoid);
|
||||
json_categorize_type(att->atttypid, false, &tcategory,
|
||||
&outfuncoid);
|
||||
|
||||
datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
|
||||
}
|
||||
@ -699,7 +581,7 @@ add_json(Datum val, bool is_null, StringInfo result,
|
||||
outfuncoid = InvalidOid;
|
||||
}
|
||||
else
|
||||
json_categorize_type(val_type,
|
||||
json_categorize_type(val_type, false,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
|
||||
@ -784,12 +666,13 @@ to_json_is_immutable(Oid typoid)
|
||||
JsonTypeCategory tcategory;
|
||||
Oid outfuncoid;
|
||||
|
||||
json_categorize_type(typoid, &tcategory, &outfuncoid);
|
||||
json_categorize_type(typoid, false, &tcategory, &outfuncoid);
|
||||
|
||||
switch (tcategory)
|
||||
{
|
||||
case JSONTYPE_BOOL:
|
||||
case JSONTYPE_JSON:
|
||||
case JSONTYPE_JSONB:
|
||||
case JSONTYPE_NULL:
|
||||
return true;
|
||||
|
||||
@ -830,7 +713,7 @@ to_json(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not determine input data type")));
|
||||
|
||||
json_categorize_type(val_type,
|
||||
json_categorize_type(val_type, false,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
result = makeStringInfo();
|
||||
@ -880,7 +763,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
appendStringInfoChar(state->str, '[');
|
||||
json_categorize_type(arg_type, &state->val_category,
|
||||
json_categorize_type(arg_type, false, &state->val_category,
|
||||
&state->val_output_func);
|
||||
}
|
||||
else
|
||||
@ -1112,7 +995,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not determine data type for argument %d", 1)));
|
||||
|
||||
json_categorize_type(arg_type, &state->key_category,
|
||||
json_categorize_type(arg_type, false, &state->key_category,
|
||||
&state->key_output_func);
|
||||
|
||||
arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
|
||||
@ -1122,7 +1005,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not determine data type for argument %d", 2)));
|
||||
|
||||
json_categorize_type(arg_type, &state->val_category,
|
||||
json_categorize_type(arg_type, false, &state->val_category,
|
||||
&state->val_output_func);
|
||||
|
||||
appendStringInfoString(state->str, "{ ");
|
||||
|
Reference in New Issue
Block a user