1 /*-------------------------------------------------------------------------
4 * Planning routines for subselects and parameters.
6 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.99 2005/06/05 22:32:56 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_operator.h"
17 #include "catalog/pg_type.h"
18 #include "miscadmin.h"
19 #include "nodes/makefuncs.h"
20 #include "nodes/params.h"
21 #include "optimizer/clauses.h"
22 #include "optimizer/cost.h"
23 #include "optimizer/planmain.h"
24 #include "optimizer/planner.h"
25 #include "optimizer/subselect.h"
26 #include "optimizer/var.h"
27 #include "parser/parsetree.h"
28 #include "parser/parse_expr.h"
29 #include "parser/parse_oper.h"
30 #include "parser/parse_relation.h"
31 #include "rewrite/rewriteManip.h"
32 #include "utils/builtins.h"
33 #include "utils/lsyscache.h"
34 #include "utils/syscache.h"
37 Index PlannerQueryLevel; /* level of current query */
38 List *PlannerInitPlan; /* init subplans for current query */
39 List *PlannerParamList; /* to keep track of cross-level Params */
41 int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
44 * PlannerParamList keeps track of the PARAM_EXEC slots that we have decided
45 * we need for the query. At runtime these slots are used to pass values
46 * either down into subqueries (for outer references in subqueries) or up out
47 * of subqueries (for the results of a subplan). The n'th entry in the list
48 * (n counts from 0) corresponds to Param->paramid = n.
50 * Each ParamList item shows the absolute query level it is associated with,
51 * where the outermost query is level 1 and nested subqueries have higher
52 * numbers. The item the parameter slot represents can be one of three kinds:
54 * A Var: the slot represents a variable of that level that must be passed
55 * down because subqueries have outer references to it. The varlevelsup
56 * value in the Var will always be zero.
58 * An Aggref (with an expression tree representing its argument): the slot
59 * represents an aggregate expression that is an outer reference for some
60 * subquery. The Aggref itself has agglevelsup = 0, and its argument tree
61 * is adjusted to match in level.
63 * A Param: the slot holds the result of a subplan (it is a setParam item
64 * for that subplan). The absolute level shown for such items corresponds
65 * to the parent query of the subplan.
67 * Note: we detect duplicate Var parameters and coalesce them into one slot,
68 * but we do not do this for Aggref or Param slots.
70 typedef struct PlannerParamItem
72 Node *item; /* the Var, Aggref, or Param */
73 Index abslevel; /* its absolute query level */
77 typedef struct finalize_primnode_context
79 Bitmapset *paramids; /* Set of PARAM_EXEC paramids found */
80 Bitmapset *outer_params; /* Set of accessible outer paramids */
81 } finalize_primnode_context;
84 static List *convert_sublink_opers(List *lefthand, List *operOids,
85 List *targetlist, int rtindex,
87 static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
88 static Node *replace_correlation_vars_mutator(Node *node, void *context);
89 static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
90 static Bitmapset *finalize_plan(Plan *plan, List *rtable,
91 Bitmapset *outer_params,
92 Bitmapset *valid_params);
93 static bool finalize_primnode(Node *node, finalize_primnode_context *context);
97 * Generate a Param node to replace the given Var,
98 * which is expected to have varlevelsup > 0 (ie, it is not local).
101 replace_outer_var(Var *var)
105 PlannerParamItem *pitem;
109 Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
110 abslevel = PlannerQueryLevel - var->varlevelsup;
113 * If there's already a PlannerParamList entry for this same Var, just
114 * use it. NOTE: in sufficiently complex querytrees, it is possible
115 * for the same varno/abslevel to refer to different RTEs in different
116 * parts of the parsetree, so that different fields might end up
117 * sharing the same Param number. As long as we check the vartype as
118 * well, I believe that this sort of aliasing will cause no trouble.
119 * The correct field should get stored into the Param slot at
120 * execution in each part of the tree.
122 * We also need to demand a match on vartypmod. This does not matter for
123 * the Param itself, since those are not typmod-dependent, but it does
124 * matter when make_subplan() instantiates a modified copy of the Var
125 * for a subplan's args list.
128 foreach(ppl, PlannerParamList)
130 pitem = (PlannerParamItem *) lfirst(ppl);
131 if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
133 Var *pvar = (Var *) pitem->item;
135 if (pvar->varno == var->varno &&
136 pvar->varattno == var->varattno &&
137 pvar->vartype == var->vartype &&
138 pvar->vartypmod == var->vartypmod)
146 /* Nope, so make a new one */
147 var = (Var *) copyObject(var);
148 var->varlevelsup = 0;
150 pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
151 pitem->item = (Node *) var;
152 pitem->abslevel = abslevel;
154 PlannerParamList = lappend(PlannerParamList, pitem);
155 /* i is already the correct index for the new item */
158 retval = makeNode(Param);
159 retval->paramkind = PARAM_EXEC;
160 retval->paramid = (AttrNumber) i;
161 retval->paramtype = var->vartype;
167 * Generate a Param node to replace the given Aggref
168 * which is expected to have agglevelsup > 0 (ie, it is not local).
171 replace_outer_agg(Aggref *agg)
174 PlannerParamItem *pitem;
178 Assert(agg->agglevelsup > 0 && agg->agglevelsup < PlannerQueryLevel);
179 abslevel = PlannerQueryLevel - agg->agglevelsup;
182 * It does not seem worthwhile to try to match duplicate outer aggs.
183 * Just make a new slot every time.
185 agg = (Aggref *) copyObject(agg);
186 IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
187 Assert(agg->agglevelsup == 0);
189 pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
190 pitem->item = (Node *) agg;
191 pitem->abslevel = abslevel;
193 PlannerParamList = lappend(PlannerParamList, pitem);
194 i = list_length(PlannerParamList) - 1;
196 retval = makeNode(Param);
197 retval->paramkind = PARAM_EXEC;
198 retval->paramid = (AttrNumber) i;
199 retval->paramtype = agg->aggtype;
205 * Generate a new Param node that will not conflict with any other.
207 * This is used to allocate PARAM_EXEC slots for subplan outputs.
209 * paramtypmod is currently unused but might be wanted someday.
212 generate_new_param(Oid paramtype, int32 paramtypmod)
215 PlannerParamItem *pitem;
217 retval = makeNode(Param);
218 retval->paramkind = PARAM_EXEC;
219 retval->paramid = (AttrNumber) list_length(PlannerParamList);
220 retval->paramtype = paramtype;
222 pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
223 pitem->item = (Node *) retval;
224 pitem->abslevel = PlannerQueryLevel;
226 PlannerParamList = lappend(PlannerParamList, pitem);
232 * Convert a bare SubLink (as created by the parser) into a SubPlan.
234 * We are given the raw SubLink and the already-processed lefthand argument
235 * list (use this instead of the SubLink's own field). We are also told if
236 * this expression appears at top level of a WHERE/HAVING qual.
238 * The result is whatever we need to substitute in place of the SubLink
239 * node in the executable expression. This will be either the SubPlan
240 * node (if we have to do the subplan as a subplan), or a Param node
241 * representing the result of an InitPlan, or possibly an AND or OR tree
242 * containing InitPlan Param nodes.
245 make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
247 SubPlan *node = makeNode(SubPlan);
248 Query *subquery = (Query *) (slink->subselect);
249 double tuple_fraction;
256 * Copy the source Query node. This is a quick and dirty kluge to
257 * resolve the fact that the parser can generate trees with multiple
258 * links to the same sub-Query node, but the planner wants to scribble
259 * on the Query. Try to clean this up when we do querytree redesign...
261 subquery = (Query *) copyObject(subquery);
264 * For an EXISTS subplan, tell lower-level planner to expect that only
265 * the first tuple will be retrieved. For ALL and ANY subplans, we
266 * will be able to stop evaluating if the test condition fails, so
267 * very often not all the tuples will be retrieved; for lack of a
268 * better idea, specify 50% retrieval. For EXPR and MULTIEXPR
269 * subplans, use default behavior (we're only expecting one row out,
272 * NOTE: if you change these numbers, also change cost_qual_eval_walker()
273 * in path/costsize.c.
275 * XXX If an ALL/ANY subplan is uncorrelated, we may decide to hash or
276 * materialize its result below. In that case it would've been better
277 * to specify full retrieval. At present, however, we can only detect
278 * correlation or lack of it after we've made the subplan :-(. Perhaps
279 * detection of correlation should be done as a separate step.
280 * Meanwhile, we don't want to be too optimistic about the percentage
281 * of tuples retrieved, for fear of selecting a plan that's bad for
282 * the materialization case.
284 if (slink->subLinkType == EXISTS_SUBLINK)
285 tuple_fraction = 1.0; /* just like a LIMIT 1 */
286 else if (slink->subLinkType == ALL_SUBLINK ||
287 slink->subLinkType == ANY_SUBLINK)
288 tuple_fraction = 0.5; /* 50% */
290 tuple_fraction = 0.0; /* default behavior */
293 * Generate the plan for the subquery.
295 node->plan = plan = subquery_planner(subquery, tuple_fraction, NULL);
297 node->plan_id = PlannerPlanId++; /* Assign unique ID to this
300 node->rtable = subquery->rtable;
303 * Initialize other fields of the SubPlan node.
305 node->subLinkType = slink->subLinkType;
306 node->useOr = slink->useOr;
308 node->paramIds = NIL;
309 node->useHashTable = false;
310 /* At top level of a qual, can treat UNKNOWN the same as FALSE */
311 node->unknownEqFalse = isTopQual;
312 node->setParam = NIL;
313 node->parParam = NIL;
317 * Make parParam list of params that current query level will pass to
320 tmpset = bms_copy(plan->extParam);
321 while ((paramid = bms_first_member(tmpset)) >= 0)
323 PlannerParamItem *pitem = list_nth(PlannerParamList, paramid);
325 if (pitem->abslevel == PlannerQueryLevel)
326 node->parParam = lappend_int(node->parParam, paramid);
331 * Un-correlated or undirect correlated plans of EXISTS, EXPR, ARRAY,
332 * or MULTIEXPR types can be used as initPlans. For EXISTS, EXPR, or
333 * ARRAY, we just produce a Param referring to the result of
334 * evaluating the initPlan. For MULTIEXPR, we must build an AND or
335 * OR-clause of the individual comparison operators, using the
336 * appropriate lefthand side expressions and Params for the initPlan's
339 if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
343 prm = generate_new_param(BOOLOID, -1);
344 node->setParam = list_make1_int(prm->paramid);
345 PlannerInitPlan = lappend(PlannerInitPlan, node);
346 result = (Node *) prm;
348 else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
350 TargetEntry *te = linitial(plan->targetlist);
353 Assert(!te->resjunk);
354 prm = generate_new_param(exprType((Node *) te->expr),
355 exprTypmod((Node *) te->expr));
356 node->setParam = list_make1_int(prm->paramid);
357 PlannerInitPlan = lappend(PlannerInitPlan, node);
358 result = (Node *) prm;
360 else if (node->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
362 TargetEntry *te = linitial(plan->targetlist);
366 Assert(!te->resjunk);
367 arraytype = get_array_type(exprType((Node *) te->expr));
368 if (!OidIsValid(arraytype))
369 elog(ERROR, "could not find array type for datatype %s",
370 format_type_be(exprType((Node *) te->expr)));
371 prm = generate_new_param(arraytype, -1);
372 node->setParam = list_make1_int(prm->paramid);
373 PlannerInitPlan = lappend(PlannerInitPlan, node);
374 result = (Node *) prm;
376 else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
380 /* Convert the lefthand exprs and oper OIDs into executable exprs */
381 exprs = convert_sublink_opers(lefthand,
386 node->setParam = list_copy(node->paramIds);
387 PlannerInitPlan = lappend(PlannerInitPlan, node);
390 * The executable expressions are returned to become part of the
391 * outer plan's expression tree; they are not kept in the initplan
394 if (list_length(exprs) > 1)
395 result = (Node *) (node->useOr ? make_orclause(exprs) :
396 make_andclause(exprs));
398 result = (Node *) linitial(exprs);
406 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
407 * to initPlans, even when they are uncorrelated or undirect
408 * correlated, because we need to scan the output of the subplan
409 * for each outer tuple. But if it's an IN (= ANY) test, we might
410 * be able to use a hashtable to avoid comparing all the tuples.
412 if (subplan_is_hashable(slink, node))
413 node->useHashTable = true;
416 * Otherwise, we have the option to tack a MATERIAL node onto the
417 * top of the subplan, to reduce the cost of reading it
418 * repeatedly. This is pointless for a direct-correlated subplan,
419 * since we'd have to recompute its results each time anyway. For
420 * uncorrelated/undirect correlated subplans, we add MATERIAL unless
421 * the subplan's top plan node would materialize its output anyway.
423 else if (node->parParam == NIL)
427 switch (nodeTag(plan))
432 use_material = false;
439 node->plan = plan = materialize_finished_plan(plan);
442 /* Convert the lefthand exprs and oper OIDs into executable exprs */
443 node->exprs = convert_sublink_opers(lefthand,
450 * Make node->args from parParam.
453 foreach(l, node->parParam)
455 PlannerParamItem *pitem = list_nth(PlannerParamList, lfirst_int(l));
458 * The Var or Aggref has already been adjusted to have the
459 * correct varlevelsup or agglevelsup. We probably don't even
460 * need to copy it again, but be safe.
462 args = lappend(args, copyObject(pitem->item));
466 result = (Node *) node;
473 * convert_sublink_opers: given a lefthand-expressions list and a list of
474 * operator OIDs, build a list of actually executable expressions. The
475 * righthand sides of the expressions are Params or Vars representing the
476 * results of the sub-select.
478 * If rtindex is 0, we build Params to represent the sub-select outputs.
479 * The paramids of the Params created are returned in the *righthandIds list.
481 * If rtindex is not 0, we build Vars using that rtindex as varno. Copies
482 * of the Var nodes are returned in *righthandIds (this is a bit of a type
483 * cheat, but we can get away with it).
486 convert_sublink_opers(List *lefthand, List *operOids,
487 List *targetlist, int rtindex,
496 lefthand_item = list_head(lefthand);
497 tlist_item = list_head(targetlist);
501 Oid opid = lfirst_oid(l);
502 Node *leftop = (Node *) lfirst(lefthand_item);
503 TargetEntry *te = (TargetEntry *) lfirst(tlist_item);
507 Assert(!te->resjunk);
511 /* Make the Var node representing the subplan's result */
512 rightop = (Node *) makeVar(rtindex,
514 exprType((Node *) te->expr),
515 exprTypmod((Node *) te->expr),
519 * Copy it for caller. NB: we need a copy to avoid having
520 * doubly-linked substructure in the modified parse tree.
522 *righthandIds = lappend(*righthandIds, copyObject(rightop));
526 /* Make the Param node representing the subplan's result */
529 prm = generate_new_param(exprType((Node *) te->expr),
530 exprTypmod((Node *) te->expr));
532 *righthandIds = lappend_int(*righthandIds, prm->paramid);
533 rightop = (Node *) prm;
536 /* Look up the operator to pass to make_op_expr */
537 tup = SearchSysCache(OPEROID,
538 ObjectIdGetDatum(opid),
540 if (!HeapTupleIsValid(tup))
541 elog(ERROR, "cache lookup failed for operator %u", opid);
544 * Make the expression node.
546 * Note: we use make_op_expr in case runtime type conversion function
547 * calls must be inserted for this operator! (But we are not
548 * expecting to have to resolve unknown Params, so it's okay to
549 * pass a null pstate.)
551 result = lappend(result,
557 exprType((Node *) te->expr)));
559 ReleaseSysCache(tup);
561 lefthand_item = lnext(lefthand_item);
562 tlist_item = lnext(tlist_item);
569 * subplan_is_hashable: decide whether we can implement a subplan by hashing
571 * Caution: the SubPlan node is not completely filled in yet. We can rely
572 * on its plan and parParam fields, however.
575 subplan_is_hashable(SubLink *slink, SubPlan *node)
577 double subquery_size;
581 * The sublink type must be "= ANY" --- that is, an IN operator. (We
582 * require the operator name to be unqualified, which may be overly
583 * paranoid, or may not be.) XXX since we also check that the
584 * operators are hashable, the test on operator name may be redundant?
586 if (slink->subLinkType != ANY_SUBLINK)
588 if (list_length(slink->operName) != 1 ||
589 strcmp(strVal(linitial(slink->operName)), "=") != 0)
593 * The subplan must not have any direct correlation vars --- else we'd
594 * have to recompute its output each time, so that the hashtable
595 * wouldn't gain anything.
597 if (node->parParam != NIL)
601 * The estimated size of the subquery result must fit in work_mem.
602 * (XXX what about hashtable overhead?)
604 subquery_size = node->plan->plan_rows *
605 (MAXALIGN(node->plan->plan_width) + MAXALIGN(sizeof(HeapTupleData)));
606 if (subquery_size > work_mem * 1024L)
610 * The combining operators must be hashable, strict, and
611 * self-commutative. The need for hashability is obvious, since we
612 * want to use hashing. Without strictness, behavior in the presence
613 * of nulls is too unpredictable. (We actually must assume even more
614 * than plain strictness, see nodeSubplan.c for details.) And
615 * commutativity ensures that the left and right datatypes are the
616 * same; this allows us to assume that the combining operators are
617 * equality for the righthand datatype, so that they can be used to
618 * compare righthand tuples as well as comparing lefthand to righthand
619 * tuples. (This last restriction could be relaxed by using two
620 * different sets of operators with the hash table, but there is no
621 * obvious usefulness to that at present.)
623 foreach(l, slink->operOids)
625 Oid opid = lfirst_oid(l);
627 Form_pg_operator optup;
629 tup = SearchSysCache(OPEROID,
630 ObjectIdGetDatum(opid),
632 if (!HeapTupleIsValid(tup))
633 elog(ERROR, "cache lookup failed for operator %u", opid);
634 optup = (Form_pg_operator) GETSTRUCT(tup);
635 if (!optup->oprcanhash || optup->oprcom != opid ||
636 !func_strict(optup->oprcode))
638 ReleaseSysCache(tup);
641 ReleaseSysCache(tup);
647 * convert_IN_to_join: can we convert an IN SubLink to join style?
649 * The caller has found a SubLink at the top level of WHERE, but has not
650 * checked the properties of the SubLink at all. Decide whether it is
651 * appropriate to process this SubLink in join style. If not, return NULL.
652 * If so, build the qual clause(s) to replace the SubLink, and return them.
654 * Side effects of a successful conversion include adding the SubLink's
655 * subselect to the query's rangetable and adding an InClauseInfo node to
659 convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
661 Query *parse = root->parse;
662 Query *subselect = (Query *) sublink->subselect;
667 InClauseInfo *ininfo;
671 * The sublink type must be "= ANY" --- that is, an IN operator. (We
672 * require the operator name to be unqualified, which may be overly
673 * paranoid, or may not be.)
675 if (sublink->subLinkType != ANY_SUBLINK)
677 if (list_length(sublink->operName) != 1 ||
678 strcmp(strVal(linitial(sublink->operName)), "=") != 0)
682 * The sub-select must not refer to any Vars of the parent query.
683 * (Vars of higher levels should be okay, though.)
685 if (contain_vars_of_level((Node *) subselect, 1))
689 * The left-hand expressions must contain some Vars of the current
690 * query, else it's not gonna be a join.
692 left_varnos = pull_varnos((Node *) sublink->lefthand);
693 if (bms_is_empty(left_varnos))
697 * The left-hand expressions mustn't be volatile. (Perhaps we should
698 * test the combining operators, too? We'd only need to point the
699 * function directly at the sublink ...)
701 if (contain_volatile_functions((Node *) sublink->lefthand))
705 * Okay, pull up the sub-select into top range table and jointree.
707 * We rely here on the assumption that the outer query has no references
708 * to the inner (necessarily true, other than the Vars that we build
709 * below). Therefore this is a lot easier than what
710 * pull_up_subqueries has to go through.
712 rte = addRangeTableEntryForSubquery(NULL,
714 makeAlias("IN_subquery", NIL),
716 parse->rtable = lappend(parse->rtable, rte);
717 rtindex = list_length(parse->rtable);
718 rtr = makeNode(RangeTblRef);
719 rtr->rtindex = rtindex;
720 parse->jointree->fromlist = lappend(parse->jointree->fromlist, rtr);
723 * Now build the InClauseInfo node.
725 ininfo = makeNode(InClauseInfo);
726 ininfo->lefthand = left_varnos;
727 ininfo->righthand = bms_make_singleton(rtindex);
728 root->in_info_list = lappend(root->in_info_list, ininfo);
731 * Build the result qual expressions. As a side effect,
732 * ininfo->sub_targetlist is filled with a list of Vars representing
733 * the subselect outputs.
735 exprs = convert_sublink_opers(sublink->lefthand,
737 subselect->targetList,
739 &ininfo->sub_targetlist);
740 return (Node *) make_ands_explicit(exprs);
744 * Replace correlation vars (uplevel vars) with Params.
746 * Uplevel aggregates are replaced, too.
748 * Note: it is critical that this runs immediately after SS_process_sublinks.
749 * Since we do not recurse into the arguments of uplevel aggregates, they will
750 * get copied to the appropriate subplan args list in the parent query with
751 * uplevel vars not replaced by Params, but only adjusted in level (see
752 * replace_outer_agg). That's exactly what we want for the vars of the parent
753 * level --- but if an aggregate's argument contains any further-up variables,
754 * they have to be replaced with Params in their turn. That will happen when
755 * the parent level runs SS_replace_correlation_vars. Therefore it must do
756 * so after expanding its sublinks to subplans. And we don't want any steps
757 * in between, else those steps would never get applied to the aggregate
758 * argument expressions, either in the parent or the child level.
761 SS_replace_correlation_vars(Node *expr)
763 /* No setup needed for tree walk, so away we go */
764 return replace_correlation_vars_mutator(expr, NULL);
768 replace_correlation_vars_mutator(Node *node, void *context)
774 if (((Var *) node)->varlevelsup > 0)
775 return (Node *) replace_outer_var((Var *) node);
777 if (IsA(node, Aggref))
779 if (((Aggref *) node)->agglevelsup > 0)
780 return (Node *) replace_outer_agg((Aggref *) node);
782 return expression_tree_mutator(node,
783 replace_correlation_vars_mutator,
788 * Expand SubLinks to SubPlans in the given expression.
790 * The isQual argument tells whether or not this expression is a WHERE/HAVING
791 * qualifier expression. If it is, any sublinks appearing at top level need
792 * not distinguish FALSE from UNKNOWN return values.
795 SS_process_sublinks(Node *expr, bool isQual)
797 /* The only context needed is the initial are-we-in-a-qual flag */
798 return process_sublinks_mutator(expr, &isQual);
802 process_sublinks_mutator(Node *node, bool *isTopQual)
808 if (IsA(node, SubLink))
810 SubLink *sublink = (SubLink *) node;
814 * First, recursively process the lefthand-side expressions, if
819 process_sublinks_mutator((Node *) sublink->lefthand, &locTopQual);
822 * Now build the SubPlan node and make the expr to return.
824 return make_subplan(sublink, lefthand, *isTopQual);
828 * We should never see a SubPlan expression in the input (since this
829 * is the very routine that creates 'em to begin with). We shouldn't
830 * find ourselves invoked directly on a Query, either.
832 Assert(!is_subplan(node));
833 Assert(!IsA(node, Query));
836 * Because make_subplan() could return an AND or OR clause, we have to
837 * take steps to preserve AND/OR flatness of a qual. We assume the
838 * input has been AND/OR flattened and so we need no recursion here.
840 * If we recurse down through anything other than an AND node, we are
841 * definitely not at top qual level anymore. (Due to the coding here,
842 * we will not get called on the List subnodes of an AND, so no check
843 * is needed for List.)
845 if (and_clause(node))
850 /* Still at qual top-level */
851 locTopQual = *isTopQual;
853 foreach(l, ((BoolExpr *) node)->args)
857 newarg = process_sublinks_mutator(lfirst(l),
858 (void *) &locTopQual);
859 if (and_clause(newarg))
860 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
862 newargs = lappend(newargs, newarg);
864 return (Node *) make_andclause(newargs);
867 /* otherwise not at qual top-level */
875 foreach(l, ((BoolExpr *) node)->args)
879 newarg = process_sublinks_mutator(lfirst(l),
880 (void *) &locTopQual);
881 if (or_clause(newarg))
882 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
884 newargs = lappend(newargs, newarg);
886 return (Node *) make_orclause(newargs);
889 return expression_tree_mutator(node,
890 process_sublinks_mutator,
891 (void *) &locTopQual);
895 * SS_finalize_plan - do final sublink processing for a completed Plan.
897 * This recursively computes the extParam and allParam sets for every Plan
898 * node in the given plan tree. It also attaches any generated InitPlans
899 * to the top plan node.
902 SS_finalize_plan(Plan *plan, List *rtable)
904 Bitmapset *outer_params = NULL;
905 Bitmapset *valid_params = NULL;
906 Cost initplan_cost = 0;
911 * First, scan the param list to discover the sets of params that are
912 * available from outer query levels and my own query level. We do
913 * this once to save time in the per-plan recursion steps.
916 foreach(l, PlannerParamList)
918 PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
920 if (pitem->abslevel < PlannerQueryLevel)
922 /* valid outer-level parameter */
923 outer_params = bms_add_member(outer_params, paramid);
924 valid_params = bms_add_member(valid_params, paramid);
926 else if (pitem->abslevel == PlannerQueryLevel &&
927 IsA(pitem->item, Param))
929 /* valid local parameter (i.e., a setParam of my child) */
930 valid_params = bms_add_member(valid_params, paramid);
937 * Now recurse through plan tree.
939 (void) finalize_plan(plan, rtable, outer_params, valid_params);
941 bms_free(outer_params);
942 bms_free(valid_params);
945 * Finally, attach any initPlans to the topmost plan node,
946 * and add their extParams to the topmost node's, too.
948 * We also add the total_cost of each initPlan to the startup cost of
949 * the top node. This is a conservative overestimate, since in
950 * fact each initPlan might be executed later than plan startup,
951 * or even not at all.
953 plan->initPlan = PlannerInitPlan;
954 PlannerInitPlan = NIL; /* make sure they're not attached twice */
956 foreach(l, plan->initPlan)
958 SubPlan *initplan = (SubPlan *) lfirst(l);
960 plan->extParam = bms_add_members(plan->extParam,
961 initplan->plan->extParam);
962 /* allParam must include all members of extParam */
963 plan->allParam = bms_add_members(plan->allParam,
965 initplan_cost += initplan->plan->total_cost;
968 plan->startup_cost += initplan_cost;
969 plan->total_cost += initplan_cost;
973 * Recursive processing of all nodes in the plan tree
975 * The return value is the computed allParam set for the given Plan node.
976 * This is just an internal notational convenience.
979 finalize_plan(Plan *plan, List *rtable,
980 Bitmapset *outer_params, Bitmapset *valid_params)
982 finalize_primnode_context context;
987 context.paramids = NULL; /* initialize set to empty */
988 context.outer_params = outer_params;
991 * When we call finalize_primnode, context.paramids sets are
992 * automatically merged together. But when recursing to self, we have
993 * to do it the hard way. We want the paramids set to include params
994 * in subplans as well as at this level.
997 /* Find params in targetlist and qual */
998 finalize_primnode((Node *) plan->targetlist, &context);
999 finalize_primnode((Node *) plan->qual, &context);
1001 /* Check additional node-type-specific fields */
1002 switch (nodeTag(plan))
1005 finalize_primnode(((Result *) plan)->resconstantqual,
1010 finalize_primnode((Node *) ((IndexScan *) plan)->indexqual,
1014 * we need not look at indexqualorig, since it will have the
1015 * same param references as indexqual.
1019 case T_BitmapIndexScan:
1020 finalize_primnode((Node *) ((BitmapIndexScan *) plan)->indexqual,
1023 * we need not look at indexqualorig, since it will have the
1024 * same param references as indexqual.
1028 case T_BitmapHeapScan:
1029 finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
1034 finalize_primnode((Node *) ((TidScan *) plan)->tideval,
1038 case T_SubqueryScan:
1041 * In a SubqueryScan, SS_finalize_plan has already been run on
1042 * the subplan by the inner invocation of subquery_planner, so
1043 * there's no need to do it again. Instead, just pull out the
1044 * subplan's extParams list, which represents the params it
1045 * needs from my level and higher levels.
1047 context.paramids = bms_add_members(context.paramids,
1048 ((SubqueryScan *) plan)->subplan->extParam);
1051 case T_FunctionScan:
1055 rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
1057 Assert(rte->rtekind == RTE_FUNCTION);
1058 finalize_primnode(rte->funcexpr, &context);
1066 foreach(l, ((Append *) plan)->appendplans)
1069 bms_add_members(context.paramids,
1070 finalize_plan((Plan *) lfirst(l),
1082 foreach(l, ((BitmapAnd *) plan)->bitmapplans)
1085 bms_add_members(context.paramids,
1086 finalize_plan((Plan *) lfirst(l),
1098 foreach(l, ((BitmapOr *) plan)->bitmapplans)
1101 bms_add_members(context.paramids,
1102 finalize_plan((Plan *) lfirst(l),
1111 finalize_primnode((Node *) ((Join *) plan)->joinqual,
1116 finalize_primnode((Node *) ((Join *) plan)->joinqual,
1118 finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
1123 finalize_primnode((Node *) ((Join *) plan)->joinqual,
1125 finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
1130 finalize_primnode(((Limit *) plan)->limitOffset,
1132 finalize_primnode(((Limit *) plan)->limitCount,
1147 elog(ERROR, "unrecognized node type: %d",
1148 (int) nodeTag(plan));
1151 /* Process left and right child plans, if any */
1152 context.paramids = bms_add_members(context.paramids,
1153 finalize_plan(plan->lefttree,
1158 context.paramids = bms_add_members(context.paramids,
1159 finalize_plan(plan->righttree,
1164 /* Now we have all the paramids */
1166 if (!bms_is_subset(context.paramids, valid_params))
1167 elog(ERROR, "plan should not reference subplan's variable");
1169 plan->extParam = bms_intersect(context.paramids, outer_params);
1170 plan->allParam = context.paramids;
1173 * For speed at execution time, make sure extParam/allParam are
1174 * actually NULL if they are empty sets.
1176 if (bms_is_empty(plan->extParam))
1178 bms_free(plan->extParam);
1179 plan->extParam = NULL;
1181 if (bms_is_empty(plan->allParam))
1183 bms_free(plan->allParam);
1184 plan->allParam = NULL;
1187 return plan->allParam;
1191 * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given
1192 * expression tree to the result set.
1195 finalize_primnode(Node *node, finalize_primnode_context *context)
1199 if (IsA(node, Param))
1201 if (((Param *) node)->paramkind == PARAM_EXEC)
1203 int paramid = (int) ((Param *) node)->paramid;
1205 context->paramids = bms_add_member(context->paramids, paramid);
1207 return false; /* no more to do here */
1209 if (is_subplan(node))
1211 SubPlan *subplan = (SubPlan *) node;
1213 /* Add outer-level params needed by the subplan to paramids */
1214 context->paramids = bms_join(context->paramids,
1215 bms_intersect(subplan->plan->extParam,
1216 context->outer_params));
1217 /* fall through to recurse into subplan args */
1219 return expression_tree_walker(node, finalize_primnode,
1224 * SS_make_initplan_from_plan - given a plan tree, make it an InitPlan
1226 * The plan is expected to return a scalar value of the indicated type.
1227 * We build an EXPR_SUBLINK SubPlan node and put it into the initplan
1228 * list for the current query level. A Param that represents the initplan's
1229 * output is returned.
1231 * We assume the plan hasn't been put through SS_finalize_plan.
1234 SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
1235 Oid resulttype, int32 resulttypmod)
1237 List *saved_initplan = PlannerInitPlan;
1244 * Set up for a new level of subquery. This is just to keep
1245 * SS_finalize_plan from becoming confused.
1247 PlannerQueryLevel++;
1248 PlannerInitPlan = NIL;
1251 * Build extParam/allParam sets for plan nodes.
1253 SS_finalize_plan(plan, root->parse->rtable);
1255 /* Return to outer subquery context */
1256 PlannerQueryLevel--;
1257 PlannerInitPlan = saved_initplan;
1260 * Create a SubPlan node and add it to the outer list of InitPlans.
1262 node = makeNode(SubPlan);
1263 node->subLinkType = EXPR_SUBLINK;
1265 node->plan_id = PlannerPlanId++; /* Assign unique ID to this
1268 node->rtable = root->parse->rtable;
1270 PlannerInitPlan = lappend(PlannerInitPlan, node);
1273 * Make parParam list of params that current query level will pass to
1274 * this child plan. (In current usage there probably aren't any.)
1276 tmpset = bms_copy(plan->extParam);
1277 while ((paramid = bms_first_member(tmpset)) >= 0)
1279 PlannerParamItem *pitem = list_nth(PlannerParamList, paramid);
1281 if (pitem->abslevel == PlannerQueryLevel)
1282 node->parParam = lappend_int(node->parParam, paramid);
1287 * Make a Param that will be the subplan's output.
1289 prm = generate_new_param(resulttype, resulttypmod);
1290 node->setParam = list_make1_int(prm->paramid);