~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/optimizer/plan/subselect.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * subselect.c
 
4
 *        Planning routines for subselects and parameters.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        src/backend/optimizer/plan/subselect.c
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#include "postgres.h"
 
15
 
 
16
#include "catalog/pg_operator.h"
 
17
#include "catalog/pg_type.h"
 
18
#include "executor/executor.h"
 
19
#include "miscadmin.h"
 
20
#include "nodes/makefuncs.h"
 
21
#include "nodes/nodeFuncs.h"
 
22
#include "optimizer/clauses.h"
 
23
#include "optimizer/cost.h"
 
24
#include "optimizer/planmain.h"
 
25
#include "optimizer/planner.h"
 
26
#include "optimizer/prep.h"
 
27
#include "optimizer/subselect.h"
 
28
#include "optimizer/var.h"
 
29
#include "parser/parse_relation.h"
 
30
#include "parser/parsetree.h"
 
31
#include "rewrite/rewriteManip.h"
 
32
#include "utils/builtins.h"
 
33
#include "utils/lsyscache.h"
 
34
#include "utils/syscache.h"
 
35
 
 
36
 
 
37
typedef struct convert_testexpr_context
 
38
{
 
39
        PlannerInfo *root;
 
40
        List       *subst_nodes;        /* Nodes to substitute for Params */
 
41
} convert_testexpr_context;
 
42
 
 
43
typedef struct process_sublinks_context
 
44
{
 
45
        PlannerInfo *root;
 
46
        bool            isTopQual;
 
47
} process_sublinks_context;
 
48
 
 
49
typedef struct finalize_primnode_context
 
50
{
 
51
        PlannerInfo *root;
 
52
        Bitmapset  *paramids;           /* Non-local PARAM_EXEC paramids found */
 
53
} finalize_primnode_context;
 
54
 
 
55
 
 
56
static Node *build_subplan(PlannerInfo *root, Plan *plan,
 
57
                          List *rtable, List *rowmarks,
 
58
                          SubLinkType subLinkType, Node *testexpr,
 
59
                          bool adjust_testexpr, bool unknownEqFalse);
 
60
static List *generate_subquery_params(PlannerInfo *root, List *tlist,
 
61
                                                 List **paramIds);
 
62
static List *generate_subquery_vars(PlannerInfo *root, List *tlist,
 
63
                                           Index varno);
 
64
static Node *convert_testexpr(PlannerInfo *root,
 
65
                                 Node *testexpr,
 
66
                                 List *subst_nodes);
 
67
static Node *convert_testexpr_mutator(Node *node,
 
68
                                                 convert_testexpr_context *context);
 
69
static bool subplan_is_hashable(Plan *plan);
 
70
static bool testexpr_is_hashable(Node *testexpr);
 
71
static bool hash_ok_operator(OpExpr *expr);
 
72
static bool simplify_EXISTS_query(Query *query);
 
73
static Query *convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
 
74
                                          Node **testexpr, List **paramIds);
 
75
static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
 
76
static Node *process_sublinks_mutator(Node *node,
 
77
                                                 process_sublinks_context *context);
 
78
static Bitmapset *finalize_plan(PlannerInfo *root,
 
79
                          Plan *plan,
 
80
                          Bitmapset *valid_params,
 
81
                          Bitmapset *scan_params);
 
82
static bool finalize_primnode(Node *node, finalize_primnode_context *context);
 
83
 
 
84
 
 
85
/*
 
86
 * Select a PARAM_EXEC number to identify the given Var.
 
87
 * If the Var already has a param slot, return that one.
 
88
 */
 
89
static int
 
90
assign_param_for_var(PlannerInfo *root, Var *var)
 
91
{
 
92
        ListCell   *ppl;
 
93
        PlannerParamItem *pitem;
 
94
        Index           abslevel;
 
95
        int                     i;
 
96
 
 
97
        abslevel = root->query_level - var->varlevelsup;
 
98
 
 
99
        /* If there's already a paramlist entry for this same Var, just use it */
 
100
        i = 0;
 
101
        foreach(ppl, root->glob->paramlist)
 
102
        {
 
103
                pitem = (PlannerParamItem *) lfirst(ppl);
 
104
                if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
 
105
                {
 
106
                        Var                *pvar = (Var *) pitem->item;
 
107
 
 
108
                        if (pvar->varno == var->varno &&
 
109
                                pvar->varattno == var->varattno &&
 
110
                                pvar->vartype == var->vartype &&
 
111
                                pvar->vartypmod == var->vartypmod)
 
112
                                return i;
 
113
                }
 
114
                i++;
 
115
        }
 
116
 
 
117
        /* Nope, so make a new one */
 
118
        var = (Var *) copyObject(var);
 
119
        var->varlevelsup = 0;
 
120
 
 
121
        pitem = makeNode(PlannerParamItem);
 
122
        pitem->item = (Node *) var;
 
123
        pitem->abslevel = abslevel;
 
124
 
 
125
        root->glob->paramlist = lappend(root->glob->paramlist, pitem);
 
126
 
 
127
        /* i is already the correct list index for the new item */
 
128
        return i;
 
129
}
 
130
 
 
131
/*
 
132
 * Generate a Param node to replace the given Var,
 
133
 * which is expected to have varlevelsup > 0 (ie, it is not local).
 
134
 */
 
135
static Param *
 
136
replace_outer_var(PlannerInfo *root, Var *var)
 
137
{
 
138
        Param      *retval;
 
139
        int                     i;
 
140
 
 
141
        Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
 
142
 
 
143
        /*
 
144
         * Find the Var in root->glob->paramlist, or add it if not present.
 
145
         *
 
146
         * NOTE: in sufficiently complex querytrees, it is possible for the same
 
147
         * varno/abslevel to refer to different RTEs in different parts of the
 
148
         * parsetree, so that different fields might end up sharing the same Param
 
149
         * number.      As long as we check the vartype/typmod as well, I believe that
 
150
         * this sort of aliasing will cause no trouble.  The correct field should
 
151
         * get stored into the Param slot at execution in each part of the tree.
 
152
         */
 
153
        i = assign_param_for_var(root, var);
 
154
 
 
155
        retval = makeNode(Param);
 
156
        retval->paramkind = PARAM_EXEC;
 
157
        retval->paramid = i;
 
158
        retval->paramtype = var->vartype;
 
159
        retval->paramtypmod = var->vartypmod;
 
160
        retval->paramcollid = var->varcollid;
 
161
        retval->location = -1;
 
162
 
 
163
        return retval;
 
164
}
 
165
 
 
166
/*
 
167
 * Generate a Param node to replace the given Var, which will be supplied
 
168
 * from an upper NestLoop join node.
 
169
 *
 
170
 * Because we allow nestloop and subquery Params to alias each other,
 
171
 * this is effectively the same as replace_outer_var, except that we expect
 
172
 * the Var to be local to the current query level.
 
173
 */
 
174
Param *
 
175
assign_nestloop_param(PlannerInfo *root, Var *var)
 
176
{
 
177
        Param      *retval;
 
178
        int                     i;
 
179
 
 
180
        Assert(var->varlevelsup == 0);
 
181
 
 
182
        i = assign_param_for_var(root, var);
 
183
 
 
184
        retval = makeNode(Param);
 
185
        retval->paramkind = PARAM_EXEC;
 
186
        retval->paramid = i;
 
187
        retval->paramtype = var->vartype;
 
188
        retval->paramtypmod = var->vartypmod;
 
189
        retval->paramcollid = var->varcollid;
 
190
        retval->location = -1;
 
191
 
 
192
        return retval;
 
193
}
 
194
 
 
195
/*
 
196
 * Generate a Param node to replace the given Aggref
 
197
 * which is expected to have agglevelsup > 0 (ie, it is not local).
 
198
 */
 
199
static Param *
 
200
replace_outer_agg(PlannerInfo *root, Aggref *agg)
 
201
{
 
202
        Param      *retval;
 
203
        PlannerParamItem *pitem;
 
204
        Index           abslevel;
 
205
        int                     i;
 
206
 
 
207
        Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
 
208
        abslevel = root->query_level - agg->agglevelsup;
 
209
 
 
210
        /*
 
211
         * It does not seem worthwhile to try to match duplicate outer aggs. Just
 
212
         * make a new slot every time.
 
213
         */
 
214
        agg = (Aggref *) copyObject(agg);
 
215
        IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
 
216
        Assert(agg->agglevelsup == 0);
 
217
 
 
218
        pitem = makeNode(PlannerParamItem);
 
219
        pitem->item = (Node *) agg;
 
220
        pitem->abslevel = abslevel;
 
221
 
 
222
        root->glob->paramlist = lappend(root->glob->paramlist, pitem);
 
223
        i = list_length(root->glob->paramlist) - 1;
 
224
 
 
225
        retval = makeNode(Param);
 
226
        retval->paramkind = PARAM_EXEC;
 
227
        retval->paramid = i;
 
228
        retval->paramtype = agg->aggtype;
 
229
        retval->paramtypmod = -1;
 
230
        retval->paramcollid = agg->aggcollid;
 
231
        retval->location = -1;
 
232
 
 
233
        return retval;
 
234
}
 
235
 
 
236
/*
 
237
 * Generate a new Param node that will not conflict with any other.
 
238
 *
 
239
 * This is used to allocate PARAM_EXEC slots for subplan outputs.
 
240
 */
 
241
static Param *
 
242
generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
 
243
                                   Oid paramcollation)
 
244
{
 
245
        Param      *retval;
 
246
        PlannerParamItem *pitem;
 
247
 
 
248
        retval = makeNode(Param);
 
249
        retval->paramkind = PARAM_EXEC;
 
250
        retval->paramid = list_length(root->glob->paramlist);
 
251
        retval->paramtype = paramtype;
 
252
        retval->paramtypmod = paramtypmod;
 
253
        retval->paramcollid = paramcollation;
 
254
        retval->location = -1;
 
255
 
 
256
        pitem = makeNode(PlannerParamItem);
 
257
        pitem->item = (Node *) retval;
 
258
        pitem->abslevel = root->query_level;
 
259
 
 
260
        root->glob->paramlist = lappend(root->glob->paramlist, pitem);
 
261
 
 
262
        return retval;
 
263
}
 
264
 
 
265
/*
 
266
 * Assign a (nonnegative) PARAM_EXEC ID for a special parameter (one that
 
267
 * is not actually used to carry a value at runtime).  Such parameters are
 
268
 * used for special runtime signaling purposes, such as connecting a
 
269
 * recursive union node to its worktable scan node or forcing plan
 
270
 * re-evaluation within the EvalPlanQual mechanism.
 
271
 */
 
272
int
 
273
SS_assign_special_param(PlannerInfo *root)
 
274
{
 
275
        Param      *param;
 
276
 
 
277
        /* We generate a Param of datatype INTERNAL */
 
278
        param = generate_new_param(root, INTERNALOID, -1, InvalidOid);
 
279
        /* ... but the caller only cares about its ID */
 
280
        return param->paramid;
 
281
}
 
282
 
 
283
/*
 
284
 * Get the datatype/typmod/collation of the first column of the plan's output.
 
285
 *
 
286
 * This information is stored for ARRAY_SUBLINK execution and for
 
287
 * exprType()/exprTypmod()/exprCollation(), which have no way to get at the
 
288
 * plan associated with a SubPlan node.  We really only need the info for
 
289
 * EXPR_SUBLINK and ARRAY_SUBLINK subplans, but for consistency we save it
 
290
 * always.
 
291
 */
 
292
static void
 
293
get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod,
 
294
                                   Oid *colcollation)
 
295
{
 
296
        /* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
 
297
        if (plan->targetlist)
 
298
        {
 
299
                TargetEntry *tent = (TargetEntry *) linitial(plan->targetlist);
 
300
 
 
301
                Assert(IsA(tent, TargetEntry));
 
302
                if (!tent->resjunk)
 
303
                {
 
304
                        *coltype = exprType((Node *) tent->expr);
 
305
                        *coltypmod = exprTypmod((Node *) tent->expr);
 
306
                        *colcollation = exprCollation((Node *) tent->expr);
 
307
                        return;
 
308
                }
 
309
        }
 
310
        *coltype = VOIDOID;
 
311
        *coltypmod = -1;
 
312
        *colcollation = InvalidOid;
 
313
}
 
314
 
 
315
/*
 
316
 * Convert a SubLink (as created by the parser) into a SubPlan.
 
317
 *
 
318
 * We are given the SubLink's contained query, type, and testexpr.  We are
 
319
 * also told if this expression appears at top level of a WHERE/HAVING qual.
 
320
 *
 
321
 * Note: we assume that the testexpr has been AND/OR flattened (actually,
 
322
 * it's been through eval_const_expressions), but not converted to
 
323
 * implicit-AND form; and any SubLinks in it should already have been
 
324
 * converted to SubPlans.  The subquery is as yet untouched, however.
 
325
 *
 
326
 * The result is whatever we need to substitute in place of the SubLink
 
327
 * node in the executable expression.  This will be either the SubPlan
 
328
 * node (if we have to do the subplan as a subplan), or a Param node
 
329
 * representing the result of an InitPlan, or a row comparison expression
 
330
 * tree containing InitPlan Param nodes.
 
331
 */
 
332
static Node *
 
333
make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
 
334
                         Node *testexpr, bool isTopQual)
 
