Coverage Report

Created: 2025-07-03 06:49

/src/postgres/src/backend/optimizer/util/plancat.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * plancat.c
4
 *     routines for accessing the system catalogs
5
 *
6
 *
7
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8
 * Portions Copyright (c) 1994, Regents of the University of California
9
 *
10
 *
11
 * IDENTIFICATION
12
 *    src/backend/optimizer/util/plancat.c
13
 *
14
 *-------------------------------------------------------------------------
15
 */
16
#include "postgres.h"
17
18
#include <math.h>
19
20
#include "access/genam.h"
21
#include "access/htup_details.h"
22
#include "access/nbtree.h"
23
#include "access/sysattr.h"
24
#include "access/table.h"
25
#include "access/tableam.h"
26
#include "access/transam.h"
27
#include "access/xlog.h"
28
#include "catalog/catalog.h"
29
#include "catalog/heap.h"
30
#include "catalog/pg_am.h"
31
#include "catalog/pg_proc.h"
32
#include "catalog/pg_statistic_ext.h"
33
#include "catalog/pg_statistic_ext_data.h"
34
#include "foreign/fdwapi.h"
35
#include "miscadmin.h"
36
#include "nodes/makefuncs.h"
37
#include "nodes/nodeFuncs.h"
38
#include "nodes/supportnodes.h"
39
#include "optimizer/cost.h"
40
#include "optimizer/optimizer.h"
41
#include "optimizer/plancat.h"
42
#include "parser/parse_relation.h"
43
#include "parser/parsetree.h"
44
#include "partitioning/partdesc.h"
45
#include "rewrite/rewriteManip.h"
46
#include "statistics/statistics.h"
47
#include "storage/bufmgr.h"
48
#include "tcop/tcopprot.h"
49
#include "utils/builtins.h"
50
#include "utils/lsyscache.h"
51
#include "utils/partcache.h"
52
#include "utils/rel.h"
53
#include "utils/snapmgr.h"
54
#include "utils/syscache.h"
55
56
/* GUC parameter */
57
int     constraint_exclusion = CONSTRAINT_EXCLUSION_PARTITION;
58
59
/* Hook for plugins to get control in get_relation_info() */
60
get_relation_info_hook_type get_relation_info_hook = NULL;
61
62
63
static void get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
64
                    Relation relation, bool inhparent);
65
static bool infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
66
                      List *idxExprs);
67
static List *get_relation_constraints(PlannerInfo *root,
68
                    Oid relationObjectId, RelOptInfo *rel,
69
                    bool include_noinherit,
70
                    bool include_notnull,
71
                    bool include_partition);
72
static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
73
                 Relation heapRelation);
74
static List *get_relation_statistics(RelOptInfo *rel, Relation relation);
75
static void set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
76
                    Relation relation);
77
static PartitionScheme find_partition_scheme(PlannerInfo *root,
78
                       Relation relation);
79
static void set_baserel_partition_key_exprs(Relation relation,
80
                      RelOptInfo *rel);
81
static void set_baserel_partition_constraint(Relation relation,
82
                       RelOptInfo *rel);
83
84
85
/*
86
 * get_relation_info -
87
 *    Retrieves catalog information for a given relation.
88
 *
89
 * Given the Oid of the relation, return the following info into fields
90
 * of the RelOptInfo struct:
91
 *
92
 *  min_attr  lowest valid AttrNumber
93
 *  max_attr  highest valid AttrNumber
94
 *  indexlist list of IndexOptInfos for relation's indexes
95
 *  statlist  list of StatisticExtInfo for relation's statistic objects
96
 *  serverid  if it's a foreign table, the server OID
97
 *  fdwroutine  if it's a foreign table, the FDW function pointers
98
 *  pages   number of pages
99
 *  tuples    number of tuples
100
 *  rel_parallel_workers user-defined number of parallel workers
101
 *
102
 * Also, add information about the relation's foreign keys to root->fkey_list.
103
 *
104
 * Also, initialize the attr_needed[] and attr_widths[] arrays.  In most
105
 * cases these are left as zeroes, but sometimes we need to compute attr
106
 * widths here, and we may as well cache the results for costsize.c.
107
 *
108
 * If inhparent is true, all we need to do is set up the attr arrays:
109
 * the RelOptInfo actually represents the appendrel formed by an inheritance
110
 * tree, and so the parent rel's physical size and index information isn't
111
 * important for it, however, for partitioned tables, we do populate the
112
 * indexlist as the planner uses unique indexes as unique proofs for certain
113
 * optimizations.
114
 */
115
void
116
get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
117
          RelOptInfo *rel)
118
0
{
119
0
  Index   varno = rel->relid;
120
0
  Relation  relation;
121
0
  bool    hasindex;
122
0
  List     *indexinfos = NIL;
123
124
  /*
125
   * We need not lock the relation since it was already locked, either by
126
   * the rewriter or when expand_inherited_rtentry() added it to the query's
127
   * rangetable.
128
   */
129
0
  relation = table_open(relationObjectId, NoLock);
130
131
  /*
132
   * Relations without a table AM can be used in a query only if they are of
133
   * special-cased relkinds.  This check prevents us from crashing later if,
134
   * for example, a view's ON SELECT rule has gone missing.  Note that
135
   * table_open() already rejected indexes and composite types; spell the
136
   * error the same way it does.
137
   */
138
0
  if (!relation->rd_tableam)
139
0
  {
140
0
    if (!(relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
141
0
        relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
142
0
      ereport(ERROR,
143
0
          (errcode(ERRCODE_WRONG_OBJECT_TYPE),
144
0
           errmsg("cannot open relation \"%s\"",
145
0
              RelationGetRelationName(relation)),
146
0
           errdetail_relkind_not_supported(relation->rd_rel->relkind)));
147
0
  }
148
149
  /* Temporary and unlogged relations are inaccessible during recovery. */
150
0
  if (!RelationIsPermanent(relation) && RecoveryInProgress())
151
0
    ereport(ERROR,
152
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
153
0
         errmsg("cannot access temporary or unlogged relations during recovery")));
154
155
0
  rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
156
0
  rel->max_attr = RelationGetNumberOfAttributes(relation);
157
0
  rel->reltablespace = RelationGetForm(relation)->reltablespace;
158
159
0
  Assert(rel->max_attr >= rel->min_attr);
160
0
  rel->attr_needed = (Relids *)
161
0
    palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
162
0
  rel->attr_widths = (int32 *)
163
0
    palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
164
165
  /*
166
   * Record which columns are defined as NOT NULL.  We leave this
167
   * unpopulated for non-partitioned inheritance parent relations as it's
168
   * ambiguous as to what it means.  Some child tables may have a NOT NULL
169
   * constraint for a column while others may not.  We could work harder and
170
   * build a unioned set of all child relations notnullattnums, but there's
171
   * currently no need.  The RelOptInfo corresponding to the !inh
172
   * RangeTblEntry does get populated.
173
   */
174
0
  if (!inhparent || relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
175
0
  {
176
0
    for (int i = 0; i < relation->rd_att->natts; i++)
177
0
    {
178
0
      CompactAttribute *attr = TupleDescCompactAttr(relation->rd_att, i);
179
180
0
      Assert(attr->attnullability != ATTNULLABLE_UNKNOWN);
181
182
0
      if (attr->attnullability == ATTNULLABLE_VALID)
183
0
      {
184
0
        rel->notnullattnums = bms_add_member(rel->notnullattnums,
185
0
                           i + 1);
186
187
        /*
188
         * Per RemoveAttributeById(), dropped columns will have their
189
         * attnotnull unset, so we needn't check for dropped columns
190
         * in the above condition.
191
         */
192
0
        Assert(!attr->attisdropped);
193
0
      }
194
0
    }
195
0
  }
196
197
  /*
198
   * Estimate relation size --- unless it's an inheritance parent, in which
199
   * case the size we want is not the rel's own size but the size of its
200
   * inheritance tree.  That will be computed in set_append_rel_size().
201
   */
202
0
  if (!inhparent)
203
0
    estimate_rel_size(relation, rel->attr_widths - rel->min_attr,
204
0
              &rel->pages, &rel->tuples, &rel->allvisfrac);
205
206
  /* Retrieve the parallel_workers reloption, or -1 if not set. */
207
0
  rel->rel_parallel_workers = RelationGetParallelWorkers(relation, -1);
208
209
  /*
210
   * Make list of indexes.  Ignore indexes on system catalogs if told to.
211
   * Don't bother with indexes from traditional inheritance parents.  For
212
   * partitioned tables, we need a list of at least unique indexes as these
213
   * serve as unique proofs for certain planner optimizations.  However,
214
   * let's not discriminate here and just record all partitioned indexes
215
   * whether they're unique indexes or not.
216
   */
217
0
  if ((inhparent && relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
218
0
    || (IgnoreSystemIndexes && IsSystemRelation(relation)))
219
0
    hasindex = false;
220
0
  else
221
0
    hasindex = relation->rd_rel->relhasindex;
222
223
0
  if (hasindex)
224
0
  {
225
0
    List     *indexoidlist;
226
0
    LOCKMODE  lmode;
227
0
    ListCell   *l;
228
229
0
    indexoidlist = RelationGetIndexList(relation);
230
231
    /*
232
     * For each index, we get the same type of lock that the executor will
233
     * need, and do not release it.  This saves a couple of trips to the
234
     * shared lock manager while not creating any real loss of
235
     * concurrency, because no schema changes could be happening on the
236
     * index while we hold lock on the parent rel, and no lock type used
237
     * for queries blocks any other kind of index operation.
238
     */
239
0
    lmode = root->simple_rte_array[varno]->rellockmode;
240
241
0
    foreach(l, indexoidlist)
242
0
    {
243
0
      Oid     indexoid = lfirst_oid(l);
244
0
      Relation  indexRelation;
245
0
      Form_pg_index index;
246
0
      IndexAmRoutine *amroutine = NULL;
247
0
      IndexOptInfo *info;
248
0
      int     ncolumns,
249
0
            nkeycolumns;
250
0
      int     i;
251
252
      /*
253
       * Extract info from the relation descriptor for the index.
254
       */
255
0
      indexRelation = index_open(indexoid, lmode);
256
0
      index = indexRelation->rd_index;
257
258
      /*
259
       * Ignore invalid indexes, since they can't safely be used for
260
       * queries.  Note that this is OK because the data structure we
261
       * are constructing is only used by the planner --- the executor
262
       * still needs to insert into "invalid" indexes, if they're marked
263
       * indisready.
264
       */
265
0
      if (!index->indisvalid)
266
0
      {
267
0
        index_close(indexRelation, NoLock);
268
0
        continue;
269
0
      }
270
271
      /*
272
       * If the index is valid, but cannot yet be used, ignore it; but
273
       * mark the plan we are generating as transient. See
274
       * src/backend/access/heap/README.HOT for discussion.
275
       */
276
0
      if (index->indcheckxmin &&
277
0
        !TransactionIdPrecedes(HeapTupleHeaderGetXmin(indexRelation->rd_indextuple->t_data),
278
0
                     TransactionXmin))
279
0
      {
280
0
        root->glob->transientPlan = true;
281
0
        index_close(indexRelation, NoLock);
282
0
        continue;
283
0
      }
284
285
0
      info = makeNode(IndexOptInfo);
286
287
0
      info->indexoid = index->indexrelid;
288
0
      info->reltablespace =
289
0
        RelationGetForm(indexRelation)->reltablespace;
290
0
      info->rel = rel;
291
0
      info->ncolumns = ncolumns = index->indnatts;
292
0
      info->nkeycolumns = nkeycolumns = index->indnkeyatts;
293
294
0
      info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
295
0
      info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
296
0
      info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
297
0
      info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
298
0
      info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
299
300
0
      for (i = 0; i < ncolumns; i++)
301
0
      {
302
0
        info->indexkeys[i] = index->indkey.values[i];
303
0
        info->canreturn[i] = index_can_return(indexRelation, i + 1);
304
0
      }
305
306
0
      for (i = 0; i < nkeycolumns; i++)
307
0
      {
308
0
        info->opfamily[i] = indexRelation->rd_opfamily[i];
309
0
        info->opcintype[i] = indexRelation->rd_opcintype[i];
310
0
        info->indexcollations[i] = indexRelation->rd_indcollation[i];
311
0
      }
312
313
0
      info->relam = indexRelation->rd_rel->relam;
314
315
      /*
316
       * We don't have an AM for partitioned indexes, so we'll just
317
       * NULLify the AM related fields for those.
318
       */
319
0
      if (indexRelation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
320
0
      {
321
        /* We copy just the fields we need, not all of rd_indam */
322
0
        amroutine = indexRelation->rd_indam;
323
0
        info->amcanorderbyop = amroutine->amcanorderbyop;
324
0
        info->amoptionalkey = amroutine->amoptionalkey;
325
0
        info->amsearcharray = amroutine->amsearcharray;
326
0
        info->amsearchnulls = amroutine->amsearchnulls;
327
0
        info->amcanparallel = amroutine->amcanparallel;
328
0
        info->amhasgettuple = (amroutine->amgettuple != NULL);
329
0
        info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
330
0
          relation->rd_tableam->scan_bitmap_next_tuple != NULL;
331
0
        info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
332
0
                    amroutine->amrestrpos != NULL);
333
0
        info->amcostestimate = amroutine->amcostestimate;
334
0
        Assert(info->amcostestimate != NULL);
335
336
        /* Fetch index opclass options */
337
0
        info->opclassoptions = RelationGetIndexAttOptions(indexRelation, true);
338
339
        /*
340
         * Fetch the ordering information for the index, if any.
341
         */
342
0
        if (info->relam == BTREE_AM_OID)
343
0
        {
344
          /*
345
           * If it's a btree index, we can use its opfamily OIDs
346
           * directly as the sort ordering opfamily OIDs.
347
           */
348
0
          Assert(amroutine->amcanorder);
349
350
0
          info->sortopfamily = info->opfamily;
351
0
          info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
352
0
          info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
353
354
0
          for (i = 0; i < nkeycolumns; i++)
355
0
          {
356
0
            int16   opt = indexRelation->rd_indoption[i];
357
358
0
            info->reverse_sort[i] = (opt & INDOPTION_DESC) != 0;
359
0
            info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
360
0
          }
361
0
        }
362
0
        else if (amroutine->amcanorder)
363
0
        {
364
          /*
365
           * Otherwise, identify the corresponding btree opfamilies
366
           * by trying to map this index's "<" operators into btree.
367
           * Since "<" uniquely defines the behavior of a sort
368
           * order, this is a sufficient test.
369
           *
370
           * XXX This method is rather slow and complicated.  It'd
371
           * be better to have a way to explicitly declare the
372
           * corresponding btree opfamily for each opfamily of the
373
           * other index type.
374
           */
375
0
          info->sortopfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
376
0
          info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
377
0
          info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
378
379
0
          for (i = 0; i < nkeycolumns; i++)
380
0
          {
381
0
            int16   opt = indexRelation->rd_indoption[i];
382
0
            Oid     ltopr;
383
0
            Oid     opfamily;
384
0
            Oid     opcintype;
385
0
            CompareType cmptype;
386
387
0
            info->reverse_sort[i] = (opt & INDOPTION_DESC) != 0;
388
0
            info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
389
390
0
            ltopr = get_opfamily_member_for_cmptype(info->opfamily[i],
391
0
                                info->opcintype[i],
392
0
                                info->opcintype[i],
393
0
                                COMPARE_LT);
394
0
            if (OidIsValid(ltopr) &&
395
0
              get_ordering_op_properties(ltopr,
396
0
                             &opfamily,
397
0
                             &opcintype,
398
0
                             &cmptype) &&
399
0
              opcintype == info->opcintype[i] &&
400
0
              cmptype == COMPARE_LT)
401
0
            {
402
              /* Successful mapping */
403
0
              info->sortopfamily[i] = opfamily;
404
0
            }
405
0
            else
406
0
            {
407
              /* Fail ... quietly treat index as unordered */
408
0
              info->sortopfamily = NULL;
409
0
              info->reverse_sort = NULL;
410
0
              info->nulls_first = NULL;
411
0
              break;
412
0
            }
413
0
          }
414
0
        }
415
0
        else
416
0
        {
417
0
          info->sortopfamily = NULL;
418
0
          info->reverse_sort = NULL;
419
0
          info->nulls_first = NULL;
420
0
        }
421
0
      }
422
0
      else
423
0
      {
424
0
        info->amcanorderbyop = false;
425
0
        info->amoptionalkey = false;
426
0
        info->amsearcharray = false;
427
0
        info->amsearchnulls = false;
428
0
        info->amcanparallel = false;
429
0
        info->amhasgettuple = false;
430
0
        info->amhasgetbitmap = false;
431
0
        info->amcanmarkpos = false;
432
0
        info->amcostestimate = NULL;
433
434
0
        info->sortopfamily = NULL;
435
0
        info->reverse_sort = NULL;
436
0
        info->nulls_first = NULL;
437
0
      }
438
439
      /*
440
       * Fetch the index expressions and predicate, if any.  We must
441
       * modify the copies we obtain from the relcache to have the
442
       * correct varno for the parent relation, so that they match up
443
       * correctly against qual clauses.
444
       */
445
0
      info->indexprs = RelationGetIndexExpressions(indexRelation);
446
0
      info->indpred = RelationGetIndexPredicate(indexRelation);
447
0
      if (info->indexprs && varno != 1)
448
0
        ChangeVarNodes((Node *) info->indexprs, 1, varno, 0);
449
0
      if (info->indpred && varno != 1)
450
0
        ChangeVarNodes((Node *) info->indpred, 1, varno, 0);
451
452
      /* Build targetlist using the completed indexprs data */
453
0
      info->indextlist = build_index_tlist(root, info, relation);
454
455
0
      info->indrestrictinfo = NIL; /* set later, in indxpath.c */
456
0
      info->predOK = false; /* set later, in indxpath.c */
457
0
      info->unique = index->indisunique;
458
0
      info->nullsnotdistinct = index->indnullsnotdistinct;
459
0
      info->immediate = index->indimmediate;
460
0
      info->hypothetical = false;
461
462
      /*
463
       * Estimate the index size.  If it's not a partial index, we lock
464
       * the number-of-tuples estimate to equal the parent table; if it
465
       * is partial then we have to use the same methods as we would for
466
       * a table, except we can be sure that the index is not larger
467
       * than the table.  We must ignore partitioned indexes here as
468
       * there are not physical indexes.
469
       */
470
0
      if (indexRelation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
471
0
      {
472
0
        if (info->indpred == NIL)
473
0
        {
474
0
          info->pages = RelationGetNumberOfBlocks(indexRelation);
475
0
          info->tuples = rel->tuples;
476
0
        }
477
0
        else
478
0
        {
479
0
          double    allvisfrac; /* dummy */
480
481
0
          estimate_rel_size(indexRelation, NULL,
482
0
                    &info->pages, &info->tuples, &allvisfrac);
483
0
          if (info->tuples > rel->tuples)
484
0
            info->tuples = rel->tuples;
485
0
        }
486
487
        /*
488
         * Get tree height while we have the index open
489
         */
490
0
        if (amroutine->amgettreeheight)
491
0
        {
492
0
          info->tree_height = amroutine->amgettreeheight(indexRelation);
493
0
        }
494
0
        else
495
0
        {
496
          /* For other index types, just set it to "unknown" for now */
497
0
          info->tree_height = -1;
498
0
        }
499
0
      }
500
0
      else
501
0
      {
502
        /* Zero these out for partitioned indexes */
503
0
        info->pages = 0;
504
0
        info->tuples = 0.0;
505
0
        info->tree_height = -1;
506
0
      }
507
508
0
      index_close(indexRelation, NoLock);
509
510
      /*
511
       * We've historically used lcons() here.  It'd make more sense to
512
       * use lappend(), but that causes the planner to change behavior
513
       * in cases where two indexes seem equally attractive.  For now,
514
       * stick with lcons() --- few tables should have so many indexes
515
       * that the O(N^2) behavior of lcons() is really a problem.
516
       */
517
0
      indexinfos = lcons(info, indexinfos);
518
0
    }
519
520
0
    list_free(indexoidlist);
521
0
  }
522
523
0
  rel->indexlist = indexinfos;
524
525
0
  rel->statlist = get_relation_statistics(rel, relation);
526
527
  /* Grab foreign-table info using the relcache, while we have it */
528
0
  if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
529
0
  {
530
    /* Check if the access to foreign tables is restricted */
531
0
    if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
532
0
    {
533
      /* there must not be built-in foreign tables */
534
0
      Assert(RelationGetRelid(relation) >= FirstNormalObjectId);
535
536
0
      ereport(ERROR,
537
0
          (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
538
0
           errmsg("access to non-system foreign table is restricted")));
539
0
    }
540
541
0
    rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
542
0
    rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
543
0
  }
544
0
  else
545
0
  {
546
0
    rel->serverid = InvalidOid;
547
0
    rel->fdwroutine = NULL;
548
0
  }
549
550
  /* Collect info about relation's foreign keys, if relevant */
551
0
  get_relation_foreign_keys(root, rel, relation, inhparent);
552
553
  /* Collect info about functions implemented by the rel's table AM. */
554
0
  if (relation->rd_tableam &&
555
0
    relation->rd_tableam->scan_set_tidrange != NULL &&
556
0
    relation->rd_tableam->scan_getnextslot_tidrange != NULL)
557
0
    rel->amflags |= AMFLAG_HAS_TID_RANGE;
558
559
  /*
560
   * Collect info about relation's partitioning scheme, if any. Only
561
   * inheritance parents may be partitioned.
562
   */
563
0
  if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
564
0
    set_relation_partition_info(root, rel, relation);
565
566
0
  table_close(relation, NoLock);
567
568
  /*
569
   * Allow a plugin to editorialize on the info we obtained from the
570
   * catalogs.  Actions might include altering the assumed relation size,
571
   * removing an index, or adding a hypothetical index to the indexlist.
572
   */
573
0
  if (get_relation_info_hook)
574
0
    (*get_relation_info_hook) (root, relationObjectId, inhparent, rel);
575
0
}
576
577
/*
578
 * get_relation_foreign_keys -
579
 *    Retrieves foreign key information for a given relation.
580
 *
581
 * ForeignKeyOptInfos for relevant foreign keys are created and added to
582
 * root->fkey_list.  We do this now while we have the relcache entry open.
583
 * We could sometimes avoid making useless ForeignKeyOptInfos if we waited
584
 * until all RelOptInfos have been built, but the cost of re-opening the
585
 * relcache entries would probably exceed any savings.
586
 */
587
static void
588
get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
589
              Relation relation, bool inhparent)
590
0
{
591
0
  List     *rtable = root->parse->rtable;
592
0
  List     *cachedfkeys;
593
0
  ListCell   *lc;
594
595
  /*
596
   * If it's not a baserel, we don't care about its FKs.  Also, if the query
597
   * references only a single relation, we can skip the lookup since no FKs
598
   * could satisfy the requirements below.
599
   */
600
0
  if (rel->reloptkind != RELOPT_BASEREL ||
601
0
    list_length(rtable) < 2)
602
0
    return;
603
604
  /*
605
   * If it's the parent of an inheritance tree, ignore its FKs.  We could
606
   * make useful FK-based deductions if we found that all members of the
607
   * inheritance tree have equivalent FK constraints, but detecting that
608
   * would require code that hasn't been written.
609
   */
610
0
  if (inhparent)
611
0
    return;
612
613
  /*
614
   * Extract data about relation's FKs from the relcache.  Note that this
615
   * list belongs to the relcache and might disappear in a cache flush, so
616
   * we must not do any further catalog access within this function.
617
   */
618
0
  cachedfkeys = RelationGetFKeyList(relation);
619
620
  /*
621
   * Figure out which FKs are of interest for this query, and create
622
   * ForeignKeyOptInfos for them.  We want only FKs that reference some
623
   * other RTE of the current query.  In queries containing self-joins,
624
   * there might be more than one other RTE for a referenced table, and we
625
   * should make a ForeignKeyOptInfo for each occurrence.
626
   *
627
   * Ideally, we would ignore RTEs that correspond to non-baserels, but it's
628
   * too hard to identify those here, so we might end up making some useless
629
   * ForeignKeyOptInfos.  If so, match_foreign_keys_to_quals() will remove
630
   * them again.
631
   */
632
0
  foreach(lc, cachedfkeys)
633
0
  {
634
0
    ForeignKeyCacheInfo *cachedfk = (ForeignKeyCacheInfo *) lfirst(lc);
635
0
    Index   rti;
636
0
    ListCell   *lc2;
637
638
    /* conrelid should always be that of the table we're considering */
639
0
    Assert(cachedfk->conrelid == RelationGetRelid(relation));
640
641
    /* skip constraints currently not enforced */
642
0
    if (!cachedfk->conenforced)
643
0
      continue;
644
645
    /* Scan to find other RTEs matching confrelid */
646
0
    rti = 0;
647
0
    foreach(lc2, rtable)
648
0
    {
649
0
      RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
650
0
      ForeignKeyOptInfo *info;
651
652
0
      rti++;
653
      /* Ignore if not the correct table */
654
0
      if (rte->rtekind != RTE_RELATION ||
655
0
        rte->relid != cachedfk->confrelid)
656
0
        continue;
657
      /* Ignore if it's an inheritance parent; doesn't really match */
658
0
      if (rte->inh)
659
0
        continue;
660
      /* Ignore self-referential FKs; we only care about joins */
661
0
      if (rti == rel->relid)
662
0
        continue;
663
664
      /* OK, let's make an entry */
665
0
      info = makeNode(ForeignKeyOptInfo);
666
0
      info->con_relid = rel->relid;
667
0
      info->ref_relid = rti;
668
0
      info->nkeys = cachedfk->nkeys;
669
0
      memcpy(info->conkey, cachedfk->conkey, sizeof(info->conkey));
670
0
      memcpy(info->confkey, cachedfk->confkey, sizeof(info->confkey));
671
0
      memcpy(info->conpfeqop, cachedfk->conpfeqop, sizeof(info->conpfeqop));
672
      /* zero out fields to be filled by match_foreign_keys_to_quals */
673
0
      info->nmatched_ec = 0;
674
0
      info->nconst_ec = 0;
675
0
      info->nmatched_rcols = 0;
676
0
      info->nmatched_ri = 0;
677
0
      memset(info->eclass, 0, sizeof(info->eclass));
678
0
      memset(info->fk_eclass_member, 0, sizeof(info->fk_eclass_member));
679
0
      memset(info->rinfos, 0, sizeof(info->rinfos));
680
681
0
      root->fkey_list = lappend(root->fkey_list, info);
682
0
    }
683
0
  }
684
0
}
685
686
/*
687
 * infer_arbiter_indexes -
688
 *    Determine the unique indexes used to arbitrate speculative insertion.
689
 *
690
 * Uses user-supplied inference clause expressions and predicate to match a
691
 * unique index from those defined and ready on the heap relation (target).
692
 * An exact match is required on columns/expressions (although they can appear
693
 * in any order).  However, the predicate given by the user need only restrict
694
 * insertion to a subset of some part of the table covered by some particular
695
 * unique index (in particular, a partial unique index) in order to be
696
 * inferred.
697
 *
698
 * The implementation does not consider which B-Tree operator class any
699
 * particular available unique index attribute uses, unless one was specified
700
 * in the inference specification. The same is true of collations.  In
701
 * particular, there is no system dependency on the default operator class for
702
 * the purposes of inference.  If no opclass (or collation) is specified, then
703
 * all matching indexes (that may or may not match the default in terms of
704
 * each attribute opclass/collation) are used for inference.
705
 */
706
List *
707
infer_arbiter_indexes(PlannerInfo *root)
708
0
{
709
0
  OnConflictExpr *onconflict = root->parse->onConflict;
710
711
  /* Iteration state */
712
0
  Index   varno;
713
0
  RangeTblEntry *rte;
714
0
  Relation  relation;
715
0
  Oid     indexOidFromConstraint = InvalidOid;
716
0
  List     *indexList;
717
0
  ListCell   *l;
718
719
  /* Normalized inference attributes and inference expressions: */
720
0
  Bitmapset  *inferAttrs = NULL;
721
0
  List     *inferElems = NIL;
722
723
  /* Results */
724
0
  List     *results = NIL;
725
726
  /*
727
   * Quickly return NIL for ON CONFLICT DO NOTHING without an inference
728
   * specification or named constraint.  ON CONFLICT DO UPDATE statements
729
   * must always provide one or the other (but parser ought to have caught
730
   * that already).
731
   */
732
0
  if (onconflict->arbiterElems == NIL &&
733
0
    onconflict->constraint == InvalidOid)
734
0
    return NIL;
735
736
  /*
737
   * We need not lock the relation since it was already locked, either by
738
   * the rewriter or when expand_inherited_rtentry() added it to the query's
739
   * rangetable.
740
   */
741
0
  varno = root->parse->resultRelation;
742
0
  rte = rt_fetch(varno, root->parse->rtable);
743
744
0
  relation = table_open(rte->relid, NoLock);
745
746
  /*
747
   * Build normalized/BMS representation of plain indexed attributes, as
748
   * well as a separate list of expression items.  This simplifies matching
749
   * the cataloged definition of indexes.
750
   */
751
0
  foreach(l, onconflict->arbiterElems)
752
0
  {
753
0
    InferenceElem *elem = (InferenceElem *) lfirst(l);
754
0
    Var      *var;
755
0
    int     attno;
756
757
0
    if (!IsA(elem->expr, Var))
758
0
    {
759
      /* If not a plain Var, just shove it in inferElems for now */
760
0
      inferElems = lappend(inferElems, elem->expr);
761
0
      continue;
762
0
    }
763
764
0
    var = (Var *) elem->expr;
765
0
    attno = var->varattno;
766
767
0
    if (attno == 0)
768
0
      ereport(ERROR,
769
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
770
0
           errmsg("whole row unique index inference specifications are not supported")));
771
772
0
    inferAttrs = bms_add_member(inferAttrs,
773
0
                  attno - FirstLowInvalidHeapAttributeNumber);
774
0
  }
775
776
  /*
777
   * Lookup named constraint's index.  This is not immediately returned
778
   * because some additional sanity checks are required.
779
   */
780
0
  if (onconflict->constraint != InvalidOid)
781
0
  {
782
0
    indexOidFromConstraint = get_constraint_index(onconflict->constraint);
783
784
0
    if (indexOidFromConstraint == InvalidOid)
785
0
      ereport(ERROR,
786
0
          (errcode(ERRCODE_WRONG_OBJECT_TYPE),
787
0
           errmsg("constraint in ON CONFLICT clause has no associated index")));
788
0
  }
789
790
  /*
791
   * Using that representation, iterate through the list of indexes on the
792
   * target relation to try and find a match
793
   */
794
0
  indexList = RelationGetIndexList(relation);
795
796
0
  foreach(l, indexList)
797
0
  {
798
0
    Oid     indexoid = lfirst_oid(l);
799
0
    Relation  idxRel;
800
0
    Form_pg_index idxForm;
801
0
    Bitmapset  *indexedAttrs;
802
0
    List     *idxExprs;
803
0
    List     *predExprs;
804
0
    AttrNumber  natt;
805
0
    ListCell   *el;
806
807
    /*
808
     * Extract info from the relation descriptor for the index.  Obtain
809
     * the same lock type that the executor will ultimately use.
810
     *
811
     * Let executor complain about !indimmediate case directly, because
812
     * enforcement needs to occur there anyway when an inference clause is
813
     * omitted.
814
     */
815
0
    idxRel = index_open(indexoid, rte->rellockmode);
816
0
    idxForm = idxRel->rd_index;
817
818
0
    if (!idxForm->indisvalid)
819
0
      goto next;
820
821
    /*
822
     * Note that we do not perform a check against indcheckxmin (like e.g.
823
     * get_relation_info()) here to eliminate candidates, because
824
     * uniqueness checking only cares about the most recently committed
825
     * tuple versions.
826
     */
827
828
    /*
829
     * Look for match on "ON constraint_name" variant, which may not be
830
     * unique constraint.  This can only be a constraint name.
831
     */
832
0
    if (indexOidFromConstraint == idxForm->indexrelid)
833
0
    {
834
0
      if (idxForm->indisexclusion && onconflict->action == ONCONFLICT_UPDATE)
835
0
        ereport(ERROR,
836
0
            (errcode(ERRCODE_WRONG_OBJECT_TYPE),
837
0
             errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
838
839
0
      results = lappend_oid(results, idxForm->indexrelid);
840
0
      list_free(indexList);
841
0
      index_close(idxRel, NoLock);
842
0
      table_close(relation, NoLock);
843
0
      return results;
844
0
    }
845
0
    else if (indexOidFromConstraint != InvalidOid)
846
0
    {
847
      /* No point in further work for index in named constraint case */
848
0
      goto next;
849
0
    }
850
851
    /*
852
     * Only considering conventional inference at this point (not named
853
     * constraints), so index under consideration can be immediately
854
     * skipped if it's not unique
855
     */
856
0
    if (!idxForm->indisunique)
857
0
      goto next;
858
859
    /*
860
     * So-called unique constraints with WITHOUT OVERLAPS are really
861
     * exclusion constraints, so skip those too.
862
     */
863
0
    if (idxForm->indisexclusion)
864
0
      goto next;
865
866
    /* Build BMS representation of plain (non expression) index attrs */
867
0
    indexedAttrs = NULL;
868
0
    for (natt = 0; natt < idxForm->indnkeyatts; natt++)
869
0
    {
870
0
      int     attno = idxRel->rd_index->indkey.values[natt];
871
872
0
      if (attno != 0)
873
0
        indexedAttrs = bms_add_member(indexedAttrs,
874
0
                        attno - FirstLowInvalidHeapAttributeNumber);
875
0
    }
876
877
    /* Non-expression attributes (if any) must match */
878
0
    if (!bms_equal(indexedAttrs, inferAttrs))
879
0
      goto next;
880
881
    /* Expression attributes (if any) must match */
882
0
    idxExprs = RelationGetIndexExpressions(idxRel);
883
0
    if (idxExprs && varno != 1)
884
0
      ChangeVarNodes((Node *) idxExprs, 1, varno, 0);
885
886
0
    foreach(el, onconflict->arbiterElems)
887
0
    {
888
0
      InferenceElem *elem = (InferenceElem *) lfirst(el);
889
890
      /*
891
       * Ensure that collation/opclass aspects of inference expression
892
       * element match.  Even though this loop is primarily concerned
893
       * with matching expressions, it is a convenient point to check
894
       * this for both expressions and ordinary (non-expression)
895
       * attributes appearing as inference elements.
896
       */
897
0
      if (!infer_collation_opclass_match(elem, idxRel, idxExprs))
898
0
        goto next;
899
900
      /*
901
       * Plain Vars don't factor into count of expression elements, and
902
       * the question of whether or not they satisfy the index
903
       * definition has already been considered (they must).
904
       */
905
0
      if (IsA(elem->expr, Var))
906
0
        continue;
907
908
      /*
909
       * Might as well avoid redundant check in the rare cases where
910
       * infer_collation_opclass_match() is required to do real work.
911
       * Otherwise, check that element expression appears in cataloged
912
       * index definition.
913
       */
914
0
      if (elem->infercollid != InvalidOid ||
915
0
        elem->inferopclass != InvalidOid ||
916
0
        list_member(idxExprs, elem->expr))
917
0
        continue;
918
919
0
      goto next;
920
0
    }
921
922
    /*
923
     * Now that all inference elements were matched, ensure that the
924
     * expression elements from inference clause are not missing any
925
     * cataloged expressions.  This does the right thing when unique
926
     * indexes redundantly repeat the same attribute, or if attributes
927
     * redundantly appear multiple times within an inference clause.
928
     */
929
0
    if (list_difference(idxExprs, inferElems) != NIL)
930
0
      goto next;
931
932
    /*
933
     * If it's a partial index, its predicate must be implied by the ON
934
     * CONFLICT's WHERE clause.
935
     */
936
0
    predExprs = RelationGetIndexPredicate(idxRel);
937
0
    if (predExprs && varno != 1)
938
0
      ChangeVarNodes((Node *) predExprs, 1, varno, 0);
939
940
0
    if (!predicate_implied_by(predExprs, (List *) onconflict->arbiterWhere, false))
941
0
      goto next;
942
943
0
    results = lappend_oid(results, idxForm->indexrelid);
944
0
next:
945
0
    index_close(idxRel, NoLock);
946
0
  }
947
948
0
  list_free(indexList);
949
0
  table_close(relation, NoLock);
950
951
0
  if (results == NIL)
952
0
    ereport(ERROR,
953
0
        (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
954
0
         errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
955
956
0
  return results;
957
0
}
958
959
/*
960
 * infer_collation_opclass_match - ensure infer element opclass/collation match
961
 *
962
 * Given unique index inference element from inference specification, if
963
 * collation was specified, or if opclass was specified, verify that there is
964
 * at least one matching indexed attribute (occasionally, there may be more).
965
 * Skip this in the common case where inference specification does not include
966
 * collation or opclass (instead matching everything, regardless of cataloged
967
 * collation/opclass of indexed attribute).
968
 *
969
 * At least historically, Postgres has not offered collations or opclasses
970
 * with alternative-to-default notions of equality, so these additional
971
 * criteria should only be required infrequently.
972
 *
973
 * Don't give up immediately when an inference element matches some attribute
974
 * cataloged as indexed but not matching additional opclass/collation
975
 * criteria.  This is done so that the implementation is as forgiving as
976
 * possible of redundancy within cataloged index attributes (or, less
977
 * usefully, within inference specification elements).  If collations actually
978
 * differ between apparently redundantly indexed attributes (redundant within
979
 * or across indexes), then there really is no redundancy as such.
980
 *
981
 * Note that if an inference element specifies an opclass and a collation at
982
 * once, both must match in at least one particular attribute within index
983
 * catalog definition in order for that inference element to be considered
984
 * inferred/satisfied.
985
 */
986
static bool
987
infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
988
                List *idxExprs)
989
0
{
990
0
  AttrNumber  natt;
991
0
  Oid     inferopfamily = InvalidOid; /* OID of opclass opfamily */
992
0
  Oid     inferopcinputtype = InvalidOid; /* OID of opclass input type */
993
0
  int     nplain = 0;   /* # plain attrs observed */
994
995
  /*
996
   * If inference specification element lacks collation/opclass, then no
997
   * need to check for exact match.
998
   */
999
0
  if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
1000
0
    return true;
1001
1002
  /*
1003
   * Lookup opfamily and input type, for matching indexes
1004
   */
1005
0
  if (elem->inferopclass)
1006
0
  {
1007
0
    inferopfamily = get_opclass_family(elem->inferopclass);
1008
0
    inferopcinputtype = get_opclass_input_type(elem->inferopclass);
1009
0
  }
1010
1011
0
  for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
1012
0
  {
1013
0
    Oid     opfamily = idxRel->rd_opfamily[natt - 1];
1014
0
    Oid     opcinputtype = idxRel->rd_opcintype[natt - 1];
1015
0
    Oid     collation = idxRel->rd_indcollation[natt - 1];
1016
0
    int     attno = idxRel->rd_index->indkey.values[natt - 1];
1017
1018
0
    if (attno != 0)
1019
0
      nplain++;
1020
1021
0
    if (elem->inferopclass != InvalidOid &&
1022
0
      (inferopfamily != opfamily || inferopcinputtype != opcinputtype))
1023
0
    {
1024
      /* Attribute needed to match opclass, but didn't */
1025
0
      continue;
1026
0
    }
1027
1028
0
    if (elem->infercollid != InvalidOid &&
1029
0
      elem->infercollid != collation)
1030
0
    {
1031
      /* Attribute needed to match collation, but didn't */
1032
0
      continue;
1033
0
    }
1034
1035
    /* If one matching index att found, good enough -- return true */
1036
0
    if (IsA(elem->expr, Var))
1037
0
    {
1038
0
      if (((Var *) elem->expr)->varattno == attno)
1039
0
        return true;
1040
0
    }
1041
0
    else if (attno == 0)
1042
0
    {
1043
0
      Node     *nattExpr = list_nth(idxExprs, (natt - 1) - nplain);
1044
1045
      /*
1046
       * Note that unlike routines like match_index_to_operand() we
1047
       * don't need to care about RelabelType.  Neither the index
1048
       * definition nor the inference clause should contain them.
1049
       */
1050
0
      if (equal(elem->expr, nattExpr))
1051
0
        return true;
1052
0
    }
1053
0
  }
1054
1055
0
  return false;
1056
0
}
1057
1058
/*
1059
 * estimate_rel_size - estimate # pages and # tuples in a table or index
1060
 *
1061
 * We also estimate the fraction of the pages that are marked all-visible in
1062
 * the visibility map, for use in estimation of index-only scans.
1063
 *
1064
 * If attr_widths isn't NULL, it points to the zero-index entry of the
1065
 * relation's attr_widths[] cache; we fill this in if we have need to compute
1066
 * the attribute widths for estimation purposes.
1067
 */
1068
void
1069
estimate_rel_size(Relation rel, int32 *attr_widths,
1070
          BlockNumber *pages, double *tuples, double *allvisfrac)
1071
0
{
1072
0
  BlockNumber curpages;
1073
0
  BlockNumber relpages;
1074
0
  double    reltuples;
1075
0
  BlockNumber relallvisible;
1076
0
  double    density;
1077
1078
0
  if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
1079
0
  {
1080
0
    table_relation_estimate_size(rel, attr_widths, pages, tuples,
1081
0
                   allvisfrac);
1082
0
  }
1083
0
  else if (rel->rd_rel->relkind == RELKIND_INDEX)
1084
0
  {
1085
    /*
1086
     * XXX: It'd probably be good to move this into a callback, individual
1087
     * index types e.g. know if they have a metapage.
1088
     */
1089
1090
    /* it has storage, ok to call the smgr */
1091
0
    curpages = RelationGetNumberOfBlocks(rel);
1092
1093
    /* report estimated # pages */
1094
0
    *pages = curpages;
1095
    /* quick exit if rel is clearly empty */
1096
0
    if (curpages == 0)
1097
0
    {
1098
0
      *tuples = 0;
1099
0
      *allvisfrac = 0;
1100
0
      return;
1101
0
    }
1102
1103
    /* coerce values in pg_class to more desirable types */
1104
0
    relpages = (BlockNumber) rel->rd_rel->relpages;
1105
0
    reltuples = (double) rel->rd_rel->reltuples;
1106
0
    relallvisible = (BlockNumber) rel->rd_rel->relallvisible;
1107
1108
    /*
1109
     * Discount the metapage while estimating the number of tuples. This
1110
     * is a kluge because it assumes more than it ought to about index
1111
     * structure.  Currently it's OK for btree, hash, and GIN indexes but
1112
     * suspect for GiST indexes.
1113
     */
1114
0
    if (relpages > 0)
1115
0
    {
1116
0
      curpages--;
1117
0
      relpages--;
1118
0
    }
1119
1120
    /* estimate number of tuples from previous tuple density */
1121
0
    if (reltuples >= 0 && relpages > 0)
1122
0
      density = reltuples / (double) relpages;
1123
0
    else
1124
0
    {
1125
      /*
1126
       * If we have no data because the relation was never vacuumed,
1127
       * estimate tuple width from attribute datatypes.  We assume here
1128
       * that the pages are completely full, which is OK for tables
1129
       * (since they've presumably not been VACUUMed yet) but is
1130
       * probably an overestimate for indexes.  Fortunately
1131
       * get_relation_info() can clamp the overestimate to the parent
1132
       * table's size.
1133
       *
1134
       * Note: this code intentionally disregards alignment
1135
       * considerations, because (a) that would be gilding the lily
1136
       * considering how crude the estimate is, and (b) it creates
1137
       * platform dependencies in the default plans which are kind of a
1138
       * headache for regression testing.
1139
       *
1140
       * XXX: Should this logic be more index specific?
1141
       */
1142
0
      int32   tuple_width;
1143
1144
0
      tuple_width = get_rel_data_width(rel, attr_widths);
1145
0
      tuple_width += MAXALIGN(SizeofHeapTupleHeader);
1146
0
      tuple_width += sizeof(ItemIdData);
1147
      /* note: integer division is intentional here */
1148
0
      density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;
1149
0
    }
1150
0
    *tuples = rint(density * (double) curpages);
1151
1152
    /*
1153
     * We use relallvisible as-is, rather than scaling it up like we do
1154
     * for the pages and tuples counts, on the theory that any pages added
1155
     * since the last VACUUM are most likely not marked all-visible.  But
1156
     * costsize.c wants it converted to a fraction.
1157
     */
1158
0
    if (relallvisible == 0 || curpages <= 0)
1159
0
      *allvisfrac = 0;
1160
0
    else if ((double) relallvisible >= curpages)
1161
0
      *allvisfrac = 1;
1162
0
    else
1163
0
      *allvisfrac = (double) relallvisible / curpages;
1164
0
  }
1165
0
  else
1166
0
  {
1167
    /*
1168
     * Just use whatever's in pg_class.  This covers foreign tables,
1169
     * sequences, and also relkinds without storage (shouldn't get here?);
1170
     * see initializations in AddNewRelationTuple().  Note that FDW must
1171
     * cope if reltuples is -1!
1172
     */
1173
0
    *pages = rel->rd_rel->relpages;
1174
0
    *tuples = rel->rd_rel->reltuples;
1175
0
    *allvisfrac = 0;
1176
0
  }
1177
0
}
1178
1179
1180
/*
1181
 * get_rel_data_width
1182
 *
1183
 * Estimate the average width of (the data part of) the relation's tuples.
1184
 *
1185
 * If attr_widths isn't NULL, it points to the zero-index entry of the
1186
 * relation's attr_widths[] cache; use and update that cache as appropriate.
1187
 *
1188
 * Currently we ignore dropped columns.  Ideally those should be included
1189
 * in the result, but we haven't got any way to get info about them; and
1190
 * since they might be mostly NULLs, treating them as zero-width is not
1191
 * necessarily the wrong thing anyway.
1192
 */
1193
int32
1194
get_rel_data_width(Relation rel, int32 *attr_widths)
1195
0
{
1196
0
  int64   tuple_width = 0;
1197
0
  int     i;
1198
1199
0
  for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++)
1200
0
  {
1201
0
    Form_pg_attribute att = TupleDescAttr(rel->rd_att, i - 1);
1202
0
    int32   item_width;
1203
1204
0
    if (att->attisdropped)
1205
0
      continue;
1206
1207
    /* use previously cached data, if any */
1208
0
    if (attr_widths != NULL && attr_widths[i] > 0)
1209
0
    {
1210
0
      tuple_width += attr_widths[i];
1211
0
      continue;
1212
0
    }
1213
1214
    /* This should match set_rel_width() in costsize.c */
1215
0
    item_width = get_attavgwidth(RelationGetRelid(rel), i);
1216
0
    if (item_width <= 0)
1217
0
    {
1218
0
      item_width = get_typavgwidth(att->atttypid, att->atttypmod);
1219
0
      Assert(item_width > 0);
1220
0
    }
1221
0
    if (attr_widths != NULL)
1222
0
      attr_widths[i] = item_width;
1223
0
    tuple_width += item_width;
1224
0
  }
1225
1226
0
  return clamp_width_est(tuple_width);
1227
0
}
1228
1229
/*
1230
 * get_relation_data_width
1231
 *
1232
 * External API for get_rel_data_width: same behavior except we have to
1233
 * open the relcache entry.
1234
 */
1235
int32
1236
get_relation_data_width(Oid relid, int32 *attr_widths)
1237
0
{
1238
0
  int32   result;
1239
0
  Relation  relation;
1240
1241
  /* As above, assume relation is already locked */
1242
0
  relation = table_open(relid, NoLock);
1243
1244
0
  result = get_rel_data_width(relation, attr_widths);
1245
1246
0
  table_close(relation, NoLock);
1247
1248
0
  return result;
1249
0
}
1250
1251
1252
/*
1253
 * get_relation_constraints
1254
 *
1255
 * Retrieve the applicable constraint expressions of the given relation.
1256
 * Only constraints that have been validated are considered.
1257
 *
1258
 * Returns a List (possibly empty) of constraint expressions.  Each one
1259
 * has been canonicalized, and its Vars are changed to have the varno
1260
 * indicated by rel->relid.  This allows the expressions to be easily
1261
 * compared to expressions taken from WHERE.
1262
 *
1263
 * If include_noinherit is true, it's okay to include constraints that
1264
 * are marked NO INHERIT.
1265
 *
1266
 * If include_notnull is true, "col IS NOT NULL" expressions are generated
1267
 * and added to the result for each column that's marked attnotnull.
1268
 *
1269
 * If include_partition is true, and the relation is a partition,
1270
 * also include the partitioning constraints.
1271
 *
1272
 * Note: at present this is invoked at most once per relation per planner
1273
 * run, and in many cases it won't be invoked at all, so there seems no
1274
 * point in caching the data in RelOptInfo.
1275
 */
1276
static List *
1277
get_relation_constraints(PlannerInfo *root,
1278
             Oid relationObjectId, RelOptInfo *rel,
1279
             bool include_noinherit,
1280
             bool include_notnull,
1281
             bool include_partition)
1282
0
{
1283
0
  List     *result = NIL;
1284
0
  Index   varno = rel->relid;
1285
0
  Relation  relation;
1286
0
  TupleConstr *constr;
1287
1288
  /*
1289
   * We assume the relation has already been safely locked.
1290
   */
1291
0
  relation = table_open(relationObjectId, NoLock);
1292
1293
0
  constr = relation->rd_att->constr;
1294
0
  if (constr != NULL)
1295
0
  {
1296
0
    int     num_check = constr->num_check;
1297
0
    int     i;
1298
1299
0
    for (i = 0; i < num_check; i++)
1300
0
    {
1301
0
      Node     *cexpr;
1302
1303
      /*
1304
       * If this constraint hasn't been fully validated yet, we must
1305
       * ignore it here.
1306
       */
1307
0
      if (!constr->check[i].ccvalid)
1308
0
        continue;
1309
1310
      /*
1311
       * NOT ENFORCED constraints are always marked as invalid, which
1312
       * should have been ignored.
1313
       */
1314
0
      Assert(constr->check[i].ccenforced);
1315
1316
      /*
1317
       * Also ignore if NO INHERIT and we weren't told that that's safe.
1318
       */
1319
0
      if (constr->check[i].ccnoinherit && !include_noinherit)
1320
0
        continue;
1321
1322
0
      cexpr = stringToNode(constr->check[i].ccbin);
1323
1324
      /*
1325
       * Run each expression through const-simplification and
1326
       * canonicalization.  This is not just an optimization, but is
1327
       * necessary, because we will be comparing it to
1328
       * similarly-processed qual clauses, and may fail to detect valid
1329
       * matches without this.  This must match the processing done to
1330
       * qual clauses in preprocess_expression()!  (We can skip the
1331
       * stuff involving subqueries, however, since we don't allow any
1332
       * in check constraints.)
1333
       */
1334
0
      cexpr = eval_const_expressions(root, cexpr);
1335
1336
0
      cexpr = (Node *) canonicalize_qual((Expr *) cexpr, true);
1337
1338
      /* Fix Vars to have the desired varno */
1339
0
      if (varno != 1)
1340
0
        ChangeVarNodes(cexpr, 1, varno, 0);
1341
1342
      /*
1343
       * Finally, convert to implicit-AND format (that is, a List) and
1344
       * append the resulting item(s) to our output list.
1345
       */
1346
0
      result = list_concat(result,
1347
0
                 make_ands_implicit((Expr *) cexpr));
1348
0
    }
1349
1350
    /* Add NOT NULL constraints in expression form, if requested */
1351
0
    if (include_notnull && constr->has_not_null)
1352
0
    {
1353
0
      int     natts = relation->rd_att->natts;
1354
1355
0
      for (i = 1; i <= natts; i++)
1356
0
      {
1357
0
        CompactAttribute *att = TupleDescCompactAttr(relation->rd_att, i - 1);
1358
1359
0
        if (att->attnullability == ATTNULLABLE_VALID && !att->attisdropped)
1360
0
        {
1361
0
          Form_pg_attribute wholeatt = TupleDescAttr(relation->rd_att, i - 1);
1362
0
          NullTest   *ntest = makeNode(NullTest);
1363
1364
0
          ntest->arg = (Expr *) makeVar(varno,
1365
0
                          i,
1366
0
                          wholeatt->atttypid,
1367
0
                          wholeatt->atttypmod,
1368
0
                          wholeatt->attcollation,
1369
0
                          0);
1370
0
          ntest->nulltesttype = IS_NOT_NULL;
1371
1372
          /*
1373
           * argisrow=false is correct even for a composite column,
1374
           * because attnotnull does not represent a SQL-spec IS NOT
1375
           * NULL test in such a case, just IS DISTINCT FROM NULL.
1376
           */
1377
0
          ntest->argisrow = false;
1378
0
          ntest->location = -1;
1379
0
          result = lappend(result, ntest);
1380
0
        }
1381
0
      }
1382
0
    }
1383
0
  }
1384
1385
  /*
1386
   * Add partitioning constraints, if requested.
1387
   */
1388
0
  if (include_partition && relation->rd_rel->relispartition)
1389
0
  {
1390
    /* make sure rel->partition_qual is set */
1391
0
    set_baserel_partition_constraint(relation, rel);
1392
0
    result = list_concat(result, rel->partition_qual);
1393
0
  }
1394
1395
0
  table_close(relation, NoLock);
1396
1397
0
  return result;
1398
0
}
1399
1400
/*
1401
 * Try loading data for the statistics object.
1402
 *
1403
 * We don't know if the data (specified by statOid and inh value) exist.
1404
 * The result is stored in stainfos list.
1405
 */
1406
static void
1407
get_relation_statistics_worker(List **stainfos, RelOptInfo *rel,
1408
                 Oid statOid, bool inh,
1409
                 Bitmapset *keys, List *exprs)
1410
0
{
1411
0
  Form_pg_statistic_ext_data dataForm;
1412
0
  HeapTuple dtup;
1413
1414
0
  dtup = SearchSysCache2(STATEXTDATASTXOID,
1415
0
               ObjectIdGetDatum(statOid), BoolGetDatum(inh));
1416
0
  if (!HeapTupleIsValid(dtup))
1417
0
    return;
1418
1419
0
  dataForm = (Form_pg_statistic_ext_data) GETSTRUCT(dtup);
1420
1421
  /* add one StatisticExtInfo for each kind built */
1422
0
  if (statext_is_kind_built(dtup, STATS_EXT_NDISTINCT))
1423
0
  {
1424
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1425
1426
0
    info->statOid = statOid;
1427
0
    info->inherit = dataForm->stxdinherit;
1428
0
    info->rel = rel;
1429
0
    info->kind = STATS_EXT_NDISTINCT;
1430
0
    info->keys = bms_copy(keys);
1431
0
    info->exprs = exprs;
1432
1433
0
    *stainfos = lappend(*stainfos, info);
1434
0
  }
1435
1436
0
  if (statext_is_kind_built(dtup, STATS_EXT_DEPENDENCIES))
1437
0
  {
1438
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1439
1440
0
    info->statOid = statOid;
1441
0
    info->inherit = dataForm->stxdinherit;
1442
0
    info->rel = rel;
1443
0
    info->kind = STATS_EXT_DEPENDENCIES;
1444
0
    info->keys = bms_copy(keys);
1445
0
    info->exprs = exprs;
1446
1447
0
    *stainfos = lappend(*stainfos, info);
1448
0
  }
1449
1450
0
  if (statext_is_kind_built(dtup, STATS_EXT_MCV))
1451
0
  {
1452
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1453
1454
0
    info->statOid = statOid;
1455
0
    info->inherit = dataForm->stxdinherit;
1456
0
    info->rel = rel;
1457
0
    info->kind = STATS_EXT_MCV;
1458
0
    info->keys = bms_copy(keys);
1459
0
    info->exprs = exprs;
1460
1461
0
    *stainfos = lappend(*stainfos, info);
1462
0
  }
1463
1464
0
  if (statext_is_kind_built(dtup, STATS_EXT_EXPRESSIONS))
1465
0
  {
1466
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1467
1468
0
    info->statOid = statOid;
1469
0
    info->inherit = dataForm->stxdinherit;
1470
0
    info->rel = rel;
1471
0
    info->kind = STATS_EXT_EXPRESSIONS;
1472
0
    info->keys = bms_copy(keys);
1473
0
    info->exprs = exprs;
1474
1475
0
    *stainfos = lappend(*stainfos, info);
1476
0
  }
1477
1478
0
  ReleaseSysCache(dtup);
1479
0
}
1480
1481
/*
1482
 * get_relation_statistics
1483
 *    Retrieve extended statistics defined on the table.
1484
 *
1485
 * Returns a List (possibly empty) of StatisticExtInfo objects describing
1486
 * the statistics.  Note that this doesn't load the actual statistics data,
1487
 * just the identifying metadata.  Only stats actually built are considered.
1488
 */
1489
static List *
1490
get_relation_statistics(RelOptInfo *rel, Relation relation)
1491
0
{
1492
0
  Index   varno = rel->relid;
1493
0
  List     *statoidlist;
1494
0
  List     *stainfos = NIL;
1495
0
  ListCell   *l;
1496
1497
0
  statoidlist = RelationGetStatExtList(relation);
1498
1499
0
  foreach(l, statoidlist)
1500
0
  {
1501
0
    Oid     statOid = lfirst_oid(l);
1502
0
    Form_pg_statistic_ext staForm;
1503
0
    HeapTuple htup;
1504
0
    Bitmapset  *keys = NULL;
1505
0
    List     *exprs = NIL;
1506
0
    int     i;
1507
1508
0
    htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statOid));
1509
0
    if (!HeapTupleIsValid(htup))
1510
0
      elog(ERROR, "cache lookup failed for statistics object %u", statOid);
1511
0
    staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
1512
1513
    /*
1514
     * First, build the array of columns covered.  This is ultimately
1515
     * wasted if no stats within the object have actually been built, but
1516
     * it doesn't seem worth troubling over that case.
1517
     */
1518
0
    for (i = 0; i < staForm->stxkeys.dim1; i++)
1519
0
      keys = bms_add_member(keys, staForm->stxkeys.values[i]);
1520
1521
    /*
1522
     * Preprocess expressions (if any). We read the expressions, run them
1523
     * through eval_const_expressions, and fix the varnos.
1524
     *
1525
     * XXX We don't know yet if there are any data for this stats object,
1526
     * with either stxdinherit value. But it's reasonable to assume there
1527
     * is at least one of those, possibly both. So it's better to process
1528
     * keys and expressions here.
1529
     */
1530
0
    {
1531
0
      bool    isnull;
1532
0
      Datum   datum;
1533
1534
      /* decode expression (if any) */
1535
0
      datum = SysCacheGetAttr(STATEXTOID, htup,
1536
0
                  Anum_pg_statistic_ext_stxexprs, &isnull);
1537
1538
0
      if (!isnull)
1539
0
      {
1540
0
        char     *exprsString;
1541
1542
0
        exprsString = TextDatumGetCString(datum);
1543
0
        exprs = (List *) stringToNode(exprsString);
1544
0
        pfree(exprsString);
1545
1546
        /*
1547
         * Run the expressions through eval_const_expressions. This is
1548
         * not just an optimization, but is necessary, because the
1549
         * planner will be comparing them to similarly-processed qual
1550
         * clauses, and may fail to detect valid matches without this.
1551
         * We must not use canonicalize_qual, however, since these
1552
         * aren't qual expressions.
1553
         */
1554
0
        exprs = (List *) eval_const_expressions(NULL, (Node *) exprs);
1555
1556
        /* May as well fix opfuncids too */
1557
0
        fix_opfuncids((Node *) exprs);
1558
1559
        /*
1560
         * Modify the copies we obtain from the relcache to have the
1561
         * correct varno for the parent relation, so that they match
1562
         * up correctly against qual clauses.
1563
         */
1564
0
        if (varno != 1)
1565
0
          ChangeVarNodes((Node *) exprs, 1, varno, 0);
1566
0
      }
1567
0
    }
1568
1569
    /* extract statistics for possible values of stxdinherit flag */
1570
1571
0
    get_relation_statistics_worker(&stainfos, rel, statOid, true, keys, exprs);
1572
1573
0
    get_relation_statistics_worker(&stainfos, rel, statOid, false, keys, exprs);
1574
1575
0
    ReleaseSysCache(htup);
1576
0
    bms_free(keys);
1577
0
  }
1578
1579
0
  list_free(statoidlist);
1580
1581
0
  return stainfos;
1582
0
}
1583
1584
/*
1585
 * relation_excluded_by_constraints
1586
 *
1587
 * Detect whether the relation need not be scanned because it has either
1588
 * self-inconsistent restrictions, or restrictions inconsistent with the
1589
 * relation's applicable constraints.
1590
 *
1591
 * Note: this examines only rel->relid, rel->reloptkind, and
1592
 * rel->baserestrictinfo; therefore it can be called before filling in
1593
 * other fields of the RelOptInfo.
1594
 */
1595
bool
1596
relation_excluded_by_constraints(PlannerInfo *root,
1597
                 RelOptInfo *rel, RangeTblEntry *rte)
1598
0
{
1599
0
  bool    include_noinherit;
1600
0
  bool    include_notnull;
1601
0
  bool    include_partition = false;
1602
0
  List     *safe_restrictions;
1603
0
  List     *constraint_pred;
1604
0
  List     *safe_constraints;
1605
0
  ListCell   *lc;
1606
1607
  /* As of now, constraint exclusion works only with simple relations. */
1608
0
  Assert(IS_SIMPLE_REL(rel));
1609
1610
  /*
1611
   * If there are no base restriction clauses, we have no hope of proving
1612
   * anything below, so fall out quickly.
1613
   */
1614
0
  if (rel->baserestrictinfo == NIL)
1615
0
    return false;
1616
1617
  /*
1618
   * Regardless of the setting of constraint_exclusion, detect
1619
   * constant-FALSE-or-NULL restriction clauses.  Although const-folding
1620
   * will reduce "anything AND FALSE" to just "FALSE", the baserestrictinfo
1621
   * list can still have other members besides the FALSE constant, due to
1622
   * qual pushdown and other mechanisms; so check them all.  This doesn't
1623
   * fire very often, but it seems cheap enough to be worth doing anyway.
1624
   * (Without this, we'd miss some optimizations that 9.5 and earlier found
1625
   * via much more roundabout methods.)
1626
   */
1627
0
  foreach(lc, rel->baserestrictinfo)
1628
0
  {
1629
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1630
0
    Expr     *clause = rinfo->clause;
1631
1632
0
    if (clause && IsA(clause, Const) &&
1633
0
      (((Const *) clause)->constisnull ||
1634
0
       !DatumGetBool(((Const *) clause)->constvalue)))
1635
0
      return true;
1636
0
  }
1637
1638
  /*
1639
   * Skip further tests, depending on constraint_exclusion.
1640
   */
1641
0
  switch (constraint_exclusion)
1642
0
  {
1643
0
    case CONSTRAINT_EXCLUSION_OFF:
1644
      /* In 'off' mode, never make any further tests */
1645
0
      return false;
1646
1647
0
    case CONSTRAINT_EXCLUSION_PARTITION:
1648
1649
      /*
1650
       * When constraint_exclusion is set to 'partition' we only handle
1651
       * appendrel members.  Partition pruning has already been applied,
1652
       * so there is no need to consider the rel's partition constraints
1653
       * here.
1654
       */
1655
0
      if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
1656
0
        break;     /* appendrel member, so process it */
1657
0
      return false;
1658
1659
0
    case CONSTRAINT_EXCLUSION_ON:
1660
1661
      /*
1662
       * In 'on' mode, always apply constraint exclusion.  If we are
1663
       * considering a baserel that is a partition (i.e., it was
1664
       * directly named rather than expanded from a parent table), then
1665
       * its partition constraints haven't been considered yet, so
1666
       * include them in the processing here.
1667
       */
1668
0
      if (rel->reloptkind == RELOPT_BASEREL)
1669
0
        include_partition = true;
1670
0
      break;        /* always try to exclude */
1671
0
  }
1672
1673
  /*
1674
   * Check for self-contradictory restriction clauses.  We dare not make
1675
   * deductions with non-immutable functions, but any immutable clauses that
1676
   * are self-contradictory allow us to conclude the scan is unnecessary.
1677
   *
1678
   * Note: strip off RestrictInfo because predicate_refuted_by() isn't
1679
   * expecting to see any in its predicate argument.
1680
   */
1681
0
  safe_restrictions = NIL;
1682
0
  foreach(lc, rel->baserestrictinfo)
1683
0
  {
1684
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1685
1686
0
    if (!contain_mutable_functions((Node *) rinfo->clause))
1687
0
      safe_restrictions = lappend(safe_restrictions, rinfo->clause);
1688
0
  }
1689
1690
  /*
1691
   * We can use weak refutation here, since we're comparing restriction
1692
   * clauses with restriction clauses.
1693
   */
1694
0
  if (predicate_refuted_by(safe_restrictions, safe_restrictions, true))
1695
0
    return true;
1696
1697
  /*
1698
   * Only plain relations have constraints, so stop here for other rtekinds.
1699
   */
1700
0
  if (rte->rtekind != RTE_RELATION)
1701
0
    return false;
1702
1703
  /*
1704
   * If we are scanning just this table, we can use NO INHERIT constraints,
1705
   * but not if we're scanning its children too.  (Note that partitioned
1706
   * tables should never have NO INHERIT constraints; but it's not necessary
1707
   * for us to assume that here.)
1708
   */
1709
0
  include_noinherit = !rte->inh;
1710
1711
  /*
1712
   * Currently, attnotnull constraints must be treated as NO INHERIT unless
1713
   * this is a partitioned table.  In future we might track their
1714
   * inheritance status more accurately, allowing this to be refined.
1715
   *
1716
   * XXX do we need/want to change this?
1717
   */
1718
0
  include_notnull = (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE);
1719
1720
  /*
1721
   * Fetch the appropriate set of constraint expressions.
1722
   */
1723
0
  constraint_pred = get_relation_constraints(root, rte->relid, rel,
1724
0
                         include_noinherit,
1725
0
                         include_notnull,
1726
0
                         include_partition);
1727
1728
  /*
1729
   * We do not currently enforce that CHECK constraints contain only
1730
   * immutable functions, so it's necessary to check here. We daren't draw
1731
   * conclusions from plan-time evaluation of non-immutable functions. Since
1732
   * they're ANDed, we can just ignore any mutable constraints in the list,
1733
   * and reason about the rest.
1734
   */
1735
0
  safe_constraints = NIL;
1736
0
  foreach(lc, constraint_pred)
1737
0
  {
1738
0
    Node     *pred = (Node *) lfirst(lc);
1739
1740
0
    if (!contain_mutable_functions(pred))
1741
0
      safe_constraints = lappend(safe_constraints, pred);
1742
0
  }
1743
1744
  /*
1745
   * The constraints are effectively ANDed together, so we can just try to
1746
   * refute the entire collection at once.  This may allow us to make proofs
1747
   * that would fail if we took them individually.
1748
   *
1749
   * Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
1750
   * an obvious optimization.  Some of the clauses might be OR clauses that
1751
   * have volatile and nonvolatile subclauses, and it's OK to make
1752
   * deductions with the nonvolatile parts.
1753
   *
1754
   * We need strong refutation because we have to prove that the constraints
1755
   * would yield false, not just NULL.
1756
   */
1757
0
  if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo, false))
1758
0
    return true;
1759
1760
0
  return false;
1761
0
}
1762
1763
1764
/*
1765
 * build_physical_tlist
1766
 *
1767
 * Build a targetlist consisting of exactly the relation's user attributes,
1768
 * in order.  The executor can special-case such tlists to avoid a projection
1769
 * step at runtime, so we use such tlists preferentially for scan nodes.
1770
 *
1771
 * Exception: if there are any dropped or missing columns, we punt and return
1772
 * NIL.  Ideally we would like to handle these cases too.  However this
1773
 * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc
1774
 * for a tlist that includes vars of no-longer-existent types.  In theory we
1775
 * could dig out the required info from the pg_attribute entries of the
1776
 * relation, but that data is not readily available to ExecTypeFromTL.
1777
 * For now, we don't apply the physical-tlist optimization when there are
1778
 * dropped cols.
1779
 *
1780
 * We also support building a "physical" tlist for subqueries, functions,
1781
 * values lists, table expressions, and CTEs, since the same optimization can
1782
 * occur in SubqueryScan, FunctionScan, ValuesScan, CteScan, TableFunc,
1783
 * NamedTuplestoreScan, and WorkTableScan nodes.
1784
 */
1785
List *
1786
build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
1787
0
{
1788
0
  List     *tlist = NIL;
1789
0
  Index   varno = rel->relid;
1790
0
  RangeTblEntry *rte = planner_rt_fetch(varno, root);
1791
0
  Relation  relation;
1792
0
  Query    *subquery;
1793
0
  Var      *var;
1794
0
  ListCell   *l;
1795
0
  int     attrno,
1796
0
        numattrs;
1797
0
  List     *colvars;
1798
1799
0
  switch (rte->rtekind)
1800
0
  {
1801
0
    case RTE_RELATION:
1802
      /* Assume we already have adequate lock */
1803
0
      relation = table_open(rte->relid, NoLock);
1804
1805
0
      numattrs = RelationGetNumberOfAttributes(relation);
1806
0
      for (attrno = 1; attrno <= numattrs; attrno++)
1807
0
      {
1808
0
        Form_pg_attribute att_tup = TupleDescAttr(relation->rd_att,
1809
0
                              attrno - 1);
1810
1811
0
        if (att_tup->attisdropped || att_tup->atthasmissing)
1812
0
        {
1813
          /* found a dropped or missing col, so punt */
1814
0
          tlist = NIL;
1815
0
          break;
1816
0
        }
1817
1818
0
        var = makeVar(varno,
1819
0
                attrno,
1820
0
                att_tup->atttypid,
1821
0
                att_tup->atttypmod,
1822
0
                att_tup->attcollation,
1823
0
                0);
1824
1825
0
        tlist = lappend(tlist,
1826
0
                makeTargetEntry((Expr *) var,
1827
0
                        attrno,
1828
0
                        NULL,
1829
0
                        false));
1830
0
      }
1831
1832
0
      table_close(relation, NoLock);
1833
0
      break;
1834
1835
0
    case RTE_SUBQUERY:
1836
0
      subquery = rte->subquery;
1837
0
      foreach(l, subquery->targetList)
1838
0
      {
1839
0
        TargetEntry *tle = (TargetEntry *) lfirst(l);
1840
1841
        /*
1842
         * A resjunk column of the subquery can be reflected as
1843
         * resjunk in the physical tlist; we need not punt.
1844
         */
1845
0
        var = makeVarFromTargetEntry(varno, tle);
1846
1847
0
        tlist = lappend(tlist,
1848
0
                makeTargetEntry((Expr *) var,
1849
0
                        tle->resno,
1850
0
                        NULL,
1851
0
                        tle->resjunk));
1852
0
      }
1853
0
      break;
1854
1855
0
    case RTE_FUNCTION:
1856
0
    case RTE_TABLEFUNC:
1857
0
    case RTE_VALUES:
1858
0
    case RTE_CTE:
1859
0
    case RTE_NAMEDTUPLESTORE:
1860
0
    case RTE_RESULT:
1861
      /* Not all of these can have dropped cols, but share code anyway */
1862
0
      expandRTE(rte, varno, 0, VAR_RETURNING_DEFAULT, -1,
1863
0
            true /* include dropped */ , NULL, &colvars);
1864
0
      foreach(l, colvars)
1865
0
      {
1866
0
        var = (Var *) lfirst(l);
1867
1868
        /*
1869
         * A non-Var in expandRTE's output means a dropped column;
1870
         * must punt.
1871
         */
1872
0
        if (!IsA(var, Var))
1873
0
        {
1874
0
          tlist = NIL;
1875
0
          break;
1876
0
        }
1877
1878
0
        tlist = lappend(tlist,
1879
0
                makeTargetEntry((Expr *) var,
1880
0
                        var->varattno,
1881
0
                        NULL,
1882
0
                        false));
1883
0
      }
1884
0
      break;
1885
1886
0
    default:
1887
      /* caller error */
1888
0
      elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",
1889
0
         (int) rte->rtekind);
1890
0
      break;
1891
0
  }
1892
1893
0
  return tlist;
1894
0
}
1895
1896
/*
1897
 * build_index_tlist
1898
 *
1899
 * Build a targetlist representing the columns of the specified index.
1900
 * Each column is represented by a Var for the corresponding base-relation
1901
 * column, or an expression in base-relation Vars, as appropriate.
1902
 *
1903
 * There are never any dropped columns in indexes, so unlike
1904
 * build_physical_tlist, we need no failure case.
1905
 */
1906
static List *
1907
build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
1908
          Relation heapRelation)
1909
0
{
1910
0
  List     *tlist = NIL;
1911
0
  Index   varno = index->rel->relid;
1912
0
  ListCell   *indexpr_item;
1913
0
  int     i;
1914
1915
0
  indexpr_item = list_head(index->indexprs);
1916
0
  for (i = 0; i < index->ncolumns; i++)
1917
0
  {
1918
0
    int     indexkey = index->indexkeys[i];
1919
0
    Expr     *indexvar;
1920
1921
0
    if (indexkey != 0)
1922
0
    {
1923
      /* simple column */
1924
0
      const FormData_pg_attribute *att_tup;
1925
1926
0
      if (indexkey < 0)
1927
0
        att_tup = SystemAttributeDefinition(indexkey);
1928
0
      else
1929
0
        att_tup = TupleDescAttr(heapRelation->rd_att, indexkey - 1);
1930
1931
0
      indexvar = (Expr *) makeVar(varno,
1932
0
                    indexkey,
1933
0
                    att_tup->atttypid,
1934
0
                    att_tup->atttypmod,
1935
0
                    att_tup->attcollation,
1936
0
                    0);
1937
0
    }
1938
0
    else
1939
0
    {
1940
      /* expression column */
1941
0
      if (indexpr_item == NULL)
1942
0
        elog(ERROR, "wrong number of index expressions");
1943
0
      indexvar = (Expr *) lfirst(indexpr_item);
1944
0
      indexpr_item = lnext(index->indexprs, indexpr_item);
1945
0
    }
1946
1947
0
    tlist = lappend(tlist,
1948
0
            makeTargetEntry(indexvar,
1949
0
                    i + 1,
1950
0
                    NULL,
1951
0
                    false));
1952
0
  }
1953
0
  if (indexpr_item != NULL)
1954
0
    elog(ERROR, "wrong number of index expressions");
1955
1956
0
  return tlist;
1957
0
}
1958
1959
/*
1960
 * restriction_selectivity
1961
 *
1962
 * Returns the selectivity of a specified restriction operator clause.
1963
 * This code executes registered procedures stored in the
1964
 * operator relation, by calling the function manager.
1965
 *
1966
 * See clause_selectivity() for the meaning of the additional parameters.
1967
 */
