mirror of
https://github.com/postgres/postgres.git
synced 2025-07-09 22:41:56 +03:00
Apply fixes for problems with dropped columns whose types have also been
dropped. The simplest fix for INSERT/UPDATE cases turns out to be for preptlist.c to insert NULLs of a known-good type (I used INT4) rather than making them match the deleted column's type. Since the representation of NULL is actually datatype-independent, this should work fine. I also re-reverted the patch to disable the use_physical_tlist optimization in the presence of dropped columns. It still doesn't look worth the trouble to be smarter, if there are no other bugs to fix. Added a regression test to catch future problems in this area.
This commit is contained in:
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.141 2003/05/11 20:25:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.142 2003/05/12 00:17:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -295,6 +295,12 @@ use_physical_tlist(RelOptInfo *rel)
|
||||
*/
|
||||
if (rel->reloptkind != RELOPT_BASEREL)
|
||||
return false;
|
||||
/*
|
||||
* Can't do it if relation contains dropped columns. This is detected
|
||||
* in plancat.c, see notes there.
|
||||
*/
|
||||
if (rel->varlist == NIL)
|
||||
return false;
|
||||
/*
|
||||
* Can't do it if any system columns are requested, either. (This could
|
||||
* possibly be fixed but would take some fragile assumptions in setrefs.c,
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.60 2003/02/03 21:15:44 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.61 2003/05/12 00:17:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -171,6 +171,15 @@ expand_targetlist(List *tlist, int command_type,
|
||||
* the attribute, so that it gets copied to the new tuple. But
|
||||
* generate a NULL for dropped columns (we want to drop any
|
||||
* old values).
|
||||
*
|
||||
* When generating a NULL constant for a dropped column, we label
|
||||
* it INT4 (any other guaranteed-to-exist datatype would do as
|
||||
* well). We can't label it with the dropped column's datatype
|
||||
* since that might not exist anymore. It does not really
|
||||
* matter what we claim the type is, since NULL is NULL --- its
|
||||
* representation is datatype-independent. This could perhaps
|
||||
* confuse code comparing the finished plan to the target
|
||||
* relation, however.
|
||||
*/
|
||||
Oid atttype = att_tup->atttypid;
|
||||
int32 atttypmod = att_tup->atttypmod;
|
||||
@ -179,31 +188,52 @@ expand_targetlist(List *tlist, int command_type,
|
||||
switch (command_type)
|
||||
{
|
||||
case CMD_INSERT:
|
||||
new_expr = (Node *) makeConst(atttype,
|
||||
att_tup->attlen,
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
att_tup->attbyval);
|
||||
if (!att_tup->attisdropped)
|
||||
{
|
||||
new_expr = (Node *) makeConst(atttype,
|
||||
att_tup->attlen,
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
att_tup->attbyval);
|
||||
new_expr = coerce_to_domain(new_expr,
|
||||
InvalidOid,
|
||||
atttype,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert NULL for dropped column */
|
||||
new_expr = (Node *) makeConst(INT4OID,
|
||||
sizeof(int32),
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
true /* byval */);
|
||||
/* label resdom with INT4, too */
|
||||
atttype = INT4OID;
|
||||
atttypmod = -1;
|
||||
}
|
||||
break;
|
||||
case CMD_UPDATE:
|
||||
/* Insert NULLs for dropped columns */
|
||||
if (att_tup->attisdropped)
|
||||
new_expr = (Node *) makeConst(atttype,
|
||||
att_tup->attlen,
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
att_tup->attbyval);
|
||||
else
|
||||
if (!att_tup->attisdropped)
|
||||
{
|
||||
new_expr = (Node *) makeVar(result_relation,
|
||||
attrno,
|
||||
atttype,
|
||||
atttypmod,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert NULL for dropped column */
|
||||
new_expr = (Node *) makeConst(INT4OID,
|
||||
sizeof(int32),
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
true /* byval */);
|
||||
/* label resdom with INT4, too */
|
||||
atttype = INT4OID;
|
||||
atttypmod = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "expand_targetlist: unexpected command_type");
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.81 2003/05/11 20:25:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.82 2003/05/12 00:17:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -62,8 +62,15 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
|
||||
relation = heap_open(relationObjectId, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Make list of physical Vars. Note we do NOT ignore dropped columns;
|
||||
* the intent is to model the physical tuples of the relation.
|
||||
* Make list of physical Vars. But if there are any dropped columns,
|
||||
* punt and set varlist to NIL. (XXX Ideally we would like to include
|
||||
* dropped columns so that the varlist models the physical tuples
|
||||
* of the relation. However this creates problems for ExecTypeFromTL,
|
||||
* which may be asked to build a tupdesc for a tlist that includes vars
|
||||
* of no-longer-existent types. In theory we could dig out the required
|
||||
* info from the pg_attribute entries of the relation, but that data is
|
||||
* not readily available to ExecTypeFromTL. For now, punt and don't
|
||||
* apply the physical-tlist optimization when there are dropped cols.)
|
||||
*/
|
||||
numattrs = RelationGetNumberOfAttributes(relation);
|
||||
|
||||
@ -71,6 +78,13 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
|
||||
{
|
||||
Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
|
||||
|
||||
if (att_tup->attisdropped)
|
||||
{
|
||||
/* found a dropped col, so punt */
|
||||
varlist = NIL;
|
||||
break;
|
||||
}
|
||||
|
||||
varlist = lappend(varlist,
|
||||
makeVar(varno,
|
||||
attrno,
|
||||
|
Reference in New Issue
Block a user