Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/optimizer/util/relnode.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * relnode.c
4
 *    Relation-node lookup/construction routines
5
 *
6
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *
10
 * IDENTIFICATION
11
 *    src/backend/optimizer/util/relnode.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
#include "postgres.h"
16
17
#include <limits.h>
18
19
#include "miscadmin.h"
20
#include "nodes/nodeFuncs.h"
21
#include "optimizer/appendinfo.h"
22
#include "optimizer/clauses.h"
23
#include "optimizer/cost.h"
24
#include "optimizer/inherit.h"
25
#include "optimizer/optimizer.h"
26
#include "optimizer/pathnode.h"
27
#include "optimizer/paths.h"
28
#include "optimizer/placeholder.h"
29
#include "optimizer/plancat.h"
30
#include "optimizer/restrictinfo.h"
31
#include "optimizer/tlist.h"
32
#include "parser/parse_relation.h"
33
#include "rewrite/rewriteManip.h"
34
#include "utils/hsearch.h"
35
#include "utils/lsyscache.h"
36
37
38
typedef struct JoinHashEntry
39
{
40
  Relids    join_relids;  /* hash key --- MUST BE FIRST */
41
  RelOptInfo *join_rel;
42
} JoinHashEntry;
43
44
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
45
                RelOptInfo *input_rel,
46
                SpecialJoinInfo *sjinfo,
47
                List *pushed_down_joins,
48
                bool can_null);
49
static List *build_joinrel_restrictlist(PlannerInfo *root,
50
                    RelOptInfo *joinrel,
51
                    RelOptInfo *outer_rel,
52
                    RelOptInfo *inner_rel,
53
                    SpecialJoinInfo *sjinfo);
54
static void build_joinrel_joinlist(RelOptInfo *joinrel,
55
                   RelOptInfo *outer_rel,
56
                   RelOptInfo *inner_rel);
57
static List *subbuild_joinrel_restrictlist(PlannerInfo *root,
58
                       RelOptInfo *joinrel,
59
                       RelOptInfo *input_rel,
60
                       Relids both_input_relids,
61
                       List *new_restrictlist);
62
static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
63
                     List *joininfo_list,
64
                     List *new_joininfo);
65
static void set_foreign_rel_properties(RelOptInfo *joinrel,
66
                     RelOptInfo *outer_rel, RelOptInfo *inner_rel);
67
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
68
static void build_joinrel_partition_info(PlannerInfo *root,
69
                     RelOptInfo *joinrel,
70
                     RelOptInfo *outer_rel, RelOptInfo *inner_rel,
71
                     SpecialJoinInfo *sjinfo,
72
                     List *restrictlist);
73
static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
74
                   RelOptInfo *rel1, RelOptInfo *rel2,
75
                   JoinType jointype, List *restrictlist);
76
static int  match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
77
                     bool strict_op);
78
static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
79
                      RelOptInfo *outer_rel, RelOptInfo *inner_rel,
80
                      JoinType jointype);
81
static void build_child_join_reltarget(PlannerInfo *root,
82
                     RelOptInfo *parentrel,
83
                     RelOptInfo *childrel,
84
                     int nappinfos,
85
                     AppendRelInfo **appinfos);
86
87
88
/*
89
 * setup_simple_rel_arrays
90
 *    Prepare the arrays we use for quickly accessing base relations
91
 *    and AppendRelInfos.
92
 */
93
void
94
setup_simple_rel_arrays(PlannerInfo *root)
95
0
{
96
0
  int     size;
97
0
  Index   rti;
98
0
  ListCell   *lc;
99
100
  /* Arrays are accessed using RT indexes (1..N) */
101
0
  size = list_length(root->parse->rtable) + 1;
102
0
  root->simple_rel_array_size = size;
103
104
  /*
105
   * simple_rel_array is initialized to all NULLs, since no RelOptInfos
106
   * exist yet.  It'll be filled by later calls to build_simple_rel().
107
   */
108
0
  root->simple_rel_array = (RelOptInfo **)
109
0
    palloc0(size * sizeof(RelOptInfo *));
110
111
  /* simple_rte_array is an array equivalent of the rtable list */
112
0
  root->simple_rte_array = (RangeTblEntry **)
113
0
    palloc0(size * sizeof(RangeTblEntry *));
114
0
  rti = 1;
115
0
  foreach(lc, root->parse->rtable)
116
0
  {
117
0
    RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
118
119
0
    root->simple_rte_array[rti++] = rte;
120
0
  }
121
122
  /* append_rel_array is not needed if there are no AppendRelInfos */
123
0
  if (root->append_rel_list == NIL)
124
0
  {
125
0
    root->append_rel_array = NULL;
126
0
    return;
127
0
  }
128
129
0
  root->append_rel_array = (AppendRelInfo **)
130
0
    palloc0(size * sizeof(AppendRelInfo *));
131
132
  /*
133
   * append_rel_array is filled with any already-existing AppendRelInfos,
134
   * which currently could only come from UNION ALL flattening.  We might
135
   * add more later during inheritance expansion, but it's the
136
   * responsibility of the expansion code to update the array properly.
137
   */
138
0
  foreach(lc, root->append_rel_list)
139
0
  {
140
0
    AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
141
0
    int     child_relid = appinfo->child_relid;
142
143
    /* Sanity check */
144
0
    Assert(child_relid < size);
145
146
0
    if (root->append_rel_array[child_relid])
147
0
      elog(ERROR, "child relation already exists");
148
149
0
    root->append_rel_array[child_relid] = appinfo;
150
0
  }
151
0
}
152
153
/*
154
 * expand_planner_arrays
155
 *    Expand the PlannerInfo's per-RTE arrays by add_size members
156
 *    and initialize the newly added entries to NULLs
157
 *
158
 * Note: this causes the append_rel_array to become allocated even if
159
 * it was not before.  This is okay for current uses, because we only call
160
 * this when adding child relations, which always have AppendRelInfos.
161
 */
162
void
163
expand_planner_arrays(PlannerInfo *root, int add_size)
164
0
{
165
0
  int     new_size;
166
167
0
  Assert(add_size > 0);
168
169
0
  new_size = root->simple_rel_array_size + add_size;
170
171
0
  root->simple_rel_array =
172
0
    repalloc0_array(root->simple_rel_array, RelOptInfo *, root->simple_rel_array_size, new_size);
173
174
0
  root->simple_rte_array =
175
0
    repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
176
177
0
  if (root->append_rel_array)
178
0
    root->append_rel_array =
179
0
      repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
180
0
  else
181
0
    root->append_rel_array =
182
0
      palloc0_array(AppendRelInfo *, new_size);
183
184
0
  root->simple_rel_array_size = new_size;
185
0
}
186
187
/*
188
 * build_simple_rel
189
 *    Construct a new RelOptInfo for a base relation or 'other' relation.
190
 */
191
RelOptInfo *
192
build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
193
0
{
194
0
  RelOptInfo *rel;
195
0
  RangeTblEntry *rte;
196
197
  /* Rel should not exist already */
198
0
  Assert(relid > 0 && relid < root->simple_rel_array_size);
199
0
  if (root->simple_rel_array[relid] != NULL)
200
0
    elog(ERROR, "rel %d already exists", relid);
201
202
  /* Fetch RTE for relation */
203
0
  rte = root->simple_rte_array[relid];
204
0
  Assert(rte != NULL);
205
206
0
  rel = makeNode(RelOptInfo);
207
0
  rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
208
0
  rel->relids = bms_make_singleton(relid);
209
0
  rel->rows = 0;
210
  /* cheap startup cost is interesting iff not all tuples to be retrieved */
211
0
  rel->consider_startup = (root->tuple_fraction > 0);
212
0
  rel->consider_param_startup = false;  /* might get changed later */
213
0
  rel->consider_parallel = false; /* might get changed later */
214
0
  rel->reltarget = create_empty_pathtarget();
215
0
  rel->pathlist = NIL;
216
0
  rel->ppilist = NIL;
217
0
  rel->partial_pathlist = NIL;
218
0
  rel->cheapest_startup_path = NULL;
219
0
  rel->cheapest_total_path = NULL;
220
0
  rel->cheapest_unique_path = NULL;
221
0
  rel->cheapest_parameterized_paths = NIL;
222
0
  rel->relid = relid;
223
0
  rel->rtekind = rte->rtekind;
224
  /* min_attr, max_attr, attr_needed, attr_widths are set below */
225
0
  rel->notnullattnums = NULL;
226
0
  rel->lateral_vars = NIL;
227
0
  rel->indexlist = NIL;
228
0
  rel->statlist = NIL;
229
0
  rel->pages = 0;
230
0
  rel->tuples = 0;
231
0
  rel->allvisfrac = 0;
232
0
  rel->eclass_indexes = NULL;
233
0
  rel->subroot = NULL;
234
0
  rel->subplan_params = NIL;
235
0
  rel->rel_parallel_workers = -1; /* set up in get_relation_info */
236
0
  rel->amflags = 0;
237
0
  rel->serverid = InvalidOid;
238
0
  if (rte->rtekind == RTE_RELATION)
239
0
  {
240
0
    Assert(parent == NULL ||
241
0
         parent->rtekind == RTE_RELATION ||
242
0
         parent->rtekind == RTE_SUBQUERY);
243
244
    /*
245
     * For any RELATION rte, we need a userid with which to check
246
     * permission access. Baserels simply use their own
247
     * RTEPermissionInfo's checkAsUser.
248
     *
249
     * For otherrels normally there's no RTEPermissionInfo, so we use the
250
     * parent's, which normally has one. The exceptional case is that the
251
     * parent is a subquery, in which case the otherrel will have its own.
252
     */
253
0
    if (rel->reloptkind == RELOPT_BASEREL ||
254
0
      (rel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
255
0
       parent->rtekind == RTE_SUBQUERY))
256
0
    {
257
0
      RTEPermissionInfo *perminfo;
258
259
0
      perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
260
0
      rel->userid = perminfo->checkAsUser;
261
0
    }
262
0
    else
263
0
      rel->userid = parent->userid;
264
0
  }
265
0
  else
266
0
    rel->userid = InvalidOid;
267
0
  rel->useridiscurrent = false;
268
0
  rel->fdwroutine = NULL;
269
0
  rel->fdw_private = NULL;
270
0
  rel->unique_for_rels = NIL;
271
0
  rel->non_unique_for_rels = NIL;
272
0
  rel->baserestrictinfo = NIL;
273
0
  rel->baserestrictcost.startup = 0;
274
0
  rel->baserestrictcost.per_tuple = 0;
275
0
  rel->baserestrict_min_security = UINT_MAX;
276
0
  rel->joininfo = NIL;
277
0
  rel->has_eclass_joins = false;
278
0
  rel->consider_partitionwise_join = false; /* might get changed later */
279
0
  rel->part_scheme = NULL;
280
0
  rel->nparts = -1;
281
0
  rel->boundinfo = NULL;
282
0
  rel->partbounds_merged = false;
283
0
  rel->partition_qual = NIL;
284
0
  rel->part_rels = NULL;
285
0
  rel->live_parts = NULL;
286
0
  rel->all_partrels = NULL;
287
0
  rel->partexprs = NULL;
288
0
  rel->nullable_partexprs = NULL;
289
290
  /*
291
   * Pass assorted information down the inheritance hierarchy.
292
   */
293
0
  if (parent)
294
0
  {
295
    /* We keep back-links to immediate parent and topmost parent. */
296
0
    rel->parent = parent;
297
0
    rel->top_parent = parent->top_parent ? parent->top_parent : parent;
298
0
    rel->top_parent_relids = rel->top_parent->relids;
299
300
    /*
301
     * A child rel is below the same outer joins as its parent.  (We
302
     * presume this info was already calculated for the parent.)
303
     */
304
0
    rel->nulling_relids = parent->nulling_relids;
305
306
    /*
307
     * Also propagate lateral-reference information from appendrel parent
308
     * rels to their child rels.  We intentionally give each child rel the
309
     * same minimum parameterization, even though it's quite possible that
310
     * some don't reference all the lateral rels.  This is because any
311
     * append path for the parent will have to have the same
312
     * parameterization for every child anyway, and there's no value in
313
     * forcing extra reparameterize_path() calls.  Similarly, a lateral
314
     * reference to the parent prevents use of otherwise-movable join rels
315
     * for each child.
316
     *
317
     * It's possible for child rels to have their own children, in which
318
     * case the topmost parent's lateral info propagates all the way down.
319
     */
320
0
    rel->direct_lateral_relids = parent->direct_lateral_relids;
321
0
    rel->lateral_relids = parent->lateral_relids;
322
0
    rel->lateral_referencers = parent->lateral_referencers;
323
0
  }
324
0
  else
325
0
  {
326
0
    rel->parent = NULL;
327
0
    rel->top_parent = NULL;
328
0
    rel->top_parent_relids = NULL;
329
0
    rel->nulling_relids = NULL;
330
0
    rel->direct_lateral_relids = NULL;
331
0
    rel->lateral_relids = NULL;
332
0
    rel->lateral_referencers = NULL;
333
0
  }
334
335
  /* Check type of rtable entry */
336
0
  switch (rte->rtekind)
337
0
  {
338
0
    case RTE_RELATION:
339
      /* Table --- retrieve statistics from the system catalogs */
340
0
      get_relation_info(root, rte->relid, rte->inh, rel);
341
0
      break;
342
0
    case RTE_SUBQUERY:
343
0
    case RTE_FUNCTION:
344
0
    case RTE_TABLEFUNC:
345
0
    case RTE_VALUES:
346
0
    case RTE_CTE:
347
0
    case RTE_NAMEDTUPLESTORE:
348
349
      /*
350
       * Subquery, function, tablefunc, values list, CTE, or ENR --- set
351
       * up attr range and arrays
352
       *
353
       * Note: 0 is included in range to support whole-row Vars
354
       */
355
0
      rel->min_attr = 0;
356
0
      rel->max_attr = list_length(rte->eref->colnames);
357
0
      rel->attr_needed = (Relids *)
358
0
        palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
359
0
      rel->attr_widths = (int32 *)
360
0
        palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
361
0
      break;
362
0
    case RTE_RESULT:
363
      /* RTE_RESULT has no columns, nor could it have whole-row Var */
364
0
      rel->min_attr = 0;
365
0
      rel->max_attr = -1;
366
0
      rel->attr_needed = NULL;
367
0
      rel->attr_widths = NULL;
368
0
      break;
369
0
    default:
370
0
      elog(ERROR, "unrecognized RTE kind: %d",
371
0
         (int) rte->rtekind);
372
0
      break;
373
0
  }
374
375
  /*
376
   * We must apply the partially filled in RelOptInfo before calling
377
   * apply_child_basequals due to some transformations within that function
378
   * which require the RelOptInfo to be available in the simple_rel_array.
379
   */
380
0
  root->simple_rel_array[relid] = rel;
381
382
  /*
383
   * Apply the parent's quals to the child, with appropriate substitution of
384
   * variables.  If the resulting clause is constant-FALSE or NULL after
385
   * applying transformations, apply_child_basequals returns false to
386
   * indicate that scanning this relation won't yield any rows.  In this
387
   * case, we mark the child as dummy right away.  (We must do this
388
   * immediately so that pruning works correctly when recursing in
389
   * expand_partitioned_rtentry.)
390
   */
391
0
  if (parent)
392
0
  {
393
0
    AppendRelInfo *appinfo = root->append_rel_array[relid];
394
395
0
    Assert(appinfo != NULL);
396
0
    if (!apply_child_basequals(root, parent, rel, rte, appinfo))
397
0
    {
398
      /*
399
       * Restriction clause reduced to constant FALSE or NULL.  Mark as
400
       * dummy so we won't scan this relation.
401
       */
402
0
      mark_dummy_rel(rel);
403
0
    }
404
0
  }
405
406
0
  return rel;
407
0
}
408
409
/*
410
 * find_base_rel
411
 *    Find a base or otherrel relation entry, which must already exist.
412
 */
