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