Coverage Report

Created: 2026-10-16 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/optimizer/prep/prepjointree.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * prepjointree.c
4
 *    Planner preprocessing for subqueries and join tree manipulation.
5
 *
6
 * NOTE: the intended sequence for invoking these operations is
7
 *    preprocess_relation_rtes
8
 *    replace_empty_jointree
9
 *    pull_up_sublinks
10
 *    preprocess_function_rtes
11
 *    pull_up_subqueries
12
 *    flatten_simple_union_all
13
 *    do expression preprocessing (including flattening JOIN alias vars)
14
 *    reduce_outer_joins
15
 *    remove_useless_result_rtes
16
 *
17
 *
18
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
19
 * Portions Copyright (c) 1994, Regents of the University of California
20
 *
21
 *
22
 * IDENTIFICATION
23
 *    src/backend/optimizer/prep/prepjointree.c
24
 *
25
 *-------------------------------------------------------------------------
26
 */
27
#include "postgres.h"
28
29
#include "access/table.h"
30
#include "catalog/pg_type.h"
31
#include "funcapi.h"
32
#include "miscadmin.h"
33
#include "nodes/makefuncs.h"
34
#include "nodes/multibitmapset.h"
35
#include "nodes/nodeFuncs.h"
36
#include "optimizer/clauses.h"
37
#include "optimizer/optimizer.h"
38
#include "optimizer/placeholder.h"
39
#include "optimizer/plancat.h"
40
#include "optimizer/prep.h"
41
#include "optimizer/subselect.h"
42
#include "optimizer/tlist.h"
43
#include "parser/parse_relation.h"
44
#include "parser/parsetree.h"
45
#include "rewrite/rewriteHandler.h"
46
#include "rewrite/rewriteManip.h"
47
#include "utils/rel.h"
48
49
50
typedef struct nullingrel_info
51
{
52
  /*
53
   * For each leaf RTE, nullingrels[rti] is the set of relids of outer joins
54
   * that potentially null that RTE.
55
   */
56
  Relids     *nullingrels;
57
  /* Length of range table (maximum index in nullingrels[]) */
58
  int     rtlength;   /* used only for assertion checks */
59
} nullingrel_info;
60
61
/* Options for wrapping an expression for identification purposes */
62
typedef enum ReplaceWrapOption
63
{
64
  REPLACE_WRAP_NONE,      /* no expressions need to be wrapped */
65
  REPLACE_WRAP_ALL,     /* all expressions need to be wrapped */
66
  REPLACE_WRAP_VARFREE,   /* variable-free expressions need to be
67
                 * wrapped */
68
} ReplaceWrapOption;
69
70
typedef struct pullup_replace_vars_context
71
{
72
  PlannerInfo *root;
73
  List     *targetlist;   /* tlist of subquery being pulled up */
74
  RangeTblEntry *target_rte;  /* RTE of subquery */
75
  int     result_relation;  /* the index of the result relation in the
76
                   * rewritten query */
77
  Relids    relids;     /* relids within subquery, as numbered after
78
                 * pullup (set only if target_rte->lateral) */
79
  nullingrel_info *nullinfo;  /* per-RTE nullingrel info (set only if
80
                 * target_rte->lateral) */
81
  bool     *outer_hasSubLinks;  /* -> outer query's hasSubLinks */
82
  int     varno;      /* varno of subquery */
83
  ReplaceWrapOption wrap_option;  /* do we need certain outputs to be PHVs? */
84
  Node    **rv_cache;   /* cache for results with PHVs */
85
} pullup_replace_vars_context;
86
87
typedef struct reduce_outer_joins_pass1_state
88
{
89
  Relids    relids;     /* base relids within this subtree */
90
  bool    contains_outer; /* does subtree contain outer join(s)? */
91
  Relids    nullable_rels;  /* base relids that are nullable within this
92
                 * subtree */
93
  Node     *jtnode;     /* the jointree node this state describes */
94
  List     *sub_states;   /* List of states for subtree components */
95
} reduce_outer_joins_pass1_state;
96
97
typedef struct reduce_outer_joins_pass2_state
98
{
99
  Relids    inner_reduced;  /* OJ relids reduced to plain inner joins */
100
  List     *partial_reduced;  /* List of partially reduced FULL joins */
101
  Relids    anti_reduced; /* OJ relids reduced to antijoins */
102
} reduce_outer_joins_pass2_state;
103
104
typedef struct reduce_outer_joins_partial_state
105
{
106
  int     full_join_rti;  /* RT index of a formerly-FULL join */
107
  Relids    unreduced_side; /* relids in its still-nullable side */
108
} reduce_outer_joins_partial_state;
109
110
static Query *expand_virtual_generated_columns(PlannerInfo *root, Query *parse,
111
                         RangeTblEntry *rte, int rt_index,
112
                         Relation relation);
113
static Node *pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
114
                         Relids *relids);
115
static Node *pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
116
                       Node **jtlink1, Relids available_rels1,
117
                       Node **jtlink2, Relids available_rels2);
118
static Node *pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
119
                    JoinExpr *lowest_outer_join,
120
                    AppendRelInfo *containing_appendrel);
121
static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
122
                   RangeTblEntry *rte,
123
                   JoinExpr *lowest_outer_join,
124
                   AppendRelInfo *containing_appendrel);
125
static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
126
                    RangeTblEntry *rte);
127
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
128
                     int parentRTindex, Query *setOpQuery,
129
                     int childRToffset);
130
static void make_setop_translation_list(Query *query, int newvarno,
131
                    AppendRelInfo *appinfo);
132
static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
133
                 RangeTblEntry *rte,
134
                 JoinExpr *lowest_outer_join);
135
static Node *pull_up_simple_values(PlannerInfo *root, Node *jtnode,
136
                   RangeTblEntry *rte);
137
static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte);
138
static Node *pull_up_constant_function(PlannerInfo *root, Node *jtnode,
139
                     RangeTblEntry *rte,
140
                     AppendRelInfo *containing_appendrel);
141
static bool is_simple_union_all(Query *subquery);
142
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
143
                    List *colTypes);
144
static bool is_safe_append_member(Query *subquery);
145
static bool jointree_contains_lateral_outer_refs(PlannerInfo *root,
146
                         Node *jtnode, bool restricted,
147
                         Relids safe_upper_varnos);
148
static void flatten_join_alias_vars_in_jointree(PlannerInfo *root,
149
                        Node *jtnode);
150
static void perform_pullup_replace_vars(PlannerInfo *root,
151
                    pullup_replace_vars_context *rvcontext,
152
                    AppendRelInfo *containing_appendrel);
153
static void replace_vars_in_jointree(Node *jtnode,
154
                   pullup_replace_vars_context *context);
155
static Node *pullup_replace_vars(Node *expr,
156
                 pullup_replace_vars_context *context);
157
static Node *pullup_replace_vars_callback(const Var *var,
158
                      replace_rte_variables_context *context);
159
static Query *pullup_replace_vars_subquery(Query *query,
160
                       pullup_replace_vars_context *context);
161
static reduce_outer_joins_pass1_state *reduce_outer_joins_pass1(Node *jtnode);
162
static void reduce_outer_joins_pass2(Node *jtnode,
163
                   reduce_outer_joins_pass1_state *state1,
164
                   reduce_outer_joins_pass2_state *state2,
165
                   PlannerInfo *root,
166
                   Relids nonnullable_rels,
167
                   List *forced_null_vars);
168
static void report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
169
                   int rtindex, Relids relids);
170
static void remove_redundant_nullability_quals(Node *jtnode,
171
                         Relids antijoins);
172
static Node *strip_redundant_nullability_quals(Node *quals, Relids antijoins);
173
static bool forced_null_var_is_attnotnull(PlannerInfo *root,
174
                      List *forced_null_vars,
175
                      reduce_outer_joins_pass1_state *state);
176
static bool forced_null_var_is_nonnullable(PlannerInfo *root,
177
                       List *forced_null_vars,
178
                       reduce_outer_joins_pass1_state *state,
179
                       List *extra_quals);
180
static Node *remove_useless_results_recurse(PlannerInfo *root, Node *jtnode,
181
                      Relids baserels,
182
                      Node **parent_quals,
183
                      Relids *dropped_outer_joins);
184
static int  get_result_relid(PlannerInfo *root, Node *jtnode);
185
static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc);
186
static bool find_dependent_phvs(PlannerInfo *root, int varno, Relids baserels);
187
static bool find_dependent_phvs_in_jointree(PlannerInfo *root,
188
                      Node *node, int varno,
189
                      Relids baserels);
190
static void substitute_phv_relids(Node *node,
191
                  int varno, Relids subrelids);
192
static void fix_append_rel_relids(PlannerInfo *root, int varno,
193
                  Relids subrelids);
194
static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
195
static nullingrel_info *get_nullingrels(Query *parse);
196
static void get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels,
197
                  nullingrel_info *info);
198
199
200
/*
201
 * transform_MERGE_to_join
202
 *    Replace a MERGE's jointree to also include the target relation.
203
 */
204
void
205
transform_MERGE_to_join(Query *parse)
206
0
{
207
0
  RangeTblEntry *joinrte;
208
0
  JoinExpr   *joinexpr;
209
0
  bool    have_action[NUM_MERGE_MATCH_KINDS];
210
0
  JoinType  jointype;
211
0
  int     joinrti;
212
0
  List     *vars;
213
0
  RangeTblRef *rtr;
214
0
  FromExpr   *target;
215
0
  Node     *source;
216
0
  int     sourcerti;
217
218
0
  if (parse->commandType != CMD_MERGE)
219
0
    return;
220
221
  /* XXX probably bogus */
222
0
  vars = NIL;
223
224
  /*
225
   * Work out what kind of join is required.  If there any WHEN NOT MATCHED
226
   * BY SOURCE/TARGET actions, an outer join is required so that we process
227
   * all unmatched tuples from the source and/or target relations.
228
   * Otherwise, we can use an inner join.
229
   */
230
0
  have_action[MERGE_WHEN_MATCHED] = false;
231
0
  have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] = false;
232
0
  have_action[MERGE_WHEN_NOT_MATCHED_BY_TARGET] = false;
233
234
0
  foreach_node(MergeAction, action, parse->mergeActionList)
235
0
  {
236
0
    if (action->commandType != CMD_NOTHING)
237
0
      have_action[action->matchKind] = true;
238
0
  }
239
240
0
  if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] &&
241
0
    have_action[MERGE_WHEN_NOT_MATCHED_BY_TARGET])
242
0
    jointype = JOIN_FULL;
243
0
  else if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE])
244
0
    jointype = JOIN_LEFT;
245
0
  else if (have_action[MERGE_WHEN_NOT_MATCHED_BY_TARGET])
246
0
    jointype = JOIN_RIGHT;
247
0
  else
248
0
    jointype = JOIN_INNER;
249
250
  /* Manufacture a join RTE to use. */
251
0
  joinrte = makeNode(RangeTblEntry);
252
0
  joinrte->rtekind = RTE_JOIN;
253
0
  joinrte->jointype = jointype;
254
0
  joinrte->joinmergedcols = 0;
255
0
  joinrte->joinaliasvars = vars;
256
0
  joinrte->joinleftcols = NIL; /* MERGE does not allow JOIN USING */
257
0
  joinrte->joinrightcols = NIL; /* ditto */
258
0
  joinrte->join_using_alias = NULL;
259
260
0
  joinrte->alias = NULL;
261
0
  joinrte->eref = makeAlias("*MERGE*", NIL);
262
0
  joinrte->lateral = false;
263
0
  joinrte->inh = false;
264
0
  joinrte->inFromCl = true;
265
266
  /*
267
   * Add completed RTE to pstate's range table list, so that we know its
268
   * index.
269
   */
270
0
  parse->rtable = lappend(parse->rtable, joinrte);
271
0
  joinrti = list_length(parse->rtable);
272
273
  /*
274
   * Create a JOIN between the target and the source relation.
275
   *
276
   * Here the target is identified by parse->mergeTargetRelation.  For a
277
   * regular table, this will equal parse->resultRelation, but for a
278
   * trigger-updatable view, it will be the expanded view subquery that we
279
   * need to pull data from.
280
   *
281
   * The source relation is in parse->jointree->fromlist, but any quals in
282
   * parse->jointree->quals are restrictions on the target relation (if the
283
   * target relation is an auto-updatable view).
284
   */
285
  /* target rel, with any quals */
286
0
  rtr = makeNode(RangeTblRef);
287
0
  rtr->rtindex = parse->mergeTargetRelation;
288
0
  target = makeFromExpr(list_make1(rtr), parse->jointree->quals);
289
290
  /* source rel (expect exactly one -- see transformMergeStmt()) */
291
0
  Assert(list_length(parse->jointree->fromlist) == 1);
292
0
  source = linitial(parse->jointree->fromlist);
293
294
  /*
295
   * index of source rel (expect either a RangeTblRef or a JoinExpr -- see
296
   * transformFromClauseItem()).
297
   */
298
0
  if (IsA(source, RangeTblRef))
299
0
    sourcerti = ((RangeTblRef *) source)->rtindex;
300
0
  else if (IsA(source, JoinExpr))
301
0
    sourcerti = ((JoinExpr *) source)->rtindex;
302
0
  else
303
0
  {
304
0
    elog(ERROR, "unrecognized source node type: %d",
305
0
       (int) nodeTag(source));
306
0
    sourcerti = 0;      /* keep compiler quiet */
307
0
  }
308
309
  /* Join the source and target */
310
0
  joinexpr = makeNode(JoinExpr);
311
0
  joinexpr->jointype = jointype;
312
0
  joinexpr->isNatural = false;
313
0
  joinexpr->larg = (Node *) target;
314
0
  joinexpr->rarg = source;
315
0
  joinexpr->usingClause = NIL;
316
0
  joinexpr->join_using_alias = NULL;
317
0
  joinexpr->quals = parse->mergeJoinCondition;
318
0
  joinexpr->alias = NULL;
319
0
  joinexpr->rtindex = joinrti;
320
321
  /* Make the new join be the sole entry in the query's jointree */
322
0
  parse->jointree->fromlist = list_make1(joinexpr);
323
0
  parse->jointree->quals = NULL;
324
325
  /*
326
   * If necessary, mark parse->targetlist entries that refer to the target
327
   * as nullable by the join.  Normally the targetlist will be empty for a
328
   * MERGE, but if the target is a trigger-updatable view, it will contain a
329
   * whole-row Var referring to the expanded view query.
330
   */
331
0
  if (parse->targetList != NIL &&
332
0
    (jointype == JOIN_RIGHT || jointype == JOIN_FULL))
333
0
    parse->targetList = (List *)
334
0
      add_nulling_relids((Node *) parse->targetList,
335
0
                 bms_make_singleton(parse->mergeTargetRelation),
336
0
                 bms_make_singleton(joinrti));
337
338
  /*
339
   * If the source relation is on the outer side of the join, mark any
340
   * source relation Vars in the join condition, actions, and RETURNING list
341
   * as nullable by the join.  These Vars will be added to the targetlist by
342
   * preprocess_targetlist(), so it's important to mark them correctly here.
343
   *
344
   * It might seem that this is not necessary for Vars in the join
345
   * condition, since it is inside the join, but it is also needed above the
346
   * join (in the ModifyTable node) to distinguish between the MATCHED and
347
   * NOT MATCHED BY SOURCE cases -- see ExecMergeMatched().  Note that this
348
   * creates a modified copy of the join condition, for use above the join,
349
   * without modifying the original join condition, inside the join.
350
   */
351
0
  if (jointype == JOIN_LEFT || jointype == JOIN_FULL)
352
0
  {
353
0
    parse->mergeJoinCondition =
354
0
      add_nulling_relids(parse->mergeJoinCondition,
355
0
                 bms_make_singleton(sourcerti),
356
0
                 bms_make_singleton(joinrti));
357
358
0
    foreach_node(MergeAction, action, parse->mergeActionList)
359
0
    {
360
0
      action->qual =
361
0
        add_nulling_relids(action->qual,
362
0
                   bms_make_singleton(sourcerti),
363
0
                   bms_make_singleton(joinrti));
364
365
0
      action->targetList = (List *)
366
0
        add_nulling_relids((Node *) action->targetList,
367
0
                   bms_make_singleton(sourcerti),
368
0
                   bms_make_singleton(joinrti));
369
0
    }
370
371
0
    parse->returningList = (List *)
372
0
      add_nulling_relids((Node *) parse->returningList,
373
0
                 bms_make_singleton(sourcerti),
374
0
                 bms_make_singleton(joinrti));
375
0
  }
376
377
  /*
378
   * If there are any WHEN NOT MATCHED BY SOURCE actions, the executor will
379
   * use the join condition to distinguish between MATCHED and NOT MATCHED
380
   * BY SOURCE cases.  Otherwise, it's no longer needed, and we set it to
381
   * NULL, saving cycles during planning and execution.
382
   *
383
   * We need to be careful though: the executor evaluates this condition
384
   * using the output of the join subplan node, which nulls the output from
385
   * the source relation when the join condition doesn't match.  That risks
386
   * producing incorrect results when rechecking using a "non-strict" join
387
   * condition, such as "src.col IS NOT DISTINCT FROM tgt.col".  To guard
388
   * against that, we add an additional "src IS NOT NULL" check to the join
389
   * condition, so that it does the right thing when performing a recheck
390
   * based on the output of the join subplan.
391
   */
392
0
  if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE])
393
0
  {
394
0
    Var      *var;
395
0
    NullTest   *ntest;
396
397
    /* source wholerow Var (nullable by the new join) */
398
0
    var = makeWholeRowVar(rt_fetch(sourcerti, parse->rtable),
399
0
                sourcerti, 0, false);
400
0
    var->varnullingrels = bms_make_singleton(joinrti);
401
402
    /* "src IS NOT NULL" check */
403
0
    ntest = makeNode(NullTest);
404
0
    ntest->arg = (Expr *) var;
405
0
    ntest->nulltesttype = IS_NOT_NULL;
406
0
    ntest->argisrow = false;
407
0
    ntest->location = -1;
408
409
    /* combine it with the original join condition */
410
0
    parse->mergeJoinCondition =
411
0
      (Node *) make_and_qual((Node *) ntest, parse->mergeJoinCondition);
412
0
  }
413
0
  else
414
0
    parse->mergeJoinCondition = NULL; /* join condition not needed */
415
0
}
416
417
/*
418
 * preprocess_relation_rtes
419
 *    Do the preprocessing work for any relation RTEs in the FROM clause.
420
 *
421
 * This scans the rangetable for relation RTEs and retrieves the necessary
422
 * catalog information for each relation.  Using this information, it clears
423
 * the inh flag for any relation that has no children, collects not-null
424
 * attribute numbers for any relation that has column not-null constraints, and
425
 * expands virtual generated columns for any relation that contains them.
426
 *
427
 * Note that expanding virtual generated columns may cause the query tree to
428
 * have new copies of rangetable entries.  Therefore, we have to use list_nth
429
 * instead of foreach when iterating over the query's rangetable.
430
 *
431
 * Returns a modified copy of the query tree, if any relations with virtual
432
 * generated columns are present.
433
 */
434
Query *
435
preprocess_relation_rtes(PlannerInfo *root)
436
0
{
437
0
  Query    *parse = root->parse;
438
0
  int     rtable_size;
439
0
  int     rt_index;
440
441
0
  rtable_size = list_length(parse->rtable);
442
443
0
  for (rt_index = 0; rt_index < rtable_size; rt_index++)
444
0
  {
445
0
    RangeTblEntry *rte = rt_fetch(rt_index + 1, parse->rtable);
446
0
    Relation  relation;
447
448
    /* We only care about relation RTEs. */
449
0
    if (rte->rtekind != RTE_RELATION)
450
0
      continue;
451
452
    /*
453
     * We need not lock the relation since it was already locked by the
454
     * rewriter.
455
     */
456
0
    relation = table_open(rte->relid, NoLock);
457
458
    /*
459
     * Check to see if the relation actually has any children; if not,
460
     * clear the inh flag so we can treat it as a plain base relation.
461
     *
462
     * Note: this could give a false-positive result, if the rel once had
463
     * children but no longer does.  We used to be able to clear rte->inh
464
     * later on when we discovered that, but no more; we have to handle
465
     * such cases as full-fledged inheritance.
466
     */
467
0
    if (rte->inh)
468
0
      rte->inh = relation->rd_rel->relhassubclass;
469
470
    /*
471
     * Check to see if the relation has any column not-null constraints;
472
     * if so, retrieve the constraint information and store it in a
473
     * relation OID based hash table.
474
     */
475
0
    get_relation_notnullatts(root, relation);
476
477
    /*
478
     * Check to see if the relation has any virtual generated columns; if
479
     * so, replace all Var nodes in the query that reference these columns
480
     * with the generation expressions.
481
     */
482
0
    parse = expand_virtual_generated_columns(root, parse,
483
0
                         rte, rt_index + 1,
484
0
                         relation);
485
486
0
    table_close(relation, NoLock);
487
0
  }
488
489
0
  return parse;
490
0
}
491
492
/*
493
 * expand_virtual_generated_columns
494
 *    Expand virtual generated columns for the given relation.
495
 *
496
 * This checks whether the given relation has any virtual generated columns,
497
 * and if so, replaces all Var nodes in the query that reference those columns
498
 * with their generation expressions.
499
 *
500
 * Returns a modified copy of the query tree if the relation contains virtual
501
 * generated columns.
502
 */
503
static Query *
504
expand_virtual_generated_columns(PlannerInfo *root, Query *parse,
505
                 RangeTblEntry *rte, int rt_index,
506
                 Relation relation)
507
0
{
508
0
  TupleDesc tupdesc;
509
510
  /* Only normal relations can have virtual generated columns */
511
0
  Assert(rte->rtekind == RTE_RELATION);
512
513
0
  tupdesc = RelationGetDescr(relation);
514
0
  if (tupdesc->constr && tupdesc->constr->has_generated_virtual)
515
0
  {
516
0
    List     *tlist = NIL;
517
0
    pullup_replace_vars_context rvcontext;
518
0
    List     *save_exclRelTlist = NIL;
519
520
0
    for (int i = 0; i < tupdesc->natts; i++)
521
0
    {
522
0
      Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
523
0
      TargetEntry *tle;
524
525
0
      if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
526
0
      {
527
0
        Node     *defexpr;
528
529
0
        defexpr = build_generation_expression(relation, i + 1);
530
0
        ChangeVarNodes(defexpr, 1, rt_index, 0);
531
532
0
        tle = makeTargetEntry((Expr *) defexpr, i + 1, 0, false);
533
0
        tlist = lappend(tlist, tle);
534
0
      }
535
0
      else
536
0
      {
537
0
        Var      *var;
538
539
0
        var = makeVar(rt_index,
540
0
                i + 1,
541
0
                attr->atttypid,
542
0
                attr->atttypmod,
543
0
                attr->attcollation,
544
0
                0);
545
546
0
        tle = makeTargetEntry((Expr *) var, i + 1, 0, false);
547
0
        tlist = lappend(tlist, tle);
548
0
      }
549
0
    }
550
551
0
    Assert(list_length(tlist) > 0);
552
0
    Assert(!rte->lateral);
553
554
    /*
555
     * The relation's targetlist items are now in the appropriate form to
556
     * insert into the query, except that we may need to wrap them in
557
     * PlaceHolderVars.  Set up required context data for
558
     * pullup_replace_vars.
559
     */
560
0
    rvcontext.root = root;
561
0
    rvcontext.targetlist = tlist;
562
0
    rvcontext.target_rte = rte;
563
0
    rvcontext.result_relation = parse->resultRelation;
564
    /* won't need these values */
565
0
    rvcontext.relids = NULL;
566
0
    rvcontext.nullinfo = NULL;
567
    /* pass NULL for outer_hasSubLinks */
568
0
    rvcontext.outer_hasSubLinks = NULL;
569
0
    rvcontext.varno = rt_index;
570
    /* this flag will be set below, if needed */
571
0
    rvcontext.wrap_option = REPLACE_WRAP_NONE;
572
    /* initialize cache array with indexes 0 .. length(tlist) */
573
0
    rvcontext.rv_cache = palloc0_array(Node *, list_length(tlist) + 1);
574
575
    /*
576
     * If the query uses grouping sets, we need a PlaceHolderVar for each
577
     * expression of the relation's targetlist items.  (See comments in
578
     * pull_up_simple_subquery().)
579
     */
580
0
    if (parse->groupingSets)
581
0
      rvcontext.wrap_option = REPLACE_WRAP_ALL;
582
583
    /*
584
     * Apply pullup variable replacement throughout the query tree.
585
     *
586
     * We intentionally do not touch the EXCLUDED pseudo-relation's
587
     * targetlist here.  Various places in the planner assume that it
588
     * contains only Vars, and we want that to remain the case.  More
589
     * importantly, we don't want setrefs.c to turn any expanded
590
     * EXCLUDED.virtual_column expressions in other parts of the query
591
     * back into Vars referencing the original virtual column, which
592
     * set_plan_refs() would do if exclRelTlist contained matching
593
     * expressions.
594
     */
595
0
    if (parse->onConflict)
596
0
    {
597
0
      save_exclRelTlist = parse->onConflict->exclRelTlist;
598
0
      parse->onConflict->exclRelTlist = NIL;
599
0
    }
600
601
0
    parse = (Query *) pullup_replace_vars((Node *) parse, &rvcontext);
602
603
0
    if (parse->onConflict)
604
0
      parse->onConflict->exclRelTlist = save_exclRelTlist;
605
0
  }
606
607
0
  return parse;
608
0
}
609
610
/*
611
 * replace_empty_jointree
612
 *    If the Query's jointree is empty, replace it with a dummy RTE_RESULT
613
 *    relation.
614
 *
615
 * By doing this, we can avoid a bunch of corner cases that formerly existed
616
 * for SELECTs with omitted FROM clauses.  An example is that a subquery
617
 * with empty jointree previously could not be pulled up, because that would
618
 * have resulted in an empty relid set, making the subquery not uniquely
619
 * identifiable for join or PlaceHolderVar processing.
620
 *
621
 * Unlike most other functions in this file, this function doesn't recurse;
622
 * we rely on other processing to invoke it on sub-queries at suitable times.
623
 */