413
RelOptInfo *
414
find_base_rel(PlannerInfo *root, int relid)
415
0
{
416
0
  RelOptInfo *rel;
417
418
  /* use an unsigned comparison to prevent negative array element access */
419
0
  if ((uint32) relid < (uint32) root->simple_rel_array_size)
420
0
  {
421
0
    rel = root->simple_rel_array[relid];
422
0
    if (rel)
423
0
      return rel;
424
0
  }
425
426
0
  elog(ERROR, "no relation entry for relid %d", relid);
427
428
0
  return NULL;       /* keep compiler quiet */
429
0
}
430
431
/*
432
 * find_base_rel_noerr
433
 *    Find a base or otherrel relation entry, returning NULL if there's none
434
 */
435
RelOptInfo *
436
find_base_rel_noerr(PlannerInfo *root, int relid)
437
0
{
438
  /* use an unsigned comparison to prevent negative array element access */
439
0
  if ((uint32) relid < (uint32) root->simple_rel_array_size)
440
0
    return root->simple_rel_array[relid];
441
0
  return NULL;
442
0
}
443
444
/*
445
 * find_base_rel_ignore_join
446
 *    Find a base or otherrel relation entry, which must already exist.
447
 *
448
 * Unlike find_base_rel, if relid references an outer join then this
449
 * will return NULL rather than raising an error.  This is convenient
450
 * for callers that must deal with relid sets including both base and
451
 * outer joins.
452
 */
453
RelOptInfo *
454
find_base_rel_ignore_join(PlannerInfo *root, int relid)
455
0
{
456
  /* use an unsigned comparison to prevent negative array element access */
457
0
  if ((uint32) relid < (uint32) root->simple_rel_array_size)
458
0
  {
459
0
    RelOptInfo *rel;
460
0
    RangeTblEntry *rte;
461
462
0
    rel = root->simple_rel_array[relid];
463
0
    if (rel)
464
0
      return rel;
465
466
    /*
467
     * We could just return NULL here, but for debugging purposes it seems
468
     * best to actually verify that the relid is an outer join and not
469
     * something weird.
470
     */
471
0
    rte = root->simple_rte_array[relid];
472
0
    if (rte && rte->rtekind == RTE_JOIN && rte->jointype != JOIN_INNER)
473
0
      return NULL;
474
0
  }
475
476
0
  elog(ERROR, "no relation entry for relid %d", relid);
477
478
0
  return NULL;       /* keep compiler quiet */
479
0
}
480
481
/*
482
 * build_join_rel_hash
483
 *    Construct the auxiliary hash table for join relations.
484
 */
485
static void
486
build_join_rel_hash(PlannerInfo *root)
487
0
{
488
0
  HTAB     *hashtab;
489
0
  HASHCTL   hash_ctl;
490
0
  ListCell   *l;
491
492
  /* Create the hash table */
493
0
  hash_ctl.keysize = sizeof(Relids);
494
0
  hash_ctl.entrysize = sizeof(JoinHashEntry);
495
0
  hash_ctl.hash = bitmap_hash;
496
0
  hash_ctl.match = bitmap_match;
497
0
  hash_ctl.hcxt = CurrentMemoryContext;
498
0
  hashtab = hash_create("JoinRelHashTable",
499
0
              256L,
500
0
              &hash_ctl,
501
0
              HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
502
503
  /* Insert all the already-existing joinrels */
504
0
  foreach(l, root->join_rel_list)
505
0
  {
506
0
    RelOptInfo *rel = (RelOptInfo *) lfirst(l);
507
0
    JoinHashEntry *hentry;
508
0
    bool    found;
509
510
0
    hentry = (JoinHashEntry *) hash_search(hashtab,
511
0
                         &(rel->relids),
512
0
                         HASH_ENTER,
513
0
                         &found);
514
0
    Assert(!found);
515
0
    hentry->join_rel = rel;
516
0
  }
517
518
0
  root->join_rel_hash = hashtab;
519
0
}
520
521
/*
522
 * find_join_rel
523
 *    Returns relation entry corresponding to 'relids' (a set of RT indexes),
524
 *    or NULL if none exists.  This is for join relations.
525
 */
526
RelOptInfo *
527
find_join_rel(PlannerInfo *root, Relids relids)
528
0
{
529
  /*
530
   * Switch to using hash lookup when list grows "too long".  The threshold
531
   * is arbitrary and is known only here.
532
   */
533
0
  if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
534
0
    build_join_rel_hash(root);
535
536
  /*
537
   * Use either hashtable lookup or linear search, as appropriate.
538
   *
539
   * Note: the seemingly redundant hashkey variable is used to avoid taking
540
   * the address of relids; unless the compiler is exceedingly smart, doing
541
   * so would force relids out of a register and thus probably slow down the
542
   * list-search case.
543
   */
544
0
  if (root->join_rel_hash)
545
0
  {
546
0
    Relids    hashkey = relids;
547
0
    JoinHashEntry *hentry;
548
549
0
    hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
550
0
                         &hashkey,
551
0
                         HASH_FIND,
552
0
                         NULL);
553
0
    if (hentry)
554
0
      return hentry->join_rel;
555
0
  }
556
0
  else
557
0
  {
558
0
    ListCell   *l;
559
560
0
    foreach(l, root->join_rel_list)
561
0
    {
562
0
      RelOptInfo *rel = (RelOptInfo *) lfirst(l);
563
564
0
      if (bms_equal(rel->relids, relids))
565
0
        return rel;
566
0
    }
567
0
  }
568
569
0
  return NULL;
570
0
}
571
572
/*
573
 * set_foreign_rel_properties
574
 *    Set up foreign-join fields if outer and inner relation are foreign
575
 *    tables (or joins) belonging to the same server and assigned to the same
576
 *    user to check access permissions as.
577
 *
578
 * In addition to an exact match of userid, we allow the case where one side
579
 * has zero userid (implying current user) and the other side has explicit
580
 * userid that happens to equal the current user; but in that case, pushdown of
581
 * the join is only valid for the current user.  The useridiscurrent field
582
 * records whether we had to make such an assumption for this join or any
583
 * sub-join.
584
 *
585
 * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
586
 * called for the join relation.
587
 */
588
static void
589
set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
590
               RelOptInfo *inner_rel)
591
0
{
592
0
  if (OidIsValid(outer_rel->serverid) &&
593
0
    inner_rel->serverid == outer_rel->serverid)
594
0
  {
595
0
    if (inner_rel->userid == outer_rel->userid)
596
0
    {
597
0
      joinrel->serverid = outer_rel->serverid;
598
0
      joinrel->userid = outer_rel->userid;
599
0
      joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
600
0
      joinrel->fdwroutine = outer_rel->fdwroutine;
601
0
    }
602
0
    else if (!OidIsValid(inner_rel->userid) &&
603
0
         outer_rel->userid == GetUserId())
604
0
    {
605
0
      joinrel->serverid = outer_rel->serverid;
606
0
      joinrel->userid = outer_rel->userid;
607
0
      joinrel->useridiscurrent = true;
608
0
      joinrel->fdwroutine = outer_rel->fdwroutine;
609
0
    }
610
0
    else if (!OidIsValid(outer_rel->userid) &&
611
0
         inner_rel->userid == GetUserId())
612
0
    {
613
0
      joinrel->serverid = outer_rel->serverid;
614
0
      joinrel->userid = inner_rel->userid;
615
0
      joinrel->useridiscurrent = true;
616
0
      joinrel->fdwroutine = outer_rel->fdwroutine;
617
0
    }
618
0
  }
619
0
}
620
621
/*
622
 * add_join_rel
623
 *    Add given join relation to the list of join relations in the given
624
 *    PlannerInfo. Also add it to the auxiliary hashtable if there is one.
625
 */
626
static void
627
add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
628
0
{
629
  /* GEQO requires us to append the new joinrel to the end of the list! */
630
0
  root->join_rel_list = lappend(root->join_rel_list, joinrel);
631
632
  /* store it into the auxiliary hashtable if there is one. */
633
0
  if (root->join_rel_hash)
634
0
  {
635
0
    JoinHashEntry *hentry;
636
0
    bool    found;
637
638
0
    hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
639
0
                         &(joinrel->relids),
640
0
                         HASH_ENTER,
641
0
                         &found);
642
0
    Assert(!found);
643
0
    hentry->join_rel = joinrel;
644
0
  }
645
0
}
646
647
/*
648
 * build_join_rel
649
 *    Returns relation entry corresponding to the union of two given rels,
650
 *    creating a new relation entry if none already exists.
651
 *
652
 * 'joinrelids' is the Relids set that uniquely identifies the join
653
 * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
654
 *    joined
655
 * 'sjinfo': join context info
656
 * 'pushed_down_joins': any pushed-down outer joins that are now completed
657
 * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr
658
 *    receives the list of RestrictInfo nodes that apply to this
659
 *    particular pair of joinable relations.
660
 *
661
 * restrictlist_ptr makes the routine's API a little grotty, but it saves
662
 * duplicated calculation of the restrictlist...
663
 */
664
RelOptInfo *
665
build_join_rel(PlannerInfo *root,
666
         Relids joinrelids,
667
         RelOptInfo *outer_rel,
668
         RelOptInfo *inner_rel,
669
         SpecialJoinInfo *sjinfo,
670
         List *pushed_down_joins,
671
         List **restrictlist_ptr)
