diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-11-06 17:46:38 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-11-06 17:46:38 +0000 |
commit | f245c4eb1a0d8520c1a217d18d3e965042a1cb2f (patch) | |
tree | 068bf02f8333fbf5e64c30573f2a93b3cc715cfd /src/backend/parser/parse_coerce.c | |
parent | a981b0233622600754aaa287f05c685615353bc6 (diff) |
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).
Diffstat (limited to 'src/backend/parser/parse_coerce.c')
-rw-r--r-- | src/backend/parser/parse_coerce.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index ff513a0c131..4ac4ec84ece 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -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 |