v1-0001-hanlde-types-that-have-type-modifier-for-json-on-.patch
application/x-patch
Filename: v1-0001-hanlde-types-that-have-type-modifier-for-json-on-.patch
Type: application/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: hanlde types that have type modifier for json on error, on empty
| File | + | − |
|---|---|---|
| src/backend/parser/parse_expr.c | 65 | 18 |
From 5f2d070d3cc47f7461d1474a5fe18e905243b31b Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 1 Jul 2024 14:26:09 +0800
Subject: [PATCH v1 1/1] hanlde types that have type modifier for json on
error, on empty
---
src/backend/parser/parse_expr.c | 83 ++++++++++++++++++++++++++-------
1 file changed, 65 insertions(+), 18 deletions(-)
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 560b3606..15cdea1c 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -3582,7 +3582,7 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
Node *res;
int location;
Oid exprtype = exprType(expr);
- int32 baseTypmod = returning->typmod;
+ int32 baseTypmod = -1;
/* if output type is not specified or equals to function type, return */
if (!OidIsValid(returning->typid) || returning->typid == exprtype)
@@ -3615,8 +3615,10 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
* For domains, consider the base type's typmod to decide whether to setup
* an implicit or explicit cast.
*/
- if (get_typtype(returning->typid) == TYPTYPE_DOMAIN)
+ if (returning->typmod < 0)
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
+ else
+ baseTypmod = returning->typmod;
/* try to coerce expression to the output type */
res = coerce_to_target_type(pstate, expr, exprtype,
@@ -3649,7 +3651,7 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr);
Node *placeholder;
Node *coercion;
- int32 baseTypmod = returning->typmod;
+ int32 baseTypmod = -1;
jsctor->args = args;
jsctor->func = fexpr;
@@ -3693,8 +3695,10 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
* there are no implicit casts from json(b) to such types. For domains,
* the base type's typmod will be considered, so do so here too.
*/
- if (get_typtype(returning->typid) == TYPTYPE_DOMAIN)
+ if (returning->typmod < 0)
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
+ else
+ baseTypmod = returning->typmod;
if (baseTypmod > 0)
placeholder = coerce_to_specific_type(pstate, placeholder, TEXTOID,
"JSON_CONSTRUCTOR()");
@@ -4718,22 +4722,65 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
coerce_at_runtime = true;
else
{
- int32 baseTypmod = returning->typmod;
-
- if (get_typtype(returning->typid) == TYPTYPE_DOMAIN)
+ int32 baseTypmod = -1;
+ char typcategory;
+ bool typispreferred;
+ get_type_category_preferred(returning->typid, &typcategory, &typispreferred);
+ if (returning->typmod < 0)
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
+ else
+ baseTypmod = returning->typmod;
- if (baseTypmod > 0)
- expr = coerce_to_specific_type(pstate, expr, TEXTOID,
- "JSON_FUNCTION()");
- coerced_expr =
- coerce_to_target_type(pstate, expr, exprType(expr),
- returning->typid, baseTypmod,
- baseTypmod > 0 ? COERCION_IMPLICIT :
- COERCION_EXPLICIT,
- baseTypmod > 0 ? COERCE_IMPLICIT_CAST :
- COERCE_EXPLICIT_CAST,
- exprLocation((Node *) behavior));
+ if (typcategory == TYPCATEGORY_STRING)
+ {
+ if (baseTypmod > 0)
+ expr = coerce_to_specific_type(pstate, expr, TEXTOID,
+ "JSON_FUNCTION()");
+ coerced_expr =
+ coerce_to_target_type(pstate, expr, exprType(expr),
+ returning->typid, baseTypmod,
+ baseTypmod > 0 ? COERCION_IMPLICIT :
+ COERCION_EXPLICIT,
+ baseTypmod > 0 ? COERCE_IMPLICIT_CAST :
+ COERCE_EXPLICIT_CAST,
+ exprLocation((Node *) behavior));
+ }
+ else if (typcategory == TYPCATEGORY_BITSTRING)
+ {
+ CoercionContext ccontext;
+ CoercionForm cformat;
+
+ /*
+ * pg_cast don't have bit & text entry, so in function can_coerce_type
+ * cannot implilcit cast to text then cast to varbit.
+ * but we can unknown cast to bit via implilcit cast.
+ * select '21'::text::bit(2); --fail
+ * select 21::int4::bit(2); --ok
+ * so DEFAULT 21 ON ERROR, DEFAULT 11 ON ERROR should be fine;
+ */
+ if(baseTypmod > 0 && ((exprType(expr) != INT4OID && exprType(expr) != INT8OID)))
+ {
+ ccontext = COERCION_IMPLICIT;
+ cformat = COERCE_IMPLICIT_CAST;
+ }
+ else
+ {
+ ccontext = COERCION_EXPLICIT;
+ cformat = COERCE_EXPLICIT_CAST;
+ }
+ coerced_expr =
+ coerce_to_target_type(pstate, expr, exprType(expr),
+ returning->typid, returning->typmod,
+ ccontext,
+ cformat,
+ exprLocation((Node *) behavior));
+ }
+ else
+ coerced_expr =
+ coerce_to_target_type(pstate, expr, exprType(expr),
+ returning->typid, returning->typmod,
+ COERCION_EXPLICIT, COERCE_EXPLICIT_CAST,
+ exprLocation((Node *) behavior));
}
if (coerced_expr == NULL)
--
2.34.1