From 21591967bc19c749a100fb97ec82f6086ce5cc3c Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Wed, 5 Mar 2003 20:01:04 +0000 Subject: [PATCH] Turns out new IN implementation has got some problems in an UPDATE or DELETE with inherited target table. Fix it; add a regression test. Also, correct ancient misspelling of 'inherited'. --- src/backend/nodes/copyfuncs.c | 14 +++++++----- src/backend/nodes/equalfuncs.c | 12 +++++----- src/backend/optimizer/path/allpaths.c | 4 ++-- src/backend/optimizer/plan/planner.c | 6 ++--- src/backend/optimizer/prep/prepunion.c | 6 ++--- src/include/optimizer/prep.h | 4 ++-- src/test/regress/expected/inherit.out | 31 ++++++++++++++++++++++++++ src/test/regress/sql/inherit.sql | 23 +++++++++++++++++++ 8 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 2698f084787..627f62c84f8 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.244 2003/02/16 02:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.245 2003/03/05 20:01:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1481,12 +1481,16 @@ _copyQuery(Query *from) COPY_NODE_FIELD(limitCount); COPY_NODE_FIELD(setOperations); COPY_INTLIST_FIELD(resultRelations); + COPY_NODE_FIELD(in_info_list); + COPY_SCALAR_FIELD(hasJoinRTEs); /* - * We do not copy the planner internal fields: base_rel_list, - * other_rel_list, join_rel_list, equi_key_list, in_info_list, - * query_pathkeys, hasJoinRTEs. That would get us into copying - * RelOptInfo/Path trees, which we don't want to do. + * We do not copy the other planner internal fields: base_rel_list, + * other_rel_list, join_rel_list, equi_key_list, query_pathkeys. + * That would get us into copying RelOptInfo/Path trees, which we don't + * want to do. It is necessary to copy in_info_list and hasJoinRTEs + * for the benefit of inheritance_planner(), which may try to copy a + * Query in which these are already set. */ return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 378d8e44031..6a0f3660097 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.187 2003/02/16 02:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.188 2003/03/05 20:01:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -576,12 +576,14 @@ _equalQuery(Query *a, Query *b) COMPARE_NODE_FIELD(limitCount); COMPARE_NODE_FIELD(setOperations); COMPARE_INTLIST_FIELD(resultRelations); + COMPARE_NODE_FIELD(in_info_list); + COMPARE_SCALAR_FIELD(hasJoinRTEs); /* - * We do not check the internal-to-the-planner fields: base_rel_list, - * other_rel_list, join_rel_list, equi_key_list, in_info_list, - * query_pathkeys, hasJoinRTEs. They might not be set yet, and in any - * case they should be derivable from the other fields. + * We do not check the other planner internal fields: base_rel_list, + * other_rel_list, join_rel_list, equi_key_list, query_pathkeys. + * They might not be set yet, and in any case they should be derivable + * from the other fields. */ return true; } diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 24a604716b8..99d979d57c0 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.97 2003/02/15 20:12:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.98 2003/03/05 20:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -115,7 +115,7 @@ set_base_rel_pathlists(Query *root) /* RangeFunction --- generate a separate plan for it */ set_function_pathlist(root, rel, rte); } - else if ((inheritlist = expand_inherted_rtentry(root, rti, true)) + else if ((inheritlist = expand_inherited_rtentry(root, rti, true)) != NIL) { /* Relation is root of an inheritance tree, process specially */ diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index c597e44f1d4..c7c072fe2eb 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.149 2003/03/05 18:38:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.150 2003/03/05 20:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -276,8 +276,8 @@ subquery_planner(Query *parse, double tuple_fraction) * grouping_planner. */ if (parse->resultRelation && - (lst = expand_inherted_rtentry(parse, parse->resultRelation, false)) - != NIL) + (lst = expand_inherited_rtentry(parse, parse->resultRelation, + false)) != NIL) plan = inheritance_planner(parse, lst); else plan = grouping_planner(parse, tuple_fraction); diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 0f63d2306c7..f0a64f2980c 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.90 2003/02/09 06:56:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.91 2003/03/05 20:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -642,7 +642,7 @@ find_all_inheritors(Oid parentrel) } /* - * expand_inherted_rtentry + * expand_inherited_rtentry * Check whether a rangetable entry represents an inheritance set. * If so, add entries for all the child tables to the query's * rangetable, and return an integer list of RT indexes for the @@ -666,7 +666,7 @@ find_all_inheritors(Oid parentrel) * XXX probably should convert the result type to Relids? */ List * -expand_inherted_rtentry(Query *parse, Index rti, bool dup_parent) +expand_inherited_rtentry(Query *parse, Index rti, bool dup_parent) { RangeTblEntry *rte = rt_fetch(rti, parse->rtable); Oid parentOID; diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h index 681d1c2eb1d..5cde6096a1e 100644 --- a/src/include/optimizer/prep.h +++ b/src/include/optimizer/prep.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: prep.h,v 1.37 2003/02/09 23:57:19 tgl Exp $ + * $Id: prep.h,v 1.38 2003/03/05 20:01:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -52,7 +52,7 @@ extern Plan *plan_set_operations(Query *parse); extern List *find_all_inheritors(Oid parentrel); -extern List *expand_inherted_rtentry(Query *parse, Index rti, +extern List *expand_inherited_rtentry(Query *parse, Index rti, bool dup_parent); extern Node *adjust_inherited_attrs(Node *node, diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 6ca59e799bf..e6fc8bcb575 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -539,3 +539,34 @@ CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'z_pkey' for table 'z' INSERT INTO z VALUES (NULL, 'text'); -- should fail ERROR: ExecInsert: Fail to add null value in not null attribute aa +-- Check UPDATE with inherited target and an inherited source table +create temp table foo(f1 int, f2 int); +create temp table foo2(f3 int) inherits (foo); +create temp table bar(f1 int, f2 int); +create temp table bar2(f3 int) inherits (bar); +insert into foo values(1,1); +insert into foo values(3,3); +insert into foo2 values(2,2,2); +insert into foo2 values(3,3,3); +insert into bar values(1,1); +insert into bar values(2,2); +insert into bar values(3,3); +insert into bar values(4,4); +insert into bar2 values(1,1,1); +insert into bar2 values(2,2,2); +insert into bar2 values(3,3,3); +insert into bar2 values(4,4,4); +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); +SELECT relname, bar.* FROM bar, pg_class where bar.tableoid = pg_class.oid; + relname | f1 | f2 +---------+----+----- + bar | 4 | 4 + bar | 1 | 101 + bar | 2 | 102 + bar | 3 | 103 + bar2 | 4 | 4 + bar2 | 1 | 101 + bar2 | 2 | 102 + bar2 | 3 | 103 +(8 rows) + diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index d8d73f8860f..a50b5e75f93 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -96,3 +96,26 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid; -- Confirm PRIMARY KEY adds NOT NULL constraint to child table CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); INSERT INTO z VALUES (NULL, 'text'); -- should fail + +-- Check UPDATE with inherited target and an inherited source table +create temp table foo(f1 int, f2 int); +create temp table foo2(f3 int) inherits (foo); +create temp table bar(f1 int, f2 int); +create temp table bar2(f3 int) inherits (bar); + +insert into foo values(1,1); +insert into foo values(3,3); +insert into foo2 values(2,2,2); +insert into foo2 values(3,3,3); +insert into bar values(1,1); +insert into bar values(2,2); +insert into bar values(3,3); +insert into bar values(4,4); +insert into bar2 values(1,1,1); +insert into bar2 values(2,2,2); +insert into bar2 values(3,3,3); +insert into bar2 values(4,4,4); + +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); + +SELECT relname, bar.* FROM bar, pg_class where bar.tableoid = pg_class.oid; -- GitLab