mirror of
https://github.com/postgres/postgres.git
synced 2025-08-19 23:22:23 +03:00
When implementing a coercion to a domain type with a combined
type-and-length coercion function, make sure that the coercion function is told the correct typmod. Fixes Kris Jurka's example of a domain over bit(N).
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.123 2004/08/29 05:06:44 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.124 2004/11/06 17:46:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -191,7 +191,7 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
/* If target is a domain, apply constraints. */
|
||||
if (targetTyptype == 'd')
|
||||
result = coerce_to_domain(result, InvalidOid, targetTypeId,
|
||||
cformat, false);
|
||||
cformat, false, false);
|
||||
|
||||
ReleaseSysCache(targetType);
|
||||
|
||||
@@ -253,23 +253,33 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* Generate an expression tree representing run-time
|
||||
* application of the conversion function. If we are dealing
|
||||
* with a domain target type, the conversion function will
|
||||
* yield the base type (and we assume targetTypeMod must be
|
||||
* -1).
|
||||
* yield the base type, and we need to extract the correct
|
||||
* typmod to use from the domain's typtypmod.
|
||||
*/
|
||||
Oid baseTypeId = getBaseType(targetTypeId);
|
||||
int32 baseTypeMod;
|
||||
|
||||
if (targetTypeId != baseTypeId)
|
||||
baseTypeMod = get_typtypmod(targetTypeId);
|
||||
else
|
||||
baseTypeMod = targetTypeMod;
|
||||
|
||||
result = build_coercion_expression(node, funcId,
|
||||
baseTypeId, targetTypeMod,
|
||||
baseTypeId, baseTypeMod,
|
||||
cformat,
|
||||
(cformat != COERCE_IMPLICIT_CAST));
|
||||
|
||||
/*
|
||||
* If domain, coerce to the domain type and relabel with
|
||||
* domain type ID
|
||||
* domain type ID. We can skip the internal length-coercion
|
||||
* step if the selected coercion function was a type-and-length
|
||||
* coercion.
|
||||
*/
|
||||
if (targetTypeId != baseTypeId)
|
||||
result = coerce_to_domain(result, baseTypeId, targetTypeId,
|
||||
cformat, true);
|
||||
cformat, true,
|
||||
exprIsLengthCoercion(result,
|
||||
NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -284,7 +294,7 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* then we won't need a RelabelType node.
|
||||
*/
|
||||
result = coerce_to_domain(node, InvalidOid, targetTypeId,
|
||||
cformat, false);
|
||||
cformat, false, false);
|
||||
if (result == node)
|
||||
{
|
||||
/*
|
||||
@@ -425,15 +435,16 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
||||
* 'typeId': target type to coerce to
|
||||
* 'cformat': coercion format
|
||||
* 'hideInputCoercion': if true, hide the input coercion under this one.
|
||||
* 'lengthCoercionDone': if true, caller already accounted for length.
|
||||
*
|
||||
* If the target type isn't a domain, the given 'arg' is returned as-is.
|
||||
*/
|
||||
Node *
|
||||
coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
|
||||
CoercionForm cformat, bool hideInputCoercion)
|
||||
CoercionForm cformat, bool hideInputCoercion,
|
||||
bool lengthCoercionDone)
|
||||
{
|
||||
CoerceToDomain *result;
|
||||
int32 typmod;
|
||||
|
||||
/* Get the base type if it hasn't been supplied */
|
||||
if (baseTypeId == InvalidOid)
|
||||
@@ -461,12 +472,16 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
|
||||
* that would be safe to do anyway, without lots of knowledge about
|
||||
* what the base type thinks the typmod means.
|
||||
*/
|
||||
typmod = get_typtypmod(typeId);
|
||||
if (typmod >= 0)
|
||||
arg = coerce_type_typmod(arg, baseTypeId, typmod,
|
||||
COERCE_IMPLICIT_CAST,
|
||||
(cformat != COERCE_IMPLICIT_CAST),
|
||||
false);
|
||||
if (!lengthCoercionDone)
|
||||
{
|
||||
int32 typmod = get_typtypmod(typeId);
|
||||
|
||||
if (typmod >= 0)
|
||||
arg = coerce_type_typmod(arg, baseTypeId, typmod,
|
||||
COERCE_IMPLICIT_CAST,
|
||||
(cformat != COERCE_IMPLICIT_CAST),
|
||||
false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now build the domain coercion node. This represents run-time
|
||||
|
Reference in New Issue
Block a user