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.62 2003/01/09 20:50:51 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_operator.h"
17 #include "catalog/pg_type.h"
18 #include "nodes/makefuncs.h"
19 #include "nodes/params.h"
20 #include "optimizer/clauses.h"
21 #include "optimizer/cost.h"
22 #include "optimizer/planmain.h"
23 #include "optimizer/planner.h"
24 #include "optimizer/subselect.h"
25 #include "parser/parsetree.h"
26 #include "parser/parse_expr.h"
27 #include "parser/parse_oper.h"
28 #include "utils/syscache.h"
31 Index PlannerQueryLevel; /* level of current query */
32 List *PlannerInitPlan; /* init subplans for current query */
33 List *PlannerParamVar; /* to get Var from Param->paramid */
35 int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
37 /*--------------------
38 * PlannerParamVar is a list of Var nodes, wherein the n'th entry
39 * (n counts from 0) corresponds to Param->paramid = n. The Var nodes
40 * are ordinary except for one thing: their varlevelsup field does NOT
41 * have the usual interpretation of "subplan levels out from current".
42 * Instead, it contains the absolute plan level, with the outermost
43 * plan being level 1 and nested plans having higher level numbers.
44 * This nonstandardness is useful because we don't have to run around
45 * and update the list elements when we enter or exit a subplan
46 * recursion level. But we must pay attention not to confuse this
47 * meaning with the normal meaning of varlevelsup.
49 * We also need to create Param slots that don't correspond to any outer Var.
50 * For these, we set varno = 0 and varlevelsup = 0, so that they can't
51 * accidentally match an outer Var.
56 typedef struct finalize_primnode_results
58 List *paramids; /* List of PARAM_EXEC paramids found */
59 } finalize_primnode_results;
62 static List *convert_sublink_opers(List *operlist, List *lefthand,
63 List *targetlist, List **setParams);
64 static Node *replace_correlation_vars_mutator(Node *node, void *context);
65 static Node *process_sublinks_mutator(Node *node, void *context);
66 static bool finalize_primnode(Node *node, finalize_primnode_results *results);
70 * Create a new entry in the PlannerParamVar list, and return its index.
72 * var contains the data to use, except for varlevelsup which
73 * is set from the absolute level value given by varlevel. NOTE that
74 * the passed var is scribbled on and placed directly into the list!
75 * Generally, caller should have just created or copied it.
78 new_param(Var *var, Index varlevel)
80 var->varlevelsup = varlevel;
82 PlannerParamVar = lappend(PlannerParamVar, var);
84 return length(PlannerParamVar) - 1;
88 * Generate a Param node to replace the given Var,
89 * which is expected to have varlevelsup > 0 (ie, it is not local).
99 Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
100 varlevel = PlannerQueryLevel - var->varlevelsup;
103 * If there's already a PlannerParamVar entry for this same Var, just
104 * use it. NOTE: in sufficiently complex querytrees, it is possible
105 * for the same varno/varlevel to refer to different RTEs in different
106 * parts of the parsetree, so that different fields might end up
107 * sharing the same Param number. As long as we check the vartype as
108 * well, I believe that this sort of aliasing will cause no trouble.
109 * The correct field should get stored into the Param slot at
110 * execution in each part of the tree.
113 foreach(ppv, PlannerParamVar)
115 Var *pvar = lfirst(ppv);
117 if (pvar->varno == var->varno &&
118 pvar->varattno == var->varattno &&
119 pvar->varlevelsup == varlevel &&
120 pvar->vartype == var->vartype)
127 /* Nope, so make a new one */
128 i = new_param((Var *) copyObject(var), varlevel);
131 retval = makeNode(Param);
132 retval->paramkind = PARAM_EXEC;
133 retval->paramid = (AttrNumber) i;
134 retval->paramtype = var->vartype;
140 * Generate a new Param node that will not conflict with any other.
143 generate_new_param(Oid paramtype, int32 paramtypmod)
145 Var *var = makeVar(0, 0, paramtype, paramtypmod, 0);
146 Param *retval = makeNode(Param);
148 retval->paramkind = PARAM_EXEC;
149 retval->paramid = (AttrNumber) new_param(var, 0);
150 retval->paramtype = paramtype;
156 * Convert a bare SubLink (as created by the parser) into a SubPlan.
158 * We are given the raw SubLink and the already-processed lefthand argument
159 * list (use this instead of the SubLink's own field).
161 * The result is whatever we need to substitute in place of the SubLink
162 * node in the executable expression. This will be either the SubPlan
163 * node (if we have to do the subplan as a subplan), or a Param node
164 * representing the result of an InitPlan, or possibly an AND or OR tree
165 * containing InitPlan Param nodes.
168 make_subplan(SubLink *slink, List *lefthand)
170 SubPlan *node = makeNode(SubPlan);
171 Query *subquery = (Query *) (slink->subselect);
172 double tuple_fraction;
178 * Copy the source Query node. This is a quick and dirty kluge to
179 * resolve the fact that the parser can generate trees with multiple
180 * links to the same sub-Query node, but the planner wants to scribble
181 * on the Query. Try to clean this up when we do querytree redesign...
183 subquery = (Query *) copyObject(subquery);
186 * For an EXISTS subplan, tell lower-level planner to expect that only
187 * the first tuple will be retrieved. For ALL and ANY subplans, we
188 * will be able to stop evaluating if the test condition fails, so
189 * very often not all the tuples will be retrieved; for lack of a
190 * better idea, specify 50% retrieval. For EXPR and MULTIEXPR
191 * subplans, use default behavior (we're only expecting one row out,
194 * NOTE: if you change these numbers, also change cost_qual_eval_walker()
195 * in path/costsize.c.
197 * XXX If an ALL/ANY subplan is uncorrelated, we may decide to
198 * materialize its result below. In that case it would've been better
199 * to specify full retrieval. At present, however, we can only detect
200 * correlation or lack of it after we've made the subplan :-(. Perhaps
201 * detection of correlation should be done as a separate step.
202 * Meanwhile, we don't want to be too optimistic about the percentage
203 * of tuples retrieved, for fear of selecting a plan that's bad for
204 * the materialization case.
206 if (slink->subLinkType == EXISTS_SUBLINK)
207 tuple_fraction = 1.0; /* just like a LIMIT 1 */
208 else if (slink->subLinkType == ALL_SUBLINK ||
209 slink->subLinkType == ANY_SUBLINK)
210 tuple_fraction = 0.5; /* 50% */
212 tuple_fraction = -1.0; /* default behavior */
215 * Generate the plan for the subquery.
217 node->plan = plan = subquery_planner(subquery, tuple_fraction);
219 node->plan_id = PlannerPlanId++; /* Assign unique ID to this
222 node->rtable = subquery->rtable;
225 * Fill in other fields of the SubPlan node.
227 node->subLinkType = slink->subLinkType;
228 node->useOr = slink->useOr;
230 node->setParam = NIL;
231 node->parParam = NIL;
235 * Make parParam list of params that current query level will pass to
238 foreach(lst, plan->extParam)
240 int paramid = lfirsti(lst);
241 Var *var = nth(paramid, PlannerParamVar);
243 /* note varlevelsup is absolute level number */
244 if (var->varlevelsup == PlannerQueryLevel)
245 node->parParam = lappendi(node->parParam, paramid);
249 * Un-correlated or undirect correlated plans of EXISTS, EXPR, or
250 * MULTIEXPR types can be used as initPlans. For EXISTS or EXPR, we
251 * just produce a Param referring to the result of evaluating the
252 * initPlan. For MULTIEXPR, we must build an AND or OR-clause of the
253 * individual comparison operators, using the appropriate lefthand
254 * side expressions and Params for the initPlan's target items.
256 if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
260 prm = generate_new_param(BOOLOID, -1);
261 node->setParam = lappendi(node->setParam, prm->paramid);
262 PlannerInitPlan = lappend(PlannerInitPlan, node);
263 result = (Node *) prm;
265 else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
267 TargetEntry *te = lfirst(plan->targetlist);
270 prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
271 node->setParam = lappendi(node->setParam, prm->paramid);
272 PlannerInitPlan = lappend(PlannerInitPlan, node);
273 result = (Node *) prm;
275 else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
279 /* Convert the oper list, but don't put it into the SubPlan node */
280 oper = convert_sublink_opers(slink->oper,
284 PlannerInitPlan = lappend(PlannerInitPlan, node);
285 if (length(oper) > 1)
286 result = (Node *) (node->useOr ? make_orclause(oper) :
287 make_andclause(oper));
289 result = (Node *) lfirst(oper);
296 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
297 * to initPlans, even when they are uncorrelated or undirect
298 * correlated, because we need to scan the output of the subplan
299 * for each outer tuple. However, we have the option to tack a
300 * MATERIAL node onto the top of an uncorrelated/undirect
301 * correlated subplan, which lets us do the work of evaluating the
302 * subplan only once. We do this if the subplan's top plan node
303 * is anything more complicated than a plain sequential scan, and
304 * we do it even for seqscan if the qual appears selective enough
305 * to eliminate many tuples.
307 * XXX It's pretty ugly to be inserting a MATERIAL node at this
308 * point. Since subquery_planner has already run SS_finalize_plan
309 * on the subplan tree, we have to kluge up parameter lists for
310 * the MATERIAL node. Possibly this could be fixed by postponing
311 * SS_finalize_plan processing until setrefs.c is run.
313 if (node->parParam == NIL)
317 switch (nodeTag(plan))
326 qualsel = clauselist_selectivity(subquery,
329 /* Is 10% selectivity a good threshold?? */
330 use_material = qualsel < 0.10;
338 * Don't add another Material node if there's one
339 * already, nor if the top node is any other type that
340 * materializes its output anyway.
342 use_material = false;
351 Path matpath; /* dummy for result of cost_material */
353 matplan = (Plan *) make_material(plan->targetlist, plan);
354 /* need to calculate costs */
355 cost_material(&matpath,
359 matplan->startup_cost = matpath.startup_cost;
360 matplan->total_cost = matpath.total_cost;
361 /* parameter kluge --- see comments above */
362 matplan->extParam = listCopy(plan->extParam);
363 matplan->locParam = listCopy(plan->locParam);
364 node->plan = plan = matplan;
368 /* Convert the SubLink's oper list into executable form */
369 node->oper = convert_sublink_opers(slink->oper,
375 * Make node->args from parParam.
378 foreach(lst, node->parParam)
380 Var *var = nth(lfirsti(lst), PlannerParamVar);
382 var = (Var *) copyObject(var);
385 * Must fix absolute-level varlevelsup from the
386 * PlannerParamVar entry. But since var is at current subplan
387 * level, this is easy:
389 var->varlevelsup = 0;
390 args = lappend(args, var);
394 result = (Node *) node;
401 * convert_sublink_opers: convert a SubLink's oper list from the
402 * parser/rewriter format into the executor's format.
404 * The oper list is initially a list of OpExpr nodes with NIL args. We
405 * convert it to a list of actually executable expressions, in which the
406 * specified operators are applied to corresponding elements of the
407 * lefthand list and Params representing the results of the subplan.
409 * If setParams is not NULL, the paramids of the Params created are added
410 * to the *setParams list.
413 convert_sublink_opers(List *operlist, List *lefthand,
414 List *targetlist, List **setParams)
417 List *leftlist = lefthand;
420 foreach(lst, operlist)
422 OpExpr *oper = (OpExpr *) lfirst(lst);
423 Node *leftop = lfirst(leftlist);
424 TargetEntry *te = lfirst(targetlist);
427 Form_pg_operator opform;
431 /* Make the Param node representing the subplan's result */
432 prm = generate_new_param(te->resdom->restype,
433 te->resdom->restypmod);
435 /* Record its ID if needed */
437 *setParams = lappendi(*setParams, prm->paramid);
439 /* Look up the operator to check its declared input types */
440 Assert(IsA(oper, OpExpr));
441 tup = SearchSysCache(OPEROID,
442 ObjectIdGetDatum(oper->opno),
444 if (!HeapTupleIsValid(tup))
445 elog(ERROR, "cache lookup failed for operator %u", oper->opno);
446 opform = (Form_pg_operator) GETSTRUCT(tup);
449 * Make the expression node.
451 * Note: we use make_operand in case runtime type conversion
452 * function calls must be inserted for this operator!
454 left = make_operand(leftop, exprType(leftop), opform->oprleft);
455 right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
456 newoper = lappend(newoper,
457 make_opclause(oper->opno,
463 ReleaseSysCache(tup);
465 leftlist = lnext(leftlist);
466 targetlist = lnext(targetlist);
473 * Replace correlation vars (uplevel vars) with Params.
476 SS_replace_correlation_vars(Node *expr)
478 /* No setup needed for tree walk, so away we go */
479 return replace_correlation_vars_mutator(expr, NULL);
483 replace_correlation_vars_mutator(Node *node, void *context)
489 if (((Var *) node)->varlevelsup > 0)
490 return (Node *) replace_var((Var *) node);
492 return expression_tree_mutator(node,
493 replace_correlation_vars_mutator,
498 * Expand SubLinks to SubPlans in the given expression.
501 SS_process_sublinks(Node *expr)
503 /* No setup needed for tree walk, so away we go */
504 return process_sublinks_mutator(expr, NULL);
508 process_sublinks_mutator(Node *node, void *context)
512 if (IsA(node, SubLink))
514 SubLink *sublink = (SubLink *) node;
518 * First, recursively process the lefthand-side expressions, if any.
521 process_sublinks_mutator((Node *) sublink->lefthand, context);
523 * Now build the SubPlan node and make the expr to return.
525 return make_subplan(sublink, lefthand);
529 * Note that we will never see a SubPlan expression in the input
530 * (since this is the very routine that creates 'em to begin with). So
531 * the code in expression_tree_mutator() that might do inappropriate
532 * things with SubPlans or SubLinks will not be exercised.
534 Assert(!is_subplan(node));
536 return expression_tree_mutator(node,
537 process_sublinks_mutator,
542 * SS_finalize_plan - do final sublink processing for a completed Plan.
544 * This recursively computes and sets the extParam and locParam lists
545 * for every Plan node in the given tree.
548 SS_finalize_plan(Plan *plan, List *rtable)
550 List *extParam = NIL;
551 List *locParam = NIL;
552 finalize_primnode_results results;
558 results.paramids = NIL; /* initialize list to NIL */
561 * When we call finalize_primnode, results.paramids lists are
562 * automatically merged together. But when recursing to self, we have
563 * to do it the hard way. We want the paramids list to include params
564 * in subplans as well as at this level.
567 /* Find params in targetlist and qual */
568 finalize_primnode((Node *) plan->targetlist, &results);
569 finalize_primnode((Node *) plan->qual, &results);
571 /* Check additional node-type-specific fields */
572 switch (nodeTag(plan))
575 finalize_primnode(((Result *) plan)->resconstantqual,
580 finalize_primnode((Node *) ((IndexScan *) plan)->indxqual,
584 * we need not look at indxqualorig, since it will have the
585 * same param references as indxqual.
590 finalize_primnode((Node *) ((TidScan *) plan)->tideval,
597 * In a SubqueryScan, SS_finalize_plan has already been run on
598 * the subplan by the inner invocation of subquery_planner, so
599 * there's no need to do it again. Instead, just pull out the
600 * subplan's extParams list, which represents the params it
601 * needs from my level and higher levels.
603 results.paramids = set_unioni(results.paramids,
604 ((SubqueryScan *) plan)->subplan->extParam);
611 rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
613 Assert(rte->rtekind == RTE_FUNCTION);
614 finalize_primnode(rte->funcexpr, &results);
619 foreach(lst, ((Append *) plan)->appendplans)
620 results.paramids = set_unioni(results.paramids,
621 SS_finalize_plan((Plan *) lfirst(lst),
626 finalize_primnode((Node *) ((Join *) plan)->joinqual,
631 finalize_primnode((Node *) ((Join *) plan)->joinqual,
633 finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
638 finalize_primnode((Node *) ((Join *) plan)->joinqual,
640 finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
645 finalize_primnode((Node *) ((Hash *) plan)->hashkeys,
660 elog(ERROR, "SS_finalize_plan: node %d unsupported",
664 /* Process left and right child plans, if any */
665 results.paramids = set_unioni(results.paramids,
666 SS_finalize_plan(plan->lefttree,
668 results.paramids = set_unioni(results.paramids,
669 SS_finalize_plan(plan->righttree,
672 /* Now we have all the paramids */
674 foreach(lst, results.paramids)
676 int paramid = lfirsti(lst);
677 Var *var = nth(paramid, PlannerParamVar);
679 /* note varlevelsup is absolute level number */
680 if (var->varlevelsup < PlannerQueryLevel)
681 extParam = lappendi(extParam, paramid);
682 else if (var->varlevelsup > PlannerQueryLevel)
683 elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");
686 Assert(var->varno == 0 && var->varattno == 0);
687 locParam = lappendi(locParam, paramid);
691 plan->extParam = extParam;
692 plan->locParam = locParam;
694 return results.paramids;
698 * finalize_primnode: build lists of params appearing
699 * in the given expression tree. NOTE: items are added to list passed in,
700 * so caller must initialize list to NIL before first call!
703 finalize_primnode(Node *node, finalize_primnode_results *results)
707 if (IsA(node, Param))
709 if (((Param *) node)->paramkind == PARAM_EXEC)
711 int paramid = (int) ((Param *) node)->paramid;
713 if (!intMember(paramid, results->paramids))
714 results->paramids = lconsi(paramid, results->paramids);
716 return false; /* no more to do here */
718 if (is_subplan(node))
720 SubPlan *subplan = (SubPlan *) node;
723 /* Check extParam list for params to add to paramids */
724 foreach(lst, subplan->plan->extParam)
726 int paramid = lfirsti(lst);
727 Var *var = nth(paramid, PlannerParamVar);
729 /* note varlevelsup is absolute level number */
730 if (var->varlevelsup < PlannerQueryLevel &&
731 !intMember(paramid, results->paramids))
732 results->paramids = lconsi(paramid, results->paramids);
734 /* fall through to recurse into subplan args */
736 return expression_tree_walker(node, finalize_primnode,