335
{
 
336
        Query      *subquery;
 
337
        bool            simple_exists = false;
 
338
        double          tuple_fraction;
 
339
        Plan       *plan;
 
340
        PlannerInfo *subroot;
 
341
        Node       *result;
 
342
 
 
343
        /*
 
344
         * Copy the source Query node.  This is a quick and dirty kluge to resolve
 
345
         * the fact that the parser can generate trees with multiple links to the
 
346
         * same sub-Query node, but the planner wants to scribble on the Query.
 
347
         * Try to clean this up when we do querytree redesign...
 
348
         */
 
349
        subquery = (Query *) copyObject(orig_subquery);
 
350
 
 
351
        /*
 
352
         * If it's an EXISTS subplan, we might be able to simplify it.
 
353
         */
 
354
        if (subLinkType == EXISTS_SUBLINK)
 
355
                simple_exists = simplify_EXISTS_query(subquery);
 
356
 
 
357
        /*
 
358
         * For an EXISTS subplan, tell lower-level planner to expect that only the
 
359
         * first tuple will be retrieved.  For ALL and ANY subplans, we will be
 
360
         * able to stop evaluating if the test condition fails or matches, so very
 
361
         * often not all the tuples will be retrieved; for lack of a better idea,
 
362
         * specify 50% retrieval.  For EXPR and ROWCOMPARE subplans, use default
 
363
         * behavior (we're only expecting one row out, anyway).
 
364
         *
 
365
         * NOTE: if you change these numbers, also change cost_subplan() in
 
366
         * path/costsize.c.
 
367
         *
 
368
         * XXX If an ANY subplan is uncorrelated, build_subplan may decide to hash
 
369
         * its output.  In that case it would've been better to specify full
 
370
         * retrieval.  At present, however, we can only check hashability after
 
371
         * we've made the subplan :-(.  (Determining whether it'll fit in work_mem
 
372
         * is the really hard part.)  Therefore, we don't want to be too
 
373
         * optimistic about the percentage of tuples retrieved, for fear of
 
374
         * selecting a plan that's bad for the materialization case.
 
375
         */
 
376
        if (subLinkType == EXISTS_SUBLINK)
 
377
                tuple_fraction = 1.0;   /* just like a LIMIT 1 */
 
378
        else if (subLinkType == ALL_SUBLINK ||
 
379
                         subLinkType == ANY_SUBLINK)
 
380
                tuple_fraction = 0.5;   /* 50% */
 
381
        else
 
382
                tuple_fraction = 0.0;   /* default behavior */
 
383
 
 
384
        /*
 
385
         * Generate the plan for the subquery.
 
386
         */
 
387
        plan = subquery_planner(root->glob, subquery,
 
388
                                                        root,
 
389
                                                        false, tuple_fraction,
 
390
                                                        &subroot);
 
391
 
 
392
        /* And convert to SubPlan or InitPlan format. */
 
393
        result = build_subplan(root, plan,
 
394
                                                   subroot->parse->rtable, subroot->rowMarks,
 
395
                                                   subLinkType, testexpr, true, isTopQual);
 
396
 
 
397
        /*
 
398
         * If it's a correlated EXISTS with an unimportant targetlist, we might be
 
399
         * able to transform it to the equivalent of an IN and then implement it
 
400
         * by hashing.  We don't have enough information yet to tell which way is
 
401
         * likely to be better (it depends on the expected number of executions of
 
402
         * the EXISTS qual, and we are much too early in planning the outer query
 
403
         * to be able to guess that).  So we generate both plans, if possible, and
 
404
         * leave it to the executor to decide which to use.
 
405
         */
 
406
        if (simple_exists && IsA(result, SubPlan))
 
407
        {
 
408
                Node       *newtestexpr;
 
409
                List       *paramIds;
 
410
 
 
411
                /* Make a second copy of the original subquery */
 
412
                subquery = (Query *) copyObject(orig_subquery);
 
413
                /* and re-simplify */
 
414
                simple_exists = simplify_EXISTS_query(subquery);
 
415
                Assert(simple_exists);
 
416
                /* See if it can be converted to an ANY query */
 
417
                subquery = convert_EXISTS_to_ANY(root, subquery,
 
418
                                                                                 &newtestexpr, &paramIds);
 
419
                if (subquery)
 
420
                {
 
421
                        /* Generate the plan for the ANY subquery; we'll need all rows */
 
422
                        plan = subquery_planner(root->glob, subquery,
 
423
                                                                        root,
 
424
                                                                        false, 0.0,
 
425
                                                                        &subroot);
 
426
 
 
427
                        /* Now we can check if it'll fit in work_mem */
 
428
                        if (subplan_is_hashable(plan))
 
429
                        {
 
430
                                SubPlan    *hashplan;
 
431
                                AlternativeSubPlan *asplan;
 
432
 
 
433
                                /* OK, convert to SubPlan format. */
 
434
                                hashplan = (SubPlan *) build_subplan(root, plan,
 
435
                                                                                                         subroot->parse->rtable,
 
436
                                                                                                         subroot->rowMarks,
 
437
                                                                                                         ANY_SUBLINK, newtestexpr,
 
438
                                                                                                         false, true);
 
439
                                /* Check we got what we expected */
 
440
                                Assert(IsA(hashplan, SubPlan));
 
441
                                Assert(hashplan->parParam == NIL);
 
442
                                Assert(hashplan->useHashTable);
 
443
                                /* build_subplan won't have filled in paramIds */
 
444
                                hashplan->paramIds = paramIds;
 
445
 
 
446
                                /* Leave it to the executor to decide which plan to use */
 
447
                                asplan = makeNode(AlternativeSubPlan);
 
448
                                asplan->subplans = list_make2(result, hashplan);
 
449
                                result = (Node *) asplan;
 
450
                        }
 
451
                }
 
452
        }
 
453
 
 
454
        return result;
 
455
}
 
456
 
 
457
/*
 
458
 * Build a SubPlan node given the raw inputs --- subroutine for make_subplan
 
459
 *
 
460
 * Returns either the SubPlan, or an expression using initplan output Params,
 
461
 * as explained in the comments for make_subplan.
 
462
 */
 
463
static Node *
 
464
build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
 
465
                          SubLinkType subLinkType, Node *testexpr,
 
466
                          bool adjust_testexpr, bool unknownEqFalse)
 
467
{
 
468
        Node       *result;
 
469
        SubPlan    *splan;
 
470
        bool            isInitPlan;
 
471
        Bitmapset  *tmpset;
 
472
        int                     paramid;
 
473
 
 
474
        /*
 
475
         * Initialize the SubPlan node.  Note plan_id, plan_name, and cost fields
 
476
         * are set further down.
 
477
         */
 
478
        splan = makeNode(SubPlan);
 
479
        splan->subLinkType = subLinkType;
 
480
        splan->testexpr = NULL;
 
481
        splan->paramIds = NIL;
 
482
        get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
 
483
                                           &splan->firstColCollation);
 
484
        splan->useHashTable = false;
 
485
        splan->unknownEqFalse = unknownEqFalse;
 
486
        splan->setParam = NIL;
 
487
        splan->parParam = NIL;
 
488
        splan->args = NIL;
 
489
 
 
490
        /*
 
491
         * Make parParam and args lists of param IDs and expressions that current
 
492
         * query level will pass to this child plan.
 
493
         */
 
494
        tmpset = bms_copy(plan->extParam);
 
495
        while ((paramid = bms_first_member(tmpset)) >= 0)
 
496
        {
 
497
                PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
 
498
 
 
499
                if (pitem->abslevel == root->query_level)
 
500
                {
 
501
                        Node       *arg;
 
502
 
 
503
                        /*
 
504
                         * The Var or Aggref has already been adjusted to have the correct
 
505
                         * varlevelsup or agglevelsup.  We probably don't even need to
 
506
                         * copy it again, but be safe.
 
507
                         */
 
508
                        arg = copyObject(pitem->item);
 
509
 
 
510
                        /*
 
511
                         * If it's an Aggref, its arguments might contain SubLinks, which
 
512
                         * have not yet been processed.  Do that now.
 
513
                         */
 
514
                        if (IsA(arg, Aggref))
 
515
                                arg = SS_process_sublinks(root, arg, false);
 
516
 
 
517
                        splan->parParam = lappend_int(splan->parParam, paramid);
 
518
                        splan->args = lappend(splan->args, arg);
 
519
                }
 
520
        }
 
521
        bms_free(tmpset);
 
522
 
 
523
        /*
 
524
         * Un-correlated or undirect correlated plans of EXISTS, EXPR, ARRAY, or
 
525
         * ROWCOMPARE types can be used as initPlans.  For EXISTS, EXPR, or ARRAY,
 
526
         * we just produce a Param referring to the result of evaluating the
 
527
         * initPlan.  For ROWCOMPARE, we must modify the testexpr tree to contain
 
528
         * PARAM_EXEC Params instead of the PARAM_SUBLINK Params emitted by the
 
529
         * parser.
 
530
         */
 
531
        if (splan->parParam == NIL && subLinkType == EXISTS_SUBLINK)
 
532
        {
 
533
                Param      *prm;
 
534
 
 
535
                Assert(testexpr == NULL);
 
536
                prm = generate_new_param(root, BOOLOID, -1, InvalidOid);
 
537
                splan->setParam = list_make1_int(prm->paramid);
 
538
                isInitPlan = true;
 
539
                result = (Node *) prm;
 
540
        }
 
541
        else if (splan->parParam == NIL && subLinkType == EXPR_SUBLINK)
 
542
        {
 
543
                TargetEntry *te = linitial(plan->targetlist);
 
544
                Param      *prm;
 
545
 
 
546
                Assert(!te->resjunk);
 
547
                Assert(testexpr == NULL);
 
548
                prm = generate_new_param(root,
 
549
                                                                 exprType((Node *) te->expr),
 
550
                                                                 exprTypmod((Node *) te->expr),
 
551
                                                                 exprCollation((Node *) te->expr));
 
552
                splan->setParam = list_make1_int(prm->paramid);
 
553
                isInitPlan = true;
 
554
                result = (Node *) prm;
 
555
        }
 
556
        else if (splan->parParam == NIL && subLinkType == ARRAY_SUBLINK)
 
557
        {
 
558
                TargetEntry *te = linitial(plan->targetlist);
 
559
                Oid                     arraytype;
 
560
                Param      *prm;
 
561
 
 
562
                Assert(!te->resjunk);
 
563
                Assert(testexpr == NULL);
 
564
                arraytype = get_array_type(exprType((Node *) te->expr));
 
565
                if (!OidIsValid(arraytype))
 
566
                        elog(ERROR, "could not find array type for datatype %s",
 
567
                                 format_type_be(exprType((Node *) te->expr)));
 
568
                prm = generate_new_param(root,
 
569
                                                                 arraytype,
 
570
                                                                 exprTypmod((Node *) te->expr),
 
571
                                                                 exprCollation((Node *) te->expr));
 
572
                splan->setParam = list_make1_int(prm->paramid);
 
573
                isInitPlan = true;
 
574
                result = (Node *) prm;
 
575
        }
 
576
        else if (splan->parParam == NIL && subLinkType == ROWCOMPARE_SUBLINK)
 
577
        {
 
578
                /* Adjust the Params */
 
579
                List       *params;
 
580
 
 
581
                Assert(testexpr != NULL);
 
582
                params = generate_subquery_params(root,
 
583
                                                                                  plan->targetlist,
 
584
                                                                                  &splan->paramIds);
 
585
                result = convert_testexpr(root,
 
586
                                                                  testexpr,
 
587
                                                                  params);
 
588
                splan->setParam = list_copy(splan->paramIds);
 
589
                isInitPlan = true;
 
590
 
 
591
                /*
 
592
                 * The executable expression is returned to become part of the outer
 
593
                 * plan's expression tree; it is not kept in the initplan node.
 
594
                 */
 
595
        }
 
596
        else
 
597
        {
 
598
                /*
 
599
                 * Adjust the Params in the testexpr, unless caller said it's not
 
600
                 * needed.
 
601
                 */
 
602
                if (testexpr && adjust_testexpr)
 
603
                {
 
604
                        List       *params;
 
605
 
 
606
                        params = generate_subquery_params(root,
 
607
                                                                                          plan->targetlist,
 
608
                                                                                          &splan->paramIds);
 
609
                        splan->testexpr = convert_testexpr(root,
 
610
                                                                                           testexpr,
 
611
                                                                                           params);
 
612
                }
 
613
                else
 
614
                        splan->testexpr = testexpr;
 
615
 
 
616
                /*
 
617
                 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
 
618
                 * initPlans, even when they are uncorrelated or undirect correlated,
 
619
                 * because we need to scan the output of the subplan for each outer
 
620
                 * tuple.  But if it's a not-direct-correlated IN (= ANY) test, we
 
621
                 * might be able to use a hashtable to avoid comparing all the tuples.
 
622
                 */
 
623
                if (subLinkType == ANY_SUBLINK &&
 
624
                        splan->parParam == NIL &&
 
625
                        subplan_is_hashable(plan) &&
 
626
                        testexpr_is_hashable(splan->testexpr))
 
627
                        splan->useHashTable = true;
 
628
 
 
629
                /*
 
630
                 * Otherwise, we have the option to tack a Material node onto the top
 
631
                 * of the subplan, to reduce the cost of reading it repeatedly.  This
 
632
                 * is pointless for a direct-correlated subplan, since we'd have to
 
633
                 * recompute its results each time anyway.      For uncorrelated/undirect
 
634
                 * correlated subplans, we add Material unless the subplan's top plan
 
635
                 * node would materialize its output anyway.  Also, if enable_material
 
636
                 * is false, then the user does not want us to materialize anything
 
637
                 * unnecessarily, so we don't.
 
638
                 */
 
639
                else if (splan->parParam == NIL && enable_material &&
 
640
                                 !ExecMaterializesOutput(nodeTag(plan)))
 
641
                        plan = materialize_finished_plan(plan);
 
642
 
 
643
                result = (Node *) splan;
 
644
                isInitPlan = false;
 
645
        }
 
