mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 22:02:03 +03:00
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'.
This commit is contained in:
parent
147fbf9c6e
commit
21591967bc
@ -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
|
||||||
* $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(limitCount);
|
||||||
COPY_NODE_FIELD(setOperations);
|
COPY_NODE_FIELD(setOperations);
|
||||||
COPY_INTLIST_FIELD(resultRelations);
|
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,
|
* We do not copy the other planner internal fields: base_rel_list,
|
||||||
* other_rel_list, join_rel_list, equi_key_list, in_info_list,
|
* other_rel_list, join_rel_list, equi_key_list, query_pathkeys.
|
||||||
* query_pathkeys, hasJoinRTEs. That would get us into copying
|
* That would get us into copying RelOptInfo/Path trees, which we don't
|
||||||
* RelOptInfo/Path trees, which we don't want to do.
|
* 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;
|
return newnode;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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(limitCount);
|
||||||
COMPARE_NODE_FIELD(setOperations);
|
COMPARE_NODE_FIELD(setOperations);
|
||||||
COMPARE_INTLIST_FIELD(resultRelations);
|
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,
|
* We do not check the other planner internal fields: base_rel_list,
|
||||||
* other_rel_list, join_rel_list, equi_key_list, in_info_list,
|
* other_rel_list, join_rel_list, equi_key_list, query_pathkeys.
|
||||||
* query_pathkeys, hasJoinRTEs. They might not be set yet, and in any
|
* They might not be set yet, and in any case they should be derivable
|
||||||
* case they should be derivable from the other fields.
|
* from the other fields.
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
/* RangeFunction --- generate a separate plan for it */
|
||||||
set_function_pathlist(root, rel, rte);
|
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)
|
!= NIL)
|
||||||
{
|
{
|
||||||
/* Relation is root of an inheritance tree, process specially */
|
/* Relation is root of an inheritance tree, process specially */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* grouping_planner.
|
||||||
*/
|
*/
|
||||||
if (parse->resultRelation &&
|
if (parse->resultRelation &&
|
||||||
(lst = expand_inherted_rtentry(parse, parse->resultRelation, false))
|
(lst = expand_inherited_rtentry(parse, parse->resultRelation,
|
||||||
!= NIL)
|
false)) != NIL)
|
||||||
plan = inheritance_planner(parse, lst);
|
plan = inheritance_planner(parse, lst);
|
||||||
else
|
else
|
||||||
plan = grouping_planner(parse, tuple_fraction);
|
plan = grouping_planner(parse, tuple_fraction);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* Check whether a rangetable entry represents an inheritance set.
|
||||||
* If so, add entries for all the child tables to the query's
|
* If so, add entries for all the child tables to the query's
|
||||||
* rangetable, and return an integer list of RT indexes for the
|
* 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?
|
* XXX probably should convert the result type to Relids?
|
||||||
*/
|
*/
|
||||||
List *
|
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);
|
RangeTblEntry *rte = rt_fetch(rti, parse->rtable);
|
||||||
Oid parentOID;
|
Oid parentOID;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 *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);
|
bool dup_parent);
|
||||||
|
|
||||||
extern Node *adjust_inherited_attrs(Node *node,
|
extern Node *adjust_inherited_attrs(Node *node,
|
||||||
|
@ -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'
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'z_pkey' for table 'z'
|
||||||
INSERT INTO z VALUES (NULL, 'text'); -- should fail
|
INSERT INTO z VALUES (NULL, 'text'); -- should fail
|
||||||
ERROR: ExecInsert: Fail to add null value in not null attribute aa
|
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)
|
||||||
|
|
||||||
|
@ -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
|
-- Confirm PRIMARY KEY adds NOT NULL constraint to child table
|
||||||
CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
|
CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
|
||||||
INSERT INTO z VALUES (NULL, 'text'); -- should fail
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user