Coverage Report

Created: 2026-10-16 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/optimizer/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     *idxNonVarExprs;
944
0
    ListCell   *idxExprItem;
945
0
    List     *predExprs;
946
0
    AttrNumber  natt;
947
0
    bool    match;
948
949
    /*
950
     * Extract info from the relation descriptor for the index.
951
     *
952
     * Let executor complain about !indimmediate case directly, because
953
     * enforcement needs to occur there anyway when an inference clause is
954
     * omitted.
955
     */
956
0
    idxForm = idxRel->rd_index;
957
958
    /*
959
     * Ignore indexes that aren't indisready, because we cannot trust
960
     * their catalog structure yet.  However, if any indexes are marked
961
     * indisready but not yet indisvalid, we still consider them, because
962
     * they might turn valid while we're running.  Doing it this way
963
     * allows a concurrent transaction with a slightly later catalog
964
     * snapshot infer the same set of indexes, which is critical to
965
     * prevent spurious 'duplicate key' errors.
966
     *
967
     * However, another critical aspect is that a unique index that isn't
968
     * yet marked indisvalid=true might not be complete yet, meaning it
969
     * wouldn't detect possible duplicate rows.  In order to prevent false
970
     * negatives, we require that we include in the set of inferred
971
     * indexes at least one index that is marked valid.
972
     */
973
0
    if (!idxForm->indisready)
974
0
      continue;
975
976
    /*
977
     * Ignore invalid indexes for partitioned tables.  It's possible that
978
     * some partitions don't have the index (yet), and then we would not
979
     * find a match during ExecInitPartitionInfo.
980
     */
981
0
    if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
982
0
      !idxForm->indisvalid)
983
0
      continue;
984
985
    /*
986
     * Note that we do not perform a check against indcheckxmin (like e.g.
987
     * get_relation_info()) here to eliminate candidates, because
988
     * uniqueness checking only cares about the most recently committed
989
     * tuple versions.
990
     */
991
992
    /*
993
     * Look for match for "ON constraint_name" variant, which may not be a
994
     * unique constraint.  This can only be a constraint name.
995
     */
996
0
    if (indexOidFromConstraint == idxForm->indexrelid)
997
0
    {
998
      /*
999
       * ON CONFLICT DO UPDATE and ON CONFLICT DO SELECT are not
1000
       * supported with exclusion constraints.
1001
       */
1002
0
      if (idxForm->indisexclusion &&
1003
0
        (onconflict->action == ONCONFLICT_UPDATE ||
1004
0
         onconflict->action == ONCONFLICT_SELECT))
1005
0
        ereport(ERROR,
1006
0
            errcode(ERRCODE_WRONG_OBJECT_TYPE),
1007
        /* translator: %s is an ON CONFLICT clause */
1008
0
            errmsg("%s not supported with exclusion constraints",
1009
0
                 onconflict->action == ONCONFLICT_UPDATE ?
1010
0
                 "ON CONFLICT DO UPDATE" : "ON CONFLICT DO SELECT"));
1011
1012
      /* Consider this one a match already */
1013
0
      results = lappend_oid(results, idxForm->indexrelid);
1014
0
      foundValid |= idxForm->indisvalid;
1015
0
      continue;
1016
0
    }
1017
0
    else if (indexOidFromConstraint != InvalidOid)
1018
0
    {
1019
      /*
1020
       * When a constraint is named, the only other index that may
1021
       * arbitrate is an exact structural equivalents of its index,
1022
       * which exists while REINDEX CONCURRENTLY is processing it.
1023
       */
1024
0
      if (IsIndexCompatibleAsArbiter(indexRelFromConstraint, idxRel))
1025
0
      {
1026
0
        results = lappend_oid(results, idxForm->indexrelid);
1027
0
        foundValid |= idxForm->indisvalid;
1028
0
      }
1029
0
      continue;
1030
0
    }
1031
0
    else
1032
0
    {
1033
      /*
1034
       * Only considering conventional inference at this point (not
1035
       * named constraints), so index under consideration can be
1036
       * immediately skipped if it's not unique.
1037
       */
1038
0
      if (!idxForm->indisunique)
1039
0
        continue;
1040
0
    }
1041
1042
    /*
1043
     * So-called unique constraints with WITHOUT OVERLAPS are really
1044
     * exclusion constraints, so skip those too.
1045
     */
1046
0
    if (idxForm->indisexclusion)
1047
0
      continue;
1048
1049
    /* Simplify the index expressions the same way arbiterElems were */
1050
0
    idxExprs = RelationGetIndexExpressions(idxRel);
1051
0
    if (idxExprs)
1052
0
    {
1053
0
      if (varno != 1)
1054
0
        ChangeVarNodes((Node *) idxExprs, 1, varno, 0);
1055
1056
0
      idxExprs = (List *) eval_const_expressions(root, (Node *) idxExprs);
1057
0
    }
1058
1059
    /*
1060
     * Build BMS representation of plain index attrs.  An index expression
1061
     * that was simplified to a plain Var is treated as a plain attr too,
1062
     * to match how arbiterElems are classified above.
1063
     */
1064
0
    indexedAttrs = NULL;
1065
0
    idxNonVarExprs = NIL;
1066
0
    idxExprItem = list_head(idxExprs);
1067
0
    for (natt = 0; natt < idxForm->indnkeyatts; natt++)
1068
0
    {
1069
0
      int     attno = idxRel->rd_index->indkey.values[natt];
1070
1071
0
      if (attno == 0)
1072
0
      {
1073
0
        Node     *idxExpr;
1074
1075
0
        if (idxExprItem == NULL)
1076
0
          elog(ERROR, "wrong number of index expressions");
1077
0
        idxExpr = (Node *) lfirst(idxExprItem);
1078
0
        idxExprItem = lnext(idxExprs, idxExprItem);
1079
1080
0
        if (!IsA(idxExpr, Var) || ((Var *) idxExpr)->varattno == 0)
1081
0
        {
1082
0
          idxNonVarExprs = lappend(idxNonVarExprs, idxExpr);
1083
0
          continue;
1084
0
        }
1085
1086
0
        attno = ((Var *) idxExpr)->varattno;
1087
0
      }
1088
1089
0
      indexedAttrs = bms_add_member(indexedAttrs,
1090
0
                      attno - FirstLowInvalidHeapAttributeNumber);
1091
0
    }
1092
1093
    /* Plain attributes (if any) must match */
1094
0
    if (!bms_equal(indexedAttrs, inferAttrs))
1095
0
      continue;
1096
1097
    /* Check the arbiterElems against this index. */
1098
0
    match = true;
1099
0
    foreach_ptr(InferenceElem, elem, onconflict->arbiterElems)
1100
0
    {
1101
      /*
1102
       * Ensure that collation/opclass aspects of inference expression
1103
       * element match.  Even though this loop is primarily concerned
1104
       * with matching expressions, it is a convenient point to check
1105
       * this for both expressions and ordinary (non-expression)
1106
       * attributes appearing as inference elements.
1107
       */
1108
0
      if (!infer_collation_opclass_match(elem, idxRel, idxExprs))
1109
0
      {
1110
0
        match = false;
1111
0
        break;
1112
0
      }
1113
1114
      /*
1115
       * Plain Vars don't factor into count of expression elements, and
1116
       * the question of whether or not they satisfy the index
1117
       * definition has already been considered (they must).
1118
       */
1119
0
      if (IsA(elem->expr, Var))
1120
0
        continue;
1121
1122
      /*
1123
       * Might as well avoid redundant check in the rare cases where
1124
       * infer_collation_opclass_match() is required to do real work.
1125
       * Otherwise, check that element expression appears in cataloged
1126
       * index definition.
1127
       */
1128
0
      if (elem->infercollid != InvalidOid ||
1129
0
        elem->inferopclass != InvalidOid ||
1130
0
        list_member(idxExprs, elem->expr))
1131
0
        continue;
1132
1133
0
      match = false;
1134
0
      break;
1135
0
    }
1136
0
    if (!match)
1137
0
      continue;
1138
1139
    /*
1140
     * Now that all inference elements were matched, ensure that the
1141
     * expression elements from inference clause are not missing any
1142
     * cataloged expressions.  This does the right thing when unique
1143
     * indexes redundantly repeat the same attribute, or if attributes
1144
     * redundantly appear multiple times within an inference clause.
1145
     */
1146
0
    if (list_difference(idxNonVarExprs, inferElems) != NIL)
1147
0
      continue;
1148
1149
0
    predExprs = RelationGetIndexPredicate(idxRel);
1150
0
    if (predExprs)
1151
0
    {
1152
0
      if (varno != 1)
1153
0
        ChangeVarNodes((Node *) predExprs, 1, varno, 0);
1154
1155
0
      predExprs = (List *)
1156
0
        eval_const_expressions(root,
1157
0
                     (Node *) make_ands_explicit(predExprs));
1158
0
      predExprs = make_ands_implicit((Expr *) predExprs);
1159
0
    }
1160
1161
    /*
1162
     * If it's a partial index, its predicate must be implied by the ON
1163
     * CONFLICT's WHERE clause.
1164
     */
1165
0
    if (!predicate_implied_by(predExprs,
1166
0
                  (List *) onconflict->arbiterWhere, false))
1167
0
      continue;
1168
1169
    /* All good -- consider this index a match */
1170
0
    results = lappend_oid(results, idxForm->indexrelid);
1171
0
    foundValid |= idxForm->indisvalid;
1172
0
  }
1173
1174
  /* Close all indexes */
1175
0
  foreach_ptr(RelationData, idxRel, indexRelList)
1176
0
  {
1177
0
    index_close(idxRel, NoLock);
1178
0
  }
