*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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--
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;
/*
*/
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
{
*/
set_rest_relselec(root, rels);
- return (find_join_paths(root, rels, levels_left - 1));
+ return find_join_paths(root, rels, levels_needed);
}
}
* '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;
/*******************************************
* 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;
}
/*****************************************************************************
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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));
}
/*
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;
}
/*