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)
Foreign Scan
Output: t1.a, ftprt2_p1.b, ftprt2_p1.c
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)
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)
* A childless table is never considered to be an inheritance set. For
* regular inheritance, a parent RTE must always have at least two associated
* AppendRelInfos: one corresponding to the parent table as a simple member of
* inheritance set and one or more corresponding to the actual children.
* Since a partitioned table is not scanned, it might have only one associated
* AppendRelInfo.
* the inheritance set and one or more corresponding to the actual children.
* (But a partitioned table might have only one associated 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
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 */
if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
/*
* Partitioned table, so set up for partitioning.
*/
Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
if (root->glob->partition_directory == NULL)
......@@ -161,6 +165,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
}
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;
RangeTblEntry *childrte;
Index childRTindex;
......@@ -182,8 +191,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
}
/*
* This table has no partitions. Expand any plain inheritance
* children in the order the OIDs were returned by
* Expand inheritance children in the order the OIDs were returned by
* find_all_inheritors.
*/
foreach(l, inhOIDs)
......@@ -273,11 +281,6 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
root->partColsUpdated =
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
* non-inheritance case.
......@@ -288,6 +291,11 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
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++)
{
Oid childOID = partdesc->oids[i];
......@@ -321,8 +329,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
/*
* expand_single_inheritance_child
* Build a RangeTblEntry and an AppendRelInfo, if appropriate, plus
* maybe a PlanRowMark.
* Build a RangeTblEntry and an AppendRelInfo, plus maybe a PlanRowMark.
*
* We now expand the partition hierarchy level by level, creating a
* corresponding hierarchy of AppendRelInfos and RelOptInfos, where each
......@@ -371,9 +378,11 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
childrte->relid = childOID;
childrte->relkind = childrel->rd_rel->relkind;
/* A partitioned child will need to be expanded further. */
if (childOID != parentOID &&
childrte->relkind == RELKIND_PARTITIONED_TABLE)
if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
{
Assert(childOID != parentOID);
childrte->inh = true;
}
else
childrte->inh = false;
childrte->requiredPerms = 0;
......@@ -383,22 +392,16 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
*childRTindex_p = childRTindex;
/*
* We need an AppendRelInfo if paths will be built for the child RTE. If
* 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.
* Build an AppendRelInfo struct for each parent/child pair.
*/
if (childrte->relkind != RELKIND_PARTITIONED_TABLE || childrte->inh)
{
appinfo = make_append_rel_info(parentrel, childrel,
parentRTindex, childRTindex);
*appinfos = lappend(*appinfos, appinfo);
/*
* Translate the column permissions bitmaps to the child's attnums (we
* have to build the translated_vars list before we can do this). But
* if this is the parent table, leave copyObject's result alone.
* have to build the translated_vars list before we can do this). But if
* 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
* permissions checks on the child RTE. The insertedCols/updatedCols
......@@ -413,7 +416,6 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
childrte->updatedCols = translate_col_privs(parentrte->updatedCols,
appinfo->translated_vars);
}
}
/*
* Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
......
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