diff --exclude gram.c -ur postgresql-7.1.orig/doc/TODO postgresql-7.1/doc/TODO --- postgresql-7.1.orig/doc/TODO Mon Apr 9 04:11:09 2001 +++ postgresql-7.1/doc/TODO Sat Jul 7 15:06:55 2001 @@ -144,7 +144,7 @@ fails index can't store constant parameters * -Allow SQL function indexes * Add FILLFACTOR to index creation -* Re-enable partial indexes +* -Re-enable partial indexes * Allow inherited tables to inherit index, UNIQUE constraint, and primary key [inheritance] * Prevent pg_attribute from having duplicate oids for indexes (Tom) diff --exclude gram.c -ur postgresql-7.1.orig/doc/src/sgml/catalogs.sgml postgresql-7.1/doc/src/sgml/catalogs.sgml --- postgresql-7.1.orig/doc/src/sgml/catalogs.sgml Mon Apr 2 05:17:30 2001 +++ postgresql-7.1/doc/src/sgml/catalogs.sgml Sat Jul 7 15:01:17 2001 @@ -1053,7 +1053,7 @@ indpred text - Query plan for partial index predicate (not functional) + Query plan for partial index predicate diff --exclude gram.c -ur postgresql-7.1.orig/doc/src/sgml/indices.sgml postgresql-7.1/doc/src/sgml/indices.sgml --- postgresql-7.1.orig/doc/src/sgml/indices.sgml Sat Feb 24 05:11:55 2001 +++ postgresql-7.1/doc/src/sgml/indices.sgml Sat Jul 7 15:06:09 2001 @@ -557,11 +557,12 @@ Note - Partial indices are not currently supported by - PostgreSQL, but they were once supported - by its predecessor Postgres, and much - of the code is still there. We hope to revive support for this - feature someday. + For a long time partial indicies were not supported by + PostgreSQL, but they were once supported by + its predecessor Postgres, and much of the + code was still there. Currently (July 2001) there is some work underway + to revive this feature. See the pgsql-general mailing list archives for + details. diff --exclude gram.c -ur postgresql-7.1.orig/doc/src/sgml/ref/create_index.sgml postgresql-7.1/doc/src/sgml/ref/create_index.sgml --- postgresql-7.1.orig/doc/src/sgml/ref/create_index.sgml Mon Jan 29 13:53:33 2001 +++ postgresql-7.1/doc/src/sgml/ref/create_index.sgml Tue Jul 10 00:34:22 2001 @@ -25,8 +25,10 @@ CREATE [ UNIQUE ] INDEX index_name ON table [ USING acc_name ] ( column [ ops_name ] [, ...] ) + [ WHERE expr ] CREATE [ UNIQUE ] INDEX index_name ON table [ USING acc_name ] ( func_name( column [, ... ]) [ ops_name ] ) + [ WHERE expr ] @@ -137,6 +139,15 @@ + + + expr + + + Defines the expression for a partial index. + + + @@ -225,6 +236,23 @@ of these access methods are fully dynamic and do not have to be optimized periodically (as is the case with, for example, static hash access methods). + + + + When the WHERE clause is present, this defines a + partial index. A partial index is an index that only covers a portion of + a table, usually a portion that is somehow more interesting than the + rest of the table. For example, if you have a table that contains both + billed and unbilled orders where the unbilled order take up a small + fraction of the total table and yet that is an often used section, you + can improve performance by creating an index on just that portion. + + + + The expression used in the WHERE clause is restricted + to forms the planner can easily use. Each element can only consist of + ATTR OP CONST and these can only be joined by + AND and OR operators. diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/access/gist/gist.c postgresql-7.1/src/backend/access/gist/gist.c --- postgresql-7.1.orig/src/backend/access/gist/gist.c Sat Mar 24 11:54:34 2001 +++ postgresql-7.1/src/backend/access/gist/gist.c Wed Jul 4 22:05:47 2001 @@ -193,7 +193,7 @@ */ if (oldPred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (ExecQual((List *) oldPred, econtext, false)) { nitups++; @@ -207,7 +207,7 @@ */ if (pred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (!ExecQual((List *) pred, econtext, false)) continue; } diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/access/hash/hash.c postgresql-7.1/src/backend/access/hash/hash.c --- postgresql-7.1.orig/src/backend/access/hash/hash.c Sat Mar 24 11:54:34 2001 +++ postgresql-7.1/src/backend/access/hash/hash.c Wed Jul 4 22:06:10 2001 @@ -128,7 +128,7 @@ */ if (oldPred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (ExecQual((List *) oldPred, econtext, false)) { nitups++; @@ -142,7 +142,7 @@ */ if (pred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (!ExecQual((List *) pred, econtext, false)) continue; } diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/access/nbtree/nbtree.c postgresql-7.1/src/backend/access/nbtree/nbtree.c --- postgresql-7.1.orig/src/backend/access/nbtree/nbtree.c Sat Mar 24 11:54:35 2001 +++ postgresql-7.1/src/backend/access/nbtree/nbtree.c Wed Jul 4 21:59:55 2001 @@ -206,7 +206,8 @@ */ if (oldPred != NULL) { - slot->val = htup; + /* Invalid buffer should be ok, index shouldn't go away, i hope */ + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (ExecQual((List *) oldPred, econtext, false)) { nitups++; @@ -220,7 +221,8 @@ */ if (pred != NULL) { - slot->val = htup; + /* Invalid buffer should be ok, index shouldn't go away, i hope */ + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (!ExecQual((List *) pred, econtext, false)) continue; } diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/access/rtree/rtree.c postgresql-7.1/src/backend/access/rtree/rtree.c --- postgresql-7.1.orig/src/backend/access/rtree/rtree.c Sat Mar 24 11:54:35 2001 +++ postgresql-7.1/src/backend/access/rtree/rtree.c Wed Jul 4 22:07:13 2001 @@ -182,7 +182,7 @@ */ if (oldPred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (ExecQual((List *) oldPred, econtext, false)) { nitups++; @@ -196,7 +196,7 @@ */ if (pred != NULL) { - slot->val = htup; + ExecStoreTuple( htup, slot, InvalidBuffer, false ); if (!ExecQual((List *) pred, econtext, false)) continue; } diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/optimizer/path/indxpath.c postgresql-7.1/src/backend/optimizer/path/indxpath.c --- postgresql-7.1.orig/src/backend/optimizer/path/indxpath.c Sat Mar 24 11:54:40 2001 +++ postgresql-7.1/src/backend/optimizer/path/indxpath.c Wed Jul 4 19:59:53 2001 @@ -196,8 +196,10 @@ * 4. Generate an indexscan path if there are relevant restriction * clauses OR the index ordering is potentially useful for later * merging or final output ordering. + * + * If there is a predicate, consider it anyway since the clause may be useful */ - if (restrictclauses != NIL || useful_pathkeys != NIL) + if (restrictclauses != NIL || useful_pathkeys != NIL || index->indpred != NIL) add_path(rel, (Path *) create_index_path(root, rel, index, restrictclauses, @@ -1153,6 +1155,8 @@ ScanKeyData entry[3]; Form_pg_amop aform; + ExprContext *econtext; + pred_var = (Var *) get_leftop(predicate); pred_const = (Const *) get_rightop(predicate); clause_var = (Var *) get_leftop((Expr *) clause); @@ -1302,7 +1306,8 @@ copyObject(clause_const), copyObject(pred_const)); - test_result = ExecEvalExpr((Node *) test_expr, NULL, &isNull, NULL); + econtext = MakeExprContext(NULL, TransactionCommandContext); + test_result = ExecEvalExpr((Node *) test_expr, econtext, &isNull, NULL); if (isNull) { diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/optimizer/util/pathnode.c postgresql-7.1/src/backend/optimizer/util/pathnode.c --- postgresql-7.1.orig/src/backend/optimizer/util/pathnode.c Sat Mar 24 11:54:42 2001 +++ postgresql-7.1/src/backend/optimizer/util/pathnode.c Wed Jul 4 20:27:42 2001 @@ -362,6 +362,11 @@ pathnode->alljoinquals = false; pathnode->rows = rel->rows; + /* Not sure if this is necessary, but it should help if the + * statistics are too far off */ + if( index->indpred && index->tuples < pathnode->rows ) + pathnode->rows = index->tuples; + cost_index(&pathnode->path, root, rel, index, indexquals, false); return pathnode; diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/parser/analyze.c postgresql-7.1/src/backend/parser/analyze.c --- postgresql-7.1.orig/src/backend/parser/analyze.c Sat Mar 24 11:54:42 2001 +++ postgresql-7.1/src/backend/parser/analyze.c Wed Jul 4 23:03:16 2001 @@ -1525,6 +1525,12 @@ { Query *qry; + /* Add the table to the range table so that the WHERE clause can use the fields */ + /* no inheritence, yes we can use fields from relation */ + RangeTblEntry *rte = addRangeTableEntry( pstate, stmt->relname, NULL, false, true ); + /* no to join list, yes to namespace */ + addRTEtoQuery( pstate, rte, false, true ); + qry = makeNode(Query); qry->commandType = CMD_UTILITY; diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/parser/gram.y postgresql-7.1/src/backend/parser/gram.y --- postgresql-7.1.orig/src/backend/parser/gram.y Sat Feb 24 05:12:06 2001 +++ postgresql-7.1/src/backend/parser/gram.y Tue Jul 10 00:20:28 2001 @@ -446,7 +446,7 @@ | DropPLangStmt | DropTrigStmt | DropUserStmt - | ExtendStmt +/* | ExtendStmt */ | ExplainStmt | FetchStmt | GrantStmt @@ -2309,11 +2309,10 @@ * using "(" ( with )+ ")" [with * ] * - * [where ] is not supported anymore *****************************************************************************/ IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name - access_method_clause '(' index_params ')' opt_with + access_method_clause '(' index_params ')' opt_with where_clause { IndexStmt *n = makeNode(IndexStmt); n->unique = $2; @@ -2322,7 +2321,7 @@ n->accessMethod = $7; n->indexParams = $9; n->withClause = $11; - n->whereClause = NULL; + n->whereClause = $12; $$ = (Node *)n; } ; @@ -2390,8 +2389,9 @@ * QUERY: * extend index [where ] * + * Removed. No longer supported. (July 2001) *****************************************************************************/ - +/* ExtendStmt: EXTEND INDEX index_name where_clause { ExtendStmt *n = makeNode(ExtendStmt); @@ -2400,7 +2400,7 @@ $$ = (Node *)n; } ; - +*/ /***************************************************************************** * * QUERY: diff --exclude gram.c -ur postgresql-7.1.orig/src/backend/utils/adt/selfuncs.c postgresql-7.1/src/backend/utils/adt/selfuncs.c --- postgresql-7.1.orig/src/backend/utils/adt/selfuncs.c Sat Mar 24 11:54:50 2001 +++ postgresql-7.1/src/backend/utils/adt/selfuncs.c Sun Jul 8 11:01:10 2001 @@ -2103,18 +2103,26 @@ Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4); Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5); Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6); + Selectivity thisIndexSelectivity; double numIndexTuples; double numIndexPages; + /* Create the list of all relevent clauses by including any index predicates */ + List *selectQuals = nconc( listCopy( index->indpred ), indexQuals ); + /* Estimate the fraction of main-table tuples that will be visited */ - *indexSelectivity = clauselist_selectivity(root, indexQuals, + *indexSelectivity = clauselist_selectivity(root, selectQuals, lfirsti(rel->relids)); + /* Estimate the fraction of index tuples to be visited (for partial indicies) */ + /* This is a simple way of doing it. Should we call clauselist_selectivity again? */ + thisIndexSelectivity = *indexSelectivity * rel->tuples / index->tuples; + /* Estimate the number of index tuples that will be visited */ - numIndexTuples = *indexSelectivity * index->tuples; + numIndexTuples = thisIndexSelectivity * index->tuples; /* Estimate the number of index pages that will be retrieved */ - numIndexPages = *indexSelectivity * index->pages; + numIndexPages = thisIndexSelectivity * index->pages; /* * Always estimate at least one tuple and page are touched, even when diff --exclude gram.c -ur postgresql-7.1.orig/src/test/regress/sql/create_index.sql postgresql-7.1/src/test/regress/sql/create_index.sql --- postgresql-7.1.orig/src/test/regress/sql/create_index.sql Thu Feb 17 14:40:02 2000 +++ postgresql-7.1/src/test/regress/sql/create_index.sql Sat Jul 7 15:32:19 2001 @@ -50,20 +50,19 @@ -- -- BTREE partial indices --- partial indices are not supported in PostgreSQL -- ---CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops) --- where onek2.unique1 < 20 or onek2.unique1 > 980; +CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops) + where onek2.unique1 < 20 or onek2.unique1 > 980; ---CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops) --- where onek2.stringu1 < 'B'; +CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops) + where onek2.stringu1 < 'B'; --- EXTEND INDEX onek2_u2_prtl where onek2.stringu1 < 'C'; +EXTEND INDEX onek2_u2_prtl where onek2.stringu1 < 'C'; --- EXTEND INDEX onek2_u2_prtl; +EXTEND INDEX onek2_u2_prtl; --- CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) --- where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K'; +CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) + where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K'; -- -- RTREE