1968
Selectivity
1969
restriction_selectivity(PlannerInfo *root,
1970
            Oid operatorid,
1971
            List *args,
1972
            Oid inputcollid,
1973
            int varRelid)
1974
0
{
1975
0
  RegProcedure oprrest = get_oprrest(operatorid);
1976
0
  float8    result;
1977
1978
  /*
1979
   * if the oprrest procedure is missing for whatever reason, use a
1980
   * selectivity of 0.5
1981
   */
1982
0
  if (!oprrest)
1983
0
    return (Selectivity) 0.5;
1984
1985
0
  result = DatumGetFloat8(OidFunctionCall4Coll(oprrest,
1986
0
                         inputcollid,
1987
0
                         PointerGetDatum(root),
1988
0
                         ObjectIdGetDatum(operatorid),
1989
0
                         PointerGetDatum(args),
1990
0
                         Int32GetDatum(varRelid)));
1991
1992
0
  if (result < 0.0 || result > 1.0)
1993
0
    elog(ERROR, "invalid restriction selectivity: %f", result);
1994
1995
0
  return (Selectivity) result;
1996
0
}
1997
1998
/*
1999
 * join_selectivity
2000
 *
2001
 * Returns the selectivity of a specified join operator clause.
2002
 * This code executes registered procedures stored in the
2003
 * operator relation, by calling the function manager.
2004
 *
2005
 * See clause_selectivity() for the meaning of the additional parameters.
2006
 */
2007
Selectivity
2008
join_selectivity(PlannerInfo *root,
2009
         Oid operatorid,
2010
         List *args,
2011
         Oid inputcollid,
2012
         JoinType jointype,
2013
         SpecialJoinInfo *sjinfo)
2014
0
{
2015
0
  RegProcedure oprjoin = get_oprjoin(operatorid);
2016
0
  float8    result;
2017
2018
  /*
2019
   * if the oprjoin procedure is missing for whatever reason, use a
2020
   * selectivity of 0.5
2021
   */
2022
0
  if (!oprjoin)
2023
0
    return (Selectivity) 0.5;
2024
2025
0
  result = DatumGetFloat8(OidFunctionCall5Coll(oprjoin,
2026
0
                         inputcollid,
2027
0
                         PointerGetDatum(root),
2028
0
                         ObjectIdGetDatum(operatorid),
2029
0
                         PointerGetDatum(args),
2030
0
                         Int16GetDatum(jointype),
2031
0
                         PointerGetDatum(sjinfo)));
2032
2033
0
  if (result < 0.0 || result > 1.0)
2034
0
    elog(ERROR, "invalid join selectivity: %f", result);
2035
2036
0
  return (Selectivity) result;
2037
0
}
2038
2039
/*
2040
 * function_selectivity
2041
 *
2042
 * Returns the selectivity of a specified boolean function clause.
2043
 * This code executes registered procedures stored in the
2044
 * pg_proc relation, by calling the function manager.
2045
 *
2046
 * See clause_selectivity() for the meaning of the additional parameters.
2047
 */
2048
Selectivity
2049
function_selectivity(PlannerInfo *root,
2050
           Oid funcid,
2051
           List *args,
2052
           Oid inputcollid,
2053
           bool is_join,
2054
           int varRelid,
2055
           JoinType jointype,
2056
           SpecialJoinInfo *sjinfo)
2057
0
{
2058
0
  RegProcedure prosupport = get_func_support(funcid);
2059
0
  SupportRequestSelectivity req;
2060
0
  SupportRequestSelectivity *sresult;
2061
2062
  /*
2063
   * If no support function is provided, use our historical default
2064
   * estimate, 0.3333333.  This seems a pretty unprincipled choice, but
2065
   * Postgres has been using that estimate for function calls since 1992.
2066
   * The hoariness of this behavior suggests that we should not be in too
2067
   * much hurry to use another value.
2068
   */
2069
0
  if (!prosupport)
2070
0
    return (Selectivity) 0.3333333;
2071
2072
0
  req.type = T_SupportRequestSelectivity;
2073
0
  req.root = root;
2074
0
  req.funcid = funcid;
2075
0
  req.args = args;
2076
0
  req.inputcollid = inputcollid;
2077
0
  req.is_join = is_join;
2078
0
  req.varRelid = varRelid;
2079
0
  req.jointype = jointype;
2080
0
  req.sjinfo = sjinfo;
2081
0
  req.selectivity = -1;   /* to catch failure to set the value */
2082
2083
0
  sresult = (SupportRequestSelectivity *)
2084
0
    DatumGetPointer(OidFunctionCall1(prosupport,
2085
0
                     PointerGetDatum(&req)));
2086
2087
  /* If support function fails, use default */
2088
0
  if (sresult != &req)
2089
0
    return (Selectivity) 0.3333333;
2090
2091
0
  if (req.selectivity < 0.0 || req.selectivity > 1.0)
2092
0
    elog(ERROR, "invalid function selectivity: %f", req.selectivity);
2093
2094
0
  return (Selectivity) req.selectivity;
2095
0
}
2096
2097
/*
2098
 * add_function_cost
2099
 *
2100
 * Get an estimate of the execution cost of a function, and *add* it to
2101
 * the contents of *cost.  The estimate may include both one-time and
2102
 * per-tuple components, since QualCost does.
2103
 *
2104
 * The funcid must always be supplied.  If it is being called as the
2105
 * implementation of a specific parsetree node (FuncExpr, OpExpr,
2106
 * WindowFunc, etc), pass that as "node", else pass NULL.
2107
 *
2108
 * In some usages root might be NULL, too.
2109
 */
2110
void
2111
add_function_cost(PlannerInfo *root, Oid funcid, Node *node,
2112
          QualCost *cost)
2113
0
{
2114
0
  HeapTuple proctup;
2115
0
  Form_pg_proc procform;
2116
2117
0
  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2118
0
  if (!HeapTupleIsValid(proctup))
2119
0
    elog(ERROR, "cache lookup failed for function %u", funcid);
2120
0
  procform = (Form_pg_proc) GETSTRUCT(proctup);
2121
2122
0
  if (OidIsValid(procform->prosupport))
2123
0
  {
2124
0
    SupportRequestCost req;
2125
0
    SupportRequestCost *sresult;
2126
2127
0
    req.type = T_SupportRequestCost;
2128
0
    req.root = root;
2129
0
    req.funcid = funcid;
2130
0
    req.node = node;
2131
2132
    /* Initialize cost fields so that support function doesn't have to */
2133
0
    req.startup = 0;
2134
0
    req.per_tuple = 0;
2135
2136
0
    sresult = (SupportRequestCost *)
2137
0
      DatumGetPointer(OidFunctionCall1(procform->prosupport,
2138
0
                       PointerGetDatum(&req)));
2139
2140
0
    if (sresult == &req)
2141
0
    {
2142
      /* Success, so accumulate support function's estimate into *cost */
2143
0
      cost->startup += req.startup;
2144
0
      cost->per_tuple += req.per_tuple;
2145
0
      ReleaseSysCache(proctup);
2146
0
      return;
2147
0
    }
2148
0
  }
2149
2150
  /* No support function, or it failed, so rely on procost */
2151
0
  cost->per_tuple += procform->procost * cpu_operator_cost;
2152
2153
0
  ReleaseSysCache(proctup);
2154
0
}
2155
2156
/*
2157
 * get_function_rows
2158
 *
2159
 * Get an estimate of the number of rows returned by a set-returning function.
2160
 *
2161
 * The funcid must always be supplied.  In current usage, the calling node
2162
 * will always be supplied, and will be either a FuncExpr or OpExpr.
2163
 * But it's a good idea to not fail if it's NULL.
2164
 *
2165
 * In some usages root might be NULL, too.
2166
 *
2167
 * Note: this returns the unfiltered result of the support function, if any.
2168
 * It's usually a good idea to apply clamp_row_est() to the result, but we
2169
 * leave it to the caller to do so.
2170
 */
2171
double
2172
get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
2173
0
{
2174
0
  HeapTuple proctup;
2175
0
  Form_pg_proc procform;
2176
0
  double    result;
2177
2178
0
  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2179
0
  if (!HeapTupleIsValid(proctup))
2180
0
    elog(ERROR, "cache lookup failed for function %u", funcid);
2181
0
  procform = (Form_pg_proc) GETSTRUCT(proctup);
2182
2183
0
  Assert(procform->proretset);  /* else caller error */
2184
2185
0
  if (OidIsValid(procform->prosupport))
2186
0
  {
2187
0
    SupportRequestRows req;
2188
0
    SupportRequestRows *sresult;
2189
2190
0
    req.type = T_SupportRequestRows;
2191
0
    req.root = root;
2192
0
    req.funcid = funcid;
2193
0
    req.node = node;
2194
2195
0
    req.rows = 0;     /* just for sanity */
2196
2197
0
    sresult = (SupportRequestRows *)
2198
0
      DatumGetPointer(OidFunctionCall1(procform->prosupport,
2199
0
                       PointerGetDatum(&req)));
2200
2201
0
    if (sresult == &req)
2202
0
    {
2203
      /* Success */
2204
0
      ReleaseSysCache(proctup);
2205
0
      return req.rows;
2206
0
    }
2207
0
  }
2208
2209
  /* No support function, or it failed, so rely on prorows */
2210
0
  result = procform->prorows;
2211
2212
0
  ReleaseSysCache(proctup);
2213
2214
0
  return result;
2215
0
}
2216
2217
/*
2218
 * has_unique_index
2219
 *
2220
 * Detect whether there is a unique index on the specified attribute
2221
 * of the specified relation, thus allowing us to conclude that all
2222
 * the (non-null) values of the attribute are distinct.
2223
 *
2224
 * This function does not check the index's indimmediate property, which
2225
 * means that uniqueness may transiently fail to hold intra-transaction.
2226
 * That's appropriate when we are making statistical estimates, but beware
2227
 * of using this for any correctness proofs.
2228
 */
2229
bool
2230
has_unique_index(RelOptInfo *rel, AttrNumber attno)
2231
0
{
2232
0
  ListCell   *ilist;
2233
2234
0
  foreach(ilist, rel->indexlist)
2235
0
  {
2236
0
    IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
2237
2238
    /*
2239
     * Note: ignore partial indexes, since they don't allow us to conclude
2240
     * that all attr values are distinct, *unless* they are marked predOK
2241
     * which means we know the index's predicate is satisfied by the
2242
     * query. We don't take any interest in expressional indexes either.
2243
     * Also, a multicolumn unique index doesn't allow us to conclude that
2244
     * just the specified attr is unique.
2245
     */
2246
0
    if (index->unique &&
2247
0
      index->nkeycolumns == 1 &&
2248
0
      index->indexkeys[0] == attno &&
2249
0
      (index->indpred == NIL || index->predOK))
2250
0
      return true;
2251
0
  }
2252
0
  return false;
2253
0
}
2254
2255
2256
/*
2257
 * has_row_triggers
2258
 *
2259
 * Detect whether the specified relation has any row-level triggers for event.
2260
 */
2261
bool
2262
has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
2263
0
{
2264
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2265
0
  Relation  relation;
2266
0
  TriggerDesc *trigDesc;
2267
0
  bool    result = false;
2268
2269
  /* Assume we already have adequate lock */
2270
0
  relation = table_open(rte->relid, NoLock);
2271
2272
0
  trigDesc = relation->trigdesc;
2273
0
  switch (event)
2274
0
  {
2275
0
    case CMD_INSERT:
2276
0
      if (trigDesc &&
2277
0
        (trigDesc->trig_insert_after_row ||
2278
0
         trigDesc->trig_insert_before_row))
2279
0
        result = true;
2280
0
      break;
2281
0
    case CMD_UPDATE:
2282
0
      if (trigDesc &&
2283
0
        (trigDesc->trig_update_after_row ||
2284
0
         trigDesc->trig_update_before_row))
2285
0
        result = true;
2286
0
      break;
2287
0
    case CMD_DELETE:
2288
0
      if (trigDesc &&
2289
0
        (trigDesc->trig_delete_after_row ||
2290
0
         trigDesc->trig_delete_before_row))
2291
0
        result = true;
2292
0
      break;
2293
      /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
2294
0
    case CMD_MERGE:
2295
0
      result = false;
2296
0
      break;
2297
0
    default:
2298
0
      elog(ERROR, "unrecognized CmdType: %d", (int) event);
2299
0
      break;
2300
0
  }
2301
2302
0
  table_close(relation, NoLock);
2303
0
  return result;
2304
0
}
2305
2306
/*
2307
 * has_stored_generated_columns
2308
 *
2309
 * Does table identified by RTI have any STORED GENERATED columns?
2310
 */