624
void
625
replace_empty_jointree(Query *parse)
626
0
{
627
0
  RangeTblEntry *rte;
628
0
  Index   rti;
629
0
  RangeTblRef *rtr;
630
631
  /* Nothing to do if jointree is already nonempty */
632
0
  if (parse->jointree->fromlist != NIL)
633
0
    return;
634
635
  /* We mustn't change it in the top level of a setop tree, either */
636
0
  if (parse->setOperations)
637
0
    return;
638
639
  /* Create suitable RTE */
640
0
  rte = makeNode(RangeTblEntry);
641
0
  rte->rtekind = RTE_RESULT;
642
0
  rte->eref = makeAlias("*RESULT*", NIL);
643
644
  /* Add it to rangetable */
645
0
  parse->rtable = lappend(parse->rtable, rte);
646
0
  rti = list_length(parse->rtable);
647
648
  /* And jam a reference into the jointree */
649
0
  rtr = makeNode(RangeTblRef);
650
0
  rtr->rtindex = rti;
651
0
  parse->jointree->fromlist = list_make1(rtr);
652
0
}
653
654
/*
655
 * pull_up_sublinks
656
 *    Attempt to pull up ANY and EXISTS SubLinks to be treated as
657
 *    semijoins or anti-semijoins.
658
 *
659
 * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
660
 * sub-SELECT up to become a rangetable entry and treating the implied
661
 * comparisons as quals of a semijoin.  However, this optimization *only*
662
 * works at the top level of WHERE or a JOIN/ON clause, because we cannot
663
 * distinguish whether the ANY ought to return FALSE or NULL in cases
664
 * involving NULL inputs.  Also, in an outer join's ON clause we can only
665
 * do this if the sublink is degenerate (ie, references only the nullable
666
 * side of the join).  In that case it is legal to push the semijoin
667
 * down into the nullable side of the join.  If the sublink references any
668
 * nonnullable-side variables then it would have to be evaluated as part
669
 * of the outer join, which makes things way too complicated.
670
 *
671
 * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
672
 * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
673
 *
674
 * This routine searches for such clauses and does the necessary parsetree
675
 * transformations if any are found.
676
 *
677
 * This routine has to run before preprocess_expression(), so the quals
678
 * clauses are not yet reduced to implicit-AND format, and are not guaranteed
679
 * to be AND/OR-flat either.  That means we need to recursively search through
680
 * explicit AND clauses.  We stop as soon as we hit a non-AND item.
681
 */
682
void
683
pull_up_sublinks(PlannerInfo *root)
684
0
{
685
0
  Node     *jtnode;
686
0
  Relids    relids;
687
688
  /* Begin recursion through the jointree */
689
0
  jtnode = pull_up_sublinks_jointree_recurse(root,
690
0
                         (Node *) root->parse->jointree,
691
0
                         &relids);
692
693
  /*
694
   * root->parse->jointree must always be a FromExpr, so insert a dummy one
695
   * if we got a bare RangeTblRef or JoinExpr out of the recursion.
696
   */
697
0
  if (IsA(jtnode, FromExpr))
698
0
    root->parse->jointree = (FromExpr *) jtnode;
699
0
  else
700
0
    root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
701
0
}
702
703
/*
704
 * Recurse through jointree nodes for pull_up_sublinks()
705
 *
706
 * In addition to returning the possibly-modified jointree node, we return
707
 * a relids set of the contained rels into *relids.
708
 */
709
static Node *
710
pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
711
                  Relids *relids)
712
0
{
713
  /* Since this function recurses, it could be driven to stack overflow. */
714
0
  check_stack_depth();
715
716
0
  if (jtnode == NULL)
717
0
  {
718
0
    *relids = NULL;
719
0
  }
720
0
  else if (IsA(jtnode, RangeTblRef))
721
0
  {
722
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
723
724
0
    *relids = bms_make_singleton(varno);
725
    /* jtnode is returned unmodified */
726
0
  }
727
0
  else if (IsA(jtnode, FromExpr))
728
0
  {
729
0
    FromExpr   *f = (FromExpr *) jtnode;
730
0
    List     *newfromlist = NIL;
731
0
    Relids    frelids = NULL;
732
0
    FromExpr   *newf;
733
0
    Node     *jtlink;
734
0
    ListCell   *l;
735
736
    /* First, recurse to process children and collect their relids */
737
0
    foreach(l, f->fromlist)
738
0
    {
739
0
      Node     *newchild;
740
0
      Relids    childrelids;
741
742
0
      newchild = pull_up_sublinks_jointree_recurse(root,
743
0
                             lfirst(l),
744
0
                             &childrelids);
745
0
      newfromlist = lappend(newfromlist, newchild);
746
0
      frelids = bms_join(frelids, childrelids);
747
0
    }
748
    /* Build the replacement FromExpr; no quals yet */
749
0
    newf = makeFromExpr(newfromlist, NULL);
750
    /* Set up a link representing the rebuilt jointree */
751
0
    jtlink = (Node *) newf;
752
    /* Now process qual --- all children are available for use */
753
0
    newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,
754
0
                          &jtlink, frelids,
755
0
                          NULL, NULL);
756
757
    /*
758
     * Note that the result will be either newf, or a stack of JoinExprs
759
     * with newf at the base.  We rely on subsequent optimization steps to
760
     * flatten this and rearrange the joins as needed.
761
     *
762
     * Although we could include the pulled-up subqueries in the returned
763
     * relids, there's no need since upper quals couldn't refer to their
764
     * outputs anyway.
765
     */
766
0
    *relids = frelids;
767
0
    jtnode = jtlink;
768
0
  }
769
0
  else if (IsA(jtnode, JoinExpr))
770
0
  {
771
0
    JoinExpr   *j;
772
0
    Relids    leftrelids;
773
0
    Relids    rightrelids;
774
0
    Node     *jtlink;
775
776
    /*
777
     * Make a modifiable copy of join node, but don't bother copying its
778
     * subnodes (yet).
779
     */
780
0
    j = palloc_object(JoinExpr);
781
0
    memcpy(j, jtnode, sizeof(JoinExpr));
782
0
    jtlink = (Node *) j;
783
784
    /* Recurse to process children and collect their relids */
785
0
    j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,
786
0
                          &leftrelids);
787
0
    j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,
788
0
                          &rightrelids);
789
790
    /*
791
     * Now process qual, showing appropriate child relids as available,
792
     * and attach any pulled-up jointree items at the right place. In the
793
     * inner-join case we put new JoinExprs above the existing one (much
794
     * as for a FromExpr-style join).  In outer-join cases the new
795
     * JoinExprs must go into the nullable side of the outer join. The
796
     * point of the available_rels machinations is to ensure that we only
797
     * pull up quals for which that's okay.
798
     *
799
     * We don't expect to see any pre-existing JOIN_SEMI, JOIN_ANTI,
800
     * JOIN_RIGHT_SEMI, or JOIN_RIGHT_ANTI jointypes here.
801
     */
802
0
    switch (j->jointype)
803
0
    {
804
0
      case JOIN_INNER:
805
0
        j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
806
0
                             &jtlink,
807
0
                             bms_union(leftrelids,
808
0
                                   rightrelids),
809
0
                             NULL, NULL);
810
0
        break;
811
0
      case JOIN_LEFT:
812
0
        j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
813
0
                             &j->rarg,
814
0
                             rightrelids,
815
0
                             NULL, NULL);
816
0
        break;
817
0
      case JOIN_FULL:
818
        /* can't do anything with full-join quals */
819
0
        break;
820
0
      case JOIN_RIGHT:
821
0
        j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
822
0
                             &j->larg,
823
0
                             leftrelids,
824
0
                             NULL, NULL);
825
0
        break;
826
0
      default:
827
0
        elog(ERROR, "unrecognized join type: %d",
828
0
           (int) j->jointype);
829
0
        break;
830
0
    }
831
832
    /*
833
     * Although we could include the pulled-up subqueries in the returned
834
     * relids, there's no need since upper quals couldn't refer to their
835
     * outputs anyway.  But we *do* need to include the join's own rtindex
836
     * because we haven't yet collapsed join alias variables, so upper
837
     * levels would mistakenly think they couldn't use references to this
838
     * join.
839
     */
840
0
    *relids = bms_join(leftrelids, rightrelids);
841
0
    if (j->rtindex)
842
0
      *relids = bms_add_member(*relids, j->rtindex);
843
0
    jtnode = jtlink;
844
0
  }
845
0
  else
846
0
    elog(ERROR, "unrecognized node type: %d",
847
0
       (int) nodeTag(jtnode));
848
0
  return jtnode;
849
0
}
850
851
/*
852
 * Recurse through top-level qual nodes for pull_up_sublinks()
853
 *
854
 * jtlink1 points to the link in the jointree where any new JoinExprs should
855
 * be inserted if they reference available_rels1 (i.e., available_rels1
856
 * denotes the relations present underneath jtlink1).  Optionally, jtlink2 can
857
 * point to a second link where new JoinExprs should be inserted if they
858
 * reference available_rels2 (pass NULL for both those arguments if not used).
859
 * Note that SubLinks referencing both sets of variables cannot be optimized.
860
 * If we find multiple pull-up-able SubLinks, they'll get stacked onto jtlink1
861
 * and/or jtlink2 in the order we encounter them.  We rely on subsequent
862
 * optimization to rearrange the stack if appropriate.
863
 *
864
 * Returns the replacement qual node, or NULL if the qual should be removed.
865
 */
866
static Node *
867
pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
868
                Node **jtlink1, Relids available_rels1,
869
                Node **jtlink2, Relids available_rels2)
870
0
{
871
0
  if (node == NULL)
872
0
    return NULL;
873
0
  if (IsA(node, SubLink))
874
0
  {
875
0
    SubLink    *sublink = (SubLink *) node;
876
0
    JoinExpr   *j;
877
0
    Relids    child_rels;
878
879
    /* Is it a convertible ANY or EXISTS clause? */
880
0
    if (sublink->subLinkType == ANY_SUBLINK)
881
0
    {
882
0
      ScalarArrayOpExpr *saop;
883
884
0
      if ((saop = convert_VALUES_to_ANY(root,
885
0
                        sublink->testexpr,
886
0
                        (Query *) sublink->subselect)) != NULL)
887
0
      {
888
        /*
889
         * The VALUES sequence was simplified.  Nothing more to do
890
         * here.
891
         */
892
0
        return (Node *) saop;
893
0
      }
894
895
0
      if ((j = convert_ANY_sublink_to_join(root, sublink, false,
896
0
                         available_rels1)) != NULL)
897
0
      {
898
        /* Yes; insert the new join node into the join tree */
899
0
        j->larg = *jtlink1;
900
0
        *jtlink1 = (Node *) j;
901
        /* Recursively process pulled-up jointree nodes */
902
0
        j->rarg = pull_up_sublinks_jointree_recurse(root,
903
0
                              j->rarg,
904
0
                              &child_rels);
905
906
        /*
907
         * Now recursively process the pulled-up quals.  Any inserted
908
         * joins can get stacked onto either j->larg or j->rarg,
909
         * depending on which rels they reference.
910
         */
911
0
        j->quals = pull_up_sublinks_qual_recurse(root,
912
0
                             j->quals,
913
0
                             &j->larg,
914
0
                             available_rels1,
915
0
                             &j->rarg,
916
0
                             child_rels);
917
        /* Return NULL representing constant TRUE */
918
0
        return NULL;
919
0
      }
920
0
      if (available_rels2 != NULL &&
921
0
        (j = convert_ANY_sublink_to_join(root, sublink, false,
922
0
                         available_rels2)) != NULL)
923
0
      {
924
        /* Yes; insert the new join node into the join tree */
925
0
        j->larg = *jtlink2;
926
0
        *jtlink2 = (Node *) j;
927
        /* Recursively process pulled-up jointree nodes */
928
0
        j->rarg = pull_up_sublinks_jointree_recurse(root,
929
0
                              j->rarg,
930
0
                              &child_rels);
931
932
        /*
933
         * Now recursively process the pulled-up quals.  Any inserted
934
         * joins can get stacked onto either j->larg or j->rarg,
935
         * depending on which rels they reference.
936
         */
937
0
        j->quals = pull_up_sublinks_qual_recurse(root,
938
0
                             j->quals,
939
0
                             &j->larg,
940
0
                             available_rels2,
941
0
                             &j->rarg,
942
0
                             child_rels);
943
        /* Return NULL representing constant TRUE */
944
0
        return NULL;
945
0
      }
946
0
    }
947
0
    else if (sublink->subLinkType == EXISTS_SUBLINK)
948
0
    {
949
0
      if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
950
0
                          available_rels1)) != NULL)
951
0
      {
952
        /* Yes; insert the new join node into the join tree */
953
0
        j->larg = *jtlink1;
954
0
        *jtlink1 = (Node *) j;
955
        /* Recursively process pulled-up jointree nodes */
956
0
        j->rarg = pull_up_sublinks_jointree_recurse(root,
957
0
                              j->rarg,
958
0
                              &child_rels);
959
960
        /*
961
         * Now recursively process the pulled-up quals.  Any inserted
962
         * joins can get stacked onto either j->larg or j->rarg,
963
         * depending on which rels they reference.
964
         */
965
0
        j->quals = pull_up_sublinks_qual_recurse(root,
966
0
                             j->quals,
967
0
                             &j->larg,
968
0
                             available_rels1,
969
0
                             &j->rarg,
970
0
                             child_rels);
971
        /* Return NULL representing constant TRUE */
972
0
        return NULL;
973
0
      }
974
0
      if (available_rels2 != NULL &&
975
0
        (j = convert_EXISTS_sublink_to_join(root, sublink, false,
976
0
                          available_rels2)) != NULL)
977
0
      {
978
        /* Yes; insert the new join node into the join tree */
979
0
        j->larg = *jtlink2;
980
0
        *jtlink2 = (Node *) j;
981
        /* Recursively process pulled-up jointree nodes */
982
0
        j->rarg = pull_up_sublinks_jointree_recurse(root,
983
0
                              j->rarg,
984
0
                              &child_rels);
985
986
        /*
987
         * Now recursively process the pulled-up quals.  Any inserted
988
         * joins can get stacked onto either j->larg or j->rarg,
989
         * depending on which rels they reference.
990
         */
991
0
        j->quals = pull_up_sublinks_qual_recurse(root,
992
0
                             j->quals,
993
0
                             &j->larg,
994
0
                             available_rels2,
995
0
                             &j->rarg,
996
0
                             child_rels);
997
        /* Return NULL representing constant TRUE */
998
0
        return NULL;
999
0
      }
1000
0
    }
1001
    /* Else return it unmodified */
1002
0
    return node;
1003
0
  }
1004
0
  if (is_notclause(node))
1005
0
  {
1006
    /* If the immediate argument of NOT is ANY or EXISTS, try to convert */
1007
0
    SubLink    *sublink = (SubLink *) get_notclausearg((Expr *) node);
1008
0
    JoinExpr   *j;
1009
0
    Relids    child_rels;
1010
1011
0
    if (sublink && IsA(sublink, SubLink))
1012
0
    {
1013
0
      if (sublink->subLinkType == ANY_SUBLINK)
1014
0
      {
1015
0
        if ((j = convert_ANY_sublink_to_join(root, sublink, true,
1016
0
                           available_rels1)) != NULL)
1017
0
        {
1018
          /* Yes; insert the new join node into the join tree */
1019
0
          j->larg = *jtlink1;
1020
0
          *jtlink1 = (Node *) j;
1021
          /* Recursively process pulled-up jointree nodes */
1022
0
          j->rarg = pull_up_sublinks_jointree_recurse(root,
1023
0
                                j->rarg,
1024
0
                                &child_rels);
1025
1026
          /*
1027
           * Now recursively process the pulled-up quals.  Because
1028
           * we are underneath a NOT, we can't pull up sublinks that
1029
           * reference the left-hand stuff, but it's still okay to
1030
           * pull up sublinks referencing j->rarg.
1031
           */
1032
0
          j->quals = pull_up_sublinks_qual_recurse(root,
1033
0
                               j->quals,
1034
0
                               &j->rarg,
1035
0
                               child_rels,
1036
0
                               NULL, NULL);
1037
          /* Return NULL representing constant TRUE */
1038
0
          return NULL;
1039
0
        }
1040
0
        if (available_rels2 != NULL &&
1041
0
          (j = convert_ANY_sublink_to_join(root, sublink, true,
1042
0
                           available_rels2)) != NULL)
1043
0
        {
1044
          /* Yes; insert the new join node into the join tree */
1045
0
          j->larg = *jtlink2;
1046
0
          *jtlink2 = (Node *) j;
1047
          /* Recursively process pulled-up jointree nodes */
1048
0
          j->rarg = pull_up_sublinks_jointree_recurse(root,
1049
0
                                j->rarg,
1050
0
                                &child_rels);
1051
1052
          /*
1053
           * Now recursively process the pulled-up quals.  Because
1054
           * we are underneath a NOT, we can't pull up sublinks that
1055
           * reference the left-hand stuff, but it's still okay to
1056
           * pull up sublinks referencing j->rarg.
1057
           */
1058
0
          j->quals = pull_up_sublinks_qual_recurse(root,
1059
0
                               j->quals,
1060
0
                               &j->rarg,
1061
0
                               child_rels,
1062
0
                               NULL, NULL);
1063
          /* Return NULL representing constant TRUE */
1064
0
          return NULL;
1065
0
        }
1066
0
      }
1067
0
      else if (sublink->subLinkType == EXISTS_SUBLINK)
1068
0
      {
1069
0
        if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
1070
0
                            available_rels1)) != NULL)
1071
0
        {
1072
          /* Yes; insert the new join node into the join tree */
1073
0
          j->larg = *jtlink1;
1074
0
          *jtlink1 = (Node *) j;
1075
          /* Recursively process pulled-up jointree nodes */
1076
0
          j->rarg = pull_up_sublinks_jointree_recurse(root,
1077
0
                                j->rarg,
1078
0
                                &child_rels);
1079
1080
          /*
1081
           * Now recursively process the pulled-up quals.  Because
1082
           * we are underneath a NOT, we can't pull up sublinks that
1083
           * reference the left-hand stuff, but it's still okay to
1084
           * pull up sublinks referencing j->rarg.
1085
           */
1086
0
          j->quals = pull_up_sublinks_qual_recurse(root,
1087
0
                               j->quals,
1088
0
                               &j->rarg,
1089
0
                               child_rels,
1090
0
                               NULL, NULL);
1091
          /* Return NULL representing constant TRUE */
1092
0
          return NULL;
1093
0
        }
1094
0
        if (available_rels2 != NULL &&
1095
0
          (j = convert_EXISTS_sublink_to_join(root, sublink, true,
1096
0
                            available_rels2)) != NULL)
1097
0
        {
1098
          /* Yes; insert the new join node into the join tree */
1099
0
          j->larg = *jtlink2;
1100
0
          *jtlink2 = (Node *) j;
1101
          /* Recursively process pulled-up jointree nodes */
1102
0
          j->rarg = pull_up_sublinks_jointree_recurse(root,
1103
0
                                j->rarg,
1104
0
                                &child_rels);
1105
1106
          /*
1107
           * Now recursively process the pulled-up quals.  Because
1108
           * we are underneath a NOT, we can't pull up sublinks that
1109
           * reference the left-hand stuff, but it's still okay to
1110
           * pull up sublinks referencing j->rarg.
1111
           */
1112
0
          j->quals = pull_up_sublinks_qual_recurse(root,
1113
0
                               j->quals,
1114
0
                               &j->rarg,
1115
0
                               child_rels,
1116
0
                               NULL, NULL);
1117
          /* Return NULL representing constant TRUE */
1118
0
          return NULL;
1119
0
        }
1120
0
      }
1121
0
    }
1122
    /* Else return it unmodified */
1123
0
    return node;
1124
0
  }
1125
0
  if (is_andclause(node))
1126
0
  {
1127
    /* Recurse into AND clause */
1128
0
    List     *newclauses = NIL;
1129
0
    ListCell   *l;
1130
1131
0
    foreach(l, ((BoolExpr *) node)->args)
1132
0
    {
1133
0
      Node     *oldclause = (Node *) lfirst(l);
1134
0
      Node     *newclause;
1135
1136
0
      newclause = pull_up_sublinks_qual_recurse(root,
1137
0
                            oldclause,
1138
0
                            jtlink1,
1139
0
                            available_rels1,
1140
0
                            jtlink2,
1141
0
                            available_rels2);
1142
0
      if (newclause)
1143
0
        newclauses = lappend(newclauses, newclause);
1144
0
    }
1145
    /* We might have got back fewer clauses than we started with */
1146
0
    if (newclauses == NIL)
1147
0
      return NULL;
1148
0
    else if (list_length(newclauses) == 1)
1149
0
      return (Node *) linitial(newclauses);
1150
0
    else
1151
0
      return (Node *) make_andclause(newclauses);
1152
0
  }
1153
  /* Stop if not an AND */
1154
0
  return node;
1155
0
}
1156
1157
/*
1158
 * preprocess_function_rtes
1159
 *    Constant-simplify any FUNCTION RTEs in the FROM clause, and then
1160
 *    attempt to "inline" any that can be converted to simple subqueries.
1161
 *
1162
 * If an RTE_FUNCTION rtable entry invokes a set-returning SQL function that
1163
 * contains just a simple SELECT, we can convert the rtable entry to an
1164
 * RTE_SUBQUERY entry exposing the SELECT directly.  Other sorts of functions
1165
 * are also inline-able if they have a support function that can generate
1166
 * the replacement sub-Query.  This is especially useful if the subquery can
1167
 * then be "pulled up" for further optimization, but we do it even if not,
1168
 * to reduce executor overhead.
1169
 *
1170
 * This has to be done before we have started to do any optimization of
1171
 * subqueries, else any such steps wouldn't get applied to subqueries
1172
 * obtained via inlining.  However, we do it after pull_up_sublinks
1173
 * so that we can inline any functions used in SubLink subselects.
1174
 *
1175
 * The reason for applying const-simplification at this stage is that
1176
 * (a) we'd need to do it anyway to inline a SRF, and (b) by doing it now,
1177
 * we can be sure that pull_up_constant_function() will see constants
1178
 * if there are constants to be seen.  This approach also guarantees
1179
 * that every FUNCTION RTE has been const-simplified, allowing planner.c's
1180
 * preprocess_expression() to skip doing it again.
1181
 *
1182
 * Like most of the planner, this feels free to scribble on its input data
1183
 * structure.
1184
 */
1185
void
1186
preprocess_function_rtes(PlannerInfo *root)
1187
0
{
1188
0
  ListCell   *rt;
1189
1190
0
  foreach(rt, root->parse->rtable)
1191
0
  {
1192
0
    RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
1193
1194
0
    if (rte->rtekind == RTE_FUNCTION)
1195
0
    {
1196
0
      Query    *funcquery;
1197
1198
      /* Apply const-simplification */
1199
0
      rte->functions = (List *)
1200
0
        eval_const_expressions(root, (Node *) rte->functions);
1201
1202
      /* Check safety of expansion, and expand if possible */
1203
0
      funcquery = inline_function_in_from(root, rte);
1204
0
      if (funcquery)
1205
0
      {
1206
        /* Successful expansion, convert the RTE to a subquery */
1207
0
        rte->rtekind = RTE_SUBQUERY;
1208
0
        rte->subquery = funcquery;
1209
0
        rte->security_barrier = false;
1210
1211
        /*
1212
         * Clear fields that should not be set in a subquery RTE.
1213
         * However, we leave rte->functions filled in for the moment,
1214
         * in case makeWholeRowVar needs to consult it.  We'll clear
1215
         * it in setrefs.c (see add_rte_to_flat_rtable) so that this
1216
         * abuse of the data structure doesn't escape the planner.
1217
         */
1218
0
        rte->funcordinality = false;
1219
0
      }
1220
0
    }
1221
0
  }
1222
0
}
1223
1224
/*
1225
 * pull_up_subqueries
1226
 *    Look for subqueries in the rangetable that can be pulled up into
1227
 *    the parent query.  If the subquery has no special features like
1228
 *    grouping/aggregation then we can merge it into the parent's jointree.
1229
 *    Also, subqueries that are simple UNION ALL structures can be
1230
 *    converted into "append relations".
1231
 */
1232
void
1233
pull_up_subqueries(PlannerInfo *root)
1234
0
{
1235
  /* Top level of jointree must always be a FromExpr */
1236
0
  Assert(IsA(root->parse->jointree, FromExpr));
1237
  /* Recursion starts with no containing join nor appendrel */
1238
0
  root->parse->jointree = (FromExpr *)
1239
0
    pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,
1240
0
                   NULL, NULL);
1241
  /* We should still have a FromExpr */
1242
0
  Assert(IsA(root->parse->jointree, FromExpr));
1243
0
}
1244
1245
/*
1246
 * pull_up_subqueries_recurse
1247
 *    Recursive guts of pull_up_subqueries.
1248
 *
1249
 * This recursively processes the jointree and returns a modified jointree.
1250
 *
1251
 * If this jointree node is within either side of an outer join, then
1252
 * lowest_outer_join references the lowest such JoinExpr node; otherwise
1253
 * it is NULL.  We use this to constrain the effects of LATERAL subqueries.
1254
 *
1255
 * If we are looking at a member subquery of an append relation,
1256
 * containing_appendrel describes that relation; else it is NULL.
1257
 * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
1258
 * items, and puts some additional restrictions on what can be pulled up.
1259
 *
1260
 * A tricky aspect of this code is that if we pull up a subquery we have
1261
 * to replace Vars that reference the subquery's outputs throughout the
1262
 * parent query, including quals attached to jointree nodes above the one
1263
 * we are currently processing!  We handle this by being careful to maintain
1264
 * validity of the jointree structure while recursing, in the following sense:
1265
 * whenever we recurse, all qual expressions in the tree must be reachable
1266
 * from the top level, in case the recursive call needs to modify them.
1267
 *
1268
 * Notice also that we can't turn pullup_replace_vars loose on the whole
1269
 * jointree, because it'd return a mutated copy of the tree; we have to
1270
 * invoke it just on the quals, instead.  This behavior is what makes it
1271
 * reasonable to pass lowest_outer_join as a pointer rather than some
1272
 * more-indirect way of identifying the lowest OJ.  Likewise, we don't
1273
 * replace append_rel_list members but only their substructure, so the
1274
 * containing_appendrel reference is safe to use.
1275
 */
