From 3c152a27b06313fe27bd47079658f928e291986b Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Thu, 20 Jul 2023 16:19:56 +0900 Subject: Unify JSON categorize type API and export for external use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Álvaro Herrera Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com --- src/backend/utils/adt/jsonfuncs.c | 111 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) (limited to 'src/backend/utils/adt/jsonfuncs.c') diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 70cb922e6b7..a4bfa5e4040 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -26,6 +26,7 @@ #include "mb/pg_wchar.h" #include "miscadmin.h" #include "nodes/miscnodes.h" +#include "parser/parse_coerce.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -5685,3 +5686,113 @@ json_get_first_token(text *json, bool throw_error) return JSON_TOKEN_INVALID; /* invalid json */ } + +/* + * Determine how we want to print values of a given type in datum_to_json(b). + * + * 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. + */ +void +json_categorize_type(Oid typoid, bool is_jsonb, + JsonTypeCategory *tcategory, Oid *outfuncoid) +{ + bool typisvarlena; + + /* Look through any domain */ + typoid = getBaseType(typoid); + + *outfuncoid = InvalidOid; + + switch (typoid) + { + case BOOLOID: + *outfuncoid = F_BOOLOUT; + *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: + *outfuncoid = F_DATE_OUT; + *tcategory = JSONTYPE_DATE; + break; + + case TIMESTAMPOID: + *outfuncoid = F_TIMESTAMP_OUT; + *tcategory = JSONTYPE_TIMESTAMP; + break; + + case TIMESTAMPTZOID: + *outfuncoid = F_TIMESTAMPTZ_OUT; + *tcategory = JSONTYPE_TIMESTAMPTZ; + break; + + case JSONOID: + getTypeOutputInfo(typoid, outfuncoid, &typisvarlena); + *tcategory = JSONTYPE_JSON; + break; + + case JSONBOID: + getTypeOutputInfo(typoid, outfuncoid, &typisvarlena); + *tcategory = is_jsonb ? JSONTYPE_JSONB : JSONTYPE_JSON; + break; + + default: + /* Check for arrays and composites */ + if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID + || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID) + { + *outfuncoid = F_ARRAY_OUT; + *tcategory = JSONTYPE_ARRAY; + } + else if (type_is_rowtype(typoid)) /* includes RECORDOID */ + { + *outfuncoid = F_RECORD_OUT; + *tcategory = JSONTYPE_COMPOSITE; + } + else + { + /* + * It's probably the general case. But let's look for a cast + * to json (note: not to jsonb even if is_jsonb is true), if + * it's not built-in. + */ + *tcategory = JSONTYPE_OTHER; + if (typoid >= FirstNormalObjectId) + { + Oid castfunc; + CoercionPathType ctype; + + ctype = find_coercion_pathway(JSONOID, typoid, + COERCION_EXPLICIT, + &castfunc); + if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc)) + { + *outfuncoid = castfunc; + *tcategory = JSONTYPE_CAST; + } + else + { + /* non builtin type with no cast */ + getTypeOutputInfo(typoid, outfuncoid, &typisvarlena); + } + } + else + { + /* any other builtin type */ + getTypeOutputInfo(typoid, outfuncoid, &typisvarlena); + } + } + break; + } +} -- cgit v1.2.3