1179
1180
0
  list_free(indexList);
1181
0
  list_free(indexRelList);
1182
0
  table_close(relation, NoLock);
1183
1184
  /* We require at least one indisvalid index */
1185
0
  if (results == NIL || !foundValid)
1186
0
    ereport(ERROR,
1187
0
        (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1188
0
         errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
1189
1190
0
  return results;
1191
0
}
1192
1193
/*
1194
 * infer_collation_opclass_match - ensure infer element opclass/collation match
1195
 *
1196
 * Given unique index inference element from inference specification, if
1197
 * collation was specified, or if opclass was specified, verify that there is
1198
 * at least one matching indexed attribute (occasionally, there may be more).
1199
 * Skip this in the common case where inference specification does not include
1200
 * collation or opclass (instead matching everything, regardless of cataloged
1201
 * collation/opclass of indexed attribute).
1202
 *
1203
 * At least historically, Postgres has not offered collations or opclasses
1204
 * with alternative-to-default notions of equality, so these additional
1205
 * criteria should only be required infrequently.  XXX That is no longer
1206
 * true: nondeterministic collations, supported since PostgreSQL 12, do
1207
 * equate values that the default notion of equality keeps distinct.
1208
 *
1209
 * Don't give up immediately when an inference element matches some attribute
1210
 * cataloged as indexed but not matching additional opclass/collation
1211
 * criteria.  This is done so that the implementation is as forgiving as
1212
 * possible of redundancy within cataloged index attributes (or, less
1213
 * usefully, within inference specification elements).  If collations actually
1214
 * differ between apparently redundantly indexed attributes (redundant within
1215
 * or across indexes), then there really is no redundancy as such.
1216
 *
1217
 * Note that if an inference element specifies an opclass and a collation at
1218
 * once, both must match in at least one particular attribute within index
1219
 * catalog definition in order for that inference element to be considered
1220
 * inferred/satisfied.
1221
 */
1222
static bool
1223
infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
1224
                List *idxExprs)
1225
0
{
1226
0
  AttrNumber  natt;
1227
0
  Oid     inferopfamily = InvalidOid; /* OID of opclass opfamily */
1228
0
  Oid     inferopcinputtype = InvalidOid; /* OID of opclass input type */
1229
0
  int     nplain = 0;   /* # plain attrs observed */
1230
1231
  /*
1232
   * If inference specification element lacks collation/opclass, then no
1233
   * need to check for exact match.
1234
   */
1235
0
  if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
1236
0
    return true;
1237
1238
  /*
1239
   * Lookup opfamily and input type, for matching indexes
1240
   */
1241
0
  if (elem->inferopclass)
1242
0
  {
1243
0
    inferopfamily = get_opclass_family(elem->inferopclass);
1244
0
    inferopcinputtype = get_opclass_input_type(elem->inferopclass);
1245
0
  }
1246
1247
0
  for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
1248
0
  {
1249
0
    Oid     opfamily = idxRel->rd_opfamily[natt - 1];
1250
0
    Oid     opcinputtype = idxRel->rd_opcintype[natt - 1];
1251
0
    Oid     collation = idxRel->rd_indcollation[natt - 1];
1252
0
    int     attno = idxRel->rd_index->indkey.values[natt - 1];
1253
1254
0
    if (attno != 0)
1255
0
      nplain++;
1256
1257
0
    if (elem->inferopclass != InvalidOid &&
1258
0
      (inferopfamily != opfamily || inferopcinputtype != opcinputtype))
1259
0
    {
1260
      /* Attribute needed to match opclass, but didn't */
1261
0
      continue;
1262
0
    }
1263
1264
0
    if (elem->infercollid != InvalidOid &&
1265
0
      elem->infercollid != collation)
1266
0
    {
1267
      /* Attribute needed to match collation, but didn't */
1268
0
      continue;
1269
0
    }
1270
1271
    /* If one matching index att found, good enough -- return true */
1272
0
    if (attno != 0)
1273
0
    {
1274
0
      if (IsA(elem->expr, Var) &&
1275
0
        ((Var *) elem->expr)->varattno == attno)
1276
0
        return true;
1277
0
    }
1278
0
    else
1279
0
    {
1280
0
      Node     *nattExpr = list_nth(idxExprs, (natt - 1) - nplain);
1281
1282
      /*
1283
       * Note that unlike routines like match_index_to_operand() we
1284
       * don't need to care about RelabelType.  Neither the index
1285
       * definition nor the inference clause should contain them.
1286
       */
1287
0
      if (equal(elem->expr, nattExpr))
1288
0
        return true;
1289
0
    }
1290
0
  }
1291
1292
0
  return false;
1293
0
}
1294
1295
/*
1296
 * estimate_rel_size - estimate # pages and # tuples in a table or index
1297
 *
1298
 * We also estimate the fraction of the pages that are marked all-visible in
1299
 * the visibility map, for use in estimation of index-only scans.
1300
 *
1301
 * If attr_widths isn't NULL, it points to the zero-index entry of the
1302
 * relation's attr_widths[] cache; we fill this in if we have need to compute
1303
 * the attribute widths for estimation purposes.
1304
 */
1305
void
1306
estimate_rel_size(Relation rel, int32 *attr_widths,
1307
          BlockNumber *pages, double *tuples, double *allvisfrac)
1308
0
{
1309
0
  BlockNumber curpages;
1310
0
  BlockNumber relpages;
1311
0
  double    reltuples;
1312
0
  BlockNumber relallvisible;
1313
0
  double    density;
1314
1315
0
  if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
1316
0
  {
1317
0
    table_relation_estimate_size(rel, attr_widths, pages, tuples,
1318
0
                   allvisfrac);
1319
0
  }
1320
0
  else if (rel->rd_rel->relkind == RELKIND_INDEX)
1321
0
  {
1322
    /*
1323
     * XXX: It'd probably be good to move this into a callback, individual
1324
     * index types e.g. know if they have a metapage.
1325
     */
1326
1327
    /* it has storage, ok to call the smgr */
1328
0
    curpages = RelationGetNumberOfBlocks(rel);
1329
1330
    /* report estimated # pages */
1331
0
    *pages = curpages;
1332
    /* quick exit if rel is clearly empty */
1333
0
    if (curpages == 0)
1334
0
    {
1335
0
      *tuples = 0;
1336
0
      *allvisfrac = 0;
1337
0
      return;
1338
0
    }
1339
1340
    /* coerce values in pg_class to more desirable types */
1341
0
    relpages = (BlockNumber) rel->rd_rel->relpages;
1342
0
    reltuples = (double) rel->rd_rel->reltuples;
1343
0
    relallvisible = (BlockNumber) rel->rd_rel->relallvisible;
1344
1345
    /*
1346
     * Discount the metapage while estimating the number of tuples. This
1347
     * is a kluge because it assumes more than it ought to about index
1348
     * structure.  Currently it's OK for btree, hash, and GIN indexes but
1349
     * suspect for GiST indexes.
1350
     */
1351
0
    if (relpages > 0)
1352
0
    {
1353
0
      curpages--;
1354
0
      relpages--;
1355
0
    }
1356
1357
    /* estimate number of tuples from previous tuple density */
1358
0
    if (reltuples >= 0 && relpages > 0)
1359
0
      density = reltuples / (double) relpages;
1360
0
    else
1361
0
    {
1362
      /*
1363
       * If we have no data because the relation was never vacuumed,
1364
       * estimate tuple width from attribute datatypes.  We assume here
1365
       * that the pages are completely full, which is OK for tables
1366
       * (since they've presumably not been VACUUMed yet) but is
1367
       * probably an overestimate for indexes.  Fortunately
1368
       * get_relation_info() can clamp the overestimate to the parent
1369
       * table's size.
1370
       *
1371
       * Note: this code intentionally disregards alignment
1372
       * considerations, because (a) that would be gilding the lily
1373
       * considering how crude the estimate is, and (b) it creates
1374
       * platform dependencies in the default plans which are kind of a
1375
       * headache for regression testing.
1376
       *
1377
       * XXX: Should this logic be more index specific?
1378
       */
1379
0
      int32   tuple_width;
1380
1381
0
      tuple_width = get_rel_data_width(rel, attr_widths);
1382
0
      tuple_width += MAXALIGN(SizeofHeapTupleHeader);
1383
0
      tuple_width += sizeof(ItemIdData);
1384
      /* note: integer division is intentional here */
1385
0
      density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;
1386
0
    }
1387
0
    *tuples = rint(density * (double) curpages);
1388
1389
    /*
1390
     * We use relallvisible as-is, rather than scaling it up like we do
1391
     * for the pages and tuples counts, on the theory that any pages added
1392
     * since the last VACUUM are most likely not marked all-visible.  But
1393
     * costsize.c wants it converted to a fraction.
1394
     */
1395
0
    if (relallvisible == 0 || curpages <= 0)
1396
0
      *allvisfrac = 0;
1397
0
    else if ((double) relallvisible >= curpages)
1398
0
      *allvisfrac = 1;
1399
0
    else
1400
0
      *allvisfrac = (double) relallvisible / curpages;
1401
0
  }
1402
0
  else
1403
0
  {
1404
    /*
1405
     * Just use whatever's in pg_class.  This covers foreign tables,
1406
     * sequences, and also relkinds without storage (shouldn't get here?);
1407
     * see initializations in AddNewRelationTuple().  Note that FDW must
1408
     * cope if reltuples is -1!
1409
     */
1410
0
    *pages = rel->rd_rel->relpages;
1411
0
    *tuples = rel->rd_rel->reltuples;
1412
0
    *allvisfrac = 0;
1413
0
  }
1414
0
}
1415
1416
1417
/*
1418
 * get_rel_data_width
1419
 *
1420
 * Estimate the average width of (the data part of) the relation's tuples.
1421
 *
1422
 * If attr_widths isn't NULL, it points to the zero-index entry of the
1423
 * relation's attr_widths[] cache; use and update that cache as appropriate.
1424
 *
1425
 * Currently we ignore dropped columns.  Ideally those should be included
1426
 * in the result, but we haven't got any way to get info about them; and
1427
 * since they might be mostly NULLs, treating them as zero-width is not
1428
 * necessarily the wrong thing anyway.
1429
 */
