diff options
Diffstat (limited to 'src/backend/optimizer/geqo/geqo_eval.c')
-rw-r--r-- | src/backend/optimizer/geqo/geqo_eval.c | 549 |
1 files changed, 12 insertions, 537 deletions
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 00dbffa4ea3..a109ecc48ef 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: geqo_eval.c,v 1.31 1999/02/15 02:04:58 tgl Exp $ + * $Id: geqo_eval.c,v 1.32 1999/02/15 03:22:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,15 +47,7 @@ #include "optimizer/geqo_gene.h" #include "optimizer/geqo.h" -#include "optimizer/geqo_paths.h" - -static List *gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel); -static RelOptInfo *gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel); -static RelOptInfo *init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo); -static List *new_join_tlist(List *tlist, List *other_relids, int first_resdomno); -static List *new_joininfo_list(List *joininfo_list, List *join_relids); -static void geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel); static RelOptInfo *geqo_nth(int stop, List *rels); /* @@ -123,15 +115,18 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out } else { /* tree main part */ - - if (!(new_rels = gimme_clause_joins(root, outer_rel, inner_rel))) + if (!(new_rels = make_rels_by_clause_joins(root, outer_rel, + inner_rel->joininfo, + inner_rel->relids))) { +#ifdef NOT_USED if (BushyPlanFlag) - { - new_rels = lcons(gimme_clauseless_join(outer_rel, outer_rel), NIL); /* ??? MAU */ - } + new_rels = make_rels_by_clauseless_joins(outer_rel, + lcons(outer_rel,NIL)); else - new_rels = lcons(gimme_clauseless_join(outer_rel, inner_rel), NIL); +#endif + new_rels = make_rels_by_clauseless_joins(outer_rel, + lcons(inner_rel,NIL)); } /* process new_rel->pathlist */ @@ -150,7 +145,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out * not possible */ if (length(new_rels) > 1) - new_rels = geqo_prune_rels(new_rels); + merge_rels_with_same_relids(new_rels); if (length(new_rels) > 1) { /* should never be reached ... */ @@ -161,7 +156,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out new_rel = (RelOptInfo *) lfirst(new_rels); rel_count++; - geqo_set_cheapest(new_rel); + set_cheapest(new_rel, new_rel->pathlist); /* processing of other new_rel attributes */ if (new_rel->size <= 0) @@ -178,526 +173,6 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out return outer_rel; /* tree finished ... */ } -/* - * gimme_clause_joins - * - * 'outer_rel' is the relation entry for the outer relation - * 'inner_rel' is the relation entry for the inner relation - * - * Returns a list of new join relations. - */ - -static List * -gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel) -{ - List *join_list = NIL; - List *i = NIL; - List *joininfo_list = (List *) outer_rel->joininfo; - - foreach(i, joininfo_list) - { - JoinInfo *joininfo = (JoinInfo *) lfirst(i); - RelOptInfo *rel = NULL; - - if (!joininfo->inactive) - { - List *other_rels = (List *) joininfo->otherrels; - - if (other_rels != NIL) - { - if ((length(other_rels) == 1)) - { - - if (same(other_rels, inner_rel->relids)) - { /* look if inner_rel is it... */ - rel = init_join_rel(outer_rel, inner_rel, joininfo); - } - } - else if (BushyPlanFlag) - { /* ?!? MAU */ - rel = init_join_rel(outer_rel, get_join_rel(root, other_rels), joininfo); - } - else - rel = NULL; - - if (rel != NULL) - join_list = lappend(join_list, rel); - - } - } - } - - return join_list; -} - -/* - * gimme_clauseless_join - * Given an outer relation 'outer_rel' and an inner relation - * 'inner_rel', create a join relation between 'outer_rel' and 'inner_rel' - * - * Returns a new join relation. - */ - -static RelOptInfo * -gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel) -{ - return init_join_rel(outer_rel, inner_rel, (JoinInfo *) NULL); -} - -/* - * init_join_rel - * Creates and initializes a new join relation. - * - * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be - * joined - * 'joininfo' is the joininfo node(join clause) containing both - * 'outer_rel' and 'inner_rel', if any exists - * - * Returns the new join relation node. - */ -static RelOptInfo * -init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo) -{ - RelOptInfo *joinrel = makeNode(RelOptInfo); - List *joinrel_joininfo_list = NIL; - List *new_outer_tlist; - List *new_inner_tlist; - - /* - * Create a new tlist by removing irrelevant elements from both tlists - * of the outer and inner join relations and then merging the results - * together. - */ - new_outer_tlist = new_join_tlist(outer_rel->targetlist, /* XXX 1-based attnos */ - inner_rel->relids, 1); - new_inner_tlist = new_join_tlist(inner_rel->targetlist, /* XXX 1-based attnos */ - outer_rel->relids, - length(new_outer_tlist) + 1); - - joinrel->relids = NIL; - joinrel->indexed = false; - joinrel->pages = 0; - joinrel->tuples = 0; - joinrel->width = 0; -/* joinrel->targetlist = NIL;*/ - joinrel->pathlist = NIL; - joinrel->cheapestpath = (Path *) NULL; - joinrel->pruneable = true; - joinrel->classlist = NULL; - joinrel->relam = InvalidOid; - joinrel->ordering = NULL; - joinrel->restrictinfo = NIL; - joinrel->joininfo = NULL; - joinrel->innerjoin = NIL; - joinrel->superrels = NIL; - - joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL)); - - new_outer_tlist = nconc(new_outer_tlist, new_inner_tlist); - joinrel->targetlist = new_outer_tlist; - - if (joininfo) - { - joinrel->restrictinfo = joininfo->jinfo_restrictinfo; - if (BushyPlanFlag) - joininfo->inactive = true; - } - - 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; - - geqo_joinrel_size(joinrel, outer_rel, inner_rel); - - return joinrel; -} - -/* - * new_join_tlist - * Builds a join relations'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 - * of all relids in 'other_relids'. - * - * 'tlist' is the target list of one of the join relations - * 'other_relids' is a list of relids contained within the other - * join relation - * 'first_resdomno' is the resdom number to use for the first created - * target list entry - * - * Returns the new target list. - */ -static List * -new_join_tlist(List *tlist, - List *other_relids, - int first_resdomno) -{ - int resdomno = first_resdomno - 1; - TargetEntry *xtl = NULL; - List *t_list = NIL; - List *i = NIL; - List *join_list = NIL; - bool in_final_tlist = false; - - foreach(i, tlist) - { - xtl = lfirst(i); - /* XXX surely this is wrong? join_list is never changed? tgl 2/99 */ - in_final_tlist = (join_list == NIL); - if (in_final_tlist) - { - resdomno += 1; - t_list = lappend(t_list, - create_tl_element(get_expr(xtl), resdomno)); - } - } - - return t_list; -} - -/* - * new_joininfo_list - * Builds a join relation's joininfo list by checking for join clauses - * which still need to used in future joins involving this relation. A - * join clause is still needed if there are still relations in the clause - * not contained in the list of relations comprising this join relation. - * New joininfo nodes are only created and added to - * 'current_joininfo_list' if a node for a particular join hasn't already - * been created. - * - * 'current_joininfo_list' contains a list of those joininfo nodes that - * have already been built - * 'joininfo_list' is the list of join clauses involving this relation - * 'join_relids' is a list of relids corresponding to the relations - * currently being joined - * - * Returns a list of joininfo nodes, new and old. - */ -static List * -new_joininfo_list(List *joininfo_list, List *join_relids) -{ - List *current_joininfo_list = NIL; - List *new_otherrels = NIL; - JoinInfo *other_joininfo = (JoinInfo *) NULL; - List *xjoininfo = NIL; - - foreach(xjoininfo, joininfo_list) - { - List *or; - JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - - new_otherrels = joininfo->otherrels; - foreach(or, new_otherrels) - { - if (intMember(lfirsti(or), join_relids)) - new_otherrels = lremove((void *) lfirst(or), new_otherrels); - } - joininfo->otherrels = new_otherrels; - if (new_otherrels != NIL) - { - other_joininfo = joininfo_member(new_otherrels, - current_joininfo_list); - if (other_joininfo) - { - other_joininfo->jinfo_restrictinfo = - (List *) LispUnion(joininfo->jinfo_restrictinfo, - other_joininfo->jinfo_restrictinfo); - } - else - { - other_joininfo = makeNode(JoinInfo); - - other_joininfo->otherrels = joininfo->otherrels; - other_joininfo->jinfo_restrictinfo = joininfo->jinfo_restrictinfo; - other_joininfo->mergejoinable = joininfo->mergejoinable; - other_joininfo->hashjoinable = joininfo->hashjoinable; - other_joininfo->inactive = false; - - current_joininfo_list = lcons(other_joininfo, - current_joininfo_list); - } - } - } - - return current_joininfo_list; -} - -#ifdef NOTUSED -/* - * add_new_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. - */ -static void -geqo_add_new_joininfos(Query *root, List *joinrels, List *outerrels) -{ - List *xjoinrel = NIL; - List *xrelid = NIL; - List *xrel = NIL; - List *xjoininfo = NIL; - - RelOptInfo *rel; - List *relids; - - List *super_rels; - List *xsuper_rel = NIL; - JoinInfo *new_joininfo; - - foreach(xjoinrel, joinrels) - { - RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel); - - foreach(xrelid, joinrel->relids) - { - - /* - * length(joinrel->relids) should always be greater that 1, - * because of *JOIN* - */ - - /* - * ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid); RelOptInfo - * *rel = get_join_rel(root, relid); - */ - - /* - * if ( (root->join_rel_list) != NIL ) { rel = - * get_join_rel(root, xrelid); } else { rel = - * get_base_rel(root, lfirsti(xrelid)); } - */ - - /* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */ - - /* - * relids = lconsi(lfirsti(xrelid), NIL); rel = - * rel_member(relids, outerrels); - */ - - relids = lconsi(lfirsti(xrelid), NIL); - rel = rel_member(relids, root->base_rel_list); - - add_superrels(rel, joinrel); - } - } - foreach(xjoinrel, joinrels) - { - RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel); - - foreach(xjoininfo, joinrel->joininfo) - { - JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - List *other_rels = joininfo->otherrels; - List *restrict_info = joininfo->jinfo_restrictinfo; - bool mergejoinable = joininfo->mergejoinable; - bool hashjoinable = joininfo->hashjoinable; - - foreach(xrelid, other_rels) - { - - /* - * ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid); - * RelOptInfo *rel = get_join_rel(root, relid); - */ - - /* - * if ( (root->join_rel_list) != NIL ) { rel = - * get_join_rel(root, xrelid); } else { rel = - * get_base_rel(root, lfirsti(xrelid)); } - */ - - /* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */ - - /* - * relids = lconsi(lfirsti(xrelid), NIL); rel = - * rel_member(relids, outerrels); - */ - - relids = lconsi(lfirsti(xrelid), NIL); - rel = rel_member(relids, root->base_rel_list); - - super_rels = rel->superrels; - new_joininfo = makeNode(JoinInfo); - - new_joininfo->otherrels = joinrel->relids; - new_joininfo->jinfo_restrictinfo = restrict_info; - new_joininfo->mergejoinable = mergejoinable; - new_joininfo->hashjoinable = hashjoinable; - new_joininfo->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->otherrels = new_relids; - new_joininfo->jinfo_restrictinfo = restrict_info; - new_joininfo->mergejoinable = mergejoinable; - new_joininfo->hashjoinable = hashjoinable; - new_joininfo->inactive = false; - joinrel->joininfo = lappend(joinrel->joininfo, - new_joininfo); - } - } - } - } - } - } - foreach(xrel, outerrels) - { - rel = (RelOptInfo *) lfirst(xrel); - rel->superrels = NIL; - } -} - -/* - * final_join_rels - * Find the join relation that includes all the original - * relations, i.e. the final join result. - * - * 'join_rel_list' is a list of join relations. - * - * Returns the list of final join relations. - */ -static List * -geqo_final_join_rels(List *join_rel_list) -{ - List *xrel = NIL; - List *t_list = NIL; - - /* - * find the relations that has no further joins, i.e., its joininfos - * all have otherrels nil. - */ - foreach(xrel, join_rel_list) - { - RelOptInfo *rel = (RelOptInfo *) lfirst(xrel); - List *xjoininfo = NIL; - bool final = true; - - foreach(xjoininfo, rel->joininfo) - { - JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo); - - if (joininfo->otherrels != NIL) - { - final = false; - break; - } - } - if (final) - { - t_list = lappend(t_list, rel); - } - } - - return t_list; -} - -/* - * 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) -{ - return nonoverlap_sets(rel1->relids, rel2->relids); -} - -static bool -nonoverlap_sets(List *s1, List *s2) -{ - List *x = NIL; - - foreach(x, s1) - { - int e = lfirsti(x); - - if (intMember(e, s2)) - return false; - } - return true; -} - -#endif /* NOTUSED */ - -/* - * geqo_joinrel_size - * compute estimate for join relation tuples, even for - * long join queries; so get logarithm of size when MAXINT overflow; - */ -static void -geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel) -{ - Cost temp; - int ntuples; - - temp = (Cost) inner_rel->tuples * (Cost) outer_rel->tuples; /* cartesian product */ - - if (joinrel->restrictinfo) - temp = temp * product_selec(joinrel->restrictinfo); - - if (temp >= (MAXINT - 1)) - ntuples = ceil(geqo_log((double) temp, (double) GEQO_LOG_BASE)); - else - ntuples = ceil((double) temp); - - if (ntuples < 1) - ntuples = 1; /* make the best case 1 instead of 0 */ - - joinrel->tuples = ntuples; -} - -double -geqo_log(double x, double b) -{ - return log(x) / log(b); -} - static RelOptInfo * geqo_nth(int stop, List *rels) { |