672
0
{
673
0
  RelOptInfo *joinrel;
674
0
  List     *restrictlist;
675
676
  /* This function should be used only for join between parents. */
677
0
  Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
678
679
  /*
680
   * See if we already have a joinrel for this set of base rels.
681
   */
682
0
  joinrel = find_join_rel(root, joinrelids);
683
684
0
  if (joinrel)
685
0
  {
686
    /*
687
     * Yes, so we only need to figure the restrictlist for this particular
688
     * pair of component relations.
689
     */
690
0
    if (restrictlist_ptr)
691
0
      *restrictlist_ptr = build_joinrel_restrictlist(root,
692
0
                               joinrel,
693
0
                               outer_rel,
694
0
                               inner_rel,
695
0
                               sjinfo);
696
0
    return joinrel;
697
0
  }
698
699
  /*
700
   * Nope, so make one.
701
   */
702
0
  joinrel = makeNode(RelOptInfo);
703
0
  joinrel->reloptkind = RELOPT_JOINREL;
704
0
  joinrel->relids = bms_copy(joinrelids);
705
0
  joinrel->rows = 0;
706
  /* cheap startup cost is interesting iff not all tuples to be retrieved */
707
0
  joinrel->consider_startup = (root->tuple_fraction > 0);
708
0
  joinrel->consider_param_startup = false;
709
0
  joinrel->consider_parallel = false;
710
0
  joinrel->reltarget = create_empty_pathtarget();
711
0
  joinrel->pathlist = NIL;
712
0
  joinrel->ppilist = NIL;
713
0
  joinrel->partial_pathlist = NIL;
714
0
  joinrel->cheapest_startup_path = NULL;
715
0
  joinrel->cheapest_total_path = NULL;
716
0
  joinrel->cheapest_unique_path = NULL;
717
0
  joinrel->cheapest_parameterized_paths = NIL;
718
  /* init direct_lateral_relids from children; we'll finish it up below */
719
0
  joinrel->direct_lateral_relids =
720
0
    bms_union(outer_rel->direct_lateral_relids,
721
0
          inner_rel->direct_lateral_relids);
722
0
  joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
723
0
                            outer_rel, inner_rel);
724
0
  joinrel->relid = 0;     /* indicates not a baserel */
725
0
  joinrel->rtekind = RTE_JOIN;
726
0
  joinrel->min_attr = 0;
727
0
  joinrel->max_attr = 0;
728
0
  joinrel->attr_needed = NULL;
729
0
  joinrel->attr_widths = NULL;
730
0
  joinrel->notnullattnums = NULL;
731
0
  joinrel->nulling_relids = NULL;
732
0
  joinrel->lateral_vars = NIL;
733
0
  joinrel->lateral_referencers = NULL;
734
0
  joinrel->indexlist = NIL;
735
0
  joinrel->statlist = NIL;
736
0
  joinrel->pages = 0;
737
0
  joinrel->tuples = 0;
738
0
  joinrel->allvisfrac = 0;
739
0
  joinrel->eclass_indexes = NULL;
740
0
  joinrel->subroot = NULL;
741
0
  joinrel->subplan_params = NIL;
742
0
  joinrel->rel_parallel_workers = -1;
743
0
  joinrel->amflags = 0;
744
0
  joinrel->serverid = InvalidOid;
745
0
  joinrel->userid = InvalidOid;
746
0
  joinrel->useridiscurrent = false;
747
0
  joinrel->fdwroutine = NULL;
748
0
  joinrel->fdw_private = NULL;
749
0
  joinrel->unique_for_rels = NIL;
750
0
  joinrel->non_unique_for_rels = NIL;
751
0
  joinrel->baserestrictinfo = NIL;
752
0
  joinrel->baserestrictcost.startup = 0;
753
0
  joinrel->baserestrictcost.per_tuple = 0;
754
0
  joinrel->baserestrict_min_security = UINT_MAX;
755
0
  joinrel->joininfo = NIL;
756
0
  joinrel->has_eclass_joins = false;
757
0
  joinrel->consider_partitionwise_join = false; /* might get changed later */
758
0
  joinrel->parent = NULL;
759
0
  joinrel->top_parent = NULL;
760
0
  joinrel->top_parent_relids = NULL;
761
0
  joinrel->part_scheme = NULL;
762
0
  joinrel->nparts = -1;
763
0
  joinrel->boundinfo = NULL;
764
0
  joinrel->partbounds_merged = false;
765
0
  joinrel->partition_qual = NIL;
766
0
  joinrel->part_rels = NULL;
767
0
  joinrel->live_parts = NULL;
768
0
  joinrel->all_partrels = NULL;
769
0
  joinrel->partexprs = NULL;
770
0
  joinrel->nullable_partexprs = NULL;
771
772
  /* Compute information relevant to the foreign relations. */
773
0
  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
774
775
  /*
776
   * Fill the joinrel's tlist with just the Vars and PHVs that need to be
777
   * output from this join (ie, are needed for higher joinclauses or final
778
   * output).
779
   *
780
   * NOTE: the tlist order for a join rel will depend on which pair of outer
781
   * and inner rels we first try to build it from.  But the contents should
782
   * be the same regardless.
783
   */
784
0
  build_joinrel_tlist(root, joinrel, outer_rel, sjinfo, pushed_down_joins,
785
0
            (sjinfo->jointype == JOIN_FULL));
786
0
  build_joinrel_tlist(root, joinrel, inner_rel, sjinfo, pushed_down_joins,
787
0
            (sjinfo->jointype != JOIN_INNER));
788
0
  add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
789
790
  /*
791
   * add_placeholders_to_joinrel also took care of adding the ph_lateral
792
   * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
793
   * now we can finish computing that.  This is much like the computation of
794
   * the transitively-closed lateral_relids in min_join_parameterization,
795
   * except that here we *do* have to consider the added PHVs.
796
   */
797
0
  joinrel->direct_lateral_relids =
798
0
    bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
799
800
  /*
801
   * Construct restrict and join clause lists for the new joinrel. (The
802
   * caller might or might not need the restrictlist, but I need it anyway
803
   * for set_joinrel_size_estimates().)
804
   */
805
0
  restrictlist = build_joinrel_restrictlist(root, joinrel,
806
0
                        outer_rel, inner_rel,
807
0
                        sjinfo);
808
0
  if (restrictlist_ptr)
809
0
    *restrictlist_ptr = restrictlist;
810
0
  build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
811
812
  /*
813
   * This is also the right place to check whether the joinrel has any
814
   * pending EquivalenceClass joins.
815
   */
816
0
  joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
817
818
  /* Store the partition information. */
819
0
  build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
820
0
                 restrictlist);
821
822
  /*
823
   * Set estimates of the joinrel's size.
824
   */
825
0
  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
826
0
                 sjinfo, restrictlist);
827
828
  /*
829
   * Set the consider_parallel flag if this joinrel could potentially be
830
   * scanned within a parallel worker.  If this flag is false for either
831
   * inner_rel or outer_rel, then it must be false for the joinrel also.
832
   * Even if both are true, there might be parallel-restricted expressions
833
   * in the targetlist or quals.
834
   *
835
   * Note that if there are more than two rels in this relation, they could
836
   * be divided between inner_rel and outer_rel in any arbitrary way.  We
837
   * assume this doesn't matter, because we should hit all the same baserels
838
   * and joinclauses while building up to this joinrel no matter which we
839
   * take; therefore, we should make the same decision here however we get
840
   * here.
841
   */
842
0
  if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
843
0
    is_parallel_safe(root, (Node *) restrictlist) &&
844
0
    is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
845
0
    joinrel->consider_parallel = true;
846
847
  /* Add the joinrel to the PlannerInfo. */
848
0
  add_join_rel(root, joinrel);
849
850
  /*
851
   * Also, if dynamic-programming join search is active, add the new joinrel
852
   * to the appropriate sublist.  Note: you might think the Assert on number
853
   * of members should be for equality, but some of the level 1 rels might
854
   * have been joinrels already, so we can only assert <=.
855
   */
856
0
  if (root->join_rel_level)
857
0
  {
858
0
    Assert(root->join_cur_level > 0);
859
0
    Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
860
0
    root->join_rel_level[root->join_cur_level] =
861
0
      lappend(root->join_rel_level[root->join_cur_level], joinrel);
862
0
  }
863
864
0
  return joinrel;
865
0
}
866
867
/*
868
 * build_child_join_rel
869
 *    Builds RelOptInfo representing join between given two child relations.
870
 *
871
 * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
872
 *    joined
873
 * 'parent_joinrel' is the RelOptInfo representing the join between parent
874
 *    relations. Some of the members of new RelOptInfo are produced by
875
 *    translating corresponding members of this RelOptInfo
876
 * 'restrictlist': list of RestrictInfo nodes that apply to this particular
877
 *    pair of joinable relations
878
 * 'sjinfo': child join's join-type details
879
 * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids
880
 */
881
RelOptInfo *
882
build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
883
           RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
884
           List *restrictlist, SpecialJoinInfo *sjinfo,
885
           int nappinfos, AppendRelInfo **appinfos)
886
0
{
887
0
  RelOptInfo *joinrel = makeNode(RelOptInfo);
888
889
  /* Only joins between "other" relations land here. */
890
0
  Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
891
892
  /* The parent joinrel should have consider_partitionwise_join set. */
893
0
  Assert(parent_joinrel->consider_partitionwise_join);
894
895
0
  joinrel->reloptkind = RELOPT_OTHER_JOINREL;
896
0
  joinrel->relids = adjust_child_relids(parent_joinrel->relids,
897
0
                      nappinfos, appinfos);
898
0
  joinrel->rows = 0;
899
  /* cheap startup cost is interesting iff not all tuples to be retrieved */
900
0
  joinrel->consider_startup = (root->tuple_fraction > 0);
901
0
  joinrel->consider_param_startup = false;
902
0
  joinrel->consider_parallel = false;
903
0
  joinrel->reltarget = create_empty_pathtarget();
904
0
  joinrel->pathlist = NIL;
905
0
  joinrel->ppilist = NIL;
906
0
  joinrel->partial_pathlist = NIL;
907
0
  joinrel->cheapest_startup_path = NULL;
908
0
  joinrel->cheapest_total_path = NULL;
909
0
  joinrel->cheapest_unique_path = NULL;
910
0
  joinrel->cheapest_parameterized_paths = NIL;
911
0
  joinrel->direct_lateral_relids = NULL;
912
0
  joinrel->lateral_relids = NULL;
913
0
  joinrel->relid = 0;     /* indicates not a baserel */
914
0
  joinrel->rtekind = RTE_JOIN;
915
0
  joinrel->min_attr = 0;
916
0
  joinrel->max_attr = 0;
917
0
  joinrel->attr_needed = NULL;
918
0
  joinrel->attr_widths = NULL;
919
0
  joinrel->notnullattnums = NULL;
920
0
  joinrel->nulling_relids = NULL;
921
0
  joinrel->lateral_vars = NIL;
922
0
  joinrel->lateral_referencers = NULL;
923
0
  joinrel->indexlist = NIL;
924
0
  joinrel->pages = 0;
925
0
  joinrel->tuples = 0;
926
0
  joinrel->allvisfrac = 0;
927
0
  joinrel->eclass_indexes = NULL;
928
0
  joinrel->subroot = NULL;
929
0
  joinrel->subplan_params = NIL;
930
0
  joinrel->amflags = 0;
931
0
  joinrel->serverid = InvalidOid;
932
0
  joinrel->userid = InvalidOid;
933
0
  joinrel->useridiscurrent = false;
934
0
  joinrel->fdwroutine = NULL;
935
0
  joinrel->fdw_private = NULL;
936
0
  joinrel->baserestrictinfo = NIL;
937
0
  joinrel->baserestrictcost.startup = 0;
938
0
  joinrel->baserestrictcost.per_tuple = 0;
939
0
  joinrel->joininfo = NIL;
940
0
  joinrel->has_eclass_joins = false;
941
0
  joinrel->consider_partitionwise_join = false; /* might get changed later */
942
0
  joinrel->parent = parent_joinrel;
943
0
  joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
944
0
  joinrel->top_parent_relids = joinrel->top_parent->relids;
945
0
  joinrel->part_scheme = NULL;
946
0
  joinrel->nparts = -1;
947
0
  joinrel->boundinfo = NULL;
948
0
  joinrel->partbounds_merged = false;
949
0
  joinrel->partition_qual = NIL;
950
0
  joinrel->part_rels = NULL;
951
0
  joinrel->live_parts = NULL;
952
0
  joinrel->all_partrels = NULL;
953
0
  joinrel->partexprs = NULL;
954
0
  joinrel->nullable_partexprs = NULL;
955
956
  /* Compute information relevant to foreign relations. */
957
0
  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
958
959
  /* Set up reltarget struct */
960
0
  build_child_join_reltarget(root, parent_joinrel, joinrel,
961
0
                 nappinfos, appinfos);
962
963
  /* Construct joininfo list. */
964
0
  joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
965
0
                            (Node *) parent_joinrel->joininfo,
966
0
                            nappinfos,
967
0
                            appinfos);
