1 /*-------------------------------------------------------------------------
4 * Planning routines for subselects and parameters.
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.39 2000/07/12 02:37:09 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_operator.h"
17 #include "catalog/pg_type.h"
18 #include "nodes/makefuncs.h"
19 #include "optimizer/clauses.h"
20 #include "optimizer/cost.h"
21 #include "optimizer/planmain.h"
22 #include "optimizer/planner.h"
23 #include "optimizer/subselect.h"
24 #include "parser/parse_expr.h"
25 #include "parser/parse_oper.h"
26 #include "utils/lsyscache.h"
29 Index PlannerQueryLevel; /* level of current query */
30 List *PlannerInitPlan; /* init subplans for current query */
31 List *PlannerParamVar; /* to get Var from Param->paramid */
32 int PlannerPlanId; /* to assign unique ID to subquery plans */
34 /*--------------------
35 * PlannerParamVar is a list of Var nodes, wherein the n'th entry
36 * (n counts from 0) corresponds to Param->paramid = n. The Var nodes
37 * are ordinary except for one thing: their varlevelsup field does NOT
38 * have the usual interpretation of "subplan levels out from current".
39 * Instead, it contains the absolute plan level, with the outermost
40 * plan being level 1 and nested plans having higher level numbers.
41 * This nonstandardness is useful because we don't have to run around
42 * and update the list elements when we enter or exit a subplan
43 * recursion level. But we must pay attention not to confuse this
44 * meaning with the normal meaning of varlevelsup.
50 * Create a new entry in the PlannerParamVar list, and return its index.
52 * var contains the data to be copied, except for varlevelsup which
53 * is set from the absolute level value given by varlevel.
56 new_param(Var *var, Index varlevel)
58 Var *paramVar = (Var *) copyObject(var);
60 paramVar->varlevelsup = varlevel;
62 PlannerParamVar = lappend(PlannerParamVar, paramVar);
64 return length(PlannerParamVar) - 1;
68 * Generate a Param node to replace the given Var,
69 * which is expected to have varlevelsup > 0 (ie, it is not local).
79 Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
80 varlevel = PlannerQueryLevel - var->varlevelsup;
83 * If there's already a PlannerParamVar entry for this same Var, just
84 * use it. NOTE: in situations involving UNION or inheritance, it is
85 * possible for the same varno/varlevel to refer to different RTEs in
86 * different parts of the parsetree, so that different fields might
87 * end up sharing the same Param number. As long as we check the
88 * vartype as well, I believe that this sort of aliasing will cause no
89 * trouble. The correct field should get stored into the Param slot at
90 * execution in each part of the tree.
93 foreach(ppv, PlannerParamVar)
95 Var *pvar = lfirst(ppv);
97 if (pvar->varno == var->varno &&
98 pvar->varattno == var->varattno &&
99 pvar->varlevelsup == varlevel &&
100 pvar->vartype == var->vartype)
107 /* Nope, so make a new one */
108 i = new_param(var, varlevel);
111 retval = makeNode(Param);
112 retval->paramkind = PARAM_EXEC;
113 retval->paramid = (AttrNumber) i;
114 retval->paramtype = var->vartype;
120 * Convert a bare SubLink (as created by the parser) into a SubPlan.
123 make_subplan(SubLink *slink)
125 SubPlan *node = makeNode(SubPlan);
126 Query *subquery = (Query *) (slink->subselect);
127 double tuple_fraction;
131 List *saved_ip = PlannerInitPlan;
133 PlannerInitPlan = NULL;
135 PlannerQueryLevel++; /* we become child */
137 /* Check to see if this node was already processed; if so we have
138 * trouble. Someday should change tree representation so that we can
139 * cope with multiple links to the same subquery, but for now...
141 if (subquery == NULL)
142 elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)");
145 * For an EXISTS subplan, tell lower-level planner to expect that only
146 * the first tuple will be retrieved. For ALL and ANY subplans, we
147 * will be able to stop evaluating if the test condition fails, so
148 * very often not all the tuples will be retrieved; for lack of a
149 * better idea, specify 50% retrieval. For EXPR and MULTIEXPR
150 * subplans, use default behavior (we're only expecting one row out,
153 * NOTE: if you change these numbers, also change cost_qual_eval_walker()
154 * in path/costsize.c.
156 * XXX If an ALL/ANY subplan is uncorrelated, we may decide to
157 * materialize its result below. In that case it would've been better
158 * to specify full retrieval. At present, however, we can only detect
159 * correlation or lack of it after we've made the subplan :-(. Perhaps
160 * detection of correlation should be done as a separate step.
161 * Meanwhile, we don't want to be too optimistic about the percentage
162 * of tuples retrieved, for fear of selecting a plan that's bad for
163 * the materialization case.
165 if (slink->subLinkType == EXISTS_SUBLINK)
166 tuple_fraction = 1.0; /* just like a LIMIT 1 */
167 else if (slink->subLinkType == ALL_SUBLINK ||
168 slink->subLinkType == ANY_SUBLINK)
169 tuple_fraction = 0.5; /* 50% */
171 tuple_fraction = -1.0; /* default behavior */
173 node->plan = plan = subquery_planner(subquery, tuple_fraction);
176 * Assign subPlan, extParam and locParam to plan nodes. At the moment,
177 * SS_finalize_plan doesn't handle initPlan-s and so we assign them to
178 * the topmost plan node and take care about its extParam too.
180 (void) SS_finalize_plan(plan);
181 plan->initPlan = PlannerInitPlan;
183 /* Create extParam list as union of InitPlan-s' lists */
184 foreach(lst, PlannerInitPlan)
188 foreach(lp, ((SubPlan *) lfirst(lst))->plan->extParam)
190 if (!intMember(lfirsti(lp), plan->extParam))
191 plan->extParam = lappendi(plan->extParam, lfirsti(lp));
195 /* and now we are parent again */
196 PlannerInitPlan = saved_ip;
199 node->plan_id = PlannerPlanId++;
200 node->rtable = subquery->rtable;
201 node->sublink = slink;
202 slink->subselect = NULL; /* cool ?! see error check above! */
204 /* make parParam list of params coming from current query level */
205 foreach(lst, plan->extParam)
207 Var *var = nth(lfirsti(lst), PlannerParamVar);
209 /* note varlevelsup is absolute level number */
210 if (var->varlevelsup == PlannerQueryLevel)
211 node->parParam = lappendi(node->parParam, lfirsti(lst));
215 * Un-correlated or undirect correlated plans of EXISTS, EXPR, or
216 * MULTIEXPR types can be used as initPlans. For EXISTS or EXPR, we
217 * just produce a Param referring to the result of evaluating the
218 * initPlan. For MULTIEXPR, we must build an AND or OR-clause of the
219 * individual comparison operators, using the appropriate lefthand
220 * side expressions and Params for the initPlan's target items.
222 if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
224 Var *var = makeVar(0, 0, BOOLOID, -1, 0);
225 Param *prm = makeNode(Param);
227 prm->paramkind = PARAM_EXEC;
228 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
229 prm->paramtype = var->vartype;
230 pfree(var); /* var is only needed for new_param */
231 node->setParam = lappendi(node->setParam, prm->paramid);
232 PlannerInitPlan = lappend(PlannerInitPlan, node);
233 result = (Node *) prm;
235 else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
237 TargetEntry *te = lfirst(plan->targetlist);
239 /* need a var node just to pass to new_param()... */
240 Var *var = makeVar(0, 0, te->resdom->restype,
241 te->resdom->restypmod, 0);
242 Param *prm = makeNode(Param);
244 prm->paramkind = PARAM_EXEC;
245 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
246 prm->paramtype = var->vartype;
247 pfree(var); /* var is only needed for new_param */
248 node->setParam = lappendi(node->setParam, prm->paramid);
249 PlannerInitPlan = lappend(PlannerInitPlan, node);
250 result = (Node *) prm;
252 else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
258 * Convert oper list of Opers into a list of Exprs, using lefthand
259 * arguments and Params representing inside results.
261 foreach(lst, slink->oper)
263 Oper *oper = (Oper *) lfirst(lst);
264 Node *lefthand = nth(i, slink->lefthand);
265 TargetEntry *te = nth(i, plan->targetlist);
267 /* need a var node just to pass to new_param()... */
268 Var *var = makeVar(0, 0, te->resdom->restype,
269 te->resdom->restypmod, 0);
270 Param *prm = makeNode(Param);
272 Form_pg_operator opform;
276 prm->paramkind = PARAM_EXEC;
277 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
278 prm->paramtype = var->vartype;
279 pfree(var); /* var is only needed for new_param */
281 Assert(IsA(oper, Oper));
282 tup = get_operator_tuple(oper->opno);
283 Assert(HeapTupleIsValid(tup));
284 opform = (Form_pg_operator) GETSTRUCT(tup);
287 * Note: we use make_operand in case runtime type conversion
288 * function calls must be inserted for this operator!
290 left = make_operand("", lefthand,
291 exprType(lefthand), opform->oprleft);
292 right = make_operand("", (Node *) prm,
293 prm->paramtype, opform->oprright);
294 newoper = lappend(newoper,
298 node->setParam = lappendi(node->setParam, prm->paramid);
301 slink->oper = newoper;
302 slink->lefthand = NIL;
303 PlannerInitPlan = lappend(PlannerInitPlan, node);
305 result = (Node *) ((slink->useor) ? make_orclause(newoper) :
306 make_andclause(newoper));
308 result = (Node *) lfirst(newoper);
312 Expr *expr = makeNode(Expr);
318 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
319 * to initPlans, even when they are uncorrelated or undirect
320 * correlated, because we need to scan the output of the subplan
321 * for each outer tuple. However, we have the option to tack a
322 * MATERIAL node onto the top of an uncorrelated/undirect
323 * correlated subplan, which lets us do the work of evaluating the
324 * subplan only once. We do this if the subplan's top plan node
325 * is anything more complicated than a plain sequential scan, and
326 * we do it even for seqscan if the qual appears selective enough
327 * to eliminate many tuples.
329 if (node->parParam == NIL)
333 switch (nodeTag(plan))
336 if (plan->initPlan || plan->subPlan)
342 qualsel = clauselist_selectivity(subquery,
345 /* Is 10% selectivity a good threshold?? */
346 use_material = qualsel < 0.10;
353 * Don't add another Material node if there's one
354 * already, nor if the top node is a Sort, since Sort
355 * materializes its output anyway. (I doubt either
356 * case can happen in practice for a subplan, but...)
358 use_material = false;
366 plan = (Plan *) make_material(plan->targetlist, plan);
372 * Make expression of SUBPLAN type
374 expr->typeOid = BOOLOID;/* bogus, but we don't really care */
375 expr->opType = SUBPLAN_EXPR;
376 expr->oper = (Node *) node;
379 * Make expr->args from parParam.
381 foreach(lst, node->parParam)
383 Var *var = nth(lfirsti(lst), PlannerParamVar);
385 var = (Var *) copyObject(var);
388 * Must fix absolute-level varlevelsup from the
389 * PlannerParamVar entry. But since var is at current subplan
390 * level, this is easy:
392 var->varlevelsup = 0;
393 args = lappend(args, var);
398 * Convert oper list of Opers into a list of Exprs, using lefthand
399 * arguments and Consts representing inside results.
401 foreach(lst, slink->oper)
403 Oper *oper = (Oper *) lfirst(lst);
404 Node *lefthand = nth(i, slink->lefthand);
405 TargetEntry *te = nth(i, plan->targetlist);
408 Form_pg_operator opform;
413 * XXX really ought to fill in constlen and constbyval
414 * correctly, but right now ExecEvalExpr won't look at them...
416 con = makeConst(te->resdom->restype, 0, 0, true, 0, 0, 0);
418 Assert(IsA(oper, Oper));
419 tup = get_operator_tuple(oper->opno);
420 Assert(HeapTupleIsValid(tup));
421 opform = (Form_pg_operator) GETSTRUCT(tup);
424 * Note: we use make_operand in case runtime type conversion
425 * function calls must be inserted for this operator!
427 left = make_operand("", lefthand,
428 exprType(lefthand), opform->oprleft);
429 right = make_operand("", (Node *) con,
430 con->consttype, opform->oprright);
431 newoper = lappend(newoper,
437 slink->oper = newoper;
438 slink->lefthand = NIL;
439 result = (Node *) expr;
445 /* this oughta be merged with LispUnioni */
448 set_unioni(List *l1, List *l2)
455 return nconc(l1, set_differencei(l2, l1));
459 * finalize_primnode: build lists of subplans and params appearing
460 * in the given expression tree. NOTE: items are added to lists passed in,
461 * so caller must initialize lists to NIL before first call!
463 * Note: the subplan list that is constructed here and assigned to the
464 * plan's subPlan field will be replaced with an up-to-date list in
465 * set_plan_references(). We could almost dispense with building this
466 * subplan list at all; I believe the only place that uses it is the
467 * check in make_subplan to see whether a subselect has any subselects.
470 typedef struct finalize_primnode_results
472 List *subplans; /* List of subplans found in expr */
473 List *paramids; /* List of PARAM_EXEC paramids found */
474 } finalize_primnode_results;
477 finalize_primnode(Node *node, finalize_primnode_results *results)
481 if (IsA(node, Param))
483 if (((Param *) node)->paramkind == PARAM_EXEC)
485 int paramid = (int) ((Param *) node)->paramid;
487 if (!intMember(paramid, results->paramids))
488 results->paramids = lconsi(paramid, results->paramids);
490 return false; /* no more to do here */
492 if (is_subplan(node))
494 SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper;
497 /* Add subplan to subplans list */
498 results->subplans = lappend(results->subplans, subplan);
499 /* Check extParam list for params to add to paramids */
500 foreach(lst, subplan->plan->extParam)
502 int paramid = lfirsti(lst);
503 Var *var = nth(paramid, PlannerParamVar);
505 /* note varlevelsup is absolute level number */
506 if (var->varlevelsup < PlannerQueryLevel &&
507 !intMember(paramid, results->paramids))
508 results->paramids = lconsi(paramid, results->paramids);
510 /* fall through to recurse into subplan args */
512 return expression_tree_walker(node, finalize_primnode,
517 * Replace correlation vars (uplevel vars) with Params.
520 static Node *replace_correlation_vars_mutator(Node *node, void *context);
523 SS_replace_correlation_vars(Node *expr)
525 /* No setup needed for tree walk, so away we go */
526 return replace_correlation_vars_mutator(expr, NULL);
530 replace_correlation_vars_mutator(Node *node, void *context)
536 if (((Var *) node)->varlevelsup > 0)
537 return (Node *) replace_var((Var *) node);
539 return expression_tree_mutator(node,
540 replace_correlation_vars_mutator,
545 * Expand SubLinks to SubPlans in the given expression.
548 static Node *process_sublinks_mutator(Node *node, void *context);
551 SS_process_sublinks(Node *expr)
553 /* No setup needed for tree walk, so away we go */
554 return process_sublinks_mutator(expr, NULL);
558 process_sublinks_mutator(Node *node, void *context)
562 if (IsA(node, SubLink))
564 SubLink *sublink = (SubLink *) node;
567 * First, scan the lefthand-side expressions, if any. This is a
568 * tad klugy since we modify the input SubLink node, but that
569 * should be OK (make_subplan does it too!)
571 sublink->lefthand = (List *)
572 process_sublinks_mutator((Node *) sublink->lefthand, context);
573 /* Now build the SubPlan node and make the expr to return */
574 return make_subplan(sublink);
578 * Note that we will never see a SubPlan expression in the input
579 * (since this is the very routine that creates 'em to begin with). So
580 * the code in expression_tree_mutator() that might do inappropriate
581 * things with SubPlans or SubLinks will not be exercised.
583 Assert(!is_subplan(node));
585 return expression_tree_mutator(node,
586 process_sublinks_mutator,
591 SS_finalize_plan(Plan *plan)
593 List *extParam = NIL;
594 List *locParam = NIL;
595 finalize_primnode_results results;
601 results.subplans = NIL; /* initialize lists to NIL */
602 results.paramids = NIL;
605 * When we call finalize_primnode, results.paramids lists are
606 * automatically merged together. But when recursing to self, we have
607 * to do it the hard way. We want the paramids list to include params
608 * in subplans as well as at this level. (We don't care about finding
609 * subplans of subplans, though.)
612 /* Find params and subplans in targetlist and qual */
613 finalize_primnode((Node *) plan->targetlist, &results);
614 finalize_primnode((Node *) plan->qual, &results);
616 /* Check additional node-type-specific fields */
617 switch (nodeTag(plan))
620 finalize_primnode(((Result *) plan)->resconstantqual,
625 foreach(lst, ((Append *) plan)->appendplans)
626 results.paramids = set_unioni(results.paramids,
627 SS_finalize_plan((Plan *) lfirst(lst)));
631 finalize_primnode((Node *) ((IndexScan *) plan)->indxqual,
635 * we need not look at indxqualorig, since it will have the
636 * same param references as indxqual, and we aren't really
637 * concerned yet about having a complete subplan list.
642 finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
647 finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
652 finalize_primnode(((Hash *) plan)->hashkey,
657 finalize_primnode((Node *) ((TidScan *) plan)->tideval,
671 elog(ERROR, "SS_finalize_plan: node %d unsupported",
675 /* Process left and right subplans, if any */
676 results.paramids = set_unioni(results.paramids,
677 SS_finalize_plan(plan->lefttree));
678 results.paramids = set_unioni(results.paramids,
679 SS_finalize_plan(plan->righttree));
681 /* Now we have all the paramids and subplans */
683 foreach(lst, results.paramids)
685 Var *var = nth(lfirsti(lst), PlannerParamVar);
687 /* note varlevelsup is absolute level number */
688 if (var->varlevelsup < PlannerQueryLevel)
689 extParam = lappendi(extParam, lfirsti(lst));
690 else if (var->varlevelsup > PlannerQueryLevel)
691 elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");
694 Assert(var->varno == 0 && var->varattno == 0);
695 locParam = lappendi(locParam, lfirsti(lst));
699 plan->extParam = extParam;
700 plan->locParam = locParam;
701 plan->subPlan = results.subplans;
703 return results.paramids;