1276
static Node *
1277
pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
1278
               JoinExpr *lowest_outer_join,
1279
               AppendRelInfo *containing_appendrel)
1280
0
{
1281
  /* Since this function recurses, it could be driven to stack overflow. */
1282
0
  check_stack_depth();
1283
  /* Also, since it's a bit expensive, let's check for query cancel. */
1284
0
  CHECK_FOR_INTERRUPTS();
1285
1286
0
  Assert(jtnode != NULL);
1287
0
  if (IsA(jtnode, RangeTblRef))
1288
0
  {
1289
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
1290
0
    RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
1291
1292
    /*
1293
     * Is this a subquery RTE, and if so, is the subquery simple enough to
1294
     * pull up?
1295
     *
1296
     * If we are looking at an append-relation member, we can't pull it up
1297
     * unless is_safe_append_member says so.
1298
     */
1299
0
    if (rte->rtekind == RTE_SUBQUERY &&
1300
0
      is_simple_subquery(root, rte->subquery, rte, lowest_outer_join) &&
1301
0
      (containing_appendrel == NULL ||
1302
0
       is_safe_append_member(rte->subquery)))
1303
0
      return pull_up_simple_subquery(root, jtnode, rte,
1304
0
                       lowest_outer_join,
1305
0
                       containing_appendrel);
1306
1307
    /*
1308
     * Alternatively, is it a simple UNION ALL subquery?  If so, flatten
1309
     * into an "append relation".
1310
     *
1311
     * It's safe to do this regardless of whether this query is itself an
1312
     * appendrel member.  (If you're thinking we should try to flatten the
1313
     * two levels of appendrel together, you're right; but we handle that
1314
     * in set_append_rel_pathlist, not here.)
1315
     */
1316
0
    if (rte->rtekind == RTE_SUBQUERY &&
1317
0
      is_simple_union_all(rte->subquery))
1318
0
      return pull_up_simple_union_all(root, jtnode, rte);
1319
1320
    /*
1321
     * Or perhaps it's a simple VALUES RTE?
1322
     *
1323
     * We don't allow VALUES pullup below an outer join nor into an
1324
     * appendrel (such cases are impossible anyway at the moment).
1325
     */
1326
0
    if (rte->rtekind == RTE_VALUES &&
1327
0
      lowest_outer_join == NULL &&
1328
0
      containing_appendrel == NULL &&
1329
0
      is_simple_values(root, rte))
1330
0
      return pull_up_simple_values(root, jtnode, rte);
1331
1332
    /*
1333
     * Or perhaps it's a FUNCTION RTE that we could inline?
1334
     */
1335
0
    if (rte->rtekind == RTE_FUNCTION)
1336
0
      return pull_up_constant_function(root, jtnode, rte,
1337
0
                       containing_appendrel);
1338
1339
    /* Otherwise, do nothing at this node. */
1340
0
  }
1341
0
  else if (IsA(jtnode, FromExpr))
1342
0
  {
1343
0
    FromExpr   *f = (FromExpr *) jtnode;
1344
0
    ListCell   *l;
1345
1346
0
    Assert(containing_appendrel == NULL);
1347
    /* Recursively transform all the child nodes */
1348
0
    foreach(l, f->fromlist)
1349
0
    {
1350
0
      lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),
1351
0
                           lowest_outer_join,
1352
0
                           NULL);
1353
0
    }
1354
0
  }
1355
0
  else if (IsA(jtnode, JoinExpr))
1356
0
  {
1357
0
    JoinExpr   *j = (JoinExpr *) jtnode;
1358
1359
0
    Assert(containing_appendrel == NULL);
1360
    /* Recurse, being careful to tell myself when inside outer join */
1361
0
    switch (j->jointype)
1362
0
    {
1363
0
      case JOIN_INNER:
1364
0
        j->larg = pull_up_subqueries_recurse(root, j->larg,
1365
0
                           lowest_outer_join,
1366
0
                           NULL);
1367
0
        j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1368
0
                           lowest_outer_join,
1369
0
                           NULL);
1370
0
        break;
1371
0
      case JOIN_LEFT:
1372
0
      case JOIN_SEMI:
1373
0
      case JOIN_ANTI:
1374
0
        j->larg = pull_up_subqueries_recurse(root, j->larg,
1375
0
                           j,
1376
0
                           NULL);
1377
0
        j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1378
0
                           j,
1379
0
                           NULL);
1380
0
        break;
1381
0
      case JOIN_FULL:
1382
0
        j->larg = pull_up_subqueries_recurse(root, j->larg,
1383
0
                           j,
1384
0
                           NULL);
1385
0
        j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1386
0
                           j,
1387
0
                           NULL);
1388
0
        break;
1389
0
      case JOIN_RIGHT:
1390
0
        j->larg = pull_up_subqueries_recurse(root, j->larg,
1391
0
                           j,
1392
0
                           NULL);
1393
0
        j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1394
0
                           j,
1395
0
                           NULL);
1396
0
        break;
1397
0
      default:
1398
0
        elog(ERROR, "unrecognized join type: %d",
1399
0
           (int) j->jointype);
1400
0
        break;
1401
0
    }
1402
0
  }
1403
0
  else
1404
0
    elog(ERROR, "unrecognized node type: %d",
1405
0
       (int) nodeTag(jtnode));
1406
0
  return jtnode;
1407
0
}
1408
1409
/*
1410
 * pull_up_simple_subquery
1411
 *    Attempt to pull up a single simple subquery.
1412
 *
1413
 * jtnode is a RangeTblRef that has been tentatively identified as a simple
1414
 * subquery by pull_up_subqueries.  We return the replacement jointree node,
1415
 * or jtnode itself if we determine that the subquery can't be pulled up
1416
 * after all.
1417
 *
1418
 * rte is the RangeTblEntry referenced by jtnode.  Remaining parameters are
1419
 * as for pull_up_subqueries_recurse.
1420
 */
1421
static Node *
1422
pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
1423
            JoinExpr *lowest_outer_join,
1424
            AppendRelInfo *containing_appendrel)
1425
0
{
1426
0
  Query    *parse = root->parse;
1427
0
  int     varno = ((RangeTblRef *) jtnode)->rtindex;
1428
0
  Query    *subquery;
1429
0
  PlannerInfo *subroot;
1430
0
  int     rtoffset;
1431
0
  pullup_replace_vars_context rvcontext;
1432
0
  ListCell   *lc;
1433
1434
  /*
1435
   * Make a modifiable copy of the subquery to hack on, so that the RTE will
1436
   * be left unchanged in case we decide below that we can't pull it up
1437
   * after all.
1438
   */
1439
0
  subquery = copyObject(rte->subquery);
1440
1441
  /*
1442
   * Create a PlannerInfo data structure for this subquery.
1443
   *
1444
   * NOTE: the next few steps should match the first processing in
1445
   * subquery_planner().  Can we refactor to avoid code duplication, or
1446
   * would that just make things uglier?
1447
   */
1448
0
  subroot = makeNode(PlannerInfo);
1449
0
  subroot->parse = subquery;
1450
0
  subroot->glob = root->glob;
1451
0
  subroot->query_level = root->query_level;
1452
0
  subroot->plan_name = root->plan_name;
1453
0
  subroot->alternative_plan_name = root->alternative_plan_name;
1454
0
  subroot->parent_root = root->parent_root;
1455
0
  subroot->plan_params = NIL;
1456
0
  subroot->outer_params = NULL;
1457
0
  subroot->planner_cxt = CurrentMemoryContext;
1458
0
  subroot->init_plans = NIL;
1459
0
  subroot->cte_plan_ids = NIL;
1460
0
  subroot->multiexpr_params = NIL;
1461
0
  subroot->join_domains = NIL;
1462
0
  subroot->eq_classes = NIL;
1463
0
  subroot->ec_merging_done = false;
1464
0
  subroot->last_rinfo_serial = 0;
1465
0
  subroot->all_result_relids = NULL;
1466
0
  subroot->leaf_result_relids = NULL;
1467
0
  subroot->append_rel_list = NIL;
1468
0
  subroot->row_identity_vars = NIL;
1469
0
  subroot->rowMarks = NIL;
1470
0
  memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
1471
0
  memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
1472
0
  subroot->processed_groupClause = NIL;
1473
0
  subroot->processed_distinctClause = NIL;
1474
0
  subroot->processed_tlist = NIL;
1475
0
  subroot->update_colnos = NIL;
1476
0
  subroot->grouping_map = NULL;
1477
0
  subroot->minmax_aggs = NIL;
1478
0
  subroot->qual_security_level = 0;
1479
0
  subroot->placeholdersFrozen = false;
1480
0
  subroot->hasRecursion = false;
1481
0
  subroot->assumeReplanning = false;
1482
0
  subroot->wt_param_id = -1;
1483
0
  subroot->non_recursive_path = NULL;
1484
  /* We don't currently need a top JoinDomain for the subroot */
1485
1486
  /* No CTEs to worry about */
1487
0
  Assert(subquery->cteList == NIL);
1488
1489
  /*
1490
   * Scan the rangetable for relation RTEs and retrieve the necessary
1491
   * catalog information for each relation.  Using this information, clear
1492
   * the inh flag for any relation that has no children, collect not-null
1493
   * attribute numbers for any relation that has column not-null
1494
   * constraints, and expand virtual generated columns for any relation that
1495
   * contains them.
1496
   */
1497
0
  subquery = subroot->parse = preprocess_relation_rtes(subroot);
1498
1499
  /*
1500
   * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
1501
   * that we don't need so many special cases to deal with that situation.
1502
   */
1503
0
  replace_empty_jointree(subquery);
1504
1505
  /*
1506
   * Pull up any SubLinks within the subquery's quals, so that we don't
1507
   * leave unoptimized SubLinks behind.
1508
   */
1509
0
  if (subquery->hasSubLinks)
1510
0
    pull_up_sublinks(subroot);
1511
1512
  /*
1513
   * Similarly, preprocess its function RTEs to inline any set-returning
1514
   * functions in its rangetable.
1515
   */
1516
0
  preprocess_function_rtes(subroot);
1517
1518
  /*
1519
   * Recursively pull up the subquery's subqueries, so that
1520
   * pull_up_subqueries' processing is complete for its jointree and
1521
   * rangetable.
1522
   *
1523
   * Note: it's okay that the subquery's recursion starts with NULL for
1524
   * containing-join info, even if we are within an outer join in the upper
1525
   * query; the lower query starts with a clean slate for outer-join
1526
   * semantics.  Likewise, we needn't pass down appendrel state.
1527
   */
1528
0
  pull_up_subqueries(subroot);
1529
1530
  /*
1531
   * We must flatten any join alias Vars in the subquery's targetlist,
1532
   * because pulling up the subquery's subqueries might have changed their
1533
   * expansions into arbitrary expressions.  That could affect
1534
   * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1535
   * are needed for tlist entries, and if the subquery is LATERAL, the
1536
   * expansions might contain lateral references that the is_simple_subquery
1537
   * recheck below has to see.  The latter also requires flattening join
1538
   * alias Vars in the jointree quals of a LATERAL subquery.  (Likely it'd
1539
   * be better to do flatten_join_alias_vars on the whole query tree at some
1540
   * earlier stage, maybe even in the rewriter; but for now let's just fix
1541
   * these cases here.)
1542
   */
1543
0
  subquery->targetList = (List *)
1544
0
    flatten_join_alias_vars(subroot, subroot->parse,
1545
0
                (Node *) subquery->targetList);
1546
0
  if (rte->lateral)
1547
0
    flatten_join_alias_vars_in_jointree(subroot,
1548
0
                      (Node *) subquery->jointree);
1549
1550
  /*
1551
   * Now we must recheck whether the subquery is still simple enough to pull
1552
   * up.  If not, abandon processing it.
1553
   *
1554
   * We don't really need to recheck all the conditions involved, but it's
1555
   * easier just to keep this "if" looking the same as the one in
1556
   * pull_up_subqueries_recurse.
1557
   */
1558
0
  if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
1559
0
    (containing_appendrel == NULL || is_safe_append_member(subquery)))
1560
0
  {
1561
    /* good to go */
1562
0
  }
1563
0
  else
1564
0
  {
1565
    /*
1566
     * Give up, return unmodified RangeTblRef.
1567
     *
1568
     * Note: The work we just did will be redone when the subquery gets
1569
     * planned on its own.  Perhaps we could avoid that by storing the
1570
     * modified subquery back into the rangetable, but I'm not gonna risk
1571
     * it now.
1572
     */
1573
0
    return jtnode;
1574
0
  }
1575
1576
  /*
1577
   * Adjust level-0 varnos in subquery so that we can append its rangetable
1578
   * to upper query's.  We have to fix the subquery's append_rel_list as
1579
   * well.
1580
   */
1581
0
  rtoffset = list_length(parse->rtable);
1582
0
  OffsetVarNodes((Node *) subquery, rtoffset, 0);
1583
0
  OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1584
1585
  /*
1586
   * Upper-level vars in subquery are now one level closer to their parent
1587
   * than before.
1588
   */
1589
0
  IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1590
0
  IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
1591
1592
  /*
1593
   * The subquery's targetlist items are now in the appropriate form to
1594
   * insert into the top query, except that we may need to wrap them in
1595
   * PlaceHolderVars.  Set up required context data for pullup_replace_vars.
1596
   * (Note that we should include the subquery's inner joins in relids,
1597
   * since it may include join alias vars referencing them.)
1598
   */
1599
0
  rvcontext.root = root;
1600
0
  rvcontext.targetlist = subquery->targetList;
1601
0
  rvcontext.target_rte = rte;
1602
0
  rvcontext.result_relation = 0;
1603
0
  if (rte->lateral)
1604
0
  {
1605
0
    rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1606
0
                          true, true);
1607
0
    rvcontext.nullinfo = get_nullingrels(parse);
1608
0
  }
1609
0
  else            /* won't need these values */
1610
0
  {
1611
0
    rvcontext.relids = NULL;
1612
0
    rvcontext.nullinfo = NULL;
1613
0
  }
1614
0
  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1615
0
  rvcontext.varno = varno;
1616
  /* this flag will be set below, if needed */
1617
0
  rvcontext.wrap_option = REPLACE_WRAP_NONE;
1618
  /* initialize cache array with indexes 0 .. length(tlist) */
1619
0
  rvcontext.rv_cache = palloc0_array(Node *, list_length(subquery->targetList) + 1);
1620
1621
  /*
1622
   * If the parent query uses grouping sets, we need a PlaceHolderVar for
1623
   * each expression of the subquery's targetlist items.  This ensures that
1624
   * expressions retain their separate identity so that they will match
1625
   * grouping set columns when appropriate.  (It'd be sufficient to wrap
1626
   * values used in grouping set columns, and do so only in non-aggregated
1627
   * portions of the tlist and havingQual, but that would require a lot of
1628
   * infrastructure that pullup_replace_vars hasn't currently got.)
1629
   */
1630
0
  if (parse->groupingSets)
1631
0
    rvcontext.wrap_option = REPLACE_WRAP_ALL;
1632
1633
  /*
1634
   * Replace all of the top query's references to the subquery's outputs
1635
   * with copies of the adjusted subtlist items, being careful not to
1636
   * replace any of the jointree structure.
1637
   */
1638
0
  perform_pullup_replace_vars(root, &rvcontext,
1639
0
                containing_appendrel);
1640
1641
  /*
1642
   * If the subquery had a LATERAL marker, propagate that to any of its
1643
   * child RTEs that could possibly now contain lateral cross-references.
1644
   * The children might or might not contain any actual lateral
1645
   * cross-references, but we have to mark the pulled-up child RTEs so that
1646
   * later planner stages will check for such.
1647
   */
1648
0
  if (rte->lateral)
1649
0
  {
1650
0
    foreach(lc, subquery->rtable)
1651
0
    {
1652
0
      RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1653
1654
0
      switch (child_rte->rtekind)
1655
0
      {
1656
0
        case RTE_RELATION:
1657
0
          if (child_rte->tablesample)
1658
0
            child_rte->lateral = true;
1659
0
          break;
1660
0
        case RTE_SUBQUERY:
1661
0
        case RTE_FUNCTION:
1662
0
        case RTE_VALUES:
1663
0
        case RTE_TABLEFUNC:
1664
0
          child_rte->lateral = true;
1665
0
          break;
1666
0
        case RTE_JOIN:
1667
0
        case RTE_CTE:
1668
0
        case RTE_NAMEDTUPLESTORE:
1669
0
        case RTE_RESULT:
1670
0
        case RTE_GROUP:
1671
          /* these can't contain any lateral references */
1672
0
          break;
1673
0
      }
1674
0
    }
1675
0
  }
1676
1677
  /*
1678
   * Now append the adjusted rtable entries and their perminfos to upper
1679
   * query. (We hold off until after fixing the upper rtable entries; no
1680
   * point in running that code on the subquery ones too.)
1681
   */
1682
0
  CombineRangeTables(&parse->rtable, &parse->rteperminfos,
1683
0
             subquery->rtable, subquery->rteperminfos);
1684
1685
  /*
1686
   * Pull up any FOR UPDATE/SHARE markers, too.  (OffsetVarNodes already
1687
   * adjusted the marker rtindexes, so just concat the lists.)
1688
   */
1689
0
  parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
1690
1691
  /*
1692
   * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1693
   * parent query.  (This could perhaps be done by pullup_replace_vars(),
1694
   * but it seems cleaner to use two passes.)  Note in particular that any
1695
   * PlaceHolderVar nodes just created by pullup_replace_vars() will be
1696
   * adjusted, so having created them with the subquery's varno is correct.
1697
   *
1698
   * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1699
   * already checked that this won't require introducing multiple subrelids
1700
   * into the single-slot AppendRelInfo structs.
1701
   */
1702
0
  if (root->glob->lastPHId != 0 || root->append_rel_list)
1703
0
  {
1704
0
    Relids    subrelids;
1705
1706
0
    subrelids = get_relids_in_jointree((Node *) subquery->jointree,
1707
0
                       true, false);
1708
0
    if (root->glob->lastPHId != 0)
1709
0
      substitute_phv_relids((Node *) parse, varno, subrelids);
1710
0
    fix_append_rel_relids(root, varno, subrelids);
1711
0
  }
1712
1713
  /*
1714
   * And now add subquery's AppendRelInfos to our list.
1715
   */
1716
0
  root->append_rel_list = list_concat(root->append_rel_list,
1717
0
                    subroot->append_rel_list);
1718
1719
  /*
1720
   * We don't have to do the equivalent bookkeeping for outer-join info,
1721
   * because that hasn't been set up yet.  placeholder_list likewise.
1722
   */
1723
0
  Assert(root->join_info_list == NIL);
1724
0
  Assert(subroot->join_info_list == NIL);
1725
0
  Assert(root->placeholder_list == NIL);
1726
0
  Assert(subroot->placeholder_list == NIL);
1727
1728
  /*
1729
   * We no longer need the RTE's copy of the subquery's query tree.  Getting
1730
   * rid of it saves nothing in particular so far as this level of query is
1731
   * concerned; but if this query level is in turn pulled up into a parent,
1732
   * we'd waste cycles copying the now-unused query tree.
1733
   */
1734
0
  rte->subquery = NULL;
1735
1736
  /*
1737
   * Miscellaneous housekeeping.
1738
   *
1739
   * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1740
   * if it copied any SubLinks out of the subquery's targetlist, we still
1741
   * could have SubLinks added to the query in the expressions of FUNCTION
1742
   * and VALUES RTEs copied up from the subquery.  So it's necessary to copy
1743
   * subquery->hasSubLinks anyway.  Perhaps this can be improved someday.
1744
   */
1745
0
  parse->hasSubLinks |= subquery->hasSubLinks;
1746
1747
  /* If subquery had any RLS conditions, now main query does too */
1748
0
  parse->hasRowSecurity |= subquery->hasRowSecurity;
1749
1750
  /*
1751
   * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1752
   * hasTargetSRFs, so no work needed on those flags
1753
   */
1754
1755
  /*
1756
   * Return the adjusted subquery jointree to replace the RangeTblRef entry
1757
   * in parent's jointree; or, if the FromExpr is degenerate, just return
1758
   * its single member.
1759
   */
1760
0
  Assert(IsA(subquery->jointree, FromExpr));
1761
0
  Assert(subquery->jointree->fromlist != NIL);
1762
0
  if (subquery->jointree->quals == NULL &&
1763
0
    list_length(subquery->jointree->fromlist) == 1)
1764
0
    return (Node *) linitial(subquery->jointree->fromlist);
1765
1766
0
  return (Node *) subquery->jointree;
1767
0
}
1768
1769
/*
1770
 * pull_up_simple_union_all
1771
 *    Pull up a single simple UNION ALL subquery.
1772
 *
1773
 * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1774
 * subquery by pull_up_subqueries.  We pull up the leaf subqueries and
1775
 * build an "append relation" for the union set.  The result value is just
1776
 * jtnode, since we don't actually need to change the query jointree.
1777
 */
1778
static Node *
1779
pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1780
0
{
1781
0
  int     varno = ((RangeTblRef *) jtnode)->rtindex;
1782
0
  Query    *subquery = rte->subquery;
1783
0
  int     rtoffset = list_length(root->parse->rtable);
1784
0
  List     *rtable;
1785
1786
  /*
1787
   * Make a modifiable copy of the subquery's rtable, so we can adjust
1788
   * upper-level Vars in it.  There are no such Vars in the setOperations
1789
   * tree proper, so fixing the rtable should be sufficient.
1790
   */
1791
0
  rtable = copyObject(subquery->rtable);
1792
1793
  /*
1794
   * Upper-level vars in subquery are now one level closer to their parent
1795
   * than before.  We don't have to worry about offsetting varnos, though,
1796
   * because the UNION leaf queries can't cross-reference each other.
1797
   */
1798
0
  IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1799
1800
  /*
1801
   * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1802
   * its children.  The individual children might or might not contain any
1803
   * actual lateral cross-references, but we have to mark the pulled-up
1804
   * child RTEs so that later planner stages will check for such.
1805
   */
1806
0
  if (rte->lateral)
1807
0
  {
1808
0
    ListCell   *rt;
1809
1810
0
    foreach(rt, rtable)
1811
0
    {
1812
0
      RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1813
1814
0
      Assert(child_rte->rtekind == RTE_SUBQUERY);
1815
0
      child_rte->lateral = true;
1816
0
    }
1817
0
  }
1818
1819
  /*
1820
   * Append child RTEs (and their perminfos) to parent rtable.
1821
   */
1822
0
  CombineRangeTables(&root->parse->rtable, &root->parse->rteperminfos,
1823
0
             rtable, subquery->rteperminfos);
1824
1825
  /*
1826
   * Recursively scan the subquery's setOperations tree and add
1827
   * AppendRelInfo nodes for leaf subqueries to the parent's
1828
   * append_rel_list.  Also apply pull_up_subqueries to the leaf subqueries.
1829
   */
1830
0
  Assert(subquery->setOperations);
1831
0
  pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1832
0
                 rtoffset);
1833
1834
  /*
1835
   * Mark the parent as an append relation.
1836
   */
1837
0
  rte->inh = true;
1838
1839
0
  return jtnode;
1840
0
}
1841
1842
/*
1843
 * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1844
 *
1845
 * Build an AppendRelInfo for each leaf query in the setop tree, and then
1846
 * apply pull_up_subqueries to the leaf query.
1847
 *
1848
 * Note that setOpQuery is the Query containing the setOp node, whose tlist
1849
 * contains references to all the setop output columns.  When called from
1850
 * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1851
 * the parent Query we are pulling up into.
1852
 *
1853
 * parentRTindex is the appendrel parent's index in root->parse->rtable.
1854
 *
1855
 * The child RTEs have already been copied to the parent.  childRToffset
1856
 * tells us where in the parent's range table they were copied.  When called
1857
 * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1858
 * were already in root->parse->rtable and no RT index adjustment is needed.
1859
 */
1860
static void
1861
pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
1862
               Query *setOpQuery, int childRToffset)
1863
0
{
1864
0
  if (IsA(setOp, RangeTblRef))
1865
0
  {
1866
0
    RangeTblRef *rtr = (RangeTblRef *) setOp;
1867
0
    int     childRTindex;
1868
0
    AppendRelInfo *appinfo;
1869
1870
    /*
1871
     * Calculate the index in the parent's range table
1872
     */
1873
0
    childRTindex = childRToffset + rtr->rtindex;
1874
1875
    /*
1876
     * Build a suitable AppendRelInfo, and attach to parent's list.
1877
     */
1878
0
    appinfo = makeNode(AppendRelInfo);
1879
0
    appinfo->parent_relid = parentRTindex;
1880
0
    appinfo->child_relid = childRTindex;
1881
0
    appinfo->parent_reltype = InvalidOid;
1882
0
    appinfo->child_reltype = InvalidOid;
1883
0
    make_setop_translation_list(setOpQuery, childRTindex, appinfo);
1884
0
    appinfo->parent_reloid = InvalidOid;
1885
0
    root->append_rel_list = lappend(root->append_rel_list, appinfo);
1886
1887
    /*
1888
     * Recursively apply pull_up_subqueries to the new child RTE.  (We
1889
     * must build the AppendRelInfo first, because this will modify it;
1890
     * indeed, that's the only part of the upper query where Vars
1891
     * referencing childRTindex can exist at this point.)
1892
     *
1893
     * Note that we can pass NULL for containing-join info even if we're
1894
     * actually under an outer join, because the child's expressions
1895
     * aren't going to propagate up to the join.  Also, we ignore the
1896
     * possibility that pull_up_subqueries_recurse() returns a different
1897
     * jointree node than what we pass it; if it does, the important thing
1898
     * is that it replaced the child relid in the AppendRelInfo node.
1899
     */
1900
0
    rtr = makeNode(RangeTblRef);
1901
0
    rtr->rtindex = childRTindex;
1902
0
    (void) pull_up_subqueries_recurse(root, (Node *) rtr,
1903
0
                      NULL, appinfo);
1904
0
  }
1905
0
  else if (IsA(setOp, SetOperationStmt))
1906
0
  {
1907
0
    SetOperationStmt *op = (SetOperationStmt *) setOp;
1908
1909
    /* Recurse to reach leaf queries */
1910
0
    pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1911
0
                   childRToffset);
1912
0
    pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1913
0
                   childRToffset);
