1 /*-------------------------------------------------------------------------
4 * routines for accessing the system catalogs
7 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.152 2008/10/04 21:56:53 tgl Exp $
14 *-------------------------------------------------------------------------
20 #include "access/genam.h"
21 #include "access/heapam.h"
22 #include "access/sysattr.h"
23 #include "access/transam.h"
24 #include "catalog/catalog.h"
25 #include "catalog/pg_inherits.h"
26 #include "miscadmin.h"
27 #include "nodes/makefuncs.h"
28 #include "nodes/nodeFuncs.h"
29 #include "optimizer/clauses.h"
30 #include "optimizer/plancat.h"
31 #include "optimizer/predtest.h"
32 #include "optimizer/prep.h"
33 #include "parser/parse_relation.h"
34 #include "parser/parsetree.h"
35 #include "rewrite/rewriteManip.h"
36 #include "storage/bufmgr.h"
37 #include "utils/fmgroids.h"
38 #include "utils/lsyscache.h"
39 #include "utils/rel.h"
40 #include "utils/snapmgr.h"
41 #include "utils/syscache.h"
42 #include "utils/tqual.h"
46 bool constraint_exclusion = false;
48 /* Hook for plugins to get control in get_relation_info() */
49 get_relation_info_hook_type get_relation_info_hook = NULL;
52 static List *get_relation_constraints(PlannerInfo *root,
53 Oid relationObjectId, RelOptInfo *rel,
54 bool include_notnull);
59 * Retrieves catalog information for a given relation.
61 * Given the Oid of the relation, return the following info into fields
62 * of the RelOptInfo struct:
64 * min_attr lowest valid AttrNumber
65 * max_attr highest valid AttrNumber
66 * indexlist list of IndexOptInfos for relation's indexes
67 * pages number of pages
68 * tuples number of tuples
70 * Also, initialize the attr_needed[] and attr_widths[] arrays. In most
71 * cases these are left as zeroes, but sometimes we need to compute attr
72 * widths here, and we may as well cache the results for costsize.c.
74 * If inhparent is true, all we need to do is set up the attr arrays:
75 * the RelOptInfo actually represents the appendrel formed by an inheritance
76 * tree, and so the parent rel's physical size and index information isn't
80 get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
83 Index varno = rel->relid;
86 List *indexinfos = NIL;
89 * We need not lock the relation since it was already locked, either by
90 * the rewriter or when expand_inherited_rtentry() added it to the query's
93 relation = heap_open(relationObjectId, NoLock);
95 rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
96 rel->max_attr = RelationGetNumberOfAttributes(relation);
98 Assert(rel->max_attr >= rel->min_attr);
99 rel->attr_needed = (Relids *)
100 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
101 rel->attr_widths = (int32 *)
102 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
105 * Estimate relation size --- unless it's an inheritance parent, in which
106 * case the size will be computed later in set_append_rel_pathlist, and we
107 * must leave it zero for now to avoid bollixing the total_table_pages
111 estimate_rel_size(relation, rel->attr_widths - rel->min_attr,
112 &rel->pages, &rel->tuples);
115 * Make list of indexes. Ignore indexes on system catalogs if told to.
116 * Don't bother with indexes for an inheritance parent, either.
119 (IgnoreSystemIndexes && IsSystemClass(relation->rd_rel)))
122 hasindex = relation->rd_rel->relhasindex;
130 indexoidlist = RelationGetIndexList(relation);
133 * For each index, we get the same type of lock that the executor will
134 * need, and do not release it. This saves a couple of trips to the
135 * shared lock manager while not creating any real loss of
136 * concurrency, because no schema changes could be happening on the
137 * index while we hold lock on the parent rel, and neither lock type
138 * blocks any other kind of index operation.
140 if (rel->relid == root->parse->resultRelation)
141 lmode = RowExclusiveLock;
143 lmode = AccessShareLock;
145 foreach(l, indexoidlist)
147 Oid indexoid = lfirst_oid(l);
148 Relation indexRelation;
155 * Extract info from the relation descriptor for the index.
157 indexRelation = index_open(indexoid, lmode);
158 index = indexRelation->rd_index;
161 * Ignore invalid indexes, since they can't safely be used for
162 * queries. Note that this is OK because the data structure we
163 * are constructing is only used by the planner --- the executor
164 * still needs to insert into "invalid" indexes!
166 if (!index->indisvalid)
168 index_close(indexRelation, NoLock);
173 * If the index is valid, but cannot yet be used, ignore it; but
174 * mark the plan we are generating as transient. See
175 * src/backend/access/heap/README.HOT for discussion.
177 if (index->indcheckxmin &&
178 !TransactionIdPrecedes(HeapTupleHeaderGetXmin(indexRelation->rd_indextuple->t_data),
181 root->glob->transientPlan = true;
182 index_close(indexRelation, NoLock);
186 info = makeNode(IndexOptInfo);
188 info->indexoid = index->indexrelid;
190 info->ncolumns = ncolumns = index->indnatts;
193 * Allocate per-column info arrays. To save a few palloc cycles
194 * we allocate all the Oid-type arrays in one request. Note that
195 * the opfamily array needs an extra, terminating zero at the end.
196 * We pre-zero the ordering info in case the index is unordered.
198 info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
199 info->opfamily = (Oid *) palloc0(sizeof(Oid) * (4 * ncolumns + 1));
200 info->opcintype = info->opfamily + (ncolumns + 1);
201 info->fwdsortop = info->opcintype + ncolumns;
202 info->revsortop = info->fwdsortop + ncolumns;
203 info->nulls_first = (bool *) palloc0(sizeof(bool) * ncolumns);
205 for (i = 0; i < ncolumns; i++)
207 info->indexkeys[i] = index->indkey.values[i];
208 info->opfamily[i] = indexRelation->rd_opfamily[i];
209 info->opcintype[i] = indexRelation->rd_opcintype[i];
212 info->relam = indexRelation->rd_rel->relam;
213 info->amcostestimate = indexRelation->rd_am->amcostestimate;
214 info->amoptionalkey = indexRelation->rd_am->amoptionalkey;
215 info->amsearchnulls = indexRelation->rd_am->amsearchnulls;
218 * Fetch the ordering operators associated with the index, if any.
219 * We expect that all ordering-capable indexes use btree's
220 * strategy numbers for the ordering operators.
222 if (indexRelation->rd_am->amcanorder)
224 int nstrat = indexRelation->rd_am->amstrategies;
226 for (i = 0; i < ncolumns; i++)
228 int16 opt = indexRelation->rd_indoption[i];
232 if (opt & INDOPTION_DESC)
234 fwdstrat = BTGreaterStrategyNumber;
235 revstrat = BTLessStrategyNumber;
239 fwdstrat = BTLessStrategyNumber;
240 revstrat = BTGreaterStrategyNumber;
244 * Index AM must have a fixed set of strategies for it to
245 * make sense to specify amcanorder, so we need not allow
246 * the case amstrategies == 0.
250 Assert(fwdstrat <= nstrat);
251 info->fwdsortop[i] = indexRelation->rd_operator[i * nstrat + fwdstrat - 1];
255 Assert(revstrat <= nstrat);
256 info->revsortop[i] = indexRelation->rd_operator[i * nstrat + revstrat - 1];
258 info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
263 * Fetch the index expressions and predicate, if any. We must
264 * modify the copies we obtain from the relcache to have the
265 * correct varno for the parent relation, so that they match up
266 * correctly against qual clauses.
268 info->indexprs = RelationGetIndexExpressions(indexRelation);
269 info->indpred = RelationGetIndexPredicate(indexRelation);
270 if (info->indexprs && varno != 1)
271 ChangeVarNodes((Node *) info->indexprs, 1, varno, 0);
272 if (info->indpred && varno != 1)
273 ChangeVarNodes((Node *) info->indpred, 1, varno, 0);
274 info->predOK = false; /* set later in indxpath.c */
275 info->unique = index->indisunique;
278 * Estimate the index size. If it's not a partial index, we lock
279 * the number-of-tuples estimate to equal the parent table; if it
280 * is partial then we have to use the same methods as we would for
281 * a table, except we can be sure that the index is not larger
284 if (info->indpred == NIL)
286 info->pages = RelationGetNumberOfBlocks(indexRelation);
287 info->tuples = rel->tuples;
291 estimate_rel_size(indexRelation, NULL,
292 &info->pages, &info->tuples);
293 if (info->tuples > rel->tuples)
294 info->tuples = rel->tuples;
297 index_close(indexRelation, NoLock);
299 indexinfos = lcons(info, indexinfos);
302 list_free(indexoidlist);
305 rel->indexlist = indexinfos;
307 heap_close(relation, NoLock);
310 * Allow a plugin to editorialize on the info we obtained from the
311 * catalogs. Actions might include altering the assumed relation size,
312 * removing an index, or adding a hypothetical index to the indexlist.
314 if (get_relation_info_hook)
315 (*get_relation_info_hook) (root, relationObjectId, inhparent, rel);
319 * estimate_rel_size - estimate # pages and # tuples in a table or index
321 * If attr_widths isn't NULL, it points to the zero-index entry of the
322 * relation's attr_width[] cache; we fill this in if we have need to compute
323 * the attribute widths for estimation purposes.
326 estimate_rel_size(Relation rel, int32 *attr_widths,
327 BlockNumber *pages, double *tuples)
329 BlockNumber curpages;
330 BlockNumber relpages;
334 switch (rel->rd_rel->relkind)
336 case RELKIND_RELATION:
338 case RELKIND_TOASTVALUE:
339 /* it has storage, ok to call the smgr */
340 curpages = RelationGetNumberOfBlocks(rel);
343 * HACK: if the relation has never yet been vacuumed, use a
344 * minimum estimate of 10 pages. This emulates a desirable aspect
345 * of pre-8.0 behavior, which is that we wouldn't assume a newly
346 * created relation is really small, which saves us from making
347 * really bad plans during initial data loading. (The plans are
348 * not wrong when they are made, but if they are cached and used
349 * again after the table has grown a lot, they are bad.) It would
350 * be better to force replanning if the table size has changed a
351 * lot since the plan was made ... but we don't currently have any
352 * infrastructure for redoing cached plans at all, so we have to
353 * kluge things here instead.
355 * We approximate "never vacuumed" by "has relpages = 0", which
356 * means this will also fire on genuinely empty relations. Not
357 * great, but fortunately that's a seldom-seen case in the real
358 * world, and it shouldn't degrade the quality of the plan too
359 * much anyway to err in this direction.
361 if (curpages < 10 && rel->rd_rel->relpages == 0)
364 /* report estimated # pages */
366 /* quick exit if rel is clearly empty */
372 /* coerce values in pg_class to more desirable types */
373 relpages = (BlockNumber) rel->rd_rel->relpages;
374 reltuples = (double) rel->rd_rel->reltuples;
377 * If it's an index, discount the metapage. This is a kluge
378 * because it assumes more than it ought to about index contents;
379 * it's reasonably OK for btrees but a bit suspect otherwise.
381 if (rel->rd_rel->relkind == RELKIND_INDEX &&
387 /* estimate number of tuples from previous tuple density */
389 density = reltuples / (double) relpages;
393 * When we have no data because the relation was truncated,
394 * estimate tuple width from attribute datatypes. We assume
395 * here that the pages are completely full, which is OK for
396 * tables (since they've presumably not been VACUUMed yet) but
397 * is probably an overestimate for indexes. Fortunately
398 * get_relation_info() can clamp the overestimate to the
399 * parent table's size.
401 * Note: this code intentionally disregards alignment
402 * considerations, because (a) that would be gilding the lily
403 * considering how crude the estimate is, and (b) it creates
404 * platform dependencies in the default plans which are kind
405 * of a headache for regression testing.
407 int32 tuple_width = 0;
410 for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++)
412 Form_pg_attribute att = rel->rd_att->attrs[i - 1];
415 if (att->attisdropped)
417 /* This should match set_rel_width() in costsize.c */
418 item_width = get_attavgwidth(RelationGetRelid(rel), i);
421 item_width = get_typavgwidth(att->atttypid,
423 Assert(item_width > 0);
425 if (attr_widths != NULL)
426 attr_widths[i] = item_width;
427 tuple_width += item_width;
429 tuple_width += sizeof(HeapTupleHeaderData);
430 tuple_width += sizeof(ItemPointerData);
431 /* note: integer division is intentional here */
432 density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;
434 *tuples = rint(density * (double) curpages);
436 case RELKIND_SEQUENCE:
437 /* Sequences always have a known size */
442 /* else it has no disk storage; probably shouldn't get here? */
451 * get_relation_constraints
453 * Retrieve the CHECK constraint expressions of the given relation.
455 * Returns a List (possibly empty) of constraint expressions. Each one
456 * has been canonicalized, and its Vars are changed to have the varno
457 * indicated by rel->relid. This allows the expressions to be easily
458 * compared to expressions taken from WHERE.
460 * If include_notnull is true, "col IS NOT NULL" expressions are generated
461 * and added to the result for each column that's marked attnotnull.
463 * Note: at present this is invoked at most once per relation per planner
464 * run, and in many cases it won't be invoked at all, so there seems no
465 * point in caching the data in RelOptInfo.
468 get_relation_constraints(PlannerInfo *root,
469 Oid relationObjectId, RelOptInfo *rel,
470 bool include_notnull)
473 Index varno = rel->relid;
478 * We assume the relation has already been safely locked.
480 relation = heap_open(relationObjectId, NoLock);
482 constr = relation->rd_att->constr;
485 int num_check = constr->num_check;
488 for (i = 0; i < num_check; i++)
492 cexpr = stringToNode(constr->check[i].ccbin);
495 * Run each expression through const-simplification and
496 * canonicalization. This is not just an optimization, but is
497 * necessary, because we will be comparing it to
498 * similarly-processed qual clauses, and may fail to detect valid
499 * matches without this. This must match the processing done to
500 * qual clauses in preprocess_expression()! (We can skip the
501 * stuff involving subqueries, however, since we don't allow any
502 * in check constraints.)
504 cexpr = eval_const_expressions(root, cexpr);
506 cexpr = (Node *) canonicalize_qual((Expr *) cexpr);
509 * Also mark any coercion format fields as "don't care", so that
510 * we can match to both explicit and implicit coercions.
512 set_coercionform_dontcare(cexpr);
514 /* Fix Vars to have the desired varno */
516 ChangeVarNodes(cexpr, 1, varno, 0);
519 * Finally, convert to implicit-AND format (that is, a List) and
520 * append the resulting item(s) to our output list.
522 result = list_concat(result,
523 make_ands_implicit((Expr *) cexpr));
526 /* Add NOT NULL constraints in expression form, if requested */
527 if (include_notnull && constr->has_not_null)
529 int natts = relation->rd_att->natts;
531 for (i = 1; i <= natts; i++)
533 Form_pg_attribute att = relation->rd_att->attrs[i - 1];
535 if (att->attnotnull && !att->attisdropped)
537 NullTest *ntest = makeNode(NullTest);
539 ntest->arg = (Expr *) makeVar(varno,
544 ntest->nulltesttype = IS_NOT_NULL;
545 result = lappend(result, ntest);
551 heap_close(relation, NoLock);
558 * relation_excluded_by_constraints
560 * Detect whether the relation need not be scanned because it has either
561 * self-inconsistent restrictions, or restrictions inconsistent with the
562 * relation's CHECK constraints.
564 * Note: this examines only rel->relid and rel->baserestrictinfo; therefore
565 * it can be called before filling in other fields of the RelOptInfo.
568 relation_excluded_by_constraints(PlannerInfo *root,
569 RelOptInfo *rel, RangeTblEntry *rte)
571 List *safe_restrictions;
572 List *constraint_pred;
573 List *safe_constraints;
576 /* Skip the test if constraint exclusion is disabled */
577 if (!constraint_exclusion)
581 * Check for self-contradictory restriction clauses. We dare not make
582 * deductions with non-immutable functions, but any immutable clauses that
583 * are self-contradictory allow us to conclude the scan is unnecessary.
585 * Note: strip off RestrictInfo because predicate_refuted_by() isn't
586 * expecting to see any in its predicate argument.
588 safe_restrictions = NIL;
589 foreach(lc, rel->baserestrictinfo)
591 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
593 if (!contain_mutable_functions((Node *) rinfo->clause))
594 safe_restrictions = lappend(safe_restrictions, rinfo->clause);
597 if (predicate_refuted_by(safe_restrictions, safe_restrictions))
600 /* Only plain relations have constraints */
601 if (rte->rtekind != RTE_RELATION || rte->inh)
605 * OK to fetch the constraint expressions. Include "col IS NOT NULL"
606 * expressions for attnotnull columns, in case we can refute those.
608 constraint_pred = get_relation_constraints(root, rte->relid, rel, true);
611 * We do not currently enforce that CHECK constraints contain only
612 * immutable functions, so it's necessary to check here. We daren't draw
613 * conclusions from plan-time evaluation of non-immutable functions. Since
614 * they're ANDed, we can just ignore any mutable constraints in the list,
615 * and reason about the rest.
617 safe_constraints = NIL;
618 foreach(lc, constraint_pred)
620 Node *pred = (Node *) lfirst(lc);
622 if (!contain_mutable_functions(pred))
623 safe_constraints = lappend(safe_constraints, pred);
627 * The constraints are effectively ANDed together, so we can just try to
628 * refute the entire collection at once. This may allow us to make proofs
629 * that would fail if we took them individually.
631 * Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
632 * an obvious optimization. Some of the clauses might be OR clauses that
633 * have volatile and nonvolatile subclauses, and it's OK to make
634 * deductions with the nonvolatile parts.
636 if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo))
644 * build_physical_tlist
646 * Build a targetlist consisting of exactly the relation's user attributes,
647 * in order. The executor can special-case such tlists to avoid a projection
648 * step at runtime, so we use such tlists preferentially for scan nodes.
650 * Exception: if there are any dropped columns, we punt and return NIL.
651 * Ideally we would like to handle the dropped-column case too. However this
652 * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc
653 * for a tlist that includes vars of no-longer-existent types. In theory we
654 * could dig out the required info from the pg_attribute entries of the
655 * relation, but that data is not readily available to ExecTypeFromTL.
656 * For now, we don't apply the physical-tlist optimization when there are
659 * We also support building a "physical" tlist for subqueries, functions,
660 * values lists, and CTEs, since the same optimization can occur in
661 * SubqueryScan, FunctionScan, ValuesScan, CteScan, and WorkTableScan nodes.
664 build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
667 Index varno = rel->relid;
668 RangeTblEntry *rte = planner_rt_fetch(varno, root);
677 switch (rte->rtekind)
680 /* Assume we already have adequate lock */
681 relation = heap_open(rte->relid, NoLock);
683 numattrs = RelationGetNumberOfAttributes(relation);
684 for (attrno = 1; attrno <= numattrs; attrno++)
686 Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
688 if (att_tup->attisdropped)
690 /* found a dropped col, so punt */
701 tlist = lappend(tlist,
702 makeTargetEntry((Expr *) var,
708 heap_close(relation, NoLock);
712 subquery = rte->subquery;
713 foreach(l, subquery->targetList)
715 TargetEntry *tle = (TargetEntry *) lfirst(l);
718 * A resjunk column of the subquery can be reflected as
719 * resjunk in the physical tlist; we need not punt.
723 exprType((Node *) tle->expr),
724 exprTypmod((Node *) tle->expr),
727 tlist = lappend(tlist,
728 makeTargetEntry((Expr *) var,
738 /* Not all of these can have dropped cols, but share code anyway */
739 expandRTE(rte, varno, 0, -1, true /* include dropped */ ,
743 var = (Var *) lfirst(l);
746 * A non-Var in expandRTE's output means a dropped column;
755 tlist = lappend(tlist,
756 makeTargetEntry((Expr *) var,
765 elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",
774 * restriction_selectivity
776 * Returns the selectivity of a specified restriction operator clause.
777 * This code executes registered procedures stored in the
778 * operator relation, by calling the function manager.
780 * See clause_selectivity() for the meaning of the additional parameters.
783 restriction_selectivity(PlannerInfo *root,
788 RegProcedure oprrest = get_oprrest(operator);
792 * if the oprrest procedure is missing for whatever reason, use a
796 return (Selectivity) 0.5;
798 result = DatumGetFloat8(OidFunctionCall4(oprrest,
799 PointerGetDatum(root),
800 ObjectIdGetDatum(operator),
801 PointerGetDatum(args),
802 Int32GetDatum(varRelid)));
804 if (result < 0.0 || result > 1.0)
805 elog(ERROR, "invalid restriction selectivity: %f", result);
807 return (Selectivity) result;
813 * Returns the selectivity of a specified join operator clause.
814 * This code executes registered procedures stored in the
815 * operator relation, by calling the function manager.
818 join_selectivity(PlannerInfo *root,
822 SpecialJoinInfo *sjinfo)
824 RegProcedure oprjoin = get_oprjoin(operator);
828 * if the oprjoin procedure is missing for whatever reason, use a
832 return (Selectivity) 0.5;
834 result = DatumGetFloat8(OidFunctionCall5(oprjoin,
835 PointerGetDatum(root),
836 ObjectIdGetDatum(operator),
837 PointerGetDatum(args),
838 Int16GetDatum(jointype),
839 PointerGetDatum(sjinfo)));
841 if (result < 0.0 || result > 1.0)
842 elog(ERROR, "invalid join selectivity: %f", result);
844 return (Selectivity) result;
848 * find_inheritance_children
850 * Returns a list containing the OIDs of all relations which
851 * inherit *directly* from the relation with OID 'inhparent'.
853 * XXX might be a good idea to create an index on pg_inherits' inhparent
854 * field, so that we can use an indexscan instead of sequential scan here.
855 * However, in typical databases pg_inherits won't have enough entries to
856 * justify an indexscan...
859 find_inheritance_children(Oid inhparent)
864 HeapTuple inheritsTuple;
869 * Can skip the scan if pg_class shows the relation has never had a
872 if (!has_subclass(inhparent))
876 Anum_pg_inherits_inhparent,
877 BTEqualStrategyNumber, F_OIDEQ,
878 ObjectIdGetDatum(inhparent));
879 relation = heap_open(InheritsRelationId, AccessShareLock);
880 scan = heap_beginscan(relation, SnapshotNow, 1, key);
881 while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
883 inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
884 list = lappend_oid(list, inhrelid);
887 heap_close(relation, AccessShareLock);
894 * In the current implementation, has_subclass returns whether a
895 * particular class *might* have a subclass. It will not return the
896 * correct result if a class had a subclass which was later dropped.
897 * This is because relhassubclass in pg_class is not updated when a
898 * subclass is dropped, primarily because of concurrency concerns.
900 * Currently has_subclass is only used as an efficiency hack to skip
901 * unnecessary inheritance searches, so this is OK.
904 has_subclass(Oid relationId)
909 tuple = SearchSysCache(RELOID,
910 ObjectIdGetDatum(relationId),
912 if (!HeapTupleIsValid(tuple))
913 elog(ERROR, "cache lookup failed for relation %u", relationId);
915 result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
916 ReleaseSysCache(tuple);
923 * Detect whether there is a unique index on the specified attribute
924 * of the specified relation, thus allowing us to conclude that all
925 * the (non-null) values of the attribute are distinct.
928 has_unique_index(RelOptInfo *rel, AttrNumber attno)
932 foreach(ilist, rel->indexlist)
934 IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
937 * Note: ignore partial indexes, since they don't allow us to conclude
938 * that all attr values are distinct. We don't take any interest in
939 * expressional indexes either. Also, a multicolumn unique index
940 * doesn't allow us to conclude that just the specified attr is
944 index->ncolumns == 1 &&
945 index->indexkeys[0] == attno &&
946 index->indpred == NIL)