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