646
 
 
647
        /*
 
648
         * Add the subplan and its rtable to the global lists.
 
649
         */
 
650
        root->glob->subplans = lappend(root->glob->subplans, plan);
 
651
        root->glob->subrtables = lappend(root->glob->subrtables, rtable);
 
652
        root->glob->subrowmarks = lappend(root->glob->subrowmarks, rowmarks);
 
653
        splan->plan_id = list_length(root->glob->subplans);
 
654
 
 
655
        if (isInitPlan)
 
656
                root->init_plans = lappend(root->init_plans, splan);
 
657
 
 
658
        /*
 
659
         * A parameterless subplan (not initplan) should be prepared to handle
 
660
         * REWIND efficiently.  If it has direct parameters then there's no point
 
661
         * since it'll be reset on each scan anyway; and if it's an initplan then
 
662
         * there's no point since it won't get re-run without parameter changes
 
663
         * anyway.      The input of a hashed subplan doesn't need REWIND either.
 
664
         */
 
665
        if (splan->parParam == NIL && !isInitPlan && !splan->useHashTable)
 
666
                root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
 
667
                                                                                                   splan->plan_id);
 
668
 
 
669
        /* Label the subplan for EXPLAIN purposes */
 
670
        if (isInitPlan)
 
671
        {
 
672
                ListCell   *lc;
 
673
                int                     offset;
 
674
 
 
675
                splan->plan_name = palloc(32 + 12 * list_length(splan->setParam));
 
676
                sprintf(splan->plan_name, "InitPlan %d (returns ", splan->plan_id);
 
677
                offset = strlen(splan->plan_name);
 
678
                foreach(lc, splan->setParam)
 
679
                {
 
680
                        sprintf(splan->plan_name + offset, "$%d%s",
 
681
                                        lfirst_int(lc),
 
682
                                        lnext(lc) ? "," : "");
 
683
                        offset += strlen(splan->plan_name + offset);
 
684
                }
 
685
                sprintf(splan->plan_name + offset, ")");
 
686
        }
 
687
        else
 
688
        {
 
689
                splan->plan_name = palloc(32);
 
690
                sprintf(splan->plan_name, "SubPlan %d", splan->plan_id);
 
691
        }
 
692
 
 
693
        /* Lastly, fill in the cost estimates for use later */
 
694
        cost_subplan(root, splan, plan);
 
695
 
 
696
        return result;
 
697
}
 
698
 
 
699
/*
 
700
 * generate_subquery_params: build a list of Params representing the output
 
701
 * columns of a sublink's sub-select, given the sub-select's targetlist.
 
702
 *
 
703
 * We also return an integer list of the paramids of the Params.
 
704
 */
 
705
static List *
 
706
generate_subquery_params(PlannerInfo *root, List *tlist, List **paramIds)
 
707
{
 
708
        List       *result;
 
709
        List       *ids;
 
710
        ListCell   *lc;
 
711
 
 
712
        result = ids = NIL;
 
713
        foreach(lc, tlist)
 
714
        {
 
715
                TargetEntry *tent = (TargetEntry *) lfirst(lc);
 
716
                Param      *param;
 
717
 
 
718
                if (tent->resjunk)
 
719
                        continue;
 
720
 
 
721
                param = generate_new_param(root,
 
722
                                                                   exprType((Node *) tent->expr),
 
723
                                                                   exprTypmod((Node *) tent->expr),
 
724
                                                                   exprCollation((Node *) tent->expr));
 
725
                result = lappend(result, param);
 
726
                ids = lappend_int(ids, param->paramid);
 
727
        }
 
728
 
 
729
        *paramIds = ids;
 
730
        return result;
 
731
}
 
732
 
 
733
/*
 
734
 * generate_subquery_vars: build a list of Vars representing the output
 
735
 * columns of a sublink's sub-select, given the sub-select's targetlist.
 
736
 * The Vars have the specified varno (RTE index).
 
737
 */
 
738
static List *
 
739
generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
 
740
{
 
741
        List       *result;
 
742
        ListCell   *lc;
 
743
 
 
744
        result = NIL;
 
745
        foreach(lc, tlist)
 
746
        {
 
747
                TargetEntry *tent = (TargetEntry *) lfirst(lc);
 
748
                Var                *var;
 
749
 
 
750
                if (tent->resjunk)
 
751
                        continue;
 
752
 
 
753
                var = makeVarFromTargetEntry(varno, tent);
 
754
                result = lappend(result, var);
 
755
        }
 
756
 
 
757
        return result;
 
758
}
 
759
 
 
760
/*
 
761
 * convert_testexpr: convert the testexpr given by the parser into
 
762
 * actually executable form.  This entails replacing PARAM_SUBLINK Params
 
763
 * with Params or Vars representing the results of the sub-select.      The
 
764
 * nodes to be substituted are passed in as the List result from
 
765
 * generate_subquery_params or generate_subquery_vars.
 
766
 *
 
767
 * The given testexpr has already been recursively processed by
 
768
 * process_sublinks_mutator.  Hence it can no longer contain any
 
769
 * PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that
 
770
 * any we find are for our own level of SubLink.
 
771
 */
 
772
static Node *
 
773
convert_testexpr(PlannerInfo *root,
 
774
                                 Node *testexpr,
 
775
                                 List *subst_nodes)
 
776
{
 
777
        convert_testexpr_context context;
 
778
 
 
779
        context.root = root;
 
780
        context.subst_nodes = subst_nodes;
 
781
        return convert_testexpr_mutator(testexpr, &context);
 
782
}
 
783
 
 
784
static Node *
 
785
convert_testexpr_mutator(Node *node,
 
786
                                                 convert_testexpr_context *context)
 
787
{
 
788
        if (node == NULL)
 
789
                return NULL;
 
790
        if (IsA(node, Param))
 
791
        {
 
792
                Param      *param = (Param *) node;
 
793
 
 
794
                if (param->paramkind == PARAM_SUBLINK)
 
795
                {
 
796
                        if (param->paramid <= 0 ||
 
797
                                param->paramid > list_length(context->subst_nodes))
 
798
                                elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid);
 
799
 
 
800
                        /*
 
801
                         * We copy the list item to avoid having doubly-linked
 
802
                         * substructure in the modified parse tree.  This is probably
 
803
                         * unnecessary when it's a Param, but be safe.
 
804
                         */
 
805
                        return (Node *) copyObject(list_nth(context->subst_nodes,
 
806
                                                                                                param->paramid - 1));
 
807
                }
 
808
        }
 
809
        return expression_tree_mutator(node,
 
810
                                                                   convert_testexpr_mutator,
 
811
                                                                   (void *) context);
 
812
}
 
813
 
 
814
/*
 
815
 * subplan_is_hashable: can we implement an ANY subplan by hashing?
 
816
 */
 
817
static bool
 
818
subplan_is_hashable(Plan *plan)
 
819
{
 
820
        double          subquery_size;
 
821
 
 
822
        /*
 
823
         * The estimated size of the subquery result must fit in work_mem. (Note:
 
824
         * we use sizeof(HeapTupleHeaderData) here even though the tuples will
 
825
         * actually be stored as MinimalTuples; this provides some fudge factor
 
826
         * for hashtable overhead.)
 
827
         */
 
828
        subquery_size = plan->plan_rows *
 
829
                (MAXALIGN(plan->plan_width) + MAXALIGN(sizeof(HeapTupleHeaderData)));
 
830
        if (subquery_size > work_mem * 1024L)
 
831
                return false;
 
832
 
 
833
        return true;
 
834
}
 
835
 
 
836
/*
 
837
 * testexpr_is_hashable: is an ANY SubLink's test expression hashable?
 
838
 */
 
839
static bool
 
840
testexpr_is_hashable(Node *testexpr)
 
841
{
 
842
        /*
 
843
         * The testexpr must be a single OpExpr, or an AND-clause containing only
 
844
         * OpExprs.
 
845
         *
 
846
         * The combining operators must be hashable and strict. The need for
 
847
         * hashability is obvious, since we want to use hashing. Without
 
848
         * strictness, behavior in the presence of nulls is too unpredictable.  We
 
849
         * actually must assume even more than plain strictness: they can't yield
 
850
         * NULL for non-null inputs, either (see nodeSubplan.c).  However, hash
 
851
         * indexes and hash joins assume that too.
 
852
         */
 
853
        if (testexpr && IsA(testexpr, OpExpr))
 
854
        {
 
855
                if (hash_ok_operator((OpExpr *) testexpr))
 
856
                        return true;
 
857
        }
 
858
        else if (and_clause(testexpr))
 
859
        {
 
860
                ListCell   *l;
 
861
 
 
862
                foreach(l, ((BoolExpr *) testexpr)->args)
 
863
                {
 
864
                        Node       *andarg = (Node *) lfirst(l);
 
865
 
 
866
                        if (!IsA(andarg, OpExpr))
 
867
                                return false;
 
868
                        if (!hash_ok_operator((OpExpr *) andarg))
 
869
                                return false;
 
870
                }
 
871
                return true;
 
872
        }
 
873
 
 
874
        return false;
 
875
}
 
876
 
 
877
/*
 
878
 * Check expression is hashable + strict
 
879
 *
 
880
 * We could use op_hashjoinable() and op_strict(), but do it like this to
 
881
 * avoid a redundant cache lookup.
 
882
 */
 
883
static bool
 
884
hash_ok_operator(OpExpr *expr)
 
885
{
 
886
        Oid                     opid = expr->opno;
 
887
 
 
888
        /* quick out if not a binary operator */
 
889
        if (list_length(expr->args) != 2)
 
890
                return false;
 
891
        if (opid == ARRAY_EQ_OP)
 
892
        {
 
893
                /* array_eq is strict, but must check input type to ensure hashable */
 
894
                Node       *leftarg = linitial(expr->args);
 
895
 
 
896
                return op_hashjoinable(opid, exprType(leftarg));
 
897
        }
 
898
        else
 
899
        {
 
900
                /* else must look up the operator properties */
 
901
                HeapTuple       tup;
 
902
                Form_pg_operator optup;
 
903
 
 
904
                tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opid));
 
905
                if (!HeapTupleIsValid(tup))
 
906
                        elog(ERROR, "cache lookup failed for operator %u", opid);
 
907
                optup = (Form_pg_operator) GETSTRUCT(tup);
 
908
                if (!optup->oprcanhash || !func_strict(optup->oprcode))
 
909
                {
 
910
                        ReleaseSysCache(tup);
 
911
                        return false;
 
912
                }
 
913
                ReleaseSysCache(tup);
 
914
                return true;
 
915
        }
 
916
}
 
917
 
 
918
 
 
919
/*
 
920
 * SS_process_ctes: process a query's WITH list
 
921
 *
 
922
 * We plan each interesting WITH item and convert it to an initplan.
 
923
 * A side effect is to fill in root->cte_plan_ids with a list that
 
924
 * parallels root->parse->cteList and provides the subplan ID for
 
925
 * each CTE's initplan.
 
926
 */
 
927
void
 
928
SS_process_ctes(PlannerInfo *root)
 
