summaryrefslogtreecommitdiff
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.c85
1 files changed, 26 insertions, 59 deletions
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index 1fcbe64e88..29cfccfef7 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.59 2000/09/12 21:06:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.60 2000/09/29 18:21:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,8 +32,8 @@
#include "utils/memutils.h"
-static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
- double tuple_fraction);
+static Plan *subplanner(Query *root, List *flat_tlist,
+ double tuple_fraction);
/*--------------------
@@ -75,46 +75,36 @@ query_planner(Query *root,
List *tlist,
double tuple_fraction)
{
- List *normal_qual;
- List *noncachable_qual;
- List *constant_qual;
+ List *constant_quals;
List *var_only_tlist;
Plan *subplan;
/*
- * If the query contains no relation references at all, it must be
- * something like "SELECT 2+2;". Build a trivial "Result" plan.
+ * If the query has an empty join tree, then it's something easy like
+ * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly.
*/
- if (root->rtable == NIL)
+ if (root->jointree->fromlist == NIL)
{
- /* If it's not a select, it should have had a target relation... */
- if (root->commandType != CMD_SELECT)
- elog(ERROR, "Empty range table for non-SELECT query");
-
root->query_pathkeys = NIL; /* signal unordered result */
/* Make childless Result node to evaluate given tlist. */
- return (Plan *) make_result(tlist, root->qual, (Plan *) NULL);
+ return (Plan *) make_result(tlist, root->jointree->quals,
+ (Plan *) NULL);
}
/*
- * Pull out any non-variable qual clauses so these can be put in a
+ * Pull out any non-variable WHERE clauses so these can be put in a
* toplevel "Result" node, where they will gate execution of the whole
* plan (the Result will not invoke its descendant plan unless the
* quals are true). Note that any *really* non-variable quals will
* have been optimized away by eval_const_expressions(). What we're
* mostly interested in here is quals that depend only on outer-level
* vars, although if the qual reduces to "WHERE FALSE" this path will
- * also be taken. We also need a special case for quals that contain
- * 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 plan, so that they get evaluated once per potential
- * output tuple.
+ * also be taken.
*/
- normal_qual = pull_constant_clauses((List *) root->qual,
- &noncachable_qual,
- &constant_qual);
+ root->jointree->quals = (Node *)
+ pull_constant_clauses((List *) root->jointree->quals,
+ &constant_quals);
/*
* Create a target list that consists solely of (resdom var) target
@@ -132,18 +122,12 @@ query_planner(Query *root,
/*
* Choose the best access path and build a plan for it.
*/
- subplan = subplanner(root, var_only_tlist, normal_qual, tuple_fraction);
-
- /*
- * Handle the noncachable quals.
- */
- if (noncachable_qual)
- subplan->qual = nconc(subplan->qual, noncachable_qual);
+ subplan = subplanner(root, var_only_tlist, tuple_fraction);
/*
* Build a result node to control the plan if we have constant quals.
*/
- if (constant_qual)
+ if (constant_quals)
{
/*
@@ -151,7 +135,7 @@ query_planner(Query *root,
* originally requested tlist.
*/
subplan = (Plan *) make_result(tlist,
- (Node *) constant_qual,
+ (Node *) constant_quals,
subplan);
}
else
@@ -175,7 +159,6 @@ query_planner(Query *root,
* for processing a single level of attributes.
*
* flat_tlist is the flattened target list
- * qual is the qualification to be satisfied (restrict and join quals only)
* tuple_fraction is the fraction of tuples we expect will be retrieved
*
* See query_planner() comments about the interpretation of tuple_fraction.
@@ -185,7 +168,6 @@ query_planner(Query *root,
static Plan *
subplanner(Query *root,
List *flat_tlist,
- List *qual,
double tuple_fraction)
{
List *joined_rels;
@@ -210,9 +192,8 @@ subplanner(Query *root,
root->equi_key_list = NIL;
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);
+
+ (void) distribute_quals_to_rels(root, (Node *) root->jointree);
/*
* Make sure we have RelOptInfo nodes for all relations to be joined.
@@ -270,26 +251,7 @@ subplanner(Query *root,
final_rel = make_one_rel(root);
if (!final_rel)
- {
-
- /*
- * 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 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 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 */
-
- /* Make childless Result node to evaluate given tlist. */
- resultplan = (Plan *) make_result(flat_tlist, (Node *) qual,
- (Plan *) NULL);
- goto plan_built;
- }
+ elog(ERROR, "subplanner: failed to construct a relation");
#ifdef NOT_USED /* fix xfunc */
@@ -395,7 +357,10 @@ plan_built:
/*
* Must copy the completed plan tree and its pathkeys out of temporary
- * context.
+ * context. We also have to copy the rtable in case it contains any
+ * subqueries. (If it does, they'll have been modified during the
+ * recursive invocation of planner.c, and hence will contain substructure
+ * allocated in my temporary context...)
*/
MemoryContextSwitchTo(oldcxt);
@@ -403,6 +368,8 @@ plan_built:
root->query_pathkeys = copyObject(root->query_pathkeys);
+ root->rtable = copyObject(root->rtable);
+
/*
* Now we can release the Path storage.
*/