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

Commit c44c47a

Browse files
committed
Some preliminary refactoring towards partitionwise join.
Partitionwise join proposes add a concept of child join relations, which will have the same relationship with join relations as "other member" relations do with base relations. These relations will need some but not all of the handling that we currently have for join relations, and some but not all of the handling that we currently have for appendrels, since they are a mix of the two. Refactor a little bit so that the necessary bits of logic are exposed as separate functions. Ashutosh Bapat, reviewed and tested by Rajkumar Raghuwanshi and by me. Discussion: http://postgr.es/m/CAFjFpRfqotRR6cM3sooBHMHEVdkFfAZ6PyYg4GRZsoMuW08HjQ@mail.gmail.com
1 parent 60f826c commit c44c47a

File tree

3 files changed

+149
-73
lines changed

3 files changed

+149
-73
lines changed

src/backend/optimizer/path/allpaths.c

+42-10
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ static void subquery_push_qual(Query *subquery,
129129
static void recurse_push_qual(Node *setOp, Query *topquery,
130130
RangeTblEntry *rte, Index rti, Node *qual);
131131
static void remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel);
132+
static void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
133+
List *live_childrels);
132134

133135

134136
/*
@@ -1182,27 +1184,18 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
11821184
{
11831185
int parentRTindex = rti;
11841186
List *live_childrels = NIL;
1185-
List *subpaths = NIL;
1186-
bool subpaths_valid = true;
1187-
List *partial_subpaths = NIL;
1188-
bool partial_subpaths_valid = true;
1189-
List *all_child_pathkeys = NIL;
1190-
List *all_child_outers = NIL;
11911187
ListCell *l;
11921188

11931189
/*
11941190
* Generate access paths for each member relation, and remember the
1195-
* cheapest path for each one. Also, identify all pathkeys (orderings)
1196-
* and parameterizations (required_outer sets) available for the member
1197-
* relations.
1191+
* non-dummy children.
11981192
*/
11991193
foreach(l, root->append_rel_list)
12001194
{
12011195
AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
12021196
int childRTindex;
12031197
RangeTblEntry *childRTE;
12041198
RelOptInfo *childrel;
1205-
ListCell *lcp;
12061199

12071200
/* append_rel_list contains all append rels; ignore others */
12081201
if (appinfo->parent_relid != parentRTindex)
@@ -1237,6 +1230,45 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
12371230
* Child is live, so add it to the live_childrels list for use below.
12381231
*/
12391232
live_childrels = lappend(live_childrels, childrel);
1233+
}
1234+
1235+
/* Add paths to the "append" relation. */
1236+
add_paths_to_append_rel(root, rel, live_childrels);
1237+
}
1238+
1239+
1240+
/*
1241+
* add_paths_to_append_rel
1242+
* Generate paths for given "append" relation given the set of non-dummy
1243+
* child rels.
1244+
*
1245+
* The function collects all parameterizations and orderings supported by the
1246+
* non-dummy children. For every such parameterization or ordering, it creates
1247+
* an append path collecting one path from each non-dummy child with given
1248+
* parameterization or ordering. Similarly it collects partial paths from
1249+
* non-dummy children to create partial append paths.
1250+
*/
1251+
static void
1252+
add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
1253+
List *live_childrels)
1254+
{
1255+
List *subpaths = NIL;
1256+
bool subpaths_valid = true;
1257+
List *partial_subpaths = NIL;
1258+
bool partial_subpaths_valid = true;
1259+
List *all_child_pathkeys = NIL;
1260+
List *all_child_outers = NIL;
1261+
ListCell *l;
1262+
1263+
/*
1264+
* For every non-dummy child, remember the cheapest path. Also, identify
1265+
* all pathkeys (orderings) and parameterizations (required_outer sets)
1266+
* available for the non-dummy member relations.
1267+
*/
1268+
foreach(l, live_childrels)
1269+
{
1270+
RelOptInfo *childrel = lfirst(l);
1271+
ListCell *lcp;
12401272

12411273
/*
12421274
* If child has an unparameterized cheapest-total path, add that to

src/backend/optimizer/path/joinrels.c

+24-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ static bool is_dummy_rel(RelOptInfo *rel);
3232
static void mark_dummy_rel(RelOptInfo *rel);
3333
static bool restriction_is_constant_false(List *restrictlist,
3434
bool only_pushed_down);
35+
static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
36+
RelOptInfo *rel2, RelOptInfo *joinrel,
37+
SpecialJoinInfo *sjinfo, List *restrictlist);
3538

3639

3740
/*
@@ -724,6 +727,27 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
724727
return joinrel;
725728
}
726729

730+
/* Add paths to the join relation. */
731+
populate_joinrel_with_paths(root, rel1, rel2, joinrel, sjinfo,
732+
restrictlist);
733+
734+
bms_free(joinrelids);
735+
736+
return joinrel;
737+
}
738+
739+
/*
740+
* populate_joinrel_with_paths
741+
* Add paths to the given joinrel for given pair of joining relations. The
742+
* SpecialJoinInfo provides details about the join and the restrictlist
743+
* contains the join clauses and the other clauses applicable for given pair
744+
* of the joining relations.
745+
*/
746+
static void
747+
populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
748+
RelOptInfo *rel2, RelOptInfo *joinrel,
749+
SpecialJoinInfo *sjinfo, List *restrictlist)
750+
{
727751
/*
728752
* Consider paths using each rel as both outer and inner. Depending on
729753
* the join type, a provably empty outer or inner rel might mean the join
@@ -868,10 +892,6 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
868892
elog(ERROR, "unrecognized join type: %d", (int) sjinfo->jointype);
869893
break;
870894
}
871-
872-
bms_free(joinrelids);
873-
874-
return joinrel;
875895
}
876896

877897

src/backend/optimizer/util/relnode.c

+83-59
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
4949
static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
5050
List *joininfo_list,
5151
List *new_joininfo);
52+
static void set_foreign_rel_properties(RelOptInfo *joinrel,
53+
RelOptInfo *outer_rel, RelOptInfo *inner_rel);
54+
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
5255

5356

5457
/*
@@ -327,6 +330,82 @@ find_join_rel(PlannerInfo *root, Relids relids)
327330
return NULL;
328331
}
329332

333+
/*
334+
* set_foreign_rel_properties
335+
* Set up foreign-join fields if outer and inner relation are foreign
336+
* tables (or joins) belonging to the same server and assigned to the same
337+
* user to check access permissions as.
338+
*
339+
* In addition to an exact match of userid, we allow the case where one side
340+
* has zero userid (implying current user) and the other side has explicit
341+
* userid that happens to equal the current user; but in that case, pushdown of
342+
* the join is only valid for the current user. The useridiscurrent field
343+
* records whether we had to make such an assumption for this join or any
344+
* sub-join.
345+
*
346+
* Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
347+
* called for the join relation.
348+
*
349+
*/
350+
static void
351+
set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
352+
RelOptInfo *inner_rel)
353+
{
354+
if (OidIsValid(outer_rel->serverid) &&
355+
inner_rel->serverid == outer_rel->serverid)
356+
{
357+
if (inner_rel->userid == outer_rel->userid)
358+
{
359+
joinrel->serverid = outer_rel->serverid;
360+
joinrel->userid = outer_rel->userid;
361+
joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
362+
joinrel->fdwroutine = outer_rel->fdwroutine;
363+
}
364+
else if (!OidIsValid(inner_rel->userid) &&
365+
outer_rel->userid == GetUserId())
366+
{
367+
joinrel->serverid = outer_rel->serverid;
368+
joinrel->userid = outer_rel->userid;
369+
joinrel->useridiscurrent = true;
370+
joinrel->fdwroutine = outer_rel->fdwroutine;
371+
}
372+
else if (!OidIsValid(outer_rel->userid) &&
373+
inner_rel->userid == GetUserId())
374+
{
375+
joinrel->serverid = outer_rel->serverid;
376+
joinrel->userid = inner_rel->userid;
377+
joinrel->useridiscurrent = true;
378+
joinrel->fdwroutine = outer_rel->fdwroutine;
379+
}
380+
}
381+
}
382+
383+
/*
384+
* add_join_rel
385+
* Add given join relation to the list of join relations in the given
386+
* PlannerInfo. Also add it to the auxiliary hashtable if there is one.
387+
*/
388+
static void
389+
add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
390+
{
391+
/* GEQO requires us to append the new joinrel to the end of the list! */
392+
root->join_rel_list = lappend(root->join_rel_list, joinrel);
393+
394+
/* store it into the auxiliary hashtable if there is one. */
395+
if (root->join_rel_hash)
396+
{
397+
JoinHashEntry *hentry;
398+
bool found;
399+
400+
hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
401+
&(joinrel->relids),
402+
HASH_ENTER,
403+
&found);
404+
Assert(!found);
405+
hentry->join_rel = joinrel;
406+
}
407+
}
408+
330409
/*
331410
* build_join_rel
332411
* Returns relation entry corresponding to the union of two given rels,
@@ -425,46 +504,8 @@ build_join_rel(PlannerInfo *root,
425504
joinrel->joininfo = NIL;
426505
joinrel->has_eclass_joins = false;
427506

428-
/*
429-
* Set up foreign-join fields if outer and inner relation are foreign
430-
* tables (or joins) belonging to the same server and assigned to the same
431-
* user to check access permissions as. In addition to an exact match of
432-
* userid, we allow the case where one side has zero userid (implying
433-
* current user) and the other side has explicit userid that happens to
434-
* equal the current user; but in that case, pushdown of the join is only
435-
* valid for the current user. The useridiscurrent field records whether
436-
* we had to make such an assumption for this join or any sub-join.
437-
*
438-
* Otherwise these fields are left invalid, so GetForeignJoinPaths will
439-
* not be called for the join relation.
440-
*/
441-
if (OidIsValid(outer_rel->serverid) &&
442-
inner_rel->serverid == outer_rel->serverid)
443-
{
444-
if (inner_rel->userid == outer_rel->userid)
445-
{
446-
joinrel->serverid = outer_rel->serverid;
447-
joinrel->userid = outer_rel->userid;
448-
joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
449-
joinrel->fdwroutine = outer_rel->fdwroutine;
450-
}
451-
else if (!OidIsValid(inner_rel->userid) &&
452-
outer_rel->userid == GetUserId())
453-
{
454-
joinrel->serverid = outer_rel->serverid;
455-
joinrel->userid = outer_rel->userid;
456-
joinrel->useridiscurrent = true;
457-
joinrel->fdwroutine = outer_rel->fdwroutine;
458-
}
459-
else if (!OidIsValid(outer_rel->userid) &&
460-
inner_rel->userid == GetUserId())
461-
{
462-
joinrel->serverid = outer_rel->serverid;
463-
joinrel->userid = inner_rel->userid;
464-
joinrel->useridiscurrent = true;
465-
joinrel->fdwroutine = outer_rel->fdwroutine;
466-
}
467-
}
507+
/* Compute information relevant to the foreign relations. */
508+
set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
468509

469510
/*
470511
* Create a new tlist containing just the vars that need to be output from
@@ -532,25 +573,8 @@ build_join_rel(PlannerInfo *root,
532573
is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
533574
joinrel->consider_parallel = true;
534575

535-
/*
536-
* Add the joinrel to the query's joinrel list, and store it into the
537-
* auxiliary hashtable if there is one. NB: GEQO requires us to append
538-
* the new joinrel to the end of the list!
539-
*/
540-
root->join_rel_list = lappend(root->join_rel_list, joinrel);
541-
542-
if (root->join_rel_hash)
543-
{
544-
JoinHashEntry *hentry;
545-
bool found;
546-
547-
hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
548-
&(joinrel->relids),
549-
HASH_ENTER,
550-
&found);
551-
Assert(!found);
552-
hentry->join_rel = joinrel;
553-
}
576+
/* Add the joinrel to the PlannerInfo. */
577+
add_join_rel(root, joinrel);
554578

555579
/*
556580
* Also, if dynamic-programming join search is active, add the new joinrel

0 commit comments

Comments
 (0)