aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
authorAmit Langote <amitlan@postgresql.org>2023-07-20 16:19:56 +0900
committerAmit Langote <amitlan@postgresql.org>2023-07-20 16:19:56 +0900
commit3c152a27b06313fe27bd47079658f928e291986b (patch)
treedcaec379d19f32b4aa8279c685ce4847f80cdae0 /src/backend/utils/adt/json.c
parent2a990abd79acea4717cc8f982a28f35b6b347ddb (diff)
downloadpostgresql-3c152a27b06313fe27bd47079658f928e291986b.tar.gz
postgresql-3c152a27b06313fe27bd47079658f928e291986b.zip
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
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c137
1 files changed, 10 insertions, 127 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 49080e5fbff..f6bef9c1484 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -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);
@@ -183,106 +164,6 @@ json_recv(PG_FUNCTION_ARGS)
}
/*
- * 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".
*
* tcategory and outfuncoid are from a previous call to json_categorize_type,
@@ -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, "{ ");