]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/plan/subselect.c
Repair subselect.c's occasional assignment of the wrong vartypmod to
[postgresql] / src / backend / optimizer / plan / subselect.c
1 /*-------------------------------------------------------------------------
2  *
3  * subselect.c
4  *        Planning routines for subselects and parameters.
5  *
6  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.85 2003/11/25 23:59:12 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
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"
35
36
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 */
40
41 int                     PlannerPlanId = 0;      /* to assign unique ID to subquery plans */
42
43 /*
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.
49  *
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:
53  *
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.
57  *
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.
62  *
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.
66  *
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.
69  */
70 typedef struct PlannerParamItem
71 {
72         Node       *item;                       /* the Var, Aggref, or Param */
73         Index           abslevel;               /* its absolute query level */
74 } PlannerParamItem;
75
76
77 typedef struct finalize_primnode_context
78 {
79         Bitmapset  *paramids;           /* Set of PARAM_EXEC paramids found */
80         Bitmapset  *outer_params;       /* Set of accessible outer paramids */
81 } finalize_primnode_context;
82
83
84 static List *convert_sublink_opers(List *lefthand, List *operOids,
85                                           List *targetlist, int rtindex,
86                                           List **righthandIds);
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);
94
95
96 /*
97  * Generate a Param node to replace the given Var,
98  * which is expected to have varlevelsup > 0 (ie, it is not local).
99  */
100 static Param *
101 replace_outer_var(Var *var)
102 {
103         Param      *retval;
104         List       *ppl;
105         PlannerParamItem *pitem;
106         Index           abslevel;
107         int                     i;
108
109         Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
110         abslevel = PlannerQueryLevel - var->varlevelsup;
111
112         /*
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.
121          *
122          * We also need to demand a match on vartypmod.  This does not matter
123          * for the Param itself, since those are not typmod-dependent, but it
124          * does matter when make_subplan() instantiates a modified copy of the
125          * Var for a subplan's args list.
126          */
127         i = 0;
128         foreach(ppl, PlannerParamList)
129         {
130                 pitem = (PlannerParamItem *) lfirst(ppl);
131                 if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
132                 {
133                         Var                *pvar = (Var *) pitem->item;
134
135                         if (pvar->varno == var->varno &&
136                                 pvar->varattno == var->varattno &&
137                                 pvar->vartype == var->vartype &&
138                                 pvar->vartypmod == var->vartypmod)
139                                 break;
140                 }
141                 i++;
142         }
143
144         if (!ppl)
145         {
146                 /* Nope, so make a new one */
147                 var = (Var *) copyObject(var);
148                 var->varlevelsup = 0;
149
150                 pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
151                 pitem->item = (Node *) var;
152                 pitem->abslevel = abslevel;
153
154                 PlannerParamList = lappend(PlannerParamList, pitem);
155                 /* i is already the correct index for the new item */
156         }
157
158         retval = makeNode(Param);
159         retval->paramkind = PARAM_EXEC;
160         retval->paramid = (AttrNumber) i;
161         retval->paramtype = var->vartype;
162
163         return retval;
164 }
165
166 /*
167  * Generate a Param node to replace the given Aggref
168  * which is expected to have agglevelsup > 0 (ie, it is not local).
169  */
170 static Param *
171 replace_outer_agg(Aggref *agg)
172 {
173         Param      *retval;
174         PlannerParamItem *pitem;
175         Index           abslevel;
176         int                     i;
177
178         Assert(agg->agglevelsup > 0 && agg->agglevelsup < PlannerQueryLevel);
179         abslevel = PlannerQueryLevel - agg->agglevelsup;
180
181         /*
182          * It does not seem worthwhile to try to match duplicate outer aggs.
183          * Just make a new slot every time.
184          */
185         agg = (Aggref *) copyObject(agg);
186         IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
187         Assert(agg->agglevelsup == 0);
188
189         pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
190         pitem->item = (Node *) agg;
191         pitem->abslevel = abslevel;
192
193         PlannerParamList = lappend(PlannerParamList, pitem);
194         i = length(PlannerParamList) - 1;
195
196         retval = makeNode(Param);
197         retval->paramkind = PARAM_EXEC;
198         retval->paramid = (AttrNumber) i;
199         retval->paramtype = agg->aggtype;
200
201         return retval;
202 }
203
204 /*
205  * Generate a new Param node that will not conflict with any other.
206  *
207  * This is used to allocate PARAM_EXEC slots for subplan outputs.
208  *
209  * paramtypmod is currently unused but might be wanted someday.
210  */
211 static Param *
212 generate_new_param(Oid paramtype, int32 paramtypmod)
213 {
214         Param      *retval;
215         PlannerParamItem *pitem;
216
217         retval = makeNode(Param);
218         retval->paramkind = PARAM_EXEC;
219         retval->paramid = (AttrNumber) length(PlannerParamList);
220         retval->paramtype = paramtype;
221
222         pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
223         pitem->item = (Node *) retval;
224         pitem->abslevel = PlannerQueryLevel;
225
226         PlannerParamList = lappend(PlannerParamList, pitem);
227
228         return retval;
229 }
230
231 /*
232  * Convert a bare SubLink (as created by the parser) into a SubPlan.
233  *
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.
237  *
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.
243  */
244 static Node *
245 make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
246 {
247         SubPlan    *node = makeNode(SubPlan);
248         Query      *subquery = (Query *) (slink->subselect);
249         double          tuple_fraction;
250         Plan       *plan;
251         Bitmapset  *tmpset;
252         int                     paramid;
253         List       *lst;
254         Node       *result;
255
256         /*
257          * Copy the source Query node.  This is a quick and dirty kluge to
258          * resolve the fact that the parser can generate trees with multiple
259          * links to the same sub-Query node, but the planner wants to scribble
260          * on the Query. Try to clean this up when we do querytree redesign...
261          */
262         subquery = (Query *) copyObject(subquery);
263
264         /*
265          * For an EXISTS subplan, tell lower-level planner to expect that only
266          * the first tuple will be retrieved.  For ALL and ANY subplans, we
267          * will be able to stop evaluating if the test condition fails, so
268          * very often not all the tuples will be retrieved; for lack of a
269          * better idea, specify 50% retrieval.  For EXPR and MULTIEXPR
270          * subplans, use default behavior (we're only expecting one row out,
271          * anyway).
272          *
273          * NOTE: if you change these numbers, also change cost_qual_eval_walker()
274          * in path/costsize.c.
275          *
276          * XXX If an ALL/ANY subplan is uncorrelated, we may decide to hash or
277          * materialize its result below.  In that case it would've been better
278          * to specify full retrieval.  At present, however, we can only detect
279          * correlation or lack of it after we've made the subplan :-(. Perhaps
280          * detection of correlation should be done as a separate step.
281          * Meanwhile, we don't want to be too optimistic about the percentage
282          * of tuples retrieved, for fear of selecting a plan that's bad for
283          * the materialization case.
284          */
285         if (slink->subLinkType == EXISTS_SUBLINK)
286                 tuple_fraction = 1.0;   /* just like a LIMIT 1 */
287         else if (slink->subLinkType == ALL_SUBLINK ||
288                          slink->subLinkType == ANY_SUBLINK)
289                 tuple_fraction = 0.5;   /* 50% */
290         else
291                 tuple_fraction = 0.0;   /* default behavior */
292
293         /*
294          * Generate the plan for the subquery.
295          */
296         node->plan = plan = subquery_planner(subquery, tuple_fraction);
297
298         node->plan_id = PlannerPlanId++;        /* Assign unique ID to this
299                                                                                  * SubPlan */
300
301         node->rtable = subquery->rtable;
302
303         /*
304          * Initialize other fields of the SubPlan node.
305          */
306         node->subLinkType = slink->subLinkType;
307         node->useOr = slink->useOr;
308         node->exprs = NIL;
309         node->paramIds = NIL;
310         node->useHashTable = false;
311         /* At top level of a qual, can treat UNKNOWN the same as FALSE */
312         node->unknownEqFalse = isTopQual;
313         node->setParam = NIL;
314         node->parParam = NIL;
315         node->args = NIL;
316
317         /*
318          * Make parParam list of params that current query level will pass to
319          * this child plan.
320          */
321         tmpset = bms_copy(plan->extParam);
322         while ((paramid = bms_first_member(tmpset)) >= 0)
323         {
324                 PlannerParamItem *pitem = nth(paramid, PlannerParamList);
325
326                 if (pitem->abslevel == PlannerQueryLevel)
327                         node->parParam = lappendi(node->parParam, paramid);
328         }
329         bms_free(tmpset);
330
331         /*
332          * Un-correlated or undirect correlated plans of EXISTS, EXPR, ARRAY,
333          * or MULTIEXPR types can be used as initPlans.  For EXISTS, EXPR, or
334          * ARRAY, we just produce a Param referring to the result of
335          * evaluating the initPlan.  For MULTIEXPR, we must build an AND or
336          * OR-clause of the individual comparison operators, using the
337          * appropriate lefthand side expressions and Params for the initPlan's
338          * target items.
339          */
340         if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
341         {
342                 Param      *prm;
343
344                 prm = generate_new_param(BOOLOID, -1);
345                 node->setParam = makeListi1(prm->paramid);
346                 PlannerInitPlan = lappend(PlannerInitPlan, node);
347                 result = (Node *) prm;
348         }
349         else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
350         {
351                 TargetEntry *te = lfirst(plan->targetlist);
352                 Param      *prm;
353
354                 Assert(!te->resdom->resjunk);
355                 prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
356                 node->setParam = makeListi1(prm->paramid);
357                 PlannerInitPlan = lappend(PlannerInitPlan, node);
358                 result = (Node *) prm;
359         }
360         else if (node->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
361         {
362                 TargetEntry *te = lfirst(plan->targetlist);
363                 Oid                     arraytype;
364                 Param      *prm;
365
366                 Assert(!te->resdom->resjunk);
367                 arraytype = get_array_type(te->resdom->restype);
368                 if (!OidIsValid(arraytype))
369                         elog(ERROR, "could not find array type for datatype %s",
370                                  format_type_be(te->resdom->restype));
371                 prm = generate_new_param(arraytype, -1);
372                 node->setParam = makeListi1(prm->paramid);
373                 PlannerInitPlan = lappend(PlannerInitPlan, node);
374                 result = (Node *) prm;
375         }
376         else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
377         {
378                 List       *exprs;
379
380                 /* Convert the lefthand exprs and oper OIDs into executable exprs */
381                 exprs = convert_sublink_opers(lefthand,
382                                                                           slink->operOids,
383                                                                           plan->targetlist,
384                                                                           0,
385                                                                           &node->paramIds);
386                 node->setParam = listCopy(node->paramIds);
387                 PlannerInitPlan = lappend(PlannerInitPlan, node);
388
389                 /*
390                  * The executable expressions are returned to become part of the
391                  * outer plan's expression tree; they are not kept in the initplan
392                  * node.
393                  */
394                 if (length(exprs) > 1)
395                         result = (Node *) (node->useOr ? make_orclause(exprs) :
396                                                            make_andclause(exprs));
397                 else
398                         result = (Node *) lfirst(exprs);
399         }
400         else
401         {
402                 List       *args;
403
404                 /*
405                  * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
406                  * to initPlans, even when they are uncorrelated or undirect
407                  * correlated, because we need to scan the output of the subplan
408                  * for each outer tuple.  But if it's an IN (= ANY) test, we might
409                  * be able to use a hashtable to avoid comparing all the tuples.
410                  */
411                 if (subplan_is_hashable(slink, node))
412                         node->useHashTable = true;
413
414                 /*
415                  * Otherwise, we have the option to tack a MATERIAL node onto the
416                  * top of the subplan, to reduce the cost of reading it
417                  * repeatedly.  This is pointless for a direct-correlated subplan,
418                  * since we'd have to recompute its results each time anyway.  For
419                  * uncorrelated/undirect correlated subplans, we add MATERIAL if
420                  * the subplan's top plan node is anything more complicated than a
421                  * plain sequential scan, and we do it even for seqscan if the
422                  * qual appears selective enough to eliminate many tuples.
423                  */
424                 else if (node->parParam == NIL)
425                 {
426                         bool            use_material;
427
428                         switch (nodeTag(plan))
429                         {
430                                 case T_SeqScan:
431                                         if (plan->initPlan)
432                                                 use_material = true;
433                                         else
434                                         {
435                                                 Selectivity qualsel;
436
437                                                 qualsel = clauselist_selectivity(subquery,
438                                                                                                                  plan->qual,
439                                                                                                                  0, JOIN_INNER);
440                                                 /* Is 10% selectivity a good threshold?? */
441                                                 use_material = qualsel < 0.10;
442                                         }
443                                         break;
444                                 case T_Material:
445                                 case T_FunctionScan:
446                                 case T_Sort:
447
448                                         /*
449                                          * Don't add another Material node if there's one
450                                          * already, nor if the top node is any other type that
451                                          * materializes its output anyway.
452                                          */
453                                         use_material = false;
454                                         break;
455                                 default:
456                                         use_material = true;
457                                         break;
458                         }
459                         if (use_material)
460                                 node->plan = plan = materialize_finished_plan(plan);
461                 }
462
463                 /* Convert the lefthand exprs and oper OIDs into executable exprs */
464                 node->exprs = convert_sublink_opers(lefthand,
465                                                                                         slink->operOids,
466                                                                                         plan->targetlist,
467                                                                                         0,
468                                                                                         &node->paramIds);
469
470                 /*
471                  * Make node->args from parParam.
472                  */
473                 args = NIL;
474                 foreach(lst, node->parParam)
475                 {
476                         PlannerParamItem *pitem = nth(lfirsti(lst), PlannerParamList);
477
478                         /*
479                          * The Var or Aggref has already been adjusted to have the
480                          * correct varlevelsup or agglevelsup.  We probably don't even
481                          * need to copy it again, but be safe.
482                          */
483                         args = lappend(args, copyObject(pitem->item));
484                 }
485                 node->args = args;
486
487                 result = (Node *) node;
488         }
489
490         return result;
491 }
492
493 /*
494  * convert_sublink_opers: given a lefthand-expressions list and a list of
495  * operator OIDs, build a list of actually executable expressions.      The
496  * righthand sides of the expressions are Params or Vars representing the
497  * results of the sub-select.
498  *
499  * If rtindex is 0, we build Params to represent the sub-select outputs.
500  * The paramids of the Params created are returned in the *righthandIds list.
501  *
502  * If rtindex is not 0, we build Vars using that rtindex as varno.      Copies
503  * of the Var nodes are returned in *righthandIds (this is a bit of a type
504  * cheat, but we can get away with it).
505  */
506 static List *
507 convert_sublink_opers(List *lefthand, List *operOids,
508                                           List *targetlist, int rtindex,
509                                           List **righthandIds)
510 {
511         List       *result = NIL;
512         List       *lst;
513
514         *righthandIds = NIL;
515
516         foreach(lst, operOids)
517         {
518                 Oid                     opid = lfirsto(lst);
519                 Node       *leftop = lfirst(lefthand);
520                 TargetEntry *te = lfirst(targetlist);
521                 Node       *rightop;
522                 Operator        tup;
523
524                 Assert(!te->resdom->resjunk);
525
526                 if (rtindex)
527                 {
528                         /* Make the Var node representing the subplan's result */
529                         rightop = (Node *) makeVar(rtindex,
530                                                                            te->resdom->resno,
531                                                                            te->resdom->restype,
532                                                                            te->resdom->restypmod,
533                                                                            0);
534                         /*
535                          * Copy it for caller.  NB: we need a copy to avoid having
536                          * doubly-linked substructure in the modified parse tree.
537                          */
538                         *righthandIds = lappend(*righthandIds, copyObject(rightop));
539                 }
540                 else
541                 {
542                         /* Make the Param node representing the subplan's result */
543                         Param      *prm;
544
545                         prm = generate_new_param(te->resdom->restype,
546                                                                          te->resdom->restypmod);
547                         /* Record its ID */
548                         *righthandIds = lappendi(*righthandIds, prm->paramid);
549                         rightop = (Node *) prm;
550                 }
551
552                 /* Look up the operator to pass to make_op_expr */
553                 tup = SearchSysCache(OPEROID,
554                                                          ObjectIdGetDatum(opid),
555                                                          0, 0, 0);
556                 if (!HeapTupleIsValid(tup))
557                         elog(ERROR, "cache lookup failed for operator %u", opid);
558
559                 /*
560                  * Make the expression node.
561                  *
562                  * Note: we use make_op_expr in case runtime type conversion function
563                  * calls must be inserted for this operator!  (But we are not
564                  * expecting to have to resolve unknown Params, so it's okay to
565                  * pass a null pstate.)
566                  */
567                 result = lappend(result,
568                                                  make_op_expr(NULL,
569                                                                           tup,
570                                                                           leftop,
571                                                                           rightop,
572                                                                           exprType(leftop),
573                                                                           te->resdom->restype));
574
575                 ReleaseSysCache(tup);
576
577                 lefthand = lnext(lefthand);
578                 targetlist = lnext(targetlist);
579         }
580
581         return result;
582 }
583
584 /*
585  * subplan_is_hashable: decide whether we can implement a subplan by hashing
586  *
587  * Caution: the SubPlan node is not completely filled in yet.  We can rely
588  * on its plan and parParam fields, however.
589  */
590 static bool
591 subplan_is_hashable(SubLink *slink, SubPlan *node)
592 {
593         double          subquery_size;
594         List       *opids;
595
596         /*
597          * The sublink type must be "= ANY" --- that is, an IN operator. (We
598          * require the operator name to be unqualified, which may be overly
599          * paranoid, or may not be.)  XXX since we also check that the
600          * operators are hashable, the test on operator name may be redundant?
601          */
602         if (slink->subLinkType != ANY_SUBLINK)
603                 return false;
604         if (length(slink->operName) != 1 ||
605                 strcmp(strVal(lfirst(slink->operName)), "=") != 0)
606                 return false;
607
608         /*
609          * The subplan must not have any direct correlation vars --- else we'd
610          * have to recompute its output each time, so that the hashtable
611          * wouldn't gain anything.
612          */
613         if (node->parParam != NIL)
614                 return false;
615
616         /*
617          * The estimated size of the subquery result must fit in SortMem. (XXX
618          * what about hashtable overhead?)
619          */
620         subquery_size = node->plan->plan_rows *
621                 (MAXALIGN(node->plan->plan_width) + MAXALIGN(sizeof(HeapTupleData)));
622         if (subquery_size > SortMem * 1024L)
623                 return false;
624
625         /*
626          * The combining operators must be hashable, strict, and
627          * self-commutative. The need for hashability is obvious, since we
628          * want to use hashing. Without strictness, behavior in the presence
629          * of nulls is too unpredictable.  (We actually must assume even more
630          * than plain strictness, see nodeSubplan.c for details.)  And
631          * commutativity ensures that the left and right datatypes are the
632          * same; this allows us to assume that the combining operators are
633          * equality for the righthand datatype, so that they can be used to
634          * compare righthand tuples as well as comparing lefthand to righthand
635          * tuples.      (This last restriction could be relaxed by using two
636          * different sets of operators with the hash table, but there is no
637          * obvious usefulness to that at present.)
638          */
639         foreach(opids, slink->operOids)
640         {
641                 Oid                     opid = lfirsto(opids);
642                 HeapTuple       tup;
643                 Form_pg_operator optup;
644
645                 tup = SearchSysCache(OPEROID,
646                                                          ObjectIdGetDatum(opid),
647                                                          0, 0, 0);
648                 if (!HeapTupleIsValid(tup))
649                         elog(ERROR, "cache lookup failed for operator %u", opid);
650                 optup = (Form_pg_operator) GETSTRUCT(tup);
651                 if (!optup->oprcanhash || optup->oprcom != opid ||
652                         !func_strict(optup->oprcode))
653                 {
654                         ReleaseSysCache(tup);
655                         return false;
656                 }
657                 ReleaseSysCache(tup);
658         }
659         return true;
660 }
661
662 /*
663  * convert_IN_to_join: can we convert an IN SubLink to join style?
664  *
665  * The caller has found a SubLink at the top level of WHERE, but has not
666  * checked the properties of the SubLink at all.  Decide whether it is
667  * appropriate to process this SubLink in join style.  If not, return NULL.
668  * If so, build the qual clause(s) to replace the SubLink, and return them.
669  *
670  * Side effects of a successful conversion include adding the SubLink's
671  * subselect to the query's rangetable and adding an InClauseInfo node to
672  * its in_info_list.
673  */
674 Node *
675 convert_IN_to_join(Query *parse, SubLink *sublink)
676 {
677         Query      *subselect = (Query *) sublink->subselect;
678         Relids          left_varnos;
679         int                     rtindex;
680         RangeTblEntry *rte;
681         RangeTblRef *rtr;
682         InClauseInfo *ininfo;
683         List       *exprs;
684
685         /*
686          * The sublink type must be "= ANY" --- that is, an IN operator. (We
687          * require the operator name to be unqualified, which may be overly
688          * paranoid, or may not be.)
689          */
690         if (sublink->subLinkType != ANY_SUBLINK)
691                 return NULL;
692         if (length(sublink->operName) != 1 ||
693                 strcmp(strVal(lfirst(sublink->operName)), "=") != 0)
694                 return NULL;
695
696         /*
697          * The sub-select must not refer to any Vars of the parent query.
698          * (Vars of higher levels should be okay, though.)
699          */
700         if (contain_vars_of_level((Node *) subselect, 1))
701                 return NULL;
702
703         /*
704          * The left-hand expressions must contain some Vars of the current
705          * query, else it's not gonna be a join.
706          */
707         left_varnos = pull_varnos((Node *) sublink->lefthand);
708         if (bms_is_empty(left_varnos))
709                 return NULL;
710
711         /*
712          * The left-hand expressions mustn't be volatile.  (Perhaps we should
713          * test the combining operators, too?  We'd only need to point the
714          * function directly at the sublink ...)
715          */
716         if (contain_volatile_functions((Node *) sublink->lefthand))
717                 return NULL;
718
719         /*
720          * Okay, pull up the sub-select into top range table and jointree.
721          *
722          * We rely here on the assumption that the outer query has no references
723          * to the inner (necessarily true, other than the Vars that we build
724          * below).      Therefore this is a lot easier than what
725          * pull_up_subqueries has to go through.
726          */
727         rte = addRangeTableEntryForSubquery(NULL,
728                                                                                 subselect,
729                                                                                 makeAlias("IN_subquery", NIL),
730                                                                                 false);
731         parse->rtable = lappend(parse->rtable, rte);
732         rtindex = length(parse->rtable);
733         rtr = makeNode(RangeTblRef);
734         rtr->rtindex = rtindex;
735         parse->jointree->fromlist = lappend(parse->jointree->fromlist, rtr);
736
737         /*
738          * Now build the InClauseInfo node.
739          */
740         ininfo = makeNode(InClauseInfo);
741         ininfo->lefthand = left_varnos;
742         ininfo->righthand = bms_make_singleton(rtindex);
743         parse->in_info_list = lcons(ininfo, parse->in_info_list);
744
745         /*
746          * Build the result qual expressions.  As a side effect,
747          * ininfo->sub_targetlist is filled with a list of Vars
748          * representing the subselect outputs.
749          */
750         exprs = convert_sublink_opers(sublink->lefthand,
751                                                                   sublink->operOids,
752                                                                   subselect->targetList,
753                                                                   rtindex,
754                                                                   &ininfo->sub_targetlist);
755         return (Node *) make_ands_explicit(exprs);
756 }
757
758 /*
759  * Replace correlation vars (uplevel vars) with Params.
760  *
761  * Uplevel aggregates are replaced, too.
762  *
763  * Note: it is critical that this runs immediately after SS_process_sublinks.
764  * Since we do not recurse into the arguments of uplevel aggregates, they will
765  * get copied to the appropriate subplan args list in the parent query with
766  * uplevel vars not replaced by Params, but only adjusted in level (see
767  * replace_outer_agg).  That's exactly what we want for the vars of the parent
768  * level --- but if an aggregate's argument contains any further-up variables,
769  * they have to be replaced with Params in their turn.  That will happen when
770  * the parent level runs SS_replace_correlation_vars.  Therefore it must do
771  * so after expanding its sublinks to subplans.  And we don't want any steps
772  * in between, else those steps would never get applied to the aggregate
773  * argument expressions, either in the parent or the child level.
774  */
775 Node *
776 SS_replace_correlation_vars(Node *expr)
777 {
778         /* No setup needed for tree walk, so away we go */
779         return replace_correlation_vars_mutator(expr, NULL);
780 }
781
782 static Node *
783 replace_correlation_vars_mutator(Node *node, void *context)
784 {
785         if (node == NULL)
786                 return NULL;
787         if (IsA(node, Var))
788         {
789                 if (((Var *) node)->varlevelsup > 0)
790                         return (Node *) replace_outer_var((Var *) node);
791         }
792         if (IsA(node, Aggref))
793         {
794                 if (((Aggref *) node)->agglevelsup > 0)
795                         return (Node *) replace_outer_agg((Aggref *) node);
796         }
797         return expression_tree_mutator(node,
798                                                                    replace_correlation_vars_mutator,
799                                                                    context);
800 }
801
802 /*
803  * Expand SubLinks to SubPlans in the given expression.
804  *
805  * The isQual argument tells whether or not this expression is a WHERE/HAVING
806  * qualifier expression.  If it is, any sublinks appearing at top level need
807  * not distinguish FALSE from UNKNOWN return values.
808  */
809 Node *
810 SS_process_sublinks(Node *expr, bool isQual)
811 {
812         /* The only context needed is the initial are-we-in-a-qual flag */
813         return process_sublinks_mutator(expr, &isQual);
814 }
815
816 static Node *
817 process_sublinks_mutator(Node *node, bool *isTopQual)
818 {
819         bool            locTopQual;
820
821         if (node == NULL)
822                 return NULL;
823         if (IsA(node, SubLink))
824         {
825                 SubLink    *sublink = (SubLink *) node;
826                 List       *lefthand;
827
828                 /*
829                  * First, recursively process the lefthand-side expressions, if
830                  * any.
831                  */
832                 locTopQual = false;
833                 lefthand = (List *)
834                         process_sublinks_mutator((Node *) sublink->lefthand, &locTopQual);
835
836                 /*
837                  * Now build the SubPlan node and make the expr to return.
838                  */
839                 return make_subplan(sublink, lefthand, *isTopQual);
840         }
841
842         /*
843          * We should never see a SubPlan expression in the input (since this
844          * is the very routine that creates 'em to begin with).  We shouldn't
845          * find ourselves invoked directly on a Query, either.
846          */
847         Assert(!is_subplan(node));
848         Assert(!IsA(node, Query));
849
850         /*
851          * If we recurse down through anything other than a List node, we are
852          * definitely not at top qual level anymore.
853          */
854         if (IsA(node, List))
855                 locTopQual = *isTopQual;
856         else
857                 locTopQual = false;
858
859         return expression_tree_mutator(node,
860                                                                    process_sublinks_mutator,
861                                                                    (void *) &locTopQual);
862 }
863
864 /*
865  * SS_finalize_plan - do final sublink processing for a completed Plan.
866  *
867  * This recursively computes the extParam and allParam sets
868  * for every Plan node in the given plan tree.
869  */
870 void
871 SS_finalize_plan(Plan *plan, List *rtable)
872 {
873         Bitmapset  *outer_params = NULL;
874         Bitmapset  *valid_params = NULL;
875         int                     paramid;
876         List       *lst;
877
878         /*
879          * First, scan the param list to discover the sets of params that are
880          * available from outer query levels and my own query level. We do
881          * this once to save time in the per-plan recursion steps.
882          */
883         paramid = 0;
884         foreach(lst, PlannerParamList)
885         {
886                 PlannerParamItem *pitem = (PlannerParamItem *) lfirst(lst);
887
888                 if (pitem->abslevel < PlannerQueryLevel)
889                 {
890                         /* valid outer-level parameter */
891                         outer_params = bms_add_member(outer_params, paramid);
892                         valid_params = bms_add_member(valid_params, paramid);
893                 }
894                 else if (pitem->abslevel == PlannerQueryLevel &&
895                                  IsA(pitem->item, Param))
896                 {
897                         /* valid local parameter (i.e., a setParam of my child) */
898                         valid_params = bms_add_member(valid_params, paramid);
899                 }
900
901                 paramid++;
902         }
903
904         /*
905          * Now recurse through plan tree.
906          */
907         (void) finalize_plan(plan, rtable, outer_params, valid_params);
908
909         bms_free(outer_params);
910         bms_free(valid_params);
911 }
912
913 /*
914  * Recursive processing of all nodes in the plan tree
915  *
916  * The return value is the computed allParam set for the given Plan node.
917  * This is just an internal notational convenience.
918  */
919 static Bitmapset *
920 finalize_plan(Plan *plan, List *rtable,
921                           Bitmapset *outer_params, Bitmapset *valid_params)
922 {
923         finalize_primnode_context context;
924         List       *lst;
925
926         if (plan == NULL)
927                 return NULL;
928
929         context.paramids = NULL;        /* initialize set to empty */
930         context.outer_params = outer_params;
931
932         /*
933          * When we call finalize_primnode, context.paramids sets are
934          * automatically merged together.  But when recursing to self, we have
935          * to do it the hard way.  We want the paramids set to include params
936          * in subplans as well as at this level.
937          */
938
939         /* Find params in targetlist and qual */
940         finalize_primnode((Node *) plan->targetlist, &context);
941         finalize_primnode((Node *) plan->qual, &context);
942
943         /* Check additional node-type-specific fields */
944         switch (nodeTag(plan))
945         {
946                 case T_Result:
947                         finalize_primnode(((Result *) plan)->resconstantqual,
948                                                           &context);
949                         break;
950
951                 case T_IndexScan:
952                         finalize_primnode((Node *) ((IndexScan *) plan)->indxqual,
953                                                           &context);
954
955                         /*
956                          * we need not look at indxqualorig, since it will have the
957                          * same param references as indxqual.
958                          */
959                         break;
960
961                 case T_TidScan:
962                         finalize_primnode((Node *) ((TidScan *) plan)->tideval,
963                                                           &context);
964                         break;
965
966                 case T_SubqueryScan:
967
968                         /*
969                          * In a SubqueryScan, SS_finalize_plan has already been run on
970                          * the subplan by the inner invocation of subquery_planner, so
971                          * there's no need to do it again.  Instead, just pull out the
972                          * subplan's extParams list, which represents the params it
973                          * needs from my level and higher levels.
974                          */
975                         context.paramids = bms_add_members(context.paramids,
976                                                          ((SubqueryScan *) plan)->subplan->extParam);
977                         break;
978
979                 case T_FunctionScan:
980                         {
981                                 RangeTblEntry *rte;
982
983                                 rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
984                                                            rtable);
985                                 Assert(rte->rtekind == RTE_FUNCTION);
986                                 finalize_primnode(rte->funcexpr, &context);
987                         }
988                         break;
989
990                 case T_Append:
991                         foreach(lst, ((Append *) plan)->appendplans)
992                         {
993                                 context.paramids =
994                                         bms_add_members(context.paramids,
995                                                                         finalize_plan((Plan *) lfirst(lst),
996                                                                                                   rtable,
997                                                                                                   outer_params,
998                                                                                                   valid_params));
999                         }
1000                         break;
1001
1002                 case T_NestLoop:
1003                         finalize_primnode((Node *) ((Join *) plan)->joinqual,
1004                                                           &context);
1005                         break;
1006
1007                 case T_MergeJoin:
1008                         finalize_primnode((Node *) ((Join *) plan)->joinqual,
1009                                                           &context);
1010                         finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
1011                                                           &context);
1012                         break;
1013
1014                 case T_HashJoin:
1015                         finalize_primnode((Node *) ((Join *) plan)->joinqual,
1016                                                           &context);
1017                         finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
1018                                                           &context);
1019                         break;
1020
1021                 case T_Hash:
1022                 case T_Agg:
1023                 case T_SeqScan:
1024                 case T_Material:
1025                 case T_Sort:
1026                 case T_Unique:
1027                 case T_SetOp:
1028                 case T_Limit:
1029                 case T_Group:
1030                         break;
1031
1032                 default:
1033                         elog(ERROR, "unrecognized node type: %d",
1034                                  (int) nodeTag(plan));
1035         }
1036
1037         /* Process left and right child plans, if any */
1038         context.paramids = bms_add_members(context.paramids,
1039                                                                            finalize_plan(plan->lefttree,
1040                                                                                                          rtable,
1041                                                                                                          outer_params,
1042                                                                                                          valid_params));
1043
1044         context.paramids = bms_add_members(context.paramids,
1045                                                                            finalize_plan(plan->righttree,
1046                                                                                                          rtable,
1047                                                                                                          outer_params,
1048                                                                                                          valid_params));
1049
1050         /* Now we have all the paramids */
1051
1052         if (!bms_is_subset(context.paramids, valid_params))
1053                 elog(ERROR, "plan should not reference subplan's variable");
1054
1055         plan->extParam = bms_intersect(context.paramids, outer_params);
1056         plan->allParam = context.paramids;
1057
1058         /*
1059          * For speed at execution time, make sure extParam/allParam are
1060          * actually NULL if they are empty sets.
1061          */
1062         if (bms_is_empty(plan->extParam))
1063         {
1064                 bms_free(plan->extParam);
1065                 plan->extParam = NULL;
1066         }
1067         if (bms_is_empty(plan->allParam))
1068         {
1069                 bms_free(plan->allParam);
1070                 plan->allParam = NULL;
1071         }
1072
1073         return plan->allParam;
1074 }
1075
1076 /*
1077  * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given
1078  * expression tree to the result set.
1079  */
1080 static bool
1081 finalize_primnode(Node *node, finalize_primnode_context *context)
1082 {
1083         if (node == NULL)
1084                 return false;
1085         if (IsA(node, Param))
1086         {
1087                 if (((Param *) node)->paramkind == PARAM_EXEC)
1088                 {
1089                         int                     paramid = (int) ((Param *) node)->paramid;
1090
1091                         context->paramids = bms_add_member(context->paramids, paramid);
1092                 }
1093                 return false;                   /* no more to do here */
1094         }
1095         if (is_subplan(node))
1096         {
1097                 SubPlan    *subplan = (SubPlan *) node;
1098
1099                 /* Add outer-level params needed by the subplan to paramids */
1100                 context->paramids = bms_join(context->paramids,
1101                                                                    bms_intersect(subplan->plan->extParam,
1102                                                                                                  context->outer_params));
1103                 /* fall through to recurse into subplan args */
1104         }
1105         return expression_tree_walker(node, finalize_primnode,
1106                                                                   (void *) context);
1107 }