1914
0
  }
1915
0
  else
1916
0
  {
1917
0
    elog(ERROR, "unrecognized node type: %d",
1918
0
       (int) nodeTag(setOp));
1919
0
  }
1920
0
}
1921
1922
/*
1923
 * make_setop_translation_list
1924
 *    Build the list of translations from parent Vars to child Vars for
1925
 *    a UNION ALL member.  (At this point it's just a simple list of
1926
 *    referencing Vars, but if we succeed in pulling up the member
1927
 *    subquery, the Vars will get replaced by pulled-up expressions.)
1928
 *    Also create the rather trivial reverse-translation array.
1929
 */
1930
static void
1931
make_setop_translation_list(Query *query, int newvarno,
1932
              AppendRelInfo *appinfo)
1933
0
{
1934
0
  List     *vars = NIL;
1935
0
  AttrNumber *pcolnos;
1936
0
  ListCell   *l;
1937
1938
  /* Initialize reverse-translation array with all entries zero */
1939
  /* (entries for resjunk columns will stay that way) */
1940
0
  appinfo->num_child_cols = list_length(query->targetList);
1941
0
  appinfo->parent_colnos = pcolnos = palloc0_array(AttrNumber, appinfo->num_child_cols);
1942
1943
0
  foreach(l, query->targetList)
1944
0
  {
1945
0
    TargetEntry *tle = (TargetEntry *) lfirst(l);
1946
1947
0
    if (tle->resjunk)
1948
0
      continue;
1949
1950
0
    vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1951
0
    pcolnos[tle->resno - 1] = tle->resno;
1952
0
  }
1953
1954
0
  appinfo->translated_vars = vars;
1955
0
}
1956
1957
/*
1958
 * is_simple_subquery
1959
 *    Check a subquery in the range table to see if it's simple enough
1960
 *    to pull up into the parent query.
1961
 *
1962
 * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1963
 * (Note subquery is not necessarily equal to rte->subquery; it could be a
1964
 * processed copy of that.)
1965
 * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1966
 */
1967
static bool
1968
is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte,
1969
           JoinExpr *lowest_outer_join)
1970
0
{
1971
  /*
1972
   * Let's just make sure it's a valid subselect ...
1973
   */
1974
0
  if (!IsA(subquery, Query) ||
1975
0
    subquery->commandType != CMD_SELECT)
1976
0
    elog(ERROR, "subquery is bogus");
1977
1978
  /*
1979
   * Can't currently pull up a query with setops (unless it's simple UNION
1980
   * ALL, which is handled by a different code path). Maybe after querytree
1981
   * redesign...
1982
   */
1983
0
  if (subquery->setOperations)
1984
0
    return false;
1985
1986
  /*
1987
   * Can't pull up a subquery involving grouping, aggregation, SRFs,
1988
   * sorting, limiting, or WITH.  (XXX WITH could possibly be allowed later)
1989
   *
1990
   * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1991
   * clauses, because pullup would cause the locking to occur semantically
1992
   * higher than it should.  Implicit FOR UPDATE/SHARE is okay because in
1993
   * that case the locking was originally declared in the upper query
1994
   * anyway.
1995
   */
1996
0
  if (subquery->hasAggs ||
1997
0
    subquery->hasWindowFuncs ||
1998
0
    subquery->hasTargetSRFs ||
1999
0
    subquery->groupClause ||
2000
0
    subquery->groupingSets ||
2001
0
    subquery->havingQual ||
2002
0
    subquery->sortClause ||
2003
0
    subquery->distinctClause ||
2004
0
    subquery->limitOffset ||
2005
0
    subquery->limitCount ||
2006
0
    subquery->hasForUpdate ||
2007
0
    subquery->cteList)
2008
0
    return false;
2009
2010
  /*
2011
   * Don't pull up if the RTE represents a security-barrier view; we
2012
   * couldn't prevent information leakage once the RTE's Vars are scattered
2013
   * about in the upper query.
2014
   */
2015
0
  if (rte->security_barrier)
2016
0
    return false;
2017
2018
  /*
2019
   * If the subquery is LATERAL, check for pullup restrictions from that.
2020
   */
2021
0
  if (rte->lateral)
2022
0
  {
2023
0
    bool    restricted;
2024
0
    Relids    safe_upper_varnos;
2025
2026
    /*
2027
     * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
2028
     * references to rels outside a higher outer join (including the case
2029
     * where the outer join is within the subquery itself).  In such a
2030
     * case, pulling up would result in a situation where we need to
2031
     * postpone quals from below an outer join to above it, which is
2032
     * probably completely wrong and in any case is a complication that
2033
     * doesn't seem worth addressing at the moment.
2034
     */
2035
0
    if (lowest_outer_join != NULL)
2036
0
    {
2037
0
      restricted = true;
2038
0
      safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
2039
0
                             true, true);
2040
0
    }
2041
0
    else
2042
0
    {
2043
0
      restricted = false;
2044
0
      safe_upper_varnos = NULL; /* doesn't matter */
2045
0
    }
2046
2047
0
    if (jointree_contains_lateral_outer_refs(root,
2048
0
                         (Node *) subquery->jointree,
2049
0
                         restricted, safe_upper_varnos))
2050
0
      return false;
2051
2052
    /*
2053
     * If there's an outer join above the LATERAL subquery, also disallow
2054
     * pullup if the subquery's targetlist has any references to rels
2055
     * outside the outer join, since these might get pulled into quals
2056
     * above the subquery (but in or below the outer join) and then lead
2057
     * to qual-postponement issues similar to the case checked for above.
2058
     * (We wouldn't need to prevent pullup if no such references appear in
2059
     * outer-query quals, but we don't have enough info here to check
2060
     * that.  Also, maybe this restriction could be removed if we forced
2061
     * such refs to be wrapped in PlaceHolderVars, even when they're below
2062
     * the nearest outer join?  But it's a pretty hokey usage, so not
2063
     * clear this is worth sweating over.)
2064
     *
2065
     * If you change this, see also the comments about lateral references
2066
     * in pullup_replace_vars_callback().
2067
     */
2068
0
    if (lowest_outer_join != NULL)
2069
0
    {
2070
0
      Relids    lvarnos = pull_varnos_of_level(root,
2071
0
                             (Node *) subquery->targetList,
2072
0
                             1);
2073
2074
0
      if (!bms_is_subset(lvarnos, safe_upper_varnos))
2075
0
        return false;
2076
0
    }
2077
0
  }
2078
2079
  /*
2080
   * Don't pull up a subquery that has any volatile functions in its
2081
   * targetlist.  Otherwise we might introduce multiple evaluations of these
2082
   * functions, if they get copied to multiple places in the upper query,
2083
   * leading to surprising results.  (Note: the PlaceHolderVar mechanism
2084
   * doesn't quite guarantee single evaluation; else we could pull up anyway
2085
   * and just wrap such items in PlaceHolderVars ...)
2086
   */
2087
0
  if (contain_volatile_functions((Node *) subquery->targetList))
2088
0
    return false;
2089
2090
0
  return true;
2091
0
}
2092
2093
/*
2094
 * pull_up_simple_values
2095
 *    Pull up a single simple VALUES RTE.
2096
 *
2097
 * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
2098
 * by pull_up_subqueries.  We always return a RangeTblRef representing a
2099
 * RESULT RTE to replace it (all failure cases should have been detected by
2100
 * is_simple_values()).  Actually, what we return is just jtnode, because
2101
 * we replace the VALUES RTE in the rangetable with the RESULT RTE.
2102
 *
2103
 * rte is the RangeTblEntry referenced by jtnode.  Because of the limited
2104
 * possible usage of VALUES RTEs, we do not need the remaining parameters
2105
 * of pull_up_subqueries_recurse.
2106
 */
2107
static Node *
2108
pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
2109
0
{
2110
0
  Query    *parse = root->parse;
2111
0
  int     varno = ((RangeTblRef *) jtnode)->rtindex;
2112
0
  List     *values_list;
2113
0
  List     *tlist;
2114
0
  AttrNumber  attrno;
2115
0
  pullup_replace_vars_context rvcontext;
2116
0
  ListCell   *lc;
2117
2118
0
  Assert(rte->rtekind == RTE_VALUES);
2119
0
  Assert(list_length(rte->values_lists) == 1);
2120
2121
  /*
2122
   * Need a modifiable copy of the VALUES list to hack on, just in case it's
2123
   * multiply referenced.
2124
   */
2125
0
  values_list = copyObject(linitial(rte->values_lists));
2126
2127
  /*
2128
   * The VALUES RTE can't contain any Vars of level zero, let alone any that
2129
   * are join aliases, so no need to flatten join alias Vars.
2130
   */
2131
0
  Assert(!contain_vars_of_level((Node *) values_list, 0));
2132
2133
  /*
2134
   * Set up required context data for pullup_replace_vars.  In particular,
2135
   * we have to make the VALUES list look like a subquery targetlist.
2136
   */
2137
0
  tlist = NIL;
2138
0
  attrno = 1;
2139
0
  foreach(lc, values_list)
2140
0
  {
2141
0
    tlist = lappend(tlist,
2142
0
            makeTargetEntry((Expr *) lfirst(lc),
2143
0
                    attrno,
2144
0
                    NULL,
2145
0
                    false));
2146
0
    attrno++;
2147
0
  }
2148
0
  rvcontext.root = root;
2149
0
  rvcontext.targetlist = tlist;
2150
0
  rvcontext.target_rte = rte;
2151
0
  rvcontext.result_relation = 0;
2152
0
  rvcontext.relids = NULL; /* can't be any lateral references here */
2153
0
  rvcontext.nullinfo = NULL;
2154
0
  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
2155
0
  rvcontext.varno = varno;
2156
0
  rvcontext.wrap_option = REPLACE_WRAP_NONE;
2157
  /* initialize cache array with indexes 0 .. length(tlist) */
2158
0
  rvcontext.rv_cache = palloc0_array(Node *, list_length(tlist) + 1);
2159
2160
  /*
2161
   * Replace all of the top query's references to the RTE's outputs with
2162
   * copies of the adjusted VALUES expressions, being careful not to replace
2163
   * any of the jointree structure.  We can assume there's no outer joins or
2164
   * appendrels in the dummy Query that surrounds a VALUES RTE.
2165
   */
2166
0
  perform_pullup_replace_vars(root, &rvcontext, NULL);
2167
2168
  /*
2169
   * There should be no appendrels to fix, nor any outer joins and hence no
2170
   * PlaceHolderVars.
2171
   */
2172
0
  Assert(root->append_rel_list == NIL);
2173
0
  Assert(root->join_info_list == NIL);
2174
0
  Assert(root->placeholder_list == NIL);
2175
2176
  /*
2177
   * Replace the VALUES RTE with a RESULT RTE.  The VALUES RTE is the only
2178
   * rtable entry in the current query level, so this is easy.
2179
   */
2180
0
  Assert(list_length(parse->rtable) == 1);
2181
2182
  /* Create suitable RTE */
2183
0
  rte = makeNode(RangeTblEntry);
2184
0
  rte->rtekind = RTE_RESULT;
2185
0
  rte->eref = makeAlias("*RESULT*", NIL);
2186
2187
  /* Replace rangetable */
2188
0
  parse->rtable = list_make1(rte);
2189
2190
  /* We could manufacture a new RangeTblRef, but the one we have is fine */
2191
0
  Assert(varno == 1);
2192
2193
0
  return jtnode;
2194
0
}
2195
2196
/*
2197
 * is_simple_values
2198
 *    Check a VALUES RTE in the range table to see if it's simple enough
2199
 *    to pull up into the parent query.
2200
 *
2201
 * rte is the RTE_VALUES RangeTblEntry to check.
2202
 */
2203
static bool
2204
is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
2205
0
{
2206
0
  Assert(rte->rtekind == RTE_VALUES);
2207
2208
  /*
2209
   * There must be exactly one VALUES list, else it's not semantically
2210
   * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
2211
   * a unique set of expressions to substitute into the parent query.
2212
   */
2213
0
  if (list_length(rte->values_lists) != 1)
2214
0
    return false;
2215
2216
  /*
2217
   * Because VALUES can't appear under an outer join (or at least, we won't
2218
   * try to pull it up if it does), we need not worry about LATERAL, nor
2219
   * about validity of PHVs for the VALUES' outputs.
2220
   */
2221
2222
  /*
2223
   * Don't pull up a VALUES that contains any set-returning or volatile
2224
   * functions.  The considerations here are basically identical to the
2225
   * restrictions on a pull-able subquery's targetlist.
2226
   */
2227
0
  if (expression_returns_set((Node *) rte->values_lists) ||
2228
0
    contain_volatile_functions((Node *) rte->values_lists))
2229
0
    return false;
2230
2231
  /*
2232
   * Do not pull up a VALUES that's not the only RTE in its parent query.
2233
   * This is actually the only case that the parser will generate at the
2234
   * moment, and assuming this is true greatly simplifies
2235
   * pull_up_simple_values().
2236
   */
2237
0
  if (list_length(root->parse->rtable) != 1 ||
2238
0
    rte != (RangeTblEntry *) linitial(root->parse->rtable))
2239
0
    return false;
2240
2241
0
  return true;
2242
0
}
2243
2244
/*
2245
 * pull_up_constant_function
2246
 *    Pull up an RTE_FUNCTION expression that was simplified to a constant.
2247
 *
2248
 * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
2249
 * pull_up_subqueries.  If its expression is just a Const, hoist that value
2250
 * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
2251
 *
2252
 * In principle we could pull up any immutable expression, but we don't.
2253
 * That might result in multiple evaluations of the expression, which could
2254
 * be costly if it's not just a Const.  Also, the main value of this is
2255
 * to let the constant participate in further const-folding, and of course
2256
 * that won't happen for a non-Const.
2257
 *
2258
 * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
2259
 * RTE is below an outer join or is part of an appendrel; the extra
2260
 * parameters show whether that's needed.
2261
 */
2262
static Node *
2263
pull_up_constant_function(PlannerInfo *root, Node *jtnode,
2264
              RangeTblEntry *rte,
2265
              AppendRelInfo *containing_appendrel)
2266
0
{
2267
0
  Query    *parse = root->parse;
2268
0
  RangeTblFunction *rtf;
2269
0
  TypeFuncClass functypclass;
2270
0
  Oid     funcrettype;
2271
0
  TupleDesc tupdesc;
2272
0
  pullup_replace_vars_context rvcontext;
2273
2274
  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
2275
0
  if (rte->funcordinality)
2276
0
    return jtnode;
2277
2278
  /* Fail if RTE isn't a single, simple Const expr */
2279
0
  if (list_length(rte->functions) != 1)
2280
0
    return jtnode;
2281
0
  rtf = linitial_node(RangeTblFunction, rte->functions);
2282
0
  if (!IsA(rtf->funcexpr, Const))
2283
0
    return jtnode;
2284
2285
  /*
2286
   * If the function's result is not a scalar, we punt.  In principle we
2287
   * could break the composite constant value apart into per-column
2288
   * constants, but for now it seems not worth the work.
2289
   */
2290
0
  if (rtf->funccolcount != 1)
2291
0
    return jtnode;     /* definitely composite */
2292
2293
  /* If it has a coldeflist, it certainly returns RECORD */
2294
0
  if (rtf->funccolnames != NIL)
2295
0
    return jtnode;     /* must be a one-column RECORD type */
2296
2297
0
  functypclass = get_expr_result_type(rtf->funcexpr,
2298
0
                    &funcrettype,
2299
0
                    &tupdesc);
2300
0
  if (functypclass != TYPEFUNC_SCALAR)
2301
0
    return jtnode;     /* must be a one-column composite type */
2302
2303
  /* Create context for applying pullup_replace_vars */
2304
0
  rvcontext.root = root;
2305
0
  rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
2306
0
                            1,  /* resno */
2307
0
                            NULL, /* resname */
2308
0
                            false));  /* resjunk */
2309
0
  rvcontext.target_rte = rte;
2310
0
  rvcontext.result_relation = 0;
2311
2312
  /*
2313
   * Since this function was reduced to a Const, it doesn't contain any
2314
   * lateral references, even if it's marked as LATERAL.  This means we
2315
   * don't need to fill relids or nullinfo.
2316
   */
2317
0
  rvcontext.relids = NULL;
2318
0
  rvcontext.nullinfo = NULL;
2319
2320
0
  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
2321
0
  rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
2322
  /* this flag will be set below, if needed */
2323
0
  rvcontext.wrap_option = REPLACE_WRAP_NONE;
2324
  /* initialize cache array with indexes 0 .. length(tlist) */
2325
0
  rvcontext.rv_cache = palloc0_array(Node *, list_length(rvcontext.targetlist) + 1);
2326
2327
  /*
2328
   * If the parent query uses grouping sets, we need a PlaceHolderVar for
2329
   * each expression of the subquery's targetlist items.  (See comments in
2330
   * pull_up_simple_subquery().)
2331
   */
2332
0
  if (parse->groupingSets)
2333
0
    rvcontext.wrap_option = REPLACE_WRAP_ALL;
2334
2335
  /*
2336
   * Replace all of the top query's references to the RTE's output with
2337
   * copies of the funcexpr, being careful not to replace any of the
2338
   * jointree structure.
2339
   */
2340
0
  perform_pullup_replace_vars(root, &rvcontext,
2341
0
                containing_appendrel);
2342
2343
  /*
2344
   * We don't need to bother with changing PlaceHolderVars in the parent
2345
   * query.  Their references to the RT index are still good for now, and
2346
   * will get removed later if we're able to drop the RTE_RESULT.
2347
   */
2348
2349
  /*
2350
   * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
2351
   * scan it anymore, and zero out RTE_FUNCTION-specific fields.  Also make
2352
   * sure the RTE is not marked LATERAL, since elsewhere we don't expect
2353
   * RTE_RESULTs to be LATERAL.
2354
   */
2355
0
  rte->rtekind = RTE_RESULT;
2356
0
  rte->functions = NIL;
2357
0
  rte->lateral = false;
2358
2359
  /*
2360
   * We can reuse the RangeTblRef node.
2361
   */
2362
0
  return jtnode;
2363
0
}
2364
2365
/*
2366
 * is_simple_union_all
2367
 *    Check a subquery to see if it's a simple UNION ALL.
2368
 *
2369
 * We require all the setops to be UNION ALL (no mixing) and there can't be
2370
 * any datatype coercions involved, ie, all the leaf queries must emit the
2371
 * same datatypes.
2372
 */
2373
static bool
2374
is_simple_union_all(Query *subquery)
2375
0
{
2376
0
  SetOperationStmt *topop;
2377
2378
  /* Let's just make sure it's a valid subselect ... */
2379
0
  if (!IsA(subquery, Query) ||
2380
0
    subquery->commandType != CMD_SELECT)
2381
0
    elog(ERROR, "subquery is bogus");
2382
2383
  /* Is it a set-operation query at all? */
2384
0
  topop = castNode(SetOperationStmt, subquery->setOperations);
2385
0
  if (!topop)
2386
0
    return false;
2387
2388
  /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
2389
0
  if (subquery->sortClause ||
2390
0
    subquery->limitOffset ||
2391
0
    subquery->limitCount ||
2392
0
    subquery->rowMarks ||
2393
0
    subquery->cteList)
2394
0
    return false;
2395
2396
  /* Recursively check the tree of set operations */
2397
0
  return is_simple_union_all_recurse((Node *) topop, subquery,
2398
0
                     topop->colTypes);
2399
0
}
2400
2401
static bool
2402
is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
2403
0
{
2404
  /* Since this function recurses, it could be driven to stack overflow. */
2405
0
  check_stack_depth();
2406
2407
0
  if (IsA(setOp, RangeTblRef))
2408
0
  {
2409
0
    RangeTblRef *rtr = (RangeTblRef *) setOp;
2410
0
    RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
2411
0
    Query    *subquery = rte->subquery;
2412
2413
0
    Assert(subquery != NULL);
2414
2415
    /* Leaf nodes are OK if they match the toplevel column types */
2416
    /* We don't have to compare typmods or collations here */
2417
0
    return tlist_same_datatypes(subquery->targetList, colTypes, true);
2418
0
  }
2419
0
  else if (IsA(setOp, SetOperationStmt))
2420
0
  {
2421
0
    SetOperationStmt *op = (SetOperationStmt *) setOp;
2422
2423
    /* Must be UNION ALL */
2424
0
    if (op->op != SETOP_UNION || !op->all)
2425
0
      return false;
2426
2427
    /* Recurse to check inputs */
2428
0
    return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
2429
0
      is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
2430
0
  }
2431
0
  else
2432
0
  {
2433
0
    elog(ERROR, "unrecognized node type: %d",
2434
0
       (int) nodeTag(setOp));
2435
0
    return false;     /* keep compiler quiet */
2436
0
  }
2437
0
}
2438
2439
/*
2440
 * is_safe_append_member
2441
 *    Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
2442
 *    safe to pull up.
2443
 */
2444
static bool
2445
is_safe_append_member(Query *subquery)
2446
0
{
2447
0
  FromExpr   *jtnode;
2448
2449
  /*
2450
   * It's only safe to pull up the child if its jointree contains exactly
2451
   * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
2452
   * could be buried in several levels of FromExpr, however.  Also, if the
2453
   * child's jointree is completely empty, we can pull up because
2454
   * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
2455
   *
2456
   * Also, the child can't have any WHERE quals because there's no place to
2457
   * put them in an appendrel.  (This is a bit annoying...) If we didn't
2458
   * need to check this, we'd just test whether get_relids_in_jointree()
2459
   * yields a singleton set, to be more consistent with the coding of
2460
   * fix_append_rel_relids().
2461
   */
2462
0
  jtnode = subquery->jointree;
2463
0
  Assert(IsA(jtnode, FromExpr));
2464
  /* Check the completely-empty case */
2465
0
  if (jtnode->fromlist == NIL && jtnode->quals == NULL)
2466
0
    return true;
2467
  /* Check the more general case */
2468
0
  while (IsA(jtnode, FromExpr))
2469
0
  {
2470
0
    if (jtnode->quals != NULL)
2471
0
      return false;
2472
0
    if (list_length(jtnode->fromlist) != 1)
2473
0
      return false;
2474
0
    jtnode = linitial(jtnode->fromlist);
2475
0
  }
2476
0
  if (!IsA(jtnode, RangeTblRef))
2477
0
    return false;
2478
2479
0
  return true;
2480
0
}
2481
2482
/*
2483
 * jointree_contains_lateral_outer_refs
2484
 *    Check for disallowed lateral references in a jointree's quals
2485
 *
2486
 * If restricted is false, all level-1 Vars are allowed (but we still must
2487
 * search the jointree, since it might contain outer joins below which there
2488
 * will be restrictions).  If restricted is true, return true when any qual
2489
 * in the jointree contains level-1 Vars coming from outside the rels listed
2490
 * in safe_upper_varnos.
2491
 */
2492
static bool
2493
jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode,
2494
                   bool restricted,
2495
                   Relids safe_upper_varnos)
2496
0
{
2497
0
  if (jtnode == NULL)
2498
0
    return false;
2499
0
  if (IsA(jtnode, RangeTblRef))
2500
0
    return false;
2501
0
  else if (IsA(jtnode, FromExpr))
2502
0
  {
2503
0
    FromExpr   *f = (FromExpr *) jtnode;
2504
0
    ListCell   *l;
2505
2506
    /* First, recurse to check child joins */
2507
0
    foreach(l, f->fromlist)
2508
0
    {
2509
0
      if (jointree_contains_lateral_outer_refs(root,
2510
0
                           lfirst(l),
2511
0
                           restricted,
2512
0
                           safe_upper_varnos))
2513
0
        return true;
2514
0
    }
2515
2516
    /* Then check the top-level quals */
2517
0
    if (restricted &&
2518
0
      !bms_is_subset(pull_varnos_of_level(root, f->quals, 1),
2519
0
               safe_upper_varnos))
2520
0
      return true;
2521
0
  }
2522
0
  else if (IsA(jtnode, JoinExpr))
2523
0
  {
2524
0
    JoinExpr   *j = (JoinExpr *) jtnode;
2525
2526
    /*
2527
     * If this is an outer join, we mustn't allow any upper lateral
2528
     * references in or below it.
2529
     */
2530
0
    if (j->jointype != JOIN_INNER)
2531
0
    {
2532
0
      restricted = true;
2533
0
      safe_upper_varnos = NULL;
2534
0
    }
2535
2536
    /* Check the child joins */
2537
0
    if (jointree_contains_lateral_outer_refs(root,
2538
0
                         j->larg,
2539
0
                         restricted,
2540
0
                         safe_upper_varnos))
2541
0
      return true;
2542
0
    if (jointree_contains_lateral_outer_refs(root,
2543
0
                         j->rarg,
2544
0
                         restricted,
2545
0
                         safe_upper_varnos))
2546
0
      return true;
2547
2548
    /* Check the JOIN's qual clauses */
2549
0
    if (restricted &&
2550
0
      !bms_is_subset(pull_varnos_of_level(root, j->quals, 1),
2551
0
               safe_upper_varnos))
2552
0
      return true;
2553
0
  }
2554
0
  else
2555
0
    elog(ERROR, "unrecognized node type: %d",
2556
0
       (int) nodeTag(jtnode));
2557
0
  return false;
2558
0
}
2559
2560
/*
2561
 * flatten_join_alias_vars_in_jointree
2562
 *    Apply flatten_join_alias_vars to all quals in the given jointree,
2563
 *    replacing them in place.  The jointree must belong to root->parse.
2564
 */