968
969
  /*
970
   * Lateral relids referred in child join will be same as that referred in
971
   * the parent relation.
972
   */
973
0
  joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
974
0
  joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
975
976
  /*
977
   * If the parent joinrel has pending equivalence classes, so does the
978
   * child.
979
   */
980
0
  joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
981
982
  /* Is the join between partitions itself partitioned? */
983
0
  build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
984
0
                 restrictlist);
985
986
  /* Child joinrel is parallel safe if parent is parallel safe. */
987
0
  joinrel->consider_parallel = parent_joinrel->consider_parallel;
988
989
  /* Set estimates of the child-joinrel's size. */
990
0
  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
991
0
                 sjinfo, restrictlist);
992
993
  /* We build the join only once. */
994
0
  Assert(!find_join_rel(root, joinrel->relids));
995
996
  /* Add the relation to the PlannerInfo. */
997
0
  add_join_rel(root, joinrel);
998
999
  /*
1000
   * We might need EquivalenceClass members corresponding to the child join,
1001
   * so that we can represent sort pathkeys for it.  As with children of
1002
   * baserels, we shouldn't need this unless there are relevant eclass joins
1003
   * (implying that a merge join might be possible) or pathkeys to sort by.
1004
   */
1005
0
  if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
1006
0
    add_child_join_rel_equivalences(root,
1007
0
                    nappinfos, appinfos,
1008
0
                    parent_joinrel, joinrel);
1009
1010
0
  return joinrel;
1011
0
}
1012
1013
/*
1014
 * min_join_parameterization
1015
 *
1016
 * Determine the minimum possible parameterization of a joinrel, that is, the
1017
 * set of other rels it contains LATERAL references to.  We save this value in
1018
 * the join's RelOptInfo.  This function is split out of build_join_rel()
1019
 * because join_is_legal() needs the value to check a prospective join.
1020
 */
1021
Relids
1022
min_join_parameterization(PlannerInfo *root,
1023
              Relids joinrelids,
1024
              RelOptInfo *outer_rel,
1025
              RelOptInfo *inner_rel)
1026
0
{
1027
0
  Relids    result;
1028
1029
  /*
1030
   * Basically we just need the union of the inputs' lateral_relids, less
1031
   * whatever is already in the join.
1032
   *
1033
   * It's not immediately obvious that this is a valid way to compute the
1034
   * result, because it might seem that we're ignoring possible lateral refs
1035
   * of PlaceHolderVars that are due to be computed at the join but not in
1036
   * either input.  However, because create_lateral_join_info() already
1037
   * charged all such PHV refs to each member baserel of the join, they'll
1038
   * be accounted for already in the inputs' lateral_relids.  Likewise, we
1039
   * do not need to worry about doing transitive closure here, because that
1040
   * was already accounted for in the original baserel lateral_relids.
1041
   */
1042
0
  result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
1043
0
  result = bms_del_members(result, joinrelids);
1044
0
  return result;
1045
0
}
1046
1047
/*
1048
 * build_joinrel_tlist
1049
 *    Builds a join relation's target list from an input relation.
1050
 *    (This is invoked twice to handle the two input relations.)
1051
 *
1052
 * The join's targetlist includes all Vars of its member relations that
1053
 * will still be needed above the join.  This subroutine adds all such
1054
 * Vars from the specified input rel's tlist to the join rel's tlist.
1055
 * Likewise for any PlaceHolderVars emitted by the input rel.
1056
 *
1057
 * We also compute the expected width of the join's output, making use
1058
 * of data that was cached at the baserel level by set_rel_width().
1059
 *
1060
 * Pass can_null as true if the join is an outer join that can null Vars
1061
 * from this input relation.  If so, we will (normally) add the join's relid
1062
 * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
1063
 *
1064
 * When forming an outer join's target list, special handling is needed in
1065
 * case the outer join was commuted with another one per outer join identity 3
1066
 * (see optimizer/README).  We must take steps to ensure that the output Vars
1067
 * have the same nulling bitmaps that they would if the two joins had been
1068
 * done in syntactic order; else they won't match Vars appearing higher in
1069
 * the query tree.  An exception to the match-the-syntactic-order rule is
1070
 * that when an outer join is pushed down into another one's RHS per identity
1071
 * 3, we can't mark its Vars as nulled until the now-upper outer join is also
1072
 * completed.  So we need to do three things:
1073
 *
1074
 * First, we add the outer join's relid to the nulling bitmap only if the
1075
 * outer join has been completely performed and the Var or PHV actually
1076
 * comes from within the syntactically nullable side(s) of the outer join.
1077
 * This takes care of the possibility that we have transformed
1078
 *    (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1079
 * to
1080
 *    A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1081
 * Here the pushed-down B/C join cannot mark C columns as nulled yet,
1082
 * while the now-upper A/B join must not mark C columns as nulled by itself.
1083
 *
1084
 * Second, perform the same operation for each SpecialJoinInfo listed in
1085
 * pushed_down_joins (which, in this example, would be the B/C join when
1086
 * we are at the now-upper A/B join).  This allows the now-upper join to
1087
 * complete the marking of "C" Vars that now have fully valid values.
1088
 *
1089
 * Third, any relid in sjinfo->commute_above_r that is already part of
1090
 * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
1091
 * This takes care of the reverse case where we implement
1092
 *    A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1093
 * as
1094
 *    (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1095
 * The C columns emitted by the B/C join need to be shown as nulled by both
1096
 * the B/C and A/B joins, even though they've not physically traversed the
1097
 * A/B join.
1098
 */
1099
static void
1100
build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
1101
          RelOptInfo *input_rel,
1102
          SpecialJoinInfo *sjinfo,
1103
          List *pushed_down_joins,
1104
          bool can_null)
1105
0
{
1106
0
  Relids    relids = joinrel->relids;
1107
0
  int64   tuple_width = joinrel->reltarget->width;
1108
0
  ListCell   *vars;
1109
0
  ListCell   *lc;
1110
1111
0
  foreach(vars, input_rel->reltarget->exprs)
1112
0
  {
1113
0
    Var      *var = (Var *) lfirst(vars);
1114
1115
    /*
1116
     * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
1117
     */
1118
0
    if (IsA(var, PlaceHolderVar))
1119
0
    {
1120
0
      PlaceHolderVar *phv = (PlaceHolderVar *) var;
1121
0
      PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
1122
1123
      /* Is it still needed above this joinrel? */
1124
0
      if (bms_nonempty_difference(phinfo->ph_needed, relids))
1125
0
      {
1126
        /*
1127
         * Yup, add it to the output.  If this join potentially nulls
1128
         * this input, we have to update the PHV's phnullingrels,
1129
         * which means making a copy.
1130
         */
1131
0
        if (can_null)
1132
0
        {
1133
0
          phv = copyObject(phv);
1134
          /* See comments above to understand this logic */
1135
0
          if (sjinfo->ojrelid != 0 &&
1136
0
            bms_is_member(sjinfo->ojrelid, relids) &&
1137
0
            (bms_is_subset(phv->phrels, sjinfo->syn_righthand) ||
1138
0
             (sjinfo->jointype == JOIN_FULL &&
1139
0
              bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
1140
0
            phv->phnullingrels = bms_add_member(phv->phnullingrels,
1141
0
                              sjinfo->ojrelid);
1142
0
          foreach(lc, pushed_down_joins)
1143
0
          {
1144
0
            SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1145
1146
0
            Assert(bms_is_member(othersj->ojrelid, relids));
1147
0
            if (bms_is_subset(phv->phrels, othersj->syn_righthand))
1148
0
              phv->phnullingrels = bms_add_member(phv->phnullingrels,
1149
0
                                othersj->ojrelid);
1150
0
          }
1151
0
          phv->phnullingrels =
1152
0
            bms_join(phv->phnullingrels,
1153
0
                 bms_intersect(sjinfo->commute_above_r,
1154
0
                         relids));
1155
0
        }
1156
1157
0
        joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1158
0
                          phv);
1159
        /* Bubbling up the precomputed result has cost zero */
1160
0
        tuple_width += phinfo->ph_width;
1161
0
      }
1162
0
      continue;
1163
0
    }
1164
1165
    /*
1166
     * Otherwise, anything in a baserel or joinrel targetlist ought to be
1167
     * a Var.  (More general cases can only appear in appendrel child
1168
     * rels, which will never be seen here.)
1169
     */
1170
0
    if (!IsA(var, Var))
1171
0
      elog(ERROR, "unexpected node type in rel targetlist: %d",
1172
0
         (int) nodeTag(var));
1173
1174
0
    if (var->varno == ROWID_VAR)
1175
0
    {
1176
      /* UPDATE/DELETE/MERGE row identity vars are always needed */
1177
0
      RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
1178
0
        list_nth(root->row_identity_vars, var->varattno - 1);
1179
1180
      /* Update reltarget width estimate from RowIdentityVarInfo */
1181
0
      tuple_width += ridinfo->rowidwidth;
1182
0
    }
1183
0
    else
1184
0
    {
1185
0
      RelOptInfo *baserel;
1186
0
      int     ndx;
1187
1188
      /* Get the Var's original base rel */
1189
0
      baserel = find_base_rel(root, var->varno);
1190
1191
      /* Is it still needed above this joinrel? */
1192
0
      ndx = var->varattno - baserel->min_attr;
1193
0
      if (!bms_nonempty_difference(baserel->attr_needed[ndx], relids))
1194
0
        continue;   /* nope, skip it */
1195
1196
      /* Update reltarget width estimate from baserel's attr_widths */
1197
0
      tuple_width += baserel->attr_widths[ndx];
1198
0
    }
1199
1200
    /*
1201
     * Add the Var to the output.  If this join potentially nulls this
1202
     * input, we have to update the Var's varnullingrels, which means
1203
     * making a copy.  But note that we don't ever add nullingrel bits to
1204
     * row identity Vars (cf. comments in setrefs.c).
1205
     */
1206
0
    if (can_null && var->varno != ROWID_VAR)
1207
0
    {
1208
0
      var = copyObject(var);
1209
      /* See comments above to understand this logic */
1210
0
      if (sjinfo->ojrelid != 0 &&
1211
0
        bms_is_member(sjinfo->ojrelid, relids) &&
1212
0
        (bms_is_member(var->varno, sjinfo->syn_righthand) ||
1213
0
         (sjinfo->jointype == JOIN_FULL &&
1214
0
          bms_is_member(var->varno, sjinfo->syn_lefthand))))
1215
0
        var->varnullingrels = bms_add_member(var->varnullingrels,
1216
0
                           sjinfo->ojrelid);
1217
0
      foreach(lc, pushed_down_joins)
1218
0
      {
1219
0
        SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1220
1221
0
        Assert(bms_is_member(othersj->ojrelid, relids));
1222
0
        if (bms_is_member(var->varno, othersj->syn_righthand))
1223
0
          var->varnullingrels = bms_add_member(var->varnullingrels,
1224
0
                             othersj->ojrelid);
1225
0
      }
1226
0
      var->varnullingrels =
1227
0
        bms_join(var->varnullingrels,
1228
0
             bms_intersect(sjinfo->commute_above_r,
1229
0
                     relids));
1230
0
    }
1231
1232
0
    joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1233
0
                      var);
1234
1235
    /* Vars have cost zero, so no need to adjust reltarget->cost */
1236
0
  }
1237
1238
0
  joinrel->reltarget->width = clamp_width_est(tuple_width);
1239
0
}
1240
1241
/*
1242
 * build_joinrel_restrictlist
1243
 * build_joinrel_joinlist
1244
 *    These routines build lists of restriction and join clauses for a
1245
 *    join relation from the joininfo lists of the relations it joins.
1246
 *
1247
 *    These routines are separate because the restriction list must be
1248
 *    built afresh for each pair of input sub-relations we consider, whereas
1249
 *    the join list need only be computed once for any join RelOptInfo.
1250
 *    The join list is fully determined by the set of rels making up the
1251
 *    joinrel, so we should get the same results (up to ordering) from any
1252
 *    candidate pair of sub-relations.  But the restriction list is whatever
1253
 *    is not handled in the sub-relations, so it depends on which
1254
 *    sub-relations are considered.
1255
 *
1256
 *    If a join clause from an input relation refers to base+OJ rels still not
1257
 *    present in the joinrel, then it is still a join clause for the joinrel;
1258
 *    we put it into the joininfo list for the joinrel.  Otherwise,
1259
 *    the clause is now a restrict clause for the joined relation, and we
1260
 *    return it to the caller of build_joinrel_restrictlist() to be stored in
1261
 *    join paths made from this pair of sub-relations.  (It will not need to
1262
 *    be considered further up the join tree.)
1263
 *
1264
 *    In many cases we will find the same RestrictInfos in both input
1265
 *    relations' joinlists, so be careful to eliminate duplicates.
1266
 *    Pointer equality should be a sufficient test for dups, since all
1267
 *    the various joinlist entries ultimately refer to RestrictInfos
1268
 *    pushed into them by distribute_restrictinfo_to_rels().
1269
 *
1270
 * 'joinrel' is a join relation node
1271
 * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
1272
 *    to form joinrel.
1273
 * 'sjinfo': join context info
1274
 *
1275
 * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
1276
 * whereas build_joinrel_joinlist() stores its results in the joinrel's
1277
 * joininfo list.  One or the other must accept each given clause!
1278
 *
1279
 * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
1280
 * up to the join relation.  I believe this is no longer necessary, because
1281
 * RestrictInfo nodes are no longer context-dependent.  Instead, just include
1282
 * the original nodes in the lists made for the join relation.
1283
 */
1284
static List *
1285
build_joinrel_restrictlist(PlannerInfo *root,
1286
               RelOptInfo *joinrel,
1287
               RelOptInfo *outer_rel,
1288
               RelOptInfo *inner_rel,
1289
               SpecialJoinInfo *sjinfo)
1290
0
{
1291
0
  List     *result;
1292
0
  Relids    both_input_relids;
1293
1294
0
  both_input_relids = bms_union(outer_rel->relids, inner_rel->relids);
1295
1296
  /*
1297
   * Collect all the clauses that syntactically belong at this level,
1298
   * eliminating any duplicates (important since we will see many of the
1299
   * same clauses arriving from both input relations).
1300
   */
1301
0
  result = subbuild_joinrel_restrictlist(root, joinrel, outer_rel,
1302
0
                       both_input_relids, NIL);
1303
0
  result = subbuild_joinrel_restrictlist(root, joinrel, inner_rel,
1304
0
                       both_input_relids, result);
1305
1306
  /*
1307
   * Add on any clauses derived from EquivalenceClasses.  These cannot be
1308
   * redundant with the clauses in the joininfo lists, so don't bother
1309
   * checking.
1310
   */
1311
0
  result = list_concat(result,
1312
0
             generate_join_implied_equalities(root,
1313
0
                              joinrel->relids,
1314
0
                              outer_rel->relids,
1315
0
                              inner_rel,
1316
0
                              sjinfo));
1317
1318
0
  return result;
1319
0
}
1320
1321
static void
1322
build_joinrel_joinlist(RelOptInfo *joinrel,
1323
             RelOptInfo *outer_rel,
1324
             RelOptInfo *inner_rel)
1325
0
{
1326
0
  List     *result;
1327
1328
  /*
1329
   * Collect all the clauses that syntactically belong above this level,
1330
   * eliminating any duplicates (important since we will see many of the
1331
   * same clauses arriving from both input relations).
1332
   */
1333
0
  result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
1334
0
  result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
1335
1336
0
  joinrel->joininfo = result;
1337
0
}
1338
1339
static List *
1340
subbuild_joinrel_restrictlist(PlannerInfo *root,
1341
                RelOptInfo *joinrel,
1342
                RelOptInfo *input_rel,
1343
                Relids both_input_relids,
1344
                List *new_restrictlist)
1345
0
{
1346
0
  ListCell   *l;
1347
1348
0
  foreach(l, input_rel->joininfo)
1349
0
  {
1350
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1351
1352
0
    if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1353
0
    {
1354
      /*
1355
       * This clause should become a restriction clause for the joinrel,
1356
       * since it refers to no outside rels.  However, if it's a clone
1357
       * clause then it might be too late to evaluate it, so we have to
1358
       * check.  (If it is too late, just ignore the clause, taking it
1359
       * on faith that another clone was or will be selected.)  Clone
1360
       * clauses should always be outer-join clauses, so we compare
1361
       * against both_input_relids.
1362
       */
1363
0
      if (rinfo->has_clone || rinfo->is_clone)
1364
0
      {
1365
0
        Assert(!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids));
1366
0
        if (!bms_is_subset(rinfo->required_relids, both_input_relids))
1367
0
          continue;
1368
0
        if (bms_overlap(rinfo->incompatible_relids, both_input_relids))
1369
0
          continue;
1370
0
      }
1371
0
      else
1372
0
      {
1373
        /*
1374
         * For non-clone clauses, we just Assert it's OK.  These might
1375
         * be either join or filter clauses; if it's a join clause
1376
         * then it should not refer to the current join's output.
1377
         * (There is little point in checking incompatible_relids,
1378
         * because it'll be NULL.)
1379
         */
1380
0
        Assert(RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids) ||
1381
0
             bms_is_subset(rinfo->required_relids,
1382
0
                   both_input_relids));
1383
0
      }
1384
1385
      /*
1386
       * OK, so add it to the list, being careful to eliminate
1387
       * duplicates.  (Since RestrictInfo nodes in different joinlists
1388
       * will have been multiply-linked rather than copied, pointer
1389
       * equality should be a sufficient test.)
1390
       */
1391
0
      new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
1392
0
    }
1393
0
    else
1394
0
    {
1395
      /*
1396
       * This clause is still a join clause at this level, so we ignore
1397
       * it in this routine.
1398
       */
1399
0
    }
1400
0
  }
