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:
Tom Lane 2004-11-06 17:46:38 +00:00
parent a981b02336
commit f245c4eb1a
5 changed files with 40 additions and 22 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.233 2004/10/29 19:18:22 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.234 2004/11/06 17:46:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1596,7 +1596,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
node = coerce_to_domain((Node *) prm, node = coerce_to_domain((Node *) prm,
prm->paramtype, prm->paramtype,
attr[attnum - 1]->atttypid, attr[attnum - 1]->atttypid,
COERCE_IMPLICIT_CAST, false); COERCE_IMPLICIT_CAST, false, false);
constraintexprs[attnum - 1] = ExecPrepareExpr((Expr *) node, constraintexprs[attnum - 1] = ExecPrepareExpr((Expr *) node,
estate); estate);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.70 2004/08/29 04:12:34 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.71 2004/11/06 17:46:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -200,6 +200,7 @@ expand_targetlist(List *tlist, int command_type,
InvalidOid, InvalidOid,
atttype, atttype,
COERCE_IMPLICIT_CAST, COERCE_IMPLICIT_CAST,
false,
false); false);
} }
else else

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 target is a domain, apply constraints. */
if (targetTyptype == 'd') if (targetTyptype == 'd')
result = coerce_to_domain(result, InvalidOid, targetTypeId, result = coerce_to_domain(result, InvalidOid, targetTypeId,
cformat, false); cformat, false, false);
ReleaseSysCache(targetType); ReleaseSysCache(targetType);
@ -253,23 +253,33 @@ coerce_type(ParseState *pstate, Node *node,
* Generate an expression tree representing run-time * Generate an expression tree representing run-time
* application of the conversion function. If we are dealing * application of the conversion function. If we are dealing
* with a domain target type, the conversion function will * with a domain target type, the conversion function will
* yield the base type (and we assume targetTypeMod must be * yield the base type, and we need to extract the correct
* -1). * typmod to use from the domain's typtypmod.
*/ */
Oid baseTypeId = getBaseType(targetTypeId); Oid baseTypeId = getBaseType(targetTypeId);
int32 baseTypeMod;
if (targetTypeId != baseTypeId)
baseTypeMod = get_typtypmod(targetTypeId);
else
baseTypeMod = targetTypeMod;
result = build_coercion_expression(node, funcId, result = build_coercion_expression(node, funcId,
baseTypeId, targetTypeMod, baseTypeId, baseTypeMod,
cformat, cformat,
(cformat != COERCE_IMPLICIT_CAST)); (cformat != COERCE_IMPLICIT_CAST));
/* /*
* If domain, coerce to the domain type and relabel with * 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) if (targetTypeId != baseTypeId)
result = coerce_to_domain(result, baseTypeId, targetTypeId, result = coerce_to_domain(result, baseTypeId, targetTypeId,
cformat, true); cformat, true,
exprIsLengthCoercion(result,
NULL));
} }
else else
{ {
@ -284,7 +294,7 @@ coerce_type(ParseState *pstate, Node *node,
* then we won't need a RelabelType node. * then we won't need a RelabelType node.
*/ */
result = coerce_to_domain(node, InvalidOid, targetTypeId, result = coerce_to_domain(node, InvalidOid, targetTypeId,
cformat, false); cformat, false, false);
if (result == node) if (result == node)
{ {
/* /*
@ -425,15 +435,16 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
* 'typeId': target type to coerce to * 'typeId': target type to coerce to
* 'cformat': coercion format * 'cformat': coercion format
* 'hideInputCoercion': if true, hide the input coercion under this one. * '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. * If the target type isn't a domain, the given 'arg' is returned as-is.
*/ */
Node * Node *
coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
CoercionForm cformat, bool hideInputCoercion) CoercionForm cformat, bool hideInputCoercion,
bool lengthCoercionDone)
{ {
CoerceToDomain *result; CoerceToDomain *result;
int32 typmod;
/* Get the base type if it hasn't been supplied */ /* Get the base type if it hasn't been supplied */
if (baseTypeId == InvalidOid) 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 * that would be safe to do anyway, without lots of knowledge about
* what the base type thinks the typmod means. * what the base type thinks the typmod means.
*/ */
typmod = get_typtypmod(typeId); if (!lengthCoercionDone)
if (typmod >= 0) {
arg = coerce_type_typmod(arg, baseTypeId, typmod, int32 typmod = get_typtypmod(typeId);
COERCE_IMPLICIT_CAST,
(cformat != COERCE_IMPLICIT_CAST), if (typmod >= 0)
false); 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 * Now build the domain coercion node. This represents run-time

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.144 2004/08/29 05:06:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.145 2004/11/06 17:46:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -374,6 +374,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
InvalidOid, InvalidOid,
att_tup->atttypid, att_tup->atttypid,
COERCE_IMPLICIT_CAST, COERCE_IMPLICIT_CAST,
false,
false); false);
} }
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.58 2004/08/29 04:13:09 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.59 2004/11/06 17:46:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -50,7 +50,8 @@ extern Node *coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod, Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
CoercionContext ccontext, CoercionForm cformat); CoercionContext ccontext, CoercionForm cformat);
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
CoercionForm cformat, bool hideInputCoercion); CoercionForm cformat, bool hideInputCoercion,
bool lengthCoercionDone);
extern Node *coerce_to_boolean(ParseState *pstate, Node *node, extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
const char *constructName); const char *constructName);