Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita60f9db

Browse files
committed
Fix inherited UPDATE for cases where child column numbering doesn't
match parent table. This used to work, but was broken in 7.3 byrearrangement of code that handles targetlist sorting. Add a regressiontest to catch future breakage.
1 parent17194f4 commita60f9db

File tree

3 files changed

+155
-3
lines changed

3 files changed

+155
-3
lines changed

‎src/backend/optimizer/prep/prepunion.c

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.83 2002/12/14 00:17:57 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.84 2003/01/05 00:56:40 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -67,6 +67,7 @@ static List *generate_append_tlist(List *colTypes, bool flag,
6767
List*refnames_tlist);
6868
staticNode*adjust_inherited_attrs_mutator(Node*node,
6969
adjust_inherited_attrs_context*context);
70+
staticList*adjust_inherited_tlist(List*tlist,Oidnew_relid);
7071

7172

7273
/*
@@ -768,10 +769,17 @@ adjust_inherited_attrs(Node *node,
768769
Query*newnode;
769770

770771
FLATCOPY(newnode,query,Query);
771-
if (newnode->resultRelation==old_rt_index)
772-
newnode->resultRelation=new_rt_index;
773772
query_tree_mutator(newnode,adjust_inherited_attrs_mutator,
774773
(void*)&context,QTW_IGNORE_SUBQUERIES);
774+
if (newnode->resultRelation==old_rt_index)
775+
{
776+
newnode->resultRelation=new_rt_index;
777+
/* Fix tlist resnos too, if it's inherited UPDATE */
778+
if (newnode->commandType==CMD_UPDATE)
779+
newnode->targetList=
780+
adjust_inherited_tlist(newnode->targetList,
781+
new_relid);
782+
}
775783
return (Node*)newnode;
776784
}
777785
else
@@ -887,3 +895,101 @@ adjust_inherited_attrs_mutator(Node *node,
887895
returnexpression_tree_mutator(node,adjust_inherited_attrs_mutator,
888896
(void*)context);
889897
}
898+
899+
/*
900+
* Adjust the targetlist entries of an inherited UPDATE operation
901+
*
902+
* The expressions have already been fixed, but we have to make sure that
903+
* the target resnos match the child table (they may not, in the case of
904+
* a column that was added after-the-fact by ALTER TABLE). In some cases
905+
* this can force us to re-order the tlist to preserve resno ordering.
906+
* (We do all this work in special cases so that preptlist.c is fast for
907+
* the typical case.)
908+
*
909+
* The given tlist has already been through expression_tree_mutator;
910+
* therefore the TargetEntry nodes are fresh copies that it's okay to
911+
* scribble on. But the Resdom nodes have not been copied; make new ones
912+
* if we need to change them!
913+
*
914+
* Note that this is not needed for INSERT because INSERT isn't inheritable.
915+
*/
916+
staticList*
917+
adjust_inherited_tlist(List*tlist,Oidnew_relid)
918+
{
919+
boolchanged_it= false;
920+
List*tl;
921+
List*new_tlist;
922+
boolmore;
923+
intattrno;
924+
925+
/* Scan tlist and update resnos to match attnums of new_relid */
926+
foreach(tl,tlist)
927+
{
928+
TargetEntry*tle= (TargetEntry*)lfirst(tl);
929+
Resdom*resdom=tle->resdom;
930+
931+
if (resdom->resjunk)
932+
continue;/* ignore junk items */
933+
934+
attrno=get_attnum(new_relid,resdom->resname);
935+
if (attrno==InvalidAttrNumber)
936+
elog(ERROR,"Relation \"%s\" has no column \"%s\"",
937+
get_rel_name(new_relid),resdom->resname);
938+
if (resdom->resno!=attrno)
939+
{
940+
resdom= (Resdom*)copyObject((Node*)resdom);
941+
resdom->resno=attrno;
942+
tle->resdom=resdom;
943+
changed_it= true;
944+
}
945+
}
946+
947+
/*
948+
* If we changed anything, re-sort the tlist by resno, and make sure
949+
* resjunk entries have resnos above the last real resno. The sort
950+
* algorithm is a bit stupid, but for such a seldom-taken path, small
951+
* is probably better than fast.
952+
*/
953+
if (!changed_it)
954+
returntlist;
955+
956+
new_tlist=NIL;
957+
more= true;
958+
for (attrno=1;more;attrno++)
959+
{
960+
more= false;
961+
foreach(tl,tlist)
962+
{
963+
TargetEntry*tle= (TargetEntry*)lfirst(tl);
964+
Resdom*resdom=tle->resdom;
965+
966+
if (resdom->resjunk)
967+
continue;/* ignore junk items */
968+
969+
if (resdom->resno==attrno)
970+
new_tlist=lappend(new_tlist,tle);
971+
elseif (resdom->resno>attrno)
972+
more= true;
973+
}
974+
}
975+
976+
foreach(tl,tlist)
977+
{
978+
TargetEntry*tle= (TargetEntry*)lfirst(tl);
979+
Resdom*resdom=tle->resdom;
980+
981+
if (!resdom->resjunk)
982+
continue;/* here, ignore non-junk items */
983+
984+
if (resdom->resno!=attrno)
985+
{
986+
resdom= (Resdom*)copyObject((Node*)resdom);
987+
resdom->resno=attrno;
988+
tle->resdom=resdom;
989+
}
990+
new_tlist=lappend(new_tlist,tle);
991+
attrno++;
992+
}
993+
994+
returnnew_tlist;
995+
}

