diff --git a/expected/hypo_table.out b/expected/hypo_table.out index 5ea8e57..c81a055 100644 --- a/expected/hypo_table.out +++ b/expected/hypo_table.out @@ -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) + diff --git a/hypopg_table.c b/hypopg_table.c index 72f9159..29a9468 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -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; diff --git a/test/sql/hypo_table.sql b/test/sql/hypo_table.sql index 6c2980d..66ba065 100644 --- a/test/sql/hypo_table.sql +++ b/test/sql/hypo_table.sql @@ -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;