1401
1402
0
  return new_restrictlist;
1403
0
}
1404
1405
static List *
1406
subbuild_joinrel_joinlist(RelOptInfo *joinrel,
1407
              List *joininfo_list,
1408
              List *new_joininfo)
1409
0
{
1410
0
  ListCell   *l;
1411
1412
  /* Expected to be called only for join between parent relations. */
1413
0
  Assert(joinrel->reloptkind == RELOPT_JOINREL);
1414
1415
0
  foreach(l, joininfo_list)
1416
0
  {
1417
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1418
1419
0
    if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1420
0
    {
1421
      /*
1422
       * This clause becomes a restriction clause for the joinrel, since
1423
       * it refers to no outside rels.  So we can ignore it in this
1424
       * routine.
1425
       */
1426
0
    }
1427
0
    else
1428
0
    {
1429
      /*
1430
       * This clause is still a join clause at this level, so add it to
1431
       * the new joininfo list, being careful to eliminate duplicates.
1432
       * (Since RestrictInfo nodes in different joinlists will have been
1433
       * multiply-linked rather than copied, pointer equality should be
1434
       * a sufficient test.)
1435
       */
1436
0
      new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
1437
0
    }
1438
0
  }
1439
1440
0
  return new_joininfo;
1441
0
}
1442
1443
1444
/*
1445
 * fetch_upper_rel
1446
 *    Build a RelOptInfo describing some post-scan/join query processing,
1447
 *    or return a pre-existing one if somebody already built it.
1448
 *
1449
 * An "upper" relation is identified by an UpperRelationKind and a Relids set.
1450
 * The meaning of the Relids set is not specified here, and very likely will
1451
 * vary for different relation kinds.
1452
 *
1453
 * Most of the fields in an upper-level RelOptInfo are not used and are not
1454
 * set here (though makeNode should ensure they're zeroes).  We basically only
1455
 * care about fields that are of interest to add_path() and set_cheapest().
1456
 */
1457
RelOptInfo *
1458
fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
1459
0
{
1460
0
  RelOptInfo *upperrel;
1461
0
  ListCell   *lc;
1462
1463
  /*
1464
   * For the moment, our indexing data structure is just a List for each
1465
   * relation kind.  If we ever get so many of one kind that this stops
1466
   * working well, we can improve it.  No code outside this function should
1467
   * assume anything about how to find a particular upperrel.
1468
   */
1469
1470
  /* If we already made this upperrel for the query, return it */
1471
0
  foreach(lc, root->upper_rels[kind])
1472
0
  {
1473
0
    upperrel = (RelOptInfo *) lfirst(lc);
1474
1475
0
    if (bms_equal(upperrel->relids, relids))
1476
0
      return upperrel;
1477
0
  }
1478
1479
0
  upperrel = makeNode(RelOptInfo);
1480
0
  upperrel->reloptkind = RELOPT_UPPER_REL;
1481
0
  upperrel->relids = bms_copy(relids);
1482
1483
  /* cheap startup cost is interesting iff not all tuples to be retrieved */
1484
0
  upperrel->consider_startup = (root->tuple_fraction > 0);
1485
0
  upperrel->consider_param_startup = false;
1486
0
  upperrel->consider_parallel = false;  /* might get changed later */
1487
0
  upperrel->reltarget = create_empty_pathtarget();
1488
0
  upperrel->pathlist = NIL;
1489
0
  upperrel->cheapest_startup_path = NULL;
1490
0
  upperrel->cheapest_total_path = NULL;
1491
0
  upperrel->cheapest_unique_path = NULL;
1492
0
  upperrel->cheapest_parameterized_paths = NIL;
1493
1494
0
  root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1495
1496
0
  return upperrel;
1497
0
}
1498
1499
1500
/*
1501
 * find_childrel_parents
1502
 *    Compute the set of parent relids of an appendrel child rel.
1503
 *
1504
 * Since appendrels can be nested, a child could have multiple levels of
1505
 * appendrel ancestors.  This function computes a Relids set of all the
1506
 * parent relation IDs.
1507
 */
1508
Relids
1509
find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
1510
0
{
1511
0
  Relids    result = NULL;
1512
1513
0
  Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1514
0
  Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
1515
1516
0
  do
1517
0
  {
1518
0
    AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
1519
0
    Index   prelid = appinfo->parent_relid;
1520
1521
0
    result = bms_add_member(result, prelid);
1522
1523
    /* traverse up to the parent rel, loop if it's also a child rel */
1524
0
    rel = find_base_rel(root, prelid);
1525
0
  } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1526
1527
0
  Assert(rel->reloptkind == RELOPT_BASEREL);
1528
1529
0
  return result;
1530
0
}
1531
1532
1533
/*
1534
 * get_baserel_parampathinfo
1535
 *    Get the ParamPathInfo for a parameterized path for a base relation,
1536
 *    constructing one if we don't have one already.
1537
 *
1538
 * This centralizes estimating the rowcounts for parameterized paths.
1539
 * We need to cache those to be sure we use the same rowcount for all paths
1540
 * of the same parameterization for a given rel.  This is also a convenient
1541
 * place to determine which movable join clauses the parameterized path will
1542
 * be responsible for evaluating.
1543
 */
1544
ParamPathInfo *
1545
get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
1546
              Relids required_outer)