929
{
 
930
        ListCell   *lc;
 
931
 
 
932
        Assert(root->cte_plan_ids == NIL);
 
933
 
 
934
        foreach(lc, root->parse->cteList)
 
935
        {
 
936
                CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
 
937
                CmdType         cmdType = ((Query *) cte->ctequery)->commandType;
 
938
                Query      *subquery;
 
939
                Plan       *plan;
 
940
                PlannerInfo *subroot;
 
941
                SubPlan    *splan;
 
942
                Bitmapset  *tmpset;
 
943
                int                     paramid;
 
944
                Param      *prm;
 
945
 
 
946
                /*
 
947
                 * Ignore SELECT CTEs that are not actually referenced anywhere.
 
948
                 */
 
949
                if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
 
950
                {
 
951
                        /* Make a dummy entry in cte_plan_ids */
 
952
                        root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
 
953
                        continue;
 
954
                }
 
955
 
 
956
                /*
 
957
                 * Copy the source Query node.  Probably not necessary, but let's keep
 
958
                 * this similar to make_subplan.
 
959
                 */
 
960
                subquery = (Query *) copyObject(cte->ctequery);
 
961
 
 
962
                /*
 
963
                 * Generate the plan for the CTE query.  Always plan for full
 
964
                 * retrieval --- we don't have enough info to predict otherwise.
 
965
                 */
 
966
                plan = subquery_planner(root->glob, subquery,
 
967
                                                                root,
 
968
                                                                cte->cterecursive, 0.0,
 
969
                                                                &subroot);
 
970
 
 
971
                /*
 
972
                 * Make a SubPlan node for it.  This is just enough unlike
 
973
                 * build_subplan that we can't share code.
 
974
                 *
 
975
                 * Note plan_id, plan_name, and cost fields are set further down.
 
976
                 */
 
977
                splan = makeNode(SubPlan);
 
978
                splan->subLinkType = CTE_SUBLINK;
 
979
                splan->testexpr = NULL;
 
980
                splan->paramIds = NIL;
 
981
                get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
 
982
                                                   &splan->firstColCollation);
 
983
                splan->useHashTable = false;
 
984
                splan->unknownEqFalse = false;
 
985
                splan->setParam = NIL;
 
986
                splan->parParam = NIL;
 
987
                splan->args = NIL;
 
988
 
 
989
                /*
 
990
                 * Make parParam and args lists of param IDs and expressions that
 
991
                 * current query level will pass to this child plan.  Even though this
 
992
                 * is an initplan, there could be side-references to earlier
 
993
                 * initplan's outputs, specifically their CTE output parameters.
 
994
                 */
 
995
                tmpset = bms_copy(plan->extParam);
 
996
                while ((paramid = bms_first_member(tmpset)) >= 0)
 
997
                {
 
998
                        PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
 
999
 
 
1000
                        if (pitem->abslevel == root->query_level)
 
1001
                        {
 
1002
                                prm = (Param *) pitem->item;
 
1003
                                if (!IsA(prm, Param) ||
 
1004
                                        prm->paramtype != INTERNALOID)
 
1005
                                        elog(ERROR, "bogus local parameter passed to WITH query");
 
1006
 
 
1007
                                splan->parParam = lappend_int(splan->parParam, paramid);
 
1008
                                splan->args = lappend(splan->args, copyObject(prm));
 
1009
                        }
 
1010
                }
 
1011
                bms_free(tmpset);
 
1012
 
 
1013
                /*
 
1014
                 * Assign a param to represent the query output.  We only really care
 
1015
                 * about reserving a parameter ID number.
 
1016
                 */
 
1017
                prm = generate_new_param(root, INTERNALOID, -1, InvalidOid);
 
1018
                splan->setParam = list_make1_int(prm->paramid);
 
1019
 
 
1020
                /*
 
1021
                 * Add the subplan and its rtable to the global lists.
 
1022
                 */
 
1023
                root->glob->subplans = lappend(root->glob->subplans, plan);
 
1024
                root->glob->subrtables = lappend(root->glob->subrtables,
 
1025
                                                                                 subroot->parse->rtable);
 
1026
                root->glob->subrowmarks = lappend(root->glob->subrowmarks,
 
1027
                                                                                  subroot->rowMarks);
 
1028
                splan->plan_id = list_length(root->glob->subplans);
 
1029
 
 
1030
                root->init_plans = lappend(root->init_plans, splan);
 
1031
 
 
1032
                root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
 
1033
 
 
1034
                /* Label the subplan for EXPLAIN purposes */
 
1035
                splan->plan_name = palloc(4 + strlen(cte->ctename) + 1);
 
1036
                sprintf(splan->plan_name, "CTE %s", cte->ctename);
 
1037
 
 
1038
                /* Lastly, fill in the cost estimates for use later */
 
1039
                cost_subplan(root, splan, plan);
 
1040
        }
 
1041
}
 
1042
 
 
1043
/*
 
1044
 * convert_ANY_sublink_to_join: try to convert an ANY SubLink to a join
 
1045
 *
 
1046
 * The caller has found an ANY SubLink at the top level of one of the query's
 
1047
 * qual clauses, but has not checked the properties of the SubLink further.
 
1048
 * Decide whether it is appropriate to process this SubLink in join style.
 
1049
 * If so, form a JoinExpr and return it.  Return NULL if the SubLink cannot
 
1050
 * be converted to a join.
 
1051
 *
 
1052
 * The only non-obvious input parameter is available_rels: this is the set
 
1053
 * of query rels that can safely be referenced in the sublink expression.
 
1054
 * (We must restrict this to avoid changing the semantics when a sublink
 
1055
 * is present in an outer join's ON qual.)  The conversion must fail if
 
1056
 * the converted qual would reference any but these parent-query relids.
 
1057
 *
 
1058
 * On success, the returned JoinExpr has larg = NULL and rarg = the jointree
 
1059
 * item representing the pulled-up subquery.  The caller must set larg to
 
1060
 * represent the relation(s) on the lefthand side of the new join, and insert
 
1061
 * the JoinExpr into the upper query's jointree at an appropriate place
 
1062
 * (typically, where the lefthand relation(s) had been).  Note that the
 
1063
 * passed-in SubLink must also be removed from its original position in the
 
1064
 * query quals, since the quals of the returned JoinExpr replace it.
 
1065
 * (Notionally, we replace the SubLink with a constant TRUE, then elide the
 
1066
 * redundant constant from the qual.)
 
1067
 *
 
1068
 * Side effects of a successful conversion include adding the SubLink's
 
1069
 * subselect to the query's rangetable, so that it can be referenced in
 
1070
 * the JoinExpr's rarg.
 
1071
 */
 
1072
JoinExpr *
 
1073
convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
 
1074
                                                        Relids available_rels)
 
1075
{
 
1076
        JoinExpr   *result;
 
1077
        Query      *parse = root->parse;
 
1078
        Query      *subselect = (Query *) sublink->subselect;
 
1079
        Relids          upper_varnos;
 
1080
        int                     rtindex;
 
1081
        RangeTblEntry *rte;
 
1082
        RangeTblRef *rtr;
 
1083
        List       *subquery_vars;
 
1084
        Node       *quals;
 
1085
 
 
1086
        Assert(sublink->subLinkType == ANY_SUBLINK);
 
1087
 
 
1088
        /*
 
1089
         * The sub-select must not refer to any Vars of the parent query. (Vars of
 
1090
         * higher levels should be okay, though.)
 
1091
         */
 
1092
        if (contain_vars_of_level((Node *) subselect, 1))
 
1093
                return NULL;
 
1094
 
 
1095
        /*
 
1096
         * The test expression must contain some Vars of the parent query, else
 
1097
         * it's not gonna be a join.  (Note that it won't have Vars referring to
 
1098
         * the subquery, rather Params.)
 
1099
         */
 
1100
        upper_varnos = pull_varnos(sublink->testexpr);
 
1101
        if (bms_is_empty(upper_varnos))
 
1102
                return NULL;
 
1103
 
 
1104
        /*
 
1105
         * However, it can't refer to anything outside available_rels.
 
1106
         */
 
1107
        if (!bms_is_subset(upper_varnos, available_rels))
 
1108
                return NULL;
 
1109
 
 
1110
        /*
 
1111
         * The combining operators and left-hand expressions mustn't be volatile.
 
1112
         */
 
1113
        if (contain_volatile_functions(sublink->testexpr))
 
1114
                return NULL;
 
1115
 
 
1116
        /*
 
1117
         * Okay, pull up the sub-select into upper range table.
 
1118
         *
 
1119
         * We rely here on the assumption that the outer query has no references
 
1120
         * to the inner (necessarily true, other than the Vars that we build
 
1121
         * below). Therefore this is a lot easier than what pull_up_subqueries has
 
1122
         * to go through.
 
1123
         */
 
1124
        rte = addRangeTableEntryForSubquery(NULL,
 
1125
                                                                                subselect,
 
1126
                                                                                makeAlias("ANY_subquery", NIL),
 
1127
                                                                                false);
 
1128
        parse->rtable = lappend(parse->rtable, rte);
 
1129
        rtindex = list_length(parse->rtable);
 
1130
 
 
1131
        /*
 
1132
         * Form a RangeTblRef for the pulled-up sub-select.
 
1133
         */
 
1134
        rtr = makeNode(RangeTblRef);
 
1135
        rtr->rtindex = rtindex;
 
1136
 
 
1137
        /*
 
1138
         * Build a list of Vars representing the subselect outputs.
 
1139
         */
 
1140
        subquery_vars = generate_subquery_vars(root,
 
1141
                                                                                   subselect->targetList,
 
1142
                                                                                   rtindex);
 
1143
 
 
1144
        /*
 
1145
         * Build the new join's qual expression, replacing Params with these Vars.
 
1146
         */
 
1147
        quals = convert_testexpr(root, sublink->testexpr, subquery_vars);
 
1148
 
 
1149
        /*
 
1150
         * And finally, build the JoinExpr node.
 
1151
         */
 
1152
        result = makeNode(JoinExpr);
 
1153
        result->jointype = JOIN_SEMI;
 
1154
        result->isNatural = false;
 
1155
        result->larg = NULL;            /* caller must fill this in */
 
1156
        result->rarg = (Node *) rtr;
 
1157
        result->usingClause = NIL;
 
1158
        result->quals = quals;
 
1159
        result->alias = NULL;
 
1160
        result->rtindex = 0;            /* we don't need an RTE for it */
 
1161
 
 
1162
        return result;
 
1163
}
 
1164
 
 
1165
/*
 
1166
 * convert_EXISTS_sublink_to_join: try to convert an EXISTS SubLink to a join
 
1167
 *
 
1168
 * The API of this function is identical to convert_ANY_sublink_to_join's,
 
1169
 * except that we also support the case where the caller has found NOT EXISTS,
 
1170
 * so we need an additional input parameter "under_not".
 
1171
 */
 
1172
JoinExpr *
 
1173
convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
 
1174
                                                           bool under_not, Relids available_rels)
 
1175
{
 
1176
        JoinExpr   *result;
 
1177
        Query      *parse = root->parse;
 
1178
        Query      *subselect = (Query *) sublink->subselect;
 
1179
        Node       *whereClause;
 
1180
        int                     rtoffset;
 
1181
        int                     varno;
 
1182
        Relids          clause_varnos;
 
1183
        Relids          upper_varnos;
 
1184
 
 
1185
        Assert(sublink->subLinkType == EXISTS_SUBLINK);
 
1186
 
 
1187
        /*
 
1188
         * Can't flatten if it contains WITH.  (We could arrange to pull up the
 
1189
         * WITH into the parent query's cteList, but that risks changing the
 
1190
         * semantics, since a WITH ought to be executed once per associated query
 
1191
         * call.)  Note that convert_ANY_sublink_to_join doesn't have to reject
 
1192
         * this case, since it just produces a subquery RTE that doesn't have to
 
1193
         * get flattened into the parent query.
 
1194
         */
 
1195
        if (subselect->cteList)
 
1196
                return NULL;
 
1197
 
 
1198
        /*
 
1199
         * Copy the subquery so we can modify it safely (see comments in
 
1200
         * make_subplan).
 
1201
         */
 
1202
        subselect = (Query *) copyObject(subselect);
 
1203
 
 
1204
        /*
 
1205
         * See if the subquery can be simplified based on the knowledge that it's
 
1206
         * being used in EXISTS().      If we aren't able to get rid of its
 
1207
         * targetlist, we have to fail, because the pullup operation leaves us
 
1208
         * with noplace to evaluate the targetlist.
 
1209
         */
 
1210
        if (!simplify_EXISTS_query(subselect))
 
1211
                return NULL;
 
1212
 
 
1213
        /*
 
1214
         * The subquery must have a nonempty jointree, else we won't have a join.
 
1215
         */
 
1216
        if (subselect->jointree->fromlist == NIL)
 
1217
                return NULL;
 
1218
 
 
1219
        /*
 
1220
         * Separate out the WHERE clause.  (We could theoretically also remove
 
1221
         * top-level plain JOIN/ON clauses, but it's probably not worth the
 
1222
         * trouble.)
 
1223
         */
 
1224
        whereClause = subselect->jointree->quals;
 
1225
        subselect->jointree->quals = NULL;
 
1226
 
 
1227
        /*
 
1228
         * The rest of the sub-select must not refer to any Vars of the parent
 
1229
         * query.  (Vars of higher levels should be okay, though.)
 
1230
         */
 
1231
        if (contain_vars_of_level((Node *) subselect, 1))
 
1232
                return NULL;
 
1233
 
 
1234
        /*
 
1235
         * On the other hand, the WHERE clause must contain some Vars of the
 
1236
         * parent query, else it's not gonna be a join.
 
1237
         */
 
1238
        if (!contain_vars_of_level(whereClause, 1))
 
1239
                return NULL;
 
1240
 
 
1241
        /*
 
1242
         * We don't risk optimizing if the WHERE clause is volatile, either.
 
1243
         */
 
1244
        if (contain_volatile_functions(whereClause))
 
1245
                return NULL;
 
1246
 
 
1247
        /*
 
1248
         * Prepare to pull up the sub-select into top range table.
 
1249
         *
 
1250
         * We rely here on the assumption that the outer query has no references
 
1251
         * to the inner (necessarily true). Therefore this is a lot easier than
 
1252
         * what pull_up_subqueries has to go through.
 
1253
         *
 
1254
         * In fact, it's even easier than what convert_ANY_sublink_to_join has to
 
1255
         * do.  The machinations of simplify_EXISTS_query ensured that there is
 
1256
         * nothing interesting in the subquery except an rtable and jointree, and
 
1257
         * even the jointree FromExpr no longer has quals.      So we can just append
 
1258
         * the rtable to our own and use the FromExpr in our jointree. But first,
 
1259
         * adjust all level-zero varnos in the subquery to account for the rtable
 
1260
         * merger.
 
1261
         */
 
1262
        rtoffset = list_length(parse->rtable);
 
1263
        OffsetVarNodes((Node *) subselect, rtoffset, 0);
 
1264
        OffsetVarNodes(whereClause, rtoffset, 0);
 
1265
 
 
1266
        /*
 
1267
         * Upper-level vars in subquery will now be one level closer to their
 
1268
         * parent than before; in particular, anything that had been level 1
 
1269
         * becomes level zero.
 
1270
         */
 
1271
        IncrementVarSublevelsUp((Node *) subselect, -1, 1);
 
1272
        IncrementVarSublevelsUp(whereClause, -1, 1);
 
1273
 
 
1274
        /*
 
1275
         * Now that the WHERE clause is adjusted to match the parent query
 
1276
         * environment, we can easily identify all the level-zero rels it uses.
 
1277
         * The ones <= rtoffset belong to the upper query; the ones > rtoffset do
 
1278
         * not.
 
1279
         */
 
1280
        clause_varnos = pull_varnos(whereClause);
 
1281
        upper_varnos = NULL;
 
1282
        while ((varno = bms_first_member(clause_varnos)) >= 0)
 
1283
        {
 
1284
                if (varno <= rtoffset)
 
1285
                        upper_varnos = bms_add_member(upper_varnos, varno);
 
1286
        }
 
1287
        bms_free(clause_varnos);
 
1288
        Assert(!bms_is_empty(upper_varnos));
 
1289
 
 
1290
        /*
 
1291
         * Now that we've got the set of upper-level varnos, we can make the last
 
1292
         * check: only available_rels can be referenced.
 
1293
         */
 
1294
        if (!bms_is_subset(upper_varnos, available_rels))
 
1295
                return NULL;
 
1296
 
 
1297
        /* Now we can attach the modified subquery rtable to the parent */
 
1298
        parse->rtable = list_concat(parse->rtable, subselect->rtable);
 
1299
 
 
1300
        /*
 
1301
         * And finally, build the JoinExpr node.
 
1302
         */
 
1303
        result = makeNode(JoinExpr);
 
1304
        result->jointype = under_not ? JOIN_ANTI : JOIN_SEMI;
 
1305
        result->isNatural = false;
 
1306
        result->larg = NULL;            /* caller must fill this in */
 
1307
        /* flatten out the FromExpr node if it's useless */
 
1308
        if (list_length(subselect->jointree->fromlist) == 1)
 
1309
                result->rarg = (Node *) linitial(subselect->jointree->fromlist);
 
1310
        else
 
1311
                result->rarg = (Node *) subselect->jointree;
 
1312
        result->usingClause = NIL;
 
1313
        result->quals = whereClause;
 
1314
        result->alias = NULL;
 
1315
        result->rtindex = 0;            /* we don't need an RTE for it */
 
1316
 
 
1317
        return result;
 
1318
}
 
