mirror of https://github.com/postgres/postgres
SQL/JSON: Rethink c2d93c3802
This essentially revertsc2d93c3802
except tests. The problem withc2d93c3802
was that it only changed the casting behavior for types with typmod, and had coding issues noted in the post-commit review. This commit changes coerceJsonFuncExpr() to use assignment-level casts instead of explicit casts to coerce the result of JSON constructor functions to the specified or the default RETURNING type. Using assignment-level casts fixes the problem that using explicit casts was leading to the wrong typmod / length coercion behavior -- truncating results longer than the specified length instead of erroring out -- whichc2d93c3802
aimed to solve. That restricts the set of allowed target types to string types, the same set that's currently allowed. Discussion: https://postgr.es/m/202406291824.reofujy7xdj3@alvherre.pgsql
This commit is contained in:
parent
ec678692f6
commit
86d33987e8
|
@ -3582,7 +3582,6 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
|
||||||
Node *res;
|
Node *res;
|
||||||
int location;
|
int location;
|
||||||
Oid exprtype = exprType(expr);
|
Oid exprtype = exprType(expr);
|
||||||
int32 baseTypmod = returning->typmod;
|
|
||||||
|
|
||||||
/* if output type is not specified or equals to function type, return */
|
/* if output type is not specified or equals to function type, return */
|
||||||
if (!OidIsValid(returning->typid) || returning->typid == exprtype)
|
if (!OidIsValid(returning->typid) || returning->typid == exprtype)
|
||||||
|
@ -3612,19 +3611,18 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For domains, consider the base type's typmod to decide whether to setup
|
* For other cases, try to coerce expression to the output type using
|
||||||
* an implicit or explicit cast.
|
* assignment-level casts, erroring out if none available. This basically
|
||||||
|
* allows coercing the jsonb value to any string type (typcategory = 'S').
|
||||||
|
*
|
||||||
|
* Requesting assignment-level here means that typmod / length coercion
|
||||||
|
* assumes implicit coercion which is the behavior we want; see
|
||||||
|
* build_coercion_expression().
|
||||||
*/
|
*/
|
||||||
if (get_typtype(returning->typid) == TYPTYPE_DOMAIN)
|
|
||||||
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
|
|
||||||
|
|
||||||
/* try to coerce expression to the output type */
|
|
||||||
res = coerce_to_target_type(pstate, expr, exprtype,
|
res = coerce_to_target_type(pstate, expr, exprtype,
|
||||||
returning->typid, baseTypmod,
|
returning->typid, returning->typmod,
|
||||||
baseTypmod > 0 ? COERCION_IMPLICIT :
|
COERCION_ASSIGNMENT,
|
||||||
COERCION_EXPLICIT,
|
COERCE_IMPLICIT_CAST,
|
||||||
baseTypmod > 0 ? COERCE_IMPLICIT_CAST :
|
|
||||||
COERCE_EXPLICIT_CAST,
|
|
||||||
location);
|
location);
|
||||||
|
|
||||||
if (!res && report_error)
|
if (!res && report_error)
|
||||||
|
@ -3649,7 +3647,6 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
|
||||||
JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr);
|
JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr);
|
||||||
Node *placeholder;
|
Node *placeholder;
|
||||||
Node *coercion;
|
Node *coercion;
|
||||||
int32 baseTypmod = returning->typmod;
|
|
||||||
|
|
||||||
jsctor->args = args;
|
jsctor->args = args;
|
||||||
jsctor->func = fexpr;
|
jsctor->func = fexpr;
|
||||||
|
@ -3687,17 +3684,6 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
|
||||||
placeholder = (Node *) cte;
|
placeholder = (Node *) cte;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the source expression to text, because coerceJsonFuncExpr()
|
|
||||||
* will create an implicit cast to the RETURNING types with typmod and
|
|
||||||
* 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)
|
|
||||||
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
|
|
||||||
if (baseTypmod > 0)
|
|
||||||
placeholder = coerce_to_specific_type(pstate, placeholder, TEXTOID,
|
|
||||||
"JSON_CONSTRUCTOR()");
|
|
||||||
coercion = coerceJsonFuncExpr(pstate, placeholder, returning, true);
|
coercion = coerceJsonFuncExpr(pstate, placeholder, returning, true);
|
||||||
|
|
||||||
if (coercion != placeholder)
|
if (coercion != placeholder)
|
||||||
|
|
Loading…
Reference in New Issue