Commit e8d5dd6b authored by Tom Lane's avatar Tom Lane

Get rid of duplicate child RTE for a partitioned table.

We've been creating duplicate RTEs for partitioned tables just
because we do so for regular inheritance parent tables.  But unlike
regular-inheritance parents which are themselves regular tables
and thus need to be scanned, partitioned tables don't need the
extra RTE.

This makes the conditions for building a child RTE the same as those
for building an AppendRelInfo, allowing minor simplification in
expand_single_inheritance_child.  Since the planner's actual processing
is driven off the AppendRelInfo list, nothing much changes beyond that,
we just have one fewer useless RTE entry.

Amit Langote, reviewed and hacked a bit by me

Discussion: https://postgr.es/m/9d7c5112-cb99-6a47-d3be-cf1ee6862a1d@lab.ntt.co.jp
parent 1af25ca0
...@@ -8435,7 +8435,7 @@ SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) ...@@ -8435,7 +8435,7 @@ SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10)
Foreign Scan Foreign Scan
Output: t1.a, ftprt2_p1.b, ftprt2_p1.c Output: t1.a, ftprt2_p1.b, ftprt2_p1.c
Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2) Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
Remote SQL: SELECT r6.a, r9.b, r9.c FROM (public.fprt1_p1 r6 LEFT JOIN public.fprt2_p1 r9 ON (((r6.a = r9.b)) AND ((r6.b = r9.a)) AND ((r9.a < 10)))) WHERE ((r6.a < 10)) ORDER BY r6.a ASC NULLS LAST, r9.b ASC NULLS LAST, r9.c ASC NULLS LAST Remote SQL: SELECT r5.a, r7.b, r7.c FROM (public.fprt1_p1 r5 LEFT JOIN public.fprt2_p1 r7 ON (((r5.a = r7.b)) AND ((r5.b = r7.a)) AND ((r7.a < 10)))) WHERE ((r5.a < 10)) ORDER BY r5.a ASC NULLS LAST, r7.b ASC NULLS LAST, r7.c ASC NULLS LAST
(4 rows) (4 rows)
SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3;
......
...@@ -90,9 +90,10 @@ expand_inherited_tables(PlannerInfo *root) ...@@ -90,9 +90,10 @@ expand_inherited_tables(PlannerInfo *root)
* A childless table is never considered to be an inheritance set. For * A childless table is never considered to be an inheritance set. For
* regular inheritance, a parent RTE must always have at least two associated * regular inheritance, a parent RTE must always have at least two associated
* AppendRelInfos: one corresponding to the parent table as a simple member of * AppendRelInfos: one corresponding to the parent table as a simple member of
* inheritance set and one or more corresponding to the actual children. * the inheritance set and one or more corresponding to the actual children.
* Since a partitioned table is not scanned, it might have only one associated * (But a partitioned table might have only one associated AppendRelInfo,
* AppendRelInfo. * since it's not itself scanned and hence doesn't need a second RTE to
* represent itself as a member of the set.)
*/ */
static void static void
expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
...@@ -145,6 +146,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) ...@@ -145,6 +146,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
/* Scan the inheritance set and expand it */ /* Scan the inheritance set and expand it */
if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{ {
/*
* Partitioned table, so set up for partitioning.
*/
Assert(rte->relkind == RELKIND_PARTITIONED_TABLE); Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
if (root->glob->partition_directory == NULL) if (root->glob->partition_directory == NULL)
...@@ -161,6 +165,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) ...@@ -161,6 +165,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
} }
else else
{ {
/*
* Ordinary table, so process traditional-inheritance children. (Note
* that partitioned tables are not allowed to have inheritance
* children, so it's not possible for both cases to apply.)
*/
List *appinfos = NIL; List *appinfos = NIL;
RangeTblEntry *childrte; RangeTblEntry *childrte;
Index childRTindex; Index childRTindex;
...@@ -182,8 +191,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) ...@@ -182,8 +191,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
} }
/* /*
* This table has no partitions. Expand any plain inheritance * Expand inheritance children in the order the OIDs were returned by
* children in the order the OIDs were returned by
* find_all_inheritors. * find_all_inheritors.
*/ */
foreach(l, inhOIDs) foreach(l, inhOIDs)
...@@ -273,11 +281,6 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, ...@@ -273,11 +281,6 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
root->partColsUpdated = root->partColsUpdated =
has_partition_attrs(parentrel, parentrte->updatedCols, NULL); has_partition_attrs(parentrel, parentrte->updatedCols, NULL);
/* First expand the partitioned table itself. */
expand_single_inheritance_child(root, parentrte, parentRTindex, parentrel,
top_parentrc, parentrel,
appinfos, &childrte, &childRTindex);
/* /*
* If the partitioned table has no partitions, treat this as the * If the partitioned table has no partitions, treat this as the
* non-inheritance case. * non-inheritance case.
...@@ -288,6 +291,11 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, ...@@ -288,6 +291,11 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
return; return;
} }
/*
* Create a child RTE for each partition. Note that unlike traditional
* inheritance, we don't need a child RTE for the partitioned table
* itself, because it's not going to be scanned.
*/
for (i = 0; i < partdesc->nparts; i++) for (i = 0; i < partdesc->nparts; i++)
{ {
Oid childOID = partdesc->oids[i]; Oid childOID = partdesc->oids[i];
...@@ -321,8 +329,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, ...@@ -321,8 +329,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
/* /*
* expand_single_inheritance_child * expand_single_inheritance_child
* Build a RangeTblEntry and an AppendRelInfo, if appropriate, plus * Build a RangeTblEntry and an AppendRelInfo, plus maybe a PlanRowMark.
* maybe a PlanRowMark.
* *
* We now expand the partition hierarchy level by level, creating a * We now expand the partition hierarchy level by level, creating a
* corresponding hierarchy of AppendRelInfos and RelOptInfos, where each * corresponding hierarchy of AppendRelInfos and RelOptInfos, where each
...@@ -371,9 +378,11 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, ...@@ -371,9 +378,11 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
childrte->relid = childOID; childrte->relid = childOID;
childrte->relkind = childrel->rd_rel->relkind; childrte->relkind = childrel->rd_rel->relkind;
/* A partitioned child will need to be expanded further. */ /* A partitioned child will need to be expanded further. */
if (childOID != parentOID && if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
childrte->relkind == RELKIND_PARTITIONED_TABLE) {
Assert(childOID != parentOID);
childrte->inh = true; childrte->inh = true;
}
else else
childrte->inh = false; childrte->inh = false;
childrte->requiredPerms = 0; childrte->requiredPerms = 0;
...@@ -383,36 +392,29 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, ...@@ -383,36 +392,29 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
*childRTindex_p = childRTindex; *childRTindex_p = childRTindex;
/* /*
* We need an AppendRelInfo if paths will be built for the child RTE. If * Build an AppendRelInfo struct for each parent/child pair.
* childrte->inh is true, then we'll always need to generate append paths
* for it. If childrte->inh is false, we must scan it if it's not a
* partitioned table; but if it is a partitioned table, then it never has
* any data of its own and need not be scanned.
*/ */
if (childrte->relkind != RELKIND_PARTITIONED_TABLE || childrte->inh) appinfo = make_append_rel_info(parentrel, childrel,
{ parentRTindex, childRTindex);
appinfo = make_append_rel_info(parentrel, childrel, *appinfos = lappend(*appinfos, appinfo);
parentRTindex, childRTindex);
*appinfos = lappend(*appinfos, appinfo);
/* /*
* Translate the column permissions bitmaps to the child's attnums (we * Translate the column permissions bitmaps to the child's attnums (we
* have to build the translated_vars list before we can do this). But * have to build the translated_vars list before we can do this). But if
* if this is the parent table, leave copyObject's result alone. * this is the parent table, we can leave copyObject's result alone.
* *
* Note: we need to do this even though the executor won't run any * Note: we need to do this even though the executor won't run any
* permissions checks on the child RTE. The insertedCols/updatedCols * permissions checks on the child RTE. The insertedCols/updatedCols
* bitmaps may be examined for trigger-firing purposes. * bitmaps may be examined for trigger-firing purposes.
*/ */
if (childOID != parentOID) if (childOID != parentOID)
{ {
childrte->selectedCols = translate_col_privs(parentrte->selectedCols, childrte->selectedCols = translate_col_privs(parentrte->selectedCols,
appinfo->translated_vars); appinfo->translated_vars);
childrte->insertedCols = translate_col_privs(parentrte->insertedCols, childrte->insertedCols = translate_col_privs(parentrte->insertedCols,
appinfo->translated_vars); appinfo->translated_vars);
childrte->updatedCols = translate_col_privs(parentrte->updatedCols, childrte->updatedCols = translate_col_privs(parentrte->updatedCols,
appinfo->translated_vars); appinfo->translated_vars);
}
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment