mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08: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:
parent
a981b02336
commit
f245c4eb1a
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user