2565
static void
2566
flatten_join_alias_vars_in_jointree(PlannerInfo *root, Node *jtnode)
2567
0
{
2568
0
  if (jtnode == NULL)
2569
0
    return;
2570
0
  if (IsA(jtnode, RangeTblRef))
2571
0
    return;
2572
0
  else if (IsA(jtnode, FromExpr))
2573
0
  {
2574
0
    FromExpr   *f = (FromExpr *) jtnode;
2575
0
    ListCell   *l;
2576
2577
0
    foreach(l, f->fromlist)
2578
0
      flatten_join_alias_vars_in_jointree(root, lfirst(l));
2579
0
    f->quals = flatten_join_alias_vars(root, root->parse, f->quals);
2580
0
  }
2581
0
  else if (IsA(jtnode, JoinExpr))
2582
0
  {
2583
0
    JoinExpr   *j = (JoinExpr *) jtnode;
2584
2585
0
    flatten_join_alias_vars_in_jointree(root, j->larg);
2586
0
    flatten_join_alias_vars_in_jointree(root, j->rarg);
2587
0
    j->quals = flatten_join_alias_vars(root, root->parse, j->quals);
2588
0
  }
2589
0
  else
2590
0
    elog(ERROR, "unrecognized node type: %d",
2591
0
       (int) nodeTag(jtnode));
2592
0
}
2593
2594
/*
2595
 * Perform pullup_replace_vars everyplace it's needed in the query tree.
2596
 *
2597
 * Caller has already filled *rvcontext with data describing what to
2598
 * substitute for Vars referencing the target subquery.  In addition
2599
 * we need the identity of the containing appendrel if any.
2600
 */
2601
static void
2602
perform_pullup_replace_vars(PlannerInfo *root,
2603
              pullup_replace_vars_context *rvcontext,
2604
              AppendRelInfo *containing_appendrel)
2605
0
{
2606
0
  Query    *parse = root->parse;
2607
0
  ListCell   *lc;
2608
2609
  /*
2610
   * If we are considering an appendrel child subquery (that is, a UNION ALL
2611
   * member query that we're pulling up), then the only part of the upper
2612
   * query that could reference the child yet is the translated_vars list of
2613
   * the associated AppendRelInfo.  Furthermore, we do not want to force use
2614
   * of PHVs in the AppendRelInfo --- there isn't any outer join between.
2615
   */
2616
0
  if (containing_appendrel)
2617
0
  {
2618
0
    ReplaceWrapOption save_wrap_option = rvcontext->wrap_option;
2619
2620
0
    rvcontext->wrap_option = REPLACE_WRAP_NONE;
2621
0
    containing_appendrel->translated_vars = (List *)
2622
0
      pullup_replace_vars((Node *) containing_appendrel->translated_vars,
2623
0
                rvcontext);
2624
0
    rvcontext->wrap_option = save_wrap_option;
2625
0
    return;
2626
0
  }
2627
2628
  /*
2629
   * Replace all of the top query's references to the subquery's outputs
2630
   * with copies of the adjusted subtlist items, being careful not to
2631
   * replace any of the jointree structure.  (This'd be a lot cleaner if we
2632
   * could use query_tree_mutator.)  We have to use PHVs in the targetList,
2633
   * returningList, and havingQual, since those are certainly above any
2634
   * outer join.  replace_vars_in_jointree tracks its location in the
2635
   * jointree and uses PHVs or not appropriately.
2636
   */
2637
0
  parse->targetList = (List *)
2638
0
    pullup_replace_vars((Node *) parse->targetList, rvcontext);
2639
0
  parse->returningList = (List *)
2640
0
    pullup_replace_vars((Node *) parse->returningList, rvcontext);
2641
2642
0
  if (parse->onConflict)
2643
0
  {
2644
0
    parse->onConflict->onConflictSet = (List *)
2645
0
      pullup_replace_vars((Node *) parse->onConflict->onConflictSet,
2646
0
                rvcontext);
2647
0
    parse->onConflict->onConflictWhere =
2648
0
      pullup_replace_vars(parse->onConflict->onConflictWhere,
2649
0
                rvcontext);
2650
2651
    /*
2652
     * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2653
     * can't contain any references to a subquery.
2654
     */
2655
0
  }
2656
0
  if (parse->mergeActionList)
2657
0
  {
2658
0
    foreach(lc, parse->mergeActionList)
2659
0
    {
2660
0
      MergeAction *action = lfirst(lc);
2661
2662
0
      action->qual = pullup_replace_vars(action->qual, rvcontext);
2663
0
      action->targetList = (List *)
2664
0
        pullup_replace_vars((Node *) action->targetList, rvcontext);
2665
0
    }
2666
0
  }
2667
0
  parse->mergeJoinCondition = pullup_replace_vars(parse->mergeJoinCondition,
2668
0
                          rvcontext);
2669
0
  replace_vars_in_jointree((Node *) parse->jointree, rvcontext);
2670
0
  Assert(parse->setOperations == NULL);
2671
0
  parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2672
2673
  /*
2674
   * Replace references in the translated_vars lists of appendrels.
2675
   */
2676
0
  foreach(lc, root->append_rel_list)
2677
0
  {
2678
0
    AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2679
2680
0
    appinfo->translated_vars = (List *)
2681
0
      pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2682
0
  }
2683
2684
  /*
2685
   * Replace references in the joinaliasvars lists of join RTEs and the
2686
   * groupexprs list of group RTE.
2687
   */
2688
0
  foreach(lc, parse->rtable)
2689
0
  {
2690
0
    RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
2691
2692
0
    if (otherrte->rtekind == RTE_JOIN)
2693
0
      otherrte->joinaliasvars = (List *)
2694
0
        pullup_replace_vars((Node *) otherrte->joinaliasvars,
2695
0
                  rvcontext);
2696
0
    else if (otherrte->rtekind == RTE_GROUP)
2697
0
      otherrte->groupexprs = (List *)
2698
0
        pullup_replace_vars((Node *) otherrte->groupexprs,
2699
0
                  rvcontext);
2700
0
  }
2701
0
}
2702
2703
/*
2704
 * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2705
 * every expression in the jointree, without changing the jointree structure
2706
 * itself.  Ugly, but there's no other way...
2707
 */
2708
static void
2709
replace_vars_in_jointree(Node *jtnode,
2710
             pullup_replace_vars_context *context)
2711
0
{
2712
0
  if (jtnode == NULL)
2713
0
    return;
2714
0
  if (IsA(jtnode, RangeTblRef))
2715
0
  {
2716
    /*
2717
     * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2718
     * same subquery we're pulling up), it might contain references to the
2719
     * target subquery, which we must replace.  We drive this from the
2720
     * jointree scan, rather than a scan of the rtable, so that we can
2721
     * avoid processing no-longer-referenced RTEs.
2722
     */
2723
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
2724
2725
0
    if (varno != context->varno) /* ignore target subquery itself */
2726
0
    {
2727
0
      RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2728
2729
0
      Assert(rte != context->target_rte);
2730
0
      if (rte->lateral)
2731
0
      {
2732
0
        switch (rte->rtekind)
2733
0
        {
2734
0
          case RTE_RELATION:
2735
            /* shouldn't be marked LATERAL unless tablesample */
2736
0
            Assert(rte->tablesample);
2737
0
            rte->tablesample = (TableSampleClause *)
2738
0
              pullup_replace_vars((Node *) rte->tablesample,
2739
0
                        context);
2740
0
            break;
2741
0
          case RTE_SUBQUERY:
2742
0
            rte->subquery =
2743
0
              pullup_replace_vars_subquery(rte->subquery,
2744
0
                             context);
2745
0
            break;
2746
0
          case RTE_FUNCTION:
2747
0
            rte->functions = (List *)
2748
0
              pullup_replace_vars((Node *) rte->functions,
2749
0
                        context);
2750
0
            break;
2751
0
          case RTE_TABLEFUNC:
2752
0
            rte->tablefunc = (TableFunc *)
2753
0
              pullup_replace_vars((Node *) rte->tablefunc,
2754
0
                        context);
2755
0
            break;
2756
0
          case RTE_VALUES:
2757
0
            rte->values_lists = (List *)
2758
0
              pullup_replace_vars((Node *) rte->values_lists,
2759
0
                        context);
2760
0
            break;
2761
0
          case RTE_JOIN:
2762
0
          case RTE_CTE:
2763
0
          case RTE_NAMEDTUPLESTORE:
2764
0
          case RTE_RESULT:
2765
0
          case RTE_GROUP:
2766
            /* these shouldn't be marked LATERAL */
2767
0
            Assert(false);
2768
0
            break;
2769
0
        }
2770
0
      }
2771
0
    }
2772
0
  }
2773
0
  else if (IsA(jtnode, FromExpr))
2774
0
  {
2775
0
    FromExpr   *f = (FromExpr *) jtnode;
2776
0
    ListCell   *l;
2777
2778
0
    foreach(l, f->fromlist)
2779
0
      replace_vars_in_jointree(lfirst(l), context);
2780
0
    f->quals = pullup_replace_vars(f->quals, context);
2781
0
  }
2782
0
  else if (IsA(jtnode, JoinExpr))
2783
0
  {
2784
0
    JoinExpr   *j = (JoinExpr *) jtnode;
2785
0
    ReplaceWrapOption save_wrap_option = context->wrap_option;
2786
2787
0
    replace_vars_in_jointree(j->larg, context);
2788
0
    replace_vars_in_jointree(j->rarg, context);
2789
2790
    /*
2791
     * Use PHVs within the join quals of a full join for variable-free
2792
     * expressions.  Otherwise, we cannot identify which side of the join
2793
     * a pulled-up variable-free expression came from, which can lead to
2794
     * failure to make a plan at all because none of the quals appear to
2795
     * be mergeable or hashable conditions.
2796
     */
2797
0
    if (j->jointype == JOIN_FULL)
2798
0
      context->wrap_option = REPLACE_WRAP_VARFREE;
2799
2800
0
    j->quals = pullup_replace_vars(j->quals, context);
2801
2802
0
    context->wrap_option = save_wrap_option;
2803
0
  }
2804
0
  else
2805
0
    elog(ERROR, "unrecognized node type: %d",
2806
0
       (int) nodeTag(jtnode));
2807
0
}
2808
2809
/*
2810
 * Apply pullup variable replacement throughout an expression tree
2811
 *
2812
 * Returns a modified copy of the tree, so this can't be used where we
2813
 * need to do in-place replacement.
2814
 */
2815
static Node *
2816
pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
2817
0
{
2818
0
  return replace_rte_variables(expr,
2819
0
                 context->varno, 0,
2820
0
                 pullup_replace_vars_callback,
2821
0
                 context,
2822
0
                 context->outer_hasSubLinks);
2823
0
}
2824
2825
static Node *
2826
pullup_replace_vars_callback(const Var *var,
2827
               replace_rte_variables_context *context)
2828
0
{
2829
0
  pullup_replace_vars_context *rcon = (pullup_replace_vars_context *) context->callback_arg;
2830
0
  int     varattno = var->varattno;
2831
0
  bool    need_phv;
2832
0
  Node     *newnode;
2833
2834
  /* System columns are not replaced. */
2835
0
  if (varattno < InvalidAttrNumber)
2836
0
    return (Node *) copyObject(var);
2837
2838
  /*
2839
   * We need a PlaceHolderVar if the Var-to-be-replaced has nonempty
2840
   * varnullingrels (unless we find below that the replacement expression is
2841
   * a Var or PlaceHolderVar that we can just add the nullingrels to).  We
2842
   * also need one if the caller has instructed us that certain expression
2843
   * replacements need to be wrapped for identification purposes.
2844
   */
2845
0
  need_phv = (var->varnullingrels != NULL) ||
2846
0
    (rcon->wrap_option != REPLACE_WRAP_NONE);
2847
2848
  /*
2849
   * If PlaceHolderVars are needed, we cache the modified expressions in
2850
   * rcon->rv_cache[].  This is not in hopes of any material speed gain
2851
   * within this function, but to avoid generating identical PHVs with
2852
   * different IDs.  That would result in duplicate evaluations at runtime,
2853
   * and possibly prevent optimizations that rely on recognizing different
2854
   * references to the same subquery output as being equal().  So it's worth
2855
   * a bit of extra effort to avoid it.
2856
   *
2857
   * The cached items have phlevelsup = 0 and phnullingrels = NULL; we'll
2858
   * copy them and adjust those values for this reference site below.
2859
   */
2860
0
  if (need_phv &&
2861
0
    varattno >= InvalidAttrNumber &&
2862
0
    varattno <= list_length(rcon->targetlist) &&
2863
0
    rcon->rv_cache[varattno] != NULL)
2864
0
  {
2865
    /* Just copy the entry and fall through to adjust phlevelsup etc */
2866
0
    newnode = copyObject(rcon->rv_cache[varattno]);
2867
0
  }
2868
0
  else
2869
0
  {
2870
    /*
2871
     * Generate the replacement expression.  This takes care of expanding
2872
     * wholerow references and dealing with non-default varreturningtype.
2873
     */
2874
0
    newnode = ReplaceVarFromTargetList(var,
2875
0
                       rcon->target_rte,
2876
0
                       rcon->targetlist,
2877
0
                       rcon->result_relation,
2878
0
                       REPLACEVARS_REPORT_ERROR,
2879
0
                       0);
2880
2881
    /* Insert PlaceHolderVar if needed */
2882
0
    if (need_phv)
2883
0
    {
2884
0
      bool    wrap;
2885
2886
0
      if (rcon->wrap_option == REPLACE_WRAP_ALL)
2887
0
      {
2888
        /* Caller told us to wrap all expressions in a PlaceHolderVar */
2889
0
        wrap = true;
2890
0
      }
2891
0
      else if (varattno == InvalidAttrNumber)
2892
0
      {
2893
        /*
2894
         * Insert PlaceHolderVar for whole-tuple reference.  Notice
2895
         * that we are wrapping one PlaceHolderVar around the whole
2896
         * RowExpr, rather than putting one around each element of the
2897
         * row.  This is because we need the expression to yield NULL,
2898
         * not ROW(NULL,NULL,...) when it is forced to null by an
2899
         * outer join.
2900
         */
2901
0
        wrap = true;
2902
0
      }
2903
0
      else if (newnode && IsA(newnode, Var) &&
2904
0
           ((Var *) newnode)->varlevelsup == 0)
2905
0
      {
2906
        /*
2907
         * Simple Vars always escape being wrapped, unless they are
2908
         * lateral references to something outside the subquery being
2909
         * pulled up and the referenced rel is not under the same
2910
         * lowest nulling outer join.
2911
         */
2912
0
        wrap = false;
2913
0
        if (rcon->target_rte->lateral &&
2914
0
          !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2915
0
        {
2916
0
          nullingrel_info *nullinfo = rcon->nullinfo;
2917
0
          int     lvarno = ((Var *) newnode)->varno;
2918
2919
0
          Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2920
0
          if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2921
0
                     nullinfo->nullingrels[lvarno]))
2922
0
            wrap = true;
2923
0
        }
2924
0
      }
2925
0
      else if (newnode && IsA(newnode, PlaceHolderVar) &&
2926
0
           ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2927
0
      {
2928
        /* The same rules apply for a PlaceHolderVar */
2929
0
        wrap = false;
2930
0
        if (rcon->target_rte->lateral &&
2931
0
          !bms_is_subset(((PlaceHolderVar *) newnode)->phrels,
2932
0
                   rcon->relids))
2933
0
        {
2934
0
          nullingrel_info *nullinfo = rcon->nullinfo;
2935
0
          Relids    lvarnos = ((PlaceHolderVar *) newnode)->phrels;
2936
0
          int     lvarno;
2937
2938
0
          lvarno = -1;
2939
0
          while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
2940
0
          {
2941
0
            Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2942
0
            if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2943
0
                       nullinfo->nullingrels[lvarno]))
2944
0
            {
2945
0
              wrap = true;
2946
0
              break;
2947
0
            }
2948
0
          }
2949
0
        }
2950
0
      }
2951
0
      else
2952
0
      {
2953
        /*
2954
         * If the node contains Var(s) or PlaceHolderVar(s) of the
2955
         * subquery being pulled up, or of rels that are under the
2956
         * same lowest nulling outer join as the subquery, and does
2957
         * not contain any non-strict constructs, then instead of
2958
         * adding a PHV on top we can add the required nullingrels to
2959
         * those Vars/PHVs.  (This is fundamentally a generalization
2960
         * of the above cases for bare Vars and PHVs.)
2961
         *
2962
         * This test is somewhat expensive, but it avoids pessimizing
2963
         * the plan in cases where the nullingrels get removed again
2964
         * later by outer join reduction.
2965
         *
2966
         * Note that we don't force wrapping of expressions containing
2967
         * lateral references, so long as they also contain Vars/PHVs
2968
         * of the subquery, or of rels that are under the same lowest
2969
         * nulling outer join as the subquery.  This is okay because
2970
         * of the restriction to strict constructs: if those Vars/PHVs
2971
         * have been forced to NULL by an outer join then the end
2972
         * result of the expression will be NULL too, regardless of
2973
         * the lateral references.  So it's not necessary to force the
2974
         * expression to be evaluated below the outer join.  This can
2975
         * be a very valuable optimization, because it may allow us to
2976
         * avoid using a nested loop to pass the lateral reference
2977
         * down.
2978
         *
2979
         * This analysis could be tighter: in particular, a non-strict
2980
         * construct hidden within a lower-level PlaceHolderVar is not
2981
         * reason to add another PHV.  But for now it doesn't seem
2982
         * worth the code to be more exact.  This is also why it's
2983
         * preferable to handle bare PHVs in the above branch, rather
2984
         * than this branch.  We also prefer to handle bare Vars in a
2985
         * separate branch, as it's cheaper this way and parallels the
2986
         * handling of PHVs.
2987
         *
2988
         * For a LATERAL subquery, we have to check the actual var
2989
         * membership of the node, but if it's non-lateral then any
2990
         * level-zero var must belong to the subquery.
2991
         */
2992
0
        bool    contain_nullable_vars = false;
2993
2994
0
        if (!rcon->target_rte->lateral)
2995
0
        {
2996
0
          if (contain_vars_of_level(newnode, 0))
2997
0
            contain_nullable_vars = true;
2998
0
        }
2999
0
        else
3000
0
        {
3001
0
          Relids    all_varnos;
3002
3003
0
          all_varnos = pull_varnos(rcon->root, newnode);
3004
0
          if (bms_overlap(all_varnos, rcon->relids))
3005
0
            contain_nullable_vars = true;
3006
0
          else
3007
0
          {
3008
0
            nullingrel_info *nullinfo = rcon->nullinfo;
3009
0
            int     varno;
3010
3011
0
            varno = -1;
3012
0
            while ((varno = bms_next_member(all_varnos, varno)) >= 0)
3013
0
            {
3014
0
              Assert(varno > 0 && varno <= nullinfo->rtlength);
3015
0
              if (bms_is_subset(nullinfo->nullingrels[rcon->varno],
3016
0
                        nullinfo->nullingrels[varno]))
3017
0
              {
3018
0
                contain_nullable_vars = true;
3019
0
                break;
3020
0
              }
3021
0
            }
3022
0
          }
3023
0
        }
3024
3025
0
        if (contain_nullable_vars &&
3026
0
          !contain_nonstrict_functions(newnode))
3027
0
        {
3028
          /* No wrap needed */
3029
0
          wrap = false;
3030
0
        }
3031
0
        else
3032
0
        {
3033
          /* Else wrap it in a PlaceHolderVar */
3034
0
          wrap = true;
3035
0
        }
3036
0
      }
3037
3038
0
      if (wrap)
3039
0
      {
3040
0
        newnode = (Node *)
3041
0
          make_placeholder_expr(rcon->root,
3042
0
                      (Expr *) newnode,
3043
0
                      bms_make_singleton(rcon->varno));
3044
3045
        /*
3046
         * Cache it if possible (ie, if the attno is in range, which
3047
         * it probably always should be).
3048
         */
3049
0
        if (varattno >= InvalidAttrNumber &&
3050
0
          varattno <= list_length(rcon->targetlist))
3051
0
          rcon->rv_cache[varattno] = copyObject(newnode);
3052
0
      }
3053
0
    }
3054
0
  }
3055
3056
  /* Propagate any varnullingrels into the replacement expression */
3057
0
  if (var->varnullingrels != NULL)
3058
0
  {
3059
0
    if (IsA(newnode, Var))
3060
0
    {
3061
0
      Var      *newvar = (Var *) newnode;
3062
3063
0
      Assert(newvar->varlevelsup == 0);
3064
0
      newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
3065
0
                           var->varnullingrels);
3066
0
    }
3067
0
    else if (IsA(newnode, PlaceHolderVar))
3068
0
    {
3069
0
      PlaceHolderVar *newphv = (PlaceHolderVar *) newnode;
3070
3071
0
      Assert(newphv->phlevelsup == 0);
3072
0
      newphv->phnullingrels = bms_add_members(newphv->phnullingrels,
3073
0
                          var->varnullingrels);
3074
0
    }
3075
0
    else
3076
0
    {
3077
      /*
3078
       * There should be Vars/PHVs within the expression that we can
3079
       * modify.  Vars/PHVs of the subquery should have the full
3080
       * var->varnullingrels added to them, but if there are lateral
3081
       * references within the expression, those must be marked with
3082
       * only the nullingrels that potentially apply to them.  (This
3083
       * corresponds to the fact that the expression will now be
3084
       * evaluated at the join level of the Var that we are replacing:
3085
       * the lateral references may have bubbled up through fewer outer
3086
       * joins than the subquery's Vars have.  Per the discussion above,
3087
       * we'll still get the right answers.)  That relid set could be
3088
       * different for different lateral relations, so we have to do
3089
       * this work for each one.
3090
       *
3091
       * (Currently, the restrictions in is_simple_subquery() mean that
3092
       * at most we have to remove the lowest outer join's relid from
3093
       * the nullingrels of a lateral reference.  However, we might
3094
       * relax those restrictions someday, so let's do this right.)
3095
       */
3096
0
      if (rcon->target_rte->lateral)
3097
0
      {
3098
0
        nullingrel_info *nullinfo = rcon->nullinfo;
3099
0
        Relids    lvarnos;
3100
0
        int     lvarno;
3101
3102
        /*
3103
         * Identify lateral varnos used within newnode.  We must do
3104
         * this before injecting var->varnullingrels into the tree.
3105
         */
3106
0
        lvarnos = pull_varnos(rcon->root, newnode);
3107
0
        lvarnos = bms_del_members(lvarnos, rcon->relids);
3108
        /* For each one, add relevant nullingrels if any */
3109
0
        lvarno = -1;
3110
0
        while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
3111
0
        {
3112
0
          Relids    lnullingrels;
3113
3114
0
          Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
3115
0
          lnullingrels = bms_intersect(var->varnullingrels,
3116
0
                         nullinfo->nullingrels[lvarno]);
3117
0
          if (!bms_is_empty(lnullingrels))
3118
0
            newnode = add_nulling_relids(newnode,
3119
0
                           bms_make_singleton(lvarno),
3120
0
                           lnullingrels);
3121
0
        }
3122
0
      }
3123
3124
      /* Finally, deal with Vars/PHVs of the subquery itself */
3125
0
      newnode = add_nulling_relids(newnode,
3126
0
                     rcon->relids,
3127
0
                     var->varnullingrels);
3128
      /* Assert we did put the varnullingrels into the expression */
3129
0
      Assert(bms_is_subset(var->varnullingrels,
3130
0
                 pull_varnos(rcon->root, newnode)));
3131
0
    }
3132
0
  }
3133
3134
  /* Must adjust varlevelsup if replaced Var is within a subquery */
3135
0
  if (var->varlevelsup > 0)
3136
0
    IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
3137
3138
0
  return newnode;
3139
0
}
3140
3141
/*
3142
 * Apply pullup variable replacement to a subquery
3143
 *
3144
 * This needs to be different from pullup_replace_vars() because
3145
 * replace_rte_variables will think that it shouldn't increment sublevels_up
3146
 * before entering the Query; so we need to call it with sublevels_up == 1.
3147
 */
3148
static Query *
3149
pullup_replace_vars_subquery(Query *query,
3150
               pullup_replace_vars_context *context)
3151
0
{
3152
0
  Assert(IsA(query, Query));
3153
0
  return (Query *) replace_rte_variables((Node *) query,
3154
0
                       context->varno, 1,
3155
0
                       pullup_replace_vars_callback,
3156
0
                       context,
3157
0
                       NULL);
3158
0
}
3159
3160
3161
/*
3162
 * flatten_simple_union_all
3163
 *    Try to optimize top-level UNION ALL structure into an appendrel
3164
 *
3165
 * If a query's setOperations tree consists entirely of simple UNION ALL
3166
 * operations, flatten it into an append relation, which we can process more
3167
 * intelligently than the general setops case.  Otherwise, do nothing.
3168
 *
3169
 * In most cases, this can succeed only for a top-level query, because for a
3170
 * subquery in FROM, the parent query's invocation of pull_up_subqueries would
3171
 * already have flattened the UNION via pull_up_simple_union_all.  But there
3172
 * are a few cases we can support here but not in that code path, for example
3173
 * when the subquery also contains ORDER BY.
3174
 */