‎src/test/regress/expected/alter_table.out

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,3 +1179,31 @@ order by relname, attnum;
11791179
drop table p1, p2 cascade;
11801180
NOTICE: Drop cascades to table c1
11811181
NOTICE: Drop cascades to table gc1
1182+
-- test renumbering of child-table columns in inherited operations
1183+
create table p1 (f1 int);
1184+
create table c1 (f2 text, f3 int) inherits (p1);
1185+
alter table p1 add column a1 int check (a1 > 0);
1186+
alter table p1 add column f2 text;
1187+
NOTICE: ALTER TABLE: merging definition of column "f2" for child c1
1188+
insert into p1 values (1,2,'abc');
1189+
insert into c1 values(11,'xyz',33,0); -- should fail
1190+
ERROR: ExecInsert: rejected due to CHECK constraint "p1_a1" on "c1"
1191+
insert into c1 values(11,'xyz',33,22);
1192+
select * from p1;
1193+
f1 | a1 | f2
1194+
----+----+-----
1195+
1 | 2 | abc
1196+
11 | 22 | xyz
1197+
(2 rows)
1198+
1199+
update p1 set a1 = a1 + 1, f2 = upper(f2);
1200+
select * from p1;
1201+
f1 | a1 | f2
1202+
----+----+-----
1203+
1 | 3 | ABC
1204+
11 | 23 | XYZ
1205+
(2 rows)
1206+
1207+
drop table p1 cascade;
1208+
NOTICE: Drop cascades to table c1
1209+
NOTICE: Drop cascades to constraint p1_a1 on table c1

‎src/test/regress/sql/alter_table.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,3 +849,21 @@ where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
849849
order by relname, attnum;
850850

851851
droptable p1, p2 cascade;
852+
853+
-- test renumbering of child-table columns in inherited operations
854+
855+
createtablep1 (f1int);
856+
createtablec1 (f2text, f3int) inherits (p1);
857+
858+
altertable p1 add column a1intcheck (a1>0);
859+
altertable p1 add column f2text;
860+
861+
insert into p1values (1,2,'abc');
862+
insert into c1values(11,'xyz',33,0);-- should fail
863+
insert into c1values(11,'xyz',33,22);
864+
865+
select*from p1;
866+
update p1set a1= a1+1, f2=upper(f2);
867+
select*from p1;
868+
869+
droptable p1 cascade;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp