mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Partial indexes work again, courtesy of Martijn van Oosterhout.
Note: I didn't force an initdb, figuring that one today was enough. However, there is a new function in pg_proc.h, and pg_dump won't be able to dump partial indexes until you add that function.
This commit is contained in:
parent
237e5dfa58
commit
f31dc0ada7
@ -1,4 +1,4 @@
|
|||||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.19 2001/05/30 04:01:11 momjian Exp $ -->
|
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.20 2001/07/16 05:06:57 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="indexes">
|
<chapter id="indexes">
|
||||||
<title id="indexes-title">Indexes</title>
|
<title id="indexes-title">Indexes</title>
|
||||||
@ -603,22 +603,11 @@ CREATE MEMSTORE ON <replaceable>table</replaceable> COLUMNS <replaceable>cols</r
|
|||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<note>
|
|
||||||
<title>Note</title>
|
|
||||||
<para>
|
|
||||||
Partial indexes are not currently supported by
|
|
||||||
<productname>PostgreSQL</productname>, but they were once supported
|
|
||||||
by its predecessor <productname>Postgres</productname>, and much
|
|
||||||
of the code is still there. We hope to revive support for this
|
|
||||||
feature someday.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A <firstterm>partial index</firstterm>
|
A <firstterm>partial index</firstterm>
|
||||||
is an index built over a subset of a table; the subset is defined by
|
is an index built over a subset of a table; the subset is defined by
|
||||||
a predicate. <productname>Postgres</productname>
|
a predicate. <productname>Postgres</productname>
|
||||||
supported partial indexes with arbitrary
|
supports partial indexes with arbitrary
|
||||||
predicates. I believe IBM's <productname>DB2</productname>
|
predicates. I believe IBM's <productname>DB2</productname>
|
||||||
for AS/400 supports partial indexes
|
for AS/400 supports partial indexes
|
||||||
using single-clause predicates.
|
using single-clause predicates.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_index.sgml,v 1.19 2001/05/17 21:50:18 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_index.sgml,v 1.20 2001/07/16 05:06:57 tgl Exp $
|
||||||
Postgres documentation
|
Postgres documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -20,13 +20,15 @@ Postgres documentation
|
|||||||
</refnamediv>
|
</refnamediv>
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<refsynopsisdivinfo>
|
<refsynopsisdivinfo>
|
||||||
<date>1999-07-20</date>
|
<date>2001-07-15</date>
|
||||||
</refsynopsisdivinfo>
|
</refsynopsisdivinfo>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable> ON <replaceable class="parameter">table</replaceable>
|
CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable> ON <replaceable class="parameter">table</replaceable>
|
||||||
[ USING <replaceable class="parameter">acc_name</replaceable> ] ( <replaceable class="parameter">column</replaceable> [ <replaceable class="parameter">ops_name</replaceable> ] [, ...] )
|
[ USING <replaceable class="parameter">acc_method</replaceable> ] ( <replaceable class="parameter">column</replaceable> [ <replaceable class="parameter">ops_name</replaceable> ] [, ...] )
|
||||||
|
[ WHERE <replaceable class="parameter">predicate</replaceable> ]
|
||||||
CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable> ON <replaceable class="parameter">table</replaceable>
|
CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable> ON <replaceable class="parameter">table</replaceable>
|
||||||
[ USING <replaceable class="parameter">acc_name</replaceable> ] ( <replaceable class="parameter">func_name</replaceable>( <replaceable class="parameter">column</replaceable> [, ... ]) [ <replaceable class="parameter">ops_name</replaceable> ] )
|
[ USING <replaceable class="parameter">acc_method</replaceable> ] ( <replaceable class="parameter">func_name</replaceable>( <replaceable class="parameter">column</replaceable> [, ... ]) [ <replaceable class="parameter">ops_name</replaceable> ] )
|
||||||
|
[ WHERE <replaceable class="parameter">predicate</replaceable> ]
|
||||||
</synopsis>
|
</synopsis>
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATEINDEX-1">
|
<refsect2 id="R2-SQL-CREATEINDEX-1">
|
||||||
@ -71,12 +73,12 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="parameter">acc_name</replaceable></term>
|
<term><replaceable class="parameter">acc_method</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of the access method to be used for
|
The name of the access method to be used for
|
||||||
the index. The default access method is BTREE.
|
the index. The default access method is BTREE.
|
||||||
Postgres provides three access methods for indexes:
|
Postgres provides four access methods for indexes:
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -106,6 +108,15 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable>
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>GIST</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Generalized Index Search Trees.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -137,6 +148,15 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable>
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">predicate</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Defines the constraint expression for a partial index.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
@ -216,7 +236,7 @@ ERROR: Cannot create index: 'index_name' already exists.
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Postgres provides btree, rtree and hash access methods for
|
Postgres provides btree, rtree, hash, and GiST access methods for
|
||||||
indexes. The btree access method is an implementation of
|
indexes. The btree access method is an implementation of
|
||||||
Lehman-Yao high-concurrency btrees. The rtree access method
|
Lehman-Yao high-concurrency btrees. The rtree access method
|
||||||
implements standard rtrees using Guttman's quadratic split algorithm.
|
implements standard rtrees using Guttman's quadratic split algorithm.
|
||||||
@ -227,6 +247,32 @@ ERROR: Cannot create index: 'index_name' already exists.
|
|||||||
access methods).
|
access methods).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When the <command>WHERE</command> clause is present, a
|
||||||
|
<firstterm>partial index</firstterm> is created.
|
||||||
|
A partial index is an index that contains entries for only 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 orders 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.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The expression used in the <command>WHERE</command> clause may refer
|
||||||
|
only to columns of the underlying table (but it can use all columns,
|
||||||
|
not only the one(s) being indexed). Currently, the
|
||||||
|
<productname>PostgreSQL</productname> planner can only devise query
|
||||||
|
plans that make use of a partial index when the predicate is built from
|
||||||
|
<command>AND</command> and <command>OR</command> combinations of
|
||||||
|
elements of the form
|
||||||
|
<firstterm>column</firstterm>
|
||||||
|
<firstterm>operator</firstterm>
|
||||||
|
<firstterm>constant</firstterm>.
|
||||||
|
However, more general predicates may still be useful in conjunction
|
||||||
|
with UNIQUE indexes, to enforce uniqueness over a subset of a table.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Use <xref linkend="sql-dropindex" endterm="sql-dropindex-title">
|
Use <xref linkend="sql-dropindex" endterm="sql-dropindex-title">
|
||||||
to remove an index.
|
to remove an index.
|
||||||
@ -278,9 +324,10 @@ ERROR: Cannot create index: 'index_name' already exists.
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Currently, only the btree access method supports multi-column
|
Currently, only the btree and gist access methods support multi-column
|
||||||
indexes. Up to 16 keys may be specified by default (this limit
|
indexes. Up to 16 keys may be specified by default (this limit
|
||||||
can be altered when building Postgres).
|
can be altered when building Postgres). Only btree currently supports
|
||||||
|
unique indexes.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -307,9 +354,9 @@ ERROR: Cannot create index: 'index_name' already exists.
|
|||||||
The difference between them is that <literal>bigbox_ops</literal>
|
The difference between them is that <literal>bigbox_ops</literal>
|
||||||
scales box coordinates down, to avoid floating-point exceptions from
|
scales box coordinates down, to avoid floating-point exceptions from
|
||||||
doing multiplication, addition, and subtraction on very large
|
doing multiplication, addition, and subtraction on very large
|
||||||
floating-point coordinates. If the field on which your rectangles lie
|
floating-point coordinates. (Note: this was true some time ago,
|
||||||
is about 20,000 units square or larger, you should use
|
but currently the two operator classes both use floating point
|
||||||
<literal>bigbox_ops</literal>.
|
and are effectively identical.)
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
@ -319,7 +366,7 @@ ERROR: Cannot create index: 'index_name' already exists.
|
|||||||
The following query shows all defined operator classes:
|
The following query shows all defined operator classes:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT am.amname AS acc_name,
|
SELECT am.amname AS acc_method,
|
||||||
opc.opcname AS ops_name,
|
opc.opcname AS ops_name,
|
||||||
opr.oprname AS ops_comp
|
opr.oprname AS ops_comp
|
||||||
FROM pg_am am, pg_amop amop,
|
FROM pg_am am, pg_amop amop,
|
||||||
@ -327,7 +374,7 @@ SELECT am.amname AS acc_name,
|
|||||||
WHERE amop.amopid = am.oid AND
|
WHERE amop.amopid = am.oid AND
|
||||||
amop.amopclaid = opc.oid AND
|
amop.amopclaid = opc.oid AND
|
||||||
amop.amopopr = opr.oid
|
amop.amopopr = opr.oid
|
||||||
ORDER BY acc_name, ops_name, ops_comp
|
ORDER BY acc_method, ops_name, ops_comp
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.111 2001/07/15 22:48:16 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.112 2001/07/16 05:06:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1100,8 +1100,9 @@ index_register(char *heap,
|
|||||||
newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
|
newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
|
||||||
|
|
||||||
memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
|
memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
|
||||||
/* predicate will likely be null anyway, but may as well copy it */
|
/* predicate will likely be null, but may as well copy it */
|
||||||
newind->il_info->ii_Predicate = copyObject(indexInfo->ii_Predicate);
|
newind->il_info->ii_Predicate = (List *)
|
||||||
|
copyObject(indexInfo->ii_Predicate);
|
||||||
|
|
||||||
newind->il_next = ILHead;
|
newind->il_next = ILHead;
|
||||||
ILHead = newind;
|
ILHead = newind;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.156 2001/07/15 22:48:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.157 2001/07/16 05:06:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -510,7 +510,7 @@ UpdateIndexRelation(Oid indexoid,
|
|||||||
* allocate a Form_pg_index big enough to hold the index-predicate (if
|
* allocate a Form_pg_index big enough to hold the index-predicate (if
|
||||||
* any) in string form
|
* any) in string form
|
||||||
*/
|
*/
|
||||||
if (indexInfo->ii_Predicate != NULL)
|
if (indexInfo->ii_Predicate != NIL)
|
||||||
{
|
{
|
||||||
predString = nodeToString(indexInfo->ii_Predicate);
|
predString = nodeToString(indexInfo->ii_Predicate);
|
||||||
predText = DatumGetTextP(DirectFunctionCall1(textin,
|
predText = DatumGetTextP(DirectFunctionCall1(textin,
|
||||||
@ -586,87 +586,6 @@ UpdateIndexRelation(Oid indexoid,
|
|||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
|
||||||
* UpdateIndexPredicate
|
|
||||||
* ----------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
|
|
||||||
{
|
|
||||||
Node *newPred;
|
|
||||||
char *predString;
|
|
||||||
text *predText;
|
|
||||||
Relation pg_index;
|
|
||||||
HeapTuple tuple;
|
|
||||||
HeapTuple newtup;
|
|
||||||
int i;
|
|
||||||
Datum values[Natts_pg_index];
|
|
||||||
char nulls[Natts_pg_index];
|
|
||||||
char replace[Natts_pg_index];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Construct newPred as a CNF expression equivalent to the OR of the
|
|
||||||
* original partial-index predicate ("oldPred") and the extension
|
|
||||||
* predicate ("predicate").
|
|
||||||
*
|
|
||||||
* This should really try to process the result to change things like
|
|
||||||
* "a>2 OR a>1" to simply "a>1", but for now all it does is make sure
|
|
||||||
* that if the extension predicate is NULL (i.e., it is being extended
|
|
||||||
* to be a complete index), then newPred will be NULL - in effect,
|
|
||||||
* changing "a>2 OR TRUE" to "TRUE". --Nels, Jan '93
|
|
||||||
*/
|
|
||||||
newPred = NULL;
|
|
||||||
if (predicate != NULL)
|
|
||||||
{
|
|
||||||
newPred = (Node *) make_orclause(lcons(make_andclause((List *) predicate),
|
|
||||||
lcons(make_andclause((List *) oldPred),
|
|
||||||
NIL)));
|
|
||||||
newPred = (Node *) cnfify((Expr *) newPred, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* translate the index-predicate to string form */
|
|
||||||
if (newPred != NULL)
|
|
||||||
{
|
|
||||||
predString = nodeToString(newPred);
|
|
||||||
predText = DatumGetTextP(DirectFunctionCall1(textin,
|
|
||||||
CStringGetDatum(predString)));
|
|
||||||
pfree(predString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
predText = DatumGetTextP(DirectFunctionCall1(textin,
|
|
||||||
CStringGetDatum("")));
|
|
||||||
|
|
||||||
/* open the index system catalog relation */
|
|
||||||
pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
|
|
||||||
|
|
||||||
tuple = SearchSysCache(INDEXRELID,
|
|
||||||
ObjectIdGetDatum(indexoid),
|
|
||||||
0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
|
||||||
elog(ERROR, "UpdateIndexPredicate: cache lookup failed for index %u",
|
|
||||||
indexoid);
|
|
||||||
|
|
||||||
for (i = 0; i < Natts_pg_index; i++)
|
|
||||||
{
|
|
||||||
nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';
|
|
||||||
replace[i] = ' ';
|
|
||||||
values[i] = (Datum) NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
replace[Anum_pg_index_indpred - 1] = 'r';
|
|
||||||
values[Anum_pg_index_indpred - 1] = PointerGetDatum(predText);
|
|
||||||
|
|
||||||
newtup = heap_modifytuple(tuple, pg_index, values, nulls, replace);
|
|
||||||
|
|
||||||
simple_heap_update(pg_index, &newtup->t_self, newtup);
|
|
||||||
|
|
||||||
heap_freetuple(newtup);
|
|
||||||
ReleaseSysCache(tuple);
|
|
||||||
|
|
||||||
heap_close(pg_index, RowExclusiveLock);
|
|
||||||
pfree(predText);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* InitIndexStrategy
|
* InitIndexStrategy
|
||||||
*
|
*
|
||||||
@ -1084,7 +1003,7 @@ BuildIndexInfo(HeapTuple indexTuple)
|
|||||||
pfree(predString);
|
pfree(predString);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ii->ii_Predicate = NULL;
|
ii->ii_Predicate = NIL;
|
||||||
|
|
||||||
/* Other info */
|
/* Other info */
|
||||||
ii->ii_Unique = indexStruct->indisunique;
|
ii->ii_Unique = indexStruct->indisunique;
|
||||||
@ -1684,7 +1603,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
Datum attdata[INDEX_MAX_KEYS];
|
Datum attdata[INDEX_MAX_KEYS];
|
||||||
char nulls[INDEX_MAX_KEYS];
|
char nulls[INDEX_MAX_KEYS];
|
||||||
double reltuples;
|
double reltuples;
|
||||||
Node *predicate = indexInfo->ii_Predicate;
|
List *predicate = indexInfo->ii_Predicate;
|
||||||
TupleTable tupleTable;
|
TupleTable tupleTable;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
@ -1708,7 +1627,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
* We construct the ExprContext anyway since we need a per-tuple
|
* We construct the ExprContext anyway since we need a per-tuple
|
||||||
* temporary memory context for function evaluation -- tgl July 00
|
* temporary memory context for function evaluation -- tgl July 00
|
||||||
*/
|
*/
|
||||||
if (predicate != NULL)
|
if (predicate != NIL)
|
||||||
{
|
{
|
||||||
tupleTable = ExecCreateTupleTable(1);
|
tupleTable = ExecCreateTupleTable(1);
|
||||||
slot = ExecAllocTableSlot(tupleTable);
|
slot = ExecAllocTableSlot(tupleTable);
|
||||||
@ -1831,12 +1750,12 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
* VACUUM doesn't complain about tuple count mismatch for partial
|
* VACUUM doesn't complain about tuple count mismatch for partial
|
||||||
* indexes.
|
* indexes.
|
||||||
*/
|
*/
|
||||||
if (predicate != NULL)
|
if (predicate != NIL)
|
||||||
{
|
{
|
||||||
if (! tupleIsAlive)
|
if (! tupleIsAlive)
|
||||||
continue;
|
continue;
|
||||||
ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
|
ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
|
||||||
if (!ExecQual((List *) predicate, econtext, false))
|
if (!ExecQual(predicate, econtext, false))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1865,7 +1784,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
|
|
||||||
if (predicate != NULL)
|
if (predicate != NIL)
|
||||||
ExecDropTupleTable(tupleTable, true);
|
ExecDropTupleTable(tupleTable, true);
|
||||||
FreeExprContext(econtext);
|
FreeExprContext(econtext);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.135 2001/07/15 22:48:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.136 2001/07/16 05:06:57 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The PerformAddAttribute() code, like most of the relation
|
* The PerformAddAttribute() code, like most of the relation
|
||||||
@ -1882,7 +1882,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
|
|||||||
indexInfo->ii_NumIndexAttrs = 1;
|
indexInfo->ii_NumIndexAttrs = 1;
|
||||||
indexInfo->ii_NumKeyAttrs = 1;
|
indexInfo->ii_NumKeyAttrs = 1;
|
||||||
indexInfo->ii_KeyAttrNumbers[0] = 1;
|
indexInfo->ii_KeyAttrNumbers[0] = 1;
|
||||||
indexInfo->ii_Predicate = NULL;
|
indexInfo->ii_Predicate = NIL;
|
||||||
indexInfo->ii_FuncOid = InvalidOid;
|
indexInfo->ii_FuncOid = InvalidOid;
|
||||||
indexInfo->ii_Unique = false;
|
indexInfo->ii_Unique = false;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.51 2001/07/15 22:48:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.52 2001/07/16 05:06:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -45,8 +45,6 @@
|
|||||||
|
|
||||||
/* non-export function prototypes */
|
/* non-export function prototypes */
|
||||||
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
|
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
|
||||||
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
|
|
||||||
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
|
|
||||||
static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP,
|
static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP,
|
||||||
IndexElem *funcIndex,
|
IndexElem *funcIndex,
|
||||||
Oid relId,
|
Oid relId,
|
||||||
@ -144,12 +142,8 @@ DefineIndex(char *heapRelationName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the partial-index predicate from parsetree form to plan
|
* Convert the partial-index predicate from parsetree form to
|
||||||
* form, so it can be readily evaluated during index creation. Note:
|
* an implicit-AND qual expression, for easier evaluation at runtime.
|
||||||
* "predicate" comes in as a list containing (1) the predicate itself
|
|
||||||
* (a where_clause), and (2) a corresponding range table.
|
|
||||||
*
|
|
||||||
* [(1) is 'predicate' and (2) is 'rangetable' now. - ay 10/94]
|
|
||||||
*/
|
*/
|
||||||
if (predicate != NULL && rangetable != NIL)
|
if (predicate != NULL && rangetable != NIL)
|
||||||
{
|
{
|
||||||
@ -166,7 +160,7 @@ DefineIndex(char *heapRelationName,
|
|||||||
* structure
|
* structure
|
||||||
*/
|
*/
|
||||||
indexInfo = makeNode(IndexInfo);
|
indexInfo = makeNode(IndexInfo);
|
||||||
indexInfo->ii_Predicate = (Node *) cnfPred;
|
indexInfo->ii_Predicate = cnfPred;
|
||||||
indexInfo->ii_FuncOid = InvalidOid;
|
indexInfo->ii_FuncOid = InvalidOid;
|
||||||
indexInfo->ii_Unique = unique;
|
indexInfo->ii_Unique = unique;
|
||||||
|
|
||||||
@ -218,155 +212,30 @@ DefineIndex(char *heapRelationName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ExtendIndex
|
|
||||||
* Extends a partial index.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
|
|
||||||
{
|
|
||||||
Relation heapRelation;
|
|
||||||
Relation indexRelation;
|
|
||||||
Oid accessMethodId,
|
|
||||||
indexId,
|
|
||||||
relationId;
|
|
||||||
HeapTuple tuple;
|
|
||||||
Form_pg_index index;
|
|
||||||
List *cnfPred = NIL;
|
|
||||||
IndexInfo *indexInfo;
|
|
||||||
Node *oldPred;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get index's relation id and access method id from pg_class
|
|
||||||
*/
|
|
||||||
tuple = SearchSysCache(RELNAME,
|
|
||||||
PointerGetDatum(indexRelationName),
|
|
||||||
0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
|
||||||
elog(ERROR, "ExtendIndex: index \"%s\" not found",
|
|
||||||
indexRelationName);
|
|
||||||
indexId = tuple->t_data->t_oid;
|
|
||||||
accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam;
|
|
||||||
ReleaseSysCache(tuple);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extract info from the pg_index tuple for the index
|
|
||||||
*/
|
|
||||||
tuple = SearchSysCache(INDEXRELID,
|
|
||||||
ObjectIdGetDatum(indexId),
|
|
||||||
0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
|
||||||
elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
|
|
||||||
indexRelationName);
|
|
||||||
index = (Form_pg_index) GETSTRUCT(tuple);
|
|
||||||
Assert(index->indexrelid == indexId);
|
|
||||||
relationId = index->indrelid;
|
|
||||||
indexInfo = BuildIndexInfo(tuple);
|
|
||||||
oldPred = indexInfo->ii_Predicate;
|
|
||||||
ReleaseSysCache(tuple);
|
|
||||||
|
|
||||||
if (oldPred == NULL)
|
|
||||||
elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
|
|
||||||
indexRelationName);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the extension predicate from parsetree form to plan form,
|
|
||||||
* so it can be readily evaluated during index creation. Note:
|
|
||||||
* "predicate" comes in two parts (1) the predicate expression itself,
|
|
||||||
* and (2) a corresponding range table.
|
|
||||||
*
|
|
||||||
* XXX I think this code is broken --- index_build expects a single
|
|
||||||
* expression not a list --- tgl Jul 00
|
|
||||||
*/
|
|
||||||
if (rangetable != NIL)
|
|
||||||
{
|
|
||||||
cnfPred = cnfify((Expr *) copyObject(predicate), true);
|
|
||||||
fix_opids((Node *) cnfPred);
|
|
||||||
CheckPredicate(cnfPred, rangetable, relationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass new predicate to index_build */
|
|
||||||
indexInfo->ii_Predicate = (Node *) cnfPred;
|
|
||||||
|
|
||||||
/* Open heap and index rels, and get suitable locks */
|
|
||||||
heapRelation = heap_open(relationId, ShareLock);
|
|
||||||
indexRelation = index_open(indexId);
|
|
||||||
|
|
||||||
/* Obtain exclusive lock on it, just to be sure */
|
|
||||||
LockRelation(indexRelation, AccessExclusiveLock);
|
|
||||||
|
|
||||||
InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
|
|
||||||
indexRelation, accessMethodId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX currently BROKEN: if we want to support EXTEND INDEX, oldPred
|
|
||||||
* needs to be passed through to IndexBuildHeapScan. We could do this
|
|
||||||
* without help from the index AMs if we added an oldPred field to the
|
|
||||||
* IndexInfo struct. Currently I'm expecting that EXTEND INDEX will
|
|
||||||
* get removed, so I'm not going to do that --- tgl 7/14/01
|
|
||||||
*/
|
|
||||||
|
|
||||||
index_build(heapRelation, indexRelation, indexInfo);
|
|
||||||
|
|
||||||
/* heap and index rels are closed as a side-effect of index_build */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CheckPredicate
|
* CheckPredicate
|
||||||
* Checks that the given list of partial-index predicates refer
|
* Checks that the given list of partial-index predicates refer
|
||||||
* (via the given range table) only to the given base relation oid,
|
* (via the given range table) only to the given base relation oid.
|
||||||
* and that they're in a form the planner can handle, i.e.,
|
*
|
||||||
* boolean combinations of "ATTR OP CONST" (yes, for now, the ATTR
|
* This used to also constrain the form of the predicate to forms that
|
||||||
* has to be on the left).
|
* indxpath.c could do something with. However, that seems overly
|
||||||
|
* restrictive. One useful application of partial indexes is to apply
|
||||||
|
* a UNIQUE constraint across a subset of a table, and in that scenario
|
||||||
|
* any evaluatable predicate will work. So accept any predicate here
|
||||||
|
* (except ones requiring a plan), and let indxpath.c fend for itself.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
|
CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
|
||||||
{
|
{
|
||||||
List *item;
|
if (length(rangeTable) != 1 || getrelid(1, rangeTable) != baseRelOid)
|
||||||
|
|
||||||
foreach(item, predList)
|
|
||||||
CheckPredExpr(lfirst(item), rangeTable, baseRelOid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid)
|
|
||||||
{
|
|
||||||
List *clauses = NIL,
|
|
||||||
*clause;
|
|
||||||
|
|
||||||
if (is_opclause(predicate))
|
|
||||||
{
|
|
||||||
CheckPredClause((Expr *) predicate, rangeTable, baseRelOid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (or_clause(predicate) || and_clause(predicate))
|
|
||||||
clauses = ((Expr *) predicate)->args;
|
|
||||||
else
|
|
||||||
elog(ERROR, "Unsupported partial-index predicate expression type");
|
|
||||||
|
|
||||||
foreach(clause, clauses)
|
|
||||||
CheckPredExpr(lfirst(clause), rangeTable, baseRelOid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
|
|
||||||
{
|
|
||||||
Var *pred_var;
|
|
||||||
Const *pred_const;
|
|
||||||
|
|
||||||
pred_var = (Var *) get_leftop(predicate);
|
|
||||||
pred_const = (Const *) get_rightop(predicate);
|
|
||||||
|
|
||||||
if (!IsA(predicate->oper, Oper) ||
|
|
||||||
!IsA(pred_var, Var) ||
|
|
||||||
!IsA(pred_const, Const))
|
|
||||||
elog(ERROR, "Unsupported partial-index predicate clause type");
|
|
||||||
|
|
||||||
if (getrelid(pred_var->varno, rangeTable) != baseRelOid)
|
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"Partial-index predicates may refer only to the base relation");
|
"Partial-index predicates may refer only to the base relation");
|
||||||
|
|
||||||
|
if (contain_subplans((Node *) predList))
|
||||||
|
elog(ERROR, "Cannot use subselect in index predicate");
|
||||||
|
if (contain_agg_clause((Node *) predList))
|
||||||
|
elog(ERROR, "Cannot use aggregate in index predicate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.76 2001/07/15 22:48:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.77 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -641,7 +641,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
|||||||
for (i = 0; i < numIndices; i++)
|
for (i = 0; i < numIndices; i++)
|
||||||
{
|
{
|
||||||
IndexInfo *indexInfo;
|
IndexInfo *indexInfo;
|
||||||
Node *predicate;
|
List *predicate;
|
||||||
InsertIndexResult result;
|
InsertIndexResult result;
|
||||||
|
|
||||||
if (relationDescs[i] == NULL)
|
if (relationDescs[i] == NULL)
|
||||||
@ -649,10 +649,10 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
|||||||
|
|
||||||
indexInfo = indexInfoArray[i];
|
indexInfo = indexInfoArray[i];
|
||||||
predicate = indexInfo->ii_Predicate;
|
predicate = indexInfo->ii_Predicate;
|
||||||
if (predicate != NULL)
|
if (predicate != NIL)
|
||||||
{
|
{
|
||||||
/* Skip this index-update if the predicate isn't satisfied */
|
/* Skip this index-update if the predicate isn't satisfied */
|
||||||
if (!ExecQual((List *) predicate, econtext, false))
|
if (!ExecQual(predicate, econtext, false))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.108 2001/06/25 21:11:43 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.109 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -195,8 +195,13 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
|||||||
* 4. Generate an indexscan path if there are relevant restriction
|
* 4. Generate an indexscan path if there are relevant restriction
|
||||||
* clauses OR the index ordering is potentially useful for later
|
* clauses OR the index ordering is potentially useful for later
|
||||||
* merging or final output ordering.
|
* merging or final output ordering.
|
||||||
|
*
|
||||||
|
* If there is a predicate, consider it anyway since the index
|
||||||
|
* predicate has already been found to match the query.
|
||||||
*/
|
*/
|
||||||
if (restrictclauses != NIL || useful_pathkeys != NIL)
|
if (restrictclauses != NIL ||
|
||||||
|
useful_pathkeys != NIL ||
|
||||||
|
index->indpred != NIL)
|
||||||
add_path(rel, (Path *)
|
add_path(rel, (Path *)
|
||||||
create_index_path(root, rel, index,
|
create_index_path(root, rel, index,
|
||||||
restrictclauses,
|
restrictclauses,
|
||||||
@ -974,18 +979,18 @@ pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list)
|
|||||||
* clauses (those in restrictinfo_list). --Nels, Dec '92
|
* clauses (those in restrictinfo_list). --Nels, Dec '92
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (predicate_list == NULL)
|
if (predicate_list == NIL)
|
||||||
return true; /* no predicate: the index is usable */
|
return true; /* no predicate: the index is usable */
|
||||||
if (restrictinfo_list == NULL)
|
if (restrictinfo_list == NIL)
|
||||||
return false; /* no restriction clauses: the test must
|
return false; /* no restriction clauses: the test must
|
||||||
* fail */
|
* fail */
|
||||||
|
|
||||||
foreach(pred, predicate_list)
|
foreach(pred, predicate_list)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if any clause is not implied, the whole predicate is not
|
* if any clause is not implied, the whole predicate is not
|
||||||
* implied
|
* implied. Note that checking for sub-ANDs here is redundant
|
||||||
|
* if the predicate has been cnfify()-ed.
|
||||||
*/
|
*/
|
||||||
if (and_clause(lfirst(pred)))
|
if (and_clause(lfirst(pred)))
|
||||||
{
|
{
|
||||||
@ -1011,15 +1016,16 @@ pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list)
|
|||||||
static bool
|
static bool
|
||||||
one_pred_test(Expr *predicate, List *restrictinfo_list)
|
one_pred_test(Expr *predicate, List *restrictinfo_list)
|
||||||
{
|
{
|
||||||
RestrictInfo *restrictinfo;
|
|
||||||
List *item;
|
List *item;
|
||||||
|
|
||||||
Assert(predicate != NULL);
|
Assert(predicate != NULL);
|
||||||
foreach(item, restrictinfo_list)
|
foreach(item, restrictinfo_list)
|
||||||
{
|
{
|
||||||
restrictinfo = (RestrictInfo *) lfirst(item);
|
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(item);
|
||||||
|
|
||||||
/* if any clause implies the predicate, return true */
|
/* if any clause implies the predicate, return true */
|
||||||
if (one_pred_clause_expr_test(predicate, (Node *) restrictinfo->clause))
|
if (one_pred_clause_expr_test(predicate,
|
||||||
|
(Node *) restrictinfo->clause))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1055,7 +1061,6 @@ one_pred_clause_expr_test(Expr *predicate, Node *clause)
|
|||||||
items = ((Expr *) clause)->args;
|
items = ((Expr *) clause)->args;
|
||||||
foreach(item, items)
|
foreach(item, items)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if any AND item implies the predicate, the whole clause
|
* if any AND item implies the predicate, the whole clause
|
||||||
* does
|
* does
|
||||||
@ -1102,7 +1107,6 @@ one_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
items = predicate->args;
|
items = predicate->args;
|
||||||
foreach(item, items)
|
foreach(item, items)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if any item is not implied, the whole predicate is not
|
* if any item is not implied, the whole predicate is not
|
||||||
* implied
|
* implied
|
||||||
@ -1177,26 +1181,30 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
test_strategy;
|
test_strategy;
|
||||||
Oper *test_oper;
|
Oper *test_oper;
|
||||||
Expr *test_expr;
|
Expr *test_expr;
|
||||||
bool test_result,
|
Datum test_result;
|
||||||
isNull;
|
bool isNull;
|
||||||
Relation relation;
|
Relation relation;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
ScanKeyData entry[3];
|
ScanKeyData entry[3];
|
||||||
Form_pg_amop aform;
|
Form_pg_amop aform;
|
||||||
|
ExprContext *econtext;
|
||||||
|
|
||||||
|
/* Check the basic form; for now, only allow the simplest case */
|
||||||
|
/* Note caller already verified is_opclause(predicate) */
|
||||||
|
if (!is_opclause(clause))
|
||||||
|
return false;
|
||||||
|
|
||||||
pred_var = (Var *) get_leftop(predicate);
|
pred_var = (Var *) get_leftop(predicate);
|
||||||
pred_const = (Const *) get_rightop(predicate);
|
pred_const = (Const *) get_rightop(predicate);
|
||||||
clause_var = (Var *) get_leftop((Expr *) clause);
|
clause_var = (Var *) get_leftop((Expr *) clause);
|
||||||
clause_const = (Const *) get_rightop((Expr *) clause);
|
clause_const = (Const *) get_rightop((Expr *) clause);
|
||||||
|
|
||||||
/* Check the basic form; for now, only allow the simplest case */
|
if (!IsA(clause_var, Var) ||
|
||||||
if (!is_opclause(clause) ||
|
|
||||||
!IsA(clause_var, Var) ||
|
|
||||||
clause_const == NULL ||
|
clause_const == NULL ||
|
||||||
!IsA(clause_const, Const) ||
|
!IsA(clause_const, Const) ||
|
||||||
!IsA(predicate->oper, Oper) ||
|
|
||||||
!IsA(pred_var, Var) ||
|
!IsA(pred_var, Var) ||
|
||||||
|
pred_const == NULL ||
|
||||||
!IsA(pred_const, Const))
|
!IsA(pred_const, Const))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1211,10 +1219,15 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
|
pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
|
||||||
clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
|
clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Find a "btree" strategy number for the pred_op
|
* 1. Find a "btree" strategy number for the pred_op
|
||||||
|
*
|
||||||
|
* XXX consider using syscache lookups for these searches. Right
|
||||||
|
* now we don't have caches that match all of the search conditions,
|
||||||
|
* but reconsider it after upcoming restructuring of pg_opclass.
|
||||||
*/
|
*/
|
||||||
|
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&entry[0], 0,
|
ScanKeyEntryInitialize(&entry[0], 0,
|
||||||
Anum_pg_amop_amopid,
|
Anum_pg_amop_amopid,
|
||||||
F_OIDEQ,
|
F_OIDEQ,
|
||||||
@ -1225,8 +1238,6 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
F_OIDEQ,
|
F_OIDEQ,
|
||||||
ObjectIdGetDatum(pred_op));
|
ObjectIdGetDatum(pred_op));
|
||||||
|
|
||||||
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following assumes that any given operator will only be in a
|
* The following assumes that any given operator will only be in a
|
||||||
* single btree operator class. This is true at least for all the
|
* single btree operator class. This is true at least for all the
|
||||||
@ -1254,7 +1265,6 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2. From the same opclass, find a strategy num for the clause_op
|
* 2. From the same opclass, find a strategy num for the clause_op
|
||||||
*/
|
*/
|
||||||
@ -1281,13 +1291,12 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
|
|
||||||
/* Get the restriction clause operator's strategy number (1 to 5) */
|
/* Get the restriction clause operator's strategy number (1 to 5) */
|
||||||
clause_strategy = (StrategyNumber) aform->amopstrategy;
|
clause_strategy = (StrategyNumber) aform->amopstrategy;
|
||||||
heap_endscan(scan);
|
|
||||||
|
|
||||||
|
heap_endscan(scan);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 3. Look up the "test" strategy number in the implication table
|
* 3. Look up the "test" strategy number in the implication table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
|
test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
|
||||||
if (test_strategy == 0)
|
if (test_strategy == 0)
|
||||||
{
|
{
|
||||||
@ -1298,7 +1307,6 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
/*
|
/*
|
||||||
* 4. From the same opclass, find the operator for the test strategy
|
* 4. From the same opclass, find the operator for the test strategy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&entry[2], 0,
|
ScanKeyEntryInitialize(&entry[2], 0,
|
||||||
Anum_pg_amop_amopstrategy,
|
Anum_pg_amop_amopstrategy,
|
||||||
F_INT2EQ,
|
F_INT2EQ,
|
||||||
@ -1329,19 +1337,20 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
|||||||
InvalidOid, /* opid */
|
InvalidOid, /* opid */
|
||||||
BOOLOID); /* opresulttype */
|
BOOLOID); /* opresulttype */
|
||||||
replace_opid(test_oper);
|
replace_opid(test_oper);
|
||||||
|
|
||||||
test_expr = make_opclause(test_oper,
|
test_expr = make_opclause(test_oper,
|
||||||
copyObject(clause_const),
|
(Var *) clause_const,
|
||||||
copyObject(pred_const));
|
(Var *) pred_const);
|
||||||
|
|
||||||
test_result = ExecEvalExpr((Node *) test_expr, NULL, &isNull, NULL);
|
econtext = MakeExprContext(NULL, TransactionCommandContext);
|
||||||
|
test_result = ExecEvalExpr((Node *) test_expr, econtext, &isNull, NULL);
|
||||||
|
FreeExprContext(econtext);
|
||||||
|
|
||||||
if (isNull)
|
if (isNull)
|
||||||
{
|
{
|
||||||
elog(DEBUG, "clause_pred_clause_test: null test result");
|
elog(DEBUG, "clause_pred_clause_test: null test result");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return test_result;
|
return DatumGetBool(test_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.74 2001/06/05 05:26:04 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.75 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -362,6 +362,13 @@ create_index_path(Query *root,
|
|||||||
pathnode->alljoinquals = false;
|
pathnode->alljoinquals = false;
|
||||||
pathnode->rows = rel->rows;
|
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);
|
cost_index(&pathnode->path, root, rel, index, indexquals, false);
|
||||||
|
|
||||||
return pathnode;
|
return pathnode;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.192 2001/07/04 17:36:54 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.193 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -45,7 +45,6 @@ static Query *transformStmt(ParseState *pstate, Node *stmt);
|
|||||||
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
|
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
|
||||||
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
|
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
|
||||||
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
|
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
|
||||||
static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
|
|
||||||
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
|
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
|
||||||
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
|
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
|
||||||
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
|
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
|
||||||
@ -148,10 +147,6 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
|||||||
result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
|
result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ExtendStmt:
|
|
||||||
result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_RuleStmt:
|
case T_RuleStmt:
|
||||||
result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
|
result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
|
||||||
break;
|
break;
|
||||||
@ -1630,43 +1625,34 @@ static Query *
|
|||||||
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
||||||
{
|
{
|
||||||
Query *qry;
|
Query *qry;
|
||||||
|
RangeTblEntry *rte;
|
||||||
|
|
||||||
qry = makeNode(Query);
|
qry = makeNode(Query);
|
||||||
qry->commandType = CMD_UTILITY;
|
qry->commandType = CMD_UTILITY;
|
||||||
|
|
||||||
/* take care of the where clause */
|
/* take care of the where clause */
|
||||||
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
|
if (stmt->whereClause)
|
||||||
|
{
|
||||||
qry->hasSubLinks = pstate->p_hasSubLinks;
|
/*
|
||||||
|
* Put the parent table into the rtable so that the WHERE clause can
|
||||||
stmt->rangetable = pstate->p_rtable;
|
* refer to its fields without qualification. Note that this only
|
||||||
|
* works if the parent table already exists --- so we can't easily
|
||||||
qry->utilityStmt = (Node *) stmt;
|
* support predicates on indexes created implicitly by CREATE TABLE.
|
||||||
|
* Fortunately, that's not necessary.
|
||||||
return qry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* transformExtendStmt -
|
|
||||||
* transform the qualifications of the Extend Index Statement
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static Query *
|
rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true);
|
||||||
transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
|
|
||||||
{
|
|
||||||
Query *qry;
|
|
||||||
|
|
||||||
qry = makeNode(Query);
|
/* no to join list, yes to namespace */
|
||||||
qry->commandType = CMD_UTILITY;
|
addRTEtoQuery(pstate, rte, false, true);
|
||||||
|
|
||||||
/* take care of the where clause */
|
|
||||||
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
|
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
|
||||||
|
}
|
||||||
|
|
||||||
qry->hasSubLinks = pstate->p_hasSubLinks;
|
qry->hasSubLinks = pstate->p_hasSubLinks;
|
||||||
|
|
||||||
stmt->rangetable = pstate->p_rtable;
|
stmt->rangetable = pstate->p_rtable;
|
||||||
|
|
||||||
qry->utilityStmt = (Node *) stmt;
|
qry->utilityStmt = (Node *) stmt;
|
||||||
|
|
||||||
return qry;
|
return qry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.236 2001/07/12 18:02:59 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.237 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -135,7 +135,7 @@ static void doNegateFloat(Value *v);
|
|||||||
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
|
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
|
||||||
CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
|
CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
|
||||||
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
|
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
|
||||||
DropUserStmt, DropdbStmt, ExplainStmt, ExtendStmt, FetchStmt,
|
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
|
||||||
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
|
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
|
||||||
NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
|
NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
|
||||||
RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
|
RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
|
||||||
@ -345,7 +345,7 @@ static void doNegateFloat(Value *v);
|
|||||||
BACKWARD, BEFORE, BINARY, BIT,
|
BACKWARD, BEFORE, BINARY, BIT,
|
||||||
CACHE, CHECKPOINT, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
CACHE, CHECKPOINT, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
||||||
DATABASE, DELIMITERS, DO,
|
DATABASE, DELIMITERS, DO,
|
||||||
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
|
EACH, ENCODING, EXCLUSIVE, EXPLAIN,
|
||||||
FORCE, FORWARD, FUNCTION, HANDLER,
|
FORCE, FORWARD, FUNCTION, HANDLER,
|
||||||
ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
|
ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
|
||||||
LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
|
LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
|
||||||
@ -450,7 +450,6 @@ stmt : AlterSchemaStmt
|
|||||||
| DropPLangStmt
|
| DropPLangStmt
|
||||||
| DropTrigStmt
|
| DropTrigStmt
|
||||||
| DropUserStmt
|
| DropUserStmt
|
||||||
| ExtendStmt
|
|
||||||
| ExplainStmt
|
| ExplainStmt
|
||||||
| FetchStmt
|
| FetchStmt
|
||||||
| GrantStmt
|
| GrantStmt
|
||||||
@ -2392,14 +2391,14 @@ RevokeStmt: REVOKE privileges ON opt_table relation_name_list FROM grantee_list
|
|||||||
*
|
*
|
||||||
* QUERY:
|
* QUERY:
|
||||||
* create index <indexname> on <relname>
|
* create index <indexname> on <relname>
|
||||||
* using <access> "(" (<col> with <op>)+ ")" [with
|
* [ using <access> ] "(" (<col> with <op>)+ ")"
|
||||||
* <target_list>]
|
* [ with <parameters> ]
|
||||||
|
* [ where <predicate> ]
|
||||||
*
|
*
|
||||||
* [where <qual>] is not supported anymore
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
|
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);
|
IndexStmt *n = makeNode(IndexStmt);
|
||||||
n->unique = $2;
|
n->unique = $2;
|
||||||
@ -2408,7 +2407,7 @@ IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
|
|||||||
n->accessMethod = $7;
|
n->accessMethod = $7;
|
||||||
n->indexParams = $9;
|
n->indexParams = $9;
|
||||||
n->withClause = $11;
|
n->withClause = $11;
|
||||||
n->whereClause = NULL;
|
n->whereClause = $12;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -2471,22 +2470,6 @@ opt_class: class
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* QUERY:
|
|
||||||
* extend index <indexname> [where <qual>]
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
ExtendStmt: EXTEND INDEX index_name where_clause
|
|
||||||
{
|
|
||||||
ExtendStmt *n = makeNode(ExtendStmt);
|
|
||||||
n->idxname = $3;
|
|
||||||
n->whereClause = $4;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* QUERY:
|
* QUERY:
|
||||||
@ -5775,7 +5758,6 @@ ColLabel: ColId { $$ = $1; }
|
|||||||
| EXCEPT { $$ = "except"; }
|
| EXCEPT { $$ = "except"; }
|
||||||
| EXISTS { $$ = "exists"; }
|
| EXISTS { $$ = "exists"; }
|
||||||
| EXPLAIN { $$ = "explain"; }
|
| EXPLAIN { $$ = "explain"; }
|
||||||
| EXTEND { $$ = "extend"; }
|
|
||||||
| EXTRACT { $$ = "extract"; }
|
| EXTRACT { $$ = "extract"; }
|
||||||
| FALSE_P { $$ = "false"; }
|
| FALSE_P { $$ = "false"; }
|
||||||
| FLOAT { $$ = "float"; }
|
| FLOAT { $$ = "float"; }
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.93 2001/06/19 22:39:11 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.94 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -109,7 +109,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"execute", EXECUTE},
|
{"execute", EXECUTE},
|
||||||
{"exists", EXISTS},
|
{"exists", EXISTS},
|
||||||
{"explain", EXPLAIN},
|
{"explain", EXPLAIN},
|
||||||
{"extend", EXTEND},
|
|
||||||
{"extract", EXTRACT},
|
{"extract", EXTRACT},
|
||||||
{"false", FALSE_P},
|
{"false", FALSE_P},
|
||||||
{"fetch", FETCH},
|
{"fetch", FETCH},
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.114 2001/06/18 16:13:21 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.115 2001/07/16 05:06:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -567,18 +567,6 @@ ProcessUtility(Node *parsetree,
|
|||||||
DefineSequence((CreateSeqStmt *) parsetree);
|
DefineSequence((CreateSeqStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ExtendStmt:
|
|
||||||
{
|
|
||||||
ExtendStmt *stmt = (ExtendStmt *) parsetree;
|
|
||||||
|
|
||||||
set_ps_display(commandTag = "EXTEND");
|
|
||||||
|
|
||||||
ExtendIndex(stmt->idxname, /* index name */
|
|
||||||
(Expr *) stmt->whereClause, /* where */
|
|
||||||
stmt->rangetable);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_RemoveAggrStmt:
|
case T_RemoveAggrStmt:
|
||||||
{
|
{
|
||||||
RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
|
RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.79 2001/07/10 00:02:02 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.80 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -40,6 +40,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "catalog/heap.h"
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_shadow.h"
|
#include "catalog/pg_shadow.h"
|
||||||
@ -554,6 +555,64 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* get_expr - Decompile an expression tree
|
||||||
|
*
|
||||||
|
* Input: an expression tree in nodeToString form, and a relation OID
|
||||||
|
*
|
||||||
|
* Output: reverse-listed expression
|
||||||
|
*
|
||||||
|
* Currently, the expression can only refer to a single relation, namely
|
||||||
|
* the one specified by the second parameter. This is sufficient for
|
||||||
|
* partial indexes, column default expressions, etc.
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
pg_get_expr(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
text *expr = PG_GETARG_TEXT_P(0);
|
||||||
|
Oid relid = PG_GETARG_OID(1);
|
||||||
|
text *result;
|
||||||
|
Node *node;
|
||||||
|
List *context;
|
||||||
|
char *exprstr;
|
||||||
|
char *relname;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
/* Get the name for the relation */
|
||||||
|
relname = get_rel_name(relid);
|
||||||
|
if (relname == NULL)
|
||||||
|
PG_RETURN_NULL(); /* should we raise an error? */
|
||||||
|
|
||||||
|
/* Convert input TEXT object to C string */
|
||||||
|
exprstr = DatumGetCString(DirectFunctionCall1(textout,
|
||||||
|
PointerGetDatum(expr)));
|
||||||
|
|
||||||
|
/* Convert expression to node tree */
|
||||||
|
node = (Node *) stringToNode(exprstr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If top level is a List, assume it is an implicit-AND structure,
|
||||||
|
* and convert to explicit AND. This is needed for partial index
|
||||||
|
* predicates.
|
||||||
|
*/
|
||||||
|
if (node && IsA(node, List))
|
||||||
|
{
|
||||||
|
node = (Node *) make_ands_explicit((List *) node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deparse */
|
||||||
|
context = deparse_context_for(relname, relid);
|
||||||
|
str = deparse_expression(node, context, false);
|
||||||
|
|
||||||
|
/* Pass the result back as TEXT */
|
||||||
|
result = DatumGetTextP(DirectFunctionCall1(textin,
|
||||||
|
CStringGetDatum(str)));
|
||||||
|
|
||||||
|
PG_RETURN_TEXT_P(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* get_userbyid - Get a user name by usesysid and
|
* get_userbyid - Get a user name by usesysid and
|
||||||
* fallback to 'unknown (UID=n)'
|
* fallback to 'unknown (UID=n)'
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.94 2001/06/25 21:11:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.95 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -86,6 +86,7 @@
|
|||||||
#include "optimizer/cost.h"
|
#include "optimizer/cost.h"
|
||||||
#include "optimizer/pathnode.h"
|
#include "optimizer/pathnode.h"
|
||||||
#include "optimizer/plancat.h"
|
#include "optimizer/plancat.h"
|
||||||
|
#include "optimizer/prep.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
#include "parser/parse_oper.h"
|
#include "parser/parse_oper.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
@ -2950,24 +2951,63 @@ genericcostestimate(Query *root, RelOptInfo *rel,
|
|||||||
{
|
{
|
||||||
double numIndexTuples;
|
double numIndexTuples;
|
||||||
double numIndexPages;
|
double numIndexPages;
|
||||||
|
List *selectivityQuals = indexQuals;
|
||||||
/* Estimate the fraction of main-table tuples that will be visited */
|
|
||||||
*indexSelectivity = clauselist_selectivity(root, indexQuals,
|
|
||||||
lfirsti(rel->relids));
|
|
||||||
|
|
||||||
/* Estimate the number of index tuples that will be visited */
|
|
||||||
numIndexTuples = *indexSelectivity * index->tuples;
|
|
||||||
|
|
||||||
/* Estimate the number of index pages that will be retrieved */
|
|
||||||
numIndexPages = *indexSelectivity * index->pages;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always estimate at least one tuple and page are touched, even when
|
* If the index is partial, AND the index predicate with the explicitly
|
||||||
|
* given indexquals to produce a more accurate idea of the index
|
||||||
|
* restriction. This may produce redundant clauses, which we hope that
|
||||||
|
* cnfify and clauselist_selectivity will deal with intelligently.
|
||||||
|
*
|
||||||
|
* Note that index->indpred and indexQuals are both in implicit-AND
|
||||||
|
* form to start with, which we have to make explicit to hand to
|
||||||
|
* canonicalize_qual, and then we get back implicit-AND form again.
|
||||||
|
*/
|
||||||
|
if (index->indpred != NIL)
|
||||||
|
{
|
||||||
|
Expr *andedQuals;
|
||||||
|
|
||||||
|
andedQuals = make_ands_explicit(nconc(listCopy(index->indpred),
|
||||||
|
indexQuals));
|
||||||
|
selectivityQuals = canonicalize_qual(andedQuals, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estimate the fraction of main-table tuples that will be visited */
|
||||||
|
*indexSelectivity = clauselist_selectivity(root, selectivityQuals,
|
||||||
|
lfirsti(rel->relids));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
numIndexTuples = *indexSelectivity * rel->tuples;
|
||||||
|
|
||||||
|
if (numIndexTuples > index->tuples)
|
||||||
|
numIndexTuples = index->tuples;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always estimate at least one tuple is touched, even when
|
||||||
* indexSelectivity estimate is tiny.
|
* indexSelectivity estimate is tiny.
|
||||||
*/
|
*/
|
||||||
if (numIndexTuples < 1.0)
|
if (numIndexTuples < 1.0)
|
||||||
numIndexTuples = 1.0;
|
numIndexTuples = 1.0;
|
||||||
if (numIndexPages < 1.0)
|
|
||||||
|
/*
|
||||||
|
* Estimate the number of index pages that will be retrieved.
|
||||||
|
*
|
||||||
|
* For all currently-supported index types, the first page of the index
|
||||||
|
* is a metadata page, and we should figure on fetching that plus a
|
||||||
|
* pro-rated fraction of the remaining pages.
|
||||||
|
*/
|
||||||
|
if (index->pages > 1 && index->tuples > 0)
|
||||||
|
{
|
||||||
|
numIndexPages = (numIndexTuples / index->tuples) * (index->pages - 1);
|
||||||
|
numIndexPages += 1; /* count the metapage too */
|
||||||
|
numIndexPages = ceil(numIndexPages);
|
||||||
|
}
|
||||||
|
else
|
||||||
numIndexPages = 1.0;
|
numIndexPages = 1.0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.213 2001/07/03 20:21:49 petere Exp $
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.214 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
|
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
|
||||||
*
|
*
|
||||||
@ -1758,6 +1758,8 @@ clearIndInfo(IndInfo *ind, int numIndexes)
|
|||||||
free(ind[i].indisunique);
|
free(ind[i].indisunique);
|
||||||
if (ind[i].indisprimary)
|
if (ind[i].indisprimary)
|
||||||
free(ind[i].indisprimary);
|
free(ind[i].indisprimary);
|
||||||
|
if (ind[i].indpred)
|
||||||
|
free(ind[i].indpred);
|
||||||
for (a = 0; a < INDEX_MAX_KEYS; ++a)
|
for (a = 0; a < INDEX_MAX_KEYS; ++a)
|
||||||
{
|
{
|
||||||
if (ind[i].indkey[a])
|
if (ind[i].indkey[a])
|
||||||
@ -2887,10 +2889,10 @@ getIndexes(int *numIndexes)
|
|||||||
int i_indoid;
|
int i_indoid;
|
||||||
int i_oid;
|
int i_oid;
|
||||||
int i_indisprimary;
|
int i_indisprimary;
|
||||||
|
int i_indpred;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* find all the user-defined indexes. We do not handle partial
|
* find all the user-defined indexes.
|
||||||
* indexes.
|
|
||||||
*
|
*
|
||||||
* Notice we skip indexes on system classes
|
* Notice we skip indexes on system classes
|
||||||
*
|
*
|
||||||
@ -2902,7 +2904,7 @@ getIndexes(int *numIndexes)
|
|||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT i.oid, t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, "
|
"SELECT i.oid, t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, "
|
||||||
"i.indproc, i.indkey, i.indclass, "
|
"i.indproc, i.indkey, i.indclass, "
|
||||||
"a.amname as indamname, i.indisunique, i.indisprimary "
|
"a.amname as indamname, i.indisunique, i.indisprimary, i.indpred "
|
||||||
"from pg_index i, pg_class t1, pg_class t2, pg_am a "
|
"from pg_index i, pg_class t1, pg_class t2, pg_am a "
|
||||||
"WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
|
"WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
|
||||||
"and t1.relam = a.oid and i.indexrelid > '%u'::oid "
|
"and t1.relam = a.oid and i.indexrelid > '%u'::oid "
|
||||||
@ -2938,6 +2940,7 @@ getIndexes(int *numIndexes)
|
|||||||
i_indclass = PQfnumber(res, "indclass");
|
i_indclass = PQfnumber(res, "indclass");
|
||||||
i_indisunique = PQfnumber(res, "indisunique");
|
i_indisunique = PQfnumber(res, "indisunique");
|
||||||
i_indisprimary = PQfnumber(res, "indisprimary");
|
i_indisprimary = PQfnumber(res, "indisprimary");
|
||||||
|
i_indpred = PQfnumber(res, "indpred");
|
||||||
|
|
||||||
for (i = 0; i < ntups; i++)
|
for (i = 0; i < ntups; i++)
|
||||||
{
|
{
|
||||||
@ -2955,6 +2958,7 @@ getIndexes(int *numIndexes)
|
|||||||
INDEX_MAX_KEYS);
|
INDEX_MAX_KEYS);
|
||||||
indinfo[i].indisunique = strdup(PQgetvalue(res, i, i_indisunique));
|
indinfo[i].indisunique = strdup(PQgetvalue(res, i, i_indisunique));
|
||||||
indinfo[i].indisprimary = strdup(PQgetvalue(res, i, i_indisprimary));
|
indinfo[i].indisprimary = strdup(PQgetvalue(res, i, i_indisprimary));
|
||||||
|
indinfo[i].indpred = strdup(PQgetvalue(res, i, i_indpred));
|
||||||
}
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return indinfo;
|
return indinfo;
|
||||||
@ -4435,13 +4439,46 @@ dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
|
|||||||
{
|
{
|
||||||
/* need 2 printf's here cuz fmtId has static return area */
|
/* need 2 printf's here cuz fmtId has static return area */
|
||||||
appendPQExpBuffer(q, " %s", fmtId(funcname, false));
|
appendPQExpBuffer(q, " %s", fmtId(funcname, false));
|
||||||
appendPQExpBuffer(q, " (%s) %s );\n", attlist->data,
|
appendPQExpBuffer(q, " (%s) %s )", attlist->data,
|
||||||
fmtId(classname[0], force_quotes));
|
fmtId(classname[0], force_quotes));
|
||||||
free(funcname);
|
free(funcname);
|
||||||
free(classname[0]);
|
free(classname[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
appendPQExpBuffer(q, " %s );\n", attlist->data);
|
appendPQExpBuffer(q, " %s )", attlist->data);
|
||||||
|
|
||||||
|
if (*indinfo[i].indpred) /* If there is an index predicate */
|
||||||
|
{
|
||||||
|
int numRows;
|
||||||
|
PQExpBuffer pred = createPQExpBuffer();
|
||||||
|
|
||||||
|
appendPQExpBuffer(pred, "SELECT pg_get_expr(indpred,indrelid) as pred FROM pg_index WHERE oid = %s",
|
||||||
|
indinfo[i].oid);
|
||||||
|
res = PQexec(g_conn, pred->data);
|
||||||
|
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "dumpIndices(): SELECT (indpred) failed. "
|
||||||
|
"Explanation from backend: '%s'.\n",
|
||||||
|
PQerrorMessage(g_conn));
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity: Check we got only one tuple */
|
||||||
|
numRows = PQntuples(res);
|
||||||
|
if (numRows != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "dumpIndices(): SELECT (indpred) for index %s returned %d tuples. Expected 1.\n",
|
||||||
|
indinfo[i].indrelname, numRows);
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPQExpBuffer(q, " WHERE %s",
|
||||||
|
PQgetvalue(res, 0, PQfnumber(res, "pred")));
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
destroyPQExpBuffer( pred );
|
||||||
|
}
|
||||||
|
appendPQExpBuffer(q, ";\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We make the index belong to the owner of its table, which
|
* We make the index belong to the owner of its table, which
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_dump.h,v 1.65 2001/07/03 20:21:50 petere Exp $
|
* $Id: pg_dump.h,v 1.66 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
|
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
|
||||||
*
|
*
|
||||||
@ -147,6 +147,7 @@ typedef struct _indInfo
|
|||||||
char *indclass[INDEX_MAX_KEYS]; /* opclass of the keys */
|
char *indclass[INDEX_MAX_KEYS]; /* opclass of the keys */
|
||||||
char *indisunique; /* is this index unique? */
|
char *indisunique; /* is this index unique? */
|
||||||
char *indisprimary; /* is this a PK index? */
|
char *indisprimary; /* is this a PK index? */
|
||||||
|
char *indpred; /* index predicate */
|
||||||
} IndInfo;
|
} IndInfo;
|
||||||
|
|
||||||
typedef struct _aggInfo
|
typedef struct _aggInfo
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: index.h,v 1.36 2001/07/15 22:48:18 tgl Exp $
|
* $Id: index.h,v 1.37 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -30,8 +30,6 @@ typedef void (*IndexBuildCallback) (Relation index,
|
|||||||
extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId,
|
extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId,
|
||||||
MemoryContext resultCxt);
|
MemoryContext resultCxt);
|
||||||
|
|
||||||
extern void UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate);
|
|
||||||
|
|
||||||
extern void InitIndexStrategy(int numatts,
|
extern void InitIndexStrategy(int numatts,
|
||||||
Relation indexRelation,
|
Relation indexRelation,
|
||||||
Oid accessMethodObjectId);
|
Oid accessMethodObjectId);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_proc.h,v 1.197 2001/07/15 22:48:18 tgl Exp $
|
* $Id: pg_proc.h,v 1.198 2001/07/16 05:06:59 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The script catalog/genbki.sh reads this file and generates .bki
|
* The script catalog/genbki.sh reads this file and generates .bki
|
||||||
@ -2146,6 +2146,9 @@ DATA(insert OID = 1642 ( pg_get_userbyid PGUID 12 f t f t 1 f 19 "23" 100 0
|
|||||||
DESCR("user name by UID (with fallback)");
|
DESCR("user name by UID (with fallback)");
|
||||||
DATA(insert OID = 1643 ( pg_get_indexdef PGUID 12 f t f t 1 f 25 "26" 100 0 0 100 pg_get_indexdef - ));
|
DATA(insert OID = 1643 ( pg_get_indexdef PGUID 12 f t f t 1 f 25 "26" 100 0 0 100 pg_get_indexdef - ));
|
||||||
DESCR("index description");
|
DESCR("index description");
|
||||||
|
DATA(insert OID = 1716 ( pg_get_expr PGUID 12 f t f t 2 f 25 "25 26" 100 0 0 100 pg_get_expr - ));
|
||||||
|
DESCR("deparse an encoded expression");
|
||||||
|
|
||||||
|
|
||||||
/* Generic referential integrity constraint triggers */
|
/* Generic referential integrity constraint triggers */
|
||||||
DATA(insert OID = 1644 ( RI_FKey_check_ins PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_ins - ));
|
DATA(insert OID = 1644 ( RI_FKey_check_ins PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_ins - ));
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: defrem.h,v 1.22 2001/01/24 19:43:23 momjian Exp $
|
* $Id: defrem.h,v 1.23 2001/07/16 05:07:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
#include "tcop/dest.h"
|
#include "tcop/dest.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prototypes in defind.c
|
* prototypes in indexcmds.c
|
||||||
*/
|
*/
|
||||||
extern void DefineIndex(char *heapRelationName,
|
extern void DefineIndex(char *heapRelationName,
|
||||||
char *indexRelationName,
|
char *indexRelationName,
|
||||||
@ -29,9 +29,6 @@ extern void DefineIndex(char *heapRelationName,
|
|||||||
bool primary,
|
bool primary,
|
||||||
Expr *predicate,
|
Expr *predicate,
|
||||||
List *rangetable);
|
List *rangetable);
|
||||||
extern void ExtendIndex(char *indexRelationName,
|
|
||||||
Expr *predicate,
|
|
||||||
List *rangetable);
|
|
||||||
extern void RemoveIndex(char *name);
|
extern void RemoveIndex(char *name);
|
||||||
extern void ReindexIndex(const char *indexRelationName, bool force);
|
extern void ReindexIndex(const char *indexRelationName, bool force);
|
||||||
extern void ReindexTable(const char *relationName, bool force);
|
extern void ReindexTable(const char *relationName, bool force);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* or in config.h afterwards. Of course, if you edit config.h, then your
|
* or in config.h afterwards. Of course, if you edit config.h, then your
|
||||||
* changes will be overwritten the next time you run configure.
|
* changes will be overwritten the next time you run configure.
|
||||||
*
|
*
|
||||||
* $Id: config.h.in,v 1.167 2001/07/11 19:03:07 tgl Exp $
|
* $Id: config.h.in,v 1.168 2001/07/16 05:07:00 tgl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
@ -310,7 +310,6 @@
|
|||||||
/* #define ACLDEBUG */
|
/* #define ACLDEBUG */
|
||||||
/* #define RTDEBUG */
|
/* #define RTDEBUG */
|
||||||
/* #define GISTDEBUG */
|
/* #define GISTDEBUG */
|
||||||
/* #define OMIT_PARTIAL_INDEX */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* defining unsafe floats will make float4 and float8 ops faster
|
* defining unsafe floats will make float4 and float8 ops faster
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: execnodes.h,v 1.61 2001/06/01 02:41:36 tgl Exp $
|
* $Id: execnodes.h,v 1.62 2001/07/16 05:07:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,7 @@
|
|||||||
* NumKeyAttrs number of key attributes for this index
|
* NumKeyAttrs number of key attributes for this index
|
||||||
* (ie, number of attrs from underlying relation)
|
* (ie, number of attrs from underlying relation)
|
||||||
* KeyAttrNumbers underlying-rel attribute numbers used as keys
|
* KeyAttrNumbers underlying-rel attribute numbers used as keys
|
||||||
* Predicate partial-index predicate, or NULL if none
|
* Predicate partial-index predicate, or NIL if none
|
||||||
* FuncOid OID of function, or InvalidOid if not f. index
|
* FuncOid OID of function, or InvalidOid if not f. index
|
||||||
* FuncInfo fmgr lookup data for function, if FuncOid valid
|
* FuncInfo fmgr lookup data for function, if FuncOid valid
|
||||||
* Unique is it a unique index?
|
* Unique is it a unique index?
|
||||||
@ -46,7 +46,7 @@ typedef struct IndexInfo
|
|||||||
int ii_NumIndexAttrs;
|
int ii_NumIndexAttrs;
|
||||||
int ii_NumKeyAttrs;
|
int ii_NumKeyAttrs;
|
||||||
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
|
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
|
||||||
Node *ii_Predicate;
|
List *ii_Predicate;
|
||||||
Oid ii_FuncOid;
|
Oid ii_FuncOid;
|
||||||
FmgrInfo ii_FuncInfo;
|
FmgrInfo ii_FuncInfo;
|
||||||
bool ii_Unique;
|
bool ii_Unique;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: builtins.h,v 1.157 2001/07/11 22:14:03 momjian Exp $
|
* $Id: builtins.h,v 1.158 2001/07/16 05:07:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -337,6 +337,7 @@ extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
|
|||||||
extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
|
extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
|
extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
|
extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum pg_get_expr(PG_FUNCTION_ARGS);
|
||||||
extern char *deparse_expression(Node *expr, List *dpcontext,
|
extern char *deparse_expression(Node *expr, List *dpcontext,
|
||||||
bool forceprefix);
|
bool forceprefix);
|
||||||
extern List *deparse_context_for(char *relname, Oid relid);
|
extern List *deparse_context_for(char *relname, Oid relid);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.41 2001/06/01 06:23:19 meskes Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.42 2001/07/16 05:07:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -109,7 +109,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"execute", EXECUTE},
|
{"execute", EXECUTE},
|
||||||
{"exists", EXISTS},
|
{"exists", EXISTS},
|
||||||
{"explain", EXPLAIN},
|
{"explain", EXPLAIN},
|
||||||
{"extend", EXTEND},
|
|
||||||
{"extract", EXTRACT},
|
{"extract", EXTRACT},
|
||||||
{"false", FALSE_P},
|
{"false", FALSE_P},
|
||||||
{"fetch", FETCH},
|
{"fetch", FETCH},
|
||||||
@ -265,6 +264,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"type", TYPE_P},
|
{"type", TYPE_P},
|
||||||
{"union", UNION},
|
{"union", UNION},
|
||||||
{"unique", UNIQUE},
|
{"unique", UNIQUE},
|
||||||
|
{"unknown", UNKNOWN},
|
||||||
{"unlisten", UNLISTEN},
|
{"unlisten", UNLISTEN},
|
||||||
{"until", UNTIL},
|
{"until", UNTIL},
|
||||||
{"update", UPDATE},
|
{"update", UPDATE},
|
||||||
|
@ -193,7 +193,7 @@ make_name(void)
|
|||||||
SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
|
SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
|
||||||
TABLE, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR,
|
TABLE, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR,
|
||||||
TIMEZONE_MINUTE, TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
|
TIMEZONE_MINUTE, TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
|
||||||
UNION, UNIQUE, UPDATE, USER, USING,
|
UNION, UNIQUE, UNKNOWN, UPDATE, USER, USING,
|
||||||
VALUES, VARCHAR, VARYING, VIEW,
|
VALUES, VARCHAR, VARYING, VIEW,
|
||||||
WHEN, WHERE, WITH, WITHOUT, WORK, YEAR_P, ZONE
|
WHEN, WHERE, WITH, WITHOUT, WORK, YEAR_P, ZONE
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ make_name(void)
|
|||||||
BACKWARD, BEFORE, BINARY, BIT, CACHE, CHECKPOINT, CLUSTER,
|
BACKWARD, BEFORE, BINARY, BIT, CACHE, CHECKPOINT, CLUSTER,
|
||||||
COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE, DATABASE,
|
COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE, DATABASE,
|
||||||
DELIMITERS, DO, EACH, ENCODING, EXCLUSIVE, EXPLAIN,
|
DELIMITERS, DO, EACH, ENCODING, EXCLUSIVE, EXPLAIN,
|
||||||
EXTEND, FORCE, FORWARD, FUNCTION, HANDLER, INCREMENT,
|
FORCE, FORWARD, FUNCTION, HANDLER, INCREMENT,
|
||||||
INDEX, INHERITS, INSTEAD, ISNULL, LANCOMPILER, LIMIT,
|
INDEX, INHERITS, INSTEAD, ISNULL, LANCOMPILER, LIMIT,
|
||||||
LISTEN, UNLISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE,
|
LISTEN, UNLISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE,
|
||||||
MINVALUE, MODE, MOVE, NEW, NOCREATEDB, NOCREATEUSER,
|
MINVALUE, MODE, MOVE, NEW, NOCREATEDB, NOCREATEUSER,
|
||||||
@ -260,7 +260,7 @@ make_name(void)
|
|||||||
%left Op /* multi-character ops and user-defined operators */
|
%left Op /* multi-character ops and user-defined operators */
|
||||||
%nonassoc NOTNULL
|
%nonassoc NOTNULL
|
||||||
%nonassoc ISNULL
|
%nonassoc ISNULL
|
||||||
%nonassoc IS NULL_P TRUE_P FALSE_P
|
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
%left '^'
|
%left '^'
|
||||||
@ -312,7 +312,7 @@ make_name(void)
|
|||||||
%type <str> RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
|
%type <str> RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
|
||||||
%type <str> RuleStmt opt_column opt_name oper_argtypes
|
%type <str> RuleStmt opt_column opt_name oper_argtypes
|
||||||
%type <str> MathOp RemoveFuncStmt aggr_argtype for_update_clause
|
%type <str> MathOp RemoveFuncStmt aggr_argtype for_update_clause
|
||||||
%type <str> RemoveAggrStmt ExtendStmt opt_procedural select_no_parens
|
%type <str> RemoveAggrStmt opt_procedural select_no_parens
|
||||||
%type <str> RemoveOperStmt RenameStmt all_Op
|
%type <str> RemoveOperStmt RenameStmt all_Op
|
||||||
%type <str> VariableSetStmt var_value zone_value VariableShowStmt
|
%type <str> VariableSetStmt var_value zone_value VariableShowStmt
|
||||||
%type <str> VariableResetStmt AlterTableStmt DropUserStmt from_list
|
%type <str> VariableResetStmt AlterTableStmt DropUserStmt from_list
|
||||||
@ -414,7 +414,6 @@ stmt: AlterSchemaStmt { output_statement($1, 0, NULL, connection); }
|
|||||||
| DropPLangStmt { output_statement($1, 0, NULL, connection); }
|
| DropPLangStmt { output_statement($1, 0, NULL, connection); }
|
||||||
| DropTrigStmt { output_statement($1, 0, NULL, connection); }
|
| DropTrigStmt { output_statement($1, 0, NULL, connection); }
|
||||||
| DropUserStmt { output_statement($1, 0, NULL, connection); }
|
| DropUserStmt { output_statement($1, 0, NULL, connection); }
|
||||||
| ExtendStmt { output_statement($1, 0, NULL, connection); }
|
|
||||||
| ExplainStmt { output_statement($1, 0, NULL, connection); }
|
| ExplainStmt { output_statement($1, 0, NULL, connection); }
|
||||||
| FetchStmt { output_statement($1, 1, NULL, connection); }
|
| FetchStmt { output_statement($1, 1, NULL, connection); }
|
||||||
| GrantStmt { output_statement($1, 0, NULL, connection); }
|
| GrantStmt { output_statement($1, 0, NULL, connection); }
|
||||||
@ -1801,18 +1800,16 @@ RevokeStmt: REVOKE privileges ON opt_table relation_name_list FROM grantee_list
|
|||||||
*
|
*
|
||||||
* QUERY:
|
* QUERY:
|
||||||
* create index <indexname> on <relname>
|
* create index <indexname> on <relname>
|
||||||
* using <access> "(" (<col> with <op>)+ ")" [with
|
* [ using <access> ] "(" (<col> with <op>)+ ")"
|
||||||
* <target_list>]
|
* [ with <parameters> ]
|
||||||
|
* [ where <predicate> ]
|
||||||
*
|
*
|
||||||
* [where <qual>] is not supported anymore
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
|
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
|
||||||
{
|
{
|
||||||
/* should check that access_method is valid,
|
$$ = cat_str(12, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11, $12);
|
||||||
etc ... but doesn't */
|
|
||||||
$$ = cat_str(11, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1866,19 +1863,6 @@ opt_class: class {
|
|||||||
| /*EMPTY*/ { $$ = EMPTY; }
|
| /*EMPTY*/ { $$ = EMPTY; }
|
||||||
;
|
;
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* QUERY:
|
|
||||||
* extend index <indexname> [where <qual>]
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
ExtendStmt: EXTEND INDEX index_name where_clause
|
|
||||||
{
|
|
||||||
$$ = cat_str(3, make_str("extend index"), $3, $4);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
@ -3324,15 +3308,23 @@ a_expr: c_expr
|
|||||||
* but let's make them expressions to allow the optimizer
|
* but let's make them expressions to allow the optimizer
|
||||||
* a chance to eliminate them if a_expr is a constant string.
|
* a chance to eliminate them if a_expr is a constant string.
|
||||||
* - thomas 1997-12-22
|
* - thomas 1997-12-22
|
||||||
|
*
|
||||||
|
* Created BooleanTest Node type, and changed handling
|
||||||
|
* for NULL inputs
|
||||||
|
* - jec 2001-06-18
|
||||||
*/
|
*/
|
||||||
| a_expr IS TRUE_P
|
| a_expr IS TRUE_P
|
||||||
{ $$ = cat2_str($1, make_str("is true")); }
|
{ $$ = cat2_str($1, make_str("is true")); }
|
||||||
| a_expr IS NOT FALSE_P
|
|
||||||
{ $$ = cat2_str($1, make_str("is not false")); }
|
|
||||||
| a_expr IS FALSE_P
|
|
||||||
{ $$ = cat2_str($1, make_str("is false")); }
|
|
||||||
| a_expr IS NOT TRUE_P
|
| a_expr IS NOT TRUE_P
|
||||||
{ $$ = cat2_str($1, make_str("is not true")); }
|
{ $$ = cat2_str($1, make_str("is not true")); }
|
||||||
|
| a_expr IS FALSE_P
|
||||||
|
{ $$ = cat2_str($1, make_str("is false")); }
|
||||||
|
| a_expr IS NOT FALSE_P
|
||||||
|
{ $$ = cat2_str($1, make_str("is not false")); }
|
||||||
|
| a_expr IS UNKNOWN
|
||||||
|
{ $$ = cat2_str($1, make_str("is unknown")); }
|
||||||
|
| a_expr IS NOT UNKNOWN
|
||||||
|
{ $$ = cat2_str($1, make_str("is not unknown")); }
|
||||||
| a_expr BETWEEN b_expr AND b_expr %prec BETWEEN
|
| a_expr BETWEEN b_expr AND b_expr %prec BETWEEN
|
||||||
{
|
{
|
||||||
$$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5);
|
$$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5);
|
||||||
@ -5152,7 +5144,6 @@ ECPGColLabel: ECPGColId { $$ = $1; }
|
|||||||
| EXCEPT { $$ = make_str("except"); }
|
| EXCEPT { $$ = make_str("except"); }
|
||||||
| EXISTS { $$ = make_str("exists"); }
|
| EXISTS { $$ = make_str("exists"); }
|
||||||
| EXPLAIN { $$ = make_str("explain"); }
|
| EXPLAIN { $$ = make_str("explain"); }
|
||||||
| EXTEND { $$ = make_str("extend"); }
|
|
||||||
| EXTRACT { $$ = make_str("extract"); }
|
| EXTRACT { $$ = make_str("extract"); }
|
||||||
| FALSE_P { $$ = make_str("false"); }
|
| FALSE_P { $$ = make_str("false"); }
|
||||||
| FOR { $$ = make_str("for"); }
|
| FOR { $$ = make_str("for"); }
|
||||||
@ -5217,6 +5208,7 @@ ECPGColLabel: ECPGColId { $$ = $1; }
|
|||||||
| TRIM { $$ = make_str("trim"); }
|
| TRIM { $$ = make_str("trim"); }
|
||||||
| TRUE_P { $$ = make_str("true"); }
|
| TRUE_P { $$ = make_str("true"); }
|
||||||
| UNIQUE { $$ = make_str("unique"); }
|
| UNIQUE { $$ = make_str("unique"); }
|
||||||
|
| UNKNOWN { $$ = make_str("unknown"); }
|
||||||
| USER { $$ = make_str("user"); }
|
| USER { $$ = make_str("user"); }
|
||||||
| USING { $$ = make_str("using"); }
|
| USING { $$ = make_str("using"); }
|
||||||
| VACUUM { $$ = make_str("vacuum"); }
|
| VACUUM { $$ = make_str("vacuum"); }
|
||||||
|
@ -32,16 +32,13 @@ CREATE INDEX bt_txt_index ON bt_txt_heap USING btree (seqno text_ops);
|
|||||||
CREATE INDEX bt_f8_index ON bt_f8_heap USING btree (seqno float8_ops);
|
CREATE INDEX bt_f8_index ON bt_f8_heap USING btree (seqno float8_ops);
|
||||||
--
|
--
|
||||||
-- BTREE partial indices
|
-- BTREE partial indices
|
||||||
-- partial indices are not supported in PostgreSQL
|
|
||||||
--
|
--
|
||||||
--CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops)
|
CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops)
|
||||||
-- where onek2.unique1 < 20 or onek2.unique1 > 980;
|
where unique1 < 20 or unique1 > 980;
|
||||||
--CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||||
-- where onek2.stringu1 < 'B';
|
where stringu1 < 'B';
|
||||||
-- EXTEND INDEX onek2_u2_prtl where onek2.stringu1 < 'C';
|
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||||
-- EXTEND INDEX onek2_u2_prtl;
|
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
|
-- RTREE
|
||||||
--
|
--
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
--
|
--
|
||||||
-- PORTALS_P2
|
-- PORTALS_P2
|
||||||
--
|
--
|
||||||
-- EXTEND INDEX onek2_u1_prtl WHERE onek2.unique1 <= 60;
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
DECLARE foo13 CURSOR FOR
|
DECLARE foo13 CURSOR FOR
|
||||||
SELECT * FROM onek WHERE unique1 = 50;
|
SELECT * FROM onek WHERE unique1 = 50;
|
||||||
|
@ -29,6 +29,7 @@ SELECT relname, relhasindex
|
|||||||
num_exp_sqrt | t
|
num_exp_sqrt | t
|
||||||
num_exp_sub | t
|
num_exp_sub | t
|
||||||
onek | t
|
onek | t
|
||||||
|
onek2 | t
|
||||||
pg_aggregate | t
|
pg_aggregate | t
|
||||||
pg_am | t
|
pg_am | t
|
||||||
pg_amop | t
|
pg_amop | t
|
||||||
@ -57,5 +58,5 @@ SELECT relname, relhasindex
|
|||||||
shighway | t
|
shighway | t
|
||||||
tenk1 | t
|
tenk1 | t
|
||||||
tenk2 | t
|
tenk2 | t
|
||||||
(47 rows)
|
(48 rows)
|
||||||
|
|
||||||
|
@ -205,23 +205,87 @@ SELECT onek.unique1, onek.string4
|
|||||||
(20 rows)
|
(20 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- partial btree index
|
-- test partial btree indexes
|
||||||
|
--
|
||||||
|
-- As of 7.2, planner probably won't pick an indexscan without stats,
|
||||||
|
-- so ANALYZE first.
|
||||||
|
--
|
||||||
|
ANALYZE onek2;
|
||||||
|
--
|
||||||
-- awk '{if($1<10){print $0;}else{next;}}' onek.data | sort +0n -1
|
-- awk '{if($1<10){print $0;}else{next;}}' onek.data | sort +0n -1
|
||||||
--
|
--
|
||||||
--SELECT onek2.* WHERE onek2.unique1 < 10;
|
SELECT onek2.* WHERE onek2.unique1 < 10;
|
||||||
|
unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4
|
||||||
|
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
|
||||||
|
0 | 998 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | AAAAAA | KMBAAA | OOOOxx
|
||||||
|
1 | 214 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | BAAAAA | GIAAAA | OOOOxx
|
||||||
|
2 | 326 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 5 | CAAAAA | OMAAAA | OOOOxx
|
||||||
|
3 | 431 | 1 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 6 | 7 | DAAAAA | PQAAAA | VVVVxx
|
||||||
|
4 | 833 | 0 | 0 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 8 | 9 | EAAAAA | BGBAAA | HHHHxx
|
||||||
|
5 | 541 | 1 | 1 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 10 | 11 | FAAAAA | VUAAAA | HHHHxx
|
||||||
|
6 | 978 | 0 | 2 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 12 | 13 | GAAAAA | QLBAAA | OOOOxx
|
||||||
|
7 | 647 | 1 | 3 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 14 | 15 | HAAAAA | XYAAAA | VVVVxx
|
||||||
|
8 | 653 | 0 | 0 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 16 | 17 | IAAAAA | DZAAAA | HHHHxx
|
||||||
|
9 | 49 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 18 | 19 | JAAAAA | XBAAAA | HHHHxx
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- partial btree index
|
|
||||||
-- awk '{if($1<20){print $1,$14;}else{next;}}' onek.data | sort +0nr -1
|
-- awk '{if($1<20){print $1,$14;}else{next;}}' onek.data | sort +0nr -1
|
||||||
--
|
--
|
||||||
--SELECT onek2.unique1, onek2.stringu1
|
SELECT onek2.unique1, onek2.stringu1
|
||||||
-- WHERE onek2.unique1 < 20
|
WHERE onek2.unique1 < 20
|
||||||
-- ORDER BY unique1 using >;
|
ORDER BY unique1 using >;
|
||||||
|
unique1 | stringu1
|
||||||
|
---------+----------
|
||||||
|
19 | TAAAAA
|
||||||
|
18 | SAAAAA
|
||||||
|
17 | RAAAAA
|
||||||
|
16 | QAAAAA
|
||||||
|
15 | PAAAAA
|
||||||
|
14 | OAAAAA
|
||||||
|
13 | NAAAAA
|
||||||
|
12 | MAAAAA
|
||||||
|
11 | LAAAAA
|
||||||
|
10 | KAAAAA
|
||||||
|
9 | JAAAAA
|
||||||
|
8 | IAAAAA
|
||||||
|
7 | HAAAAA
|
||||||
|
6 | GAAAAA
|
||||||
|
5 | FAAAAA
|
||||||
|
4 | EAAAAA
|
||||||
|
3 | DAAAAA
|
||||||
|
2 | CAAAAA
|
||||||
|
1 | BAAAAA
|
||||||
|
0 | AAAAAA
|
||||||
|
(20 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- awk '{if($1>980){print $1,$14;}else{next;}}' onek.data | sort +1d -2
|
-- awk '{if($1>980){print $1,$14;}else{next;}}' onek.data | sort +1d -2
|
||||||
--
|
--
|
||||||
--SELECT onek2.unique1, onek2.stringu1
|
SELECT onek2.unique1, onek2.stringu1
|
||||||
-- WHERE onek2.unique1 > 980
|
WHERE onek2.unique1 > 980;
|
||||||
-- ORDER BY stringu1 using <;
|
unique1 | stringu1
|
||||||
|
---------+----------
|
||||||
|
981 | TLAAAA
|
||||||
|
982 | ULAAAA
|
||||||
|
983 | VLAAAA
|
||||||
|
984 | WLAAAA
|
||||||
|
985 | XLAAAA
|
||||||
|
986 | YLAAAA
|
||||||
|
987 | ZLAAAA
|
||||||
|
988 | AMAAAA
|
||||||
|
989 | BMAAAA
|
||||||
|
990 | CMAAAA
|
||||||
|
991 | DMAAAA
|
||||||
|
992 | EMAAAA
|
||||||
|
993 | FMAAAA
|
||||||
|
994 | GMAAAA
|
||||||
|
995 | HMAAAA
|
||||||
|
996 | IMAAAA
|
||||||
|
997 | JMAAAA
|
||||||
|
998 | KMAAAA
|
||||||
|
999 | LMAAAA
|
||||||
|
(19 rows)
|
||||||
|
|
||||||
SELECT two, stringu1, ten, string4
|
SELECT two, stringu1, ten, string4
|
||||||
INTO TABLE tmp
|
INTO TABLE tmp
|
||||||
|
@ -50,20 +50,15 @@ CREATE INDEX bt_f8_index ON bt_f8_heap USING btree (seqno float8_ops);
|
|||||||
|
|
||||||
--
|
--
|
||||||
-- BTREE partial indices
|
-- BTREE partial indices
|
||||||
-- partial indices are not supported in PostgreSQL
|
|
||||||
--
|
--
|
||||||
--CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops)
|
CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops)
|
||||||
-- where onek2.unique1 < 20 or onek2.unique1 > 980;
|
where unique1 < 20 or unique1 > 980;
|
||||||
|
|
||||||
--CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||||
-- where onek2.stringu1 < 'B';
|
where stringu1 < 'B';
|
||||||
|
|
||||||
-- EXTEND INDEX onek2_u2_prtl where onek2.stringu1 < 'C';
|
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||||
|
where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K';
|
||||||
-- 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';
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- RTREE
|
-- RTREE
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
-- PORTALS_P2
|
-- PORTALS_P2
|
||||||
--
|
--
|
||||||
|
|
||||||
-- EXTEND INDEX onek2_u1_prtl WHERE onek2.unique1 <= 60;
|
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
DECLARE foo13 CURSOR FOR
|
DECLARE foo13 CURSOR FOR
|
||||||
|
@ -55,25 +55,31 @@ SELECT onek.unique1, onek.string4
|
|||||||
ORDER BY unique1 using <, string4 using >;
|
ORDER BY unique1 using <, string4 using >;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- partial btree index
|
-- test partial btree indexes
|
||||||
-- awk '{if($1<10){print $0;}else{next;}}' onek.data | sort +0n -1
|
|
||||||
--
|
--
|
||||||
--SELECT onek2.* WHERE onek2.unique1 < 10;
|
-- As of 7.2, planner probably won't pick an indexscan without stats,
|
||||||
|
-- so ANALYZE first.
|
||||||
|
--
|
||||||
|
ANALYZE onek2;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- awk '{if($1<10){print $0;}else{next;}}' onek.data | sort +0n -1
|
||||||
|
--
|
||||||
|
SELECT onek2.* WHERE onek2.unique1 < 10;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- partial btree index
|
|
||||||
-- awk '{if($1<20){print $1,$14;}else{next;}}' onek.data | sort +0nr -1
|
-- awk '{if($1<20){print $1,$14;}else{next;}}' onek.data | sort +0nr -1
|
||||||
--
|
--
|
||||||
--SELECT onek2.unique1, onek2.stringu1
|
SELECT onek2.unique1, onek2.stringu1
|
||||||
-- WHERE onek2.unique1 < 20
|
WHERE onek2.unique1 < 20
|
||||||
-- ORDER BY unique1 using >;
|
ORDER BY unique1 using >;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- awk '{if($1>980){print $1,$14;}else{next;}}' onek.data | sort +1d -2
|
-- awk '{if($1>980){print $1,$14;}else{next;}}' onek.data | sort +1d -2
|
||||||
--
|
--
|
||||||
--SELECT onek2.unique1, onek2.stringu1
|
SELECT onek2.unique1, onek2.stringu1
|
||||||
-- WHERE onek2.unique1 > 980
|
WHERE onek2.unique1 > 980;
|
||||||
-- ORDER BY stringu1 using <;
|
|
||||||
|
|
||||||
SELECT two, stringu1, ten, string4
|
SELECT two, stringu1, ten, string4
|
||||||
INTO TABLE tmp
|
INTO TABLE tmp
|
||||||
|
Loading…
x
Reference in New Issue
Block a user