1 /*-------------------------------------------------------------------------
4 * routines for accessing the system catalogs
7 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/optimizer/util/plancat.c
14 *-------------------------------------------------------------------------
20 #include "access/genam.h"
21 #include "access/htup_details.h"
22 #include "access/nbtree.h"
23 #include "access/sysattr.h"
24 #include "access/table.h"
25 #include "access/tableam.h"
26 #include "access/transam.h"
27 #include "access/xlog.h"
28 #include "catalog/catalog.h"
29 #include "catalog/heap.h"
30 #include "catalog/pg_am.h"
31 #include "catalog/pg_proc.h"
32 #include "catalog/pg_statistic_ext.h"
33 #include "catalog/pg_statistic_ext_data.h"
34 #include "foreign/fdwapi.h"
35 #include "miscadmin.h"
36 #include "nodes/makefuncs.h"
37 #include "nodes/nodeFuncs.h"
38 #include "nodes/supportnodes.h"
39 #include "optimizer/clauses.h"
40 #include "optimizer/cost.h"
41 #include "optimizer/optimizer.h"
42 #include "optimizer/plancat.h"
43 #include "optimizer/prep.h"
44 #include "parser/parse_relation.h"
45 #include "parser/parsetree.h"
46 #include "partitioning/partdesc.h"
47 #include "rewrite/rewriteManip.h"
48 #include "statistics/statistics.h"
49 #include "storage/bufmgr.h"
50 #include "utils/builtins.h"
51 #include "utils/lsyscache.h"
52 #include "utils/partcache.h"
53 #include "utils/rel.h"
54 #include "utils/snapmgr.h"
55 #include "utils/syscache.h"
58 int constraint_exclusion
= CONSTRAINT_EXCLUSION_PARTITION
;
60 /* Hook for plugins to get control in get_relation_info() */
61 get_relation_info_hook_type get_relation_info_hook
= NULL
;
64 static void get_relation_foreign_keys(PlannerInfo
*root
, RelOptInfo
*rel
,
65 Relation relation
, bool inhparent
);
66 static bool infer_collation_opclass_match(InferenceElem
*elem
, Relation idxRel
,
68 static List
*get_relation_constraints(PlannerInfo
*root
,
69 Oid relationObjectId
, RelOptInfo
*rel
,
70 bool include_noinherit
,
72 bool include_partition
);
73 static List
*build_index_tlist(PlannerInfo
*root
, IndexOptInfo
*index
,
74 Relation heapRelation
);
75 static List
*get_relation_statistics(RelOptInfo
*rel
, Relation relation
);
76 static void set_relation_partition_info(PlannerInfo
*root
, RelOptInfo
*rel
,
78 static PartitionScheme
find_partition_scheme(PlannerInfo
*root
,
80 static void set_baserel_partition_key_exprs(Relation relation
,
82 static void set_baserel_partition_constraint(Relation relation
,
88 * Retrieves catalog information for a given relation.
90 * Given the Oid of the relation, return the following info into fields
91 * of the RelOptInfo struct:
93 * min_attr lowest valid AttrNumber
94 * max_attr highest valid AttrNumber
95 * indexlist list of IndexOptInfos for relation's indexes
96 * statlist list of StatisticExtInfo for relation's statistic objects
97 * serverid if it's a foreign table, the server OID
98 * fdwroutine if it's a foreign table, the FDW function pointers
99 * pages number of pages
100 * tuples number of tuples
101 * rel_parallel_workers user-defined number of parallel workers
103 * Also, add information about the relation's foreign keys to root->fkey_list.
105 * Also, initialize the attr_needed[] and attr_widths[] arrays. In most
106 * cases these are left as zeroes, but sometimes we need to compute attr
107 * widths here, and we may as well cache the results for costsize.c.
109 * If inhparent is true, all we need to do is set up the attr arrays:
110 * the RelOptInfo actually represents the appendrel formed by an inheritance
111 * tree, and so the parent rel's physical size and index information isn't
112 * important for it, however, for partitioned tables, we do populate the
113 * indexlist as the planner uses unique indexes as unique proofs for certain
117 get_relation_info(PlannerInfo
*root
, Oid relationObjectId
, bool inhparent
,
120 Index varno
= rel
->relid
;
123 List
*indexinfos
= NIL
;
126 * We need not lock the relation since it was already locked, either by
127 * the rewriter or when expand_inherited_rtentry() added it to the query's
130 relation
= table_open(relationObjectId
, NoLock
);
133 * Relations without a table AM can be used in a query only if they are of
134 * special-cased relkinds. This check prevents us from crashing later if,
135 * for example, a view's ON SELECT rule has gone missing. Note that
136 * table_open() already rejected indexes and composite types; spell the
137 * error the same way it does.
139 if (!relation
->rd_tableam
)
141 if (!(relation
->rd_rel
->relkind
== RELKIND_FOREIGN_TABLE
||
142 relation
->rd_rel
->relkind
== RELKIND_PARTITIONED_TABLE
))
144 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
145 errmsg("cannot open relation \"%s\"",
146 RelationGetRelationName(relation
)),
147 errdetail_relkind_not_supported(relation
->rd_rel
->relkind
)));
150 /* Temporary and unlogged relations are inaccessible during recovery. */
151 if (!RelationIsPermanent(relation
) && RecoveryInProgress())
153 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
154 errmsg("cannot access temporary or unlogged relations during recovery")));
156 rel
->min_attr
= FirstLowInvalidHeapAttributeNumber
+ 1;
157 rel
->max_attr
= RelationGetNumberOfAttributes(relation
);
158 rel
->reltablespace
= RelationGetForm(relation
)->reltablespace
;
160 Assert(rel
->max_attr
>= rel
->min_attr
);
161 rel
->attr_needed
= (Relids
*)
162 palloc0((rel
->max_attr
- rel
->min_attr
+ 1) * sizeof(Relids
));
163 rel
->attr_widths
= (int32
*)
164 palloc0((rel
->max_attr
- rel
->min_attr
+ 1) * sizeof(int32
));
167 * Estimate relation size --- unless it's an inheritance parent, in which
168 * case the size we want is not the rel's own size but the size of its
169 * inheritance tree. That will be computed in set_append_rel_size().
172 estimate_rel_size(relation
, rel
->attr_widths
- rel
->min_attr
,
173 &rel
->pages
, &rel
->tuples
, &rel
->allvisfrac
);
175 /* Retrieve the parallel_workers reloption, or -1 if not set. */
176 rel
->rel_parallel_workers
= RelationGetParallelWorkers(relation
, -1);
179 * Make list of indexes. Ignore indexes on system catalogs if told to.
180 * Don't bother with indexes from traditional inheritance parents. For
181 * partitioned tables, we need a list of at least unique indexes as these
182 * serve as unique proofs for certain planner optimizations. However,
183 * let's not discriminate here and just record all partitioned indexes
184 * whether they're unique indexes or not.
186 if ((inhparent
&& relation
->rd_rel
->relkind
!= RELKIND_PARTITIONED_TABLE
)
187 || (IgnoreSystemIndexes
&& IsSystemRelation(relation
)))
190 hasindex
= relation
->rd_rel
->relhasindex
;
198 indexoidlist
= RelationGetIndexList(relation
);
201 * For each index, we get the same type of lock that the executor will
202 * need, and do not release it. This saves a couple of trips to the
203 * shared lock manager while not creating any real loss of
204 * concurrency, because no schema changes could be happening on the
205 * index while we hold lock on the parent rel, and no lock type used
206 * for queries blocks any other kind of index operation.
208 lmode
= root
->simple_rte_array
[varno
]->rellockmode
;
210 foreach(l
, indexoidlist
)
212 Oid indexoid
= lfirst_oid(l
);
213 Relation indexRelation
;
215 IndexAmRoutine
*amroutine
;
222 * Extract info from the relation descriptor for the index.
224 indexRelation
= index_open(indexoid
, lmode
);
225 index
= indexRelation
->rd_index
;
228 * Ignore invalid indexes, since they can't safely be used for
229 * queries. Note that this is OK because the data structure we
230 * are constructing is only used by the planner --- the executor
231 * still needs to insert into "invalid" indexes, if they're marked
234 if (!index
->indisvalid
)
236 index_close(indexRelation
, NoLock
);
241 * If the index is valid, but cannot yet be used, ignore it; but
242 * mark the plan we are generating as transient. See
243 * src/backend/access/heap/README.HOT for discussion.
245 if (index
->indcheckxmin
&&
246 !TransactionIdPrecedes(HeapTupleHeaderGetXmin(indexRelation
->rd_indextuple
->t_data
),
249 root
->glob
->transientPlan
= true;
250 index_close(indexRelation
, NoLock
);
254 info
= makeNode(IndexOptInfo
);
256 info
->indexoid
= index
->indexrelid
;
257 info
->reltablespace
=
258 RelationGetForm(indexRelation
)->reltablespace
;
260 info
->ncolumns
= ncolumns
= index
->indnatts
;
261 info
->nkeycolumns
= nkeycolumns
= index
->indnkeyatts
;
263 info
->indexkeys
= (int *) palloc(sizeof(int) * ncolumns
);
264 info
->indexcollations
= (Oid
*) palloc(sizeof(Oid
) * nkeycolumns
);
265 info
->opfamily
= (Oid
*) palloc(sizeof(Oid
) * nkeycolumns
);
266 info
->opcintype
= (Oid
*) palloc(sizeof(Oid
) * nkeycolumns
);
267 info
->canreturn
= (bool *) palloc(sizeof(bool) * ncolumns
);
269 for (i
= 0; i
< ncolumns
; i
++)
271 info
->indexkeys
[i
] = index
->indkey
.values
[i
];
272 info
->canreturn
[i
] = index_can_return(indexRelation
, i
+ 1);
275 for (i
= 0; i
< nkeycolumns
; i
++)
277 info
->opfamily
[i
] = indexRelation
->rd_opfamily
[i
];
278 info
->opcintype
[i
] = indexRelation
->rd_opcintype
[i
];
279 info
->indexcollations
[i
] = indexRelation
->rd_indcollation
[i
];
282 info
->relam
= indexRelation
->rd_rel
->relam
;
285 * We don't have an AM for partitioned indexes, so we'll just
286 * NULLify the AM related fields for those.
288 if (indexRelation
->rd_rel
->relkind
!= RELKIND_PARTITIONED_INDEX
)
290 /* We copy just the fields we need, not all of rd_indam */
291 amroutine
= indexRelation
->rd_indam
;
292 info
->amcanorderbyop
= amroutine
->amcanorderbyop
;
293 info
->amoptionalkey
= amroutine
->amoptionalkey
;
294 info
->amsearcharray
= amroutine
->amsearcharray
;
295 info
->amsearchnulls
= amroutine
->amsearchnulls
;
296 info
->amcanparallel
= amroutine
->amcanparallel
;
297 info
->amhasgettuple
= (amroutine
->amgettuple
!= NULL
);
298 info
->amhasgetbitmap
= amroutine
->amgetbitmap
!= NULL
&&
299 relation
->rd_tableam
->scan_bitmap_next_block
!= NULL
;
300 info
->amcanmarkpos
= (amroutine
->ammarkpos
!= NULL
&&
301 amroutine
->amrestrpos
!= NULL
);
302 info
->amcostestimate
= amroutine
->amcostestimate
;
303 Assert(info
->amcostestimate
!= NULL
);
305 /* Fetch index opclass options */
306 info
->opclassoptions
= RelationGetIndexAttOptions(indexRelation
, true);
309 * Fetch the ordering information for the index, if any.
311 if (info
->relam
== BTREE_AM_OID
)
314 * If it's a btree index, we can use its opfamily OIDs
315 * directly as the sort ordering opfamily OIDs.
317 Assert(amroutine
->amcanorder
);
319 info
->sortopfamily
= info
->opfamily
;
320 info
->reverse_sort
= (bool *) palloc(sizeof(bool) * nkeycolumns
);
321 info
->nulls_first
= (bool *) palloc(sizeof(bool) * nkeycolumns
);
323 for (i
= 0; i
< nkeycolumns
; i
++)
325 int16 opt
= indexRelation
->rd_indoption
[i
];
327 info
->reverse_sort
[i
] = (opt
& INDOPTION_DESC
) != 0;
328 info
->nulls_first
[i
] = (opt
& INDOPTION_NULLS_FIRST
) != 0;
331 else if (amroutine
->amcanorder
)
334 * Otherwise, identify the corresponding btree opfamilies
335 * by trying to map this index's "<" operators into btree.
336 * Since "<" uniquely defines the behavior of a sort
337 * order, this is a sufficient test.
339 * XXX This method is rather slow and also requires the
340 * undesirable assumption that the other index AM numbers
341 * its strategies the same as btree. It'd be better to
342 * have a way to explicitly declare the corresponding
343 * btree opfamily for each opfamily of the other index
344 * type. But given the lack of current or foreseeable
345 * amcanorder index types, it's not worth expending more
348 info
->sortopfamily
= (Oid
*) palloc(sizeof(Oid
) * nkeycolumns
);
349 info
->reverse_sort
= (bool *) palloc(sizeof(bool) * nkeycolumns
);
350 info
->nulls_first
= (bool *) palloc(sizeof(bool) * nkeycolumns
);
352 for (i
= 0; i
< nkeycolumns
; i
++)
354 int16 opt
= indexRelation
->rd_indoption
[i
];
360 info
->reverse_sort
[i
] = (opt
& INDOPTION_DESC
) != 0;
361 info
->nulls_first
[i
] = (opt
& INDOPTION_NULLS_FIRST
) != 0;
363 ltopr
= get_opfamily_member(info
->opfamily
[i
],
366 BTLessStrategyNumber
);
367 if (OidIsValid(ltopr
) &&
368 get_ordering_op_properties(ltopr
,
372 btopcintype
== info
->opcintype
[i
] &&
373 btstrategy
== BTLessStrategyNumber
)
375 /* Successful mapping */
376 info
->sortopfamily
[i
] = btopfamily
;
380 /* Fail ... quietly treat index as unordered */
381 info
->sortopfamily
= NULL
;
382 info
->reverse_sort
= NULL
;
383 info
->nulls_first
= NULL
;
390 info
->sortopfamily
= NULL
;
391 info
->reverse_sort
= NULL
;
392 info
->nulls_first
= NULL
;
397 info
->amcanorderbyop
= false;
398 info
->amoptionalkey
= false;
399 info
->amsearcharray
= false;
400 info
->amsearchnulls
= false;
401 info
->amcanparallel
= false;
402 info
->amhasgettuple
= false;
403 info
->amhasgetbitmap
= false;
404 info
->amcanmarkpos
= false;
405 info
->amcostestimate
= NULL
;
407 info
->sortopfamily
= NULL
;
408 info
->reverse_sort
= NULL
;
409 info
->nulls_first
= NULL
;
413 * Fetch the index expressions and predicate, if any. We must
414 * modify the copies we obtain from the relcache to have the
415 * correct varno for the parent relation, so that they match up
416 * correctly against qual clauses.
418 info
->indexprs
= RelationGetIndexExpressions(indexRelation
);
419 info
->indpred
= RelationGetIndexPredicate(indexRelation
);
420 if (info
->indexprs
&& varno
!= 1)
421 ChangeVarNodes((Node
*) info
->indexprs
, 1, varno
, 0);
422 if (info
->indpred
&& varno
!= 1)
423 ChangeVarNodes((Node
*) info
->indpred
, 1, varno
, 0);
425 /* Build targetlist using the completed indexprs data */
426 info
->indextlist
= build_index_tlist(root
, info
, relation
);
428 info
->indrestrictinfo
= NIL
; /* set later, in indxpath.c */
429 info
->predOK
= false; /* set later, in indxpath.c */
430 info
->unique
= index
->indisunique
;
431 info
->immediate
= index
->indimmediate
;
432 info
->hypothetical
= false;
435 * Estimate the index size. If it's not a partial index, we lock
436 * the number-of-tuples estimate to equal the parent table; if it
437 * is partial then we have to use the same methods as we would for
438 * a table, except we can be sure that the index is not larger
439 * than the table. We must ignore partitioned indexes here as
440 * there are not physical indexes.
442 if (indexRelation
->rd_rel
->relkind
!= RELKIND_PARTITIONED_INDEX
)
444 if (info
->indpred
== NIL
)
446 info
->pages
= RelationGetNumberOfBlocks(indexRelation
);
447 info
->tuples
= rel
->tuples
;
451 double allvisfrac
; /* dummy */
453 estimate_rel_size(indexRelation
, NULL
,
454 &info
->pages
, &info
->tuples
, &allvisfrac
);
455 if (info
->tuples
> rel
->tuples
)
456 info
->tuples
= rel
->tuples
;
459 if (info
->relam
== BTREE_AM_OID
)
462 * For btrees, get tree height while we have the index
465 info
->tree_height
= _bt_getrootheight(indexRelation
);
469 /* For other index types, just set it to "unknown" for now */
470 info
->tree_height
= -1;
475 /* Zero these out for partitioned indexes */
478 info
->tree_height
= -1;
481 index_close(indexRelation
, NoLock
);
484 * We've historically used lcons() here. It'd make more sense to
485 * use lappend(), but that causes the planner to change behavior
486 * in cases where two indexes seem equally attractive. For now,
487 * stick with lcons() --- few tables should have so many indexes
488 * that the O(N^2) behavior of lcons() is really a problem.
490 indexinfos
= lcons(info
, indexinfos
);
493 list_free(indexoidlist
);
496 rel
->indexlist
= indexinfos
;
498 rel
->statlist
= get_relation_statistics(rel
, relation
);
500 /* Grab foreign-table info using the relcache, while we have it */
501 if (relation
->rd_rel
->relkind
== RELKIND_FOREIGN_TABLE
)
503 rel
->serverid
= GetForeignServerIdByRelId(RelationGetRelid(relation
));
504 rel
->fdwroutine
= GetFdwRoutineForRelation(relation
, true);
508 rel
->serverid
= InvalidOid
;
509 rel
->fdwroutine
= NULL
;
512 /* Collect info about relation's foreign keys, if relevant */
513 get_relation_foreign_keys(root
, rel
, relation
, inhparent
);
515 /* Collect info about functions implemented by the rel's table AM. */
516 if (relation
->rd_tableam
&&
517 relation
->rd_tableam
->scan_set_tidrange
!= NULL
&&
518 relation
->rd_tableam
->scan_getnextslot_tidrange
!= NULL
)
519 rel
->amflags
|= AMFLAG_HAS_TID_RANGE
;
522 * Collect info about relation's partitioning scheme, if any. Only
523 * inheritance parents may be partitioned.
525 if (inhparent
&& relation
->rd_rel
->relkind
== RELKIND_PARTITIONED_TABLE
)
526 set_relation_partition_info(root
, rel
, relation
);
528 table_close(relation
, NoLock
);
531 * Allow a plugin to editorialize on the info we obtained from the
532 * catalogs. Actions might include altering the assumed relation size,
533 * removing an index, or adding a hypothetical index to the indexlist.
535 if (get_relation_info_hook
)
536 (*get_relation_info_hook
) (root
, relationObjectId
, inhparent
, rel
);
540 * get_relation_foreign_keys -
541 * Retrieves foreign key information for a given relation.
543 * ForeignKeyOptInfos for relevant foreign keys are created and added to
544 * root->fkey_list. We do this now while we have the relcache entry open.
545 * We could sometimes avoid making useless ForeignKeyOptInfos if we waited
546 * until all RelOptInfos have been built, but the cost of re-opening the
547 * relcache entries would probably exceed any savings.
550 get_relation_foreign_keys(PlannerInfo
*root
, RelOptInfo
*rel
,
551 Relation relation
, bool inhparent
)
553 List
*rtable
= root
->parse
->rtable
;
558 * If it's not a baserel, we don't care about its FKs. Also, if the query
559 * references only a single relation, we can skip the lookup since no FKs
560 * could satisfy the requirements below.
562 if (rel
->reloptkind
!= RELOPT_BASEREL
||
563 list_length(rtable
) < 2)
567 * If it's the parent of an inheritance tree, ignore its FKs. We could
568 * make useful FK-based deductions if we found that all members of the
569 * inheritance tree have equivalent FK constraints, but detecting that
570 * would require code that hasn't been written.
576 * Extract data about relation's FKs from the relcache. Note that this
577 * list belongs to the relcache and might disappear in a cache flush, so
578 * we must not do any further catalog access within this function.
580 cachedfkeys
= RelationGetFKeyList(relation
);
583 * Figure out which FKs are of interest for this query, and create
584 * ForeignKeyOptInfos for them. We want only FKs that reference some
585 * other RTE of the current query. In queries containing self-joins,
586 * there might be more than one other RTE for a referenced table, and we
587 * should make a ForeignKeyOptInfo for each occurrence.
589 * Ideally, we would ignore RTEs that correspond to non-baserels, but it's
590 * too hard to identify those here, so we might end up making some useless
591 * ForeignKeyOptInfos. If so, match_foreign_keys_to_quals() will remove
594 foreach(lc
, cachedfkeys
)
596 ForeignKeyCacheInfo
*cachedfk
= (ForeignKeyCacheInfo
*) lfirst(lc
);
600 /* conrelid should always be that of the table we're considering */
601 Assert(cachedfk
->conrelid
== RelationGetRelid(relation
));
603 /* Scan to find other RTEs matching confrelid */
607 RangeTblEntry
*rte
= (RangeTblEntry
*) lfirst(lc2
);
608 ForeignKeyOptInfo
*info
;
611 /* Ignore if not the correct table */
612 if (rte
->rtekind
!= RTE_RELATION
||
613 rte
->relid
!= cachedfk
->confrelid
)
615 /* Ignore if it's an inheritance parent; doesn't really match */
618 /* Ignore self-referential FKs; we only care about joins */
619 if (rti
== rel
->relid
)
622 /* OK, let's make an entry */
623 info
= makeNode(ForeignKeyOptInfo
);
624 info
->con_relid
= rel
->relid
;
625 info
->ref_relid
= rti
;
626 info
->nkeys
= cachedfk
->nkeys
;
627 memcpy(info
->conkey
, cachedfk
->conkey
, sizeof(info
->conkey
));
628 memcpy(info
->confkey
, cachedfk
->confkey
, sizeof(info
->confkey
));
629 memcpy(info
->conpfeqop
, cachedfk
->conpfeqop
, sizeof(info
->conpfeqop
));
630 /* zero out fields to be filled by match_foreign_keys_to_quals */
631 info
->nmatched_ec
= 0;
633 info
->nmatched_rcols
= 0;
634 info
->nmatched_ri
= 0;
635 memset(info
->eclass
, 0, sizeof(info
->eclass
));
636 memset(info
->fk_eclass_member
, 0, sizeof(info
->fk_eclass_member
));
637 memset(info
->rinfos
, 0, sizeof(info
->rinfos
));
639 root
->fkey_list
= lappend(root
->fkey_list
, info
);
645 * infer_arbiter_indexes -
646 * Determine the unique indexes used to arbitrate speculative insertion.
648 * Uses user-supplied inference clause expressions and predicate to match a
649 * unique index from those defined and ready on the heap relation (target).
650 * An exact match is required on columns/expressions (although they can appear
651 * in any order). However, the predicate given by the user need only restrict
652 * insertion to a subset of some part of the table covered by some particular
653 * unique index (in particular, a partial unique index) in order to be
656 * The implementation does not consider which B-Tree operator class any
657 * particular available unique index attribute uses, unless one was specified
658 * in the inference specification. The same is true of collations. In
659 * particular, there is no system dependency on the default operator class for
660 * the purposes of inference. If no opclass (or collation) is specified, then
661 * all matching indexes (that may or may not match the default in terms of
662 * each attribute opclass/collation) are used for inference.
665 infer_arbiter_indexes(PlannerInfo
*root
)
667 OnConflictExpr
*onconflict
= root
->parse
->onConflict
;
669 /* Iteration state */
672 Oid indexOidFromConstraint
= InvalidOid
;
676 /* Normalized inference attributes and inference expressions: */
677 Bitmapset
*inferAttrs
= NULL
;
678 List
*inferElems
= NIL
;
684 * Quickly return NIL for ON CONFLICT DO NOTHING without an inference
685 * specification or named constraint. ON CONFLICT DO UPDATE statements
686 * must always provide one or the other (but parser ought to have caught
689 if (onconflict
->arbiterElems
== NIL
&&
690 onconflict
->constraint
== InvalidOid
)
694 * We need not lock the relation since it was already locked, either by
695 * the rewriter or when expand_inherited_rtentry() added it to the query's
698 rte
= rt_fetch(root
->parse
->resultRelation
, root
->parse
->rtable
);
700 relation
= table_open(rte
->relid
, NoLock
);
703 * Build normalized/BMS representation of plain indexed attributes, as
704 * well as a separate list of expression items. This simplifies matching
705 * the cataloged definition of indexes.
707 foreach(l
, onconflict
->arbiterElems
)
709 InferenceElem
*elem
= (InferenceElem
*) lfirst(l
);
713 if (!IsA(elem
->expr
, Var
))
715 /* If not a plain Var, just shove it in inferElems for now */
716 inferElems
= lappend(inferElems
, elem
->expr
);
720 var
= (Var
*) elem
->expr
;
721 attno
= var
->varattno
;
725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
726 errmsg("whole row unique index inference specifications are not supported")));
728 inferAttrs
= bms_add_member(inferAttrs
,
729 attno
- FirstLowInvalidHeapAttributeNumber
);
733 * Lookup named constraint's index. This is not immediately returned
734 * because some additional sanity checks are required.
736 if (onconflict
->constraint
!= InvalidOid
)
738 indexOidFromConstraint
= get_constraint_index(onconflict
->constraint
);
740 if (indexOidFromConstraint
== InvalidOid
)
742 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
743 errmsg("constraint in ON CONFLICT clause has no associated index")));
747 * Using that representation, iterate through the list of indexes on the
748 * target relation to try and find a match
750 indexList
= RelationGetIndexList(relation
);
752 foreach(l
, indexList
)
754 Oid indexoid
= lfirst_oid(l
);
756 Form_pg_index idxForm
;
757 Bitmapset
*indexedAttrs
;
764 * Extract info from the relation descriptor for the index. Obtain
765 * the same lock type that the executor will ultimately use.
767 * Let executor complain about !indimmediate case directly, because
768 * enforcement needs to occur there anyway when an inference clause is
771 idxRel
= index_open(indexoid
, rte
->rellockmode
);
772 idxForm
= idxRel
->rd_index
;
774 if (!idxForm
->indisvalid
)
778 * Note that we do not perform a check against indcheckxmin (like e.g.
779 * get_relation_info()) here to eliminate candidates, because
780 * uniqueness checking only cares about the most recently committed
785 * Look for match on "ON constraint_name" variant, which may not be
786 * unique constraint. This can only be a constraint name.
788 if (indexOidFromConstraint
== idxForm
->indexrelid
)
790 if (!idxForm
->indisunique
&& onconflict
->action
== ONCONFLICT_UPDATE
)
792 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
793 errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
795 results
= lappend_oid(results
, idxForm
->indexrelid
);
796 list_free(indexList
);
797 index_close(idxRel
, NoLock
);
798 table_close(relation
, NoLock
);
801 else if (indexOidFromConstraint
!= InvalidOid
)
803 /* No point in further work for index in named constraint case */
808 * Only considering conventional inference at this point (not named
809 * constraints), so index under consideration can be immediately
810 * skipped if it's not unique
812 if (!idxForm
->indisunique
)
815 /* Build BMS representation of plain (non expression) index attrs */
817 for (natt
= 0; natt
< idxForm
->indnkeyatts
; natt
++)
819 int attno
= idxRel
->rd_index
->indkey
.values
[natt
];
822 indexedAttrs
= bms_add_member(indexedAttrs
,
823 attno
- FirstLowInvalidHeapAttributeNumber
);
826 /* Non-expression attributes (if any) must match */
827 if (!bms_equal(indexedAttrs
, inferAttrs
))
830 /* Expression attributes (if any) must match */
831 idxExprs
= RelationGetIndexExpressions(idxRel
);
832 foreach(el
, onconflict
->arbiterElems
)
834 InferenceElem
*elem
= (InferenceElem
*) lfirst(el
);
837 * Ensure that collation/opclass aspects of inference expression
838 * element match. Even though this loop is primarily concerned
839 * with matching expressions, it is a convenient point to check
840 * this for both expressions and ordinary (non-expression)
841 * attributes appearing as inference elements.
843 if (!infer_collation_opclass_match(elem
, idxRel
, idxExprs
))
847 * Plain Vars don't factor into count of expression elements, and
848 * the question of whether or not they satisfy the index
849 * definition has already been considered (they must).
851 if (IsA(elem
->expr
, Var
))
855 * Might as well avoid redundant check in the rare cases where
856 * infer_collation_opclass_match() is required to do real work.
857 * Otherwise, check that element expression appears in cataloged
860 if (elem
->infercollid
!= InvalidOid
||
861 elem
->inferopclass
!= InvalidOid
||
862 list_member(idxExprs
, elem
->expr
))
869 * Now that all inference elements were matched, ensure that the
870 * expression elements from inference clause are not missing any
871 * cataloged expressions. This does the right thing when unique
872 * indexes redundantly repeat the same attribute, or if attributes
873 * redundantly appear multiple times within an inference clause.
875 if (list_difference(idxExprs
, inferElems
) != NIL
)
879 * If it's a partial index, its predicate must be implied by the ON
880 * CONFLICT's WHERE clause.
882 predExprs
= RelationGetIndexPredicate(idxRel
);
884 if (!predicate_implied_by(predExprs
, (List
*) onconflict
->arbiterWhere
, false))
887 results
= lappend_oid(results
, idxForm
->indexrelid
);
889 index_close(idxRel
, NoLock
);
892 list_free(indexList
);
893 table_close(relation
, NoLock
);
897 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE
),
898 errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
904 * infer_collation_opclass_match - ensure infer element opclass/collation match
906 * Given unique index inference element from inference specification, if
907 * collation was specified, or if opclass was specified, verify that there is
908 * at least one matching indexed attribute (occasionally, there may be more).
909 * Skip this in the common case where inference specification does not include
910 * collation or opclass (instead matching everything, regardless of cataloged
911 * collation/opclass of indexed attribute).
913 * At least historically, Postgres has not offered collations or opclasses
914 * with alternative-to-default notions of equality, so these additional
915 * criteria should only be required infrequently.
917 * Don't give up immediately when an inference element matches some attribute
918 * cataloged as indexed but not matching additional opclass/collation
919 * criteria. This is done so that the implementation is as forgiving as
920 * possible of redundancy within cataloged index attributes (or, less
921 * usefully, within inference specification elements). If collations actually
922 * differ between apparently redundantly indexed attributes (redundant within
923 * or across indexes), then there really is no redundancy as such.
925 * Note that if an inference element specifies an opclass and a collation at
926 * once, both must match in at least one particular attribute within index
927 * catalog definition in order for that inference element to be considered
928 * inferred/satisfied.
931 infer_collation_opclass_match(InferenceElem
*elem
, Relation idxRel
,
935 Oid inferopfamily
= InvalidOid
; /* OID of opclass opfamily */
936 Oid inferopcinputtype
= InvalidOid
; /* OID of opclass input type */
937 int nplain
= 0; /* # plain attrs observed */
940 * If inference specification element lacks collation/opclass, then no
941 * need to check for exact match.
943 if (elem
->infercollid
== InvalidOid
&& elem
->inferopclass
== InvalidOid
)
947 * Lookup opfamily and input type, for matching indexes
949 if (elem
->inferopclass
)
951 inferopfamily
= get_opclass_family(elem
->inferopclass
);
952 inferopcinputtype
= get_opclass_input_type(elem
->inferopclass
);
955 for (natt
= 1; natt
<= idxRel
->rd_att
->natts
; natt
++)
957 Oid opfamily
= idxRel
->rd_opfamily
[natt
- 1];
958 Oid opcinputtype
= idxRel
->rd_opcintype
[natt
- 1];
959 Oid collation
= idxRel
->rd_indcollation
[natt
- 1];
960 int attno
= idxRel
->rd_index
->indkey
.values
[natt
- 1];
965 if (elem
->inferopclass
!= InvalidOid
&&
966 (inferopfamily
!= opfamily
|| inferopcinputtype
!= opcinputtype
))
968 /* Attribute needed to match opclass, but didn't */
972 if (elem
->infercollid
!= InvalidOid
&&
973 elem
->infercollid
!= collation
)
975 /* Attribute needed to match collation, but didn't */
979 /* If one matching index att found, good enough -- return true */
980 if (IsA(elem
->expr
, Var
))
982 if (((Var
*) elem
->expr
)->varattno
== attno
)
987 Node
*nattExpr
= list_nth(idxExprs
, (natt
- 1) - nplain
);
990 * Note that unlike routines like match_index_to_operand() we
991 * don't need to care about RelabelType. Neither the index
992 * definition nor the inference clause should contain them.
994 if (equal(elem
->expr
, nattExpr
))
1003 * estimate_rel_size - estimate # pages and # tuples in a table or index
1005 * We also estimate the fraction of the pages that are marked all-visible in
1006 * the visibility map, for use in estimation of index-only scans.
1008 * If attr_widths isn't NULL, it points to the zero-index entry of the
1009 * relation's attr_widths[] cache; we fill this in if we have need to compute
1010 * the attribute widths for estimation purposes.
1013 estimate_rel_size(Relation rel
, int32
*attr_widths
,
1014 BlockNumber
*pages
, double *tuples
, double *allvisfrac
)
1016 BlockNumber curpages
;
1017 BlockNumber relpages
;
1019 BlockNumber relallvisible
;
1022 if (RELKIND_HAS_TABLE_AM(rel
->rd_rel
->relkind
))
1024 table_relation_estimate_size(rel
, attr_widths
, pages
, tuples
,
1027 else if (rel
->rd_rel
->relkind
== RELKIND_INDEX
)
1030 * XXX: It'd probably be good to move this into a callback, individual
1031 * index types e.g. know if they have a metapage.
1034 /* it has storage, ok to call the smgr */
1035 curpages
= RelationGetNumberOfBlocks(rel
);
1037 /* report estimated # pages */
1039 /* quick exit if rel is clearly empty */
1047 /* coerce values in pg_class to more desirable types */
1048 relpages
= (BlockNumber
) rel
->rd_rel
->relpages
;
1049 reltuples
= (double) rel
->rd_rel
->reltuples
;
1050 relallvisible
= (BlockNumber
) rel
->rd_rel
->relallvisible
;
1053 * Discount the metapage while estimating the number of tuples. This
1054 * is a kluge because it assumes more than it ought to about index
1055 * structure. Currently it's OK for btree, hash, and GIN indexes but
1056 * suspect for GiST indexes.
1064 /* estimate number of tuples from previous tuple density */
1065 if (reltuples
>= 0 && relpages
> 0)
1066 density
= reltuples
/ (double) relpages
;
1070 * If we have no data because the relation was never vacuumed,
1071 * estimate tuple width from attribute datatypes. We assume here
1072 * that the pages are completely full, which is OK for tables
1073 * (since they've presumably not been VACUUMed yet) but is
1074 * probably an overestimate for indexes. Fortunately
1075 * get_relation_info() can clamp the overestimate to the parent
1078 * Note: this code intentionally disregards alignment
1079 * considerations, because (a) that would be gilding the lily
1080 * considering how crude the estimate is, and (b) it creates
1081 * platform dependencies in the default plans which are kind of a
1082 * headache for regression testing.
1084 * XXX: Should this logic be more index specific?
1088 tuple_width
= get_rel_data_width(rel
, attr_widths
);
1089 tuple_width
+= MAXALIGN(SizeofHeapTupleHeader
);
1090 tuple_width
+= sizeof(ItemIdData
);
1091 /* note: integer division is intentional here */
1092 density
= (BLCKSZ
- SizeOfPageHeaderData
) / tuple_width
;
1094 *tuples
= rint(density
* (double) curpages
);
1097 * We use relallvisible as-is, rather than scaling it up like we do
1098 * for the pages and tuples counts, on the theory that any pages added
1099 * since the last VACUUM are most likely not marked all-visible. But
1100 * costsize.c wants it converted to a fraction.
1102 if (relallvisible
== 0 || curpages
<= 0)
1104 else if ((double) relallvisible
>= curpages
)
1107 *allvisfrac
= (double) relallvisible
/ curpages
;
1112 * Just use whatever's in pg_class. This covers foreign tables,
1113 * sequences, and also relkinds without storage (shouldn't get here?);
1114 * see initializations in AddNewRelationTuple(). Note that FDW must
1115 * cope if reltuples is -1!
1117 *pages
= rel
->rd_rel
->relpages
;
1118 *tuples
= rel
->rd_rel
->reltuples
;
1125 * get_rel_data_width
1127 * Estimate the average width of (the data part of) the relation's tuples.
1129 * If attr_widths isn't NULL, it points to the zero-index entry of the
1130 * relation's attr_widths[] cache; use and update that cache as appropriate.
1132 * Currently we ignore dropped columns. Ideally those should be included
1133 * in the result, but we haven't got any way to get info about them; and
1134 * since they might be mostly NULLs, treating them as zero-width is not
1135 * necessarily the wrong thing anyway.
1138 get_rel_data_width(Relation rel
, int32
*attr_widths
)
1140 int64 tuple_width
= 0;
1143 for (i
= 1; i
<= RelationGetNumberOfAttributes(rel
); i
++)
1145 Form_pg_attribute att
= TupleDescAttr(rel
->rd_att
, i
- 1);
1148 if (att
->attisdropped
)
1151 /* use previously cached data, if any */
1152 if (attr_widths
!= NULL
&& attr_widths
[i
] > 0)
1154 tuple_width
+= attr_widths
[i
];
1158 /* This should match set_rel_width() in costsize.c */
1159 item_width
= get_attavgwidth(RelationGetRelid(rel
), i
);
1160 if (item_width
<= 0)
1162 item_width
= get_typavgwidth(att
->atttypid
, att
->atttypmod
);
1163 Assert(item_width
> 0);
1165 if (attr_widths
!= NULL
)
1166 attr_widths
[i
] = item_width
;
1167 tuple_width
+= item_width
;
1170 return clamp_width_est(tuple_width
);
1174 * get_relation_data_width
1176 * External API for get_rel_data_width: same behavior except we have to
1177 * open the relcache entry.
1180 get_relation_data_width(Oid relid
, int32
*attr_widths
)
1185 /* As above, assume relation is already locked */
1186 relation
= table_open(relid
, NoLock
);
1188 result
= get_rel_data_width(relation
, attr_widths
);
1190 table_close(relation
, NoLock
);
1197 * get_relation_constraints
1199 * Retrieve the applicable constraint expressions of the given relation.
1201 * Returns a List (possibly empty) of constraint expressions. Each one
1202 * has been canonicalized, and its Vars are changed to have the varno
1203 * indicated by rel->relid. This allows the expressions to be easily
1204 * compared to expressions taken from WHERE.
1206 * If include_noinherit is true, it's okay to include constraints that
1207 * are marked NO INHERIT.
1209 * If include_notnull is true, "col IS NOT NULL" expressions are generated
1210 * and added to the result for each column that's marked attnotnull.
1212 * If include_partition is true, and the relation is a partition,
1213 * also include the partitioning constraints.
1215 * Note: at present this is invoked at most once per relation per planner
1216 * run, and in many cases it won't be invoked at all, so there seems no
1217 * point in caching the data in RelOptInfo.
1220 get_relation_constraints(PlannerInfo
*root
,
1221 Oid relationObjectId
, RelOptInfo
*rel
,
1222 bool include_noinherit
,
1223 bool include_notnull
,
1224 bool include_partition
)
1227 Index varno
= rel
->relid
;
1229 TupleConstr
*constr
;
1232 * We assume the relation has already been safely locked.
1234 relation
= table_open(relationObjectId
, NoLock
);
1236 constr
= relation
->rd_att
->constr
;
1239 int num_check
= constr
->num_check
;
1242 for (i
= 0; i
< num_check
; i
++)
1247 * If this constraint hasn't been fully validated yet, we must
1248 * ignore it here. Also ignore if NO INHERIT and we weren't told
1251 if (!constr
->check
[i
].ccvalid
)
1253 if (constr
->check
[i
].ccnoinherit
&& !include_noinherit
)
1256 cexpr
= stringToNode(constr
->check
[i
].ccbin
);
1259 * Run each expression through const-simplification and
1260 * canonicalization. This is not just an optimization, but is
1261 * necessary, because we will be comparing it to
1262 * similarly-processed qual clauses, and may fail to detect valid
1263 * matches without this. This must match the processing done to
1264 * qual clauses in preprocess_expression()! (We can skip the
1265 * stuff involving subqueries, however, since we don't allow any
1266 * in check constraints.)
1268 cexpr
= eval_const_expressions(root
, cexpr
);
1270 cexpr
= (Node
*) canonicalize_qual((Expr
*) cexpr
, true);
1272 /* Fix Vars to have the desired varno */
1274 ChangeVarNodes(cexpr
, 1, varno
, 0);
1277 * Finally, convert to implicit-AND format (that is, a List) and
1278 * append the resulting item(s) to our output list.
1280 result
= list_concat(result
,
1281 make_ands_implicit((Expr
*) cexpr
));
1284 /* Add NOT NULL constraints in expression form, if requested */
1285 if (include_notnull
&& constr
->has_not_null
)
1287 int natts
= relation
->rd_att
->natts
;
1289 for (i
= 1; i
<= natts
; i
++)
1291 Form_pg_attribute att
= TupleDescAttr(relation
->rd_att
, i
- 1);
1293 if (att
->attnotnull
&& !att
->attisdropped
)
1295 NullTest
*ntest
= makeNode(NullTest
);
1297 ntest
->arg
= (Expr
*) makeVar(varno
,
1303 ntest
->nulltesttype
= IS_NOT_NULL
;
1306 * argisrow=false is correct even for a composite column,
1307 * because attnotnull does not represent a SQL-spec IS NOT
1308 * NULL test in such a case, just IS DISTINCT FROM NULL.
1310 ntest
->argisrow
= false;
1311 ntest
->location
= -1;
1312 result
= lappend(result
, ntest
);
1319 * Add partitioning constraints, if requested.
1321 if (include_partition
&& relation
->rd_rel
->relispartition
)
1323 /* make sure rel->partition_qual is set */
1324 set_baserel_partition_constraint(relation
, rel
);
1325 result
= list_concat(result
, rel
->partition_qual
);
1328 table_close(relation
, NoLock
);
1334 * Try loading data for the statistics object.
1336 * We don't know if the data (specified by statOid and inh value) exist.
1337 * The result is stored in stainfos list.
1340 get_relation_statistics_worker(List
**stainfos
, RelOptInfo
*rel
,
1341 Oid statOid
, bool inh
,
1342 Bitmapset
*keys
, List
*exprs
)
1344 Form_pg_statistic_ext_data dataForm
;
1347 dtup
= SearchSysCache2(STATEXTDATASTXOID
,
1348 ObjectIdGetDatum(statOid
), BoolGetDatum(inh
));
1349 if (!HeapTupleIsValid(dtup
))
1352 dataForm
= (Form_pg_statistic_ext_data
) GETSTRUCT(dtup
);
1354 /* add one StatisticExtInfo for each kind built */
1355 if (statext_is_kind_built(dtup
, STATS_EXT_NDISTINCT
))
1357 StatisticExtInfo
*info
= makeNode(StatisticExtInfo
);
1359 info
->statOid
= statOid
;
1360 info
->inherit
= dataForm
->stxdinherit
;
1362 info
->kind
= STATS_EXT_NDISTINCT
;
1363 info
->keys
= bms_copy(keys
);
1364 info
->exprs
= exprs
;
1366 *stainfos
= lappend(*stainfos
, info
);
1369 if (statext_is_kind_built(dtup
, STATS_EXT_DEPENDENCIES
))
1371 StatisticExtInfo
*info
= makeNode(StatisticExtInfo
);
1373 info
->statOid
= statOid
;
1374 info
->inherit
= dataForm
->stxdinherit
;
1376 info
->kind
= STATS_EXT_DEPENDENCIES
;
1377 info
->keys
= bms_copy(keys
);
1378 info
->exprs
= exprs
;
1380 *stainfos
= lappend(*stainfos
, info
);
1383 if (statext_is_kind_built(dtup
, STATS_EXT_MCV
))
1385 StatisticExtInfo
*info
= makeNode(StatisticExtInfo
);
1387 info
->statOid
= statOid
;
1388 info
->inherit
= dataForm
->stxdinherit
;
1390 info
->kind
= STATS_EXT_MCV
;
1391 info
->keys
= bms_copy(keys
);
1392 info
->exprs
= exprs
;
1394 *stainfos
= lappend(*stainfos
, info
);
1397 if (statext_is_kind_built(dtup
, STATS_EXT_EXPRESSIONS
))
1399 StatisticExtInfo
*info
= makeNode(StatisticExtInfo
);
1401 info
->statOid
= statOid
;
1402 info
->inherit
= dataForm
->stxdinherit
;
1404 info
->kind
= STATS_EXT_EXPRESSIONS
;
1405 info
->keys
= bms_copy(keys
);
1406 info
->exprs
= exprs
;
1408 *stainfos
= lappend(*stainfos
, info
);
1411 ReleaseSysCache(dtup
);
1415 * get_relation_statistics
1416 * Retrieve extended statistics defined on the table.
1418 * Returns a List (possibly empty) of StatisticExtInfo objects describing
1419 * the statistics. Note that this doesn't load the actual statistics data,
1420 * just the identifying metadata. Only stats actually built are considered.
1423 get_relation_statistics(RelOptInfo
*rel
, Relation relation
)
1425 Index varno
= rel
->relid
;
1427 List
*stainfos
= NIL
;
1430 statoidlist
= RelationGetStatExtList(relation
);
1432 foreach(l
, statoidlist
)
1434 Oid statOid
= lfirst_oid(l
);
1435 Form_pg_statistic_ext staForm
;
1437 Bitmapset
*keys
= NULL
;
1441 htup
= SearchSysCache1(STATEXTOID
, ObjectIdGetDatum(statOid
));
1442 if (!HeapTupleIsValid(htup
))
1443 elog(ERROR
, "cache lookup failed for statistics object %u", statOid
);
1444 staForm
= (Form_pg_statistic_ext
) GETSTRUCT(htup
);
1447 * First, build the array of columns covered. This is ultimately
1448 * wasted if no stats within the object have actually been built, but
1449 * it doesn't seem worth troubling over that case.
1451 for (i
= 0; i
< staForm
->stxkeys
.dim1
; i
++)
1452 keys
= bms_add_member(keys
, staForm
->stxkeys
.values
[i
]);
1455 * Preprocess expressions (if any). We read the expressions, run them
1456 * through eval_const_expressions, and fix the varnos.
1458 * XXX We don't know yet if there are any data for this stats object,
1459 * with either stxdinherit value. But it's reasonable to assume there
1460 * is at least one of those, possibly both. So it's better to process
1461 * keys and expressions here.
1467 /* decode expression (if any) */
1468 datum
= SysCacheGetAttr(STATEXTOID
, htup
,
1469 Anum_pg_statistic_ext_stxexprs
, &isnull
);
1475 exprsString
= TextDatumGetCString(datum
);
1476 exprs
= (List
*) stringToNode(exprsString
);
1480 * Run the expressions through eval_const_expressions. This is
1481 * not just an optimization, but is necessary, because the
1482 * planner will be comparing them to similarly-processed qual
1483 * clauses, and may fail to detect valid matches without this.
1484 * We must not use canonicalize_qual, however, since these
1485 * aren't qual expressions.
1487 exprs
= (List
*) eval_const_expressions(NULL
, (Node
*) exprs
);
1489 /* May as well fix opfuncids too */
1490 fix_opfuncids((Node
*) exprs
);
1493 * Modify the copies we obtain from the relcache to have the
1494 * correct varno for the parent relation, so that they match
1495 * up correctly against qual clauses.
1498 ChangeVarNodes((Node
*) exprs
, 1, varno
, 0);
1502 /* extract statistics for possible values of stxdinherit flag */
1504 get_relation_statistics_worker(&stainfos
, rel
, statOid
, true, keys
, exprs
);
1506 get_relation_statistics_worker(&stainfos
, rel
, statOid
, false, keys
, exprs
);
1508 ReleaseSysCache(htup
);
1512 list_free(statoidlist
);
1518 * relation_excluded_by_constraints
1520 * Detect whether the relation need not be scanned because it has either
1521 * self-inconsistent restrictions, or restrictions inconsistent with the
1522 * relation's applicable constraints.
1524 * Note: this examines only rel->relid, rel->reloptkind, and
1525 * rel->baserestrictinfo; therefore it can be called before filling in
1526 * other fields of the RelOptInfo.
1529 relation_excluded_by_constraints(PlannerInfo
*root
,
1530 RelOptInfo
*rel
, RangeTblEntry
*rte
)
1532 bool include_noinherit
;
1533 bool include_notnull
;
1534 bool include_partition
= false;
1535 List
*safe_restrictions
;
1536 List
*constraint_pred
;
1537 List
*safe_constraints
;
1540 /* As of now, constraint exclusion works only with simple relations. */
1541 Assert(IS_SIMPLE_REL(rel
));
1544 * If there are no base restriction clauses, we have no hope of proving
1545 * anything below, so fall out quickly.
1547 if (rel
->baserestrictinfo
== NIL
)
1551 * Regardless of the setting of constraint_exclusion, detect
1552 * constant-FALSE-or-NULL restriction clauses. Although const-folding
1553 * will reduce "anything AND FALSE" to just "FALSE", the baserestrictinfo
1554 * list can still have other members besides the FALSE constant, due to
1555 * qual pushdown and other mechanisms; so check them all. This doesn't
1556 * fire very often, but it seems cheap enough to be worth doing anyway.
1557 * (Without this, we'd miss some optimizations that 9.5 and earlier found
1558 * via much more roundabout methods.)
1560 foreach(lc
, rel
->baserestrictinfo
)
1562 RestrictInfo
*rinfo
= (RestrictInfo
*) lfirst(lc
);
1563 Expr
*clause
= rinfo
->clause
;
1565 if (clause
&& IsA(clause
, Const
) &&
1566 (((Const
*) clause
)->constisnull
||
1567 !DatumGetBool(((Const
*) clause
)->constvalue
)))
1572 * Skip further tests, depending on constraint_exclusion.
1574 switch (constraint_exclusion
)
1576 case CONSTRAINT_EXCLUSION_OFF
:
1577 /* In 'off' mode, never make any further tests */
1580 case CONSTRAINT_EXCLUSION_PARTITION
:
1583 * When constraint_exclusion is set to 'partition' we only handle
1584 * appendrel members. Partition pruning has already been applied,
1585 * so there is no need to consider the rel's partition constraints
1588 if (rel
->reloptkind
== RELOPT_OTHER_MEMBER_REL
)
1589 break; /* appendrel member, so process it */
1592 case CONSTRAINT_EXCLUSION_ON
:
1595 * In 'on' mode, always apply constraint exclusion. If we are
1596 * considering a baserel that is a partition (i.e., it was
1597 * directly named rather than expanded from a parent table), then
1598 * its partition constraints haven't been considered yet, so
1599 * include them in the processing here.
1601 if (rel
->reloptkind
== RELOPT_BASEREL
)
1602 include_partition
= true;
1603 break; /* always try to exclude */
1607 * Check for self-contradictory restriction clauses. We dare not make
1608 * deductions with non-immutable functions, but any immutable clauses that
1609 * are self-contradictory allow us to conclude the scan is unnecessary.
1611 * Note: strip off RestrictInfo because predicate_refuted_by() isn't
1612 * expecting to see any in its predicate argument.
1614 safe_restrictions
= NIL
;
1615 foreach(lc
, rel
->baserestrictinfo
)
1617 RestrictInfo
*rinfo
= (RestrictInfo
*) lfirst(lc
);
1619 if (!contain_mutable_functions((Node
*) rinfo
->clause
))
1620 safe_restrictions
= lappend(safe_restrictions
, rinfo
->clause
);
1624 * We can use weak refutation here, since we're comparing restriction
1625 * clauses with restriction clauses.
1627 if (predicate_refuted_by(safe_restrictions
, safe_restrictions
, true))
1631 * Only plain relations have constraints, so stop here for other rtekinds.
1633 if (rte
->rtekind
!= RTE_RELATION
)
1637 * If we are scanning just this table, we can use NO INHERIT constraints,
1638 * but not if we're scanning its children too. (Note that partitioned
1639 * tables should never have NO INHERIT constraints; but it's not necessary
1640 * for us to assume that here.)
1642 include_noinherit
= !rte
->inh
;
1645 * Currently, attnotnull constraints must be treated as NO INHERIT unless
1646 * this is a partitioned table. In future we might track their
1647 * inheritance status more accurately, allowing this to be refined.
1649 * XXX do we need/want to change this?
1651 include_notnull
= (!rte
->inh
|| rte
->relkind
== RELKIND_PARTITIONED_TABLE
);
1654 * Fetch the appropriate set of constraint expressions.
1656 constraint_pred
= get_relation_constraints(root
, rte
->relid
, rel
,
1662 * We do not currently enforce that CHECK constraints contain only
1663 * immutable functions, so it's necessary to check here. We daren't draw
1664 * conclusions from plan-time evaluation of non-immutable functions. Since
1665 * they're ANDed, we can just ignore any mutable constraints in the list,
1666 * and reason about the rest.
1668 safe_constraints
= NIL
;
1669 foreach(lc
, constraint_pred
)
1671 Node
*pred
= (Node
*) lfirst(lc
);
1673 if (!contain_mutable_functions(pred
))
1674 safe_constraints
= lappend(safe_constraints
, pred
);
1678 * The constraints are effectively ANDed together, so we can just try to
1679 * refute the entire collection at once. This may allow us to make proofs
1680 * that would fail if we took them individually.
1682 * Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
1683 * an obvious optimization. Some of the clauses might be OR clauses that
1684 * have volatile and nonvolatile subclauses, and it's OK to make
1685 * deductions with the nonvolatile parts.
1687 * We need strong refutation because we have to prove that the constraints
1688 * would yield false, not just NULL.
1690 if (predicate_refuted_by(safe_constraints
, rel
->baserestrictinfo
, false))
1698 * build_physical_tlist
1700 * Build a targetlist consisting of exactly the relation's user attributes,
1701 * in order. The executor can special-case such tlists to avoid a projection
1702 * step at runtime, so we use such tlists preferentially for scan nodes.
1704 * Exception: if there are any dropped or missing columns, we punt and return
1705 * NIL. Ideally we would like to handle these cases too. However this
1706 * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc
1707 * for a tlist that includes vars of no-longer-existent types. In theory we
1708 * could dig out the required info from the pg_attribute entries of the
1709 * relation, but that data is not readily available to ExecTypeFromTL.
1710 * For now, we don't apply the physical-tlist optimization when there are
1713 * We also support building a "physical" tlist for subqueries, functions,
1714 * values lists, table expressions, and CTEs, since the same optimization can
1715 * occur in SubqueryScan, FunctionScan, ValuesScan, CteScan, TableFunc,
1716 * NamedTuplestoreScan, and WorkTableScan nodes.
1719 build_physical_tlist(PlannerInfo
*root
, RelOptInfo
*rel
)
1722 Index varno
= rel
->relid
;
1723 RangeTblEntry
*rte
= planner_rt_fetch(varno
, root
);
1732 switch (rte
->rtekind
)
1735 /* Assume we already have adequate lock */
1736 relation
= table_open(rte
->relid
, NoLock
);
1738 numattrs
= RelationGetNumberOfAttributes(relation
);
1739 for (attrno
= 1; attrno
<= numattrs
; attrno
++)
1741 Form_pg_attribute att_tup
= TupleDescAttr(relation
->rd_att
,
1744 if (att_tup
->attisdropped
|| att_tup
->atthasmissing
)
1746 /* found a dropped or missing col, so punt */
1751 var
= makeVar(varno
,
1755 att_tup
->attcollation
,
1758 tlist
= lappend(tlist
,
1759 makeTargetEntry((Expr
*) var
,
1765 table_close(relation
, NoLock
);
1769 subquery
= rte
->subquery
;
1770 foreach(l
, subquery
->targetList
)
1772 TargetEntry
*tle
= (TargetEntry
*) lfirst(l
);
1775 * A resjunk column of the subquery can be reflected as
1776 * resjunk in the physical tlist; we need not punt.
1778 var
= makeVarFromTargetEntry(varno
, tle
);
1780 tlist
= lappend(tlist
,
1781 makeTargetEntry((Expr
*) var
,
1792 case RTE_NAMEDTUPLESTORE
:
1794 /* Not all of these can have dropped cols, but share code anyway */
1795 expandRTE(rte
, varno
, 0, -1, true /* include dropped */ ,
1799 var
= (Var
*) lfirst(l
);
1802 * A non-Var in expandRTE's output means a dropped column;
1811 tlist
= lappend(tlist
,
1812 makeTargetEntry((Expr
*) var
,
1821 elog(ERROR
, "unsupported RTE kind %d in build_physical_tlist",
1822 (int) rte
->rtekind
);
1832 * Build a targetlist representing the columns of the specified index.
1833 * Each column is represented by a Var for the corresponding base-relation
1834 * column, or an expression in base-relation Vars, as appropriate.
1836 * There are never any dropped columns in indexes, so unlike
1837 * build_physical_tlist, we need no failure case.
1840 build_index_tlist(PlannerInfo
*root
, IndexOptInfo
*index
,
1841 Relation heapRelation
)
1844 Index varno
= index
->rel
->relid
;
1845 ListCell
*indexpr_item
;
1848 indexpr_item
= list_head(index
->indexprs
);
1849 for (i
= 0; i
< index
->ncolumns
; i
++)
1851 int indexkey
= index
->indexkeys
[i
];
1857 const FormData_pg_attribute
*att_tup
;
1860 att_tup
= SystemAttributeDefinition(indexkey
);
1862 att_tup
= TupleDescAttr(heapRelation
->rd_att
, indexkey
- 1);
1864 indexvar
= (Expr
*) makeVar(varno
,
1868 att_tup
->attcollation
,
1873 /* expression column */
1874 if (indexpr_item
== NULL
)
1875 elog(ERROR
, "wrong number of index expressions");
1876 indexvar
= (Expr
*) lfirst(indexpr_item
);
1877 indexpr_item
= lnext(index
->indexprs
, indexpr_item
);
1880 tlist
= lappend(tlist
,
1881 makeTargetEntry(indexvar
,
1886 if (indexpr_item
!= NULL
)
1887 elog(ERROR
, "wrong number of index expressions");
1893 * restriction_selectivity
1895 * Returns the selectivity of a specified restriction operator clause.
1896 * This code executes registered procedures stored in the
1897 * operator relation, by calling the function manager.
1899 * See clause_selectivity() for the meaning of the additional parameters.
1902 restriction_selectivity(PlannerInfo
*root
,
1908 RegProcedure oprrest
= get_oprrest(operatorid
);
1912 * if the oprrest procedure is missing for whatever reason, use a
1913 * selectivity of 0.5
1916 return (Selectivity
) 0.5;
1918 result
= DatumGetFloat8(OidFunctionCall4Coll(oprrest
,
1920 PointerGetDatum(root
),
1921 ObjectIdGetDatum(operatorid
),
1922 PointerGetDatum(args
),
1923 Int32GetDatum(varRelid
)));
1925 if (result
< 0.0 || result
> 1.0)
1926 elog(ERROR
, "invalid restriction selectivity: %f", result
);
1928 return (Selectivity
) result
;
1934 * Returns the selectivity of a specified join operator clause.
1935 * This code executes registered procedures stored in the
1936 * operator relation, by calling the function manager.
1938 * See clause_selectivity() for the meaning of the additional parameters.
1941 join_selectivity(PlannerInfo
*root
,
1946 SpecialJoinInfo
*sjinfo
)
1948 RegProcedure oprjoin
= get_oprjoin(operatorid
);
1952 * if the oprjoin procedure is missing for whatever reason, use a
1953 * selectivity of 0.5
1956 return (Selectivity
) 0.5;
1958 result
= DatumGetFloat8(OidFunctionCall5Coll(oprjoin
,
1960 PointerGetDatum(root
),
1961 ObjectIdGetDatum(operatorid
),
1962 PointerGetDatum(args
),
1963 Int16GetDatum(jointype
),
1964 PointerGetDatum(sjinfo
)));
1966 if (result
< 0.0 || result
> 1.0)
1967 elog(ERROR
, "invalid join selectivity: %f", result
);
1969 return (Selectivity
) result
;
1973 * function_selectivity
1975 * Returns the selectivity of a specified boolean function clause.
1976 * This code executes registered procedures stored in the
1977 * pg_proc relation, by calling the function manager.
1979 * See clause_selectivity() for the meaning of the additional parameters.
1982 function_selectivity(PlannerInfo
*root
,
1989 SpecialJoinInfo
*sjinfo
)
1991 RegProcedure prosupport
= get_func_support(funcid
);
1992 SupportRequestSelectivity req
;
1993 SupportRequestSelectivity
*sresult
;
1996 * If no support function is provided, use our historical default
1997 * estimate, 0.3333333. This seems a pretty unprincipled choice, but
1998 * Postgres has been using that estimate for function calls since 1992.
1999 * The hoariness of this behavior suggests that we should not be in too
2000 * much hurry to use another value.
2003 return (Selectivity
) 0.3333333;
2005 req
.type
= T_SupportRequestSelectivity
;
2007 req
.funcid
= funcid
;
2009 req
.inputcollid
= inputcollid
;
2010 req
.is_join
= is_join
;
2011 req
.varRelid
= varRelid
;
2012 req
.jointype
= jointype
;
2013 req
.sjinfo
= sjinfo
;
2014 req
.selectivity
= -1; /* to catch failure to set the value */
2016 sresult
= (SupportRequestSelectivity
*)
2017 DatumGetPointer(OidFunctionCall1(prosupport
,
2018 PointerGetDatum(&req
)));
2020 /* If support function fails, use default */
2021 if (sresult
!= &req
)
2022 return (Selectivity
) 0.3333333;
2024 if (req
.selectivity
< 0.0 || req
.selectivity
> 1.0)
2025 elog(ERROR
, "invalid function selectivity: %f", req
.selectivity
);
2027 return (Selectivity
) req
.selectivity
;
2033 * Get an estimate of the execution cost of a function, and *add* it to
2034 * the contents of *cost. The estimate may include both one-time and
2035 * per-tuple components, since QualCost does.
2037 * The funcid must always be supplied. If it is being called as the
2038 * implementation of a specific parsetree node (FuncExpr, OpExpr,
2039 * WindowFunc, etc), pass that as "node", else pass NULL.
2041 * In some usages root might be NULL, too.
2044 add_function_cost(PlannerInfo
*root
, Oid funcid
, Node
*node
,
2048 Form_pg_proc procform
;
2050 proctup
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
2051 if (!HeapTupleIsValid(proctup
))
2052 elog(ERROR
, "cache lookup failed for function %u", funcid
);
2053 procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
2055 if (OidIsValid(procform
->prosupport
))
2057 SupportRequestCost req
;
2058 SupportRequestCost
*sresult
;
2060 req
.type
= T_SupportRequestCost
;
2062 req
.funcid
= funcid
;
2065 /* Initialize cost fields so that support function doesn't have to */
2069 sresult
= (SupportRequestCost
*)
2070 DatumGetPointer(OidFunctionCall1(procform
->prosupport
,
2071 PointerGetDatum(&req
)));
2073 if (sresult
== &req
)
2075 /* Success, so accumulate support function's estimate into *cost */
2076 cost
->startup
+= req
.startup
;
2077 cost
->per_tuple
+= req
.per_tuple
;
2078 ReleaseSysCache(proctup
);
2083 /* No support function, or it failed, so rely on procost */
2084 cost
->per_tuple
+= procform
->procost
* cpu_operator_cost
;
2086 ReleaseSysCache(proctup
);
2092 * Get an estimate of the number of rows returned by a set-returning function.
2094 * The funcid must always be supplied. In current usage, the calling node
2095 * will always be supplied, and will be either a FuncExpr or OpExpr.
2096 * But it's a good idea to not fail if it's NULL.
2098 * In some usages root might be NULL, too.
2100 * Note: this returns the unfiltered result of the support function, if any.
2101 * It's usually a good idea to apply clamp_row_est() to the result, but we
2102 * leave it to the caller to do so.
2105 get_function_rows(PlannerInfo
*root
, Oid funcid
, Node
*node
)
2108 Form_pg_proc procform
;
2111 proctup
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
2112 if (!HeapTupleIsValid(proctup
))
2113 elog(ERROR
, "cache lookup failed for function %u", funcid
);
2114 procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
2116 Assert(procform
->proretset
); /* else caller error */
2118 if (OidIsValid(procform
->prosupport
))
2120 SupportRequestRows req
;
2121 SupportRequestRows
*sresult
;
2123 req
.type
= T_SupportRequestRows
;
2125 req
.funcid
= funcid
;
2128 req
.rows
= 0; /* just for sanity */
2130 sresult
= (SupportRequestRows
*)
2131 DatumGetPointer(OidFunctionCall1(procform
->prosupport
,
2132 PointerGetDatum(&req
)));
2134 if (sresult
== &req
)
2137 ReleaseSysCache(proctup
);
2142 /* No support function, or it failed, so rely on prorows */
2143 result
= procform
->prorows
;
2145 ReleaseSysCache(proctup
);
2153 * Detect whether there is a unique index on the specified attribute
2154 * of the specified relation, thus allowing us to conclude that all
2155 * the (non-null) values of the attribute are distinct.
2157 * This function does not check the index's indimmediate property, which
2158 * means that uniqueness may transiently fail to hold intra-transaction.
2159 * That's appropriate when we are making statistical estimates, but beware
2160 * of using this for any correctness proofs.
2163 has_unique_index(RelOptInfo
*rel
, AttrNumber attno
)
2167 foreach(ilist
, rel
->indexlist
)
2169 IndexOptInfo
*index
= (IndexOptInfo
*) lfirst(ilist
);
2172 * Note: ignore partial indexes, since they don't allow us to conclude
2173 * that all attr values are distinct, *unless* they are marked predOK
2174 * which means we know the index's predicate is satisfied by the
2175 * query. We don't take any interest in expressional indexes either.
2176 * Also, a multicolumn unique index doesn't allow us to conclude that
2177 * just the specified attr is unique.
2179 if (index
->unique
&&
2180 index
->nkeycolumns
== 1 &&
2181 index
->indexkeys
[0] == attno
&&
2182 (index
->indpred
== NIL
|| index
->predOK
))
2192 * Detect whether the specified relation has any row-level triggers for event.
2195 has_row_triggers(PlannerInfo
*root
, Index rti
, CmdType event
)
2197 RangeTblEntry
*rte
= planner_rt_fetch(rti
, root
);
2199 TriggerDesc
*trigDesc
;
2200 bool result
= false;
2202 /* Assume we already have adequate lock */
2203 relation
= table_open(rte
->relid
, NoLock
);
2205 trigDesc
= relation
->trigdesc
;
2210 (trigDesc
->trig_insert_after_row
||
2211 trigDesc
->trig_insert_before_row
))
2216 (trigDesc
->trig_update_after_row
||
2217 trigDesc
->trig_update_before_row
))
2222 (trigDesc
->trig_delete_after_row
||
2223 trigDesc
->trig_delete_before_row
))
2226 /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
2231 elog(ERROR
, "unrecognized CmdType: %d", (int) event
);
2235 table_close(relation
, NoLock
);
2240 * has_stored_generated_columns
2242 * Does table identified by RTI have any STORED GENERATED columns?
2245 has_stored_generated_columns(PlannerInfo
*root
, Index rti
)
2247 RangeTblEntry
*rte
= planner_rt_fetch(rti
, root
);
2250 bool result
= false;
2252 /* Assume we already have adequate lock */
2253 relation
= table_open(rte
->relid
, NoLock
);
2255 tupdesc
= RelationGetDescr(relation
);
2256 result
= tupdesc
->constr
&& tupdesc
->constr
->has_generated_stored
;
2258 table_close(relation
, NoLock
);
2264 * get_dependent_generated_columns
2266 * Get the column numbers of any STORED GENERATED columns of the relation
2267 * that depend on any column listed in target_cols. Both the input and
2268 * result bitmapsets contain column numbers offset by
2269 * FirstLowInvalidHeapAttributeNumber.
2272 get_dependent_generated_columns(PlannerInfo
*root
, Index rti
,
2273 Bitmapset
*target_cols
)
2275 Bitmapset
*dependentCols
= NULL
;
2276 RangeTblEntry
*rte
= planner_rt_fetch(rti
, root
);
2279 TupleConstr
*constr
;
2281 /* Assume we already have adequate lock */
2282 relation
= table_open(rte
->relid
, NoLock
);
2284 tupdesc
= RelationGetDescr(relation
);
2285 constr
= tupdesc
->constr
;
2287 if (constr
&& constr
->has_generated_stored
)
2289 for (int i
= 0; i
< constr
->num_defval
; i
++)
2291 AttrDefault
*defval
= &constr
->defval
[i
];
2293 Bitmapset
*attrs_used
= NULL
;
2295 /* skip if not generated column */
2296 if (!TupleDescAttr(tupdesc
, defval
->adnum
- 1)->attgenerated
)
2299 /* identify columns this generated column depends on */
2300 expr
= stringToNode(defval
->adbin
);
2301 pull_varattnos(expr
, 1, &attrs_used
);
2303 if (bms_overlap(target_cols
, attrs_used
))
2304 dependentCols
= bms_add_member(dependentCols
,
2305 defval
->adnum
- FirstLowInvalidHeapAttributeNumber
);
2309 table_close(relation
, NoLock
);
2311 return dependentCols
;
2315 * set_relation_partition_info
2317 * Set partitioning scheme and related information for a partitioned table.
2320 set_relation_partition_info(PlannerInfo
*root
, RelOptInfo
*rel
,
2323 PartitionDesc partdesc
;
2326 * Create the PartitionDirectory infrastructure if we didn't already.
2328 if (root
->glob
->partition_directory
== NULL
)
2330 root
->glob
->partition_directory
=
2331 CreatePartitionDirectory(CurrentMemoryContext
, true);
2334 partdesc
= PartitionDirectoryLookup(root
->glob
->partition_directory
,
2336 rel
->part_scheme
= find_partition_scheme(root
, relation
);
2337 Assert(partdesc
!= NULL
&& rel
->part_scheme
!= NULL
);
2338 rel
->boundinfo
= partdesc
->boundinfo
;
2339 rel
->nparts
= partdesc
->nparts
;
2340 set_baserel_partition_key_exprs(relation
, rel
);
2341 set_baserel_partition_constraint(relation
, rel
);
2345 * find_partition_scheme
2347 * Find or create a PartitionScheme for this Relation.
2349 static PartitionScheme
2350 find_partition_scheme(PlannerInfo
*root
, Relation relation
)
2352 PartitionKey partkey
= RelationGetPartitionKey(relation
);
2356 PartitionScheme part_scheme
;
2358 /* A partitioned table should have a partition key. */
2359 Assert(partkey
!= NULL
);
2361 partnatts
= partkey
->partnatts
;
2363 /* Search for a matching partition scheme and return if found one. */
2364 foreach(lc
, root
->part_schemes
)
2366 part_scheme
= lfirst(lc
);
2368 /* Match partitioning strategy and number of keys. */
2369 if (partkey
->strategy
!= part_scheme
->strategy
||
2370 partnatts
!= part_scheme
->partnatts
)
2373 /* Match partition key type properties. */
2374 if (memcmp(partkey
->partopfamily
, part_scheme
->partopfamily
,
2375 sizeof(Oid
) * partnatts
) != 0 ||
2376 memcmp(partkey
->partopcintype
, part_scheme
->partopcintype
,
2377 sizeof(Oid
) * partnatts
) != 0 ||
2378 memcmp(partkey
->partcollation
, part_scheme
->partcollation
,
2379 sizeof(Oid
) * partnatts
) != 0)
2383 * Length and byval information should match when partopcintype
2386 Assert(memcmp(partkey
->parttyplen
, part_scheme
->parttyplen
,
2387 sizeof(int16
) * partnatts
) == 0);
2388 Assert(memcmp(partkey
->parttypbyval
, part_scheme
->parttypbyval
,
2389 sizeof(bool) * partnatts
) == 0);
2392 * If partopfamily and partopcintype matched, must have the same
2393 * partition comparison functions. Note that we cannot reliably
2394 * Assert the equality of function structs themselves for they might
2395 * be different across PartitionKey's, so just Assert for the function
2398 #ifdef USE_ASSERT_CHECKING
2399 for (i
= 0; i
< partkey
->partnatts
; i
++)
2400 Assert(partkey
->partsupfunc
[i
].fn_oid
==
2401 part_scheme
->partsupfunc
[i
].fn_oid
);
2404 /* Found matching partition scheme. */
2409 * Did not find matching partition scheme. Create one copying relevant
2410 * information from the relcache. We need to copy the contents of the
2411 * array since the relcache entry may not survive after we have closed the
2414 part_scheme
= (PartitionScheme
) palloc0(sizeof(PartitionSchemeData
));
2415 part_scheme
->strategy
= partkey
->strategy
;
2416 part_scheme
->partnatts
= partkey
->partnatts
;
2418 part_scheme
->partopfamily
= (Oid
*) palloc(sizeof(Oid
) * partnatts
);
2419 memcpy(part_scheme
->partopfamily
, partkey
->partopfamily
,
2420 sizeof(Oid
) * partnatts
);
2422 part_scheme
->partopcintype
= (Oid
*) palloc(sizeof(Oid
) * partnatts
);
2423 memcpy(part_scheme
->partopcintype
, partkey
->partopcintype
,
2424 sizeof(Oid
) * partnatts
);
2426 part_scheme
->partcollation
= (Oid
*) palloc(sizeof(Oid
) * partnatts
);
2427 memcpy(part_scheme
->partcollation
, partkey
->partcollation
,
2428 sizeof(Oid
) * partnatts
);
2430 part_scheme
->parttyplen
= (int16
*) palloc(sizeof(int16
) * partnatts
);
2431 memcpy(part_scheme
->parttyplen
, partkey
->parttyplen
,
2432 sizeof(int16
) * partnatts
);
2434 part_scheme
->parttypbyval
= (bool *) palloc(sizeof(bool) * partnatts
);
2435 memcpy(part_scheme
->parttypbyval
, partkey
->parttypbyval
,
2436 sizeof(bool) * partnatts
);
2438 part_scheme
->partsupfunc
= (FmgrInfo
*)
2439 palloc(sizeof(FmgrInfo
) * partnatts
);
2440 for (i
= 0; i
< partnatts
; i
++)
2441 fmgr_info_copy(&part_scheme
->partsupfunc
[i
], &partkey
->partsupfunc
[i
],
2442 CurrentMemoryContext
);
2444 /* Add the partitioning scheme to PlannerInfo. */
2445 root
->part_schemes
= lappend(root
->part_schemes
, part_scheme
);
2451 * set_baserel_partition_key_exprs
2453 * Builds partition key expressions for the given base relation and fills
2457 set_baserel_partition_key_exprs(Relation relation
,
2460 PartitionKey partkey
= RelationGetPartitionKey(relation
);
2465 Index varno
= rel
->relid
;
2467 Assert(IS_SIMPLE_REL(rel
) && rel
->relid
> 0);
2469 /* A partitioned table should have a partition key. */
2470 Assert(partkey
!= NULL
);
2472 partnatts
= partkey
->partnatts
;
2473 partexprs
= (List
**) palloc(sizeof(List
*) * partnatts
);
2474 lc
= list_head(partkey
->partexprs
);
2476 for (cnt
= 0; cnt
< partnatts
; cnt
++)
2479 AttrNumber attno
= partkey
->partattrs
[cnt
];
2481 if (attno
!= InvalidAttrNumber
)
2483 /* Single column partition key is stored as a Var node. */
2486 partexpr
= (Expr
*) makeVar(varno
, attno
,
2487 partkey
->parttypid
[cnt
],
2488 partkey
->parttypmod
[cnt
],
2489 partkey
->parttypcoll
[cnt
], 0);
2494 elog(ERROR
, "wrong number of partition key expressions");
2496 /* Re-stamp the expression with given varno. */
2497 partexpr
= (Expr
*) copyObject(lfirst(lc
));
2498 ChangeVarNodes((Node
*) partexpr
, 1, varno
, 0);
2499 lc
= lnext(partkey
->partexprs
, lc
);
2502 /* Base relations have a single expression per key. */
2503 partexprs
[cnt
] = list_make1(partexpr
);
2506 rel
->partexprs
= partexprs
;
2509 * A base relation does not have nullable partition key expressions, since
2510 * no outer join is involved. We still allocate an array of empty
2511 * expression lists to keep partition key expression handling code simple.
2512 * See build_joinrel_partition_info() and match_expr_to_partition_keys().
2514 rel
->nullable_partexprs
= (List
**) palloc0(sizeof(List
*) * partnatts
);
2518 * set_baserel_partition_constraint
2520 * Builds the partition constraint for the given base relation and sets it
2521 * in the given RelOptInfo. All Var nodes are restamped with the relid of the
2525 set_baserel_partition_constraint(Relation relation
, RelOptInfo
*rel
)
2529 if (rel
->partition_qual
) /* already done */
2533 * Run the partition quals through const-simplification similar to check
2534 * constraints. We skip canonicalize_qual, though, because partition
2535 * quals should be in canonical form already; also, since the qual is in
2536 * implicit-AND format, we'd have to explicitly convert it to explicit-AND
2537 * format and back again.
2539 partconstr
= RelationGetPartitionQual(relation
);
2542 partconstr
= (List
*) expression_planner((Expr
*) partconstr
);
2543 if (rel
->relid
!= 1)
2544 ChangeVarNodes((Node
*) partconstr
, 1, rel
->relid
, 0);
2545 rel
->partition_qual
= partconstr
;