diff options
Diffstat (limited to 'src/backend/optimizer/path/joinrels.c')
-rw-r--r-- | src/backend/optimizer/path/joinrels.c | 276 |
1 files changed, 86 insertions, 190 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 8c1bc06e680..df74130cfcb 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.26 1999/02/16 00:41:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.27 1999/02/18 00:49:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -31,12 +31,11 @@ bool _use_right_sided_plans_ = false; #endif -static List *new_joininfo_list(List *joininfo_list, List *join_relids); -static void add_superrels(RelOptInfo *rel, RelOptInfo *super_rel); -static bool nonoverlap_rels(RelOptInfo *rel1, RelOptInfo *rel2); +static List *new_joininfo_list(List *joininfo_list, Relids join_relids); static bool nonoverlap_sets(List *s1, List *s2); -static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, - JoinInfo *jinfo); +static bool is_subset(List *s1, List *s2); +static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, + RelOptInfo *inner_rel, JoinInfo *jinfo); /* * make_rels_by_joins @@ -100,53 +99,69 @@ make_rels_by_joins(Query *root, List *outer_rels) */ List * make_rels_by_clause_joins(Query *root, RelOptInfo *outer_rel, - List *joininfo_list, List *only_relids) + List *joininfo_list, Relids only_relids) { List *join_list = NIL; List *i = NIL; foreach(i, joininfo_list) - { + { JoinInfo *joininfo = (JoinInfo *) lfirst(i); RelOptInfo *rel; + Relids unjoined_relids = joininfo->unjoined_relids; - if (!joininfo->bushy_inactive) + if (unjoined_relids != NIL) { - List *unjoined_rels = joininfo->unjoined_rels; - - if (unjoined_rels != NIL) + if (length(unjoined_relids) == 1 && + (only_relids == NIL || + /* geqo only wants certain relids to make new rels */ + intMember(lfirsti(unjoined_relids), only_relids))) { - if (length(unjoined_rels) == 1 && - (only_relids == NIL || - /* geqo only wants certain relids to make new rels */ - same(joininfo->unjoined_rels, only_relids))) + rel = make_join_rel(outer_rel, + get_base_rel(root, lfirsti(unjoined_relids)), + joininfo); + join_list = lappend(join_list, rel); + + /* Right-sided plan */ + if (_use_right_sided_plans_ && + length(outer_rel->relids) > 1) { - rel = make_join_rel(outer_rel, - get_base_rel(root, lfirsti(unjoined_rels)), + rel = make_join_rel( + get_base_rel(root, lfirsti(unjoined_relids)), + outer_rel, joininfo); - /* how about right-sided plan ? */ - if (_use_right_sided_plans_ && - length(outer_rel->relids) > 1) + join_list = lappend(join_list, rel); + } + } + + if (BushyPlanFlag && only_relids == NIL) /* no bushy from geqo */ + { + List *r; + + foreach(r, root->join_rel_list) + { + RelOptInfo *join_rel = lfirst(r); + + Assert(length(join_rel->relids) > 1); + if (is_subset(unjoined_relids, join_rel->relids) && + nonoverlap_sets(outer_rel->relids, join_rel->relids)) { - if (rel != NULL) + rel = make_join_rel(outer_rel, + join_rel, + joininfo); + join_list = lappend(join_list, rel); + + /* Right-sided plan */ + if (_use_right_sided_plans_ && + length(outer_rel->relids) > 1) + { + rel = make_join_rel(join_rel, + outer_rel, + joininfo); join_list = lappend(join_list, rel); - rel = make_join_rel(get_base_rel(root, - lfirsti(unjoined_rels)), - outer_rel, - joininfo); + } } } - else if (BushyPlanFlag) - { - rel = make_join_rel(outer_rel, - get_join_rel(root, unjoined_rels), - joininfo); - } - else - rel = NULL; - - if (rel != NULL) - join_list = lappend(join_list, rel); } } } @@ -172,7 +187,7 @@ make_rels_by_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels) foreach(i, inner_rels) { inner_rel = (RelOptInfo *) lfirst(i); - if (nonoverlap_rels(inner_rel, outer_rel)) + if (nonoverlap_sets(inner_rel->relids, outer_rel->relids)) { t_list = lappend(t_list, make_join_rel(outer_rel, @@ -229,11 +244,10 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo) joinrel->restrictinfo = NIL; joinrel->joininfo = NULL; joinrel->innerjoin = NIL; - joinrel->superrels = NIL; /* * This function uses a trick to pass inner/outer rels as - * different lists, and then flattens it out later. + * different lists, and then flattens it out later. bjm */ joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL)); @@ -241,13 +255,10 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo) joinrel->targetlist = new_outer_tlist; if (joininfo) - { joinrel->restrictinfo = joininfo->jinfo_restrictinfo; - if (BushyPlanFlag) - joininfo->bushy_inactive = true; - } - joinrel_joininfo_list = new_joininfo_list(append(outer_rel->joininfo, inner_rel->joininfo), + joinrel_joininfo_list = new_joininfo_list(append(outer_rel->joininfo, + inner_rel->joininfo), intAppend(outer_rel->relids, inner_rel->relids)); joinrel->joininfo = joinrel_joininfo_list; @@ -275,7 +286,7 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo) */ List * new_join_tlist(List *tlist, - List *other_relids, + Relids other_relids, int first_resdomno) { int resdomno = first_resdomno - 1; @@ -293,8 +304,7 @@ new_join_tlist(List *tlist, if (in_final_tlist) { resdomno += 1; - t_list = lappend(t_list, - create_tl_element(get_expr(xtl), resdomno)); + t_list = lappend(t_list,create_tl_element(get_expr(xtl), resdomno)); } } @@ -320,10 +330,10 @@ new_join_tlist(List *tlist, * Returns a list of joininfo nodes, new and old. */ static List * -new_joininfo_list(List *joininfo_list, List *join_relids) +new_joininfo_list(List *joininfo_list, Relids join_relids) { List *current_joininfo_list = NIL; - List *new_unjoined_rels = NIL; + Relids new_unjoined_relids = NIL; JoinInfo *other_joininfo = (JoinInfo *) NULL; List *xjoininfo = NIL; @@ -332,31 +342,31 @@ new_joininfo_list(List *joininfo_list, List *join_relids) List *or; JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - new_unjoined_rels = joininfo->unjoined_rels; - foreach(or, new_unjoined_rels) + new_unjoined_relids = joininfo->unjoined_relids; + foreach(or, new_unjoined_relids) { if (intMember(lfirsti(or), join_relids)) - new_unjoined_rels = lremove((void *) lfirst(or), new_unjoined_rels); + new_unjoined_relids = lremove((void *) lfirst(or), new_unjoined_relids); } - joininfo->unjoined_rels = new_unjoined_rels; - if (new_unjoined_rels != NIL) + joininfo->unjoined_relids = new_unjoined_relids; + if (new_unjoined_relids != NIL) { - other_joininfo = joininfo_member(new_unjoined_rels, + other_joininfo = joininfo_member(new_unjoined_relids, current_joininfo_list); if (other_joininfo) { - other_joininfo->jinfo_restrictinfo = (List *) LispUnion(joininfo->jinfo_restrictinfo, - other_joininfo->jinfo_restrictinfo); + other_joininfo->jinfo_restrictinfo = (List *) + LispUnion(joininfo->jinfo_restrictinfo, + other_joininfo->jinfo_restrictinfo); } else { other_joininfo = makeNode(JoinInfo); - other_joininfo->unjoined_rels = joininfo->unjoined_rels; + other_joininfo->unjoined_relids = joininfo->unjoined_relids; other_joininfo->jinfo_restrictinfo = joininfo->jinfo_restrictinfo; other_joininfo->mergejoinable = joininfo->mergejoinable; other_joininfo->hashjoinable = joininfo->hashjoinable; - other_joininfo->bushy_inactive = false; current_joininfo_list = lcons(other_joininfo, current_joininfo_list); @@ -368,105 +378,6 @@ new_joininfo_list(List *joininfo_list, List *join_relids) } /* - * add_rel_to_rel_joininfos - * For each new join relation, create new joininfos that - * use the join relation as inner relation, and add - * the new joininfos to those rel nodes that still - * have joins with the join relation. - * - * 'joinrels' is a list of join relations. - * - * Modifies the joininfo field of appropriate rel nodes. - */ -void -add_rel_to_rel_joininfos(Query *root, List *joinrels, List *outerrels) -{ - List *xjoinrel = NIL; - List *xrelid = NIL; - List *xrel = NIL; - List *xjoininfo = NIL; - - foreach(xjoinrel, joinrels) - { - RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel); - - foreach(xrelid, joinrel->relids) - { - Relid relid = (Relid) lfirst(xrelid); - RelOptInfo *rel = get_join_rel(root, relid); - - add_superrels(rel, joinrel); - } - } - foreach(xjoinrel, joinrels) - { - RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel); - - foreach(xjoininfo, joinrel->joininfo) - { - JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - List *unjoined_rels = joininfo->unjoined_rels; - List *restrict_info = joininfo->jinfo_restrictinfo; - bool mergejoinable = joininfo->mergejoinable; - bool hashjoinable = joininfo->hashjoinable; - - foreach(xrelid, unjoined_rels) - { - Relid relid = (Relid) lfirst(xrelid); - RelOptInfo *rel = get_join_rel(root, relid); - List *super_rels = rel->superrels; - List *xsuper_rel = NIL; - JoinInfo *new_joininfo = makeNode(JoinInfo); - - new_joininfo->unjoined_rels = joinrel->relids; - new_joininfo->jinfo_restrictinfo = restrict_info; - new_joininfo->mergejoinable = mergejoinable; - new_joininfo->hashjoinable = hashjoinable; - new_joininfo->bushy_inactive = false; - rel->joininfo = lappend(rel->joininfo, new_joininfo); - - foreach(xsuper_rel, super_rels) - { - RelOptInfo *super_rel = (RelOptInfo *) lfirst(xsuper_rel); - - if (nonoverlap_rels(super_rel, joinrel)) - { - List *new_relids = super_rel->relids; - JoinInfo *other_joininfo = joininfo_member(new_relids, - joinrel->joininfo); - - if (other_joininfo) - { - other_joininfo->jinfo_restrictinfo = (List *) LispUnion(restrict_info, - other_joininfo->jinfo_restrictinfo); - } - else - { - JoinInfo *new_joininfo = makeNode(JoinInfo); - - new_joininfo->unjoined_rels = new_relids; - new_joininfo->jinfo_restrictinfo = restrict_info; - new_joininfo->mergejoinable = mergejoinable; - new_joininfo->hashjoinable = hashjoinable; - new_joininfo->bushy_inactive = false; - joinrel->joininfo = lappend(joinrel->joininfo, - new_joininfo); - } - } - } - } - } - } - - foreach(xrel, outerrels) - { - RelOptInfo *rel = (RelOptInfo *) lfirst(xrel); - - rel->superrels = NIL; - } -} - -/* * get_cheapest_complete_rel * Find the join relation that includes all the original * relations, i.e. the final join result. @@ -482,8 +393,8 @@ get_cheapest_complete_rel(List *join_rel_list) RelOptInfo *final_rel = NULL; /* - * find the relations that has no further joins, i.e., its joininfos - * all have unjoined_rels nil. + * find the relations that have no further joins, i.e., its joininfos + * all have unjoined_relids nil. */ foreach(xrel, join_rel_list) { @@ -495,7 +406,7 @@ get_cheapest_complete_rel(List *join_rel_list) { JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - if (joininfo->unjoined_rels != NIL) + if (joininfo->unjoined_relids != NIL) { final = false; break; @@ -510,38 +421,23 @@ get_cheapest_complete_rel(List *join_rel_list) return final_rel; } -/* - * add_superrels - * add rel to the temporary property list superrels. - * - * 'rel' a rel node - * 'super_rel' rel node of a join relation that includes rel - * - * Modifies the superrels field of rel - */ -static void -add_superrels(RelOptInfo *rel, RelOptInfo *super_rel) -{ - rel->superrels = lappend(rel->superrels, super_rel); -} - -/* - * nonoverlap_rels - * test if two join relations overlap, i.e., includes the same - * relation. - * - * 'rel1' and 'rel2' are two join relations - * - * Returns non-nil if rel1 and rel2 do not overlap. - */ static bool -nonoverlap_rels(RelOptInfo *rel1, RelOptInfo *rel2) +nonoverlap_sets(List *s1, List *s2) { - return nonoverlap_sets(rel1->relids, rel2->relids); + List *x = NIL; + + foreach(x, s1) + { + int e = lfirsti(x); + + if (intMember(e, s2)) + return false; + } + return true; } static bool -nonoverlap_sets(List *s1, List *s2) +is_subset(List *s1, List *s2) { List *x = NIL; @@ -549,7 +445,7 @@ nonoverlap_sets(List *s1, List *s2) { int e = lfirsti(x); - if (intMember(e, s2)) + if (!intMember(e, s2)) return false; } return true; |