diff --git a/expected/pathman_subpartitions.out b/expected/pathman_subpartitions.out index 4dd5f5dd..a876b457 100644 --- a/expected/pathman_subpartitions.out +++ b/expected/pathman_subpartitions.out @@ -424,6 +424,39 @@ UPDATE subpartitions.abc SET id1 = -1, id2 = -1 RETURNING tableoid::regclass, *; DROP TABLE subpartitions.abc CASCADE; NOTICE: drop cascades to 9 other objects +--- basic check how rowmark plays along with subparts; PGPRO-2755 +CREATE TABLE subpartitions.a1(n1 integer); +CREATE TABLE subpartitions.a2(n1 integer not null, n2 integer not null); +SELECT create_range_partitions('subpartitions.a2', 'n1', 1, 2, 0); + create_range_partitions +------------------------- + 0 +(1 row) + +SELECT add_range_partition('subpartitions.a2', 10, 20, 'subpartitions.a2_1020'); + add_range_partition +----------------------- + subpartitions.a2_1020 +(1 row) + +SELECT create_range_partitions('subpartitions.a2_1020'::regclass, 'n2'::text, array[30,40], array['subpartitions.a2_1020_3040']); + create_range_partitions +------------------------- + 1 +(1 row) + +INSERT INTO subpartitions.a2 VALUES (10, 30), (11, 31), (12, 32), (19, 39); +INSERT INTO subpartitions.a1 VALUES (12), (19), (20); +SELECT a2.* FROM subpartitions.a1 JOIN subpartitions.a2 ON a2.n1=a1.n1 FOR UPDATE; + n1 | n2 +----+---- + 12 | 32 + 19 | 39 +(2 rows) + +DROP TABLE subpartitions.a2 CASCADE; +NOTICE: drop cascades to 4 other objects +DROP TABLE subpartitions.a1; DROP SCHEMA subpartitions CASCADE; NOTICE: drop cascades to function subpartitions.partitions_tree(regclass,text) DROP EXTENSION pg_pathman; diff --git a/sql/pathman_subpartitions.sql b/sql/pathman_subpartitions.sql index b790c20e..05ac9614 100644 --- a/sql/pathman_subpartitions.sql +++ b/sql/pathman_subpartitions.sql @@ -139,8 +139,24 @@ SELECT tableoid::regclass, * FROM subpartitions.abc ORDER BY id1, id2, val; SET pg_pathman.enable_partitionrouter = ON; UPDATE subpartitions.abc SET id1 = -1, id2 = -1 RETURNING tableoid::regclass, *; +DROP TABLE subpartitions.abc CASCADE; + + +--- basic check how rowmark plays along with subparts; PGPRO-2755 +CREATE TABLE subpartitions.a1(n1 integer); +CREATE TABLE subpartitions.a2(n1 integer not null, n2 integer not null); +SELECT create_range_partitions('subpartitions.a2', 'n1', 1, 2, 0); + +SELECT add_range_partition('subpartitions.a2', 10, 20, 'subpartitions.a2_1020'); +SELECT create_range_partitions('subpartitions.a2_1020'::regclass, 'n2'::text, array[30,40], array['subpartitions.a2_1020_3040']); +INSERT INTO subpartitions.a2 VALUES (10, 30), (11, 31), (12, 32), (19, 39); +INSERT INTO subpartitions.a1 VALUES (12), (19), (20); + +SELECT a2.* FROM subpartitions.a1 JOIN subpartitions.a2 ON a2.n1=a1.n1 FOR UPDATE; + +DROP TABLE subpartitions.a2 CASCADE; +DROP TABLE subpartitions.a1; -DROP TABLE subpartitions.abc CASCADE; DROP SCHEMA subpartitions CASCADE; DROP EXTENSION pg_pathman; diff --git a/src/include/rangeset.h b/src/include/rangeset.h index 96d6bc21..39db6a53 100644 --- a/src/include/rangeset.h +++ b/src/include/rangeset.h @@ -1,7 +1,6 @@ /* ------------------------------------------------------------------------ * * rangeset.h - * IndexRange functions * * Copyright (c) 2015-2016, Postgres Professional * @@ -17,7 +16,10 @@ /* - * IndexRange contains a set of selected partitions. + * IndexRange is essentially a segment [lower; upper]. This module provides + * functions for efficient working (intersection, union) with Lists of + * IndexRange's; this is used for quick selection of partitions. Numbers are + * indexes of partitions in PartRelationInfo's children. */ typedef struct { /* lossy == should we use quals? */ diff --git a/src/pg_pathman.c b/src/pg_pathman.c index 3511a243..2cd17c6a 100644 --- a/src/pg_pathman.c +++ b/src/pg_pathman.c @@ -437,7 +437,7 @@ append_child_relation(PlannerInfo *root, Relation child_relation; AppendRelInfo *appinfo; Index child_rti; - PlanRowMark *child_rowmark; + PlanRowMark *child_rowmark = NULL; Node *childqual; List *childquals; ListCell *lc1, @@ -493,6 +493,10 @@ append_child_relation(PlannerInfo *root, /* Create rowmarks required for child rels */ + /* + * XXX: vanilla recurses down with *top* rowmark, not immediate parent one. + * Not sure about example where this matters though. + */ if (parent_rowmark) { child_rowmark = makeNode(PlanRowMark); @@ -511,6 +515,13 @@ append_child_relation(PlannerInfo *root, root->rowMarks = lappend(root->rowMarks, child_rowmark); /* Adjust tlist for RowMarks (see planner.c) */ + /* + * XXX Saner approach seems to + * 1) Add tle to top parent and processed_tlist once in rel_pathlist_hook. + * 2) Mark isParent = true + * *parent* knows it is parent, after all; why should child bother? + * 3) Recursion (code executed in childs) starts at 2) + */ if (!parent_rowmark->isParent && !root->parse->setOperations) { append_tle_for_rowmark(root, parent_rowmark); @@ -636,6 +647,10 @@ append_child_relation(PlannerInfo *root, if (parent_rte->relid != child_oid && child_relation->rd_rel->relhassubclass) { + /* See XXX above */ + if (child_rowmark) + child_rowmark->isParent = true; + pathman_rel_pathlist_hook(root, child_rel, child_rti,