1319
 
 
1320
/*
 
1321
 * simplify_EXISTS_query: remove any useless stuff in an EXISTS's subquery
 
1322
 *
 
1323
 * The only thing that matters about an EXISTS query is whether it returns
 
1324
 * zero or more than zero rows.  Therefore, we can remove certain SQL features
 
1325
 * that won't affect that.  The only part that is really likely to matter in
 
1326
 * typical usage is simplifying the targetlist: it's a common habit to write
 
1327
 * "SELECT * FROM" even though there is no need to evaluate any columns.
 
1328
 *
 
1329
 * Note: by suppressing the targetlist we could cause an observable behavioral
 
1330
 * change, namely that any errors that might occur in evaluating the tlist
 
1331
 * won't occur, nor will other side-effects of volatile functions.  This seems
 
1332
 * unlikely to bother anyone in practice.
 
1333
 *
 
1334
 * Returns TRUE if was able to discard the targetlist, else FALSE.
 
1335
 */
 
1336
static bool
 
1337
simplify_EXISTS_query(Query *query)
 
1338
{
 
1339
        /*
 
1340
         * We don't try to simplify at all if the query uses set operations,
 
1341
         * aggregates, modifying CTEs, HAVING, LIMIT/OFFSET, or FOR UPDATE/SHARE;
 
1342
         * none of these seem likely in normal usage and their possible effects
 
1343
         * are complex.
 
1344
         */
 
1345
        if (query->commandType != CMD_SELECT ||
 
1346
                query->intoClause ||
 
1347
                query->setOperations ||
 
1348
                query->hasAggs ||
 
1349
                query->hasWindowFuncs ||
 
1350
                query->hasModifyingCTE ||
 
1351
                query->havingQual ||
 
1352
                query->limitOffset ||
 
1353
                query->limitCount ||
 
1354
                query->rowMarks)
 
1355
                return false;
 
1356
 
 
1357
        /*
 
1358
         * Mustn't throw away the targetlist if it contains set-returning
 
1359
         * functions; those could affect whether zero rows are returned!
 
1360
         */
 
1361
        if (expression_returns_set((Node *) query->targetList))
 
1362
                return false;
 
1363
 
 
1364
        /*
 
1365
         * Otherwise, we can throw away the targetlist, as well as any GROUP,
 
1366
         * WINDOW, DISTINCT, and ORDER BY clauses; none of those clauses will
 
1367
         * change a nonzero-rows result to zero rows or vice versa.  (Furthermore,
 
1368
         * since our parsetree representation of these clauses depends on the
 
1369
         * targetlist, we'd better throw them away if we drop the targetlist.)
 
1370
         */
 
1371
        query->targetList = NIL;
 
1372
        query->groupClause = NIL;
 
1373
        query->windowClause = NIL;
 
1374
        query->distinctClause = NIL;
 
1375
        query->sortClause = NIL;
 
1376
        query->hasDistinctOn = false;
 
1377
 
 
1378
        return true;
 
1379
}
 
1380
 
 
1381
/*
 
1382
 * convert_EXISTS_to_ANY: try to convert EXISTS to a hashable ANY sublink
 
1383
 *
 
1384
 * The subselect is expected to be a fresh copy that we can munge up,
 
1385
 * and to have been successfully passed through simplify_EXISTS_query.
 
1386
 *
 
1387
 * On success, the modified subselect is returned, and we store a suitable
 
1388
 * upper-level test expression at *testexpr, plus a list of the subselect's
 
1389
 * output Params at *paramIds.  (The test expression is already Param-ified
 
1390
 * and hence need not go through convert_testexpr, which is why we have to
 
1391
 * deal with the Param IDs specially.)
 
1392
 *
 
1393
 * On failure, returns NULL.
 
1394
 */
 
1395
static Query *
 
1396
convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
 
1397
                                          Node **testexpr, List **paramIds)
 
1398
{
 
1399
        Node       *whereClause;
 
1400
        List       *leftargs,
 
1401
                           *rightargs,
 
1402
                           *opids,
 
1403
                           *opcollations,
 
1404
                           *newWhere,
 
1405
                           *tlist,
 
1406
                           *testlist,
 
1407
                           *paramids;
 
1408
        ListCell   *lc,
 
1409
                           *rc,
 
1410
                           *oc,
 
1411
                           *cc;
 
1412
        AttrNumber      resno;
 
1413
 
 
1414
        /*
 
1415
         * Query must not require a targetlist, since we have to insert a new one.
 
1416
         * Caller should have dealt with the case already.
 
1417
         */
 
1418
        Assert(subselect->targetList == NIL);
 
1419
 
 
1420
        /*
 
1421
         * Separate out the WHERE clause.  (We could theoretically also remove
 
1422
         * top-level plain JOIN/ON clauses, but it's probably not worth the
 
1423
         * trouble.)
 
1424
         */
 
1425
        whereClause = subselect->jointree->quals;
 
1426
        subselect->jointree->quals = NULL;
 
1427
 
 
1428
        /*
 
1429
         * The rest of the sub-select must not refer to any Vars of the parent
 
1430
         * query.  (Vars of higher levels should be okay, though.)
 
1431
         *
 
1432
         * Note: we need not check for Aggrefs separately because we know the
 
1433
         * sub-select is as yet unoptimized; any uplevel Aggref must therefore
 
1434
         * contain an uplevel Var reference.  This is not the case below ...
 
1435
         */
 
1436
        if (contain_vars_of_level((Node *) subselect, 1))
 
1437
                return NULL;
 
1438
 
 
1439
        /*
 
1440
         * We don't risk optimizing if the WHERE clause is volatile, either.
 
1441
         */
 
1442
        if (contain_volatile_functions(whereClause))
 
1443
                return NULL;
 
1444
 
 
1445
        /*
 
1446
         * Clean up the WHERE clause by doing const-simplification etc on it.
 
1447
         * Aside from simplifying the processing we're about to do, this is
 
1448
         * important for being able to pull chunks of the WHERE clause up into the
 
1449
         * parent query.  Since we are invoked partway through the parent's
 
1450
         * preprocess_expression() work, earlier steps of preprocess_expression()
 
1451
         * wouldn't get applied to the pulled-up stuff unless we do them here. For
 
1452
         * the parts of the WHERE clause that get put back into the child query,
 
1453
         * this work is partially duplicative, but it shouldn't hurt.
 
1454
         *
 
1455
         * Note: we do not run flatten_join_alias_vars.  This is OK because any
 
1456
         * parent aliases were flattened already, and we're not going to pull any
 
1457
         * child Vars (of any description) into the parent.
 
1458
         *
 
1459
         * Note: passing the parent's root to eval_const_expressions is
 
1460
         * technically wrong, but we can get away with it since only the
 
1461
         * boundParams (if any) are used, and those would be the same in a
 
1462
         * subroot.
 
1463
         */
 
1464
        whereClause = eval_const_expressions(root, whereClause);
 
1465
        whereClause = (Node *) canonicalize_qual((Expr *) whereClause);
 
1466
        whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
 
1467
 
 
1468
        /*
 
1469
         * We now have a flattened implicit-AND list of clauses, which we try to
 
1470
         * break apart into "outervar = innervar" hash clauses. Anything that
 
1471
         * can't be broken apart just goes back into the newWhere list.  Note that
 
1472
         * we aren't trying hard yet to ensure that we have only outer or only
 
1473
         * inner on each side; we'll check that if we get to the end.
 
1474
         */
 
1475
        leftargs = rightargs = opids = opcollations = newWhere = NIL;
 
1476
        foreach(lc, (List *) whereClause)
 
1477
        {
 
1478
                OpExpr     *expr = (OpExpr *) lfirst(lc);
 
1479
 
 
1480
                if (IsA(expr, OpExpr) &&
 
1481
                        hash_ok_operator(expr))
 
1482
                {
 
1483
                        Node       *leftarg = (Node *) linitial(expr->args);
 
1484
                        Node       *rightarg = (Node *) lsecond(expr->args);
 
1485
 
 
1486
                        if (contain_vars_of_level(leftarg, 1))
 
1487
                        {
 
1488
                                leftargs = lappend(leftargs, leftarg);
 
1489
                                rightargs = lappend(rightargs, rightarg);
 
1490
                                opids = lappend_oid(opids, expr->opno);
 
1491
                                opcollations = lappend_oid(opcollations, expr->inputcollid);
 
1492
                                continue;
 
1493
                        }
 
1494
                        if (contain_vars_of_level(rightarg, 1))
 
1495
                        {
 
1496
                                /*
 
1497
                                 * We must commute the clause to put the outer var on the
 
1498
                                 * left, because the hashing code in nodeSubplan.c expects
 
1499
                                 * that.  This probably shouldn't ever fail, since hashable
 
1500
                                 * operators ought to have commutators, but be paranoid.
 
1501
                                 */
 
1502
                                expr->opno = get_commutator(expr->opno);
 
1503
                                if (OidIsValid(expr->opno) && hash_ok_operator(expr))
 
1504
                                {
 
1505
                                        leftargs = lappend(leftargs, rightarg);
 
1506
                                        rightargs = lappend(rightargs, leftarg);
 
1507
                                        opids = lappend_oid(opids, expr->opno);
 
1508
                                        opcollations = lappend_oid(opcollations, expr->inputcollid);
 
1509
                                        continue;
 
1510
                                }
 
1511
                                /* If no commutator, no chance to optimize the WHERE clause */
 
1512
                                return NULL;
 
1513
                        }
 
1514
                }
 
1515
                /* Couldn't handle it as a hash clause */
 
1516
                newWhere = lappend(newWhere, expr);
 
1517
        }
 
1518
 
 
1519
        /*
 
1520
         * If we didn't find anything we could convert, fail.
 
1521
         */
 
1522
        if (leftargs == NIL)
 
1523
                return NULL;
 
1524
 
 
1525
        /*
 
1526
         * There mustn't be any parent Vars or Aggs in the stuff that we intend to
 
1527
         * put back into the child query.  Note: you might think we don't need to
 
1528
         * check for Aggs separately, because an uplevel Agg must contain an
 
1529
         * uplevel Var in its argument.  But it is possible that the uplevel Var
 
1530
         * got optimized away by eval_const_expressions.  Consider
 
1531
         *
 
1532
         * SUM(CASE WHEN false THEN uplevelvar ELSE 0 END)
 
1533
         */
 
1534
        if (contain_vars_of_level((Node *) newWhere, 1) ||
 
1535
                contain_vars_of_level((Node *) rightargs, 1))
 
1536
                return NULL;
 
1537
        if (root->parse->hasAggs &&
 
1538
                (contain_aggs_of_level((Node *) newWhere, 1) ||
 
1539
                 contain_aggs_of_level((Node *) rightargs, 1)))
 
1540
                return NULL;
 
1541
 
 
1542
        /*
 
1543
         * And there can't be any child Vars in the stuff we intend to pull up.
 
1544
         * (Note: we'd need to check for child Aggs too, except we know the child
 
1545
         * has no aggs at all because of simplify_EXISTS_query's check. The same
 
1546
         * goes for window functions.)
 
1547
         */
 
1548
        if (contain_vars_of_level((Node *) leftargs, 0))
 
1549
                return NULL;
 
1550
 
 
1551
        /*
 
1552
         * Also reject sublinks in the stuff we intend to pull up.      (It might be
 
1553
         * possible to support this, but doesn't seem worth the complication.)
 
1554
         */
 
1555
        if (contain_subplans((Node *) leftargs))
 
1556
                return NULL;
 
1557
 
 
1558
        /*
 
1559
         * Okay, adjust the sublevelsup in the stuff we're pulling up.
 
1560
         */
 
1561
        IncrementVarSublevelsUp((Node *) leftargs, -1, 1);
 
1562
 
 
1563
        /*
 
1564
         * Put back any child-level-only WHERE clauses.
 
1565
         */
 
1566
        if (newWhere)
 
1567
                subselect->jointree->quals = (Node *) make_ands_explicit(newWhere);
 
1568
 
 
1569
        /*
 
1570
         * Build a new targetlist for the child that emits the expressions we
 
1571
         * need.  Concurrently, build a testexpr for the parent using Params to
 
1572
         * reference the child outputs.  (Since we generate Params directly here,
 
1573
         * there will be no need to convert the testexpr in build_subplan.)
 
1574
         */
 
1575
        tlist = testlist = paramids = NIL;
 
1576
        resno = 1;
 
1577
        /* there's no "forfour" so we have to chase one of the lists manually */
 
1578
        cc = list_head(opcollations);
 
1579
        forthree(lc, leftargs, rc, rightargs, oc, opids)
 
1580
        {
 
1581
                Node       *leftarg = (Node *) lfirst(lc);
 
1582
                Node       *rightarg = (Node *) lfirst(rc);
 
1583
                Oid                     opid = lfirst_oid(oc);
 
1584
                Oid                     opcollation = lfirst_oid(cc);
 
1585
                Param      *param;
 
1586
 
 
1587
                cc = lnext(cc);
 
1588
                param = generate_new_param(root,
 
1589
                                                                   exprType(rightarg),
 
1590
                                                                   exprTypmod(rightarg),
 
1591
                                                                   exprCollation(rightarg));
 
1592
                tlist = lappend(tlist,
 
1593
                                                makeTargetEntry((Expr *) rightarg,
 
1594
                                                                                resno++,
 
1595
                                                                                NULL,
 
1596
                                                                                false));
 
1597
                testlist = lappend(testlist,
 
1598
                                                   make_opclause(opid, BOOLOID, false,
 
1599
                                                                                 (Expr *) leftarg, (Expr *) param,
 
1600
                                                                                 InvalidOid, opcollation));
 
1601
                paramids = lappend_int(paramids, param->paramid);
 
1602
        }
 
1603
 
 
1604
        /* Put everything where it should go, and we're done */
 
1605
        subselect->targetList = tlist;
 
1606
        *testexpr = (Node *) make_ands_explicit(testlist);
 
1607
        *paramIds = paramids;
 
1608
 
 
1609
        return subselect;
 
1610
}
 