1430
int32
1431
get_rel_data_width(Relation rel, int32 *attr_widths)
1432
0
{
1433
0
  int64   tuple_width = 0;
1434
0
  int     i;
1435
1436
0
  for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++)
1437
0
  {
1438
0
    Form_pg_attribute att = TupleDescAttr(rel->rd_att, i - 1);
1439
0
    int32   item_width;
1440
1441
0
    if (att->attisdropped)
1442
0
      continue;
1443
1444
    /* use previously cached data, if any */
1445
0
    if (attr_widths != NULL && attr_widths[i] > 0)
1446
0
    {
1447
0
      tuple_width += attr_widths[i];
1448
0
      continue;
1449
0
    }
1450
1451
    /* This should match set_rel_width() in costsize.c */
1452
0
    item_width = get_attavgwidth(RelationGetRelid(rel), i);
1453
0
    if (item_width <= 0)
1454
0
    {
1455
0
      item_width = get_typavgwidth(att->atttypid, att->atttypmod);
1456
0
      Assert(item_width > 0);
1457
0
    }
1458
0
    if (attr_widths != NULL)
1459
0
      attr_widths[i] = item_width;
1460
0
    tuple_width += item_width;
1461
0
  }
1462
1463
0
  return clamp_width_est(tuple_width);
1464
0
}
1465
1466
/*
1467
 * get_relation_data_width
1468
 *
1469
 * External API for get_rel_data_width: same behavior except we have to
1470
 * open the relcache entry.
1471
 */
1472
int32
1473
get_relation_data_width(Oid relid, int32 *attr_widths)
1474
0
{
1475
0
  int32   result;
1476
0
  Relation  relation;
1477
1478
  /* As above, assume relation is already locked */
1479
0
  relation = table_open(relid, NoLock);
1480
1481
0
  result = get_rel_data_width(relation, attr_widths);
1482
1483
0
  table_close(relation, NoLock);
1484
1485
0
  return result;
1486
0
}
1487
1488
1489
/*
1490
 * get_relation_constraints
1491
 *
1492
 * Retrieve the applicable constraint expressions of the given relation.
1493
 * Only constraints that have been validated are considered.
1494
 *
1495
 * Returns a List (possibly empty) of constraint expressions.  Each one
1496
 * has been canonicalized, and its Vars are changed to have the varno
1497
 * indicated by rel->relid.  This allows the expressions to be easily
1498
 * compared to expressions taken from WHERE.
1499
 *
1500
 * If include_noinherit is true, it's okay to include constraints that
1501
 * are marked NO INHERIT.
1502
 *
1503
 * If include_notnull is true, "col IS NOT NULL" expressions are generated
1504
 * and added to the result for each column that's marked attnotnull.
1505
 *
1506
 * If include_partition is true, and the relation is a partition,
1507
 * also include the partitioning constraints.
1508
 *
1509
 * Note: at present this is invoked at most once per relation per planner
1510
 * run, and in many cases it won't be invoked at all, so there seems no
1511
 * point in caching the data in RelOptInfo.
1512
 */
1513
static List *
1514
get_relation_constraints(PlannerInfo *root,
1515
             Oid relationObjectId, RelOptInfo *rel,
1516
             bool include_noinherit,
1517
             bool include_notnull,
1518
             bool include_partition)
1519
0
{
1520
0
  List     *result = NIL;
1521
0
  Index   varno = rel->relid;
1522
0
  Relation  relation;
1523
0
  TupleConstr *constr;
1524
1525
  /*
1526
   * We assume the relation has already been safely locked.
1527
   */
1528
0
  relation = table_open(relationObjectId, NoLock);
1529
1530
0
  constr = relation->rd_att->constr;
1531
0
  if (constr != NULL)
1532
0
  {
1533
0
    int     num_check = constr->num_check;
1534
0
    int     i;
1535
1536
0
    for (i = 0; i < num_check; i++)
1537
0
    {
1538
0
      Node     *cexpr;
1539
1540
      /*
1541
       * If this constraint hasn't been fully validated yet, we must
1542
       * ignore it here.
1543
       */
1544
0
      if (!constr->check[i].ccvalid)
1545
0
        continue;
1546
1547
      /*
1548
       * NOT ENFORCED constraints are always marked as invalid, which
1549
       * should have been ignored.
1550
       */
1551
0
      Assert(constr->check[i].ccenforced);
1552
1553
      /*
1554
       * Also ignore if NO INHERIT and we weren't told that that's safe.
1555
       */
1556
0
      if (constr->check[i].ccnoinherit && !include_noinherit)
1557
0
        continue;
1558
1559
0
      cexpr = stringToNode(constr->check[i].ccbin);
1560
1561
      /*
1562
       * Fix Vars to have the desired varno.  This must be done before
1563
       * const-simplification because eval_const_expressions reduces
1564
       * NullTest for Vars based on varno.
1565
       */
1566
0
      if (varno != 1)
1567
0
        ChangeVarNodes(cexpr, 1, varno, 0);
1568
1569
      /*
1570
       * Run each expression through const-simplification and
1571
       * canonicalization.  This is not just an optimization, but is
1572
       * necessary, because we will be comparing it to
1573
       * similarly-processed qual clauses, and may fail to detect valid
1574
       * matches without this.  This must match the processing done to
1575
       * qual clauses in preprocess_expression()!  (We can skip the
1576
       * stuff involving subqueries, however, since we don't allow any
1577
       * in check constraints.)
1578
       */
1579
0
      cexpr = eval_const_expressions(root, cexpr);
1580
1581
0
      cexpr = (Node *) canonicalize_qual((Expr *) cexpr, true);
1582
1583
      /*
1584
       * Finally, convert to implicit-AND format (that is, a List) and
1585
       * append the resulting item(s) to our output list.
1586
       */
1587
0
      result = list_concat(result,
1588
0
                 make_ands_implicit((Expr *) cexpr));
1589
0
    }
1590
1591
    /* Add NOT NULL constraints in expression form, if requested */
1592
0
    if (include_notnull && constr->has_not_null)
1593
0
    {
1594
0
      int     natts = relation->rd_att->natts;
1595
1596
0
      for (i = 1; i <= natts; i++)
1597
0
      {
1598
0
        CompactAttribute *att = TupleDescCompactAttr(relation->rd_att, i - 1);
1599
1600
0
        if (att->attnullability == ATTNULLABLE_VALID && !att->attisdropped)
1601
0
        {
1602
0
          Form_pg_attribute wholeatt = TupleDescAttr(relation->rd_att, i - 1);
1603
0
          NullTest   *ntest = makeNode(NullTest);
1604
1605
0
          ntest->arg = (Expr *) makeVar(varno,
1606
0
                          i,
1607
0
                          wholeatt->atttypid,
1608
0
                          wholeatt->atttypmod,
1609
0
                          wholeatt->attcollation,
1610
0
                          0);
1611
0
          ntest->nulltesttype = IS_NOT_NULL;
1612
1613
          /*
1614
           * argisrow=false is correct even for a composite column,
1615
           * because attnotnull does not represent a SQL-spec IS NOT
1616
           * NULL test in such a case, just IS DISTINCT FROM NULL.
1617
           */
1618
0
          ntest->argisrow = false;
1619
0
          ntest->location = -1;
1620
0
          result = lappend(result, ntest);
1621
0
        }
1622
0
      }
1623
0
    }
1624
0
  }
1625
1626
  /*
1627
   * Add partitioning constraints, if requested.
1628
   */
1629
0
  if (include_partition && relation->rd_rel->relispartition)
1630
0
  {
1631
    /* make sure rel->partition_qual is set */
1632
0
    set_baserel_partition_constraint(relation, rel);
1633
0
    result = list_concat(result, rel->partition_qual);
1634
0
  }
1635
1636
  /*
1637
   * Expand virtual generated columns in the constraint expressions.
1638
   */
1639
0
  if (result)
1640
0
    result = (List *) expand_generated_columns_in_expr((Node *) result,
1641
0
                               relation,
1642
0
                               varno);
1643
1644
0
  table_close(relation, NoLock);
1645
1646
0
  return result;
1647
0
}
1648
1649
/*
1650
 * Try loading data for the statistics object.
1651
 *
1652
 * We don't know if the data (specified by statOid and inh value) exist.
1653
 * The result is stored in stainfos list.
1654
 */
1655
static void
1656
get_relation_statistics_worker(List **stainfos, RelOptInfo *rel,
1657
                 Oid statOid, bool inh,
1658
                 Bitmapset *keys, List *exprs)