3175
void
3176
flatten_simple_union_all(PlannerInfo *root)
3177
0
{
3178
0
  Query    *parse = root->parse;
3179
0
  SetOperationStmt *topop;
3180
0
  Node     *leftmostjtnode;
3181
0
  int     leftmostRTI;
3182
0
  RangeTblEntry *leftmostRTE;
3183
0
  int     childRTI;
3184
0
  RangeTblEntry *childRTE;
3185
0
  RangeTblRef *rtr;
3186
3187
  /* Shouldn't be called unless query has setops */
3188
0
  topop = castNode(SetOperationStmt, parse->setOperations);
3189
0
  Assert(topop);
3190
3191
  /* Can't optimize away a recursive UNION */
3192
0
  if (root->hasRecursion)
3193
0
    return;
3194
3195
  /*
3196
   * Recursively check the tree of set operations.  If not all UNION ALL
3197
   * with identical column types, punt.
3198
   */
3199
0
  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
3200
0
    return;
3201
3202
  /*
3203
   * Locate the leftmost leaf query in the setops tree.  The upper query's
3204
   * Vars all refer to this RTE (see transformSetOperationStmt).
3205
   */
3206
0
  leftmostjtnode = topop->larg;
3207
0
  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
3208
0
    leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
3209
0
  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
3210
0
  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
3211
0
  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
3212
0
  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
3213
3214
  /*
3215
   * Make a copy of the leftmost RTE and add it to the rtable.  This copy
3216
   * will represent the leftmost leaf query in its capacity as a member of
3217
   * the appendrel.  The original will represent the appendrel as a whole.
3218
   * (We must do things this way because the upper query's Vars have to be
3219
   * seen as referring to the whole appendrel.)
3220
   */
3221
0
  childRTE = copyObject(leftmostRTE);
3222
0
  parse->rtable = lappend(parse->rtable, childRTE);
3223
0
  childRTI = list_length(parse->rtable);
3224
3225
  /* Modify the setops tree to reference the child copy */
3226
0
  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
3227
3228
  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
3229
0
  leftmostRTE->inh = true;
3230
3231
  /*
3232
   * Form a RangeTblRef for the appendrel, and insert it into FROM.  The top
3233
   * Query of a setops tree should have had an empty FromClause initially.
3234
   */
3235
0
  rtr = makeNode(RangeTblRef);
3236
0
  rtr->rtindex = leftmostRTI;
3237
0
  Assert(parse->jointree->fromlist == NIL);
3238
0
  parse->jointree->fromlist = list_make1(rtr);
3239
3240
  /*
3241
   * Now pretend the query has no setops.  We must do this before trying to
3242
   * do subquery pullup, because of Assert in pull_up_simple_subquery.
3243
   */
3244
0
  parse->setOperations = NULL;
3245
3246
  /*
3247
   * Build AppendRelInfo information, and apply pull_up_subqueries to the
3248
   * leaf queries of the UNION ALL.  (We must do that now because they
3249
   * weren't previously referenced by the jointree, and so were missed by
3250
   * the main invocation of pull_up_subqueries.)
3251
   */
3252
0
  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
3253
0
}
3254
3255
3256
/*
3257
 * reduce_outer_joins
3258
 *    Attempt to reduce outer joins to plain inner joins.
3259
 *
3260
 * The idea here is that given a query like
3261
 *    SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
3262
 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
3263
 * is strict.  The strict operator will always return NULL, causing the outer
3264
 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
3265
 * columns.  Therefore, there's no need for the join to produce null-extended
3266
 * rows in the first place --- which makes it a plain join not an outer join.
3267
 * (This scenario may not be very likely in a query written out by hand, but
3268
 * it's reasonably likely when pushing quals down into complex views.)
3269
 *
3270
 * More generally, an outer join can be reduced in strength if there is a
3271
 * strict qual above it in the qual tree that constrains a Var from the
3272
 * nullable side of the join to be non-null.  (For FULL joins this applies
3273
 * to each side separately.)
3274
 *
3275
 * Another transformation we apply here is to recognize cases like
3276
 *    SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.z IS NULL;
3277
 * If we can prove that b.z must be non-null for any matching row, because
3278
 * the join clause is strict for b.z and b.z happens to be the join key b.y,
3279
 * because a strict qual within b's own subtree forces b.z non-null, or
3280
 * because b.z is defined NOT NULL by table constraints and is not nullable
3281
 * due to lower-level outer joins, then only null-extended rows could pass
3282
 * the upper WHERE, and we can conclude that what the query is really
3283
 * specifying is an anti-semijoin.  We change the join type from JOIN_LEFT
3284
 * to JOIN_ANTI.  The IS NULL clause then becomes redundant, and is removed
3285
 * at the end of this phase; see remove_redundant_nullability_quals.
3286
 *
3287
 * A whole-row Var works too.  "WHERE b IS NULL" in row-format semantics is
3288
 * true when b's whole-row value is NULL or when every column of b is NULL;
3289
 * for a matching row only the latter is possible, so proving any one column
3290
 * of b non-null in matching rows justifies the same reduction.
3291
 *
3292
 * The same recognition reduces a FULL join to an anti-semijoin when a
3293
 * forced-null Var on either side is proven non-null: only the other side's
3294
 * unmatched rows can survive.  If that surviving side is the right-hand
3295
 * input, we switch the inputs (as we do for JOIN_RIGHT below) so that it
3296
 * ends up on the left, where JOIN_ANTI requires the surviving side to be.
3297
 *
3298
 * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
3299
 * JOIN_LEFT.  This saves some code here and in some later planner routines;
3300
 * the main benefit is to reduce the number of jointypes that can appear in
3301
 * SpecialJoinInfo nodes.  Note that we can still generate Paths and Plans
3302
 * that use JOIN_RIGHT (or JOIN_RIGHT_ANTI) by switching the inputs again.
3303
 *
3304
 * To ease recognition of strict qual clauses, we require this routine to be
3305
 * run after expression preprocessing (i.e., qual canonicalization and JOIN
3306
 * alias-var expansion).
3307
 */
3308
void
3309
reduce_outer_joins(PlannerInfo *root)
3310
0
{
3311
0
  reduce_outer_joins_pass1_state *state1;
3312
0
  reduce_outer_joins_pass2_state state2;
3313
0
  ListCell   *lc;
3314
3315
  /*
3316
   * To avoid doing strictness checks on more quals than necessary, we want
3317
   * to stop descending the jointree as soon as there are no outer joins
3318
   * below our current point.  This consideration forces a two-pass process.
3319
   * The first pass gathers information about which base rels appear below
3320
   * each side of each join clause, about whether there are outer join(s)
3321
   * below each side of each join clause, and about which base rels are from
3322
   * the nullable side of those outer join(s).  The second pass examines
3323
   * qual clauses and changes join types as it descends the tree.
3324
   */
3325
0
  state1 = reduce_outer_joins_pass1((Node *) root->parse->jointree);
3326
3327
  /* planner.c shouldn't have called me if no outer joins */
3328
0
  if (state1 == NULL || !state1->contains_outer)
3329
0
    elog(ERROR, "so where are the outer joins?");
3330
3331
0
  state2.inner_reduced = NULL;
3332
0
  state2.partial_reduced = NIL;
3333
0
  state2.anti_reduced = NULL;
3334
3335
0
  reduce_outer_joins_pass2((Node *) root->parse->jointree,
3336
0
               state1, &state2,
3337
0
               root, NULL, NIL);
3338
3339
  /*
3340
   * If we successfully reduced the strength of any outer joins, we must
3341
   * remove references to those joins as nulling rels.  This is handled as
3342
   * an additional pass, for simplicity and because we can handle all
3343
   * fully-reduced joins in a single pass over the parse tree.
3344
   */
3345
0
  if (!bms_is_empty(state2.inner_reduced))
3346
0
  {
3347
0
    root->parse = (Query *)
3348
0
      remove_nulling_relids((Node *) root->parse,
3349
0
                  state2.inner_reduced,
3350
0
                  NULL);
3351
    /* There could be references in the append_rel_list, too */
3352
0
    root->append_rel_list = (List *)
3353
0
      remove_nulling_relids((Node *) root->append_rel_list,
3354
0
                  state2.inner_reduced,
3355
0
                  NULL);
3356
0
  }
3357
3358
  /*
3359
   * Partially-reduced full joins have to be done one at a time, since
3360
   * they'll each need a different setting of except_relids.
3361
   */
3362
0
  foreach(lc, state2.partial_reduced)
3363
0
  {
3364
0
    reduce_outer_joins_partial_state *statep = lfirst(lc);
3365
0
    Relids    full_join_relids = bms_make_singleton(statep->full_join_rti);
3366
3367
0
    root->parse = (Query *)
3368
0
      remove_nulling_relids((Node *) root->parse,
3369
0
                  full_join_relids,
3370
0
                  statep->unreduced_side);
3371
0
    root->append_rel_list = (List *)
3372
0
      remove_nulling_relids((Node *) root->append_rel_list,
3373
0
                  full_join_relids,
3374
0
                  statep->unreduced_side);
3375
0
  }
3376
3377
  /*
3378
   * Finally, remove any quals made redundant by reducing outer joins to
3379
   * antijoins.
3380
   */
3381
0
  if (!bms_is_empty(state2.anti_reduced))
3382
0
    remove_redundant_nullability_quals((Node *) root->parse->jointree,
3383
0
                       state2.anti_reduced);
3384
0
}
3385
3386
/*
3387
 * remove_redundant_nullability_quals
3388
 *    Remove quals made redundant by reducing outer joins to antijoins.
3389
 *
3390
 * An IS NULL qual on a Var from the nullable side of a lower antijoin is
3391
 * necessarily true.  Keeping such a qual would not be wrong, but it would
3392
 * generate bogus selectivity estimates, and it could prevent join removal
3393
 * from later removing the rel(s) it references.
3394
 */
3395
static void
3396
remove_redundant_nullability_quals(Node *jtnode, Relids antijoins)
3397
0
{
3398
0
  if (jtnode == NULL)
3399
0
    return;
3400
0
  if (IsA(jtnode, RangeTblRef))
3401
0
  {
3402
    /* nothing to do here */
3403
0
  }
3404
0
  else if (IsA(jtnode, FromExpr))
3405
0
  {
3406
0
    FromExpr   *f = (FromExpr *) jtnode;
3407
0
    ListCell   *l;
3408
3409
0
    foreach(l, f->fromlist)
3410
0
      remove_redundant_nullability_quals(lfirst(l), antijoins);
3411
0
    f->quals = strip_redundant_nullability_quals(f->quals, antijoins);
3412
0
  }
3413
0
  else if (IsA(jtnode, JoinExpr))
3414
0
  {
3415
0
    JoinExpr   *j = (JoinExpr *) jtnode;
3416
3417
0
    remove_redundant_nullability_quals(j->larg, antijoins);
3418
0
    remove_redundant_nullability_quals(j->rarg, antijoins);
3419
0
    j->quals = strip_redundant_nullability_quals(j->quals, antijoins);
3420
0
  }
3421
0
  else
3422
0
    elog(ERROR, "unrecognized jointree node type: %d",
3423
0
       (int) nodeTag(jtnode));
3424
0
}
3425
3426
/*
3427
 * strip_redundant_nullability_quals
3428
 *    Strip redundant IS NULL quals from one implicit-AND qual list.
3429
 */
3430
static Node *
3431
strip_redundant_nullability_quals(Node *quals, Relids antijoins)
3432
0
{
3433
0
  List     *newquals = NIL;
3434
3435
0
  foreach_ptr(Node, clause, castNode(List, quals))
3436
0
  {
3437
0
    Var      *var = find_forced_null_var(clause);
3438
3439
0
    if (var && bms_overlap(var->varnullingrels, antijoins))
3440
0
      continue;
3441
0
    newquals = lappend(newquals, clause);
3442
0
  }
3443
0
  return (Node *) newquals;
3444
0
}
3445
3446
/*
3447
 * reduce_outer_joins_pass1 - phase 1 data collection
3448
 *
3449
 * Returns a state node describing the given jointree node.
3450
 */
3451
static reduce_outer_joins_pass1_state *
3452
reduce_outer_joins_pass1(Node *jtnode)
3453
0
{
3454
0
  reduce_outer_joins_pass1_state *result;
3455
3456
0
  result = palloc_object(reduce_outer_joins_pass1_state);
3457
0
  result->relids = NULL;
3458
0
  result->contains_outer = false;
3459
0
  result->nullable_rels = NULL;
3460
0
  result->jtnode = jtnode;
3461
0
  result->sub_states = NIL;
3462
3463
0
  if (jtnode == NULL)
3464
0
    return result;
3465
0
  if (IsA(jtnode, RangeTblRef))
3466
0
  {
3467
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
3468
3469
0
    result->relids = bms_make_singleton(varno);
3470
0
  }
3471
0
  else if (IsA(jtnode, FromExpr))
3472
0
  {
3473
0
    FromExpr   *f = (FromExpr *) jtnode;
3474
0
    ListCell   *l;
3475
3476
0
    foreach(l, f->fromlist)
3477
0
    {
3478
0
      reduce_outer_joins_pass1_state *sub_state;
3479
3480
0
      sub_state = reduce_outer_joins_pass1(lfirst(l));
3481
0
      result->relids = bms_add_members(result->relids,
3482
0
                       sub_state->relids);
3483
0
      result->contains_outer |= sub_state->contains_outer;
3484
0
      result->nullable_rels = bms_add_members(result->nullable_rels,
3485
0
                          sub_state->nullable_rels);
3486
0
      result->sub_states = lappend(result->sub_states, sub_state);
3487
0
    }
3488
0
  }
3489
0
  else if (IsA(jtnode, JoinExpr))
3490
0
  {
3491
0
    JoinExpr   *j = (JoinExpr *) jtnode;
3492
0
    reduce_outer_joins_pass1_state *left_state;
3493
0
    reduce_outer_joins_pass1_state *right_state;
3494
3495
    /* Recurse to children */
3496
0
    left_state = reduce_outer_joins_pass1(j->larg);
3497
0
    right_state = reduce_outer_joins_pass1(j->rarg);
3498
3499
    /* join's own RT index is not wanted in result->relids */
3500
0
    result->relids = bms_union(left_state->relids, right_state->relids);
3501
3502
    /* Store children's states for pass 2 */
3503
0
    result->sub_states = list_make2(left_state, right_state);
3504
3505
    /* Collect outer join information */
3506
0
    switch (j->jointype)
3507
0
    {
3508
0
      case JOIN_INNER:
3509
0
      case JOIN_SEMI:
3510
        /* No new nullability; propagate state from children */
3511
0
        result->contains_outer = left_state->contains_outer ||
3512
0
          right_state->contains_outer;
3513
0
        result->nullable_rels = bms_union(left_state->nullable_rels,
3514
0
                          right_state->nullable_rels);
3515
0
        break;
3516
0
      case JOIN_LEFT:
3517
0
      case JOIN_ANTI:
3518
        /* RHS is nullable; LHS keeps existing status */
3519
0
        result->contains_outer = true;
3520
0
        result->nullable_rels = bms_union(left_state->nullable_rels,
3521
0
                          right_state->relids);
3522
0
        break;
3523
0
      case JOIN_RIGHT:
3524
        /* LHS is nullable; RHS keeps existing status */
3525
0
        result->contains_outer = true;
3526
0
        result->nullable_rels = bms_union(left_state->relids,
3527
0
                          right_state->nullable_rels);
3528
0
        break;
3529
0
      case JOIN_FULL:
3530
        /* Both sides are nullable */
3531
0
        result->contains_outer = true;
3532
0
        result->nullable_rels = bms_union(left_state->relids,
3533
0
                          right_state->relids);
3534
0
        break;
3535
0
      default:
3536
0
        elog(ERROR, "unrecognized join type: %d",
3537
0
           (int) j->jointype);
3538
0
        break;
3539
0
    }
3540
0
  }
3541
0
  else
3542
0
    elog(ERROR, "unrecognized node type: %d",
3543
0
       (int) nodeTag(jtnode));
3544
0
  return result;
3545
0
}
3546
3547
/*
3548
 * reduce_outer_joins_pass2 - phase 2 processing
3549
 *
3550
 *  jtnode: current jointree node
3551
 *  state1: state data collected by phase 1 for this node
3552
 *  state2: where to accumulate info about successfully-reduced joins
3553
 *  root: toplevel planner state
3554
 *  nonnullable_rels: set of base relids forced non-null by upper quals
3555
 *  forced_null_vars: multibitmapset of Vars forced null by upper quals
3556
 *
3557
 * Returns info in state2 about outer joins that were successfully simplified.
3558
 * Joins that were fully reduced to inner joins are all added to
3559
 * state2->inner_reduced, and joins that became antijoins are all added to
3560
 * state2->anti_reduced.  If a full join is reduced to a left join or an
3561
 * antijoin, it also needs its own entry in state2->partial_reduced, since
3562
 * that will require custom processing to remove only the correct nullingrel
3563
 * markers.
3564
 */
3565
static void
3566
reduce_outer_joins_pass2(Node *jtnode,
3567
             reduce_outer_joins_pass1_state *state1,
3568
             reduce_outer_joins_pass2_state *state2,
3569
             PlannerInfo *root,
3570
             Relids nonnullable_rels,
3571
             List *forced_null_vars)
3572
0
{
3573
  /*
3574
   * pass 2 should never descend as far as an empty subnode or base rel,
3575
   * because it's only called on subtrees marked as contains_outer.
3576
   */
3577
0
  if (jtnode == NULL)
3578
0
    elog(ERROR, "reached empty jointree");
3579
0
  if (IsA(jtnode, RangeTblRef))
3580
0
    elog(ERROR, "reached base rel");
3581
0
  else if (IsA(jtnode, FromExpr))
3582
0
  {
3583
0
    FromExpr   *f = (FromExpr *) jtnode;
3584
0
    ListCell   *l;
3585
0
    ListCell   *s;
3586
0
    Relids    pass_nonnullable_rels;
3587
0
    List     *pass_forced_null_vars;
3588
3589
    /* Scan quals to see if we can add any constraints */
3590
0
    pass_nonnullable_rels = find_nonnullable_rels(f->quals);
3591
0
    pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
3592
0
                        nonnullable_rels);
3593
0
    pass_forced_null_vars = find_forced_null_vars(f->quals);
3594
0
    pass_forced_null_vars = mbms_add_members(pass_forced_null_vars,
3595
0
                         forced_null_vars);
3596
    /* And recurse --- but only into interesting subtrees */
3597
0
    Assert(list_length(f->fromlist) == list_length(state1->sub_states));
3598
0
    forboth(l, f->fromlist, s, state1->sub_states)
3599
0
    {
3600
0
      reduce_outer_joins_pass1_state *sub_state = lfirst(s);
3601
3602
0
      if (sub_state->contains_outer)
3603
0
        reduce_outer_joins_pass2(lfirst(l), sub_state,
3604
0
                     state2, root,
3605
0
                     pass_nonnullable_rels,
3606
0
                     pass_forced_null_vars);
3607
0
    }
3608
0
    bms_free(pass_nonnullable_rels);
3609
    /* can't so easily clean up var lists, unfortunately */
3610
0
  }
3611
0
  else if (IsA(jtnode, JoinExpr))
3612
0
  {
3613
0
    JoinExpr   *j = (JoinExpr *) jtnode;
3614
0
    int     rtindex = j->rtindex;
3615
0
    JoinType  jointype = j->jointype;
3616
0
    reduce_outer_joins_pass1_state *left_state = linitial(state1->sub_states);
3617
0
    reduce_outer_joins_pass1_state *right_state = lsecond(state1->sub_states);
3618
3619
    /* Can we simplify this join? */
3620
0
    switch (jointype)
3621
0
    {
3622
0
      case JOIN_INNER:
3623
0
        break;
3624
0
      case JOIN_LEFT:
3625
0
        if (bms_overlap(nonnullable_rels, right_state->relids))
3626
0
          jointype = JOIN_INNER;
3627
0
        break;
3628
0
      case JOIN_RIGHT:
3629
0
        if (bms_overlap(nonnullable_rels, left_state->relids))
3630
0
          jointype = JOIN_INNER;
3631
0
        break;
3632
0
      case JOIN_FULL:
3633
0
        if (bms_overlap(nonnullable_rels, left_state->relids))
3634
0
        {
3635
0
          if (bms_overlap(nonnullable_rels, right_state->relids))
3636
0
            jointype = JOIN_INNER;
3637
0
          else
3638
0
          {
3639
0
            jointype = JOIN_LEFT;
3640
            /* Also report partial reduction in state2 */
3641
0
            report_reduced_full_join(state2, rtindex,
3642
0
                         right_state->relids);
3643
0
          }
3644
0
        }
3645
0
        else if (bms_overlap(nonnullable_rels, right_state->relids))
3646
0
        {
3647
0
          jointype = JOIN_RIGHT;
3648
          /* Also report partial reduction in state2 */
3649
0
          report_reduced_full_join(state2, rtindex,
3650
0
                       left_state->relids);
3651
0
        }
3652
0
        else if (forced_null_vars != NIL)
3653
0
        {
3654
          /*
3655
           * Neither side is forced non-null by a strict upper qual,
3656
           * but an upper qual may force a Var on one side to be
3657
           * NULL while that Var is non-null in every row that side
3658
           * emits (proven by quals within the side's own subtree,
3659
           * or a NOT NULL constraint).  Then only rows where that
3660
           * side was null-extended can satisfy the upper qual: the
3661
           * matched rows and that side's unmatched rows all drop
3662
           * out, leaving an anti-join.
3663
           *
3664
           * Unlike the JOIN_LEFT case below, we must not consult
3665
           * the join's own ON quals here: they do not hold for the
3666
           * unmatched rows that this proof has to cover.
3667
           *
3668
           * If the constrained Var is on the RHS the result is a
3669
           * plain anti-join; if it is on the LHS it is a right
3670
           * anti-join, which the input-switching step below
3671
           * normalizes to a plain anti-join (just as it does for
3672
           * JOIN_RIGHT).
3673
           */
3674
0
          if (forced_null_var_is_nonnullable(root,
3675
0
                             forced_null_vars,
3676
0
                             right_state, NIL))
3677
0
          {
3678
0
            jointype = JOIN_ANTI;
3679
0
            report_reduced_full_join(state2, rtindex,
3680
0
                         right_state->relids);
3681
0
          }
3682
0
          else if (forced_null_var_is_nonnullable(root,
3683
0
                              forced_null_vars,
3684
0
                              left_state, NIL))
3685
0
          {
3686
0
            jointype = JOIN_RIGHT_ANTI;
3687
0
            report_reduced_full_join(state2, rtindex,
3688
0
                         left_state->relids);
3689
0
          }
3690
0
        }
3691
0
        break;
3692
0
      case JOIN_SEMI:
3693
0
      case JOIN_ANTI:
3694
3695
        /*
3696
         * These could only have been introduced by pull_up_sublinks,
3697
         * so there's no way that upper quals could refer to their
3698
         * righthand sides, and no point in checking.  We don't expect
3699
         * a JOIN_RIGHT_SEMI or JOIN_RIGHT_ANTI input here; the
3700
         * JOIN_FULL case above produces JOIN_RIGHT_ANTI only as a
3701
         * transient, which is converted to JOIN_ANTI below.
3702
         */
3703
0
        break;
3704
0
      default:
3705
0
        elog(ERROR, "unrecognized join type: %d",
3706
0
           (int) jointype);
3707
0
        break;
3708
0
    }
3709
3710
    /*
3711
     * Convert JOIN_RIGHT to JOIN_LEFT, and likewise the JOIN_RIGHT_ANTI
3712
     * that the JOIN_FULL arm may have produced just above to JOIN_ANTI,
3713
     * by switching the inputs.  Note that in the case where we reduced
3714
     * JOIN_FULL this way, this will mean the JoinExpr no longer matches
3715
     * the internal ordering of any CoalesceExpr's built to represent
3716
     * merged join variables.  We don't care about that at present, but be
3717
     * wary of it ...
3718
     */
3719
0
    if (jointype == JOIN_RIGHT || jointype == JOIN_RIGHT_ANTI)
3720
0
    {
3721
0
      Node     *tmparg;
3722
3723
0
      tmparg = j->larg;
3724
0
      j->larg = j->rarg;
3725
0
      j->rarg = tmparg;
3726
0
      jointype = (jointype == JOIN_RIGHT) ? JOIN_LEFT : JOIN_ANTI;
3727
0
      right_state = linitial(state1->sub_states);
3728
0
      left_state = lsecond(state1->sub_states);
3729
0
    }
3730
3731
    /*
3732
     * See if we can reduce JOIN_LEFT to JOIN_ANTI.  This is the case if
3733
     * any var from the RHS was forced null by higher qual levels, but is
3734
     * known to be non-nullable in any matching row.  We can prove that in
3735
     * any of these ways: the join's own quals are strict for the var;
3736
     * strict quals applied within the RHS subtree prove it; or the var is
3737
     * defined NOT NULL by table constraints (being careful to exclude
3738
     * vars that are nullable due to lower-level outer joins).  In each
3739
     * such case, the only way the higher qual clause's requirement for
3740
     * NULL can be met is if the join fails to match, producing a
3741
     * null-extended row.  Thus, we can treat this as an anti-join.
3742
     */
3743
0
    if (jointype == JOIN_LEFT && forced_null_vars != NIL)
3744
0
    {
3745
      /*
3746
       * A forced-null RHS Var that is proven non-null can be NULL here
3747
       * only by null-extension.  That makes this an anti-join.
3748
       */
3749
0
      if (forced_null_var_is_nonnullable(root, forced_null_vars,
3750
0
                         right_state, (List *) j->quals))
3751
0
        jointype = JOIN_ANTI;
3752
0
    }
3753
3754
    /*
3755
     * Apply the jointype change, if any, to both jointree node and RTE.
3756
     * Also, if we changed an RTE to INNER, add its RTI to inner_reduced;
3757
     * if we changed it to ANTI, add its RTI to anti_reduced.
3758
     */
3759
0
    if (rtindex && jointype != j->jointype)
3760
0
    {
3761
0
      RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
3762
3763
0
      Assert(rte->rtekind == RTE_JOIN);
3764
0
      Assert(rte->jointype == j->jointype);
3765
0
      rte->jointype = jointype;
3766
0
      if (jointype == JOIN_INNER)
3767
0
        state2->inner_reduced = bms_add_member(state2->inner_reduced,
3768
0
                             rtindex);
3769
0
      else if (jointype == JOIN_ANTI)
3770
0
        state2->anti_reduced = bms_add_member(state2->anti_reduced,
3771
0
                            rtindex);
3772
0
    }
3773
0
    j->jointype = jointype;
3774
3775
    /* Only recurse if there's more to do below here */
3776
0
    if (left_state->contains_outer || right_state->contains_outer)
3777
0
    {
3778
0
      Relids    local_nonnullable_rels;
3779
0
      List     *local_forced_null_vars;
3780
0
      Relids    pass_nonnullable_rels;
3781
0
      List     *pass_forced_null_vars;
3782
3783
      /*
3784
       * If this join is (now) inner, we can add any constraints its
3785
       * quals provide to those we got from above.  But if it is outer,
3786
       * we can pass down the local constraints only into the nullable
3787
       * side, because an outer join never eliminates any rows from its
3788
       * non-nullable side.  Also, there is no point in passing upper
3789
       * constraints into the nullable side, since if there were any
3790
       * we'd have been able to reduce the join.  (In the case of upper
3791
       * forced-null constraints, we *must not* pass them into the
3792
       * nullable side --- they either applied here, or not.) The upshot
3793
       * is that we pass either the local or the upper constraints,
3794
       * never both, to the children of an outer join.
3795
       *
3796
       * Note that a SEMI join works like an inner join here: it's okay
3797
       * to pass down both local and upper constraints.  (There can't be
3798
       * any upper constraints affecting its inner side, but it's not
3799
       * worth having a separate code path to avoid passing them.)
3800
       *
3801
       * At a FULL join we just punt and pass nothing down --- is it
3802
       * possible to be smarter?
3803
       */
3804
0
      if (jointype != JOIN_FULL)
3805
0
      {
3806
0
        local_nonnullable_rels = find_nonnullable_rels(j->quals);
3807
0
        local_forced_null_vars = find_forced_null_vars(j->quals);
3808
0
        if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3809
0
        {
3810
          /* OK to merge upper and local constraints */
3811
0
          local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
3812
0
                               nonnullable_rels);
3813
0
          local_forced_null_vars = mbms_add_members(local_forced_null_vars,
3814
0
                                forced_null_vars);
3815
0
        }
3816
0
      }
3817
0
      else
3818
0
      {
3819
        /* no use in calculating these */
3820
0
        local_nonnullable_rels = NULL;
3821
0
        local_forced_null_vars = NIL;
3822
0
      }
3823
3824
0
      if (left_state->contains_outer)
3825
0
      {
3826
0
        if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3827
0
        {
3828
          /* pass union of local and upper constraints */
3829
0
          pass_nonnullable_rels = local_nonnullable_rels;
3830
0
          pass_forced_null_vars = local_forced_null_vars;
3831
0
        }
3832
0
        else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
3833
0
        {
3834
          /* can't pass local constraints to non-nullable side */
3835
0
          pass_nonnullable_rels = nonnullable_rels;
3836
0
          pass_forced_null_vars = forced_null_vars;
3837
0
        }
3838
0
        else
3839
0
        {
3840
          /* no constraints pass through JOIN_FULL */
3841
0
          pass_nonnullable_rels = NULL;
3842
0
          pass_forced_null_vars = NIL;
3843
0
        }
3844
0
        reduce_outer_joins_pass2(j->larg, left_state,
3845
0
                     state2, root,
3846
0
                     pass_nonnullable_rels,
3847
0
                     pass_forced_null_vars);
3848
0
      }
3849
3850
0
      if (right_state->contains_outer)
3851
0
      {
3852
0
        if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
3853
0
        {
3854
          /* pass appropriate constraints, per comment above */
3855
0
          pass_nonnullable_rels = local_nonnullable_rels;
3856
0
          pass_forced_null_vars = local_forced_null_vars;
3857
0
        }
3858
0
        else
3859
0
        {
3860
          /* no constraints pass through JOIN_FULL */
3861
0
          pass_nonnullable_rels = NULL;
3862
0
          pass_forced_null_vars = NIL;
3863
0
        }
3864
0
        reduce_outer_joins_pass2(j->rarg, right_state,
3865
0
                     state2, root,
3866
0
                     pass_nonnullable_rels,
3867
0
                     pass_forced_null_vars);
3868
0
      }
3869
0
      bms_free(local_nonnullable_rels);
3870
0
    }
