aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planmain.c')
-rw-r--r--src/backend/optimizer/plan/planmain.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index abb468aa8d1..1fcbe64e888 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.58 2000/08/13 02:50:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.59 2000/09/12 21:06:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,6 +28,7 @@
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
#include "optimizer/tlist.h"
+#include "parser/parsetree.h"
#include "utils/memutils.h"
@@ -41,11 +42,8 @@ static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
* not any fancier features.
*
* tlist is the target list the query should produce (NOT root->targetList!)
- * qual is the qualification of the query (likewise!)
* tuple_fraction is the fraction of tuples we expect will be retrieved
*
- * qual must already have been converted to implicit-AND form.
- *
* Note: the Query node now also includes a query_pathkeys field, which
* is both an input and an output of query_planner(). The input value
* signals query_planner that the indicated sort order is wanted in the
@@ -75,9 +73,9 @@ static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
Plan *
query_planner(Query *root,
List *tlist,
- List *qual,
double tuple_fraction)
{
+ List *normal_qual;
List *noncachable_qual;
List *constant_qual;
List *var_only_tlist;
@@ -96,7 +94,7 @@ query_planner(Query *root,
root->query_pathkeys = NIL; /* signal unordered result */
/* Make childless Result node to evaluate given tlist. */
- return (Plan *) make_result(tlist, (Node *) qual, (Plan *) NULL);
+ return (Plan *) make_result(tlist, root->qual, (Plan *) NULL);
}
/*
@@ -111,10 +109,12 @@ query_planner(Query *root,
* noncachable functions but no vars, such as "WHERE random() < 0.5".
* These cannot be treated as normal restriction or join quals, but
* they're not constants either. Instead, attach them to the qpqual
- * of the top-level plan, so that they get evaluated once per potential
+ * of the top plan, so that they get evaluated once per potential
* output tuple.
*/
- qual = pull_constant_clauses(qual, &noncachable_qual, &constant_qual);
+ normal_qual = pull_constant_clauses((List *) root->qual,
+ &noncachable_qual,
+ &constant_qual);
/*
* Create a target list that consists solely of (resdom var) target
@@ -132,7 +132,7 @@ query_planner(Query *root,
/*
* Choose the best access path and build a plan for it.
*/
- subplan = subplanner(root, var_only_tlist, qual, tuple_fraction);
+ subplan = subplanner(root, var_only_tlist, normal_qual, tuple_fraction);
/*
* Handle the noncachable quals.
@@ -188,6 +188,8 @@ subplanner(Query *root,
List *qual,
double tuple_fraction)
{
+ List *joined_rels;
+ List *brel;
RelOptInfo *final_rel;
Plan *resultplan;
MemoryContext mycontext;
@@ -196,7 +198,7 @@ subplanner(Query *root,
Path *presortedpath;
/*
- * Initialize the targetlist and qualification, adding entries to
+ * Examine the targetlist and qualifications, adding entries to
* base_rel_list as relation references are found (e.g., in the
* qualification, the targetlist, etc.). Restrict and join clauses
* are added to appropriate lists belonging to the mentioned
@@ -207,13 +209,29 @@ subplanner(Query *root,
root->join_rel_list = NIL;
root->equi_key_list = NIL;
- make_var_only_tlist(root, flat_tlist);
+ build_base_rel_tlists(root, flat_tlist);
+ (void) add_join_quals_to_rels(root, (Node *) root->jointree);
+ /* this must happen after add_join_quals_to_rels: */
add_restrict_and_join_to_rels(root, qual);
/*
- * Make sure we have RelOptInfo nodes for all relations used.
+ * Make sure we have RelOptInfo nodes for all relations to be joined.
+ */
+ joined_rels = add_missing_rels_to_query(root, (Node *) root->jointree);
+
+ /*
+ * Check that the join tree includes all the base relations used in
+ * the query --- otherwise, the parser or rewriter messed up.
*/
- add_missing_rels_to_query(root);
+ foreach(brel, root->base_rel_list)
+ {
+ RelOptInfo *baserel = (RelOptInfo *) lfirst(brel);
+ int relid = lfirsti(baserel->relids);
+
+ if (! ptrMember(baserel, joined_rels))
+ elog(ERROR, "Internal error: no jointree entry for rel %s (%d)",
+ rt_fetch(relid, root->rtable)->eref->relname, relid);
+ }
/*
* Use the completed lists of equijoined keys to deduce any implied
@@ -258,12 +276,11 @@ subplanner(Query *root,
* We expect to end up here for a trivial INSERT ... VALUES query
* (which will have a target relation, so it gets past
* query_planner's check for empty range table; but the target rel
- * is unreferenced and not marked inJoinSet, so we find there is
- * nothing to join).
+ * is not in the join tree, so we find there is nothing to join).
*
* It's also possible to get here if the query was rewritten by the
- * rule processor (creating rangetable entries not marked
- * inJoinSet) but the rules either did nothing or were simplified
+ * rule processor (creating dummy rangetable entries that are not in
+ * the join tree) but the rules either did nothing or were simplified
* to nothing by constant-expression folding. So, don't complain.
*/
root->query_pathkeys = NIL; /* signal unordered result */