From a0b1b7c2eadaebd236c48d9017effdf7c20fafc4 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 30 Aug 2017 15:22:08 -0400 Subject: [PATCH 2/2] EIBO --- src/backend/optimizer/prep/prepunion.c | 126 ++++++++++++++++++++++++++------- src/test/regress/expected/insert.out | 4 +- 2 files changed, 104 insertions(+), 26 deletions(-) diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 870a4a6bfd..3f5138f54e 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -33,6 +33,7 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/sysattr.h" +#include "catalog/partition.h" #include "catalog/pg_inherits_fn.h" #include "catalog/pg_type.h" #include "miscadmin.h" @@ -100,6 +101,13 @@ static List *generate_append_tlist(List *colTypes, List *colCollations, static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist); static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti); +static void expand_partitions_recursively(PlannerInfo *root, + RangeTblEntry *rte, + Index rti, Relation oldrelation, + PlanRowMark *oldrc, PartitionDesc partdesc, + LOCKMODE lockmode, + bool *has_child, List **appinfos, + List **partitioned_child_rels); static void expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *rte, Index rti, Relation oldrelation, @@ -1461,37 +1469,62 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) /* Scan the inheritance set and expand it */ appinfos = NIL; has_child = false; - foreach(l, inhOIDs) + if (RelationGetPartitionDesc(oldrelation) != NULL) { - Oid childOID = lfirst_oid(l); - Relation newrelation; - - /* Open rel if needed; we already have required locks */ - if (childOID != parentOID) - newrelation = heap_open(childOID, NoLock); - else - newrelation = oldrelation; - /* - * It is possible that the parent table has children that are temp - * tables of other backends. We cannot safely access such tables - * (because of buffering issues), and the best thing to do seems to be - * to silently ignore them. + * If this table has partitions, recursively expand them in the order + * in which they appear in the PartitionDesc. But first, expand the + * parent itself. */ - if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation)) - { - heap_close(newrelation, lockmode); - continue; - } - expand_single_inheritance_child(root, rte, rti, oldrelation, oldrc, - newrelation, + oldrelation, &has_child, &appinfos, &partitioned_child_rels); + expand_partitions_recursively(root, rte, rti, oldrelation, oldrc, + RelationGetPartitionDesc(oldrelation), + lockmode, + &has_child, &appinfos, + &partitioned_child_rels); + } + else + { + /* + * This table has no partitions. Expand any plain inheritance + * children in the order the OIDs were returned by + * find_all_inheritors. + */ + foreach(l, inhOIDs) + { + Oid childOID = lfirst_oid(l); + Relation newrelation; - /* Close child relations, but keep locks */ - if (childOID != parentOID) - heap_close(newrelation, NoLock); + /* Open rel if needed; we already have required locks */ + if (childOID != parentOID) + newrelation = heap_open(childOID, NoLock); + else + newrelation = oldrelation; + + /* + * It is possible that the parent table has children that are temp + * tables of other backends. We cannot safely access such tables + * (because of buffering issues), and the best thing to do seems + * to be to silently ignore them. + */ + if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation)) + { + heap_close(newrelation, lockmode); + continue; + } + + expand_single_inheritance_child(root, rte, rti, oldrelation, oldrc, + newrelation, + &has_child, &appinfos, + &partitioned_child_rels); + + /* Close child relations, but keep locks */ + if (childOID != parentOID) + heap_close(newrelation, NoLock); + } } heap_close(oldrelation, NoLock); @@ -1532,6 +1565,51 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) root->append_rel_list = list_concat(root->append_rel_list, appinfos); } +static void +expand_partitions_recursively(PlannerInfo *root, RangeTblEntry *rte, + Index rti, Relation oldrelation, + PlanRowMark *oldrc, PartitionDesc partdesc, + LOCKMODE lockmode, + bool *has_child, List **appinfos, + List **partitioned_child_rels) +{ + int i; + + check_stack_depth(); + + for (i = 0; i < partdesc->nparts; i++) + { + Oid childOID = partdesc->oids[i]; + Relation newrelation; + + /* Open rel; we already have required locks */ + newrelation = heap_open(childOID, NoLock); + + /* As in expand_inherited_rtentry, skip non-local temp tables */ + if (RELATION_IS_OTHER_TEMP(newrelation)) + { + heap_close(newrelation, lockmode); + continue; + } + + expand_single_inheritance_child(root, rte, rti, oldrelation, oldrc, + newrelation, + has_child, appinfos, + partitioned_child_rels); + + /* If this child is itself partitioned, recurse */ + if (newrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + expand_partitions_recursively(root, rte, rti, oldrelation, oldrc, + RelationGetPartitionDesc(newrelation), + lockmode, + has_child, appinfos, + partitioned_child_rels); + + /* Close child relation, but keep locks */ + heap_close(newrelation, NoLock); + } +} + /* * expand_single_inheritance_child * Expand a single inheritance child, if needed. diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index a2d9469592..e159d62b66 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -278,12 +278,12 @@ select tableoid::regclass, * from list_parted; -------------+----+---- part_aa_bb | aA | part_cc_dd | cC | 1 - part_null | | 0 - part_null | | 1 part_ee_ff1 | ff | 1 part_ee_ff1 | EE | 1 part_ee_ff2 | ff | 11 part_ee_ff2 | EE | 10 + part_null | | 0 + part_null | | 1 (8 rows) -- some more tests to exercise tuple-routing with multi-level partitioning -- 2.11.0 (Apple Git-81)