Correctly handle childless hypothetical partitioned tables.

This commit is contained in:
Julien Rouhaud 2018-11-04 13:17:27 +01:00
parent 8d78b0783e
commit efb1ac04f3
3 changed files with 113 additions and 14 deletions

View file

@ -58,15 +58,9 @@ INSERT INTO part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (
-- Hypothetical tables
-- -------------------
-- 0. Dropping any hypothetical object
SELECT * FROM hypopg_reset_index();
hypopg_reset_index
--------------------
(1 row)
SELECT * FROM hypopg_reset_table();
hypopg_reset_table
--------------------
SELECT * FROM hypopg_reset();
hypopg_reset
--------------
(1 row)
@ -1409,3 +1403,75 @@ EXPLAIN (COSTS OFF) WITH s AS (DELETE FROM foo USING part_range WHERE foo.id = p
Filter: (id = 42)
(9 rows)
-- childless partitioning
-- ======================
SELECT * FROM hypopg_reset();
hypopg_reset
--------------
(1 row)
DROP TABLE part_multi CASCADE;
CREATE TABLE part_multi(dpt smallint, dt date, val text) PARTITION BY LIST (dpt);
SELECT * FROM hypopg_partition_table('hypo_part_multi', 'PARTITION BY LIST (dpt)');
hypopg_partition_table
------------------------
t
(1 row)
EXPLAIN (COSTS OFF) SELECT * FROM part_multi;
QUERY PLAN
--------------------------
Result
One-Time Filter: false
(2 rows)
EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi;
QUERY PLAN
--------------------------
Result
One-Time Filter: false
(2 rows)
CREATE TABLE part_multi_2 PARTITION OF part_multi FOR VALUES IN (2) PARTITION BY RANGE(dt);
CREATE TABLE part_multi_2_q1 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$);
CREATE TABLE part_multi_1 PARTITION OF part_multi FOR VALUES IN (1) PARTITION BY RANGE(dt);
CREATE TABLE part_multi_1_q1 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$) PARTITION BY RANGE (dt);
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2', 'PARTITION OF hypo_part_multi FOR VALUES IN (2)', 'PARTITION BY RANGE(dt)');
tablename
-------------------
hypo_part_multi_2
(1 row)
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q1', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)');
tablename
----------------------
hypo_part_multi_2_q1
(1 row)
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1', 'PARTITION OF hypo_part_multi FOR VALUES IN (1)', 'PARTITION BY RANGE(dt)');
tablename
-------------------
hypo_part_multi_1
(1 row)
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1', 'PARTITION OF hypo_part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)','PARTITION BY RANGE (dt)');
tablename
----------------------
hypo_part_multi_1_q1
(1 row)
EXPLAIN (COSTS OFF) SELECT * FROM part_multi;
QUERY PLAN
-----------------------------------
Append
-> Seq Scan on part_multi_2_q1
(2 rows)
EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi;
QUERY PLAN
--------------------------------------------------------
Append
-> Seq Scan on hypo_part_multi hypo_part_multi_2_q1
(2 rows)

View file

@ -187,7 +187,7 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId,
Assert(parent_rti == -1);
rte->relkind = RELKIND_PARTITIONED_TABLE;
rte->inh = true;
rte->inh = (nparts > 0);
HYPO_TAG_RTI(rel->relid, root);
}
else /* branch partition, expand it */
@ -199,6 +199,7 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId,
if(!rte->alias)
rte->alias = makeNode(Alias);
rte->alias->aliasname = branch->tablename;
rte->inh = (nparts > 0);
hypo_expand_single_inheritance_child(root, relationObjectId, rel,
parentrel, branch, rte, branch, firstpos, parent_rti, true);
@ -206,6 +207,8 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId,
firstpos++;
}
Assert(rte->inh == (nparts > 0));
/* add the partitioned table itself */
root->simple_rte_array[firstpos] = rte;
@ -214,6 +217,13 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId,
HYPO_TAG_RTI(firstpos, root);
/*
* if the table has no partition, we need to tell caller than it has to use
* the new position
*/
if (nparts == 0)
return firstpos + 1;
/*
* create RangeTblEntries and AppendRelInfos hypothetically
* for all hypothetical partitions
@ -2021,9 +2031,10 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root,
/*
* there's no need to estimate branch partitions pages and tuples, but
* we have to setup their partitioning data
* we have to setup their partitioning data if the partition has
* children
*/
if (part->partkey)
if (part->partkey && rte->inh)
{
hypo_set_relation_partition_info(root, rel, part);
return;

View file

@ -56,8 +56,7 @@ INSERT INTO part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (
-- Hypothetical tables
-- -------------------
-- 0. Dropping any hypothetical object
SELECT * FROM hypopg_reset_index();
SELECT * FROM hypopg_reset_table();
SELECT * FROM hypopg_reset();
-- 1. Range partition
DROP TABLE IF EXISTS hypo_part_range;
CREATE TABLE hypo_part_range (id integer, val text);
@ -263,3 +262,26 @@ EXPLAIN (COSTS OFF) WITH s AS (UPDATE foo SET id = 0 from part_range WHERE foo.i
EXPLAIN (COSTS OFF) WITH s AS (DELETE FROM foo USING hypo_part_range WHERE foo.id = hypo_part_range.id AND hypo_part_range.id = 42 RETURNING *) SELECT 1;
-- same but with real table
EXPLAIN (COSTS OFF) WITH s AS (DELETE FROM foo USING part_range WHERE foo.id = part_range.id AND part_range.id = 42 RETURNING *) SELECT 1;
-- childless partitioning
-- ======================
SELECT * FROM hypopg_reset();
DROP TABLE part_multi CASCADE;
CREATE TABLE part_multi(dpt smallint, dt date, val text) PARTITION BY LIST (dpt);
SELECT * FROM hypopg_partition_table('hypo_part_multi', 'PARTITION BY LIST (dpt)');
EXPLAIN (COSTS OFF) SELECT * FROM part_multi;
EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi;
CREATE TABLE part_multi_2 PARTITION OF part_multi FOR VALUES IN (2) PARTITION BY RANGE(dt);
CREATE TABLE part_multi_2_q1 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$);
CREATE TABLE part_multi_1 PARTITION OF part_multi FOR VALUES IN (1) PARTITION BY RANGE(dt);
CREATE TABLE part_multi_1_q1 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$) PARTITION BY RANGE (dt);
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2', 'PARTITION OF hypo_part_multi FOR VALUES IN (2)', 'PARTITION BY RANGE(dt)');
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q1', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)');
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1', 'PARTITION OF hypo_part_multi FOR VALUES IN (1)', 'PARTITION BY RANGE(dt)');
SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1', 'PARTITION OF hypo_part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)','PARTITION BY RANGE (dt)');
EXPLAIN (COSTS OFF) SELECT * FROM part_multi;
EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi;