1 /*-------------------------------------------------------------------------
4 * Routines to plan a single query
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.39 1999/07/15 22:39:27 momjian Exp $
12 *-------------------------------------------------------------------------
14 #include <sys/types.h>
19 #include "optimizer/planmain.h"
20 #include "optimizer/subselect.h"
21 #include "optimizer/prep.h"
22 #include "optimizer/paths.h"
23 #include "optimizer/clauses.h"
24 #include "optimizer/tlist.h"
27 static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
28 static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
32 * Routine to create a query plan. It does so by first creating a
33 * subplan for the topmost level of attributes in the query. Then,
34 * it modifies all target list and qualifications to consider the next
35 * level of nesting and creates a plan for this modified query by
36 * recursively calling itself. The two pieces are then merged together
37 * by creating a result node that indicates which attributes should
38 * be placed where and any relation level qualifications to be
41 * command-type is the query command, e.g., select, delete, etc.
42 * tlist is the target list of the query
43 * qual is the qualification of the query
45 * Returns a query plan.
48 query_planner(Query *root,
53 List *constant_qual = NIL;
58 if (PlannerQueryLevel > 1)
60 /* should copy be made ? */
61 tlist = (List *) SS_replace_correlation_vars((Node *) tlist);
62 qual = (List *) SS_replace_correlation_vars((Node *) qual);
64 if (root->hasSubLinks)
65 qual = (List *) SS_process_sublinks((Node *) qual);
67 qual = cnfify((Expr *) qual, true);
68 #ifdef OPTIMIZER_DEBUG
69 printf("After cnfify()\n");
74 * Pull out any non-variable qualifications so these can be put in the
75 * topmost result node.
77 qual = pull_constant_clauses(qual, &constant_qual);
79 * The opids for the variable qualifications will be fixed later, but
80 * someone seems to think that the constant quals need to be fixed here.
82 fix_opids(constant_qual);
85 * Create a target list that consists solely of (resdom var) target
86 * list entries, i.e., contains no arbitrary expressions.
88 var_only_tlist = flatten_tlist(tlist);
90 level_tlist = var_only_tlist;
92 /* from old code. the logic is beyond me. - ay 2/95 */
96 * A query may have a non-variable target list and a non-variable
97 * qualification only under certain conditions: - the query creates
98 * all-new tuples, or - the query is a replace (a scan must still be
101 if (var_only_tlist == NULL && qual == NULL)
103 switch (command_type)
107 return ((Plan *) make_result(tlist,
108 (Node *) constant_qual,
114 SeqScan *scan = make_seqscan(tlist,
116 root->resultRelation,
119 if (constant_qual != NULL)
120 return ((Plan *) make_result(tlist,
121 (Node *) constant_qual,
124 return (Plan *) scan;
128 return (Plan *) NULL;
133 * Find the subplan (access path) and destructively modify the target
134 * list of the newly created subplan to contain the appropriate join
137 subplan = subplanner(root, level_tlist, qual);
139 set_tlist_references(subplan);
142 * Build a result node linking the plan if we have constant quals
146 subplan = (Plan *) make_result(tlist,
147 (Node *) constant_qual,
151 * Fix all varno's of the Result's node target list.
153 set_tlist_references(subplan);
159 * fix up the flattened target list of the plan root node so that
160 * expressions are evaluated. this forces expression evaluations that
161 * may involve expensive function calls to be delayed to the very last
162 * stage of query execution. this could be bad. but it is joey's
163 * responsibility to optimally push these expressions down the plan
166 * Note: formerly there was a test here to skip the flatten call if we
167 * expected union_planner to insert a Group or Agg node above our
168 * result. However, now union_planner tells us exactly what it wants
169 * returned, and we just do it. Much cleaner.
173 subplan->targetlist = flatten_tlist_vars(tlist,
174 subplan->targetlist);
181 * Destructively modify the query plan's targetlist to add fjoin lists
182 * to flatten functions that return sets of base types
184 subplan->targetlist = generate_fjoin(subplan->targetlist);
192 * Subplanner creates an entire plan consisting of joins and scans
193 * for processing a single level of attributes.
195 * flat_tlist is the flattened target list
196 * qual is the qualification to be satisfied
202 subplanner(Query *root,
206 RelOptInfo *final_rel;
209 * Initialize the targetlist and qualification, adding entries to
210 * base_rel_list as relation references are found (e.g., in the
211 * qualification, the targetlist, etc.)
213 root->base_rel_list = NIL;
214 root->join_rel_list = NIL;
216 make_var_only_tlist(root, flat_tlist);
217 add_restrict_and_join_to_rels(root, qual);
218 add_missing_vars_to_tlist(root, flat_tlist);
220 set_joininfo_mergeable_hashable(root->base_rel_list);
222 final_rel = make_one_rel(root, root->base_rel_list);
224 #ifdef NOT_USED /* fix xfunc */
227 * Perform Predicate Migration on each path, to optimize and correctly
228 * assess the cost of each before choosing the cheapest one. -- JMH,
231 * Needn't do so if the top rel is pruneable: that means there's no
232 * expensive functions left to pull up. -- JMH, 11/22/92
234 if (XfuncMode != XFUNC_OFF && XfuncMode != XFUNC_NOPM &&
235 XfuncMode != XFUNC_NOPULL && !final_rel->pruneable)
239 foreach(pathnode, final_rel->pathlist)
241 if (xfunc_do_predmig((Path *) lfirst(pathnode)))
242 set_cheapest(final_rel, final_rel->pathlist);
248 * Determine the cheapest path and create a subplan corresponding to
252 return create_plan((Path *) final_rel->cheapestpath);
255 elog(NOTICE, "final relation is null");
256 return create_plan((Path *) NULL);
261 /*****************************************************************************
263 *****************************************************************************/
266 make_result(List *tlist,
267 Node *resconstantqual,
270 Result *node = makeNode(Result);
271 Plan *plan = &node->plan;
274 tlist = generate_fjoin(tlist);
276 plan->cost = (subplan ? subplan->cost : 0);
277 plan->state = (EState *) NULL;
278 plan->targetlist = tlist;
279 plan->lefttree = subplan;
280 plan->righttree = NULL;
281 node->resconstantqual = resconstantqual;
282 node->resstate = NULL;