diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index b58e386535f31cd53352ee7cc7549cc6d8b8d939..e691e8cfc5b0789a732b6fb769e381e46d3c5139 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.13 1997/09/08 21:44:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.14 1997/12/21 05:18:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,7 @@ int32 _use_geqo_rels_ = GEQO_RELS; static void find_rel_paths(Query *root, List *rels); -static List *find_join_paths(Query *root, List *outer_rels, int levels_left); +static List *find_join_paths(Query *root, List *outer_rels, int levels_needed); /* * find-paths-- @@ -56,14 +56,14 @@ static List *find_join_paths(Query *root, List *outer_rels, int levels_left); List * find_paths(Query *root, List *rels) { - int levels_left; + int levels_needed; /* * Set the number of join (not nesting) levels yet to be processed. */ - levels_left = length(rels); + levels_needed = length(rels); - if (levels_left <= 0) + if (levels_needed <= 0) return NIL; /* @@ -71,13 +71,13 @@ find_paths(Query *root, List *rels) */ find_rel_paths(root, rels); - if (levels_left <= 1) + if (levels_needed <= 1) { /* * Unsorted single relation, no more processing is required. */ - return (rels); + return rels; } else { @@ -88,7 +88,7 @@ find_paths(Query *root, List *rels) */ set_rest_relselec(root, rels); - return (find_join_paths(root, rels, levels_left - 1)); + return find_join_paths(root, rels, levels_needed); } } @@ -165,17 +165,16 @@ find_rel_paths(Query *root, List *rels) * 'outer-rels' is the current list of relations for which join paths * are to be found, i.e., he current list of relations that * have already been derived. - * 'levels-left' is the current join level being processed, where '1' is - * the "last" level + * 'levels-needed' is the number of iterations needed * * Returns the final level of join relations, i.e., the relation that is - * the result of joining all the original relations togehter. + * the result of joining all the original relations together. */ static List * -find_join_paths(Query *root, List *outer_rels, int levels_left) +find_join_paths(Query *root, List *outer_rels, int levels_needed) { List *x; - List *new_rels; + List *new_rels = NIL; Rel *rel; /******************************************* @@ -190,89 +189,84 @@ find_join_paths(Query *root, List *outer_rels, int levels_left) * rest will be deprecated in case of GEQO * *******************************************/ - /* - * Determine all possible pairs of relations to be joined at this - * level. Determine paths for joining these relation pairs and modify - * 'new-rels' accordingly, then eliminate redundant join relations. - */ - new_rels = find_join_rels(root, outer_rels); - - find_all_join_paths(root, new_rels); - - new_rels = prune_joinrels(new_rels); - + while (--levels_needed) + { + /* + * Determine all possible pairs of relations to be joined at this + * level. Determine paths for joining these relation pairs and modify + * 'new-rels' accordingly, then eliminate redundant join relations. + */ + new_rels = find_join_rels(root, outer_rels); + + find_all_join_paths(root, new_rels); + + prune_joinrels(new_rels); + #if 0 - - /* - * * for each expensive predicate in each path in each distinct rel, * - * consider doing pullup -- JMH - */ - if (XfuncMode != XFUNC_NOPULL && XfuncMode != XFUNC_OFF) - foreach(x, new_rels) - xfunc_trypullup((Rel *) lfirst(x)); -#endif - - prune_rel_paths(new_rels); - - if (BushyPlanFlag) - { - + /* - * In case of bushy trees if there is still a join between a join - * relation and another relation, add a new joininfo that involves - * the join relation to the joininfo list of the other relation + * * for each expensive predicate in each path in each distinct rel, * + * consider doing pullup -- JMH */ - add_new_joininfos(root, new_rels, outer_rels); - } - - foreach(x, new_rels) - { - rel = (Rel *) lfirst(x); - if (rel->size <= 0) - rel->size = compute_rel_size(rel); - rel->width = compute_rel_width(rel); - -/*#define OPTIMIZER_DEBUG*/ + if (XfuncMode != XFUNC_NOPULL && XfuncMode != XFUNC_OFF) + foreach(x, new_rels) + xfunc_trypullup((Rel *) lfirst(x)); +#endif + + prune_rel_paths(new_rels); + + if (BushyPlanFlag) + { + + /* + * In case of bushy trees if there is still a join between a join + * relation and another relation, add a new joininfo that involves + * the join relation to the joininfo list of the other relation + */ + add_new_joininfos(root, new_rels, outer_rels); + } + + foreach(x, new_rels) + { + rel = (Rel *) lfirst(x); + if (rel->size <= 0) + rel->size = compute_rel_size(rel); + rel->width = compute_rel_width(rel); + + /*#define OPTIMIZER_DEBUG*/ #ifdef OPTIMIZER_DEBUG - printf("levels left: %d\n", levels_left); - debug_print_rel(root, rel); + printf("levels left: %d\n", levels_left); + debug_print_rel(root, rel); #endif - } - - if (BushyPlanFlag) - { - - /* - * prune rels that have been completely incorporated into new join - * rels - */ - outer_rels = prune_oldrels(outer_rels); - - /* - * merge join rels if then contain the same list of base rels - */ - outer_rels = merge_joinrels(new_rels, outer_rels); - root->join_relation_list_ = outer_rels; - } - else - { - root->join_relation_list_ = new_rels; - } - - if (levels_left == 1) - { + } + if (BushyPlanFlag) - return (final_join_rels(outer_rels)); + { + + /* + * prune rels that have been completely incorporated into new join + * rels + */ + outer_rels = prune_oldrels(outer_rels); + + /* + * merge join rels if then contain the same list of base rels + */ + outer_rels = merge_joinrels(new_rels, outer_rels); + root->join_relation_list_ = outer_rels; + } else - return (new_rels); + { + root->join_relation_list_ = new_rels; + } + if (!BushyPlanFlag) + outer_rels = new_rels; } + + if (BushyPlanFlag) + return final_join_rels(outer_rels); else - { - if (BushyPlanFlag) - return (find_join_paths(root, outer_rels, levels_left - 1)); - else - return (find_join_paths(root, new_rels, levels_left - 1)); - } + return new_rels; } /***************************************************************************** diff --git a/src/backend/optimizer/path/prune.c b/src/backend/optimizer/path/prune.c index d6064ab8e6850ec88b8cddc891ebcaee9844eaf1..26bd559696360fdb0154976b82ea609941e2c072 100644 --- a/src/backend/optimizer/path/prune.c +++ b/src/backend/optimizer/path/prune.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.6 1997/09/08 21:45:08 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.7 1997/12/21 05:18:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,23 +29,21 @@ static List *prune_joinrel(Rel *rel, List *other_rels); /* * prune-joinrels-- * Removes any redundant relation entries from a list of rel nodes - * 'rel-list'. + * 'rel-list'. Obviosly, the first relation can't be a duplicate. * * Returns the resulting list. * */ -List * +void prune_joinrels(List *rel_list) { - List *temp_list = NIL; + List *i; - if (rel_list != NIL) - { - temp_list = lcons(lfirst(rel_list), - prune_joinrels(prune_joinrel((Rel *) lfirst(rel_list), - lnext(rel_list)))); - } - return (temp_list); + /* + * rel_list can shorten while running as duplicate relations are deleted + */ + foreach(i, rel_list) + lnext(i) = prune_joinrel((Rel *) lfirst(i), lnext(i)); } /* @@ -62,28 +60,39 @@ prune_joinrels(List *rel_list) static List * prune_joinrel(Rel *rel, List *other_rels) { - List *i = NIL; - List *t_list = NIL; - List *temp_node = NIL; - Rel *other_rel = (Rel *) NULL; + List *cur = NIL; + List *return_list = NIL; - foreach(i, other_rels) + /* find first relation that doesn't match */ + foreach(cur, other_rels) { - other_rel = (Rel *) lfirst(i); - if (same(rel->relids, other_rel->relids)) - { - rel->pathlist = add_pathlist(rel, - rel->pathlist, - other_rel->pathlist); - t_list = nconc(t_list, NIL); /* XXX is this right ? */ - } - else + Rel *other_rel = (Rel *) lfirst(cur); + + if (!same(rel->relids, other_rel->relids)) + break; + } + + /* we now know cur doesn't match, or is NIL */ + return_list = cur; + + /* remove relations that do match, we use lnext so we can remove easily */ + if (cur != NIL) + { + while (lnext(cur) != NIL) { - temp_node = lcons(other_rel, NIL); - t_list = nconc(t_list, temp_node); + Rel *other_rel = (Rel *) lfirst(lnext(cur)); + + if (same(rel->relids, other_rel->relids)) + { + rel->pathlist = add_pathlist(rel, + rel->pathlist, + other_rel->pathlist); + lnext(cur) = lnext(lnext(cur)); /* delete it */ + } + cur = lnext(cur); } } - return (t_list); + return return_list; } /* diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 7f9645e0f32a736a4a560062aa1beec9f5bbe7fc..11e9489942ed5db2ca950bd6e0e4ca252e5e3f3d 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.11 1997/12/20 07:59:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.12 1997/12/21 05:18:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -236,9 +236,13 @@ plan_union_query(List *relids, new_root->uniqueFlag = NULL; new_root->sortClause = NULL; new_root->groupClause = NULL; - new_root->qry_numAgg = 0; - new_root->qry_aggs = NULL; - del_agg_tlist_references(new_root->targetList); + if (new_root->qry_numAgg != 0) + { + new_root->qry_numAgg = 0; + pfree(new_root->qry_aggs); + new_root->qry_aggs = NULL; + del_agg_tlist_references(new_root->targetList); + } fix_parsetree_attnums(rt_index, rt_entry->relid, relid, diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index b7a56ef65363f027e1c564c0e7dbbe342fedea90..42491d76053d1acc5d3ca6cdc8b6ca54fe0329b3 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: paths.h,v 1.5 1997/11/26 01:13:47 momjian Exp $ + * $Id: paths.h,v 1.6 1997/12/21 05:18:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -92,7 +92,7 @@ extern List *final_join_rels(List *join_rel_list); /* * prototypes for path/prune.c */ -extern List *prune_joinrels(List *rel_list); +extern void prune_joinrels(List *rel_list); extern void prune_rel_paths(List *rel_list); extern Path *prune_rel_path(Rel *rel, Path *unorderedpath); extern List *merge_joinrels(List *rel_list1, List *rel_list2);