1611
 
 
1612
 
 
1613
/*
 
1614
 * Replace correlation vars (uplevel vars) with Params.
 
1615
 *
 
1616
 * Uplevel aggregates are replaced, too.
 
1617
 *
 
1618
 * Note: it is critical that this runs immediately after SS_process_sublinks.
 
1619
 * Since we do not recurse into the arguments of uplevel aggregates, they will
 
1620
 * get copied to the appropriate subplan args list in the parent query with
 
1621
 * uplevel vars not replaced by Params, but only adjusted in level (see
 
1622
 * replace_outer_agg).  That's exactly what we want for the vars of the parent
 
1623
 * level --- but if an aggregate's argument contains any further-up variables,
 
1624
 * they have to be replaced with Params in their turn.  That will happen when
 
1625
 * the parent level runs SS_replace_correlation_vars.  Therefore it must do
 
1626
 * so after expanding its sublinks to subplans.  And we don't want any steps
 
1627
 * in between, else those steps would never get applied to the aggregate
 
1628
 * argument expressions, either in the parent or the child level.
 
1629
 *
 
1630
 * Another fairly tricky thing going on here is the handling of SubLinks in
 
1631
 * the arguments of uplevel aggregates.  Those are not touched inside the
 
1632
 * intermediate query level, either.  Instead, SS_process_sublinks recurses
 
1633
 * on them after copying the Aggref expression into the parent plan level
 
1634
 * (this is actually taken care of in build_subplan).
 
1635
 */
 
1636
Node *
 
1637
SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
 
1638
{
 
1639
        /* No setup needed for tree walk, so away we go */
 
1640
        return replace_correlation_vars_mutator(expr, root);
 
1641
}
 
1642
 
 
1643
static Node *
 
1644
replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
 
1645
{
 
1646
        if (node == NULL)
 
1647
                return NULL;
 
1648
        if (IsA(node, Var))
 
1649
        {
 
1650
                if (((Var *) node)->varlevelsup > 0)
 
1651
                        return (Node *) replace_outer_var(root, (Var *) node);
 
1652
        }
 
1653
        if (IsA(node, Aggref))
 
1654
        {
 
1655
                if (((Aggref *) node)->agglevelsup > 0)
 
1656
                        return (Node *) replace_outer_agg(root, (Aggref *) node);
 
1657
        }
 
1658
        return expression_tree_mutator(node,
 
1659
                                                                   replace_correlation_vars_mutator,
 
1660
                                                                   (void *) root);
 
1661
}
 
1662
 
 
1663
/*
 
1664
 * Expand SubLinks to SubPlans in the given expression.
 
1665
 *
 
1666
 * The isQual argument tells whether or not this expression is a WHERE/HAVING
 
1667
 * qualifier expression.  If it is, any sublinks appearing at top level need
 
1668
 * not distinguish FALSE from UNKNOWN return values.
 
1669
 */
 
1670
Node *
 
1671
SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
 
1672
{
 
1673
        process_sublinks_context context;
 
1674
 
 
1675
        context.root = root;
 
1676
        context.isTopQual = isQual;
 
1677
        return process_sublinks_mutator(expr, &context);
 
1678
}
 
1679
 
 
1680
static Node *
 
1681
process_sublinks_mutator(Node *node, process_sublinks_context *context)
 
1682
{
 
1683
        process_sublinks_context locContext;
 
1684
 
 
1685
        locContext.root = context->root;
 
1686
 
 
1687
        if (node == NULL)
 
1688
                return NULL;
 
1689
        if (IsA(node, SubLink))
 
1690
        {
 
1691
                SubLink    *sublink = (SubLink *) node;
 
1692
                Node       *testexpr;
 
1693
 
 
1694
                /*
 
1695
                 * First, recursively process the lefthand-side expressions, if any.
 
1696
                 * They're not top-level anymore.
 
1697
                 */
 
1698
                locContext.isTopQual = false;
 
1699
                testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
 
1700
 
 
1701
                /*
 
1702
                 * Now build the SubPlan node and make the expr to return.
 
1703
                 */
 
1704
                return make_subplan(context->root,
 
1705
                                                        (Query *) sublink->subselect,
 
1706
                                                        sublink->subLinkType,
 
1707
                                                        testexpr,
 
1708
                                                        context->isTopQual);
 
1709
        }
 
1710
 
 
1711
        /*
 
1712
         * Don't recurse into the arguments of an outer aggregate here. Any
 
1713
         * SubLinks in the arguments have to be dealt with at the outer query
 
1714
         * level; they'll be handled when build_subplan collects the Aggref into
 
1715
         * the arguments to be passed down to the current subplan.
 
1716
         */
 
1717
        if (IsA(node, Aggref))
 
1718
        {
 
1719
                if (((Aggref *) node)->agglevelsup > 0)
 
1720
                        return node;
 
1721
        }
 
1722
 
 
1723
        /*
 
1724
         * We should never see a SubPlan expression in the input (since this is
 
1725
         * the very routine that creates 'em to begin with).  We shouldn't find
 
1726
         * ourselves invoked directly on a Query, either.
 
1727
         */
 
1728
        Assert(!IsA(node, SubPlan));
 
1729
        Assert(!IsA(node, AlternativeSubPlan));
 
1730
        Assert(!IsA(node, Query));
 
1731
 
 
1732
        /*
 
1733
         * Because make_subplan() could return an AND or OR clause, we have to
 
1734
         * take steps to preserve AND/OR flatness of a qual.  We assume the input
 
1735
         * has been AND/OR flattened and so we need no recursion here.
 
1736
         *
 
1737
         * (Due to the coding here, we will not get called on the List subnodes of
 
1738
         * an AND; and the input is *not* yet in implicit-AND format.  So no check
 
1739
         * is needed for a bare List.)
 
1740
         *
 
1741
         * Anywhere within the top-level AND/OR clause structure, we can tell
 
1742
         * make_subplan() that NULL and FALSE are interchangeable.      So isTopQual
 
1743
         * propagates down in both cases.  (Note that this is unlike the meaning
 
1744
         * of "top level qual" used in most other places in Postgres.)
 
1745
         */
 
1746
        if (and_clause(node))
 
1747
        {
 
1748
                List       *newargs = NIL;
 
1749
                ListCell   *l;
 
1750
 
 
1751
                /* Still at qual top-level */
 
1752
                locContext.isTopQual = context->isTopQual;
 
1753
 
 
1754
                foreach(l, ((BoolExpr *) node)->args)
 
1755
                {
 
1756
                        Node       *newarg;
 
1757
 
 
1758
                        newarg = process_sublinks_mutator(lfirst(l), &locContext);
 
1759
                        if (and_clause(newarg))
 
1760
                                newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
 
1761
                        else
 
1762
                                newargs = lappend(newargs, newarg);
 
1763
                }
 
1764
                return (Node *) make_andclause(newargs);
 
1765
        }
 
1766
 
 
1767
        if (or_clause(node))
 
1768
        {
 
1769
                List       *newargs = NIL;
 
1770
                ListCell   *l;
 
1771
 
 
1772
                /* Still at qual top-level */
 
1773
                locContext.isTopQual = context->isTopQual;
 
1774
 
 
1775
                foreach(l, ((BoolExpr *) node)->args)
 
1776
                {
 
1777
                        Node       *newarg;
 
1778
 
 
1779
                        newarg = process_sublinks_mutator(lfirst(l), &locContext);
 
1780
                        if (or_clause(newarg))
 
1781
                                newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
 
1782
                        else
 
1783
                                newargs = lappend(newargs, newarg);
 
1784
                }
 
1785
                return (Node *) make_orclause(newargs);
 
1786
        }
 
1787
 
 
1788
        /*
 
1789
         * If we recurse down through anything other than an AND or OR node, we
 
1790
         * are definitely not at top qual level anymore.
 
1791
         */
 
1792
        locContext.isTopQual = false;
 
1793
 
 
1794
        return expression_tree_mutator(node,
 
1795
                                                                   process_sublinks_mutator,
 
1796
                                                                   (void *) &locContext);
 
1797
}
 
1798
 
 
1799
/*
 
1800
 * SS_finalize_plan - do final sublink and parameter processing for a
 
1801
 * completed Plan.
 
1802
 *
 
1803
 * This recursively computes the extParam and allParam sets for every Plan
 
1804
 * node in the given plan tree.  It also optionally attaches any previously
 
1805
 * generated InitPlans to the top plan node.  (Any InitPlans should already
 
1806
 * have been put through SS_finalize_plan.)
 
1807
 */
 
1808
void
 
1809
SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
 
1810
{
 
1811
        Bitmapset  *valid_params,
 
1812
                           *initExtParam,
 
1813
                           *initSetParam;
 
1814
        Cost            initplan_cost;
 
1815
        int                     paramid;
 
1816
        ListCell   *l;
 
1817
 
 
1818
        /*
 
1819
         * Examine any initPlans to determine the set of external params they
 
1820
         * reference, the set of output params they supply, and their total cost.
 
1821
         * We'll use at least some of this info below.  (Note we are assuming that
 
1822
         * finalize_plan doesn't touch the initPlans.)
 
1823
         *
 
1824
         * In the case where attach_initplans is false, we are assuming that the
 
1825
         * existing initPlans are siblings that might supply params needed by the
 
1826
         * current plan.
 
1827
         */
 
1828
        initExtParam = initSetParam = NULL;
 
1829
        initplan_cost = 0;
 
1830
        foreach(l, root->init_plans)
 
1831
        {
 
1832
                SubPlan    *initsubplan = (SubPlan *) lfirst(l);
 
1833
                Plan       *initplan = planner_subplan_get_plan(root, initsubplan);
 
1834
                ListCell   *l2;
 
1835
 
 
1836
                initExtParam = bms_add_members(initExtParam, initplan->extParam);
 
1837
                foreach(l2, initsubplan->setParam)
 
1838
                {
 
1839
                        initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
 
1840
                }
 
1841
                initplan_cost += initsubplan->startup_cost + initsubplan->per_call_cost;
 
1842
        }
 
1843
 
 
1844
        /*
 
1845
         * Now determine the set of params that are validly referenceable in this
 
1846
         * query level; to wit, those available from outer query levels plus the
 
1847
         * output parameters of any initPlans.  (We do not include output
 
1848
         * parameters of regular subplans.      Those should only appear within the
 
1849
         * testexpr of SubPlan nodes, and are taken care of locally within
 
1850
         * finalize_primnode.  Likewise, special parameters that are generated by
 
1851
         * nodes such as ModifyTable are handled within finalize_plan.)
 
1852
         *
 
1853
         * Note: this is a bit overly generous since some parameters of upper
 
1854
         * query levels might belong to query subtrees that don't include this
 
1855
         * query, or might be nestloop params that won't be passed down at all.
 
1856
         * However, valid_params is only a debugging crosscheck, so it doesn't
 
1857
         * seem worth expending lots of cycles to try to be exact.
 
1858
         */
 
1859
        valid_params = bms_copy(initSetParam);
 
1860
        paramid = 0;
 
1861
        foreach(l, root->glob->paramlist)
 
1862
        {
 
1863
                PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
 
1864
 
 
1865
                if (pitem->abslevel < root->query_level)
 
1866
                {
 
1867
                        /* valid outer-level parameter */
 
1868
                        valid_params = bms_add_member(valid_params, paramid);
 
1869
                }
 
1870
 
 
1871
                paramid++;
 
1872
        }
 
1873
 
 
1874
        /*
 
1875
         * Now recurse through plan tree.
 
1876
         */
 
1877
        (void) finalize_plan(root, plan, valid_params, NULL);
 
1878
 
 
1879
        bms_free(valid_params);
 
1880
 
 
1881
        /*
 
1882
         * Finally, attach any initPlans to the topmost plan node, and add their
 
1883
         * extParams to the topmost node's, too.  However, any setParams of the
 
1884
         * initPlans should not be present in the topmost node's extParams, only
 
1885
         * in its allParams.  (As of PG 8.1, it's possible that some initPlans
 
1886
         * have extParams that are setParams of other initPlans, so we have to
 
1887
         * take care of this situation explicitly.)
 
1888
         *
 
1889
         * We also add the eval cost of each initPlan to the startup cost of the
 
1890
         * top node.  This is a conservative overestimate, since in fact each
 
1891
         * initPlan might be executed later than plan startup, or even not at all.
 
1892
         */
 
1893
        if (attach_initplans)
 
1894
        {
 
1895
                plan->initPlan = root->init_plans;
 
1896
                root->init_plans = NIL; /* make sure they're not attached twice */
 
1897
 
 
1898
                /* allParam must include all these params */
 
1899
                plan->allParam = bms_add_members(plan->allParam, initExtParam);
 
1900
                plan->allParam = bms_add_members(plan->allParam, initSetParam);
 
1901
                /* extParam must include any child extParam */
 
1902
                plan->extParam = bms_add_members(plan->extParam, initExtParam);
 
1903
                /* but extParam shouldn't include any setParams */
 
1904
                plan->extParam = bms_del_members(plan->extParam, initSetParam);
 
1905
                /* ensure extParam is exactly NULL if it's empty */
 
1906
                if (bms_is_empty(plan->extParam))
 
1907
                        plan->extParam = NULL;
 
1908
 
 
1909
                plan->startup_cost += initplan_cost;
 
1910
                plan->total_cost += initplan_cost;
 
1911
        }
 
1912
}
 
1913
 
 
1914
/*
 
1915
 * Recursive processing of all nodes in the plan tree
 
1916
 *
 
1917
 * valid_params is the set of param IDs considered valid to reference in
 
1918
 * this plan node or its children.
 
1919
 * scan_params is a set of param IDs to force scan plan nodes to reference.
 
1920
 * This is for EvalPlanQual support, and is always NULL at the top of the
 
1921
 * recursion.
 
1922
 *
 
1923
 * The return value is the computed allParam set for the given Plan node.
 
1924
 * This is just an internal notational convenience.
 
1925
 */
 
1926
static Bitmapset *
 
1927
finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
 
1928
                          Bitmapset *scan_params)
 
1929
{
 
1930
        finalize_primnode_context context;
 
1931
        int                     locally_added_param;
 
1932
        Bitmapset  *nestloop_params;
 
1933
        Bitmapset  *child_params;
 
1934
 
 
1935
        if (plan == NULL)
 
1936
                return NULL;
 
1937
 
 
1938
        context.root = root;
 
1939
        context.paramids = NULL;        /* initialize set to empty */
 
1940
        locally_added_param = -1;       /* there isn't one */
 
1941
        nestloop_params = NULL;         /* there aren't any */
 
1942
 
 
1943
        /*
 
1944
         * When we call finalize_primnode, context.paramids sets are automatically
 
1945
         * merged together.  But when recursing to self, we have to do it the hard
 
1946
         * way.  We want the paramids set to include params in subplans as well as
 
1947
         * at this level.
 
1948
         */
 
1949
 
 
1950
        /* Find params in targetlist and qual */
 
1951
        finalize_primnode((Node *) plan->targetlist, &context);
 
1952
        finalize_primnode((Node *) plan->qual, &context);
 
1953
 
 
1954
        /* Check additional node-type-specific fields */
 
1955
        switch (nodeTag(plan))
 
1956
        {
 
1957
                case T_Result:
 
1958
                        finalize_primnode(((Result *) plan)->resconstantqual,
 
1959
                                                          &context);
 
1960
                        break;
 
1961
 
 
1962
                case T_SeqScan:
 
1963
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
1964
                        break;
 
1965
 
 
1966
                case T_IndexScan:
 
1967
                        finalize_primnode((Node *) ((IndexScan *) plan)->indexqual,
 
1968
                                                          &context);
 
1969
                        finalize_primnode((Node *) ((IndexScan *) plan)->indexorderby,
 
1970
                                                          &context);
 
1971
 
 
1972
                        /*
 
1973
                         * we need not look at indexqualorig, since it will have the same
 
1974
                         * param references as indexqual.  Likewise, we can ignore
 
1975
                         * indexorderbyorig.
 
1976
                         */
 
1977
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
1978
                        break;
 
1979
 
 
1980
                case T_BitmapIndexScan:
 
1981
                        finalize_primnode((Node *) ((BitmapIndexScan *) plan)->indexqual,
 
1982
                                                          &context);
 
1983
 
 
1984
                        /*
 
1985
                         * we need not look at indexqualorig, since it will have the same
 
1986
                         * param references as indexqual.
 
1987
                         */
 
1988
                        break;
 
1989
 
 
1990
                case T_BitmapHeapScan:
 
1991
                        finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
 
1992
                                                          &context);
 
1993
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
1994
                        break;
 
1995
 
 
1996
                case T_TidScan:
 
1997
                        finalize_primnode((Node *) ((TidScan *) plan)->tidquals,
 
1998
                                                          &context);
 
1999
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2000
                        break;
 
2001
 
 
2002
                case T_SubqueryScan:
 
2003
 
 
2004
                        /*
 
2005
                         * In a SubqueryScan, SS_finalize_plan has already been run on the
 
2006
                         * subplan by the inner invocation of subquery_planner, so there's
 
2007
                         * no need to do it again.      Instead, just pull out the subplan's
 
2008
                         * extParams list, which represents the params it needs from my
 
2009
                         * level and higher levels.
 
2010
                         */
 
2011
                        context.paramids = bms_add_members(context.paramids,
 
2012
                                                                 ((SubqueryScan *) plan)->subplan->extParam);
 
2013
                        /* We need scan_params too, though */
 
2014
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2015
                        break;
 
2016
 
 
2017
                case T_FunctionScan:
 
2018
                        finalize_primnode(((FunctionScan *) plan)->funcexpr,
 
2019
                                                          &context);
 
2020
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2021
                        break;
 
2022
 
 
2023
                case T_ValuesScan:
 
2024
                        finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
 
2025
                                                          &context);
 
2026
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2027
                        break;
 
2028
 
 
2029
                case T_CteScan:
 
2030
                        {
 
2031
                                /*
 
2032
                                 * You might think we should add the node's cteParam to
 
2033
                                 * paramids, but we shouldn't because that param is just a
 
2034
                                 * linkage mechanism for multiple CteScan nodes for the same
 
2035
                                 * CTE; it is never used for changed-param signaling.  What we
 
2036
                                 * have to do instead is to find the referenced CTE plan and
 
2037
                                 * incorporate its external paramids, so that the correct
 
2038
                                 * things will happen if the CTE references outer-level
 
2039
                                 * variables.  See test cases for bug #4902.
 
2040
                                 */
 
2041
                                int                     plan_id = ((CteScan *) plan)->ctePlanId;
 
2042
                                Plan       *cteplan;
 
2043
 
 
2044
                                /* so, do this ... */
 
2045
                                if (plan_id < 1 || plan_id > list_length(root->glob->subplans))
 
2046
                                        elog(ERROR, "could not find plan for CteScan referencing plan ID %d",
 
2047
                                                 plan_id);
 
2048
                                cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
 
2049
                                context.paramids =
 
2050
                                        bms_add_members(context.paramids, cteplan->extParam);
 
2051
 
 
2052
#ifdef NOT_USED
 
2053
                                /* ... but not this */
 
2054
                                context.paramids =
 
2055
                                        bms_add_member(context.paramids,
 
2056
                                                                   ((CteScan *) plan)->cteParam);
 
2057
#endif
 
2058
 
 
2059
                                context.paramids = bms_add_members(context.paramids,
 
2060
                                                                                                   scan_params);
 
2061
                        }
 
2062
                        break;
 
2063
 
 
2064
                case T_WorkTableScan:
 
2065
                        context.paramids =
 
2066
                                bms_add_member(context.paramids,
 
2067
                                                           ((WorkTableScan *) plan)->wtParam);
 
2068
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2069
                        break;
 
2070
 
 
2071
                case T_ForeignScan:
 
2072
                        context.paramids = bms_add_members(context.paramids, scan_params);
 
2073
                        break;
 
2074
 
 
2075
                case T_ModifyTable:
 
2076
                        {
 
2077
                                ModifyTable *mtplan = (ModifyTable *) plan;
 
2078
                                ListCell   *l;
 
2079
 
 
2080
                                /* Force descendant scan nodes to reference epqParam */
 
2081
                                locally_added_param = mtplan->epqParam;
 
2082
                                valid_params = bms_add_member(bms_copy(valid_params),
 
2083
                                                                                          locally_added_param);
 
2084
                                scan_params = bms_add_member(bms_copy(scan_params),
 
2085
                                                                                         locally_added_param);
 
2086
                                finalize_primnode((Node *) mtplan->returningLists,
 
2087
                                                                  &context);
 
2088
                                foreach(l, mtplan->plans)
 
2089
                                {
 
2090
                                        context.paramids =
 
2091
                                                bms_add_members(context.paramids,
 
2092
                                                                                finalize_plan(root,
 
2093
                                                                                                          (Plan *) lfirst(l),
 
2094
                                                                                                          valid_params,
 
2095
                                                                                                          scan_params));
 
2096
                                }
 
2097
                        }
 
2098
                        break;
 
2099
 
 
2100
                case T_Append:
 
2101
                        {
 
2102
                                ListCell   *l;
 
2103
 
 
2104
                                foreach(l, ((Append *) plan)->appendplans)
 
2105
                                {
 
2106
                                        context.paramids =
 
2107
                                                bms_add_members(context.paramids,
 
2108
                                                                                finalize_plan(root,
 
2109
                                                                                                          (Plan *) lfirst(l),
 
2110
                                                                                                          valid_params,
 
2111
                                                                                                          scan_params));
 
2112
                                }
 
2113
                        }
 
2114
                        break;
 
2115
 
 
2116
                case T_MergeAppend:
 
2117
                        {
 
2118
                                ListCell   *l;
 
2119
 
 
2120
                                foreach(l, ((MergeAppend *) plan)->mergeplans)
 
2121
                                {
 
2122
                                        context.paramids =
 
2123
                                                bms_add_members(context.paramids,
 
2124
                                                                                finalize_plan(root,
 
2125
                                                                                                          (Plan *) lfirst(l),
 
2126
                                                                                                          valid_params,
 
2127
                                                                                                          scan_params));
 
2128
                                }
 
2129
                        }
 
2130
                        break;
 
2131
 
 
2132
                case T_BitmapAnd:
 
