Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e8d5dd6

Browse files
committed
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
1 parent 1af25ca commit e8d5dd6

File tree

2 files changed

+45
-43
lines changed

2 files changed

+45
-43
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8435,7 +8435,7 @@ SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10)
84358435
Foreign Scan
84368436
Output: t1.a, ftprt2_p1.b, ftprt2_p1.c
84378437
Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
8438-
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
8438+
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
84398439
(4 rows)
84408440

84418441
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;

src/backend/optimizer/util/inherit.c

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ expand_inherited_tables(PlannerInfo *root)
9090
* A childless table is never considered to be an inheritance set. For
9191
* regular inheritance, a parent RTE must always have at least two associated
9292
* AppendRelInfos: one corresponding to the parent table as a simple member of
93-
* inheritance set and one or more corresponding to the actual children.
94-
* Since a partitioned table is not scanned, it might have only one associated
95-
* AppendRelInfo.
93+
* the inheritance set and one or more corresponding to the actual children.
94+
* (But a partitioned table might have only one associated AppendRelInfo,
95+
* since it's not itself scanned and hence doesn't need a second RTE to
96+
* represent itself as a member of the set.)
9697
*/
9798
static void
9899
expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
@@ -145,6 +146,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
145146
/* Scan the inheritance set and expand it */
146147
if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
147148
{
149+
/*
150+
* Partitioned table, so set up for partitioning.
151+
*/
148152
Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
149153

150154
if (root->glob->partition_directory == NULL)
@@ -161,6 +165,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
161165
}
162166
else
163167
{
168+
/*
169+
* Ordinary table, so process traditional-inheritance children. (Note
170+
* that partitioned tables are not allowed to have inheritance
171+
* children, so it's not possible for both cases to apply.)
172+
*/
164173
List *appinfos = NIL;
165174
RangeTblEntry *childrte;
166175
Index childRTindex;
@@ -182,8 +191,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
182191
}
183192

184193
/*
185-
* This table has no partitions. Expand any plain inheritance
186-
* children in the order the OIDs were returned by
194+
* Expand inheritance children in the order the OIDs were returned by
187195
* find_all_inheritors.
188196
*/
189197
foreach(l, inhOIDs)
@@ -273,11 +281,6 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
273281
root->partColsUpdated =
274282
has_partition_attrs(parentrel, parentrte->updatedCols, NULL);
275283

276-
/* First expand the partitioned table itself. */
277-
expand_single_inheritance_child(root, parentrte, parentRTindex, parentrel,
278-
top_parentrc, parentrel,
279-
appinfos, &childrte, &childRTindex);
280-
281284
/*
282285
* If the partitioned table has no partitions, treat this as the
283286
* non-inheritance case.
@@ -288,6 +291,11 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
288291
return;
289292
}
290293

294+
/*
295+
* Create a child RTE for each partition. Note that unlike traditional
296+
* inheritance, we don't need a child RTE for the partitioned table
297+
* itself, because it's not going to be scanned.
298+
*/
291299
for (i = 0; i < partdesc->nparts; i++)
292300
{
293301
Oid childOID = partdesc->oids[i];
@@ -321,8 +329,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
321329

322330
/*
323331
* expand_single_inheritance_child
324-
* Build a RangeTblEntry and an AppendRelInfo, if appropriate, plus
325-
* maybe a PlanRowMark.
332+
* Build a RangeTblEntry and an AppendRelInfo, plus maybe a PlanRowMark.
326333
*
327334
* We now expand the partition hierarchy level by level, creating a
328335
* corresponding hierarchy of AppendRelInfos and RelOptInfos, where each
@@ -371,9 +378,11 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
371378
childrte->relid = childOID;
372379
childrte->relkind = childrel->rd_rel->relkind;
373380
/* A partitioned child will need to be expanded further. */
374-
if (childOID != parentOID &&
375-
childrte->relkind == RELKIND_PARTITIONED_TABLE)
381+
if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
382+
{
383+
Assert(childOID != parentOID);
376384
childrte->inh = true;
385+
}
377386
else
378387
childrte->inh = false;
379388
childrte->requiredPerms = 0;
@@ -383,36 +392,29 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
383392
*childRTindex_p = childRTindex;
384393

385394
/*
386-
* We need an AppendRelInfo if paths will be built for the child RTE. If
387-
* childrte->inh is true, then we'll always need to generate append paths
388-
* for it. If childrte->inh is false, we must scan it if it's not a
389-
* partitioned table; but if it is a partitioned table, then it never has
390-
* any data of its own and need not be scanned.
395+
* Build an AppendRelInfo struct for each parent/child pair.
391396
*/
392-
if (childrte->relkind != RELKIND_PARTITIONED_TABLE || childrte->inh)
393-
{
394-
appinfo = make_append_rel_info(parentrel, childrel,
395-
parentRTindex, childRTindex);
396-
*appinfos = lappend(*appinfos, appinfo);
397+
appinfo = make_append_rel_info(parentrel, childrel,
398+
parentRTindex, childRTindex);
399+
*appinfos = lappend(*appinfos, appinfo);
397400

398-
/*
399-
* Translate the column permissions bitmaps to the child's attnums (we
400-
* have to build the translated_vars list before we can do this). But
401-
* if this is the parent table, leave copyObject's result alone.
402-
*
403-
* Note: we need to do this even though the executor won't run any
404-
* permissions checks on the child RTE. The insertedCols/updatedCols
405-
* bitmaps may be examined for trigger-firing purposes.
406-
*/
407-
if (childOID != parentOID)
408-
{
409-
childrte->selectedCols = translate_col_privs(parentrte->selectedCols,
410-
appinfo->translated_vars);
411-
childrte->insertedCols = translate_col_privs(parentrte->insertedCols,
412-
appinfo->translated_vars);
413-
childrte->updatedCols = translate_col_privs(parentrte->updatedCols,
414-
appinfo->translated_vars);
415-
}
401+
/*
402+
* Translate the column permissions bitmaps to the child's attnums (we
403+
* have to build the translated_vars list before we can do this). But if
404+
* this is the parent table, we can leave copyObject's result alone.
405+
*
406+
* Note: we need to do this even though the executor won't run any
407+
* permissions checks on the child RTE. The insertedCols/updatedCols
408+
* bitmaps may be examined for trigger-firing purposes.
409+
*/
410+
if (childOID != parentOID)
411+
{
412+
childrte->selectedCols = translate_col_privs(parentrte->selectedCols,
413+
appinfo->translated_vars);
414+
childrte->insertedCols = translate_col_privs(parentrte->insertedCols,
415+
appinfo->translated_vars);
416+
childrte->updatedCols = translate_col_privs(parentrte->updatedCols,
417+
appinfo->translated_vars);
416418
}
417419

418420
/*

0 commit comments

Comments
 (0)