3871
0
  }
3872
0
  else
3873
0
    elog(ERROR, "unrecognized node type: %d",
3874
0
       (int) nodeTag(jtnode));
3875
0
}
3876
3877
/* Helper for reduce_outer_joins_pass2 */
3878
static void
3879
report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
3880
             int rtindex, Relids relids)
3881
0
{
3882
0
  reduce_outer_joins_partial_state *statep;
3883
3884
0
  statep = palloc_object(reduce_outer_joins_partial_state);
3885
0
  statep->full_join_rti = rtindex;
3886
0
  statep->unreduced_side = relids;
3887
0
  state2->partial_reduced = lappend(state2->partial_reduced, statep);
3888
0
}
3889
3890
/*
3891
 * forced_null_var_is_attnotnull
3892
 *    Check if "forced_null_vars" contains any Vars belonging to the subtree
3893
 *    indicated by "state" that are known to be non-nullable due to table
3894
 *    constraints.
3895
 *
3896
 * A whole-row Var, in any matching row, requires every column of its relation
3897
 * to be NULL, so any NOT NULL column of the relation refutes it.
3898
 *
3899
 * Note that we must also consider the situation where a NOT NULL Var can be
3900
 * nulled by lower-level outer joins.
3901
 *
3902
 * Helper for reduce_outer_joins_pass2.
3903
 */
3904
static bool
3905
forced_null_var_is_attnotnull(PlannerInfo *root, List *forced_null_vars,
3906
                reduce_outer_joins_pass1_state *state)
3907
0
{
3908
0
  int     varno = -1;
3909
3910
0
  foreach_node(Bitmapset, attrs, forced_null_vars)
3911
0
  {
3912
0
    RangeTblEntry *rte;
3913
0
    Bitmapset  *notnullattnums;
3914
0
    Bitmapset  *forcednullattnums;
3915
0
    bool    wholerow = false;
3916
0
    int     lowest_attno;
3917
3918
0
    varno++;
3919
3920
    /* Skip empty bitmaps */
3921
0
    if (bms_is_empty(attrs))
3922
0
      continue;
3923
3924
    /* Skip Vars that do not belong to the target relations */
3925
0
    if (!bms_is_member(varno, state->relids))
3926
0
      continue;
3927
3928
    /*
3929
     * Skip Vars that can be nulled by lower-level outer joins within the
3930
     * given subtree.  These Vars might be NULL even if the schema defines
3931
     * them as NOT NULL.
3932
     */
3933
0
    if (bms_is_member(varno, state->nullable_rels))
3934
0
      continue;
3935
3936
    /* find the lowest member to check if system columns are present */
3937
0
    lowest_attno = bms_next_member(attrs, -1);
3938
3939
    /* we checked for an empty set above */
3940
0
    Assert(lowest_attno >= 0);
3941
3942
    /* system columns cannot be NULL */
3943
0
    if (lowest_attno + FirstLowInvalidHeapAttributeNumber < 0)
3944
0
      return true;
3945
3946
    /* attno 0 is a whole-row Var, which forces every column null */
3947
0
    if (lowest_attno + FirstLowInvalidHeapAttributeNumber == 0)
3948
0
      wholerow = true;
3949
3950
0
    rte = rt_fetch(varno, root->parse->rtable);
3951
3952
    /* We can only reason about ordinary relations */
3953
0
    if (rte->rtekind != RTE_RELATION)
3954
0
      continue;
3955
3956
    /*
3957
     * We must skip inheritance parent tables, as some child tables may
3958
     * have a NOT NULL constraint for a column while others may not.  This
3959
     * cannot happen with partitioned tables, though.
3960
     */
3961
0
    if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
3962
0
      continue;
3963
3964
    /* Get the column not-null constraint information for this relation */
3965
0
    notnullattnums = find_relation_notnullatts(root, rte->relid);
3966
3967
    /*
3968
     * A forced-null whole-row Var, in any matching row, requires every
3969
     * column of the relation to be NULL, so any NOT NULL column refutes
3970
     * it.
3971
     */
3972
0
    if (wholerow && !bms_is_empty(notnullattnums))
3973
0
      return true;
3974
3975
    /*
3976
     * Offset the bitmap members by FirstLowInvalidHeapAttributeNumber to
3977
     * get the actual attribute numbers.
3978
     */
3979
0
    forcednullattnums = bms_offset_members(attrs,
3980
0
                         FirstLowInvalidHeapAttributeNumber);
3981
3982
    /*
3983
     * Check if any forced-null attributes are defined as NOT NULL by
3984
     * table constraints.
3985
     */
3986
0
    if (bms_overlap(notnullattnums, forcednullattnums))
3987
0
    {
3988
0
      bms_free(forcednullattnums);
3989
0
      return true;
3990
0
    }
3991
3992
0
    bms_free(forcednullattnums);
3993
0
  }
3994
3995
0
  return false;
3996
0
}
3997
3998
/*
3999
 * forced_null_var_is_nonnullable
4000
 *    Detect whether some Var that "forced_null_vars" requires to be NULL is
4001
 *    actually non-nullable in every row that the given subtree emits.
4002
 *
4003
 * We prove non-nullness from quals that hold for every such row: the subtree's
4004
 * safe quals, plus any "extra_quals" the caller knows also constrain the Var,
4005
 * or a NOT NULL table constraint (excluding Vars nullable due to lower-level
4006
 * outer joins).
4007
 *
4008
 * A whole-row Var in "forced_null_vars" requires, in any matching row, every
4009
 * column of its relation to be NULL, so it is refuted by proving any one of
4010
 * those columns non-null.
4011
 *
4012
 * Helper for reduce_outer_joins_pass2.
4013
 */
4014
static bool
4015
forced_null_var_is_nonnullable(PlannerInfo *root, List *forced_null_vars,
4016
                 reduce_outer_joins_pass1_state *state,
4017
                 List *extra_quals)
4018
0
{
4019
0
  List     *all_quals = NIL;
4020
0
  List     *nonnullable_vars;
4021
0
  int     wholerow_attno = 0 - FirstLowInvalidHeapAttributeNumber;
4022
0
  int     varno = -1;
4023
4024
0
  find_safe_quals(state->jtnode, &all_quals);
4025
0
  all_quals = list_concat(all_quals, extra_quals);
4026
0
  nonnullable_vars = find_nonnullable_vars((Node *) all_quals);
4027
4028
  /*
4029
   * It's not sufficient to consider all matches between nonnullable_vars
4030
   * and forced_null_vars: a match counts only for a Var belonging to this
4031
   * subtree, and the whole-row attribute needs special treatment.
4032
   */
4033
0
  foreach_node(Bitmapset, attrs, forced_null_vars)
4034
0
  {
4035
0
    Bitmapset  *nonnull_attrs;
4036
4037
0
    varno++;
4038
4039
    /* Beyond the end of nonnullable_vars there is nothing left to prove */
4040
0
    if (varno >= list_length(nonnullable_vars))
4041
0
      break;
4042
4043
    /* Skip empty bitmaps */
4044
0
    if (bms_is_empty(attrs))
4045
0
      continue;
4046
4047
    /* Skip Vars that do not belong to the target relations */
4048
0
    if (!bms_is_member(varno, state->relids))
4049
0
      continue;
4050
4051
    /* Get what the quals prove non-null for this relation, if anything */
4052
0
    nonnull_attrs = list_nth_node(Bitmapset, nonnullable_vars, varno);
4053
4054
    /*
4055
     * A proof for the whole-row attribute refutes nothing: it shows only
4056
     * that the composite datum is non-null, and such a datum can still
4057
     * have all columns NULL.  Discard it up front.
4058
     */
4059
0
    nonnull_attrs = bms_del_member(nonnull_attrs, wholerow_attno);
4060
4061
    /* A forced-null attribute that is proven non-null settles it. */
4062
0
    if (bms_overlap(attrs, nonnull_attrs))
4063
0
      return true;
4064
4065
    /*
4066
     * So does any real column proven non-null, if the whole-row Var is
4067
     * forced null: in a matching row (whose whole-row datum is non-null)
4068
     * the row-format IS NULL test is true only when every column is NULL.
4069
     * System attributes don't count, since they are not part of the row
4070
     * value; conveniently they sort below the whole-row attribute in the
4071
     * bitmap.
4072
     */
4073
0
    if (bms_is_member(wholerow_attno, attrs) &&
4074
0
      bms_next_member(nonnull_attrs, wholerow_attno) >= 0)
4075
0
      return true;
4076
0
  }
4077
4078
  /*
4079
   * Otherwise, check if any forced-null var is defined NOT NULL by table
4080
   * constraints.
4081
   */
4082
0
  return forced_null_var_is_attnotnull(root, forced_null_vars, state);
4083
0
}
4084
4085
4086
/*
4087
 * remove_useless_result_rtes
4088
 *    Attempt to remove RTE_RESULT RTEs from the join tree.
4089
 *    Also, elide single-child FromExprs where possible.
4090
 *
4091
 * We can remove RTE_RESULT entries from the join tree using the knowledge
4092
 * that RTE_RESULT returns exactly one row and has no output columns.  Hence,
4093
 * if one is inner-joined to anything else, we can delete it.  Optimizations
4094
 * are also possible for some outer-join cases, as detailed below.
4095
 *
4096
 * This pass also replaces single-child FromExprs with their child node
4097
 * where possible.  It's appropriate to do that here and not earlier because
4098
 * RTE_RESULT removal might reduce a multiple-child FromExpr to have only one
4099
 * child.  We can remove such a FromExpr if its quals are empty, or if it's
4100
 * semantically valid to merge the quals into those of the parent node.
4101
 * While removing unnecessary join tree nodes has some micro-efficiency value,
4102
 * the real reason to do this is to eliminate cases where the nullable side of
4103
 * an outer join node is a FromExpr whose single child is another outer join.
4104
 * To correctly determine whether the two outer joins can commute,
4105
 * deconstruct_jointree() must treat any quals of such a FromExpr as being
4106
 * degenerate quals of the upper outer join.  The best way to do that is to
4107
 * make them actually *be* quals of the upper join, by dropping the FromExpr
4108
 * and hoisting the quals up into the upper join's quals.  (Note that there is
4109
 * no hazard when the intermediate FromExpr has multiple children, since then
4110
 * it represents an inner join that cannot commute with the upper outer join.)
4111
 * As long as we have to do that, we might as well elide such FromExprs
4112
 * everywhere.
4113
 *
4114
 * Some of these optimizations depend on recognizing empty (constant-true)
4115
 * quals for FromExprs and JoinExprs.  That makes it useful to apply this
4116
 * optimization pass after expression preprocessing, since that will have
4117
 * eliminated constant-true quals, allowing more cases to be recognized as
4118
 * optimizable.  What's more, the usual reason for an RTE_RESULT to be present
4119
 * is that we pulled up a subquery or VALUES clause, thus very possibly
4120
 * replacing Vars with constants, making it more likely that a qual can be
4121
 * reduced to constant true.  Also, because some optimizations depend on
4122
 * the outer-join type, it's best to have done reduce_outer_joins() first.
4123
 *
4124
 * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
4125
 * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
4126
 * we must not reduce the phrels set to empty.  If that would happen, and
4127
 * the RTE_RESULT is an immediate child of an outer join, we have to give up
4128
 * and not remove the RTE_RESULT: there is noplace else to evaluate the
4129
 * PlaceHolderVar.  (That is, in such cases the RTE_RESULT *does* have output
4130
 * columns.)  But if the RTE_RESULT is an immediate child of an inner join,
4131
 * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
4132
 * the inner join instead.  This is OK because we really only care that PHVs
4133
 * are evaluated above or below the correct outer joins.  We can't, however,
4134
 * postpone the evaluation of a PHV to above where it is used; so there are
4135
 * some checks below on whether output PHVs are laterally referenced in the
4136
 * other join input rel(s).
4137
 *
4138
 * We used to try to do this work as part of pull_up_subqueries() where the
4139
 * potentially-optimizable cases get introduced; but it's way simpler, and
4140
 * more effective, to do it separately.
4141
 */
4142
void
4143
remove_useless_result_rtes(PlannerInfo *root)
4144
0
{
4145
0
  Relids    baserels = NULL;
4146
0
  Relids    dropped_outer_joins = NULL;
4147
0
  ListCell   *cell;
4148
4149
  /*
4150
   * We'll need the set of baserels in the jointree to perform
4151
   * find_dependent_phvs() checks.  But if there are no PHVs anywhere in the
4152
   * query, those checks are no-ops, so we can skip the work.
4153
   */
4154
0
  if (root->glob->lastPHId != 0)
4155
0
    baserels = get_relids_in_jointree((Node *) root->parse->jointree,
4156
0
                      false, false);
4157
4158
  /* Top level of jointree must always be a FromExpr */
4159
0
  Assert(IsA(root->parse->jointree, FromExpr));
4160
  /* Recurse ... */
4161
0
  root->parse->jointree = (FromExpr *)
4162
0
    remove_useless_results_recurse(root,
4163
0
                     (Node *) root->parse->jointree,
4164
0
                     baserels,
4165
0
                     NULL,
4166
0
                     &dropped_outer_joins);
4167
  /* We should still have a FromExpr */
4168
0
  Assert(IsA(root->parse->jointree, FromExpr));
4169
4170
  /*
4171
   * If we removed any outer-join nodes from the jointree, run around and
4172
   * remove references to those joins as nulling rels.  (There could be such
4173
   * references in PHVs that we pulled up out of the original subquery that
4174
   * the RESULT rel replaced.  This is kosher on the grounds that we now
4175
   * know that such an outer join wouldn't really have nulled anything.)  We
4176
   * don't do this during the main recursion, for simplicity and because we
4177
   * can handle all such joins in a single pass over the parse tree.
4178
   */
4179
0
  if (!bms_is_empty(dropped_outer_joins))
4180
0
  {
4181
0
    root->parse = (Query *)
4182
0
      remove_nulling_relids((Node *) root->parse,
4183
0
                  dropped_outer_joins,
4184
0
                  NULL);
4185
    /* There could be references in the append_rel_list, too */
4186
0
    root->append_rel_list = (List *)
4187
0
      remove_nulling_relids((Node *) root->append_rel_list,
4188
0
                  dropped_outer_joins,
4189
0
                  NULL);
4190
0
  }
4191
4192
  /*
4193
   * Remove any PlanRowMark referencing an RTE_RESULT RTE.  We obviously
4194
   * must do that for any RTE_RESULT that we just removed.  But one for a
4195
   * RTE that we did not remove can be dropped anyway: since the RTE has
4196
   * only one possible output row, there is no need for EPQ to mark and
4197
   * restore that row.
4198
   *
4199
   * It's necessary, not optional, to remove the PlanRowMark for a surviving
4200
   * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
4201
   * RTE_RESULT, which the executor has no support for.
4202
   */
4203
0
  foreach(cell, root->rowMarks)
4204
0
  {
4205
0
    PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
4206
4207
0
    if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
4208
0
      root->rowMarks = foreach_delete_current(root->rowMarks, cell);
4209
0
  }
4210
0
}
4211
4212
/*
4213
 * remove_useless_results_recurse
4214
 *    Recursive guts of remove_useless_result_rtes.
4215
 *
4216
 * This recursively processes the jointree and returns a modified jointree.
4217
 * In addition, the RT indexes of any removed outer-join nodes are added to
4218
 * *dropped_outer_joins.
4219
 *
4220
 * jtnode is the current jointree node.  If it could be valid to merge
4221
 * its quals into those of the parent node, parent_quals should point to
4222
 * the parent's quals list; otherwise, pass NULL for parent_quals.
4223
 * (Note that in some cases, parent_quals points to the quals of a parent
4224
 * more than one level up in the tree.)
4225
 *
4226
 * baserels is the set of base (non-join) RT indexes in the whole jointree;
4227
 * it can be NULL if the query contains no PHVs.
4228
 */
4229
static Node *
4230
remove_useless_results_recurse(PlannerInfo *root, Node *jtnode,
4231
                 Relids baserels,
4232
                 Node **parent_quals,
4233
                 Relids *dropped_outer_joins)
4234
0
{
4235
0
  Assert(jtnode != NULL);
4236
0
  if (IsA(jtnode, RangeTblRef))
4237
0
  {
4238
    /* Can't immediately do anything with a RangeTblRef */
4239
0
  }
4240
0
  else if (IsA(jtnode, FromExpr))
4241
0
  {
4242
0
    FromExpr   *f = (FromExpr *) jtnode;
4243
0
    Relids    result_relids = NULL;
4244
0
    ListCell   *cell;
4245
4246
    /*
4247
     * We can drop RTE_RESULT rels from the fromlist so long as at least
4248
     * one child remains, since joining to a one-row table changes
4249
     * nothing.  (But we can't drop a RTE_RESULT that computes PHV(s) that
4250
     * are needed by some sibling.  The cleanup transformation below would
4251
     * reassign the PHVs to be computed at the join, which is too late for
4252
     * the sibling's use.)  The easiest way to mechanize this rule is to
4253
     * modify the list in-place.
4254
     */
4255
0
    foreach(cell, f->fromlist)
4256
0
    {
4257
0
      Node     *child = (Node *) lfirst(cell);
4258
0
      int     varno;
4259
4260
      /* Recursively transform child, allowing it to push up quals ... */
4261
0
      child = remove_useless_results_recurse(root, child,
4262
0
                           baserels,
4263
0
                           &f->quals,
4264
0
                           dropped_outer_joins);
4265
      /* ... and stick it back into the tree */
4266
0
      lfirst(cell) = child;
4267
4268
      /*
4269
       * If it's an RTE_RESULT with at least one sibling, and no sibling
4270
       * references dependent PHVs, we can drop it.  We don't yet know
4271
       * what the inner join's final relid set will be, so postpone
4272
       * cleanup of PHVs etc till after this loop.
4273
       */
4274
0
      if (list_length(f->fromlist) > 1 &&
4275
0
        (varno = get_result_relid(root, child)) != 0 &&
4276
0
        !find_dependent_phvs_in_jointree(root, (Node *) f, varno,
4277
0
                         baserels))
4278
0
      {
4279
0
        f->fromlist = foreach_delete_current(f->fromlist, cell);
4280
0
        result_relids = bms_add_member(result_relids, varno);
4281
0
      }
4282
0
    }
4283
4284
    /*
4285
     * Clean up if we dropped any RTE_RESULT RTEs.  This is a bit
4286
     * inefficient if there's more than one, but it seems better to
4287
     * optimize the support code for the single-relid case.
4288
     */
4289
0
    if (result_relids)
4290
0
    {
4291
0
      int     varno = -1;
4292
4293
0
      while ((varno = bms_next_member(result_relids, varno)) >= 0)
4294
0
        remove_result_refs(root, varno, (Node *) f);
4295
0
    }
4296
4297
    /*
4298
     * If the FromExpr now has only one child, see if we can elide it.
4299
     * This is always valid if there are no quals, except at the top of
4300
     * the jointree (since Query.jointree is required to point to a
4301
     * FromExpr).  Otherwise, we can do it if we can push the quals up to
4302
     * the parent node.
4303
     *
4304
     * Note: while it would not be terribly hard to generalize this
4305
     * transformation to merge multi-child FromExprs into their parent
4306
     * FromExpr, that risks making the parent join too expensive to plan.
4307
     * We leave it to later processing to decide heuristically whether
4308
     * that's a good idea.  Pulling up a single child is always OK,
4309
     * however.
4310
     */
4311
0
    if (list_length(f->fromlist) == 1 &&
4312
0
      f != root->parse->jointree &&
4313
0
      (f->quals == NULL || parent_quals != NULL))
4314
0
    {
4315
      /*
4316
       * Merge any quals up to parent.  They should be in implicit-AND
4317
       * format by now, so we just need to concatenate lists.  Put the
4318
       * child quals at the front, on the grounds that they should
4319
       * nominally be evaluated earlier.
4320
       */
4321
0
      if (f->quals != NULL)
4322
0
        *parent_quals = (Node *)
4323
0
          list_concat(castNode(List, f->quals),
4324
0
                castNode(List, *parent_quals));
4325
0
      return (Node *) linitial(f->fromlist);
4326
0
    }
4327
0
  }
4328
0
  else if (IsA(jtnode, JoinExpr))
4329
0
  {
4330
0
    JoinExpr   *j = (JoinExpr *) jtnode;
4331
0
    int     varno;
4332
4333
    /*
4334
     * First, recurse.  We can absorb pushed-up FromExpr quals from either
4335
     * child into this node if the jointype is INNER, since then this is
4336
     * equivalent to a FromExpr.  When the jointype is LEFT, we can absorb
4337
     * quals from the RHS child into the current node, as they're
4338
     * essentially degenerate quals of the outer join.  Moreover, if we've
4339
     * been passed down a parent_quals pointer then we can allow quals of
4340
     * the LHS child to be absorbed into the parent.  (This is important
4341
     * to ensure we remove single-child FromExprs immediately below
4342
     * commutable left joins.)  For other jointypes, we can't move child
4343
     * quals up, or at least there's no particular reason to.
4344
     */
4345
0
    j->larg = remove_useless_results_recurse(root, j->larg,
4346
0
                         baserels,
4347
0
                         (j->jointype == JOIN_INNER) ?
4348
0
                         &j->quals :
4349
0
                         (j->jointype == JOIN_LEFT) ?
4350
0
                         parent_quals : NULL,
4351
0
                         dropped_outer_joins);
4352
0
    j->rarg = remove_useless_results_recurse(root, j->rarg,
4353
0
                         baserels,
4354
0
                         (j->jointype == JOIN_INNER ||
4355
0
                          j->jointype == JOIN_LEFT) ?
4356
0
                         &j->quals : NULL,
4357
0
                         dropped_outer_joins);
4358
4359
    /* Apply join-type-specific optimization rules */
4360
0
    switch (j->jointype)
4361
0
    {
4362
0
      case JOIN_INNER:
4363
4364
        /*
4365
         * An inner join is equivalent to a FromExpr, so if either
4366
         * side was simplified to an RTE_RESULT rel, we can replace
4367
         * the join with a FromExpr with just the other side.
4368
         * Furthermore, we can elide that FromExpr according to the
4369
         * same rules as above.
4370
         *
4371
         * Just as in the FromExpr case, we can't simplify if the
4372
         * other input rel references any PHVs that are marked as to
4373
         * be evaluated at the RTE_RESULT rel, because we can't
4374
         * postpone their evaluation in that case.  But we only have
4375
         * to check this in cases where it's syntactically legal for
4376
         * the other input to have a LATERAL reference to the
4377
         * RTE_RESULT rel.  Only RHSes of inner and left joins are
4378
         * allowed to have such refs.
4379
         */
4380
0
        if ((varno = get_result_relid(root, j->larg)) != 0 &&
4381
0
          !find_dependent_phvs_in_jointree(root, j->rarg, varno,
4382
0
                           baserels))
4383
0
        {
4384
0
          remove_result_refs(root, varno, j->rarg);
4385
0
          if (j->quals != NULL && parent_quals == NULL)
4386
0
            jtnode = (Node *)
4387
0
              makeFromExpr(list_make1(j->rarg), j->quals);
4388
0
          else
4389
0
          {
4390
            /* Merge any quals up to parent */
4391
0
            if (j->quals != NULL)
4392
0
              *parent_quals = (Node *)
4393
0
                list_concat(castNode(List, j->quals),
4394
0
                      castNode(List, *parent_quals));
4395
0
            jtnode = j->rarg;
4396
0
          }
4397
0
        }
4398
0
        else if ((varno = get_result_relid(root, j->rarg)) != 0)
4399
0
        {
4400
0
          remove_result_refs(root, varno, j->larg);
4401
0
          if (j->quals != NULL && parent_quals == NULL)
4402
0
            jtnode = (Node *)
4403
0
              makeFromExpr(list_make1(j->larg), j->quals);
4404
0
          else
4405
0
          {
4406
            /* Merge any quals up to parent */
4407
0
            if (j->quals != NULL)
4408
0
              *parent_quals = (Node *)
4409
0
                list_concat(castNode(List, j->quals),
4410
0
                      castNode(List, *parent_quals));
4411
0
            jtnode = j->larg;
4412
0
          }
4413
0
        }
4414
0
        break;
4415
0
      case JOIN_LEFT:
4416
4417
        /*
4418
         * We can simplify this case if the RHS is an RTE_RESULT, with
4419
         * two different possibilities:
4420
         *
4421
         * If the qual is empty (JOIN ON TRUE), then the join can be
4422
         * strength-reduced to a plain inner join, since each LHS row
4423
         * necessarily has exactly one join partner.  So we can always
4424
         * discard the RHS, much as in the JOIN_INNER case above.
4425
         * (Again, the LHS could not contain a lateral reference to
4426
         * the RHS.)
4427
         *
4428
         * Otherwise, it's still true that each LHS row should be
4429
         * returned exactly once, and since the RHS returns no columns
4430
         * (unless there are PHVs that have to be evaluated there), we
4431
         * don't much care if it's null-extended or not.  So in this
4432
         * case also, we can just ignore the qual and discard the left
4433
         * join.
4434
         */
4435
0
        if ((varno = get_result_relid(root, j->rarg)) != 0 &&
4436
0
          (j->quals == NULL ||
4437
0
           !find_dependent_phvs(root, varno, baserels)))
4438
0
        {
4439
0
          remove_result_refs(root, varno, j->larg);
4440
0
          *dropped_outer_joins = bms_add_member(*dropped_outer_joins,
4441
0
                              j->rtindex);
4442
0
          jtnode = j->larg;
4443
0
        }
4444
0
        break;
4445
0
      case JOIN_SEMI:
4446
4447
        /*
4448
         * We may simplify this case if the RHS is an RTE_RESULT; the
4449
         * join qual becomes effectively just a filter qual for the
4450
         * LHS, since we should either return the LHS row or not.  The
4451
         * filter clause must go into a new FromExpr if we can't push
4452
         * it up to the parent.
4453
         *
4454
         * There is a fine point about PHVs that are supposed to be
4455
         * evaluated at the RHS.  Such PHVs could only appear in the
4456
         * semijoin's qual, since the rest of the query cannot
4457
         * reference any outputs of the semijoin's RHS.  Therefore,
4458
         * they can't actually go to null before being examined, and
4459
         * it'd be OK to just remove the PHV wrapping.  We don't have
4460
         * infrastructure for that, but remove_result_refs() will
4461
         * relabel them as to be evaluated at the LHS, which is fine.
4462
         *
4463
         * Also, we don't need to worry about removing traces of the
4464
         * join's rtindex, since it hasn't got one.
4465
         */
4466
0
        if ((varno = get_result_relid(root, j->rarg)) != 0)
4467
0
        {
4468
0
          Assert(j->rtindex == 0);
4469
0
          remove_result_refs(root, varno, j->larg);
4470
0
          if (j->quals != NULL && parent_quals == NULL)
4471
0
            jtnode = (Node *)
4472
0
              makeFromExpr(list_make1(j->larg), j->quals);
4473
0
          else
4474
0
          {
4475
            /* Merge any quals up to parent */
4476
0
            if (j->quals != NULL)
4477
0
              *parent_quals = (Node *)
4478
0
                list_concat(castNode(List, j->quals),
4479
0
                      castNode(List, *parent_quals));
4480
0
            jtnode = j->larg;
4481
0
          }
4482
0
        }
4483
0
        break;
4484
0
      case JOIN_FULL:
4485
0
      case JOIN_ANTI:
4486
        /* We have no special smarts for these cases */
4487
0
        break;
4488
0
      default:
4489
        /* Note: JOIN_RIGHT should be gone at this point */
4490
0
        elog(ERROR, "unrecognized join type: %d",
4491
0
           (int) j->jointype);
4492
0
        break;
4493
0
    }
4494
0
  }
4495
0
  else
4496
0
    elog(ERROR, "unrecognized node type: %d",
4497
0
       (int) nodeTag(jtnode));
4498
0
  return jtnode;
4499
0
}
4500
4501
/*
4502
 * get_result_relid
4503
 *    If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
4504
 *    otherwise return 0.
4505
 */