1659
0
{
1660
0
  Form_pg_statistic_ext_data dataForm;
1661
0
  HeapTuple dtup;
1662
1663
0
  dtup = SearchSysCache2(STATEXTDATASTXOID,
1664
0
               ObjectIdGetDatum(statOid), BoolGetDatum(inh));
1665
0
  if (!HeapTupleIsValid(dtup))
1666
0
    return;
1667
1668
0
  dataForm = (Form_pg_statistic_ext_data) GETSTRUCT(dtup);
1669
1670
  /* add one StatisticExtInfo for each kind built */
1671
0
  if (statext_is_kind_built(dtup, STATS_EXT_NDISTINCT))
1672
0
  {
1673
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1674
1675
0
    info->statOid = statOid;
1676
0
    info->inherit = dataForm->stxdinherit;
1677
0
    info->rel = rel;
1678
0
    info->kind = STATS_EXT_NDISTINCT;
1679
0
    info->keys = bms_copy(keys);
1680
0
    info->exprs = exprs;
1681
1682
0
    *stainfos = lappend(*stainfos, info);
1683
0
  }
1684
1685
0
  if (statext_is_kind_built(dtup, STATS_EXT_DEPENDENCIES))
1686
0
  {
1687
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1688
1689
0
    info->statOid = statOid;
1690
0
    info->inherit = dataForm->stxdinherit;
1691
0
    info->rel = rel;
1692
0
    info->kind = STATS_EXT_DEPENDENCIES;
1693
0
    info->keys = bms_copy(keys);
1694
0
    info->exprs = exprs;
1695
1696
0
    *stainfos = lappend(*stainfos, info);
1697
0
  }
1698
1699
0
  if (statext_is_kind_built(dtup, STATS_EXT_MCV))
1700
0
  {
1701
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1702
1703
0
    info->statOid = statOid;
1704
0
    info->inherit = dataForm->stxdinherit;
1705
0
    info->rel = rel;
1706
0
    info->kind = STATS_EXT_MCV;
1707
0
    info->keys = bms_copy(keys);
1708
0
    info->exprs = exprs;
1709
1710
0
    *stainfos = lappend(*stainfos, info);
1711
0
  }
1712
1713
0
  if (statext_is_kind_built(dtup, STATS_EXT_EXPRESSIONS))
1714
0
  {
1715
0
    StatisticExtInfo *info = makeNode(StatisticExtInfo);
1716
1717
0
    info->statOid = statOid;
1718
0
    info->inherit = dataForm->stxdinherit;
1719
0
    info->rel = rel;
1720
0
    info->kind = STATS_EXT_EXPRESSIONS;
1721
0
    info->keys = bms_copy(keys);
1722
0
    info->exprs = exprs;
1723
1724
0
    *stainfos = lappend(*stainfos, info);
1725
0
  }
1726
1727
0
  ReleaseSysCache(dtup);
1728
0
}
1729
1730
/*
1731
 * get_relation_statistics
1732
 *    Retrieve extended statistics defined on the table.
1733
 *
1734
 * Returns a List (possibly empty) of StatisticExtInfo objects describing
1735
 * the statistics.  Note that this doesn't load the actual statistics data,
1736
 * just the identifying metadata.  Only stats actually built are considered.
1737
 */
1738
static List *
1739
get_relation_statistics(PlannerInfo *root, RelOptInfo *rel,
1740
            Relation relation)
1741
0
{
1742
0
  Index   varno = rel->relid;
1743
0
  List     *statoidlist;
1744
0
  List     *stainfos = NIL;
1745
0
  ListCell   *l;
1746
1747
0
  statoidlist = RelationGetStatExtList(relation);
1748
1749
0
  foreach(l, statoidlist)
1750
0
  {
1751
0
    Oid     statOid = lfirst_oid(l);
1752
0
    Form_pg_statistic_ext staForm;
1753
0
    HeapTuple htup;
1754
0
    Bitmapset  *keys = NULL;
1755
0
    List     *exprs = NIL;
1756
0
    int     i;
1757
1758
0
    htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statOid));
1759
0
    if (!HeapTupleIsValid(htup))
1760
0
      elog(ERROR, "cache lookup failed for statistics object %u", statOid);
1761
0
    staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
1762
1763
    /*
1764
     * First, build the array of columns covered.  This is ultimately
1765
     * wasted if no stats within the object have actually been built, but
1766
     * it doesn't seem worth troubling over that case.
1767
     */
1768
0
    for (i = 0; i < staForm->stxkeys.dim1; i++)
1769
0
      keys = bms_add_member(keys, staForm->stxkeys.values[i]);
1770
1771
    /*
1772
     * Preprocess expressions (if any). We read the expressions, fix the
1773
     * varnos, and run them through eval_const_expressions.
1774
     *
1775
     * XXX We don't know yet if there are any data for this stats object,
1776
     * with either stxdinherit value. But it's reasonable to assume there
1777
     * is at least one of those, possibly both. So it's better to process
1778
     * keys and expressions here.
1779
     */
1780
0
    {
1781
0
      bool    isnull;
1782
0
      Datum   datum;
1783
1784
      /* decode expression (if any) */
1785
0
      datum = SysCacheGetAttr(STATEXTOID, htup,
1786
0
                  Anum_pg_statistic_ext_stxexprs, &isnull);
1787
1788
0
      if (!isnull)
1789
0
      {
1790
0
        char     *exprsString;
1791
1792
0
        exprsString = TextDatumGetCString(datum);
1793
0
        exprs = (List *) stringToNode(exprsString);
1794
0
        pfree(exprsString);
1795
1796
        /* Expand virtual generated columns in the expressions */
1797
0
        exprs = (List *) expand_generated_columns_in_expr((Node *) exprs, relation, 1);
1798
1799
        /*
1800
         * Modify the copies we obtain from the relcache to have the
1801
         * correct varno for the parent relation, so that they match
1802
         * up correctly against qual clauses.
1803
         *
1804
         * This must be done before const-simplification because
1805
         * eval_const_expressions reduces NullTest for Vars based on
1806
         * varno.
1807
         */
1808
0
        if (varno != 1)
1809
0
          ChangeVarNodes((Node *) exprs, 1, varno, 0);
1810
1811
        /*
1812
         * Run the expressions through eval_const_expressions. This is
1813
         * not just an optimization, but is necessary, because the
1814
         * planner will be comparing them to similarly-processed qual
1815
         * clauses, and may fail to detect valid matches without this.
1816
         * We must not use canonicalize_qual, however, since these
1817
         * aren't qual expressions.
1818
         */
1819
0
        exprs = (List *) eval_const_expressions(root, (Node *) exprs);
1820
1821
        /* May as well fix opfuncids too */
1822
0
        fix_opfuncids((Node *) exprs);
1823
0
      }
1824
0
    }
1825
1826
    /* extract statistics for possible values of stxdinherit flag */
1827
1828
0
    get_relation_statistics_worker(&stainfos, rel, statOid, true, keys, exprs);
1829
1830
0
    get_relation_statistics_worker(&stainfos, rel, statOid, false, keys, exprs);
1831
1832
0
    ReleaseSysCache(htup);
1833
0
    bms_free(keys);
1834
0
  }
1835
1836
0
  list_free(statoidlist);
1837
1838
0
  return stainfos;
1839
0
}
1840
1841
/*
1842
 * relation_excluded_by_constraints
1843
 *
1844
 * Detect whether the relation need not be scanned because it has either
1845
 * self-inconsistent restrictions, or restrictions inconsistent with the
1846
 * relation's applicable constraints.
1847
 *
1848
 * Note: this examines only rel->relid, rel->reloptkind, and
1849
 * rel->baserestrictinfo; therefore it can be called before filling in
1850
 * other fields of the RelOptInfo.
1851
 */
1852
bool
1853
relation_excluded_by_constraints(PlannerInfo *root,
1854
                 RelOptInfo *rel, RangeTblEntry *rte)
