Coverage Report

Created: 2026-09-28 06:55

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