mirror of https://github.com/postgres/postgres
Don't elide casting to typmod -1.
Casting a value that's already of a type with a specific typmod
to an unspecified typmod doesn't do anything so far as run-time
behavior is concerned. However, it really ought to change the
exposed type of the expression to match. Up to now,
coerce_type_typmod hasn't bothered with that, which creates gotchas
in contexts such as recursive unions. If for example one side of
the union is numeric(18,3), but it needs to be plain numeric to
match the other side, there's no direct way to express that.
This is easy enough to fix, by inserting a RelabelType to update the
exposed type of the expression. However, it's a bit nervous-making
to change this behavior, because it's stood for a really long time.
But no complaints have emerged about 14beta3, so go ahead and
back-patch.
Back-patch of 5c056b0c2
into previous supported branches.
Discussion: https://postgr.es/m/CABNQVagu3bZGqiTjb31a8D5Od3fUMs7Oh3gmZMQZVHZ=uWWWfQ@mail.gmail.com
Discussion: https://postgr.es/m/1488389.1631984807@sss.pgh.pa.us
This commit is contained in:
parent
e5e2e4ee60
commit
183b3aceda
|
@ -739,26 +739,38 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
|
|||
CoercionPathType pathtype;
|
||||
Oid funcId;
|
||||
|
||||
/*
|
||||
* A negative typmod is assumed to mean that no coercion is wanted. Also,
|
||||
* skip coercion if already done.
|
||||
*/
|
||||
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
|
||||
/* Skip coercion if already done */
|
||||
if (targetTypMod == exprTypmod(node))
|
||||
return node;
|
||||
|
||||
/* Suppress display of nested coercion steps */
|
||||
if (hideInputCoercion)
|
||||
hide_coercion_node(node);
|
||||
|
||||
pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
|
||||
|
||||
if (pathtype != COERCION_PATH_NONE)
|
||||
{
|
||||
/* Suppress display of nested coercion steps */
|
||||
if (hideInputCoercion)
|
||||
hide_coercion_node(node);
|
||||
|
||||
node = build_coercion_expression(node, pathtype, funcId,
|
||||
targetTypeId, targetTypMod,
|
||||
cformat, location,
|
||||
isExplicit);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We don't need to perform any actual coercion step, but we should
|
||||
* apply a RelabelType to ensure that the expression exposes the
|
||||
* intended typmod.
|
||||
*/
|
||||
RelabelType *rt;
|
||||
|
||||
rt = makeRelabelType((Expr *) node, targetTypeId, targetTypMod,
|
||||
exprCollation(node),
|
||||
cformat);
|
||||
rt->location = location;
|
||||
node = (Node *) rt;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue