diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 544f9b758d38754249fe7426cb5f9505873850f1..41d7a4e34d5e2328a985636cfc54ec28400cb625 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ <!-- Documentation of the system catalogs, directed toward PostgreSQL developers - $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.102 2005/05/17 21:46:09 tgl Exp $ + $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.103 2005/06/13 23:14:47 tgl Exp $ --> <chapter id="catalogs"> @@ -358,6 +358,14 @@ <entry>Does the access method support multicolumn indexes?</entry> </row> + <row> + <entry><structfield>amoptionalkey</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>Does the access method support a scan without any constraint + for the first index column?</entry> + </row> + <row> <entry><structfield>amindexnulls</structfield></entry> <entry><type>bool</type></entry> diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index cbc01bae8c437e3ec538d9ad45020bdf2d48ea52..b5f3d3347978bb5201ca00b321eb97f48430b9b2 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.5 2005/06/05 22:32:53 tgl Exp $ +$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.6 2005/06/13 23:14:47 tgl Exp $ --> <chapter id="indexam"> @@ -100,21 +100,30 @@ $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.5 2005/06/05 22:32:53 tgl Exp $ <structfield>amconcurrent</structfield> in <xref linkend="index-locking">. The <structfield>amcanmulticol</structfield> flag asserts that the access method supports multi-column indexes, while + <structfield>amoptionalkey</structfield> asserts that it allows scans + where no indexable restriction clause is given for the first index column. + When <structfield>amcanmulticol</structfield> is false, + <structfield>amoptionalkey</structfield> essentially says whether the + access method allows full-index scans without any restriction clause. + Access methods that support multiple index columns <emphasis>must</> + support scans that omit restrictions on any or all of the columns after + the first; however they are permitted to require some restriction to + appear for the first index column, and this is signaled by setting + <structfield>amoptionalkey</structfield> false. <structfield>amindexnulls</structfield> asserts that index entries are created for NULL key values. Since most indexable operators are strict and hence cannot return TRUE for NULL inputs, it is at first sight attractive to not store index entries for NULLs: they could never be returned by an index scan anyway. However, this - argument fails for a full-table index scan (one with no scan keys); - such a scan should include null rows. In practice this means that - indexes that support ordered scans (have <structfield>amorderstrategy</> - nonzero) must index nulls, since the planner might decide to use such a - scan as a substitute for sorting. Such indexes must also be willing to - run a scan with no scan keys at all. Another restriction is that an index + argument fails when an index scan has no restriction clause for a given + index column. In practice this means that + indexes that have <structfield>amoptionalkey</structfield> true must + index nulls, since the planner might decide to use such an index + with no scan keys at all. A related restriction is that an index access method that supports multiple index columns <emphasis>must</> support indexing null values in columns after the first, because the planner - will assume the index can be used for queries on just the first - column(s). For example, consider an index on (a,b) and a query with + will assume the index can be used for queries that do not restrict + these columns. For example, consider an index on (a,b) and a query with <literal>WHERE a = 4</literal>. The system will assume the index can be used to scan for rows with <literal>a = 4</literal>, which is wrong if the index omits rows where <literal>b</> is null. diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 81c2114976e93f5fe8f74e17c13402bc06e38762..a445efc7154cdfa0b7e0302ba7ae13c5b49a86c5 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.82 2005/05/27 23:31:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.83 2005/06/13 23:14:48 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relation OID @@ -25,7 +25,6 @@ * index_getmulti - get multiple tuples from a scan * index_bulk_delete - bulk deletion of index tuples * index_vacuum_cleanup - post-deletion cleanup of an index - * index_cost_estimator - fetch amcostestimate procedure OID * index_getprocid - get a support procedure OID * index_getprocinfo - get a support procedure's lookup info * @@ -718,27 +717,6 @@ index_vacuum_cleanup(Relation indexRelation, return result; } -/* ---------------- - * index_cost_estimator - * - * Fetch the amcostestimate procedure OID for an index. - * - * We could combine fetching and calling the procedure, - * as index_insert does for example; but that would require - * importing a bunch of planner/optimizer stuff into this file. - * ---------------- - */ -RegProcedure -index_cost_estimator(Relation indexRelation) -{ - FmgrInfo *procedure; - - RELATION_CHECKS; - GET_REL_PROCEDURE(amcostestimate); - - return procedure->fn_oid; -} - /* ---------------- * index_getprocid * diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 17b3b0dcddf45191b32383d66106dabcf7fb7246..824d5ea70e66b51b232d50f0358012c9832d399c 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.91 2005/03/29 00:16:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.92 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -594,15 +594,17 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) } /* - * Done if that was the last attribute. + * Done if that was the last attribute, or if next key + * is not in sequence (implying no boundary key is available + * for the next attribute). */ - if (i >= so->numberOfKeys) + if (i >= so->numberOfKeys || + cur->sk_attno != curattr + 1) break; /* - * Reset for next attr, which should be in sequence. + * Reset for next attr. */ - Assert(cur->sk_attno == curattr + 1); curattr = cur->sk_attno; chosen = NULL; } diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 96a3f05a5d63ef4dff51df27aa7d8840aceef42f..9a5f8d7ac901e34e318dc848a0d6ed61a5275234 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.62 2004/12/31 21:59:22 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.63 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -190,7 +190,9 @@ _bt_formitem(IndexTuple itup) * matched to continue the scan. In general, numberOfRequiredKeys is equal * to the number of keys for leading attributes with "=" keys, plus the * key(s) for the first non "=" attribute, which can be seen to be correct - * by considering the above example. + * by considering the above example. Note in particular that if there are no + * keys for a given attribute, the keys for subsequent attributes can never + * be required; for instance "WHERE y = 4" requires a full-index scan. * * If possible, redundant keys are eliminated: we keep only the tightest * >/>= bound and the tightest </<= bound, and if there's an = key then @@ -248,8 +250,8 @@ _bt_preprocess_keys(IndexScanDesc scan) outkeys = so->keyData; cur = &inkeys[0]; /* we check that input keys are correctly ordered */ - if (cur->sk_attno != 1) - elog(ERROR, "key(s) for attribute 1 missed"); + if (cur->sk_attno < 1) + elog(ERROR, "btree index keys must be ordered by attribute"); /* We can short-circuit most of the work if there's just one key */ if (numberOfKeys == 1) @@ -270,7 +272,8 @@ _bt_preprocess_keys(IndexScanDesc scan) } memcpy(outkeys, inkeys, sizeof(ScanKeyData)); so->numberOfKeys = 1; - so->numberOfRequiredKeys = 1; + if (cur->sk_attno == 1) + so->numberOfRequiredKeys = 1; return; } @@ -324,8 +327,8 @@ _bt_preprocess_keys(IndexScanDesc scan) int priorNumberOfEqualCols = numberOfEqualCols; /* check input keys are correctly ordered */ - if (i < numberOfKeys && cur->sk_attno != attno + 1) - elog(ERROR, "key(s) for attribute %d missed", attno + 1); + if (i < numberOfKeys && cur->sk_attno < attno) + elog(ERROR, "btree index keys must be ordered by attribute"); /* * If = has been specified, no other key will be used. In case diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 9c1874d5907588ce1f87de0b585bf349af058170..525304f5cb313e76a7a81a5721f03f4a4c8bb049 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.183 2005/06/10 22:25:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.184 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,7 +87,8 @@ static Const *string_to_const(const char *str, Oid datatype); * * To be considered for an index scan, an index must match one or more * restriction clauses or join clauses from the query's qual condition, - * or match the query's ORDER BY condition. + * or match the query's ORDER BY condition, or have a predicate that + * matches the query's qual condition. * * There are two basic kinds of index scans. A "plain" index scan uses * only restriction clauses (possibly none at all) in its indexqual, @@ -210,6 +211,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * 'clauses' is the current list of clauses (RestrictInfo nodes) * 'outer_clauses' is the list of additional upper-level clauses * 'istoplevel' is true if clauses are the rel's top-level restriction list + * (outer_clauses must be NIL when this is true) * 'isjoininner' is true if forming an inner indexscan (so some of the * given clauses are join clauses) * 'outer_relids' identifies the outer side of the join (pass NULL @@ -295,13 +297,12 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, * selectivity of the predicate might alone make the index useful. * * Note: not all index AMs support scans with no restriction clauses. - * We assume here that the AM does so if and only if it supports - * ordered scans. (It would probably be better if there were a - * specific flag for this in pg_am, but there's not.) + * We can't generate a scan over an index with amoptionalkey = false + * unless there's at least one restriction clause. */ if (restrictclauses != NIL || - useful_pathkeys != NIL || - (index->indpred != NIL && index_is_ordered)) + (index->amoptionalkey && + (useful_pathkeys != NIL || index->indpred != NIL))) { ipath = create_index_path(root, index, restrictclauses, @@ -608,6 +609,11 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) * group_clauses_by_indexkey * Find restriction clauses that can be used with an index. * + * Returns a list of sublists of RestrictInfo nodes for clauses that can be + * used with this index. Each sublist contains clauses that can be used + * with one index key (in no particular order); the top list is ordered by + * index key. (This is depended on by expand_indexqual_conditions().) + * * As explained in the comments for find_usable_indexes(), we can use * clauses from either of the given lists, but the result is required to * use at least one clause from the "current clauses" list. We return @@ -616,18 +622,14 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) * outer_relids determines what Vars will be allowed on the other side * of a possible index qual; see match_clause_to_indexcol(). * - * Returns a list of sublists of RestrictInfo nodes for clauses that can be - * used with this index. Each sublist contains clauses that can be used - * with one index key (in no particular order); the top list is ordered by - * index key. (This is depended on by expand_indexqual_conditions().) + * If the index has amoptionalkey = false, we give up and return NIL when + * there are no restriction clauses matching the first index key. Otherwise, + * we return NIL if there are no restriction clauses matching any index key. + * A non-NIL result will have one (possibly empty) sublist for each index key. * - * Note that in a multi-key index, we stop if we find a key that cannot be - * used with any clause. For example, given an index on (A,B,C), we might - * return ((C1 C2) (C3 C4)) if we find that clauses C1 and C2 use column A, - * clauses C3 and C4 use column B, and no clauses use column C. But if - * no clauses match B we will return ((C1 C2)), whether or not there are - * clauses matching column C, because the executor couldn't use them anyway. - * Therefore, there are no empty sublists in the result. + * Example: given an index on (A,B,C), we would return ((C1 C2) () (C3 C4)) + * if we find that clauses C1 and C2 use column A, clauses C3 and C4 use + * column C, and no clauses use column B. */ List * group_clauses_by_indexkey(IndexOptInfo *index, @@ -680,11 +682,10 @@ group_clauses_by_indexkey(IndexOptInfo *index, } /* - * If no clauses match this key, we're done; we don't want to look - * at keys to its right. + * If no clauses match this key, check for amoptionalkey restriction. */ - if (clausegroup == NIL) - break; + if (clausegroup == NIL && !index->amoptionalkey && indexcol == 0) + return NIL; clausegroup_list = lappend(clausegroup_list, clausegroup); @@ -1581,11 +1582,9 @@ match_special_index_operator(Expr *clause, Oid opclass, * will know what to do with. * * The input list is ordered by index key, and so the output list is too. - * (The latter is not depended on by any part of the planner, so far as I can - * tell; but some parts of the executor do assume that the indexqual list - * ultimately delivered to the executor is so ordered. One such place is - * _bt_preprocess_keys() in the btree support. Perhaps that ought to be fixed - * someday --- tgl 7/00) + * (The latter is not depended on by any part of the core planner, I believe, + * but parts of the executor require it, and so do the amcostestimate + * functions.) */ List * expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index a8dcdae9a2ff828381dc0220d8ef73d1452c3ebd..067e9f701ca212c363443fa14d9aaac78c087ea9 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.111 2005/06/05 22:32:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.112 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -161,7 +161,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel) } info->relam = indexRelation->rd_rel->relam; - info->amcostestimate = index_cost_estimator(indexRelation); + info->amcostestimate = indexRelation->rd_am->amcostestimate; + info->amoptionalkey = indexRelation->rd_am->amoptionalkey; /* * Fetch the ordering operators associated with the index, if diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 0b03f27c39ce98626f3a4d7d30609c41cb50fa7c..204d37bf4157b6343e4d6b243888c26fffe6e0ec 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.181 2005/06/10 22:25:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.182 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -4195,18 +4195,23 @@ string_to_bytea_const(const char *str, size_t str_len) * don't have any better idea about how to estimate. Index-type-specific * knowledge can be incorporated in the type-specific routines. * + * One bit of index-type-specific knowledge we can relatively easily use + * in genericcostestimate is the estimate of the number of index tuples + * visited. If numIndexTuples is not 0 then it is used as the estimate, + * otherwise we compute a generic estimate. + * *------------------------------------------------------------------------- */ static void genericcostestimate(PlannerInfo *root, IndexOptInfo *index, List *indexQuals, + double numIndexTuples, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation) { - double numIndexTuples; double numIndexPages; QualCost index_qual_cost; double qual_op_cost; @@ -4254,20 +4259,20 @@ genericcostestimate(PlannerInfo *root, JOIN_INNER); /* - * Estimate the number of tuples that will be visited. We do it in - * this rather peculiar-looking way in order to get the right answer - * for partial indexes. We can bound the number of tuples by the - * index size, in any case. + * If caller didn't give us an estimate, estimate the number of index + * tuples that will be visited. We do it in this rather peculiar-looking + * way in order to get the right answer for partial indexes. */ - numIndexTuples = *indexSelectivity * index->rel->tuples; - - if (numIndexTuples > index->tuples) - numIndexTuples = index->tuples; + if (numIndexTuples <= 0.0) + numIndexTuples = *indexSelectivity * index->rel->tuples; /* - * Always estimate at least one tuple is touched, even when + * We can bound the number of tuples by the index size in any case. + * Also, always estimate at least one tuple is touched, even when * indexSelectivity estimate is tiny. */ + if (numIndexTuples > index->tuples) + numIndexTuples = index->tuples; if (numIndexTuples < 1.0) numIndexTuples = 1.0; @@ -4337,8 +4342,95 @@ btcostestimate(PG_FUNCTION_ARGS) Oid relid; AttrNumber colnum; HeapTuple tuple; + double numIndexTuples; + List *indexBoundQuals; + int indexcol; + bool eqQualHere; + ListCell *l; + + /* + * For a btree scan, only leading '=' quals plus inequality quals + * for the immediately next attribute contribute to index selectivity + * (these are the "boundary quals" that determine the starting and + * stopping points of the index scan). Additional quals can suppress + * visits to the heap, so it's OK to count them in indexSelectivity, + * but they should not count for estimating numIndexTuples. So we must + * examine the given indexQuals to find out which ones count as boundary + * quals. We rely on the knowledge that they are given in index column + * order. + */ + indexBoundQuals = NIL; + indexcol = 0; + eqQualHere = false; + foreach(l, indexQuals) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(l); + Expr *clause; + Oid clause_op; + int op_strategy; + + Assert(IsA(rinfo, RestrictInfo)); + clause = rinfo->clause; + Assert(IsA(clause, OpExpr)); + clause_op = ((OpExpr *) clause)->opno; + if (match_index_to_operand(get_leftop(clause), indexcol, index)) + { + /* clause_op is correct */ + } + else if (match_index_to_operand(get_rightop(clause), indexcol, index)) + { + /* Must flip operator to get the opclass member */ + clause_op = get_commutator(clause_op); + } + else + { + /* Must be past the end of quals for indexcol, try next */ + if (!eqQualHere) + break; /* done if no '=' qual for indexcol */ + indexcol++; + eqQualHere = false; + if (match_index_to_operand(get_leftop(clause), indexcol, index)) + { + /* clause_op is correct */ + } + else if (match_index_to_operand(get_rightop(clause), + indexcol, index)) + { + /* Must flip operator to get the opclass member */ + clause_op = get_commutator(clause_op); + } + else + { + /* No quals for new indexcol, so we are done */ + break; + } + } + op_strategy = get_op_opclass_strategy(clause_op, + index->classlist[indexcol]); + Assert(op_strategy != 0); /* not a member of opclass?? */ + if (op_strategy == BTEqualStrategyNumber) + eqQualHere = true; + indexBoundQuals = lappend(indexBoundQuals, rinfo); + } + + /* + * If index is unique and we found an '=' clause for each column, + * we can just assume numIndexTuples = 1 and skip the expensive + * clauselist_selectivity calculations. + */ + if (index->unique && indexcol == index->ncolumns - 1 && eqQualHere) + numIndexTuples = 1.0; + else + { + Selectivity btreeSelectivity; + + btreeSelectivity = clauselist_selectivity(root, indexBoundQuals, + index->rel->relid, + JOIN_INNER); + numIndexTuples = btreeSelectivity * index->rel->tuples; + } - genericcostestimate(root, index, indexQuals, + genericcostestimate(root, index, indexQuals, numIndexTuples, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -4414,7 +4506,7 @@ rtcostestimate(PG_FUNCTION_ARGS) Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); double *indexCorrelation = (double *) PG_GETARG_POINTER(6); - genericcostestimate(root, index, indexQuals, + genericcostestimate(root, index, indexQuals, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -4432,7 +4524,7 @@ hashcostestimate(PG_FUNCTION_ARGS) Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); double *indexCorrelation = (double *) PG_GETARG_POINTER(6); - genericcostestimate(root, index, indexQuals, + genericcostestimate(root, index, indexQuals, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -4450,7 +4542,7 @@ gistcostestimate(PG_FUNCTION_ARGS) Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); double *indexCorrelation = (double *) PG_GETARG_POINTER(6); - genericcostestimate(root, index, indexQuals, + genericcostestimate(root, index, indexQuals, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); diff --git a/src/include/access/genam.h b/src/include/access/genam.h index 3ad0a3d4b2c7ae935db7e95229f6c16c8be28e5d..1ed42f8be60b946d57cfe183625654925f50d3bf 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.51 2005/05/27 23:31:21 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.52 2005/06/13 23:14:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,7 +101,6 @@ extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation, extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation, IndexVacuumCleanupInfo *info, IndexBulkDeleteResult *stats); -extern RegProcedure index_cost_estimator(Relation indexRelation); extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum); extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index ee8b3aee0a28787982dd8c31a6a55c097b83c90a..969c0e83299ece4577be6a33f2fc3cbb39d2e1bd 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.274 2005/06/13 02:26:50 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.275 2005/06/13 23:14:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200506121 +#define CATALOG_VERSION_NO 200506131 #endif diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index bddfda993bb7b809a7c68fb1a90ff98466efdf7b..f473277b46bafc645e9c1396559e6f5885516bf3 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.33 2005/04/14 01:38:20 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.34 2005/06/13 23:14:49 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -48,6 +48,7 @@ CATALOG(pg_am,2601) * Zero if AM is not ordered. */ bool amcanunique; /* does AM support UNIQUE indexes? */ bool amcanmulticol; /* does AM support multi-column indexes? */ + bool amoptionalkey; /* can query omit key for the first column? */ bool amindexnulls; /* does AM support NULL index entries? */ bool amconcurrent; /* does AM support concurrent updates? */ regproc aminsert; /* "insert this tuple" function */ @@ -75,42 +76,43 @@ typedef FormData_pg_am *Form_pg_am; * compiler constants for pg_am * ---------------- */ -#define Natts_pg_am 20 +#define Natts_pg_am 21 #define Anum_pg_am_amname 1 #define Anum_pg_am_amstrategies 2 #define Anum_pg_am_amsupport 3 #define Anum_pg_am_amorderstrategy 4 #define Anum_pg_am_amcanunique 5 #define Anum_pg_am_amcanmulticol 6 -#define Anum_pg_am_amindexnulls 7 -#define Anum_pg_am_amconcurrent 8 -#define Anum_pg_am_aminsert 9 -#define Anum_pg_am_ambeginscan 10 -#define Anum_pg_am_amgettuple 11 -#define Anum_pg_am_amgetmulti 12 -#define Anum_pg_am_amrescan 13 -#define Anum_pg_am_amendscan 14 -#define Anum_pg_am_ammarkpos 15 -#define Anum_pg_am_amrestrpos 16 -#define Anum_pg_am_ambuild 17 -#define Anum_pg_am_ambulkdelete 18 -#define Anum_pg_am_amvacuumcleanup 19 -#define Anum_pg_am_amcostestimate 20 +#define Anum_pg_am_amoptionalkey 7 +#define Anum_pg_am_amindexnulls 8 +#define Anum_pg_am_amconcurrent 9 +#define Anum_pg_am_aminsert 10 +#define Anum_pg_am_ambeginscan 11 +#define Anum_pg_am_amgettuple 12 +#define Anum_pg_am_amgetmulti 13 +#define Anum_pg_am_amrescan 14 +#define Anum_pg_am_amendscan 15 +#define Anum_pg_am_ammarkpos 16 +#define Anum_pg_am_amrestrpos 17 +#define Anum_pg_am_ambuild 18 +#define Anum_pg_am_ambulkdelete 19 +#define Anum_pg_am_amvacuumcleanup 20 +#define Anum_pg_am_amcostestimate 21 /* ---------------- * initial contents of pg_am * ---------------- */ -DATA(insert OID = 402 ( rtree 8 3 0 f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate )); +DATA(insert OID = 402 ( rtree 8 3 0 f f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate )); DESCR("r-tree index access method"); -DATA(insert OID = 403 ( btree 5 1 1 t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate )); +DATA(insert OID = 403 ( btree 5 1 1 t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate )); DESCR("b-tree index access method"); #define BTREE_AM_OID 403 -DATA(insert OID = 405 ( hash 1 1 0 f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate )); +DATA(insert OID = 405 ( hash 1 1 0 f f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate )); DESCR("hash index access method"); #define HASH_AM_OID 405 -DATA(insert OID = 783 ( gist 100 7 0 f t f f gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate )); +DATA(insert OID = 783 ( gist 100 7 0 f t f f f gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate )); DESCR("GiST index access method"); #define GIST_AM_OID 783 diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 687ef367841abc9f81cbbc62187c4ce6092c7103..0a2ca0e5f33fd957333a35299ceb8d6e8bc2723e 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.114 2005/06/10 03:32:25 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.115 2005/06/13 23:14:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -328,6 +328,7 @@ typedef struct IndexOptInfo bool predOK; /* true if predicate matches query */ bool unique; /* true if a unique index */ + bool amoptionalkey; /* can query omit key for the first column? */ } IndexOptInfo;