1547
0
{
1548
0
  ParamPathInfo *ppi;
1549
0
  Relids    joinrelids;
1550
0
  List     *pclauses;
1551
0
  List     *eqclauses;
1552
0
  Bitmapset  *pserials;
1553
0
  double    rows;
1554
0
  ListCell   *lc;
1555
1556
  /* If rel has LATERAL refs, every path for it should account for them */
1557
0
  Assert(bms_is_subset(baserel->lateral_relids, required_outer));
1558
1559
  /* Unparameterized paths have no ParamPathInfo */
1560
0
  if (bms_is_empty(required_outer))
1561
0
    return NULL;
1562
1563
0
  Assert(!bms_overlap(baserel->relids, required_outer));
1564
1565
  /* If we already have a PPI for this parameterization, just return it */
1566
0
  if ((ppi = find_param_path_info(baserel, required_outer)))
1567
0
    return ppi;
1568
1569
  /*
1570
   * Identify all joinclauses that are movable to this base rel given this
1571
   * parameterization.
1572
   */
1573
0
  joinrelids = bms_union(baserel->relids, required_outer);
1574
0
  pclauses = NIL;
1575
0
  foreach(lc, baserel->joininfo)
1576
0
  {
1577
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1578
1579
0
    if (join_clause_is_movable_into(rinfo,
1580
0
                    baserel->relids,
1581
0
                    joinrelids))
1582
0
      pclauses = lappend(pclauses, rinfo);
1583
0
  }
1584
1585
  /*
1586
   * Add in joinclauses generated by EquivalenceClasses, too.  (These
1587
   * necessarily satisfy join_clause_is_movable_into; but in assert-enabled
1588
   * builds, let's verify that.)
1589
   */
1590
0
  eqclauses = generate_join_implied_equalities(root,
1591
0
                         joinrelids,
1592
0
                         required_outer,
1593
0
                         baserel,
1594
0
                         NULL);
1595
#ifdef USE_ASSERT_CHECKING
1596
  foreach(lc, eqclauses)
1597
  {
1598
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1599
1600
    Assert(join_clause_is_movable_into(rinfo,
1601
                       baserel->relids,
1602
                       joinrelids));
1603
  }
1604
#endif
1605
0
  pclauses = list_concat(pclauses, eqclauses);
1606
1607
  /* Compute set of serial numbers of the enforced clauses */
1608
0
  pserials = NULL;
1609
0
  foreach(lc, pclauses)
1610
0
  {
1611
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1612
1613
0
    pserials = bms_add_member(pserials, rinfo->rinfo_serial);
1614
0
  }
1615
1616
  /* Estimate the number of rows returned by the parameterized scan */
1617
0
  rows = get_parameterized_baserel_size(root, baserel, pclauses);
1618
1619
  /* And now we can build the ParamPathInfo */
1620
0
  ppi = makeNode(ParamPathInfo);
1621
0
  ppi->ppi_req_outer = required_outer;
1622
0
  ppi->ppi_rows = rows;
1623
0
  ppi->ppi_clauses = pclauses;
1624
0
  ppi->ppi_serials = pserials;
1625
0
  baserel->ppilist = lappend(baserel->ppilist, ppi);
1626
1627
0
  return ppi;
1628
0
}
1629
1630
/*
1631
 * get_joinrel_parampathinfo
1632
 *    Get the ParamPathInfo for a parameterized path for a join relation,
1633
 *    constructing one if we don't have one already.
1634
 *
1635
 * This centralizes estimating the rowcounts for parameterized paths.
1636
 * We need to cache those to be sure we use the same rowcount for all paths
1637
 * of the same parameterization for a given rel.  This is also a convenient
1638
 * place to determine which movable join clauses the parameterized path will
1639
 * be responsible for evaluating.
1640
 *
1641
 * outer_path and inner_path are a pair of input paths that can be used to
1642
 * construct the join, and restrict_clauses is the list of regular join
1643
 * clauses (including clauses derived from EquivalenceClasses) that must be
1644
 * applied at the join node when using these inputs.
1645
 *
1646
 * Unlike the situation for base rels, the set of movable join clauses to be
1647
 * enforced at a join varies with the selected pair of input paths, so we
1648
 * must calculate that and pass it back, even if we already have a matching
1649
 * ParamPathInfo.  We handle this by adding any clauses moved down to this
1650
 * join to *restrict_clauses, which is an in/out parameter.  (The addition
1651
 * is done in such a way as to not modify the passed-in List structure.)
1652
 *
1653
 * Note: when considering a nestloop join, the caller must have removed from
1654
 * restrict_clauses any movable clauses that are themselves scheduled to be
1655
 * pushed into the right-hand path.  We do not do that here since it's
1656
 * unnecessary for other join types.
1657
 */
1658
ParamPathInfo *
1659
get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
1660
              Path *outer_path,
1661
              Path *inner_path,
1662
              SpecialJoinInfo *sjinfo,
1663
              Relids required_outer,
1664
              List **restrict_clauses)
1665
0
{
1666
0
  ParamPathInfo *ppi;
1667
0
  Relids    join_and_req;
1668
0
  Relids    outer_and_req;
1669
0
  Relids    inner_and_req;
1670
0
  List     *pclauses;
1671
0
  List     *eclauses;
1672
0
  List     *dropped_ecs;
1673
0
  double    rows;
1674
0
  ListCell   *lc;
1675
1676
  /* If rel has LATERAL refs, every path for it should account for them */
1677
0
  Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
1678
1679
  /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1680
0
  if (bms_is_empty(required_outer))
1681
0
    return NULL;
1682
1683
0
  Assert(!bms_overlap(joinrel->relids, required_outer));
1684
1685
  /*
1686
   * Identify all joinclauses that are movable to this join rel given this
1687
   * parameterization.  These are the clauses that are movable into this
1688
   * join, but not movable into either input path.  Treat an unparameterized
1689
   * input path as not accepting parameterized clauses (because it won't,
1690
   * per the shortcut exit above), even though the joinclause movement rules
1691
   * might allow the same clauses to be moved into a parameterized path for
1692
   * that rel.
1693
   */
1694
0
  join_and_req = bms_union(joinrel->relids, required_outer);
1695
0
  if (outer_path->param_info)
1696
0
    outer_and_req = bms_union(outer_path->parent->relids,
1697
0
                  PATH_REQ_OUTER(outer_path));
1698
0
  else
1699
0
    outer_and_req = NULL; /* outer path does not accept parameters */
1700
0
  if (inner_path->param_info)
1701
0
    inner_and_req = bms_union(inner_path->parent->relids,
1702
0
                  PATH_REQ_OUTER(inner_path));
1703
0
  else
1704
0
    inner_and_req = NULL; /* inner path does not accept parameters */
1705
1706
0
  pclauses = NIL;
1707
0
  foreach(lc, joinrel->joininfo)
1708
0
  {
1709
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1710
1711
0
    if (join_clause_is_movable_into(rinfo,
1712
0
                    joinrel->relids,
1713
0
                    join_and_req) &&
1714
0
      !join_clause_is_movable_into(rinfo,
1715
0
                     outer_path->parent->relids,
1716
0
                     outer_and_req) &&
1717
0
      !join_clause_is_movable_into(rinfo,
1718
0
                     inner_path->parent->relids,
1719
0
                     inner_and_req))
1720
0
      pclauses = lappend(pclauses, rinfo);
1721
0
  }
1722
1723
  /* Consider joinclauses generated by EquivalenceClasses, too */
1724
0
  eclauses = generate_join_implied_equalities(root,
1725
0
                        join_and_req,
1726
0
                        required_outer,
1727
0
                        joinrel,
1728
0
                        NULL);
1729
  /* We only want ones that aren't movable to lower levels */
1730
0
  dropped_ecs = NIL;
1731
0
  foreach(lc, eclauses)
1732
0
  {
1733
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1734
1735
0
    Assert(join_clause_is_movable_into(rinfo,
1736
0
                       joinrel->relids,
1737
0
                       join_and_req));
1738
0
    if (join_clause_is_movable_into(rinfo,
1739
0
                    outer_path->parent->relids,
1740
0
                    outer_and_req))
1741
0
      continue;     /* drop if movable into LHS */
1742
0
    if (join_clause_is_movable_into(rinfo,
1743
0
                    inner_path->parent->relids,
1744
0
                    inner_and_req))
1745
0
    {
1746
      /* drop if movable into RHS, but remember EC for use below */
1747
0
      Assert(rinfo->left_ec == rinfo->right_ec);
1748
0
      dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1749
0
      continue;
1750
0
    }
1751
0
    pclauses = lappend(pclauses, rinfo);
1752
0
  }
1753
1754
  /*
1755
   * EquivalenceClasses are harder to deal with than we could wish, because
1756
   * of the fact that a given EC can generate different clauses depending on
1757
   * context.  Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1758
   * LHS and RHS of the current join and Z is in required_outer, and further
1759
   * suppose that the inner_path is parameterized by both X and Z.  The code
1760
   * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1761
   * and in the latter case will have discarded it as being movable into the
1762
   * RHS.  However, the EC machinery might have produced either Y.Y = X.X or
1763
   * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1764
   * not have produced both, and we can't readily tell from here which one
1765
   * it did pick.  If we add no clause to this join, we'll end up with
1766
   * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1767
   * constrained to be equal to the other members of the EC.  (When we come
1768
   * to join Z to this X/Y path, we will certainly drop whichever EC clause
1769
   * is generated at that join, so this omission won't get fixed later.)
1770
   *
1771
   * To handle this, for each EC we discarded such a clause from, try to
1772
   * generate a clause connecting the required_outer rels to the join's LHS
1773
   * ("Z.Z = X.X" in the terms of the above example).  If successful, and if
1774
   * the clause can't be moved to the LHS, add it to the current join's
1775
   * restriction clauses.  (If an EC cannot generate such a clause then it
1776
   * has nothing that needs to be enforced here, while if the clause can be
1777
   * moved into the LHS then it should have been enforced within that path.)
1778
   *
1779
   * Note that we don't need similar processing for ECs whose clause was
1780
   * considered to be movable into the LHS, because the LHS can't refer to
1781
   * the RHS so there is no comparable ambiguity about what it might
1782
   * actually be enforcing internally.
1783
   */
1784
0
  if (dropped_ecs)
1785
0
  {
1786
0
    Relids    real_outer_and_req;
1787
1788
0
    real_outer_and_req = bms_union(outer_path->parent->relids,
1789
0
                     required_outer);
1790
0
    eclauses =
1791
0
      generate_join_implied_equalities_for_ecs(root,
1792
0
                           dropped_ecs,
1793
0
                           real_outer_and_req,
1794
0
                           required_outer,
1795
0
                           outer_path->parent);
1796
0
    foreach(lc, eclauses)
1797
0
    {
1798
0
      RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1799
1800
0
      Assert(join_clause_is_movable_into(rinfo,
1801
0
                         outer_path->parent->relids,
1802
0
                         real_outer_and_req));
1803
0
      if (!join_clause_is_movable_into(rinfo,
1804
0
                       outer_path->parent->relids,
1805
0
                       outer_and_req))
1806
0
        pclauses = lappend(pclauses, rinfo);
1807
0
    }
1808
0
  }
1809
1810
  /*
1811
   * Now, attach the identified moved-down clauses to the caller's
1812
   * restrict_clauses list.  By using list_concat in this order, we leave
1813
   * the original list structure of restrict_clauses undamaged.
1814
   */
1815
0
  *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1816
1817
  /* If we already have a PPI for this parameterization, just return it */
1818
0
  if ((ppi = find_param_path_info(joinrel, required_outer)))
1819
0
    return ppi;
1820
1821
  /* Estimate the number of rows returned by the parameterized join */
1822
0
  rows = get_parameterized_joinrel_size(root, joinrel,
1823
0
                      outer_path,
1824
0
                      inner_path,
1825
0
                      sjinfo,
1826
0
                      *restrict_clauses);
1827
1828
  /*
1829
   * And now we can build the ParamPathInfo.  No point in saving the
1830
   * input-pair-dependent clause list, though.
1831
   *
1832
   * Note: in GEQO mode, we'll be called in a temporary memory context, but
1833
   * the joinrel structure is there too, so no problem.
1834
   */
1835
0
  ppi = makeNode(ParamPathInfo);
1836
0
  ppi->ppi_req_outer = required_outer;
1837
0
  ppi->ppi_rows = rows;
1838
0
  ppi->ppi_clauses = NIL;
1839
0
  ppi->ppi_serials = NULL;
1840
0
  joinrel->ppilist = lappend(joinrel->ppilist, ppi);
1841
1842
0
  return ppi;
1843
0
}
1844
1845
/*
1846
 * get_appendrel_parampathinfo
1847
 *    Get the ParamPathInfo for a parameterized path for an append relation.
1848
 *
1849
 * For an append relation, the rowcount estimate will just be the sum of
1850
 * the estimates for its children.  However, we still need a ParamPathInfo
1851
 * to flag the fact that the path requires parameters.  So this just creates
1852
 * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
1853
 * the Append node isn't responsible for checking quals).
1854
 */
1855
ParamPathInfo *
1856
get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
1857
0
{
1858
0
  ParamPathInfo *ppi;
1859
1860
  /* If rel has LATERAL refs, every path for it should account for them */
1861
0
  Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
1862
1863
  /* Unparameterized paths have no ParamPathInfo */
1864
0
  if (bms_is_empty(required_outer))
1865
0
    return NULL;
1866
1867
0
  Assert(!bms_overlap(appendrel->relids, required_outer));
1868
1869
  /* If we already have a PPI for this parameterization, just return it */
1870
0
  if ((ppi = find_param_path_info(appendrel, required_outer)))
1871
0
    return ppi;
1872
1873
  /* Else build the ParamPathInfo */
1874
0
  ppi = makeNode(ParamPathInfo);
1875
0
  ppi->ppi_req_outer = required_outer;
1876
0
  ppi->ppi_rows = 0;
1877
0
  ppi->ppi_clauses = NIL;
1878
0
  ppi->ppi_serials = NULL;
1879
0
  appendrel->ppilist = lappend(appendrel->ppilist, ppi);
1880
1881
0
  return ppi;
1882
0
}
1883
1884
/*
1885
 * Returns a ParamPathInfo for the parameterization given by required_outer, if
1886
 * already available in the given rel. Returns NULL otherwise.
1887
 */