2311
bool
2312
has_stored_generated_columns(PlannerInfo *root, Index rti)
2313
0
{
2314
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2315
0
  Relation  relation;
2316
0
  TupleDesc tupdesc;
2317
0
  bool    result = false;
2318
2319
  /* Assume we already have adequate lock */
2320
0
  relation = table_open(rte->relid, NoLock);
2321
2322
0
  tupdesc = RelationGetDescr(relation);
2323
0
  result = tupdesc->constr && tupdesc->constr->has_generated_stored;
2324
2325
0
  table_close(relation, NoLock);
2326
2327
0
  return result;
2328
0
}
2329
2330
/*
2331
 * get_dependent_generated_columns
2332
 *
2333
 * Get the column numbers of any STORED GENERATED columns of the relation
2334
 * that depend on any column listed in target_cols.  Both the input and
2335
 * result bitmapsets contain column numbers offset by
2336
 * FirstLowInvalidHeapAttributeNumber.
2337
 */
2338
Bitmapset *
2339
get_dependent_generated_columns(PlannerInfo *root, Index rti,
2340
                Bitmapset *target_cols)
2341
0
{
2342
0
  Bitmapset  *dependentCols = NULL;
2343
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2344
0
  Relation  relation;
2345
0
  TupleDesc tupdesc;
2346
0
  TupleConstr *constr;
2347
2348
  /* Assume we already have adequate lock */
2349
0
  relation = table_open(rte->relid, NoLock);
2350
2351
0
  tupdesc = RelationGetDescr(relation);
2352
0
  constr = tupdesc->constr;
2353
2354
0
  if (constr && constr->has_generated_stored)
2355
0
  {
2356
0
    for (int i = 0; i < constr->num_defval; i++)
2357
0
    {
2358
0
      AttrDefault *defval = &constr->defval[i];
2359
0
      Node     *expr;
2360
0
      Bitmapset  *attrs_used = NULL;
2361
2362
      /* skip if not generated column */
2363
0
      if (!TupleDescAttr(tupdesc, defval->adnum - 1)->attgenerated)
2364
0
        continue;
2365
2366
      /* identify columns this generated column depends on */
2367
0
      expr = stringToNode(defval->adbin);
2368
0
      pull_varattnos(expr, 1, &attrs_used);
2369
2370
0
      if (bms_overlap(target_cols, attrs_used))
2371
0
        dependentCols = bms_add_member(dependentCols,
2372
0
                         defval->adnum - FirstLowInvalidHeapAttributeNumber);
2373
0
    }
2374
0
  }
2375
2376
0
  table_close(relation, NoLock);
2377
2378
0
  return dependentCols;
2379
0
}
2380
2381
/*
2382
 * set_relation_partition_info
2383
 *
2384
 * Set partitioning scheme and related information for a partitioned table.
2385
 */
2386
static void
2387
set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
2388
              Relation relation)
2389
0
{
2390
0
  PartitionDesc partdesc;
2391
2392
  /*
2393
   * Create the PartitionDirectory infrastructure if we didn't already.
2394
   */
2395
0
  if (root->glob->partition_directory == NULL)
2396
0
  {
2397
0
    root->glob->partition_directory =
2398
0
      CreatePartitionDirectory(CurrentMemoryContext, true);
2399
0
  }
2400
2401
0
  partdesc = PartitionDirectoryLookup(root->glob->partition_directory,
2402
0
                    relation);
2403
0
  rel->part_scheme = find_partition_scheme(root, relation);
2404
0
  Assert(partdesc != NULL && rel->part_scheme != NULL);
2405
0
  rel->boundinfo = partdesc->boundinfo;
2406
0
  rel->nparts = partdesc->nparts;
2407
0
  set_baserel_partition_key_exprs(relation, rel);
2408
0
  set_baserel_partition_constraint(relation, rel);
2409
0
}
2410
2411
/*
2412
 * find_partition_scheme
2413
 *
2414
 * Find or create a PartitionScheme for this Relation.
2415
 */
2416
static PartitionScheme
2417
find_partition_scheme(PlannerInfo *root, Relation relation)
2418
0
{
2419
0
  PartitionKey partkey = RelationGetPartitionKey(relation);
2420
0
  ListCell   *lc;
2421
0
  int     partnatts,
2422
0
        i;
2423
0
  PartitionScheme part_scheme;
2424
2425
  /* A partitioned table should have a partition key. */
2426
0
  Assert(partkey != NULL);
2427
2428
0
  partnatts = partkey->partnatts;
2429
2430
  /* Search for a matching partition scheme and return if found one. */
2431
0
  foreach(lc, root->part_schemes)
2432
0
  {
2433
0
    part_scheme = lfirst(lc);
2434
2435
    /* Match partitioning strategy and number of keys. */
2436
0
    if (partkey->strategy != part_scheme->strategy ||
2437
0
      partnatts != part_scheme->partnatts)
2438
0
      continue;
2439
2440
    /* Match partition key type properties. */
2441
0
    if (memcmp(partkey->partopfamily, part_scheme->partopfamily,
2442
0
           sizeof(Oid) * partnatts) != 0 ||
2443
0
      memcmp(partkey->partopcintype, part_scheme->partopcintype,
2444
0
           sizeof(Oid) * partnatts) != 0 ||
2445
0
      memcmp(partkey->partcollation, part_scheme->partcollation,
2446
0
           sizeof(Oid) * partnatts) != 0)
2447
0
      continue;
2448
2449
    /*
2450
     * Length and byval information should match when partopcintype
2451
     * matches.
2452
     */
2453
0
    Assert(memcmp(partkey->parttyplen, part_scheme->parttyplen,
2454
0
            sizeof(int16) * partnatts) == 0);
2455
0
    Assert(memcmp(partkey->parttypbyval, part_scheme->parttypbyval,
2456
0
            sizeof(bool) * partnatts) == 0);
2457
2458
    /*
2459
     * If partopfamily and partopcintype matched, must have the same
2460
     * partition comparison functions.  Note that we cannot reliably
2461
     * Assert the equality of function structs themselves for they might
2462
     * be different across PartitionKey's, so just Assert for the function
2463
     * OIDs.
2464
     */
2465
#ifdef USE_ASSERT_CHECKING
2466
    for (i = 0; i < partkey->partnatts; i++)
2467
      Assert(partkey->partsupfunc[i].fn_oid ==
2468
           part_scheme->partsupfunc[i].fn_oid);
2469
#endif
2470
2471
    /* Found matching partition scheme. */
2472
0
    return part_scheme;
2473
0
  }
2474
2475
  /*
2476
   * Did not find matching partition scheme. Create one copying relevant
2477
   * information from the relcache. We need to copy the contents of the
2478
   * array since the relcache entry may not survive after we have closed the
2479
   * relation.
2480
   */
2481
0
  part_scheme = (PartitionScheme) palloc0(sizeof(PartitionSchemeData));
2482
0
  part_scheme->strategy = partkey->strategy;
2483
0
  part_scheme->partnatts = partkey->partnatts;
2484
2485
0
  part_scheme->partopfamily = (Oid *) palloc(sizeof(Oid) * partnatts);
2486
0
  memcpy(part_scheme->partopfamily, partkey->partopfamily,
2487
0
       sizeof(Oid) * partnatts);
2488
2489
0
  part_scheme->partopcintype = (Oid *) palloc(sizeof(Oid) * partnatts);
2490
0
  memcpy(part_scheme->partopcintype, partkey->partopcintype,
2491
0
       sizeof(Oid) * partnatts);
2492
2493
0
  part_scheme->partcollation = (Oid *) palloc(sizeof(Oid) * partnatts);
2494
0
  memcpy(part_scheme->partcollation, partkey->partcollation,
2495
0
       sizeof(Oid) * partnatts);
2496
2497
0
  part_scheme->parttyplen = (int16 *) palloc(sizeof(int16) * partnatts);
2498
0
  memcpy(part_scheme->parttyplen, partkey->parttyplen,
2499
0
       sizeof(int16) * partnatts);
2500
2501
0
  part_scheme->parttypbyval = (bool *) palloc(sizeof(bool) * partnatts);
2502
0
  memcpy(part_scheme->parttypbyval, partkey->parttypbyval,
2503
0
       sizeof(bool) * partnatts);
2504
2505
0
  part_scheme->partsupfunc = (FmgrInfo *)
2506
0
    palloc(sizeof(FmgrInfo) * partnatts);
2507
0
  for (i = 0; i < partnatts; i++)
2508
0
    fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i],
2509
0
             CurrentMemoryContext);
2510
2511
  /* Add the partitioning scheme to PlannerInfo. */
2512
0
  root->part_schemes = lappend(root->part_schemes, part_scheme);
2513
2514
0
  return part_scheme;
2515
0
}
2516
2517
/*
2518
 * set_baserel_partition_key_exprs
2519
 *
2520
 * Builds partition key expressions for the given base relation and fills
2521
 * rel->partexprs.
2522
 */
2523
static void
2524
set_baserel_partition_key_exprs(Relation relation,
2525
                RelOptInfo *rel)
2526
0
{
2527
0
  PartitionKey partkey = RelationGetPartitionKey(relation);
2528
0
  int     partnatts;
2529
0
  int     cnt;
2530
0
  List    **partexprs;
2531
0
  ListCell   *lc;
2532
0
  Index   varno = rel->relid;
2533
2534
0
  Assert(IS_SIMPLE_REL(rel) && rel->relid > 0);
2535
2536
  /* A partitioned table should have a partition key. */
2537
0
  Assert(partkey != NULL);
2538
2539
0
  partnatts = partkey->partnatts;
2540
0
  partexprs = (List **) palloc(sizeof(List *) * partnatts);
2541
0
  lc = list_head(partkey->partexprs);
2542
2543
0
  for (cnt = 0; cnt < partnatts; cnt++)
2544
0
  {
2545
0
    Expr     *partexpr;
2546
0
    AttrNumber  attno = partkey->partattrs[cnt];
2547
2548
0
    if (attno != InvalidAttrNumber)
2549
0
    {
2550
      /* Single column partition key is stored as a Var node. */
2551
0
      Assert(attno > 0);
2552
2553
0
      partexpr = (Expr *) makeVar(varno, attno,
2554
0
                    partkey->parttypid[cnt],
2555
0
                    partkey->parttypmod[cnt],
2556
0
                    partkey->parttypcoll[cnt], 0);
2557
0
    }
2558
0
    else
2559
0
    {
2560
0
      if (lc == NULL)
2561
0
        elog(ERROR, "wrong number of partition key expressions");
2562
2563
      /* Re-stamp the expression with given varno. */
2564
0
      partexpr = (Expr *) copyObject(lfirst(lc));
2565
0
      ChangeVarNodes((Node *) partexpr, 1, varno, 0);
2566
0
      lc = lnext(partkey->partexprs, lc);
2567
0
    }
2568
2569
    /* Base relations have a single expression per key. */
2570
0
    partexprs[cnt] = list_make1(partexpr);
2571
0
  }
2572
2573
0
  rel->partexprs = partexprs;
2574
2575
  /*
2576
   * A base relation does not have nullable partition key expressions, since
2577
   * no outer join is involved.  We still allocate an array of empty
2578
   * expression lists to keep partition key expression handling code simple.
2579
   * See build_joinrel_partition_info() and match_expr_to_partition_keys().
2580
   */
2581
0
  rel->nullable_partexprs = (List **) palloc0(sizeof(List *) * partnatts);
2582
0
}
2583
2584
/*
2585
 * set_baserel_partition_constraint
2586
 *
2587
 * Builds the partition constraint for the given base relation and sets it
2588
 * in the given RelOptInfo.  All Var nodes are restamped with the relid of the
2589
 * given relation.
2590
 */
2591
static void
2592
set_baserel_partition_constraint(Relation relation, RelOptInfo *rel)
2593
0
{
2594
0
  List     *partconstr;
2595
2596
0
  if (rel->partition_qual) /* already done */
2597
0
    return;
2598
2599
  /*
2600
   * Run the partition quals through const-simplification similar to check
2601
   * constraints.  We skip canonicalize_qual, though, because partition
2602
   * quals should be in canonical form already; also, since the qual is in
2603
   * implicit-AND format, we'd have to explicitly convert it to explicit-AND
2604
   * format and back again.
2605
   */
2606
0
  partconstr = RelationGetPartitionQual(relation);
2607
0
  if (partconstr)
2608
0
  {
2609
0
    partconstr = (List *) expression_planner((Expr *) partconstr);
2610
0
    if (rel->relid != 1)
2611
0
      ChangeVarNodes((Node *) partconstr, 1, rel->relid, 0);
2612
0
    rel->partition_qual = partconstr;
2613
0
  }
2614
0
}