diff options
Diffstat (limited to 'src/backend/optimizer/path/joinrels.c')
-rw-r--r-- | src/backend/optimizer/path/joinrels.c | 106 |
1 files changed, 28 insertions, 78 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 9085e0a3934..9441999afb5 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.39 1999/08/16 02:17:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.40 2000/01/09 00:26:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,8 +35,6 @@ static List *new_join_tlist(List *tlist, int first_resdomno); static void build_joinrel_restrict_and_join(RelOptInfo *joinrel, List *joininfo_list, Relids join_relids); -static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, - RelOptInfo *inner_rel); /* * make_rels_by_joins @@ -207,19 +205,15 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel) * The list will be flattened out in update_rels_pathlist_for_joins(). */ joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL)); - joinrel->indexed = false; - joinrel->pages = 0; - joinrel->tuples = 0; - joinrel->size = 0; + joinrel->rows = 0; joinrel->width = 0; -/* joinrel->targetlist = NIL;*/ + joinrel->targetlist = NIL; joinrel->pathlist = NIL; joinrel->cheapestpath = (Path *) NULL; joinrel->pruneable = true; - joinrel->classlist = NULL; - joinrel->indexkeys = NULL; - joinrel->ordering = NULL; - joinrel->relam = InvalidOid; + joinrel->indexed = false; + joinrel->pages = 0; + joinrel->tuples = 0; joinrel->restrictinfo = NIL; joinrel->joininfo = NIL; joinrel->innerjoin = NIL; @@ -236,21 +230,22 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel) /* * Construct restrict and join clause lists for the new joinrel. + * + * nconc(listCopy(x), y) is an idiom for making a new list without + * changing either input list. */ build_joinrel_restrict_and_join(joinrel, - nconc(copyObject(outer_rel->joininfo), - copyObject(inner_rel->joininfo)), + nconc(listCopy(outer_rel->joininfo), + inner_rel->joininfo), nconc(listCopy(outer_rel->relids), - listCopy(inner_rel->relids))); - - set_joinrel_size(joinrel, outer_rel, inner_rel); + inner_rel->relids)); return joinrel; } /* * new_join_tlist - * Builds a join relations's target list by keeping those elements that + * Builds a join relation's target list by keeping those elements that * will be in the final target list and any other elements that are still * needed for future joins. For a target list entry to still be needed * for future joins, its 'joinlist' field must not be empty after removal @@ -311,18 +306,16 @@ new_join_tlist(List *tlist, * 'joininfo_list' is a list of joininfo nodes from the relations being joined * 'join_relids' is a list of all base relids in the new join relation * - * NB: the elements of joininfo_list have all been COPIED and so can safely - * be destructively modified and/or inserted in the new joinrel's lists. - * The amount of copying going on here is probably vastly excessive, - * since we copied the underlying clauses as well... + * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass + * up to the join relation. I believe this is no longer necessary, because + * RestrictInfo nodes are no longer context-dependent. Instead, just add + * the original nodes to the lists belonging to the join relation. */ static void build_joinrel_restrict_and_join(RelOptInfo *joinrel, List *joininfo_list, Relids join_relids) { - List *output_restrictinfo_list = NIL; - List *output_joininfo_list = NIL; List *xjoininfo; foreach(xjoininfo, joininfo_list) @@ -341,38 +334,25 @@ build_joinrel_restrict_and_join(RelOptInfo *joinrel, * Be careful to eliminate duplicates, since we will see the * same clauses arriving from both input relations... */ - output_restrictinfo_list = - LispUnion(output_restrictinfo_list, + joinrel->restrictinfo = + LispUnion(joinrel->restrictinfo, joininfo->jinfo_restrictinfo); } else { - JoinInfo *old_joininfo; - /* - * There might already be a JoinInfo with the same set of - * unjoined relids in output_joininfo_list; don't make a - * redundant entry. + * These clauses are still join clauses at this level, + * so find or make the appropriate JoinInfo item for the joinrel, + * and add the clauses to it (eliminating duplicates). */ - old_joininfo = joininfo_member(new_unjoined_relids, - output_joininfo_list); - if (old_joininfo) - { - old_joininfo->jinfo_restrictinfo = - LispUnion(old_joininfo->jinfo_restrictinfo, - joininfo->jinfo_restrictinfo); - } - else - { - joininfo->unjoined_relids = new_unjoined_relids; - output_joininfo_list = lcons(joininfo, - output_joininfo_list); - } + JoinInfo *new_joininfo; + + new_joininfo = find_joininfo_node(joinrel, new_unjoined_relids); + new_joininfo->jinfo_restrictinfo = + LispUnion(new_joininfo->jinfo_restrictinfo, + joininfo->jinfo_restrictinfo); } } - - joinrel->restrictinfo = output_restrictinfo_list; - joinrel->joininfo = output_joininfo_list; } /* @@ -424,36 +404,6 @@ get_cheapest_complete_rel(List *join_rel_list) return final_rel; } -static void -set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, - RelOptInfo *inner_rel) -{ - double dtuples; - int ntuples; - - /* avoid overflow ... probably, tuple estimates in RelOptInfo - * just ought to be double ... - */ - dtuples = (double) outer_rel->tuples * (double) inner_rel->tuples; - - if (joinrel->restrictinfo != NULL) - dtuples *= product_selec(joinrel->restrictinfo); - - if (dtuples >= MAXINT) /* avoid overflow */ - ntuples = MAXINT; - else - ntuples = (int) dtuples; - - /* - * I bet sizes less than 1 will screw up optimization so make the best - * case 1 instead of 0 - jolly - */ - if (ntuples < 1) - ntuples = 1; - - joinrel->tuples = ntuples; -} - /* * Subset-inclusion tests on integer lists. * |