4506
static int
4507
get_result_relid(PlannerInfo *root, Node *jtnode)
4508
0
{
4509
0
  int     varno;
4510
4511
0
  if (!IsA(jtnode, RangeTblRef))
4512
0
    return 0;
4513
0
  varno = ((RangeTblRef *) jtnode)->rtindex;
4514
0
  if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
4515
0
    return 0;
4516
0
  return varno;
4517
0
}
4518
4519
/*
4520
 * remove_result_refs
4521
 *    Helper routine for dropping an unneeded RTE_RESULT RTE.
4522
 *
4523
 * This doesn't physically remove the RTE from the jointree, because that's
4524
 * more easily handled in remove_useless_results_recurse.  What it does do
4525
 * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
4526
 * that may reference the RTE.  Be sure to call this at a point where the
4527
 * jointree is valid (no disconnected nodes).
4528
 *
4529
 * Note that we don't need to process the append_rel_list, since RTEs
4530
 * referenced directly in the jointree won't be appendrel members.
4531
 *
4532
 * varno is the RTE_RESULT's relid.
4533
 * newjtloc is the jointree location at which any PHVs referencing the
4534
 * RTE_RESULT should be evaluated instead.
4535
 */
4536
static void
4537
remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
4538
0
{
4539
  /* Fix up PlaceHolderVars as needed */
4540
  /* If there are no PHVs anywhere, we can skip this bit */
4541
0
  if (root->glob->lastPHId != 0)
4542
0
  {
4543
0
    Relids    subrelids;
4544
4545
0
    subrelids = get_relids_in_jointree(newjtloc, true, false);
4546
0
    Assert(!bms_is_empty(subrelids));
4547
0
    substitute_phv_relids((Node *) root->parse, varno, subrelids);
4548
0
    fix_append_rel_relids(root, varno, subrelids);
4549
0
  }
4550
4551
  /*
4552
   * We also need to remove any PlanRowMark referencing the RTE, but we
4553
   * postpone that work until we return to remove_useless_result_rtes.
4554
   */
4555
0
}
4556
4557
4558
/*
4559
 * find_dependent_phvs - are there any PlaceHolderVars whose base relids are
4560
 * exactly the given varno?
4561
 *
4562
 * We ignore outer-join relids present in a PHV's phrels, by intersecting
4563
 * with the caller-supplied "baserels" set.  This is necessary in part
4564
 * because some of the OJ relids may be stale, that is we may have
4565
 * already decided to remove those joins in remove_useless_result_rtes
4566
 * and not yet have cleaned their relid bits out of upper PHVs.
4567
 * But in general, it's the set of baserels that identify possible places
4568
 * to evaluate a PHV, and we mustn't let that go to empty.  (The caller is
4569
 * allowed to pass baserels as NULL if the query contains no PHVs at all,
4570
 * since then there is no work to do anyway.)
4571
 *
4572
 * find_dependent_phvs should be used when we want to see if there are
4573
 * any such PHVs anywhere in the Query.  Another use-case is to see if
4574
 * a subtree of the join tree contains such PHVs; but for that, we have
4575
 * to look not only at the join tree nodes themselves but at the
4576
 * referenced RTEs.  For that, use find_dependent_phvs_in_jointree.
4577
 */
4578
4579
typedef struct
4580
{
4581
  Relids    relids;     /* target relid, represented as a relid set */
4582
  Relids    baserels;   /* base RT indexes in query, NULL if no PHVs */
4583
  int     sublevels_up; /* current nesting level */
4584
} find_dependent_phvs_context;
4585
4586
static bool
4587
find_dependent_phvs_walker(Node *node,
4588
               find_dependent_phvs_context *context)
4589
0
{
4590
0
  if (node == NULL)
4591
0
    return false;
4592
0
  if (IsA(node, PlaceHolderVar))
4593
0
  {
4594
0
    PlaceHolderVar *phv = (PlaceHolderVar *) node;
4595
4596
0
    if (phv->phlevelsup == context->sublevels_up)
4597
0
    {
4598
0
      Relids    phbaserels = bms_intersect(phv->phrels,
4599
0
                           context->baserels);
4600
0
      bool    match = bms_equal(context->relids, phbaserels);
4601
4602
0
      bms_free(phbaserels);
4603
0
      if (match)
4604
0
        return true;
4605
0
    }
4606
    /* fall through to examine children */
4607
0
  }
4608
0
  if (IsA(node, Query))
4609
0
  {
4610
    /* Recurse into subselects */
4611
0
    bool    result;
4612
4613
0
    context->sublevels_up++;
4614
0
    result = query_tree_walker((Query *) node,
4615
0
                   find_dependent_phvs_walker,
4616
0
                   context, 0);
4617
0
    context->sublevels_up--;
4618
0
    return result;
4619
0
  }
4620
  /* Shouldn't need to handle most planner auxiliary nodes here */
4621
0
  Assert(!IsA(node, SpecialJoinInfo));
4622
0
  Assert(!IsA(node, PlaceHolderInfo));
4623
0
  Assert(!IsA(node, MinMaxAggInfo));
4624
4625
0
  return expression_tree_walker(node, find_dependent_phvs_walker, context);
4626
0
}
4627
4628
static bool
4629
find_dependent_phvs(PlannerInfo *root, int varno, Relids baserels)
4630
0
{
4631
0
  find_dependent_phvs_context context;
4632
4633
  /* If there are no PHVs anywhere, we needn't work hard */
4634
0
  if (root->glob->lastPHId == 0)
4635
0
    return false;
4636
4637
0
  context.relids = bms_make_singleton(varno);
4638
0
  context.baserels = baserels;
4639
0
  context.sublevels_up = 0;
4640
4641
0
  if (query_tree_walker(root->parse, find_dependent_phvs_walker, &context, 0))
4642
0
    return true;
4643
  /* The append_rel_list could be populated already, so check it too */
4644
0
  if (expression_tree_walker((Node *) root->append_rel_list,
4645
0
                 find_dependent_phvs_walker,
4646
0
                 &context))
4647
0
    return true;
4648
0
  return false;
4649
0
}
4650
4651
static bool
4652
find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno,
4653
                Relids baserels)
4654
0
{
4655
0
  find_dependent_phvs_context context;
4656
0
  Relids    subrelids;
4657
0
  int     relid;
4658
4659
  /* If there are no PHVs anywhere, we needn't work hard */
4660
0
  if (root->glob->lastPHId == 0)
4661
0
    return false;
4662
4663
0
  context.relids = bms_make_singleton(varno);
4664
0
  context.baserels = baserels;
4665
0
  context.sublevels_up = 0;
4666
4667
  /*
4668
   * See if the jointree fragment itself contains references (in join quals)
4669
   */
4670
0
  if (find_dependent_phvs_walker(node, &context))
4671
0
    return true;
4672
4673
  /*
4674
   * Otherwise, identify the set of referenced RTEs (we can ignore joins,
4675
   * since they should be flattened already, so their join alias lists no
4676
   * longer matter), and tediously check each RTE.  We can ignore RTEs that
4677
   * are not marked LATERAL, though, since they couldn't possibly contain
4678
   * any cross-references to other RTEs.
4679
   */
4680
0
  subrelids = get_relids_in_jointree(node, false, false);
4681
0
  relid = -1;
4682
0
  while ((relid = bms_next_member(subrelids, relid)) >= 0)
4683
0
  {
4684
0
    RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
4685
4686
0
    if (rte->lateral &&
4687
0
      range_table_entry_walker(rte, find_dependent_phvs_walker, &context, 0))
4688
0
      return true;
4689
0
  }
4690
4691
0
  return false;
4692
0
}
4693
4694
/*
4695
 * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
4696
 * a subquery or removing an RTE_RESULT jointree item
4697
 *
4698
 * Find any PlaceHolderVar nodes in the given tree that reference the
4699
 * pulled-up relid, and change them to reference the replacement relid(s).
4700
 *
4701
 * NOTE: although this has the form of a walker, we cheat and modify the
4702
 * nodes in-place.  This should be OK since the tree was copied by
4703
 * pullup_replace_vars earlier.  Avoid scribbling on the original values of
4704
 * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
4705
 */
4706
4707
typedef struct
4708
{
4709
  int     varno;
4710
  int     sublevels_up;
4711
  Relids    subrelids;
4712
} substitute_phv_relids_context;
4713
4714
static bool
4715
substitute_phv_relids_walker(Node *node,
4716
               substitute_phv_relids_context *context)
4717
0
{
4718
0
  if (node == NULL)
4719
0
    return false;
4720
0
  if (IsA(node, PlaceHolderVar))
4721
0
  {
4722
0
    PlaceHolderVar *phv = (PlaceHolderVar *) node;
4723
4724
0
    if (phv->phlevelsup == context->sublevels_up &&
4725
0
      bms_is_member(context->varno, phv->phrels))
4726
0
    {
4727
0
      phv->phrels = bms_union(phv->phrels,
4728
0
                  context->subrelids);
4729
0
      phv->phrels = bms_del_member(phv->phrels,
4730
0
                     context->varno);
4731
      /* Assert we haven't broken the PHV */
4732
0
      Assert(!bms_is_empty(phv->phrels));
4733
0
    }
4734
    /* fall through to examine children */
4735
0
  }
4736
0
  if (IsA(node, Query))
4737
0
  {
4738
    /* Recurse into subselects */
4739
0
    bool    result;
4740
4741
0
    context->sublevels_up++;
4742
0
    result = query_tree_walker((Query *) node,
4743
0
                   substitute_phv_relids_walker,
4744
0
                   context, 0);
4745
0
    context->sublevels_up--;
4746
0
    return result;
4747
0
  }
4748
  /* Shouldn't need to handle planner auxiliary nodes here */
4749
0
  Assert(!IsA(node, SpecialJoinInfo));
4750
0
  Assert(!IsA(node, AppendRelInfo));
4751
0
  Assert(!IsA(node, PlaceHolderInfo));
4752
0
  Assert(!IsA(node, MinMaxAggInfo));
4753
4754
0
  return expression_tree_walker(node, substitute_phv_relids_walker, context);
4755
0
}
4756
4757
static void
4758
substitute_phv_relids(Node *node, int varno, Relids subrelids)
4759
0
{
4760
0
  substitute_phv_relids_context context;
4761
4762
0
  context.varno = varno;
4763
0
  context.sublevels_up = 0;
4764
0
  context.subrelids = subrelids;
4765
4766
  /*
4767
   * Must be prepared to start with a Query or a bare expression tree.
4768
   */
4769
0
  query_or_expression_tree_walker(node,
4770
0
                  substitute_phv_relids_walker,
4771
0
                  &context,
4772
0
                  0);
4773
0
}
4774
4775
/*
4776
 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
4777
 *
4778
 * When we pull up a subquery, any AppendRelInfo references to the subquery's
4779
 * RT index have to be replaced by the substituted relid (and there had better
4780
 * be only one).  We also need to apply substitute_phv_relids to their
4781
 * translated_vars lists, since those might contain PlaceHolderVars.
4782
 *
4783
 * We assume we may modify the AppendRelInfo nodes in-place.
4784
 */
4785
static void
4786
fix_append_rel_relids(PlannerInfo *root, int varno, Relids subrelids)
4787
0
{
4788
0
  ListCell   *l;
4789
0
  int     subvarno = -1;
4790
4791
  /*
4792
   * We only want to extract the member relid once, but we mustn't fail
4793
   * immediately if there are multiple members; it could be that none of the
4794
   * AppendRelInfo nodes refer to it.  So compute it on first use. Note that
4795
   * bms_singleton_member will complain if set is not singleton.
4796
   */
4797
0
  foreach(l, root->append_rel_list)
4798
0
  {
4799
0
    AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
4800
4801
    /* The parent_relid shouldn't ever be a pullup target */
4802
0
    Assert(appinfo->parent_relid != varno);
4803
4804
0
    if (appinfo->child_relid == varno)
4805
0
    {
4806
0
      if (subvarno < 0)
4807
0
        subvarno = bms_singleton_member(subrelids);
4808
0
      appinfo->child_relid = subvarno;
4809
0
    }
4810
4811
    /* Also fix up any PHVs in its translated vars */
4812
0
    if (root->glob->lastPHId != 0)
4813
0
      substitute_phv_relids((Node *) appinfo->translated_vars,
4814
0
                  varno, subrelids);
4815
0
  }
4816
0
}
4817
4818
/*
4819
 * get_relids_in_jointree: get set of RT indexes present in a jointree
4820
 *
4821
 * Base-relation relids are always included in the result.
4822
 * If include_outer_joins is true, outer-join RT indexes are included.
4823
 * If include_inner_joins is true, inner-join RT indexes are included.
4824
 *
4825
 * Note that for most purposes in the planner, outer joins are included
4826
 * in standard relid sets.  Setting include_inner_joins true is only
4827
 * appropriate for special purposes during subquery flattening.
4828
 */
4829
Relids
4830
get_relids_in_jointree(Node *jtnode, bool include_outer_joins,
4831
             bool include_inner_joins)
4832
0
{
4833
0
  Relids    result = NULL;
4834
4835
0
  if (jtnode == NULL)
4836
0
    return result;
4837
0
  if (IsA(jtnode, RangeTblRef))
4838
0
  {
4839
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
4840
4841
0
    result = bms_make_singleton(varno);
4842
0
  }
4843
0
  else if (IsA(jtnode, FromExpr))
4844
0
  {
4845
0
    FromExpr   *f = (FromExpr *) jtnode;
4846
0
    ListCell   *l;
4847
4848
0
    foreach(l, f->fromlist)
4849
0
    {
4850
0
      result = bms_join(result,
4851
0
                get_relids_in_jointree(lfirst(l),
4852
0
                           include_outer_joins,
4853
0
                           include_inner_joins));
4854
0
    }
4855
0
  }
4856
0
  else if (IsA(jtnode, JoinExpr))
4857
0
  {
4858
0
    JoinExpr   *j = (JoinExpr *) jtnode;
4859
4860
0
    result = get_relids_in_jointree(j->larg,
4861
0
                    include_outer_joins,
4862
0
                    include_inner_joins);
4863
0
    result = bms_join(result,
4864
0
              get_relids_in_jointree(j->rarg,
4865
0
                         include_outer_joins,
4866
0
                         include_inner_joins));
4867
0
    if (j->rtindex)
4868
0
    {
4869
0
      if (j->jointype == JOIN_INNER)
4870
0
      {
4871
0
        if (include_inner_joins)
4872
0
          result = bms_add_member(result, j->rtindex);
4873
0
      }
4874
0
      else
4875
0
      {
4876
0
        if (include_outer_joins)
4877
0
          result = bms_add_member(result, j->rtindex);
4878
0
      }
4879
0
    }
4880
0
  }
4881
0
  else
4882
0
    elog(ERROR, "unrecognized node type: %d",
4883
0
       (int) nodeTag(jtnode));
4884
0
  return result;
4885
0
}
4886
4887
/*
4888
 * get_relids_for_join: get set of base+OJ RT indexes making up a join
4889
 */
4890
Relids
4891
get_relids_for_join(Query *query, int joinrelid)
4892
0
{
4893
0
  Node     *jtnode;
4894
4895
0
  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
4896
0
                    joinrelid);
4897
0
  if (!jtnode)
4898
0
    elog(ERROR, "could not find join node %d", joinrelid);
4899
0
  return get_relids_in_jointree(jtnode, true, false);
4900
0
}
4901
4902
/*
4903
 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
4904
 *
4905
 * Returns NULL if not found
4906
 */
4907
static Node *
4908
find_jointree_node_for_rel(Node *jtnode, int relid)
4909
0
{
4910
0
  if (jtnode == NULL)
4911
0
    return NULL;
4912
0
  if (IsA(jtnode, RangeTblRef))
4913
0
  {
4914
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
4915
4916
0
    if (relid == varno)
4917
0
      return jtnode;
4918
0
  }
4919
0
  else if (IsA(jtnode, FromExpr))
4920
0
  {
4921
0
    FromExpr   *f = (FromExpr *) jtnode;
4922
0
    ListCell   *l;
4923
4924
0
    foreach(l, f->fromlist)
4925
0
    {
4926
0
      jtnode = find_jointree_node_for_rel(lfirst(l), relid);
4927
0
      if (jtnode)
4928
0
        return jtnode;
4929
0
    }
4930
0
  }
4931
0
  else if (IsA(jtnode, JoinExpr))
4932
0
  {
4933
0
    JoinExpr   *j = (JoinExpr *) jtnode;
4934
4935
0
    if (relid == j->rtindex)
4936
0
      return jtnode;
4937
0
    jtnode = find_jointree_node_for_rel(j->larg, relid);
4938
0
    if (jtnode)
4939
0
      return jtnode;
4940
0
    jtnode = find_jointree_node_for_rel(j->rarg, relid);
4941
0
    if (jtnode)
4942
0
      return jtnode;
4943
0
  }
4944
0
  else
4945
0
    elog(ERROR, "unrecognized node type: %d",
4946
0
       (int) nodeTag(jtnode));
4947
0
  return NULL;
4948
0
}
4949
4950
/*
4951
 * get_nullingrels: collect info about which outer joins null which relations
4952
 *
4953
 * The result struct contains, for each leaf relation used in the query,
4954
 * the set of relids of outer joins that potentially null that rel.
4955
 */
4956
static nullingrel_info *
4957
get_nullingrels(Query *parse)
4958
0
{
4959
0
  nullingrel_info *result = palloc_object(nullingrel_info);
4960
4961
0
  result->rtlength = list_length(parse->rtable);
4962
0
  result->nullingrels = palloc0_array(Relids, result->rtlength + 1);
4963
0
  get_nullingrels_recurse((Node *) parse->jointree, NULL, result);
4964
0
  return result;
4965
0
}
4966
4967
/*
4968
 * Recursive guts of get_nullingrels().
4969
 *
4970
 * Note: at any recursion level, the passed-down upper_nullingrels must be
4971
 * treated as a constant, but it can be stored directly into *info
4972
 * if we're at leaf level.  Upper recursion levels do not free their mutated
4973
 * copies of the nullingrels, because those are probably referenced by
4974
 * at least one leaf rel.
4975
 */
4976
static void
4977
get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels,
4978
            nullingrel_info *info)
4979
0
{
4980
0
  if (jtnode == NULL)
4981
0
    return;
4982
0
  if (IsA(jtnode, RangeTblRef))
4983
0
  {
4984
0
    int     varno = ((RangeTblRef *) jtnode)->rtindex;
4985
4986
0
    Assert(varno > 0 && varno <= info->rtlength);
4987
0
    info->nullingrels[varno] = upper_nullingrels;
4988
0
  }
4989
0
  else if (IsA(jtnode, FromExpr))
4990
0
  {
4991
0
    FromExpr   *f = (FromExpr *) jtnode;
4992
0
    ListCell   *l;
4993
4994
0
    foreach(l, f->fromlist)
4995
0
    {
4996
0
      get_nullingrels_recurse(lfirst(l), upper_nullingrels, info);
4997
0
    }
4998
0
  }
4999
0
  else if (IsA(jtnode, JoinExpr))
5000
0
  {
5001
0
    JoinExpr   *j = (JoinExpr *) jtnode;
5002
0
    Relids    local_nullingrels;
5003
5004
0
    switch (j->jointype)
5005
0
    {
5006
0
      case JOIN_INNER:
5007
0
        get_nullingrels_recurse(j->larg, upper_nullingrels, info);
5008
0
        get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
5009
0
        break;
5010
0
      case JOIN_LEFT:
5011
0
      case JOIN_SEMI:
5012
0
      case JOIN_ANTI:
5013
0
        local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
5014
0
                           j->rtindex);
5015
0
        get_nullingrels_recurse(j->larg, upper_nullingrels, info);
5016
0
        get_nullingrels_recurse(j->rarg, local_nullingrels, info);
5017
0
        break;
5018
0
      case JOIN_FULL:
5019
0
        local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
5020
0
                           j->rtindex);
5021
0
        get_nullingrels_recurse(j->larg, local_nullingrels, info);
5022
0
        get_nullingrels_recurse(j->rarg, local_nullingrels, info);
5023
0
        break;
5024
0
      case JOIN_RIGHT:
5025
0
        local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
5026
0
                           j->rtindex);
5027
0
        get_nullingrels_recurse(j->larg, local_nullingrels, info);
5028
0
        get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
5029
0
        break;
5030
0
      default:
5031
0
        elog(ERROR, "unrecognized join type: %d",
5032
0
           (int) j->jointype);
5033
0
        break;
5034
0
    }
5035
0
  }
5036
0
  else
5037
0
    elog(ERROR, "unrecognized node type: %d",
5038
0
       (int) nodeTag(jtnode));
5039
0
}