1888
ParamPathInfo *
1889
find_param_path_info(RelOptInfo *rel, Relids required_outer)
1890
0
{
1891
0
  ListCell   *lc;
1892
1893
0
  foreach(lc, rel->ppilist)
1894
0
  {
1895
0
    ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
1896
1897
0
    if (bms_equal(ppi->ppi_req_outer, required_outer))
1898
0
      return ppi;
1899
0
  }
1900
1901
0
  return NULL;
1902
0
}
1903
1904
/*
1905
 * get_param_path_clause_serials
1906
 *    Given a parameterized Path, return the set of pushed-down clauses
1907
 *    (identified by rinfo_serial numbers) enforced within the Path.
1908
 */
1909
Bitmapset *
1910
get_param_path_clause_serials(Path *path)
1911
0
{
1912
0
  if (path->param_info == NULL)
1913
0
    return NULL;     /* not parameterized */
1914
1915
  /*
1916
   * We don't currently support parameterized MergeAppend paths, as
1917
   * explained in the comments for generate_orderedappend_paths.
1918
   */
1919
0
  Assert(!IsA(path, MergeAppendPath));
1920
1921
0
  if (IsA(path, NestPath) ||
1922
0
    IsA(path, MergePath) ||
1923
0
    IsA(path, HashPath))
1924
0
  {
1925
    /*
1926
     * For a join path, combine clauses enforced within either input path
1927
     * with those enforced as joinrestrictinfo in this path.  Note that
1928
     * joinrestrictinfo may include some non-pushed-down clauses, but for
1929
     * current purposes it's okay if we include those in the result. (To
1930
     * be more careful, we could check for clause_relids overlapping the
1931
     * path parameterization, but it's not worth the cycles for now.)
1932
     */
1933
0
    JoinPath   *jpath = (JoinPath *) path;
1934
0
    Bitmapset  *pserials;
1935
0
    ListCell   *lc;
1936
1937
0
    pserials = NULL;
1938
0
    pserials = bms_add_members(pserials,
1939
0
                   get_param_path_clause_serials(jpath->outerjoinpath));
1940
0
    pserials = bms_add_members(pserials,
1941
0
                   get_param_path_clause_serials(jpath->innerjoinpath));
1942
0
    foreach(lc, jpath->joinrestrictinfo)
1943
0
    {
1944
0
      RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1945
1946
0
      pserials = bms_add_member(pserials, rinfo->rinfo_serial);
1947
0
    }
1948
0
    return pserials;
1949
0
  }
1950
0
  else if (IsA(path, AppendPath))
1951
0
  {
1952
    /*
1953
     * For an appendrel, take the intersection of the sets of clauses
1954
     * enforced in each input path.
1955
     */
1956
0
    AppendPath *apath = (AppendPath *) path;
1957
0
    Bitmapset  *pserials;
1958
0
    ListCell   *lc;
1959
1960
0
    pserials = NULL;
1961
0
    foreach(lc, apath->subpaths)
1962
0
    {
1963
0
      Path     *subpath = (Path *) lfirst(lc);
1964
0
      Bitmapset  *subserials;
1965
1966
0
      subserials = get_param_path_clause_serials(subpath);
1967
0
      if (lc == list_head(apath->subpaths))
1968
0
        pserials = bms_copy(subserials);
1969
0
      else
1970
0
        pserials = bms_int_members(pserials, subserials);
1971
0
    }
1972
0
    return pserials;
1973
0
  }
1974
0
  else
1975
0
  {
1976
    /*
1977
     * Otherwise, it's a baserel path and we can use the
1978
     * previously-computed set of serial numbers.
1979
     */
1980
0
    return path->param_info->ppi_serials;
1981
0
  }
1982
0
}
1983
1984
/*
1985
 * build_joinrel_partition_info
1986
 *    Checks if the two relations being joined can use partitionwise join
1987
 *    and if yes, initialize partitioning information of the resulting
1988
 *    partitioned join relation.
1989
 */
1990
static void
1991
build_joinrel_partition_info(PlannerInfo *root,
1992
               RelOptInfo *joinrel, RelOptInfo *outer_rel,
1993
               RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo,
1994
               List *restrictlist)
1995
0
{
1996
0
  PartitionScheme part_scheme;
1997
1998
  /* Nothing to do if partitionwise join technique is disabled. */
1999
0
  if (!enable_partitionwise_join)
2000
0
  {
2001
0
    Assert(!IS_PARTITIONED_REL(joinrel));
2002
0
    return;
2003
0
  }
2004
2005
  /*
2006
   * We can only consider this join as an input to further partitionwise
2007
   * joins if (a) the input relations are partitioned and have
2008
   * consider_partitionwise_join=true, (b) the partition schemes match, and
2009
   * (c) we can identify an equi-join between the partition keys.  Note that
2010
   * if it were possible for have_partkey_equi_join to return different
2011
   * answers for the same joinrel depending on which join ordering we try
2012
   * first, this logic would break.  That shouldn't happen, though, because
2013
   * of the way the query planner deduces implied equalities and reorders
2014
   * the joins.  Please see optimizer/README for details.
2015
   */
2016
0
  if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
2017
0
    !outer_rel->consider_partitionwise_join ||
2018
0
    !inner_rel->consider_partitionwise_join ||
2019
0
    outer_rel->part_scheme != inner_rel->part_scheme ||
2020
0
    !have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
2021
0
                sjinfo->jointype, restrictlist))
2022
0
  {
2023
0
    Assert(!IS_PARTITIONED_REL(joinrel));
2024
0
    return;
2025
0
  }
2026
2027
0
  part_scheme = outer_rel->part_scheme;
2028
2029
  /*
2030
   * This function will be called only once for each joinrel, hence it
2031
   * should not have partitioning fields filled yet.
2032
   */
2033
0
  Assert(!joinrel->part_scheme && !joinrel->partexprs &&
2034
0
       !joinrel->nullable_partexprs && !joinrel->part_rels &&
2035
0
       !joinrel->boundinfo);
2036
2037
  /*
2038
   * If the join relation is partitioned, it uses the same partitioning
2039
   * scheme as the joining relations.
2040
   *
2041
   * Note: we calculate the partition bounds, number of partitions, and
2042
   * child-join relations of the join relation in try_partitionwise_join().
2043
   */
2044
0
  joinrel->part_scheme = part_scheme;
2045
0
  set_joinrel_partition_key_exprs(joinrel, outer_rel, inner_rel,
2046
0
                  sjinfo->jointype);
2047
2048
  /*
2049
   * Set the consider_partitionwise_join flag.
2050
   */
2051
0
  Assert(outer_rel->consider_partitionwise_join);
2052
0
  Assert(inner_rel->consider_partitionwise_join);
2053
0
  joinrel->consider_partitionwise_join = true;
2054
0
}
2055
2056
/*
2057
 * have_partkey_equi_join
2058
 *
2059
 * Returns true if there exist equi-join conditions involving pairs
2060
 * of matching partition keys of the relations being joined for all
2061
 * partition keys.
2062
 */
2063
static bool
2064
have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
2065
             RelOptInfo *rel1, RelOptInfo *rel2,
2066
             JoinType jointype, List *restrictlist)
2067
0
{
2068
0
  PartitionScheme part_scheme = rel1->part_scheme;
2069
0
  bool    pk_known_equal[PARTITION_MAX_KEYS];
2070
0
  int     num_equal_pks;
2071
0
  ListCell   *lc;
2072
2073
  /*
2074
   * This function must only be called when the joined relations have same
2075
   * partitioning scheme.
2076
   */
2077
0
  Assert(rel1->part_scheme == rel2->part_scheme);
2078
0
  Assert(part_scheme);
2079
2080
  /* We use a bool array to track which partkey columns are known equal */
2081
0
  memset(pk_known_equal, 0, sizeof(pk_known_equal));
2082
  /* ... as well as a count of how many are known equal */
2083
0
  num_equal_pks = 0;
2084
2085
  /* First, look through the join's restriction clauses */
2086
0
  foreach(lc, restrictlist)
2087
0
  {
2088
0
    RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
2089
0
    OpExpr     *opexpr;
2090
0
    Expr     *expr1;
2091
0
    Expr     *expr2;
2092
0
    bool    strict_op;
2093
0
    int     ipk1;
2094
0
    int     ipk2;
2095
2096
    /* If processing an outer join, only use its own join clauses. */
2097
0
    if (IS_OUTER_JOIN(jointype) &&
2098
0
      RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
2099
0
      continue;
2100
2101
    /* Skip clauses which can not be used for a join. */
2102
0
    if (!rinfo->can_join)
2103
0
      continue;
2104
2105
    /* Skip clauses which are not equality conditions. */
2106
0
    if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
2107
0
      continue;
2108
2109
    /* Should be OK to assume it's an OpExpr. */
2110
0
    opexpr = castNode(OpExpr, rinfo->clause);
2111
2112
    /* Match the operands to the relation. */
2113
0
    if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
2114
0
      bms_is_subset(rinfo->right_relids, rel2->relids))
2115
0
    {
2116
0
      expr1 = linitial(opexpr->args);
2117
0
      expr2 = lsecond(opexpr->args);
2118
0
    }
2119
0
    else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
2120
0
         bms_is_subset(rinfo->right_relids, rel1->relids))
2121
0
    {
2122
0
      expr1 = lsecond(opexpr->args);
2123
0
      expr2 = linitial(opexpr->args);
2124
0
    }
2125
0
    else
2126
0
      continue;
2127
2128
    /*
2129
     * Now we need to know whether the join operator is strict; see
2130
     * comments in pathnodes.h.
2131
     */
2132
0
    strict_op = op_strict(opexpr->opno);
2133
2134
    /*
2135
     * Vars appearing in the relation's partition keys will not have any
2136
     * varnullingrels, but those in expr1 and expr2 will if we're above
2137
     * outer joins that could null the respective rels.  It's okay to
2138
     * match anyway, if the join operator is strict.
2139
     */
2140
0
    if (strict_op)
2141
0
    {
2142
0
      if (bms_overlap(rel1->relids, root->outer_join_rels))
2143
0
        expr1 = (Expr *) remove_nulling_relids((Node *) expr1,
2144
0
                             root->outer_join_rels,
2145
0
                             NULL);
2146
0
      if (bms_overlap(rel2->relids, root->outer_join_rels))
2147
0
        expr2 = (Expr *) remove_nulling_relids((Node *) expr2,
2148
0
                             root->outer_join_rels,
2149
0
                             NULL);
2150
0
    }
2151
2152
    /*
2153
     * Only clauses referencing the partition keys are useful for
2154
     * partitionwise join.
2155
     */
2156
0
    ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
2157
0
    if (ipk1 < 0)
2158
0
      continue;
2159
0
    ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
2160
0
    if (ipk2 < 0)
2161
0
      continue;
2162
2163
    /*
2164
     * If the clause refers to keys at different ordinal positions, it can
2165
     * not be used for partitionwise join.
2166
     */
2167
0
    if (ipk1 != ipk2)
2168
0
      continue;
2169
2170
    /* Ignore clause if we already proved these keys equal. */
2171
0
    if (pk_known_equal[ipk1])
2172
0
      continue;
2173
2174
    /* Reject if the partition key collation differs from the clause's. */
2175
0
    if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
2176
0
      return false;
2177
2178
    /*
2179
     * The clause allows partitionwise join only if it uses the same
2180
     * operator family as that specified by the partition key.
2181
     */
2182
0
    if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2183
0
    {
2184
0
      if (!OidIsValid(rinfo->hashjoinoperator) ||
2185
0
        !op_in_opfamily(rinfo->hashjoinoperator,
2186
0
                part_scheme->partopfamily[ipk1]))
2187
0
        continue;
2188
0
    }
2189
0
    else if (!list_member_oid(rinfo->mergeopfamilies,
2190
0
                  part_scheme->partopfamily[ipk1]))
2191
0
      continue;
2192
2193
    /* Mark the partition key as having an equi-join clause. */
2194
0
    pk_known_equal[ipk1] = true;
2195
2196
    /* We can stop examining clauses once we prove all keys equal. */
2197
0
    if (++num_equal_pks == part_scheme->partnatts)
2198
0
      return true;
2199
0
  }
2200
2201
  /*
2202
   * Also check to see if any keys are known equal by equivclass.c.  In most
2203
   * cases there would have been a join restriction clause generated from
2204
   * any EC that had such knowledge, but there might be no such clause, or
2205
   * it might happen to constrain other members of the ECs than the ones we
2206
   * are looking for.
2207
   */
2208
0
  for (int ipk = 0; ipk < part_scheme->partnatts; ipk++)
