]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/plan/planmain.c
Remove unused #includes in *.c files.
[postgresql] / src / backend / optimizer / plan / planmain.c
1 /*-------------------------------------------------------------------------
2  *
3  * planmain.c
4  *        Routines to plan a single query
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.39 1999/07/15 22:39:27 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <sys/types.h>
15
16 #include "postgres.h"
17
18
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"
25
26
27 static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
28 static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
29
30 /*
31  * query_planner
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
39  *        satisfied.
40  *
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
44  *
45  *        Returns a query plan.
46  */
47 Plan *
48 query_planner(Query *root,
49                           int command_type,
50                           List *tlist,
51                           List *qual)
52 {
53         List       *constant_qual = NIL;
54         List       *var_only_tlist;
55         List       *level_tlist;
56         Plan       *subplan;
57
58         if (PlannerQueryLevel > 1)
59         {
60                 /* should copy be made ? */
61                 tlist = (List *) SS_replace_correlation_vars((Node *) tlist);
62                 qual = (List *) SS_replace_correlation_vars((Node *) qual);
63         }
64         if (root->hasSubLinks)
65                 qual = (List *) SS_process_sublinks((Node *) qual);
66
67         qual = cnfify((Expr *) qual, true);
68 #ifdef OPTIMIZER_DEBUG
69         printf("After cnfify()\n");
70         pprint(qual);
71 #endif
72
73         /*
74          * Pull out any non-variable qualifications so these can be put in the
75          * topmost result node.
76          */
77         qual = pull_constant_clauses(qual, &constant_qual);
78         /*
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.
81          */
82         fix_opids(constant_qual);
83
84         /*
85          * Create a target list that consists solely of (resdom var) target
86          * list entries, i.e., contains no arbitrary expressions.
87          */
88         var_only_tlist = flatten_tlist(tlist);
89         if (var_only_tlist)
90                 level_tlist = var_only_tlist;
91         else
92                 /* from old code. the logic is beyond me. - ay 2/95 */
93                 level_tlist = tlist;
94
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
99          * done in this case).
100          */
101         if (var_only_tlist == NULL && qual == NULL)
102         {
103                 switch (command_type)
104                 {
105                         case CMD_SELECT:
106                         case CMD_INSERT:
107                                 return ((Plan *) make_result(tlist,
108                                                                                          (Node *) constant_qual,
109                                                                                          (Plan *) NULL));
110                                 break;
111                         case CMD_DELETE:
112                         case CMD_UPDATE:
113                                 {
114                                         SeqScan    *scan = make_seqscan(tlist,
115                                                                                                         NIL,
116                                                                                                         root->resultRelation,
117                                                                                                         (Plan *) NULL);
118
119                                         if (constant_qual != NULL)
120                                                 return ((Plan *) make_result(tlist,
121                                                                                                          (Node *) constant_qual,
122                                                                                                          (Plan *) scan));
123                                         else
124                                                 return (Plan *) scan;
125                                 }
126                                 break;
127                         default:
128                                 return (Plan *) NULL;
129                 }
130         }
131
132         /*
133          * Find the subplan (access path) and destructively modify the target
134          * list of the newly created subplan to contain the appropriate join
135          * references.
136          */
137         subplan = subplanner(root, level_tlist, qual);
138
139         set_tlist_references(subplan);
140
141         /*
142          * Build a result node linking the plan if we have constant quals
143          */
144         if (constant_qual)
145         {
146                 subplan = (Plan *) make_result(tlist,
147                                                                            (Node *) constant_qual,
148                                                                            subplan);
149
150                 /*
151                  * Fix all varno's of the Result's node target list.
152                  */
153                 set_tlist_references(subplan);
154
155                 return subplan;
156         }
157
158         /*
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
164          * tree.  -- Wei
165          *
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.
170          */
171         else
172         {
173                 subplan->targetlist = flatten_tlist_vars(tlist,
174                                                                                                  subplan->targetlist);
175                 return subplan;
176         }
177
178 #ifdef NOT_USED
179
180         /*
181          * Destructively modify the query plan's targetlist to add fjoin lists
182          * to flatten functions that return sets of base types
183          */
184         subplan->targetlist = generate_fjoin(subplan->targetlist);
185 #endif
186
187 }
188
189 /*
190  * subplanner
191  *
192  *       Subplanner creates an entire plan consisting of joins and scans
193  *       for processing a single level of attributes.
194  *
195  *       flat_tlist is the flattened target list
196  *       qual is the qualification to be satisfied
197  *
198  *       Returns a subplan.
199  *
200  */
201 static Plan *
202 subplanner(Query *root,
203                    List *flat_tlist,
204                    List *qual)
205 {
206         RelOptInfo *final_rel;
207
208         /*
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.)
212          */
213         root->base_rel_list = NIL;
214         root->join_rel_list = NIL;
215
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);
219
220         set_joininfo_mergeable_hashable(root->base_rel_list);
221
222         final_rel = make_one_rel(root, root->base_rel_list);
223
224 #ifdef NOT_USED                                 /* fix xfunc */
225
226         /*
227          * Perform Predicate Migration on each path, to optimize and correctly
228          * assess the cost of each before choosing the cheapest one. -- JMH,
229          * 11/16/92
230          *
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
233          */
234         if (XfuncMode != XFUNC_OFF && XfuncMode != XFUNC_NOPM &&
235                 XfuncMode != XFUNC_NOPULL && !final_rel->pruneable)
236         {
237                 List       *pathnode;
238
239                 foreach(pathnode, final_rel->pathlist)
240                 {
241                         if (xfunc_do_predmig((Path *) lfirst(pathnode)))
242                                 set_cheapest(final_rel, final_rel->pathlist);
243                 }
244         }
245 #endif
246
247         /*
248          * Determine the cheapest path and create a subplan corresponding to
249          * it.
250          */
251         if (final_rel)
252                 return create_plan((Path *) final_rel->cheapestpath);
253         else
254         {
255                 elog(NOTICE, "final relation is null");
256                 return create_plan((Path *) NULL);
257         }
258
259 }
260
261 /*****************************************************************************
262  *
263  *****************************************************************************/
264
265 static Result *
266 make_result(List *tlist,
267                         Node *resconstantqual,
268                         Plan *subplan)
269 {
270         Result     *node = makeNode(Result);
271         Plan       *plan = &node->plan;
272
273 #ifdef NOT_USED
274         tlist = generate_fjoin(tlist);
275 #endif
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;
283
284         return node;
285 }