1855
0
{
1856
0
  bool    include_noinherit;
1857
0
  bool    include_notnull;
1858
0
  bool    include_partition = false;
1859
0
  List     *safe_restrictions;
1860
0
  List     *constraint_pred;
1861
0
  List     *safe_constraints;
1862
0
  ListCell   *lc;
1863
1864
  /* As of now, constraint exclusion works only with simple relations. */
1865
0
  Assert(IS_SIMPLE_REL(rel));
1866
1867
  /*
1868
   * If there are no base restriction clauses, we have no hope of proving
1869
   * anything below, so fall out quickly.
1870
   */
1871
0
  if (rel->baserestrictinfo == NIL)
1872
0
    return false;
1873
1874
  /*
1875
   * Regardless of the setting of constraint_exclusion, detect
1876
   * constant-FALSE-or-NULL restriction clauses.  Although const-folding
1877
   * will reduce "anything AND FALSE" to just "FALSE", the baserestrictinfo
1878
   * list can still have other members besides the FALSE constant, due to
1879
   * qual pushdown and other mechanisms; so check them all.  This doesn't
1880
   * fire very often, but it seems cheap enough to be worth doing anyway.
1881
   * (Without this, we'd miss some optimizations that 9.5 and earlier found
1882
   * via much more roundabout methods.)
1883
   */
1884
0
  foreach(lc, rel->baserestrictinfo)
1885
0
  {
1886
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1887
0
    Expr     *clause = rinfo->clause;
1888
1889
0
    if (clause && IsA(clause, Const) &&
1890
0
      (((Const *) clause)->constisnull ||
1891
0
       !DatumGetBool(((Const *) clause)->constvalue)))
1892
0
      return true;
1893
0
  }
1894
1895
  /*
1896
   * Skip further tests, depending on constraint_exclusion.
1897
   */
1898
0
  switch (constraint_exclusion)
1899
0
  {
1900
0
    case CONSTRAINT_EXCLUSION_OFF:
1901
      /* In 'off' mode, never make any further tests */
1902
0
      return false;
1903
1904
0
    case CONSTRAINT_EXCLUSION_PARTITION:
1905
1906
      /*
1907
       * When constraint_exclusion is set to 'partition' we only handle
1908
       * appendrel members.  Partition pruning has already been applied,
1909
       * so there is no need to consider the rel's partition constraints
1910
       * here.
1911
       */
1912
0
      if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
1913
0
        break;     /* appendrel member, so process it */
1914
0
      return false;
1915
1916
0
    case CONSTRAINT_EXCLUSION_ON:
1917
1918
      /*
1919
       * In 'on' mode, always apply constraint exclusion.  If we are
1920
       * considering a baserel that is a partition (i.e., it was
1921
       * directly named rather than expanded from a parent table), then
1922
       * its partition constraints haven't been considered yet, so
1923
       * include them in the processing here.
1924
       */
1925
0
      if (rel->reloptkind == RELOPT_BASEREL)
1926
0
        include_partition = true;
1927
0
      break;        /* always try to exclude */
1928
0
  }
1929
1930
  /*
1931
   * Check for self-contradictory restriction clauses.  We dare not make
1932
   * deductions with non-immutable functions, but any immutable clauses that
1933
   * are self-contradictory allow us to conclude the scan is unnecessary.
1934
   *
1935
   * Note: strip off RestrictInfo because predicate_refuted_by() isn't
1936
   * expecting to see any in its predicate argument.
1937
   */
1938
0
  safe_restrictions = NIL;
1939
0
  foreach(lc, rel->baserestrictinfo)
1940
0
  {
1941
0
    RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1942
1943
0
    if (!contain_mutable_functions((Node *) rinfo->clause))
1944
0
      safe_restrictions = lappend(safe_restrictions, rinfo->clause);
1945
0
  }
1946
1947
  /*
1948
   * We can use weak refutation here, since we're comparing restriction
1949
   * clauses with restriction clauses.
1950
   */
1951
0
  if (predicate_refuted_by(safe_restrictions, safe_restrictions, true))
1952
0
    return true;
1953
1954
  /*
1955
   * Only plain relations have constraints, so stop here for other rtekinds.
1956
   */
1957
0
  if (rte->rtekind != RTE_RELATION)
1958
0
    return false;
1959
1960
  /*
1961
   * If we are scanning just this table, we can use NO INHERIT constraints,
1962
   * but not if we're scanning its children too.  (Note that partitioned
1963
   * tables should never have NO INHERIT constraints; but it's not necessary
1964
   * for us to assume that here.)
1965
   */
1966
0
  include_noinherit = !rte->inh;
1967
1968
  /*
1969
   * Currently, attnotnull constraints must be treated as NO INHERIT unless
1970
   * this is a partitioned table.  In future we might track their
1971
   * inheritance status more accurately, allowing this to be refined.
1972
   *
1973
   * XXX do we need/want to change this?
1974
   */
1975
0
  include_notnull = (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE);
1976
1977
  /*
1978
   * Fetch the appropriate set of constraint expressions.
1979
   */
1980
0
  constraint_pred = get_relation_constraints(root, rte->relid, rel,
1981
0
                         include_noinherit,
1982
0
                         include_notnull,
1983
0
                         include_partition);
1984
1985
  /*
1986
   * We do not currently enforce that CHECK constraints contain only
1987
   * immutable functions, so it's necessary to check here. We daren't draw
1988
   * conclusions from plan-time evaluation of non-immutable functions. Since
1989
   * they're ANDed, we can just ignore any mutable constraints in the list,
1990
   * and reason about the rest.
1991
   */
1992
0
  safe_constraints = NIL;
1993
0
  foreach(lc, constraint_pred)
1994
0
  {
1995
0
    Node     *pred = (Node *) lfirst(lc);
1996
1997
0
    if (!contain_mutable_functions(pred))
1998
0
      safe_constraints = lappend(safe_constraints, pred);
1999
0
  }
2000
2001
  /*
2002
   * The constraints are effectively ANDed together, so we can just try to
2003
   * refute the entire collection at once.  This may allow us to make proofs
2004
   * that would fail if we took them individually.
2005
   *
2006
   * Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
2007
   * an obvious optimization.  Some of the clauses might be OR clauses that
2008
   * have volatile and nonvolatile subclauses, and it's OK to make
2009
   * deductions with the nonvolatile parts.
2010
   *
2011
   * We need strong refutation because we have to prove that the constraints
2012
   * would yield false, not just NULL.
2013
   */
2014
0
  if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo, false))
2015
0
    return true;
2016
2017
0
  return false;
2018
0
}
2019
2020
2021
/*
2022
 * build_physical_tlist
2023
 *
2024
 * Build a targetlist consisting of exactly the relation's user attributes,
2025
 * in order.  The executor can special-case such tlists to avoid a projection
2026
 * step at runtime, so we use such tlists preferentially for scan nodes.
2027
 *
2028
 * Exception: if there are any dropped or missing columns, we punt and return
2029
 * NIL.  Ideally we would like to handle these cases too.  However this
2030
 * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc
2031
 * for a tlist that includes vars of no-longer-existent types.  In theory we
2032
 * could dig out the required info from the pg_attribute entries of the
2033
 * relation, but that data is not readily available to ExecTypeFromTL.
2034
 * For now, we don't apply the physical-tlist optimization when there are
2035
 * dropped cols.
2036
 *
2037
 * We also support building a "physical" tlist for subqueries, functions,
2038
 * values lists, table expressions, and CTEs, since the same optimization can
2039
 * occur in SubqueryScan, FunctionScan, ValuesScan, CteScan, TableFunc,
2040
 * NamedTuplestoreScan, and WorkTableScan nodes.
2041
 */
2042
List *
2043
build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
2044
0
{
2045
0
  List     *tlist = NIL;
2046
0
  Index   varno = rel->relid;
2047
0
  RangeTblEntry *rte = planner_rt_fetch(varno, root);
2048
0
  Relation  relation;
2049
0
  Query    *subquery;
2050
0
  Var      *var;
2051
0
  ListCell   *l;
2052
0
  int     attrno,
2053
0
        numattrs;
2054
0
  List     *colvars;
2055
2056
0
  switch (rte->rtekind)
2057
0
  {
2058
0
    case RTE_RELATION:
2059
      /* Assume we already have adequate lock */
2060
0
      relation = table_open(rte->relid, NoLock);
2061
2062
0
      numattrs = RelationGetNumberOfAttributes(relation);
2063
0
      for (attrno = 1; attrno <= numattrs; attrno++)
2064
0
      {
2065
0
        Form_pg_attribute att_tup = TupleDescAttr(relation->rd_att,
2066
0
                              attrno - 1);
2067
2068
0
        if (att_tup->attisdropped || att_tup->atthasmissing)
2069
0
        {
2070
          /* found a dropped or missing col, so punt */
2071
0
          tlist = NIL;
2072
0
          break;
2073
0
        }
2074
2075
0
        var = makeVar(varno,
2076
0
                attrno,
2077
0
                att_tup->atttypid,
2078
0
                att_tup->atttypmod,
2079
0
                att_tup->attcollation,
2080
0
                0);
2081
2082
0
        tlist = lappend(tlist,
2083
0
                makeTargetEntry((Expr *) var,
2084
0
                        attrno,
2085
0
                        NULL,
2086
0
                        false));
2087
0
      }
2088
2089
0
      table_close(relation, NoLock);
2090
0
      break;
2091
2092
0
    case RTE_SUBQUERY:
2093
0
      subquery = rte->subquery;
2094
0
      foreach(l, subquery->targetList)
2095
0
      {
2096
0
        TargetEntry *tle = (TargetEntry *) lfirst(l);
2097
2098
        /*
2099
         * A resjunk column of the subquery can be reflected as
2100
         * resjunk in the physical tlist; we need not punt.
2101
         */
2102
0
        var = makeVarFromTargetEntry(varno, tle);
2103
2104
0
        tlist = lappend(tlist,
2105
0
                makeTargetEntry((Expr *) var,
2106
0
                        tle->resno,
2107
0
                        NULL,
2108
0
                        tle->resjunk));
2109
0
      }
2110
0
      break;
2111
2112
0
    case RTE_FUNCTION:
2113
0
    case RTE_TABLEFUNC:
2114
0
    case RTE_VALUES:
2115
0
    case RTE_CTE:
2116
0
    case RTE_NAMEDTUPLESTORE:
2117
0
    case RTE_RESULT:
2118
      /* Not all of these can have dropped cols, but share code anyway */
2119
0
      expandRTE(rte, varno, 0, VAR_RETURNING_DEFAULT, -1,
2120
0
            true /* include dropped */ , NULL, &colvars);
2121
0
      foreach(l, colvars)
2122
0
      {
2123
0
        var = (Var *) lfirst(l);
2124
2125
        /*
2126
         * A non-Var in expandRTE's output means a dropped column;
2127
         * must punt.
2128
         */
2129
0
        if (!IsA(var, Var))
2130
0
        {
2131
0
          tlist = NIL;
2132
0
          break;
2133
0
        }
2134
2135
0
        tlist = lappend(tlist,
2136
0
                makeTargetEntry((Expr *) var,
2137
0
                        var->varattno,
2138
0
                        NULL,
2139
0
                        false));
2140
0
      }
2141
0
      break;
2142
2143
0
    default:
2144
      /* caller error */
2145
0
      elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",
2146
0
         (int) rte->rtekind);
2147
0
      break;
2148
0
  }
2149
2150
0
  return tlist;
2151
0
}
2152
2153
/*
2154
 * build_index_tlist
2155
 *
2156
 * Build a targetlist representing the columns of the specified index.
2157
 * Each column is represented by a Var for the corresponding base-relation
2158
 * column, or an expression in base-relation Vars, as appropriate.
2159
 *
2160
 * There are never any dropped columns in indexes, so unlike
2161
 * build_physical_tlist, we need no failure case.
2162
 */
2163
static List *
2164
build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
2165
          Relation heapRelation)
2166
0
{
2167
0
  List     *tlist = NIL;
2168
0
  Index   varno = index->rel->relid;
2169
0
  ListCell   *indexpr_item;
2170
0
  int     i;
2171
2172
0
  indexpr_item = list_head(index->indexprs);
2173
0
  for (i = 0; i < index->ncolumns; i++)
2174
0
  {
2175
0
    int     indexkey = index->indexkeys[i];
2176
0
    Expr     *indexvar;
2177
2178
0
    if (indexkey != 0)
2179
0
    {
2180
      /* simple column */
2181
0
      const FormData_pg_attribute *att_tup;
2182
2183
0
      if (indexkey < 0)
2184
0
        att_tup = SystemAttributeDefinition(indexkey);
2185
0
      else
2186
0
        att_tup = TupleDescAttr(heapRelation->rd_att, indexkey - 1);
2187
2188
0
      indexvar = (Expr *) makeVar(varno,
2189
0
                    indexkey,
2190
0
                    att_tup->atttypid,
2191
0
                    att_tup->atttypmod,
2192
0
                    att_tup->attcollation,
2193
0
                    0);
2194
0
    }
2195
0
    else
2196
0
    {
2197
      /* expression column */
2198
0
      if (indexpr_item == NULL)
2199
0
        elog(ERROR, "wrong number of index expressions");
2200
0
      indexvar = (Expr *) lfirst(indexpr_item);
2201
0
      indexpr_item = lnext(index->indexprs, indexpr_item);
2202
0
    }
2203
2204
0
    tlist = lappend(tlist,
2205
0
            makeTargetEntry(indexvar,
2206
0
                    i + 1,
2207
0
                    NULL,
2208
0
                    false));
2209
0
  }
2210
0
  if (indexpr_item != NULL)
2211
0
    elog(ERROR, "wrong number of index expressions");
2212
2213
0
  return tlist;
2214
0
}
2215
2216
/*
2217
 * restriction_selectivity
2218
 *
2219
 * Returns the selectivity of a specified restriction operator clause.
2220
 * This code executes registered procedures stored in the
2221
 * operator relation, by calling the function manager.
2222
 *
2223
 * See clause_selectivity() for the meaning of the additional parameters.
2224
 */
2225
Selectivity
2226
restriction_selectivity(PlannerInfo *root,
2227
            Oid operatorid,
2228
            List *args,
2229
            Oid inputcollid,
2230
            int varRelid)
2231
0
{
2232
0
  RegProcedure oprrest = get_oprrest(operatorid);
2233
0
  float8    result;
2234
2235
  /*
2236
   * if the oprrest procedure is missing for whatever reason, use a
2237
   * selectivity of 0.5
2238
   */
2239
0
  if (!oprrest)
2240
0
    return (Selectivity) 0.5;
2241
2242
0
  result = DatumGetFloat8(OidFunctionCall4Coll(oprrest,
2243
0
                         inputcollid,
2244
0
                         PointerGetDatum(root),
2245
0
                         ObjectIdGetDatum(operatorid),
2246
0
                         PointerGetDatum(args),
2247
0
                         Int32GetDatum(varRelid)));
2248
2249
0
  if (result < 0.0 || result > 1.0)
2250
0
    elog(ERROR, "invalid restriction selectivity: %f", result);
2251
2252
0
  return (Selectivity) result;
2253
0
}
2254
2255
/*
2256
 * join_selectivity
2257
 *
2258
 * Returns the selectivity of a specified join operator clause.
2259
 * This code executes registered procedures stored in the
2260
 * operator relation, by calling the function manager.
2261
 *
2262
 * See clause_selectivity() for the meaning of the additional parameters.
2263
 */
2264
Selectivity
2265
join_selectivity(PlannerInfo *root,
2266
         Oid operatorid,
2267
         List *args,
2268
         Oid inputcollid,
2269
         JoinType jointype,
2270
         SpecialJoinInfo *sjinfo)
2271
0
{
2272
0
  RegProcedure oprjoin = get_oprjoin(operatorid);
2273
0
  float8    result;
2274
2275
  /*
2276
   * if the oprjoin procedure is missing for whatever reason, use a
2277
   * selectivity of 0.5
2278
   */
2279
0
  if (!oprjoin)
2280
0
    return (Selectivity) 0.5;
2281
2282
0
  result = DatumGetFloat8(OidFunctionCall5Coll(oprjoin,
2283
0
                         inputcollid,
2284
0
                         PointerGetDatum(root),
2285
0
                         ObjectIdGetDatum(operatorid),
2286
0
                         PointerGetDatum(args),
2287
0
                         Int16GetDatum(jointype),
2288
0
                         PointerGetDatum(sjinfo)));
2289
2290
0
  if (result < 0.0 || result > 1.0)
2291
0
    elog(ERROR, "invalid join selectivity: %f", result);
2292
2293
0
  return (Selectivity) result;
2294
0
}
2295
2296
/*
2297
 * function_selectivity
2298
 *
2299
 * Attempt to estimate the selectivity of a specified boolean function clause
2300
 * by asking its support function.  If the function lacks support, return -1.
2301
 *
2302
 * See clause_selectivity() for the meaning of the additional parameters.
2303
 */
2304
Selectivity
2305
function_selectivity(PlannerInfo *root,
2306
           Oid funcid,
2307
           List *args,
2308
           Oid inputcollid,
2309
           bool is_join,
2310
           int varRelid,
2311
           JoinType jointype,
2312
           SpecialJoinInfo *sjinfo)
2313
0
{
2314
0
  RegProcedure prosupport = get_func_support(funcid);
2315
0
  SupportRequestSelectivity req;
2316
0
  SupportRequestSelectivity *sresult;
2317
2318
0
  if (!prosupport)
2319
0
    return (Selectivity) -1; /* no support function */
2320
2321
0
  req.type = T_SupportRequestSelectivity;
2322
0
  req.root = root;
2323
0
  req.funcid = funcid;
2324
0
  req.args = args;
2325
0
  req.inputcollid = inputcollid;
2326
0
  req.is_join = is_join;
2327
0
  req.varRelid = varRelid;
2328
0
  req.jointype = jointype;
2329
0
  req.sjinfo = sjinfo;
2330
0
  req.selectivity = -1;   /* to catch failure to set the value */
2331
2332
0
  sresult = (SupportRequestSelectivity *)
2333
0
    DatumGetPointer(OidFunctionCall1(prosupport,
2334
0
                     PointerGetDatum(&req)));
2335
2336
0
  if (sresult != &req)
2337
0
    return (Selectivity) -1; /* function did not honor request */
2338
2339
0
  if (req.selectivity < 0.0 || req.selectivity > 1.0)
2340
0
    elog(ERROR, "invalid function selectivity: %f", req.selectivity);
2341
2342
0
  return (Selectivity) req.selectivity;
2343
0
}
2344
2345
/*
2346
 * add_function_cost
2347
 *
2348
 * Get an estimate of the execution cost of a function, and *add* it to
2349
 * the contents of *cost.  The estimate may include both one-time and
2350
 * per-tuple components, since QualCost does.
2351
 *
2352
 * The funcid must always be supplied.  If it is being called as the
2353
 * implementation of a specific parsetree node (FuncExpr, OpExpr,
2354
 * WindowFunc, etc), pass that as "node", else pass NULL.
2355
 *
2356
 * In some usages root might be NULL, too.
2357
 */
2358
void
2359
add_function_cost(PlannerInfo *root, Oid funcid, Node *node,
2360
          QualCost *cost)
2361
0
{
2362
0
  HeapTuple proctup;
2363
0
  Form_pg_proc procform;
2364
2365
0
  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2366
0
  if (!HeapTupleIsValid(proctup))
2367
0
    elog(ERROR, "cache lookup failed for function %u", funcid);
2368
0
  procform = (Form_pg_proc) GETSTRUCT(proctup);
2369
2370
0
  if (OidIsValid(procform->prosupport))
2371
0
  {
2372
0
    SupportRequestCost req;
2373
0
    SupportRequestCost *sresult;
2374
2375
0
    req.type = T_SupportRequestCost;
2376
0
    req.root = root;
2377
0
    req.funcid = funcid;
2378
0
    req.node = node;
2379
2380
    /* Initialize cost fields so that support function doesn't have to */
2381
0
    req.startup = 0;
2382
0
    req.per_tuple = 0;
2383
2384
0
    sresult = (SupportRequestCost *)
2385
0
      DatumGetPointer(OidFunctionCall1(procform->prosupport,
2386
0
                       PointerGetDatum(&req)));
2387
2388
0
    if (sresult == &req)
2389
0
    {
2390
      /* Success, so accumulate support function's estimate into *cost */
2391
0
      cost->startup += req.startup;
2392
0
      cost->per_tuple += req.per_tuple;
2393
0
      ReleaseSysCache(proctup);
2394
0
      return;
2395
0
    }
2396
0
  }
2397
2398
  /* No support function, or it failed, so rely on procost */
2399
0
  cost->per_tuple += procform->procost * cpu_operator_cost;
2400
2401
0
  ReleaseSysCache(proctup);
2402
0
}
2403
2404
/*
2405
 * get_function_rows
2406
 *
2407
 * Get an estimate of the number of rows returned by a set-returning function.
2408
 *
2409
 * The funcid must always be supplied.  In current usage, the calling node
2410
 * will always be supplied, and will be either a FuncExpr or OpExpr.
2411
 * But it's a good idea to not fail if it's NULL.
2412
 *
2413
 * In some usages root might be NULL, too.
2414
 *
2415
 * Note: this returns the unfiltered result of the support function, if any.
2416
 * It's usually a good idea to apply clamp_row_est() to the result, but we
2417
 * leave it to the caller to do so.
2418
 */