2209
0
  {
2210
0
    Oid     btree_opfamily;
2211
2212
    /* Ignore if we already proved these keys equal. */
2213
0
    if (pk_known_equal[ipk])
2214
0
      continue;
2215
2216
    /*
2217
     * We need a btree opfamily to ask equivclass.c about.  If the
2218
     * partopfamily is a hash opfamily, look up its equality operator, and
2219
     * select some btree opfamily that that operator is part of.  (Any
2220
     * such opfamily should be good enough, since equivclass.c will track
2221
     * multiple opfamilies as appropriate.)
2222
     */
2223
0
    if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2224
0
    {
2225
0
      Oid     eq_op;
2226
0
      List     *eq_opfamilies;
2227
2228
0
      eq_op = get_opfamily_member(part_scheme->partopfamily[ipk],
2229
0
                    part_scheme->partopcintype[ipk],
2230
0
                    part_scheme->partopcintype[ipk],
2231
0
                    HTEqualStrategyNumber);
2232
0
      if (!OidIsValid(eq_op))
2233
0
        break;     /* we're not going to succeed */
2234
0
      eq_opfamilies = get_mergejoin_opfamilies(eq_op);
2235
0
      if (eq_opfamilies == NIL)
2236
0
        break;     /* we're not going to succeed */
2237
0
      btree_opfamily = linitial_oid(eq_opfamilies);
2238
0
    }
2239
0
    else
2240
0
      btree_opfamily = part_scheme->partopfamily[ipk];
2241
2242
    /*
2243
     * We consider only non-nullable partition keys here; nullable ones
2244
     * would not be treated as part of the same equivalence classes as
2245
     * non-nullable ones.
2246
     */
2247
0
    foreach(lc, rel1->partexprs[ipk])
2248
0
    {
2249
0
      Node     *expr1 = (Node *) lfirst(lc);
2250
0
      ListCell   *lc2;
2251
0
      Oid     partcoll1 = rel1->part_scheme->partcollation[ipk];
2252
0
      Oid     exprcoll1 = exprCollation(expr1);
2253
2254
0
      foreach(lc2, rel2->partexprs[ipk])
2255
0
      {
2256
0
        Node     *expr2 = (Node *) lfirst(lc2);
2257
2258
0
        if (exprs_known_equal(root, expr1, expr2, btree_opfamily))
2259
0
        {
2260
          /*
2261
           * Ensure that the collation of the expression matches
2262
           * that of the partition key. Checking just one collation
2263
           * (partcoll1 and exprcoll1) suffices because partcoll1
2264
           * and partcoll2, as well as exprcoll1 and exprcoll2,
2265
           * should be identical. This holds because both rel1 and
2266
           * rel2 use the same PartitionScheme and expr1 and expr2
2267
           * are equal.
2268
           */
2269
0
          if (partcoll1 == exprcoll1)
2270
0
          {
2271
0
            Oid     partcoll2 PG_USED_FOR_ASSERTS_ONLY =
2272
0
              rel2->part_scheme->partcollation[ipk];
2273
0
            Oid     exprcoll2 PG_USED_FOR_ASSERTS_ONLY =
2274
0
              exprCollation(expr2);
2275
2276
0
            Assert(partcoll2 == exprcoll2);
2277
0
            pk_known_equal[ipk] = true;
2278
0
            break;
2279
0
          }
2280
0
        }
2281
0
      }
2282
0
      if (pk_known_equal[ipk])
2283
0
        break;
2284
0
    }
2285
2286
0
    if (pk_known_equal[ipk])
2287
0
    {
2288
      /* We can stop examining keys once we prove all keys equal. */
2289
0
      if (++num_equal_pks == part_scheme->partnatts)
2290
0
        return true;
2291
0
    }
2292
0
    else
2293
0
      break;       /* no chance to succeed, give up */
2294
0
  }
2295
2296
0
  return false;
2297
0
}
2298
2299
/*
2300
 * match_expr_to_partition_keys
2301
 *
2302
 * Tries to match an expression to one of the nullable or non-nullable
2303
 * partition keys of "rel".  Returns the matched key's ordinal position,
2304
 * or -1 if the expression could not be matched to any of the keys.
2305
 *
2306
 * strict_op must be true if the expression will be compared with the
2307
 * partition key using a strict operator.  This allows us to consider
2308
 * nullable as well as nonnullable partition keys.
2309
 */
2310
static int
2311
match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
2312
0
{
2313
0
  int     cnt;
2314
2315
  /* This function should be called only for partitioned relations. */
2316
0
  Assert(rel->part_scheme);
2317
0
  Assert(rel->partexprs);
2318
0
  Assert(rel->nullable_partexprs);
2319
2320
  /* Remove any relabel decorations. */
2321
0
  while (IsA(expr, RelabelType))
2322
0
    expr = (Expr *) (castNode(RelabelType, expr))->arg;
2323
2324
0
  for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
2325
0
  {
2326
0
    ListCell   *lc;
2327
2328
    /* We can always match to the non-nullable partition keys. */
2329
0
    foreach(lc, rel->partexprs[cnt])
2330
0
    {
2331
0
      if (equal(lfirst(lc), expr))
2332
0
        return cnt;
2333
0
    }
2334
2335
0
    if (!strict_op)
2336
0
      continue;
2337
2338
    /*
2339
     * If it's a strict join operator then a NULL partition key on one
2340
     * side will not join to any partition key on the other side, and in
2341
     * particular such a row can't join to a row from a different
2342
     * partition on the other side.  So, it's okay to search the nullable
2343
     * partition keys as well.
2344
     */
2345
0
    foreach(lc, rel->nullable_partexprs[cnt])
2346
0
    {
2347
0
      if (equal(lfirst(lc), expr))
2348
0
        return cnt;
2349
0
    }
2350
0
  }
2351
2352
0
  return -1;
2353
0
}
2354
2355
/*
2356
 * set_joinrel_partition_key_exprs
2357
 *    Initialize partition key expressions for a partitioned joinrel.
2358
 */
2359
static void
2360
set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
2361
                RelOptInfo *outer_rel, RelOptInfo *inner_rel,
2362
                JoinType jointype)
2363
0
{
2364
0
  PartitionScheme part_scheme = joinrel->part_scheme;
2365
0
  int     partnatts = part_scheme->partnatts;
2366
2367
0
  joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
2368
0
  joinrel->nullable_partexprs =
2369
0
    (List **) palloc0(sizeof(List *) * partnatts);
2370
2371
  /*
2372
   * The joinrel's partition expressions are the same as those of the input
2373
   * rels, but we must properly classify them as nullable or not in the
2374
   * joinrel's output.  (Also, we add some more partition expressions if
2375
   * it's a FULL JOIN.)
2376
   */
2377
0
  for (int cnt = 0; cnt < partnatts; cnt++)
2378
0
  {
2379
    /* mark these const to enforce that we copy them properly */
2380
0
    const List *outer_expr = outer_rel->partexprs[cnt];
2381
0
    const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
2382
0
    const List *inner_expr = inner_rel->partexprs[cnt];
2383
0
    const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
2384
0
    List     *partexpr = NIL;
2385
0
    List     *nullable_partexpr = NIL;
2386
0
    ListCell   *lc;
2387
2388
0
    switch (jointype)
2389
0
    {
2390
        /*
2391
         * A join relation resulting from an INNER join may be
2392
         * regarded as partitioned by either of the inner and outer
2393
         * relation keys.  For example, A INNER JOIN B ON A.a = B.b
2394
         * can be regarded as partitioned on either A.a or B.b.  So we
2395
         * add both keys to the joinrel's partexpr lists.  However,
2396
         * anything that was already nullable still has to be treated
2397
         * as nullable.
2398
         */
2399
0
      case JOIN_INNER:
2400
0
        partexpr = list_concat_copy(outer_expr, inner_expr);
2401
0
        nullable_partexpr = list_concat_copy(outer_null_expr,
2402
0
                           inner_null_expr);
2403
0
        break;
2404
2405
        /*
2406
         * A join relation resulting from a SEMI or ANTI join may be
2407
         * regarded as partitioned by the outer relation keys.  The
2408
         * inner relation's keys are no longer interesting; since they
2409
         * aren't visible in the join output, nothing could join to
2410
         * them.
2411
         */
2412
0
      case JOIN_SEMI:
2413
0
      case JOIN_ANTI:
2414
0
        partexpr = list_copy(outer_expr);
2415
0
        nullable_partexpr = list_copy(outer_null_expr);
2416
0
        break;
2417
2418
        /*
2419
         * A join relation resulting from a LEFT OUTER JOIN likewise
2420
         * may be regarded as partitioned on the (non-nullable) outer
2421
         * relation keys.  The inner (nullable) relation keys are okay
2422
         * as partition keys for further joins as long as they involve
2423
         * strict join operators.
2424
         */
2425
0
      case JOIN_LEFT:
2426
0
        partexpr = list_copy(outer_expr);
2427
0
        nullable_partexpr = list_concat_copy(inner_expr,
2428
0
                           outer_null_expr);
2429
0
        nullable_partexpr = list_concat(nullable_partexpr,
2430
0
                        inner_null_expr);
2431
0
        break;
2432
2433
        /*
2434
         * For FULL OUTER JOINs, both relations are nullable, so the
2435
         * resulting join relation may be regarded as partitioned on
2436
         * either of inner and outer relation keys, but only for joins
2437
         * that involve strict join operators.
2438
         */
2439
0
      case JOIN_FULL:
2440
0
        nullable_partexpr = list_concat_copy(outer_expr,
2441
0
                           inner_expr);
2442
0
        nullable_partexpr = list_concat(nullable_partexpr,
2443
0
                        outer_null_expr);
2444
0
        nullable_partexpr = list_concat(nullable_partexpr,
2445
0
                        inner_null_expr);
2446
2447
        /*
2448
         * Also add CoalesceExprs corresponding to each possible
2449
         * full-join output variable (that is, left side coalesced to
2450
         * right side), so that we can match equijoin expressions
2451
         * using those variables.  We really only need these for
2452
         * columns merged by JOIN USING, and only with the pairs of
2453
         * input items that correspond to the data structures that
2454
         * parse analysis would build for such variables.  But it's
2455
         * hard to tell which those are, so just make all the pairs.
2456
         * Extra items in the nullable_partexprs list won't cause big
2457
         * problems.  (It's possible that such items will get matched
2458
         * to user-written COALESCEs, but it should still be valid to
2459
         * partition on those, since they're going to be either the
2460
         * partition column or NULL; it's the same argument as for
2461
         * partitionwise nesting of any outer join.)  We assume no
2462
         * type coercions are needed to make the coalesce expressions,
2463
         * since columns of different types won't have gotten
2464
         * classified as the same PartitionScheme.  Note that we
2465
         * intentionally leave out the varnullingrels decoration that
2466
         * would ordinarily appear on the Vars inside these
2467
         * CoalesceExprs, because have_partkey_equi_join will strip
2468
         * varnullingrels from the expressions it will compare to the
2469
         * partexprs.
2470
         */
2471
0
        foreach(lc, list_concat_copy(outer_expr, outer_null_expr))
2472
0
        {
2473
0
          Node     *larg = (Node *) lfirst(lc);
2474
0
          ListCell   *lc2;
2475
2476
0
          foreach(lc2, list_concat_copy(inner_expr, inner_null_expr))
2477
0
          {
2478
0
            Node     *rarg = (Node *) lfirst(lc2);
2479
0
            CoalesceExpr *c = makeNode(CoalesceExpr);
2480
2481
0
            c->coalescetype = exprType(larg);
2482
0
            c->coalescecollid = exprCollation(larg);
2483
0
            c->args = list_make2(larg, rarg);
2484
0
            c->location = -1;
2485
0
            nullable_partexpr = lappend(nullable_partexpr, c);
2486
0
          }
2487
0
        }
2488
0
        break;
2489
2490
0
      default:
2491
0
        elog(ERROR, "unrecognized join type: %d", (int) jointype);
2492
0
    }
2493
2494
0
    joinrel->partexprs[cnt] = partexpr;
2495
0
    joinrel->nullable_partexprs[cnt] = nullable_partexpr;
2496
0
  }
2497
0
}
2498
2499
/*
2500
 * build_child_join_reltarget
2501
 *    Set up a child-join relation's reltarget from a parent-join relation.
2502
 */
2503
static void
2504
build_child_join_reltarget(PlannerInfo *root,
2505
               RelOptInfo *parentrel,
2506
               RelOptInfo *childrel,
2507
               int nappinfos,
2508
               AppendRelInfo **appinfos)
2509
0
{
2510
  /* Build the targetlist */
2511
0
  childrel->reltarget->exprs = (List *)
2512
0
    adjust_appendrel_attrs(root,
2513
0
                 (Node *) parentrel->reltarget->exprs,
2514
0
                 nappinfos, appinfos);
2515
2516
  /* Set the cost and width fields */
2517
0
  childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
2518
0
  childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
2519
0
  childrel->reltarget->width = parentrel->reltarget->width;
2520
0
}