1 /*-------------------------------------------------------------------------
4 * Planning routines for subselects and parameters.
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.54 2002/06/20 20:29:31 momjian 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/parsetree.h"
25 #include "parser/parse_expr.h"
26 #include "parser/parse_oper.h"
27 #include "utils/syscache.h"
30 Index PlannerQueryLevel; /* level of current query */
31 List *PlannerInitPlan; /* init subplans for current query */
32 List *PlannerParamVar; /* to get Var from Param->paramid */
34 int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
36 /*--------------------
37 * PlannerParamVar is a list of Var nodes, wherein the n'th entry
38 * (n counts from 0) corresponds to Param->paramid = n. The Var nodes
39 * are ordinary except for one thing: their varlevelsup field does NOT
40 * have the usual interpretation of "subplan levels out from current".
41 * Instead, it contains the absolute plan level, with the outermost
42 * plan being level 1 and nested plans having higher level numbers.
43 * This nonstandardness is useful because we don't have to run around
44 * and update the list elements when we enter or exit a subplan
45 * recursion level. But we must pay attention not to confuse this
46 * meaning with the normal meaning of varlevelsup.
52 * Create a new entry in the PlannerParamVar list, and return its index.
54 * var contains the data to be copied, except for varlevelsup which
55 * is set from the absolute level value given by varlevel.
58 new_param(Var *var, Index varlevel)
60 Var *paramVar = (Var *) copyObject(var);
62 paramVar->varlevelsup = varlevel;
64 PlannerParamVar = lappend(PlannerParamVar, paramVar);
66 return length(PlannerParamVar) - 1;
70 * Generate a Param node to replace the given Var,
71 * which is expected to have varlevelsup > 0 (ie, it is not local).
81 Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
82 varlevel = PlannerQueryLevel - var->varlevelsup;
85 * If there's already a PlannerParamVar entry for this same Var, just
86 * use it. NOTE: in sufficiently complex querytrees, it is possible
87 * for the same varno/varlevel to refer to different RTEs in different
88 * parts of the parsetree, so that different fields might end up
89 * sharing the same Param number. As long as we check the vartype as
90 * well, I believe that this sort of aliasing will cause no trouble.
91 * The correct field should get stored into the Param slot at
92 * execution in each part of the tree.
95 foreach(ppv, PlannerParamVar)
97 Var *pvar = lfirst(ppv);
99 if (pvar->varno == var->varno &&
100 pvar->varattno == var->varattno &&
101 pvar->varlevelsup == varlevel &&
102 pvar->vartype == var->vartype)
109 /* Nope, so make a new one */
110 i = new_param(var, varlevel);
113 retval = makeNode(Param);
114 retval->paramkind = PARAM_EXEC;
115 retval->paramid = (AttrNumber) i;
116 retval->paramtype = var->vartype;
122 * Convert a bare SubLink (as created by the parser) into a SubPlan.
125 make_subplan(SubLink *slink)
127 SubPlan *node = makeNode(SubPlan);
128 Query *subquery = (Query *) (slink->subselect);
129 Oid result_type = exprType((Node *) slink);
130 double tuple_fraction;
136 * Check to see if this node was already processed; if so we have
137 * trouble. We check to see if the linked-to Query appears to have
138 * been planned already, too.
140 if (subquery == NULL)
141 elog(ERROR, "make_subplan: invalid expression structure (SubLink already processed?)");
142 if (subquery->base_rel_list != NIL)
143 elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)");
146 * Copy the source Query node. This is a quick and dirty kluge to
147 * resolve the fact that the parser can generate trees with multiple
148 * links to the same sub-Query node, but the planner wants to scribble
149 * on the Query. Try to clean this up when we do querytree redesign...
151 subquery = (Query *) copyObject(subquery);
154 * For an EXISTS subplan, tell lower-level planner to expect that only
155 * the first tuple will be retrieved. For ALL and ANY subplans, we
156 * will be able to stop evaluating if the test condition fails, so
157 * very often not all the tuples will be retrieved; for lack of a
158 * better idea, specify 50% retrieval. For EXPR and MULTIEXPR
159 * subplans, use default behavior (we're only expecting one row out,
162 * NOTE: if you change these numbers, also change cost_qual_eval_walker()
163 * in path/costsize.c.
165 * XXX If an ALL/ANY subplan is uncorrelated, we may decide to
166 * materialize its result below. In that case it would've been better
167 * to specify full retrieval. At present, however, we can only detect
168 * correlation or lack of it after we've made the subplan :-(. Perhaps
169 * detection of correlation should be done as a separate step.
170 * Meanwhile, we don't want to be too optimistic about the percentage
171 * of tuples retrieved, for fear of selecting a plan that's bad for
172 * the materialization case.
174 if (slink->subLinkType == EXISTS_SUBLINK)
175 tuple_fraction = 1.0; /* just like a LIMIT 1 */
176 else if (slink->subLinkType == ALL_SUBLINK ||
177 slink->subLinkType == ANY_SUBLINK)
178 tuple_fraction = 0.5; /* 50% */
180 tuple_fraction = -1.0; /* default behavior */
183 * Generate the plan for the subquery.
185 node->plan = plan = subquery_planner(subquery, tuple_fraction);
187 node->plan_id = PlannerPlanId++; /* Assign unique ID to this
190 node->rtable = subquery->rtable;
191 node->sublink = slink;
193 slink->subselect = NULL; /* cool ?! see error check above! */
196 * Make parParam list of params that current query level will pass to
199 foreach(lst, plan->extParam)
201 int paramid = lfirsti(lst);
202 Var *var = nth(paramid, PlannerParamVar);
204 /* note varlevelsup is absolute level number */
205 if (var->varlevelsup == PlannerQueryLevel)
206 node->parParam = lappendi(node->parParam, paramid);
210 * Un-correlated or undirect correlated plans of EXISTS, EXPR, or
211 * MULTIEXPR types can be used as initPlans. For EXISTS or EXPR, we
212 * just produce a Param referring to the result of evaluating the
213 * initPlan. For MULTIEXPR, we must build an AND or OR-clause of the
214 * individual comparison operators, using the appropriate lefthand
215 * side expressions and Params for the initPlan's target items.
217 if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
219 Var *var = makeVar(0, 0, BOOLOID, -1, 0);
220 Param *prm = makeNode(Param);
222 prm->paramkind = PARAM_EXEC;
223 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
224 prm->paramtype = var->vartype;
225 pfree(var); /* var is only needed for new_param */
226 node->setParam = lappendi(node->setParam, prm->paramid);
227 PlannerInitPlan = lappend(PlannerInitPlan, node);
228 result = (Node *) prm;
230 else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
232 TargetEntry *te = lfirst(plan->targetlist);
234 /* need a var node just to pass to new_param()... */
235 Var *var = makeVar(0, 0, te->resdom->restype,
236 te->resdom->restypmod, 0);
237 Param *prm = makeNode(Param);
239 prm->paramkind = PARAM_EXEC;
240 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
241 prm->paramtype = var->vartype;
242 pfree(var); /* var is only needed for new_param */
243 node->setParam = lappendi(node->setParam, prm->paramid);
244 PlannerInitPlan = lappend(PlannerInitPlan, node);
245 result = (Node *) prm;
247 else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
253 * Convert oper list of Opers into a list of Exprs, using lefthand
254 * arguments and Params representing inside results.
256 foreach(lst, slink->oper)
258 Oper *oper = (Oper *) lfirst(lst);
259 Node *lefthand = nth(i, slink->lefthand);
260 TargetEntry *te = nth(i, plan->targetlist);
262 /* need a var node just to pass to new_param()... */
263 Var *var = makeVar(0, 0, te->resdom->restype,
264 te->resdom->restypmod, 0);
265 Param *prm = makeNode(Param);
267 Form_pg_operator opform;
271 prm->paramkind = PARAM_EXEC;
272 prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
273 prm->paramtype = var->vartype;
274 pfree(var); /* var is only needed for new_param */
276 Assert(IsA(oper, Oper));
277 tup = SearchSysCache(OPEROID,
278 ObjectIdGetDatum(oper->opno),
280 if (!HeapTupleIsValid(tup))
281 elog(ERROR, "cache lookup failed for operator %u", oper->opno);
282 opform = (Form_pg_operator) GETSTRUCT(tup);
285 * Note: we use make_operand in case runtime type conversion
286 * function calls must be inserted for this operator!
288 left = make_operand(lefthand,
289 exprType(lefthand), opform->oprleft);
290 right = make_operand((Node *) prm,
291 prm->paramtype, opform->oprright);
292 ReleaseSysCache(tup);
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 * XXX It's pretty ugly to be inserting a MATERIAL node at this
330 * point. Since subquery_planner has already run SS_finalize_plan
331 * on the subplan tree, we have to kluge up parameter lists for
332 * the MATERIAL node. Possibly this could be fixed by postponing
333 * SS_finalize_plan processing until setrefs.c is run.
335 if (node->parParam == NIL)
339 switch (nodeTag(plan))
342 if (plan->initPlan || plan->subPlan)
348 qualsel = clauselist_selectivity(subquery,
351 /* Is 10% selectivity a good threshold?? */
352 use_material = qualsel < 0.10;
360 * Don't add another Material node if there's one
361 * already, nor if the top node is any other type that
362 * materializes its output anyway.
364 use_material = false;
374 matplan = (Plan *) make_material(plan->targetlist, plan);
375 /* kluge --- see comments above */
376 matplan->extParam = listCopy(plan->extParam);
377 matplan->locParam = listCopy(plan->locParam);
378 node->plan = plan = matplan;
383 * Make expression of SUBPLAN type
385 expr->typeOid = result_type;
386 expr->opType = SUBPLAN_EXPR;
387 expr->oper = (Node *) node;
390 * Make expr->args from parParam.
392 foreach(lst, node->parParam)
394 Var *var = nth(lfirsti(lst), PlannerParamVar);
396 var = (Var *) copyObject(var);
399 * Must fix absolute-level varlevelsup from the
400 * PlannerParamVar entry. But since var is at current subplan
401 * level, this is easy:
403 var->varlevelsup = 0;
404 args = lappend(args, var);
409 * Convert oper list of Opers into a list of Exprs, using lefthand
410 * arguments and Consts representing inside results.
412 foreach(lst, slink->oper)
414 Oper *oper = (Oper *) lfirst(lst);
415 Node *lefthand = nth(i, slink->lefthand);
416 TargetEntry *te = nth(i, plan->targetlist);
419 Form_pg_operator opform;
423 con = makeNullConst(te->resdom->restype);
425 Assert(IsA(oper, Oper));
426 tup = SearchSysCache(OPEROID,
427 ObjectIdGetDatum(oper->opno),
429 if (!HeapTupleIsValid(tup))
430 elog(ERROR, "cache lookup failed for operator %u", oper->opno);
431 opform = (Form_pg_operator) GETSTRUCT(tup);
434 * Note: we use make_operand in case runtime type conversion
435 * function calls must be inserted for this operator!
437 left = make_operand(lefthand,
438 exprType(lefthand), opform->oprleft);
439 right = make_operand((Node *) con,
440 con->consttype, opform->oprright);
441 ReleaseSysCache(tup);
443 newoper = lappend(newoper,
449 slink->oper = newoper;
450 slink->lefthand = NIL;
451 result = (Node *) expr;
458 * finalize_primnode: build lists of subplans and params appearing
459 * in the given expression tree. NOTE: items are added to lists passed in,
460 * so caller must initialize lists to NIL before first call!
462 * Note: the subplan list that is constructed here and assigned to the
463 * plan's subPlan field will be replaced with an up-to-date list in
464 * set_plan_references(). We could almost dispense with building this
465 * subplan list at all; I believe the only place that uses it is the
466 * check in make_subplan to see whether a subselect has any subselects.
469 typedef struct finalize_primnode_results
471 List *subplans; /* List of subplans found in expr */
472 List *paramids; /* List of PARAM_EXEC paramids found */
473 } finalize_primnode_results;
476 finalize_primnode(Node *node, finalize_primnode_results *results)
480 if (IsA(node, Param))
482 if (((Param *) node)->paramkind == PARAM_EXEC)
484 int paramid = (int) ((Param *) node)->paramid;
486 if (!intMember(paramid, results->paramids))
487 results->paramids = lconsi(paramid, results->paramids);
489 return false; /* no more to do here */
491 if (is_subplan(node))
493 SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper;
496 /* Add subplan to subplans list */
497 results->subplans = lappend(results->subplans, subplan);
498 /* Check extParam list for params to add to paramids */
499 foreach(lst, subplan->plan->extParam)
501 int paramid = lfirsti(lst);
502 Var *var = nth(paramid, PlannerParamVar);
504 /* note varlevelsup is absolute level number */
505 if (var->varlevelsup < PlannerQueryLevel &&
506 !intMember(paramid, results->paramids))
507 results->paramids = lconsi(paramid, results->paramids);
509 /* fall through to recurse into subplan args */
511 return expression_tree_walker(node, finalize_primnode,
516 * Replace correlation vars (uplevel vars) with Params.
519 static Node *replace_correlation_vars_mutator(Node *node, void *context);
522 SS_replace_correlation_vars(Node *expr)
524 /* No setup needed for tree walk, so away we go */
525 return replace_correlation_vars_mutator(expr, NULL);
529 replace_correlation_vars_mutator(Node *node, void *context)
535 if (((Var *) node)->varlevelsup > 0)
536 return (Node *) replace_var((Var *) node);
538 return expression_tree_mutator(node,
539 replace_correlation_vars_mutator,
544 * Expand SubLinks to SubPlans in the given expression.
547 static Node *process_sublinks_mutator(Node *node, void *context);
550 SS_process_sublinks(Node *expr)
552 /* No setup needed for tree walk, so away we go */
553 return process_sublinks_mutator(expr, NULL);
557 process_sublinks_mutator(Node *node, void *context)
561 if (IsA(node, SubLink))
563 SubLink *sublink = (SubLink *) node;
566 * First, scan the lefthand-side expressions, if any. This is a
567 * tad klugy since we modify the input SubLink node, but that
568 * should be OK (make_subplan does it too!)
570 sublink->lefthand = (List *)
571 process_sublinks_mutator((Node *) sublink->lefthand, context);
572 /* Now build the SubPlan node and make the expr to return */
573 return make_subplan(sublink);
577 * Note that we will never see a SubPlan expression in the input
578 * (since this is the very routine that creates 'em to begin with). So
579 * the code in expression_tree_mutator() that might do inappropriate
580 * things with SubPlans or SubLinks will not be exercised.
582 Assert(!is_subplan(node));
584 return expression_tree_mutator(node,
585 process_sublinks_mutator,
590 SS_finalize_plan(Plan *plan, List *rtable)
592 List *extParam = NIL;
593 List *locParam = NIL;
594 finalize_primnode_results results;
600 results.subplans = NIL; /* initialize lists to NIL */
601 results.paramids = NIL;
604 * When we call finalize_primnode, results.paramids lists are
605 * automatically merged together. But when recursing to self, we have
606 * to do it the hard way. We want the paramids list to include params
607 * in subplans as well as at this level. (We don't care about finding
608 * subplans of subplans, though.)
611 /* Find params and subplans in targetlist and qual */
612 finalize_primnode((Node *) plan->targetlist, &results);
613 finalize_primnode((Node *) plan->qual, &results);
615 /* Check additional node-type-specific fields */
616 switch (nodeTag(plan))
619 finalize_primnode(((Result *) plan)->resconstantqual,
624 finalize_primnode((Node *) ((IndexScan *) plan)->indxqual,
628 * we need not look at indxqualorig, since it will have the
629 * same param references as indxqual, and we aren't really
630 * concerned yet about having a complete subplan list.
635 finalize_primnode((Node *) ((TidScan *) plan)->tideval,
642 * In a SubqueryScan, SS_finalize_plan has already been run on
643 * the subplan by the inner invocation of subquery_planner, so
644 * there's no need to do it again. Instead, just pull out the
645 * subplan's extParams list, which represents the params it
646 * needs from my level and higher levels.
648 results.paramids = set_unioni(results.paramids,
649 ((SubqueryScan *) plan)->subplan->extParam);
656 rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
658 Assert(rte->rtekind == RTE_FUNCTION);
659 finalize_primnode(rte->funcexpr, &results);
664 foreach(lst, ((Append *) plan)->appendplans)
665 results.paramids = set_unioni(results.paramids,
666 SS_finalize_plan((Plan *) lfirst(lst),
671 finalize_primnode((Node *) ((Join *) plan)->joinqual,
676 finalize_primnode((Node *) ((Join *) plan)->joinqual,
678 finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
683 finalize_primnode((Node *) ((Join *) plan)->joinqual,
685 finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
690 finalize_primnode(((Hash *) plan)->hashkey,
705 elog(ERROR, "SS_finalize_plan: node %d unsupported",
709 /* Process left and right subplans, if any */
710 results.paramids = set_unioni(results.paramids,
711 SS_finalize_plan(plan->lefttree,
713 results.paramids = set_unioni(results.paramids,
714 SS_finalize_plan(plan->righttree,
717 /* Now we have all the paramids and subplans */
719 foreach(lst, results.paramids)
721 int paramid = lfirsti(lst);
722 Var *var = nth(paramid, PlannerParamVar);
724 /* note varlevelsup is absolute level number */
725 if (var->varlevelsup < PlannerQueryLevel)
726 extParam = lappendi(extParam, paramid);
727 else if (var->varlevelsup > PlannerQueryLevel)
728 elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");
731 Assert(var->varno == 0 && var->varattno == 0);
732 locParam = lappendi(locParam, paramid);
736 plan->extParam = extParam;
737 plan->locParam = locParam;
738 plan->subPlan = results.subplans;
740 return results.paramids;