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;
|
||||
int location;
|
||||
Oid exprtype = exprType(expr);
|
||||
int32 baseTypmod = returning->typmod;
|
||||
|
||||
/* if output type is not specified or equals to function type, return */
|
||||
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
|
||||
* an implicit or explicit cast.
|
||||
* For other cases, try to coerce expression to the output type using
|
||||
* 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,
|
||||
returning->typid, baseTypmod,
|
||||
baseTypmod > 0 ? COERCION_IMPLICIT :
|
||||
COERCION_EXPLICIT,
|
||||
baseTypmod > 0 ? COERCE_IMPLICIT_CAST :
|
||||
COERCE_EXPLICIT_CAST,
|
||||
returning->typid, returning->typmod,
|
||||
COERCION_ASSIGNMENT,
|
||||
COERCE_IMPLICIT_CAST,
|
||||
location);
|
||||
|
||||
if (!res && report_error)
|
||||
|
@ -3649,7 +3647,6 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
|
|||
JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr);
|
||||
Node *placeholder;
|
||||
Node *coercion;
|
||||
int32 baseTypmod = returning->typmod;
|
||||
|
||||
jsctor->args = args;
|
||||
jsctor->func = fexpr;
|
||||
|
@ -3687,17 +3684,6 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
|
|||
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);
|
||||
|
||||
if (coercion != placeholder)
|
||||
|
|
Loading…
Reference in New Issue