From 8f5a19363e7a277e33aaac617f0e15d80b8aa76e Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 19 Dec 2018 10:44:29 -0500 Subject: [PATCH] Adapt optimizer. --- src/backend/optimizer/prep/prepunion.c | 85 +++++++++++--------------- src/backend/optimizer/util/plancat.c | 6 +- src/include/nodes/relation.h | 4 ++ 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index da278f785e..16f5889d65 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -48,6 +48,7 @@ #include "optimizer/tlist.h" #include "parser/parse_coerce.h" #include "parser/parsetree.h" +#include "partitioning/partdir.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/selfuncs.h" @@ -104,8 +105,7 @@ static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, static void expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, - PlanRowMark *top_parentrc, LOCKMODE lockmode, - List **appinfos); + PlanRowMark *top_parentrc, List **appinfos); static void expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, @@ -1518,7 +1518,6 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) Oid parentOID; PlanRowMark *oldrc; Relation oldrelation; - LOCKMODE lockmode; List *inhOIDs; ListCell *l; @@ -1541,37 +1540,13 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) } /* - * The rewriter should already have obtained an appropriate lock on each - * relation named in the query. However, for each child relation we add - * to the query, we must obtain an appropriate lock, because this will be - * the first use of those relations in the parse/rewrite/plan pipeline. - * Child rels should use the same lockmode as their parent. - */ - lockmode = rte->rellockmode; - - /* Scan for all members of inheritance set, acquire needed locks */ - inhOIDs = find_all_inheritors(parentOID, lockmode, NULL); - - /* - * Check that there's at least one descendant, else treat as no-child - * case. This could happen despite above has_subclass() check, if table - * once had a child but no longer does. - */ - if (list_length(inhOIDs) < 2) - { - /* Clear flag before returning */ - rte->inh = false; - return; - } - - /* - * If parent relation is selected FOR UPDATE/SHARE, we need to mark its - * PlanRowMark as isParent = true, and generate a new PlanRowMark for each - * child. + * If parent relation is selected FOR UPDATE/SHARE, we will need to mark + * its PlanRowMark as isParent = true, and generate a new PlanRowMark for + * each child. expand_single_inheritance_child() will handle this, but we + * need to pass down the rowmark for the original parent to make it + * possible. */ oldrc = get_plan_rowmark(root->rowMarks, rti); - if (oldrc) - oldrc->isParent = true; /* * Must open the parent relation to examine its tupdesc. We need not lock @@ -1584,13 +1559,16 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) { Assert(rte->relkind == RELKIND_PARTITIONED_TABLE); + if (root->partition_directory == NULL) + root->partition_directory = CreatePartitionDirectory(CurrentMemoryContext); + /* * If this table has partitions, recursively expand them in the order * in which they appear in the PartitionDesc. While at it, also * extract the partition key columns of all the partitioned tables. */ expand_partitioned_rtentry(root, rte, rti, oldrelation, oldrc, - lockmode, &root->append_rel_list); + &root->append_rel_list); } else { @@ -1598,9 +1576,12 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) RangeTblEntry *childrte; Index childRTindex; + /* Scan for all members of inheritance set, acquire needed locks */ + inhOIDs = find_all_inheritors(parentOID, rte->rellockmode, NULL); + /* - * This table has no partitions. Expand any plain inheritance - * children in the order the OIDs were returned by + * This is not a partitioned table, but it has plain inheritance + * children. Expand them in the order that the OIDs were returned by * find_all_inheritors. */ foreach(l, inhOIDs) @@ -1622,7 +1603,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) */ if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation)) { - heap_close(newrelation, lockmode); + heap_close(newrelation, rte->rellockmode); continue; } @@ -1637,11 +1618,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) } /* - * If all the children were temp tables, pretend it's a - * non-inheritance situation; we don't need Append node in that case. - * The duplicate RTE we added for the parent table is harmless, so we - * don't bother to get rid of it; ditto for the useless PlanRowMark - * node. + * If all the children were temp tables, or there were none, pretend + * it's a non-inheritance situation; we don't need Append node in that + * case. The duplicate RTE we added for the parent table is harmless, + * so we don't bother to get rid of it; ditto for the useless + * PlanRowMark node. */ if (list_length(appinfos) < 2) rte->inh = false; @@ -1661,16 +1642,17 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) static void expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, - PlanRowMark *top_parentrc, LOCKMODE lockmode, - List **appinfos) + PlanRowMark *top_parentrc, List **appinfos) { int i; RangeTblEntry *childrte; Index childRTindex; - PartitionDesc partdesc = RelationGetPartitionDesc(parentrel); + PartitionDesc partdesc; check_stack_depth(); + partdesc = PartitionDirectoryLookup(root->partition_directory, parentrel); + /* A partitioned table should always have a partition descriptor. */ Assert(partdesc); @@ -1707,8 +1689,8 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, Oid childOID = partdesc->oids[i]; Relation childrel; - /* Open rel; we already have required locks */ - childrel = heap_open(childOID, NoLock); + /* Open and lock child rel */ + childrel = heap_open(childOID, parentrte->rellockmode); /* * Temporary partitions belonging to other sessions should have been @@ -1725,8 +1707,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, /* If this child is itself partitioned, recurse */ if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) expand_partitioned_rtentry(root, childrte, childRTindex, - childrel, top_parentrc, lockmode, - appinfos); + childrel, top_parentrc, appinfos); /* Close child relation, but keep locks */ heap_close(childrel, NoLock); @@ -1862,6 +1843,14 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, /* Include child's rowmark type in top parent's allMarkTypes */ top_parentrc->allMarkTypes |= childrc->allMarkTypes; + /* + * If we create at least one child rowmark, isParent should be set + * on the original rowmark. That's very cheap, so just do it here + * unconditionally without worrying about whether it has been done + * previously. + */ + top_parentrc->isParent = true; + root->rowMarks = lappend(root->rowMarks, childrc); } } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index a570ac0aab..f0e5ef070f 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -39,6 +39,7 @@ #include "optimizer/predtest.h" #include "optimizer/prep.h" #include "partitioning/partbounds.h" +#include "partitioning/partdir.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" @@ -1903,7 +1904,10 @@ set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel, Assert(relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); - partdesc = RelationGetPartitionDesc(relation); + /* shouldn't reach here unless expand_inherited_rtentry initialized this */ + Assert(root->partition_directory != NULL); + + partdesc = PartitionDirectoryLookup(root->partition_directory, relation); partkey = RelationGetPartitionKey(relation); rel->part_scheme = find_partition_scheme(root, relation); Assert(partdesc != NULL && rel->part_scheme != NULL); diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 6fd24203dd..bcf2054838 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -19,6 +19,7 @@ #include "lib/stringinfo.h" #include "nodes/params.h" #include "nodes/parsenodes.h" +#include "partitioning/partdefs.h" #include "storage/block.h" @@ -343,6 +344,9 @@ typedef struct PlannerInfo /* Does this query modify any partition key columns? */ bool partColsUpdated; + + /* Partition directory. */ + PartitionDirectory partition_directory; } PlannerInfo; -- 2.39.5