2133
                        {
 
2134
                                ListCell   *l;
 
2135
 
 
2136
                                foreach(l, ((BitmapAnd *) plan)->bitmapplans)
 
2137
                                {
 
2138
                                        context.paramids =
 
2139
                                                bms_add_members(context.paramids,
 
2140
                                                                                finalize_plan(root,
 
2141
                                                                                                          (Plan *) lfirst(l),
 
2142
                                                                                                          valid_params,
 
2143
                                                                                                          scan_params));
 
2144
                                }
 
2145
                        }
 
2146
                        break;
 
2147
 
 
2148
                case T_BitmapOr:
 
2149
                        {
 
2150
                                ListCell   *l;
 
2151
 
 
2152
                                foreach(l, ((BitmapOr *) plan)->bitmapplans)
 
2153
                                {
 
2154
                                        context.paramids =
 
2155
                                                bms_add_members(context.paramids,
 
2156
                                                                                finalize_plan(root,
 
2157
                                                                                                          (Plan *) lfirst(l),
 
2158
                                                                                                          valid_params,
 
2159
                                                                                                          scan_params));
 
2160
                                }
 
2161
                        }
 
2162
                        break;
 
2163
 
 
2164
                case T_NestLoop:
 
2165
                        {
 
2166
                                ListCell   *l;
 
2167
 
 
2168
                                finalize_primnode((Node *) ((Join *) plan)->joinqual,
 
2169
                                                                  &context);
 
2170
                                /* collect set of params that will be passed to right child */
 
2171
                                foreach(l, ((NestLoop *) plan)->nestParams)
 
2172
                                {
 
2173
                                        NestLoopParam *nlp = (NestLoopParam *) lfirst(l);
 
2174
 
 
2175
                                        nestloop_params = bms_add_member(nestloop_params,
 
2176
                                                                                                         nlp->paramno);
 
2177
                                }
 
2178
                        }
 
2179
                        break;
 
2180
 
 
2181
                case T_MergeJoin:
 
2182
                        finalize_primnode((Node *) ((Join *) plan)->joinqual,
 
2183
                                                          &context);
 
2184
                        finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
 
2185
                                                          &context);
 
2186
                        break;
 
2187
 
 
2188
                case T_HashJoin:
 
2189
                        finalize_primnode((Node *) ((Join *) plan)->joinqual,
 
2190
                                                          &context);
 
2191
                        finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
 
2192
                                                          &context);
 
2193
                        break;
 
2194
 
 
2195
                case T_Limit:
 
2196
                        finalize_primnode(((Limit *) plan)->limitOffset,
 
2197
                                                          &context);
 
2198
                        finalize_primnode(((Limit *) plan)->limitCount,
 
2199
                                                          &context);
 
2200
                        break;
 
2201
 
 
2202
                case T_RecursiveUnion:
 
2203
                        /* child nodes are allowed to reference wtParam */
 
2204
                        locally_added_param = ((RecursiveUnion *) plan)->wtParam;
 
2205
                        valid_params = bms_add_member(bms_copy(valid_params),
 
2206
                                                                                  locally_added_param);
 
2207
                        /* wtParam does *not* get added to scan_params */
 
2208
                        break;
 
2209
 
 
2210
                case T_LockRows:
 
2211
                        /* Force descendant scan nodes to reference epqParam */
 
2212
                        locally_added_param = ((LockRows *) plan)->epqParam;
 
2213
                        valid_params = bms_add_member(bms_copy(valid_params),
 
2214
                                                                                  locally_added_param);
 
2215
                        scan_params = bms_add_member(bms_copy(scan_params),
 
2216
                                                                                 locally_added_param);
 
2217
                        break;
 
2218
 
 
2219
                case T_WindowAgg:
 
2220
                        finalize_primnode(((WindowAgg *) plan)->startOffset,
 
2221
                                                          &context);
 
2222
                        finalize_primnode(((WindowAgg *) plan)->endOffset,
 
2223
                                                          &context);
 
2224
                        break;
 
2225
 
 
2226
                case T_Hash:
 
2227
                case T_Agg:
 
2228
                case T_Material:
 
2229
                case T_Sort:
 
2230
                case T_Unique:
 
2231
                case T_SetOp:
 
2232
                case T_Group:
 
2233
                        break;
 
2234
 
 
2235
                default:
 
2236
                        elog(ERROR, "unrecognized node type: %d",
 
2237
                                 (int) nodeTag(plan));
 
2238
        }
 
2239
 
 
2240
        /* Process left and right child plans, if any */
 
2241
        child_params = finalize_plan(root,
 
2242
                                                                 plan->lefttree,
 
2243
                                                                 valid_params,
 
2244
                                                                 scan_params);
 
2245
        context.paramids = bms_add_members(context.paramids, child_params);
 
2246
 
 
2247
        if (nestloop_params)
 
2248
        {
 
2249
                /* right child can reference nestloop_params as well as valid_params */
 
2250
                child_params = finalize_plan(root,
 
2251
                                                                         plan->righttree,
 
2252
                                                                         bms_union(nestloop_params, valid_params),
 
2253
                                                                         scan_params);
 
2254
                /* ... and they don't count as parameters used at my level */
 
2255
                child_params = bms_difference(child_params, nestloop_params);
 
2256
                bms_free(nestloop_params);
 
2257
        }
 
2258
        else
 
2259
        {
 
2260
                /* easy case */
 
2261
                child_params = finalize_plan(root,
 
2262
                                                                         plan->righttree,
 
2263
                                                                         valid_params,
 
2264
                                                                         scan_params);
 
2265
        }
 
2266
        context.paramids = bms_add_members(context.paramids, child_params);
 
2267
 
 
2268
        /*
 
2269
         * Any locally generated parameter doesn't count towards its generating
 
2270
         * plan node's external dependencies.  (Note: if we changed valid_params
 
2271
         * and/or scan_params, we leak those bitmapsets; not worth the notational
 
2272
         * trouble to clean them up.)
 
2273
         */
 
2274
        if (locally_added_param >= 0)
 
2275
        {
 
2276
                context.paramids = bms_del_member(context.paramids,
 
2277
                                                                                  locally_added_param);
 
2278
        }
 
2279
 
 
2280
        /* Now we have all the paramids */
 
2281
 
 
2282
        if (!bms_is_subset(context.paramids, valid_params))
 
2283
                elog(ERROR, "plan should not reference subplan's variable");
 
2284
 
 
2285
        /*
 
2286
         * Note: by definition, extParam and allParam should have the same value
 
2287
         * in any plan node that doesn't have child initPlans.  We set them equal
 
2288
         * here, and later SS_finalize_plan will update them properly in node(s)
 
2289
         * that it attaches initPlans to.
 
2290
         *
 
2291
         * For speed at execution time, make sure extParam/allParam are actually
 
2292
         * NULL if they are empty sets.
 
2293
         */
 
2294
        if (bms_is_empty(context.paramids))
 
2295
        {
 
2296
                plan->extParam = NULL;
 
2297
                plan->allParam = NULL;
 
2298
        }
 
2299
        else
 
2300
        {
 
2301
                plan->extParam = context.paramids;
 
2302
                plan->allParam = bms_copy(context.paramids);
 
2303
        }
 
2304
 
 
2305
        return plan->allParam;
 
2306
}
 
2307
 
 
2308
/*
 
2309
 * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given
 
2310
 * expression tree to the result set.
 
2311
 */
 
2312
static bool
 
2313
finalize_primnode(Node *node, finalize_primnode_context *context)
 
2314
{
 
2315
        if (node == NULL)
 
2316
                return false;
 
2317
        if (IsA(node, Param))
 
2318
        {
 
2319
                if (((Param *) node)->paramkind == PARAM_EXEC)
 
2320
                {
 
2321
                        int                     paramid = ((Param *) node)->paramid;
 
2322
 
 
2323
                        context->paramids = bms_add_member(context->paramids, paramid);
 
2324
                }
 
2325
                return false;                   /* no more to do here */
 
2326
        }
 
2327
        if (IsA(node, SubPlan))
 
2328
        {
 
2329
                SubPlan    *subplan = (SubPlan *) node;
 
2330
                Plan       *plan = planner_subplan_get_plan(context->root, subplan);
 
2331
                ListCell   *lc;
 
2332
                Bitmapset  *subparamids;
 
2333
 
 
2334
                /* Recurse into the testexpr, but not into the Plan */
 
2335
                finalize_primnode(subplan->testexpr, context);
 
2336
 
 
2337
                /*
 
2338
                 * Remove any param IDs of output parameters of the subplan that were
 
2339
                 * referenced in the testexpr.  These are not interesting for
 
2340
                 * parameter change signaling since we always re-evaluate the subplan.
 
2341
                 * Note that this wouldn't work too well if there might be uses of the
 
2342
                 * same param IDs elsewhere in the plan, but that can't happen because
 
2343
                 * generate_new_param never tries to merge params.
 
2344
                 */
 
2345
                foreach(lc, subplan->paramIds)
 
2346
                {
 
2347
                        context->paramids = bms_del_member(context->paramids,
 
2348
                                                                                           lfirst_int(lc));
 
2349
                }
 
2350
 
 
2351
                /* Also examine args list */
 
2352
                finalize_primnode((Node *) subplan->args, context);
 
2353
 
 
2354
                /*
 
2355
                 * Add params needed by the subplan to paramids, but excluding those
 
2356
                 * we will pass down to it.
 
2357
                 */
 
2358
                subparamids = bms_copy(plan->extParam);
 
2359
                foreach(lc, subplan->parParam)
 
2360
                {
 
2361
                        subparamids = bms_del_member(subparamids, lfirst_int(lc));
 
2362
                }
 
2363
                context->paramids = bms_join(context->paramids, subparamids);
 
2364
 
 
2365
                return false;                   /* no more to do here */
 
2366
        }
 
2367
        return expression_tree_walker(node, finalize_primnode,
 
2368
                                                                  (void *) context);
 
2369
}
 
2370
 
 
2371
/*
 
2372
 * SS_make_initplan_from_plan - given a plan tree, make it an InitPlan
 
2373
 *
 
2374
 * The plan is expected to return a scalar value of the given type/collation.
 
2375
 * We build an EXPR_SUBLINK SubPlan node and put it into the initplan
 
2376
 * list for the current query level.  A Param that represents the initplan's
 
2377
 * output is returned.
 
2378
 *
 
2379
 * We assume the plan hasn't been put through SS_finalize_plan.
 
2380
 */
 
2381
Param *
 
2382
SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
 
2383
                                                   Oid resulttype, int32 resulttypmod,
 
2384
                                                   Oid resultcollation)
 
2385
{
 
2386
        SubPlan    *node;
 
2387
        Param      *prm;
 
2388
 
 
2389
        /*
 
2390
         * We must run SS_finalize_plan(), since that's normally done before a
 
2391
         * subplan gets put into the initplan list.  Tell it not to attach any
 
2392
         * pre-existing initplans to this one, since they are siblings not
 
2393
         * children of this initplan.  (This is something else that could perhaps
 
2394
         * be cleaner if we did extParam/allParam processing in setrefs.c instead
 
2395
         * of here?  See notes for materialize_finished_plan.)
 
2396
         */
 
2397
 
 
2398
        /*
 
2399
         * Build extParam/allParam sets for plan nodes.
 
2400
         */
 
2401
        SS_finalize_plan(root, plan, false);
 
2402
 
 
2403
        /*
 
2404
         * Add the subplan and its rtable to the global lists.
 
2405
         */
 
2406
        root->glob->subplans = lappend(root->glob->subplans,
 
2407
                                                                   plan);
 
2408
        root->glob->subrtables = lappend(root->glob->subrtables,
 
2409
                                                                         root->parse->rtable);
 
2410
        root->glob->subrowmarks = lappend(root->glob->subrowmarks,
 
2411
                                                                          root->rowMarks);
 
2412
 
 
2413
        /*
 
2414
         * Create a SubPlan node and add it to the outer list of InitPlans. Note
 
2415
         * it has to appear after any other InitPlans it might depend on (see
 
2416
         * comments in ExecReScan).
 
2417
         */
 
2418
        node = makeNode(SubPlan);
 
2419
        node->subLinkType = EXPR_SUBLINK;
 
2420
        get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
 
2421
                                           &node->firstColCollation);
 
2422
        node->plan_id = list_length(root->glob->subplans);
 
2423
 
 
2424
        root->init_plans = lappend(root->init_plans, node);
 
2425
 
 
2426
        /*
 
2427
         * The node can't have any inputs (since it's an initplan), so the
 
2428
         * parParam and args lists remain empty.
 
2429
         */
 
2430
 
 
2431
        cost_subplan(root, node, plan);
 
2432
 
 
2433
        /*
 
2434
         * Make a Param that will be the subplan's output.
 
2435
         */
 
2436
        prm = generate_new_param(root, resulttype, resulttypmod, resultcollation);
 
2437
        node->setParam = list_make1_int(prm->paramid);
 
2438
 
 
2439
        /* Label the subplan for EXPLAIN purposes */
 
2440
        node->plan_name = palloc(64);
 
2441
        sprintf(node->plan_name, "InitPlan %d (returns $%d)",
 
2442
                        node->plan_id, prm->paramid);
 
2443
 
 
2444
        return prm;
 
2445
}