2419
double
2420
get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
2421
0
{
2422
0
  HeapTuple proctup;
2423
0
  Form_pg_proc procform;
2424
0
  double    result;
2425
2426
0
  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2427
0
  if (!HeapTupleIsValid(proctup))
2428
0
    elog(ERROR, "cache lookup failed for function %u", funcid);
2429
0
  procform = (Form_pg_proc) GETSTRUCT(proctup);
2430
2431
0
  Assert(procform->proretset);  /* else caller error */
2432
2433
0
  if (OidIsValid(procform->prosupport))
2434
0
  {
2435
0
    SupportRequestRows req;
2436
0
    SupportRequestRows *sresult;
2437
2438
0
    req.type = T_SupportRequestRows;
2439
0
    req.root = root;
2440
0
    req.funcid = funcid;
2441
0
    req.node = node;
2442
2443
0
    req.rows = 0;     /* just for sanity */
2444
2445
0
    sresult = (SupportRequestRows *)
2446
0
      DatumGetPointer(OidFunctionCall1(procform->prosupport,
2447
0
                       PointerGetDatum(&req)));
2448
2449
0
    if (sresult == &req)
2450
0
    {
2451
      /* Success */
2452
0
      ReleaseSysCache(proctup);
2453
0
      return req.rows;
2454
0
    }
2455
0
  }
2456
2457
  /* No support function, or it failed, so rely on prorows */
2458
0
  result = procform->prorows;
2459
2460
0
  ReleaseSysCache(proctup);
2461
2462
0
  return result;
2463
0
}
2464
2465
/*
2466
 * has_unique_index
2467
 *
2468
 * Detect whether there is a unique index on the specified attribute
2469
 * of the specified relation, thus allowing us to conclude that all
2470
 * the (non-null) values of the attribute are distinct.
2471
 *
2472
 * This function does not check the index's indimmediate property, which
2473
 * means that uniqueness may transiently fail to hold intra-transaction.
2474
 * That's appropriate when we are making statistical estimates, but beware
2475
 * of using this for any correctness proofs.
2476
 */
2477
bool
2478
has_unique_index(RelOptInfo *rel, AttrNumber attno)
2479
0
{
2480
0
  ListCell   *ilist;
2481
2482
0
  foreach(ilist, rel->indexlist)
2483
0
  {
2484
0
    IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
2485
2486
    /*
2487
     * Note: ignore partial indexes, since they don't allow us to conclude
2488
     * that all attr values are distinct, *unless* they are marked predOK
2489
     * which means we know the index's predicate is satisfied by the
2490
     * query. We don't take any interest in expressional indexes either.
2491
     * Also, a multicolumn unique index doesn't allow us to conclude that
2492
     * just the specified attr is unique.
2493
     */
2494
0
    if (index->unique &&
2495
0
      index->nkeycolumns == 1 &&
2496
0
      index->indexkeys[0] == attno &&
2497
0
      (index->indpred == NIL || index->predOK))
2498
0
      return true;
2499
0
  }
2500
0
  return false;
2501
0
}
2502
2503
2504
/*
2505
 * has_row_triggers
2506
 *
2507
 * Detect whether the specified relation has any row-level triggers for event.
2508
 */
2509
bool
2510
has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
2511
0
{
2512
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2513
0
  Relation  relation;
2514
0
  TriggerDesc *trigDesc;
2515
0
  bool    result = false;
2516
2517
  /* Assume we already have adequate lock */
2518
0
  relation = table_open(rte->relid, NoLock);
2519
2520
0
  trigDesc = relation->trigdesc;
2521
0
  switch (event)
2522
0
  {
2523
0
    case CMD_INSERT:
2524
0
      if (trigDesc &&
2525
0
        (trigDesc->trig_insert_after_row ||
2526
0
         trigDesc->trig_insert_before_row))
2527
0
        result = true;
2528
0
      break;
2529
0
    case CMD_UPDATE:
2530
0
      if (trigDesc &&
2531
0
        (trigDesc->trig_update_after_row ||
2532
0
         trigDesc->trig_update_before_row))
2533
0
        result = true;
2534
0
      break;
2535
0
    case CMD_DELETE:
2536
0
      if (trigDesc &&
2537
0
        (trigDesc->trig_delete_after_row ||
2538
0
         trigDesc->trig_delete_before_row))
2539
0
        result = true;
2540
0
      break;
2541
      /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
2542
0
    case CMD_MERGE:
2543
0
      result = false;
2544
0
      break;
2545
0
    default:
2546
0
      elog(ERROR, "unrecognized CmdType: %d", (int) event);
2547
0
      break;
2548
0
  }
2549
2550
0
  table_close(relation, NoLock);
2551
0
  return result;
2552
0
}
2553
2554
/*
2555
 * has_transition_tables
2556
 *
2557
 * Detect whether the specified relation has any transition tables for event.
2558
 */
2559
bool
2560
has_transition_tables(PlannerInfo *root, Index rti, CmdType event)
2561
0
{
2562
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2563
0
  Relation  relation;
2564
0
  TriggerDesc *trigDesc;
2565
0
  bool    result = false;
2566
2567
0
  Assert(rte->rtekind == RTE_RELATION);
2568
2569
  /* Currently foreign tables cannot have transition tables */
2570
0
  if (rte->relkind == RELKIND_FOREIGN_TABLE)
2571
0
    return result;
2572
2573
  /* Assume we already have adequate lock */
2574
0
  relation = table_open(rte->relid, NoLock);
2575
2576
0
  trigDesc = relation->trigdesc;
2577
0
  switch (event)
2578
0
  {
2579
0
    case CMD_INSERT:
2580
0
      if (trigDesc &&
2581
0
        trigDesc->trig_insert_new_table)
2582
0
        result = true;
2583
0
      break;
2584
0
    case CMD_UPDATE:
2585
0
      if (trigDesc &&
2586
0
        (trigDesc->trig_update_old_table ||
2587
0
         trigDesc->trig_update_new_table))
2588
0
        result = true;
2589
0
      break;
2590
0
    case CMD_DELETE:
2591
0
      if (trigDesc &&
2592
0
        trigDesc->trig_delete_old_table)
2593
0
        result = true;
2594
0
      break;
2595
      /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
2596
0
    case CMD_MERGE:
2597
0
      result = false;
2598
0
      break;
2599
0
    default:
2600
0
      elog(ERROR, "unrecognized CmdType: %d", (int) event);
2601
0
      break;
2602
0
  }
2603
2604
0
  table_close(relation, NoLock);
2605
0
  return result;
2606
0
}
2607
2608
/*
2609
 * has_stored_generated_columns
2610
 *
2611
 * Does table identified by RTI have any STORED GENERATED columns?
2612
 */
2613
bool
2614
has_stored_generated_columns(PlannerInfo *root, Index rti)
2615
0
{
2616
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2617
0
  Relation  relation;
2618
0
  TupleDesc tupdesc;
2619
0
  bool    result = false;
2620
2621
  /* Assume we already have adequate lock */
2622
0
  relation = table_open(rte->relid, NoLock);
2623
2624
0
  tupdesc = RelationGetDescr(relation);
2625
0
  result = tupdesc->constr && tupdesc->constr->has_generated_stored;
2626
2627
0
  table_close(relation, NoLock);
2628
2629
0
  return result;
2630
0
}
2631
2632
/*
2633
 * get_dependent_generated_columns
2634
 *
2635
 * Get the column numbers of any STORED GENERATED columns of the relation
2636
 * that depend on any column listed in target_cols.  Both the input and
2637
 * result bitmapsets contain column numbers offset by
2638
 * FirstLowInvalidHeapAttributeNumber.
2639
 */
2640
Bitmapset *
2641
get_dependent_generated_columns(PlannerInfo *root, Index rti,
2642
                Bitmapset *target_cols)
2643
0
{
2644
0
  Bitmapset  *dependentCols = NULL;
2645
0
  RangeTblEntry *rte = planner_rt_fetch(rti, root);
2646
0
  Relation  relation;
2647
0
  TupleDesc tupdesc;
2648
0
  TupleConstr *constr;
2649
2650
  /* Assume we already have adequate lock */
2651
0
  relation = table_open(rte->relid, NoLock);
2652
2653
0
  tupdesc = RelationGetDescr(relation);
2654
0
  constr = tupdesc->constr;
2655
2656
0
  if (constr && constr->has_generated_stored)
2657
0
  {
2658
0
    for (int i = 0; i < constr->num_defval; i++)
2659
0
    {
2660
0
      AttrDefault *defval = &constr->defval[i];
2661
0
      Node     *expr;
2662
0
      Bitmapset  *attrs_used = NULL;
2663
2664
      /* skip if not generated column */
2665
0
      if (!TupleDescCompactAttr(tupdesc, defval->adnum - 1)->attgenerated)
2666
0
        continue;
2667
2668
      /* identify columns this generated column depends on */
2669
0
      expr = stringToNode(defval->adbin);
2670
0
      pull_varattnos(expr, 1, &attrs_used);
2671
2672
0
      if (bms_overlap(target_cols, attrs_used))
2673
0
        dependentCols = bms_add_member(dependentCols,
2674
0
                         defval->adnum - FirstLowInvalidHeapAttributeNumber);
2675
0
    }
2676
0
  }
2677
2678
0
  table_close(relation, NoLock);
2679
2680
0
  return dependentCols;
2681
0
}
2682
2683
/*
2684
 * set_relation_partition_info
2685
 *
2686
 * Set partitioning scheme and related information for a partitioned table.
2687
 */
2688
static void
2689
set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
2690
              Relation relation)
