]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/plan/planner.c
Small HAVING cleanup.
[postgresql] / src / backend / optimizer / plan / planner.c
1 /*-------------------------------------------------------------------------
2  *
3  * planner.c--
4  *        The query optimizer external interface.
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.25 1998/03/31 23:30:51 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <sys/types.h>
15 #include <string.h>
16
17 #include "postgres.h"
18
19 #include "nodes/pg_list.h"
20 #include "nodes/plannodes.h"
21 #include "nodes/parsenodes.h"
22 #include "nodes/relation.h"
23 #include "parser/parse_expr.h"
24
25 #include "utils/elog.h"
26 #include "utils/lsyscache.h"
27 #include "access/heapam.h"
28
29 #include "optimizer/internal.h"
30 #include "optimizer/planner.h"
31 #include "optimizer/plancat.h"
32 #include "optimizer/prep.h"
33 #include "optimizer/planmain.h"
34 #include "optimizer/subselect.h"
35 #include "optimizer/paths.h"
36 #include "optimizer/cost.h"
37
38 /* DATA STRUCTURE CREATION/MANIPULATION ROUTINES */
39 #include "nodes/relation.h"
40 #include "optimizer/clauseinfo.h"
41 #include "optimizer/joininfo.h"
42 #include "optimizer/keys.h"
43 #include "optimizer/ordering.h"
44 #include "optimizer/pathnode.h"
45 #include "optimizer/clauses.h"
46 #include "optimizer/tlist.h"
47 #include "optimizer/var.h"
48
49 #include "executor/executor.h"
50
51 static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
52 extern Plan *
53 make_groupPlan(List **tlist, bool tuplePerGroup,
54                            List *groupClause, Plan *subplan);
55
56 /*****************************************************************************
57  *
58  *         Query optimizer entry point
59  *
60  *****************************************************************************/
61
62
63 /***S*H***/ /* Anfang */
64
65 static List *
66 check_having_qual_for_aggs(Node *clause, List *subplanTargetList)
67 {
68         List       *t;
69         List       *agg_list = NIL;
70
71         if (IsA(clause, Var))
72         {
73           TargetEntry *subplanVar;
74           
75           /*
76            * Ha! A Var node!
77            */
78           subplanVar = match_varid((Var *) clause, subplanTargetList);
79           
80           /*
81            * Change the varno & varattno fields of the var node.
82            *
83            */
84           ((Var *) clause)->varattno = subplanVar->resdom->resno;
85           return NIL;
86         }
87         /***S*H***/
88         else if (is_funcclause(clause) || not_clause(clause) || 
89                  or_clause(clause) || and_clause(clause))
90         {
91
92                 /*
93                  * This is a function. Recursively call this routine for its
94                  * arguments...
95                  */
96                 foreach(t, ((Expr *) clause)->args)
97                 {
98                         agg_list = nconc(agg_list,
99                                            check_having_qual_for_aggs(lfirst(t), subplanTargetList));
100                 }
101                 return agg_list;
102         }
103         else if (IsA(clause, Aggreg))
104         {
105                 return lcons(clause,
106                     check_having_qual_for_aggs(((Aggreg *) clause)->target, subplanTargetList));
107                 
108         }
109         else if (IsA(clause, ArrayRef))
110         {
111                 ArrayRef   *aref = (ArrayRef *) clause;
112
113                 /*
114                  * This is an arrayref. Recursively call this routine for its
115                  * expression and its index expression...
116                  */
117                 foreach(t, aref->refupperindexpr)
118                 {
119                         agg_list = nconc(agg_list,
120                                          check_having_qual_for_aggs(lfirst(t), subplanTargetList));
121                 }
122                 foreach(t, aref->reflowerindexpr)
123                 {
124                         agg_list = nconc(agg_list,
125                                          check_having_qual_for_aggs(lfirst(t), subplanTargetList));
126                 }
127                 agg_list = nconc(agg_list,
128                                  check_having_qual_for_aggs(aref->refexpr, subplanTargetList));
129                 agg_list = nconc(agg_list,
130                                  check_having_qual_for_aggs(aref->refassgnexpr, subplanTargetList));
131
132                 return agg_list;
133         }
134         else if (is_opclause(clause))
135         {
136
137                 /*
138                  * This is an operator. Recursively call this routine for both its
139                  * left and right operands
140                  */
141                 Node       *left = (Node *) get_leftop((Expr *) clause);
142                 Node       *right = (Node *) get_rightop((Expr *) clause);
143
144                 if (left != (Node *) NULL)
145                         agg_list = nconc(agg_list,
146                                          check_having_qual_for_aggs(left, subplanTargetList));
147                 if (right != (Node *) NULL)
148                         agg_list = nconc(agg_list,
149                                          check_having_qual_for_aggs(right, subplanTargetList));
150
151                 return agg_list;
152         }
153         else if (IsA(clause, Param) ||IsA(clause, Const))
154         {
155                 /* do nothing! */
156                 return NIL;
157         }
158         else
159         {
160
161                 /*
162                  * Ooops! we can not handle that!
163                  */
164                 elog(ERROR, "check_having_qual_for_aggs: Can not handle this having_qual!\n");
165                 return NIL;
166         }
167 }
168 /***S*H***/ /* Ende */
169
170
171 Plan *
172 planner(Query *parse)
173 {
174         Plan       *result_plan;
175
176         PlannerQueryLevel = 1;
177         PlannerVarParam = NULL;
178         PlannerParamVar = NULL;
179         PlannerInitPlan = NULL;
180         PlannerPlanId = 0;
181
182         result_plan = union_planner(parse);
183
184         Assert(PlannerQueryLevel == 1);
185         if (PlannerPlanId > 0)
186         {
187                 result_plan->initPlan = PlannerInitPlan;
188                 (void) SS_finalize_plan(result_plan);
189         }
190         result_plan->nParamExec = length(PlannerParamVar);
191
192         return (result_plan);
193 }
194
195 /*
196  * union_planner--
197  *
198  *        Invokes the planner on union queries if there are any left,
199  *        recursing if necessary to get them all, then processes normal plans.
200  *
201  * Returns a query plan.
202  *
203  */
204 Plan *
205 union_planner(Query *parse)
206 {
207         List       *tlist = parse->targetList;
208         List       *rangetable = parse->rtable;
209
210         Plan       *result_plan = (Plan *) NULL;
211
212         Index           rt_index;
213
214
215         if (parse->unionClause)
216         {
217                 result_plan = (Plan *) plan_union_queries(parse);
218                 /* XXX do we need to do this? bjm 12/19/97 */
219                 tlist = preprocess_targetlist(tlist,
220                                                                           parse->commandType,
221                                                                           parse->resultRelation,
222                                                                           parse->rtable);
223         }
224         else if ((rt_index =
225                           first_inherit_rt_entry(rangetable)) != -1)
226         {
227                 result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
228                 /* XXX do we need to do this? bjm 12/19/97 */
229                 tlist = preprocess_targetlist(tlist,
230                                                                           parse->commandType,
231                                                                           parse->resultRelation,
232                                                                           parse->rtable);
233         }
234         else
235         {
236                 List      **vpm = NULL;
237
238                 tlist = preprocess_targetlist(tlist,
239                                                                           parse->commandType,
240                                                                           parse->resultRelation,
241                                                                           parse->rtable);
242                 if (parse->rtable != NULL)
243                 {
244                         vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
245                         memset(vpm, 0, length(parse->rtable) * sizeof(List *));
246                 }
247                 PlannerVarParam = lcons(vpm, PlannerVarParam);
248                 result_plan = query_planner(parse,
249                                                                         parse->commandType,
250                                                                         tlist,
251                                                                         (List *) parse->qual);
252                 PlannerVarParam = lnext(PlannerVarParam);
253                 if (vpm != NULL)
254                         pfree(vpm);
255         }
256
257         /*
258          * If we have a GROUP BY clause, insert a group node (with the
259          * appropriate sort node.)
260          */
261         if (parse->groupClause)
262         {
263                 bool            tuplePerGroup;
264
265                 /*
266                  * decide whether how many tuples per group the Group node needs
267                  * to return. (Needs only one tuple per group if no aggregate is
268                  * present. Otherwise, need every tuple from the group to do the
269                  * aggregation.)
270                  */
271                 tuplePerGroup = parse->hasAggs;
272
273                 result_plan =
274                         make_groupPlan(&tlist,
275                                                    tuplePerGroup,
276                                                    parse->groupClause,
277                                                    result_plan);
278
279         }
280
281         /*
282          * If aggregate is present, insert the agg node
283          */
284         if (parse->hasAggs)
285         {
286                 result_plan = (Plan *) make_agg(tlist, result_plan);
287
288                 /*
289                  * set the varno/attno entries to the appropriate references to
290                  * the result tuple of the subplans.
291                  */
292                 ((Agg *) result_plan)->aggs =
293                         set_agg_tlist_references((Agg *) result_plan); 
294
295                 if(parse->havingQual != NULL) {
296                   List     *clause;
297
298                   /* set qpqual of having clause */
299                   ((Agg *) result_plan)->plan.qual=cnfify((Expr *)parse->havingQual,true);
300
301                   foreach(clause, ((Agg *) result_plan)->plan.qual)
302                     {
303                       ((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs,
304                          check_having_qual_for_aggs((Node *) lfirst(clause),
305                                        ((Agg *) result_plan)->plan.lefttree->targetlist));
306                     }
307                 }
308         }
309
310         /*
311          * For now, before we hand back the plan, check to see if there is a
312          * user-specified sort that needs to be done.  Eventually, this will
313          * be moved into the guts of the planner s.t. user specified sorts
314          * will be considered as part of the planning process. Since we can
315          * only make use of user-specified sorts in special cases, we can do
316          * the optimization step later.
317          */
318
319         if (parse->uniqueFlag)
320         {
321                 Plan       *sortplan = make_sortplan(tlist, parse->sortClause, result_plan);
322
323                 return ((Plan *) make_unique(tlist, sortplan, parse->uniqueFlag));
324         }
325         else
326         {
327                 if (parse->sortClause)
328                         return (make_sortplan(tlist, parse->sortClause, result_plan));
329                 else
330                         return ((Plan *) result_plan);
331         }
332
333 }
334
335 /*
336  * make_sortplan--
337  *        Returns a sortplan which is basically a SORT node attached to the
338  *        top of the plan returned from the planner.  It also adds the
339  *         cost of sorting into the plan.
340  *
341  * sortkeys: ( resdom1 resdom2 resdom3 ...)
342  * sortops:  (sortop1 sortop2 sortop3 ...)
343  */
344 static Plan *
345 make_sortplan(List *tlist, List *sortcls, Plan *plannode)
346 {
347         Plan       *sortplan = (Plan *) NULL;
348         List       *temp_tlist = NIL;
349         List       *i = NIL;
350         Resdom     *resnode = (Resdom *) NULL;
351         Resdom     *resdom = (Resdom *) NULL;
352         int                     keyno = 1;
353
354         /*
355          * First make a copy of the tlist so that we don't corrupt the the
356          * original .
357          */
358
359         temp_tlist = new_unsorted_tlist(tlist);
360
361         foreach(i, sortcls)
362         {
363                 SortClause *sortcl = (SortClause *) lfirst(i);
364
365                 resnode = sortcl->resdom;
366                 resdom = tlist_resdom(temp_tlist, resnode);
367
368                 /*
369                  * Order the resdom keys and replace the operator OID for each key
370                  * with the regproc OID.
371                  */
372                 resdom->reskey = keyno;
373                 resdom->reskeyop = get_opcode(sortcl->opoid);
374                 keyno += 1;
375         }
376
377         sortplan = (Plan *) make_sort(temp_tlist,
378                                                                   _TEMP_RELATION_ID_,
379                                                                   (Plan *) plannode,
380                                                                   length(sortcls));
381
382         /*
383          * XXX Assuming that an internal sort has no. cost. This is wrong, but
384          * given that at this point, we don't know the no. of tuples returned,
385          * etc, we can't do better than to add a constant cost. This will be
386          * fixed once we move the sort further into the planner, but for now
387          * ... functionality....
388          */
389
390         sortplan->cost = plannode->cost;
391
392         return (sortplan);
393 }
394
395 /*
396  * pg_checkretval() -- check return value of a list of sql parse
397  *                                              trees.
398  *
399  * The return value of a sql function is the value returned by
400  * the final query in the function.  We do some ad-hoc define-time
401  * type checking here to be sure that the user is returning the
402  * type he claims.
403  */
404 void
405 pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
406 {
407         Query      *parse;
408         List       *tlist;
409         List       *rt;
410         int                     cmd;
411         Type            typ;
412         Resdom     *resnode;
413         Relation        reln;
414         Oid                     relid;
415         Oid                     tletype;
416         int                     relnatts;
417         int                     i;
418
419         /* find the final query */
420         parse = queryTreeList->qtrees[queryTreeList->len - 1];
421
422         /*
423          * test 1:      if the last query is a utility invocation, then there had
424          * better not be a return value declared.
425          */
426         if (parse->commandType == CMD_UTILITY)
427         {
428                 if (rettype == InvalidOid)
429                         return;
430                 else
431                         elog(ERROR, "return type mismatch in function decl: final query is a catalog utility");
432         }
433
434         /* okay, it's an ordinary query */
435         tlist = parse->targetList;
436         rt = parse->rtable;
437         cmd = parse->commandType;
438
439         /*
440          * test 2:      if the function is declared to return no value, then the
441          * final query had better not be a retrieve.
442          */
443         if (rettype == InvalidOid)
444         {
445                 if (cmd == CMD_SELECT)
446                         elog(ERROR,
447                                  "function declared with no return type, but final query is a retrieve");
448                 else
449                         return;
450         }
451
452         /* by here, the function is declared to return some type */
453         if ((typ = typeidType(rettype)) == NULL)
454                 elog(ERROR, "can't find return type %d for function\n", rettype);
455
456         /*
457          * test 3:      if the function is declared to return a value, then the
458          * final query had better be a retrieve.
459          */
460         if (cmd != CMD_SELECT)
461                 elog(ERROR, "function declared to return type %s, but final query is not a retrieve", typeTypeName(typ));
462
463         /*
464          * test 4:      for base type returns, the target list should have exactly
465          * one entry, and its type should agree with what the user declared.
466          */
467
468         if (typeTypeRelid(typ) == InvalidOid)
469         {
470                 if (exec_tlist_length(tlist) > 1)
471                         elog(ERROR, "function declared to return %s returns multiple values in final retrieve", typeTypeName(typ));
472
473                 resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
474                 if (resnode->restype != rettype)
475                         elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", typeTypeName(typ), typeidTypeName(resnode->restype));
476
477                 /* by here, base return types match */
478                 return;
479         }
480
481         /*
482          * If the target list is of length 1, and the type of the varnode in
483          * the target list is the same as the declared return type, this is
484          * okay.  This can happen, for example, where the body of the function
485          * is 'retrieve (x = func2())', where func2 has the same return type
486          * as the function that's calling it.
487          */
488         if (exec_tlist_length(tlist) == 1)
489         {
490                 resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
491                 if (resnode->restype == rettype)
492                         return;
493         }
494
495         /*
496          * By here, the procedure returns a (set of) tuples.  This part of the
497          * typechecking is a hack.      We look up the relation that is the
498          * declared return type, and be sure that attributes 1 .. n in the
499          * target list match the declared types.
500          */
501         reln = heap_open(typeTypeRelid(typ));
502
503         if (!RelationIsValid(reln))
504                 elog(ERROR, "cannot open relation relid %d", typeTypeRelid(typ));
505
506         relid = reln->rd_id;
507         relnatts = reln->rd_rel->relnatts;
508
509         if (exec_tlist_length(tlist) != relnatts)
510                 elog(ERROR, "function declared to return type %s does not retrieve (%s.*)", typeTypeName(typ), typeTypeName(typ));
511
512         /* expect attributes 1 .. n in order */
513         for (i = 1; i <= relnatts; i++)
514         {
515                 TargetEntry *tle = lfirst(tlist);
516                 Node       *thenode = tle->expr;
517
518                 tlist = lnext(tlist);
519                 tletype = exprType(thenode);
520
521 #if 0                                                   /* fix me */
522                 /* this is tedious */
523                 if (IsA(thenode, Var))
524                         tletype = (Oid) ((Var *) thenode)->vartype;
525                 else if (IsA(thenode, Const))
526                         tletype = (Oid) ((Const *) thenode)->consttype;
527                 else if (IsA(thenode, Param))
528                         tletype = (Oid) ((Param *) thenode)->paramtype;
529                 else if (IsA(thenode, Expr))
530                         tletype = Expr;
531
532                 else if (IsA(thenode, LispList))
533                 {
534                         thenode = lfirst(thenode);
535                         if (IsA(thenode, Oper))
536                                 tletype = (Oid) get_opresulttype((Oper *) thenode);
537                         else if (IsA(thenode, Func))
538                                 tletype = (Oid) get_functype((Func *) thenode);
539                         else
540                                 elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
541                 }
542                 else
543                         elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
544 #endif
545                 /* reach right in there, why don't you? */
546                 if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
547                         elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
548         }
549
550         heap_close(reln);
551
552         /* success */
553         return;
554 }
555
556
557