2691
0
{
2692
0
  PartitionDesc partdesc;
2693
2694
  /*
2695
   * Create the PartitionDirectory infrastructure if we didn't already.
2696
   */
2697
0
  if (root->glob->partition_directory == NULL)
2698
0
  {
2699
0
    root->glob->partition_directory =
2700
0
      CreatePartitionDirectory(CurrentMemoryContext, true);
2701
0
  }
2702
2703
0
  partdesc = PartitionDirectoryLookup(root->glob->partition_directory,
2704
0
                    relation);
2705
0
  rel->part_scheme = find_partition_scheme(root, relation);
2706
0
  Assert(partdesc != NULL && rel->part_scheme != NULL);
2707
0
  rel->boundinfo = partdesc->boundinfo;
2708
0
  rel->nparts = partdesc->nparts;
2709
0
  set_baserel_partition_key_exprs(relation, rel);
2710
0
  set_baserel_partition_constraint(relation, rel);
2711
0
}
2712
2713
/*
2714
 * find_partition_scheme
2715
 *
2716
 * Find or create a PartitionScheme for this Relation.
2717
 */
2718
static PartitionScheme
2719
find_partition_scheme(PlannerInfo *root, Relation relation)
2720
0
{
2721
0
  PartitionKey partkey = RelationGetPartitionKey(relation);
2722
0
  ListCell   *lc;
2723
0
  int     partnatts,
2724
0
        i;
2725
0
  PartitionScheme part_scheme;
2726
2727
  /* A partitioned table should have a partition key. */
2728
0
  Assert(partkey != NULL);
2729
2730
0
  partnatts = partkey->partnatts;
2731
2732
  /* Search for a matching partition scheme and return if found one. */
2733
0
  foreach(lc, root->part_schemes)
2734
0
  {
2735
0
    part_scheme = lfirst(lc);
2736
2737
    /* Match partitioning strategy and number of keys. */
2738
0
    if (partkey->strategy != part_scheme->strategy ||
2739
0
      partnatts != part_scheme->partnatts)
2740
0
      continue;
2741
2742
    /* Match partition key type properties. */
2743
0
    if (memcmp(partkey->partopfamily, part_scheme->partopfamily,
2744
0
           sizeof(Oid) * partnatts) != 0 ||
2745
0
      memcmp(partkey->partopcintype, part_scheme->partopcintype,
2746
0
           sizeof(Oid) * partnatts) != 0 ||
2747
0
      memcmp(partkey->partcollation, part_scheme->partcollation,
2748
0
           sizeof(Oid) * partnatts) != 0)
2749
0
      continue;
2750
2751
    /*
2752
     * Length and byval information should match when partopcintype
2753
     * matches.
2754
     */
2755
0
    Assert(memcmp(partkey->parttyplen, part_scheme->parttyplen,
2756
0
            sizeof(int16) * partnatts) == 0);
2757
0
    Assert(memcmp(partkey->parttypbyval, part_scheme->parttypbyval,
2758
0
            sizeof(bool) * partnatts) == 0);
2759
2760
    /*
2761
     * If partopfamily and partopcintype matched, must have the same
2762
     * partition comparison functions.  Note that we cannot reliably
2763
     * Assert the equality of function structs themselves for they might
2764
     * be different across PartitionKey's, so just Assert for the function
2765
     * OIDs.
2766
     */
2767
#ifdef USE_ASSERT_CHECKING
2768
    for (i = 0; i < partkey->partnatts; i++)
2769
      Assert(partkey->partsupfunc[i].fn_oid ==
2770
           part_scheme->partsupfunc[i].fn_oid);
2771
#endif
2772
2773
    /* Found matching partition scheme. */
2774
0
    return part_scheme;
2775
0
  }
2776
2777
  /*
2778
   * Did not find matching partition scheme. Create one copying relevant
2779
   * information from the relcache. We need to copy the contents of the
2780
   * array since the relcache entry may not survive after we have closed the
2781
   * relation.
2782
   */
2783
0
  part_scheme = palloc0_object(PartitionSchemeData);
2784
0
  part_scheme->strategy = partkey->strategy;
2785
0
  part_scheme->partnatts = partkey->partnatts;
2786
2787
0
  part_scheme->partopfamily = palloc_array(Oid, partnatts);
2788
0
  memcpy(part_scheme->partopfamily, partkey->partopfamily,
2789
0
       sizeof(Oid) * partnatts);
2790
2791
0
  part_scheme->partopcintype = palloc_array(Oid, partnatts);
2792
0
  memcpy(part_scheme->partopcintype, partkey->partopcintype,
2793
0
       sizeof(Oid) * partnatts);
2794
2795
0
  part_scheme->partcollation = palloc_array(Oid, partnatts);
2796
0
  memcpy(part_scheme->partcollation, partkey->partcollation,
2797
0
       sizeof(Oid) * partnatts);
2798
2799
0
  part_scheme->parttyplen = palloc_array(int16, partnatts);
2800
0
  memcpy(part_scheme->parttyplen, partkey->parttyplen,
2801
0
       sizeof(int16) * partnatts);
2802
2803
0
  part_scheme->parttypbyval = palloc_array(bool, partnatts);
2804
0
  memcpy(part_scheme->parttypbyval, partkey->parttypbyval,
2805
0
       sizeof(bool) * partnatts);
2806
2807
0
  part_scheme->partsupfunc = palloc_array(FmgrInfo, partnatts);
2808
0
  for (i = 0; i < partnatts; i++)
2809
0
    fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i],
2810
0
             CurrentMemoryContext);
2811
2812
  /* Add the partitioning scheme to PlannerInfo. */
2813
0
  root->part_schemes = lappend(root->part_schemes, part_scheme);
2814
2815
0
  return part_scheme;
2816
0
}
2817
2818
/*
2819
 * set_baserel_partition_key_exprs
2820
 *
2821
 * Builds partition key expressions for the given base relation and fills
2822
 * rel->partexprs.
2823
 */
2824
static void
2825
set_baserel_partition_key_exprs(Relation relation,
2826
                RelOptInfo *rel)
2827
0
{
2828
0
  PartitionKey partkey = RelationGetPartitionKey(relation);
2829
0
  int     partnatts;
2830
0
  int     cnt;
2831
0
  List    **partexprs;
2832
0
  ListCell   *lc;
2833
0
  Index   varno = rel->relid;
2834
2835
0
  Assert(IS_SIMPLE_REL(rel) && rel->relid > 0);
2836
2837
  /* A partitioned table should have a partition key. */
2838
0
  Assert(partkey != NULL);
2839
2840
0
  partnatts = partkey->partnatts;
2841
0
  partexprs = palloc_array(List *, partnatts);
2842
0
  lc = list_head(partkey->partexprs);
2843
2844
0
  for (cnt = 0; cnt < partnatts; cnt++)
2845
0
  {
2846
0
    Expr     *partexpr;
2847
0
    AttrNumber  attno = partkey->partattrs[cnt];
2848
2849
0
    if (attno != InvalidAttrNumber)
2850
0
    {
2851
      /* Single column partition key is stored as a Var node. */
2852
0
      Assert(attno > 0);
2853
2854
0
      partexpr = (Expr *) makeVar(varno, attno,
2855
0
                    partkey->parttypid[cnt],
2856
0
                    partkey->parttypmod[cnt],
2857
0
                    partkey->parttypcoll[cnt], 0);
2858
0
    }
2859
0
    else
2860
0
    {
2861
0
      if (lc == NULL)
2862
0
        elog(ERROR, "wrong number of partition key expressions");
2863
2864
      /* Re-stamp the expression with given varno. */
2865
0
      partexpr = (Expr *) copyObject(lfirst(lc));
2866
0
      ChangeVarNodes((Node *) partexpr, 1, varno, 0);
2867
0
      lc = lnext(partkey->partexprs, lc);
2868
0
    }
2869
2870
    /* Base relations have a single expression per key. */
2871
0
    partexprs[cnt] = list_make1(partexpr);
2872
0
  }
2873
2874
0
  rel->partexprs = partexprs;
2875
2876
  /*
2877
   * A base relation does not have nullable partition key expressions, since
2878
   * no outer join is involved.  We still allocate an array of empty
2879
   * expression lists to keep partition key expression handling code simple.
2880
   * See build_joinrel_partition_info() and match_expr_to_partition_keys().
2881
   */
2882
0
  rel->nullable_partexprs = palloc0_array(List *, partnatts);
2883
0
}
2884
2885
/*
2886
 * set_baserel_partition_constraint
2887
 *
2888
 * Builds the partition constraint for the given base relation and sets it
2889
 * in the given RelOptInfo.  All Var nodes are restamped with the relid of the
2890
 * given relation.
2891
 */
2892
static void
2893
set_baserel_partition_constraint(Relation relation, RelOptInfo *rel)
2894
0
{
2895
0
  List     *partconstr;
2896
2897
0
  if (rel->partition_qual) /* already done */
2898
0
    return;
2899
2900
  /*
2901
   * Run the partition quals through const-simplification similar to check
2902
   * constraints.  We skip canonicalize_qual, though, because partition
2903
   * quals should be in canonical form already; also, since the qual is in
2904
   * implicit-AND format, we'd have to explicitly convert it to explicit-AND
2905
   * format and back again.
2906
   */
2907
0
  partconstr = RelationGetPartitionQual(relation);
2908
0
  if (partconstr)
2909
0
  {
2910
0
    partconstr = (List *) expression_planner((Expr *) partconstr);
2911
0
    if (rel->relid != 1)
2912
0
      ChangeVarNodes((Node *) partconstr, 1, rel->relid, 0);
2913
0
    rel->partition_qual = partconstr;
2914
0
  }
2915
0
}