mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-18 18:44:06 +08:00
First steps towards index scans with heap access decoupled from index
access: define new index access method functions 'amgetmulti' that can fetch multiple TIDs per call. (The functions exist but are totally untested as yet.) Since I was modifying pg_am anyway, remove the no-longer-needed 'rel' parameter from amcostestimate functions, and also remove the vestigial amowner column that was creating useless work for Alvaro's shared-object-dependencies project. Initdb forced due to changes in pg_am.
This commit is contained in:
parent
351519affc
commit
bf3dbb5881
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.96 2005/02/13 03:04:15 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.97 2005/03/27 23:52:51 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="catalogs">
|
||||
@ -316,13 +316,6 @@
|
||||
<entry>Name of the access method</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amowner</structfield></entry>
|
||||
<entry><type>int4</type></entry>
|
||||
<entry><literal><link linkend="catalog-pg-shadow"><structname>pg_shadow</structname></link>.usesysid</literal></entry>
|
||||
<entry>User ID of the owner (currently not used)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amstrategies</structfield></entry>
|
||||
<entry><type>int2</type></entry>
|
||||
@ -373,13 +366,6 @@
|
||||
<entry>Does the access method support concurrent updates?</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amgettuple</structfield></entry>
|
||||
<entry><type>regproc</type></entry>
|
||||
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
|
||||
<entry><quote>Next valid tuple</quote> function</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>aminsert</structfield></entry>
|
||||
<entry><type>regproc</type></entry>
|
||||
@ -394,6 +380,20 @@
|
||||
<entry><quote>Start new scan</quote> function</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amgettuple</structfield></entry>
|
||||
<entry><type>regproc</type></entry>
|
||||
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
|
||||
<entry><quote>Next valid tuple</quote> function</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amgetmulti</structfield></entry>
|
||||
<entry><type>regproc</type></entry>
|
||||
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
|
||||
<entry><quote>Fetch multiple tuples</quote> function</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>amrescan</structfield></entry>
|
||||
<entry><type>regproc</type></entry>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.2 2005/03/21 01:23:55 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.3 2005/03/27 23:52:51 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="indexam">
|
||||
@ -252,6 +252,28 @@ amgettuple (IndexScanDesc scan,
|
||||
|
||||
<para>
|
||||
<programlisting>
|
||||
boolean
|
||||
amgetmulti (IndexScanDesc scan,
|
||||
ItemPointer tids,
|
||||
int32 max_tids,
|
||||
int32 *returned_tids);
|
||||
</programlisting>
|
||||
Fetch multiple tuples in the given scan. Returns TRUE if the scan should
|
||||
continue, FALSE if no matching tuples remain. <literal>tids</> points to
|
||||
a caller-supplied array of <literal>max_tids</>
|
||||
<structname>ItemPointerData</> records, which the call fills with TIDs of
|
||||
matching tuples. <literal>*returned_tids</> is set to the number of TIDs
|
||||
actually returned. This can be less than <literal>max_tids</>, or even
|
||||
zero, even when the return value is TRUE. (This provision allows the
|
||||
access method to choose the most efficient stopping points in its scan,
|
||||
for example index page boundaries.) <function>amgetmulti</> and
|
||||
<function>amgettuple</> cannot be used in the same index scan; there
|
||||
are other restrictions too when using <function>amgetmulti</>, as explained
|
||||
in <xref linkend="index-scanning">.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<programlisting>
|
||||
void
|
||||
amrescan (IndexScanDesc scan,
|
||||
ScanKey key);
|
||||
@ -297,7 +319,6 @@ amrestrpos (IndexScanDesc scan);
|
||||
<programlisting>
|
||||
void
|
||||
amcostestimate (Query *root,
|
||||
RelOptInfo *rel,
|
||||
IndexOptInfo *index,
|
||||
List *indexQuals,
|
||||
Cost *indexStartupCost,
|
||||
@ -407,6 +428,25 @@ amcostestimate (Query *root,
|
||||
true, insertions or deletions from other backends must be handled as well.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Instead of using <function>amgettuple</>, an index scan can be done with
|
||||
<function>amgetmulti</> to fetch multiple tuples per call. This can be
|
||||
noticeably more efficient than <function>amgettuple</> because it allows
|
||||
avoiding lock/unlock cycles within the access method. In principle
|
||||
<function>amgetmulti</> should have the same effects as repeated
|
||||
<function>amgettuple</> calls, but we impose several restrictions to
|
||||
simplify matters. In the first place, <function>amgetmulti</> does not
|
||||
take a <literal>direction</> argument, and therefore it does not support
|
||||
backwards scan nor intrascan reversal of direction. The access method
|
||||
need not support marking or restoring scan positions during an
|
||||
<function>amgetmulti</> scan, either. (These restrictions cost little
|
||||
since it would be difficult to use these features in an
|
||||
<function>amgetmulti</> scan anyway: adjusting the caller's buffered
|
||||
list of TIDs would be complex.) Finally, <function>amgetmulti</> does
|
||||
not guarantee any locking of the returned tuples, with implications
|
||||
spelled out in <xref linkend="index-locking">.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="index-locking">
|
||||
@ -515,10 +555,15 @@ amcostestimate (Query *root,
|
||||
and only visit the heap tuples sometime later, requires much less index
|
||||
locking overhead and may allow a more efficient heap access pattern.
|
||||
Per the above analysis, we must use the synchronous approach for
|
||||
non-MVCC-compliant snapshots, but an asynchronous scan would be safe
|
||||
for a query using an MVCC snapshot. This possibility is not exploited
|
||||
as of <productname>PostgreSQL</productname> 8.0, but it is likely to be
|
||||
investigated soon.
|
||||
non-MVCC-compliant snapshots, but an asynchronous scan is workable
|
||||
for a query using an MVCC snapshot.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In an <function>amgetmulti</> index scan, the access method need not
|
||||
guarantee to keep an index pin on any of the returned tuples. (It would be
|
||||
impractical to pin more than the last one anyway.) Therefore
|
||||
it is only safe to use such scans with MVCC-compliant snapshots.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
@ -611,7 +656,6 @@ amcostestimate (Query *root,
|
||||
<programlisting>
|
||||
void
|
||||
amcostestimate (Query *root,
|
||||
RelOptInfo *rel,
|
||||
IndexOptInfo *index,
|
||||
List *indexQuals,
|
||||
Cost *indexStartupCost,
|
||||
@ -632,20 +676,11 @@ amcostestimate (Query *root,
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>rel</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The relation the index is on.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>index</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The index itself.
|
||||
The index being considered.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -714,19 +749,19 @@ amcostestimate (Query *root,
|
||||
|
||||
<para>
|
||||
The index access costs should be computed in the units used by
|
||||
<filename>src/backend/optimizer/path/costsize.c</filename>: a sequential disk block fetch
|
||||
has cost 1.0, a nonsequential fetch has cost random_page_cost, and
|
||||
the cost of processing one index row should usually be taken as
|
||||
cpu_index_tuple_cost (which is a user-adjustable optimizer parameter).
|
||||
In addition, an appropriate multiple of cpu_operator_cost should be charged
|
||||
<filename>src/backend/optimizer/path/costsize.c</filename>: a sequential
|
||||
disk block fetch has cost 1.0, a nonsequential fetch has cost
|
||||
<varname>random_page_cost</>, and the cost of processing one index row
|
||||
should usually be taken as <varname>cpu_index_tuple_cost</>. In addition,
|
||||
an appropriate multiple of <varname>cpu_operator_cost</> should be charged
|
||||
for any comparison operators invoked during index processing (especially
|
||||
evaluation of the indexQuals themselves).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The access costs should include all disk and CPU costs associated with
|
||||
scanning the index itself, but NOT the costs of retrieving or processing
|
||||
the parent-table rows that are identified by the index.
|
||||
scanning the index itself, but <emphasis>not</> the costs of retrieving or
|
||||
processing the parent-table rows that are identified by the index.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -764,7 +799,7 @@ amcostestimate (Query *root,
|
||||
|
||||
<programlisting>
|
||||
*indexSelectivity = clauselist_selectivity(root, indexQuals,
|
||||
rel->relid, JOIN_INNER);
|
||||
index->rel->relid, JOIN_INNER);
|
||||
</programlisting>
|
||||
</para>
|
||||
</step>
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.44 2005/02/05 19:38:58 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.45 2005/03/27 23:52:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -47,6 +47,33 @@ gistgettuple(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
Datum
|
||||
gistgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/* XXX generic implementation: loop around guts of gistgettuple */
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
if (ItemPointerIsValid(&(s->currentItemData)))
|
||||
res = gistnext(s, ForwardScanDirection);
|
||||
else
|
||||
res = gistfirst(s, ForwardScanDirection);
|
||||
if (!res)
|
||||
break;
|
||||
tids[ntids] = s->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
static bool
|
||||
gistfirst(IndexScanDesc s, ScanDirection dir)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.77 2005/03/21 01:23:57 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.78 2005/03/27 23:52:57 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This file contains only the public interface routines.
|
||||
@ -264,6 +264,75 @@ hashgettuple(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hashgetmulti() -- get multiple tuples at once
|
||||
*
|
||||
* This is a somewhat generic implementation: it avoids lock reacquisition
|
||||
* overhead, but there's no smarts about picking especially good stopping
|
||||
* points such as index page boundaries.
|
||||
*/
|
||||
Datum
|
||||
hashgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
HashScanOpaque so = (HashScanOpaque) scan->opaque;
|
||||
Relation rel = scan->indexRelation;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/*
|
||||
* We hold pin but not lock on current buffer while outside the hash
|
||||
* AM. Reacquire the read lock here.
|
||||
*/
|
||||
if (BufferIsValid(so->hashso_curbuf))
|
||||
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
|
||||
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
/*
|
||||
* Start scan, or advance to next tuple.
|
||||
*/
|
||||
if (ItemPointerIsValid(&(scan->currentItemData)))
|
||||
res = _hash_next(scan, ForwardScanDirection);
|
||||
else
|
||||
res = _hash_first(scan, ForwardScanDirection);
|
||||
/*
|
||||
* Skip killed tuples if asked to.
|
||||
*/
|
||||
if (scan->ignore_killed_tuples)
|
||||
{
|
||||
while (res)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
|
||||
page = BufferGetPage(so->hashso_curbuf);
|
||||
if (!ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
break;
|
||||
res = _hash_next(scan, ForwardScanDirection);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
/* Save tuple ID, and continue scanning */
|
||||
tids[ntids] = scan->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
/* Release read lock on current buffer, but keep it pinned */
|
||||
if (BufferIsValid(so->hashso_curbuf))
|
||||
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK);
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hashbeginscan() -- start a scan on a hash index
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.184 2005/03/20 23:40:23 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.185 2005/03/27 23:52:58 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -933,18 +933,35 @@ heap_release_fetch(Relation relation,
|
||||
* Need share lock on buffer to examine tuple commit status.
|
||||
*/
|
||||
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||
dp = (PageHeader) BufferGetPage(buffer);
|
||||
|
||||
/*
|
||||
* We'd better check for out-of-range offnum in case of VACUUM since
|
||||
* the TID was obtained.
|
||||
*/
|
||||
offnum = ItemPointerGetOffsetNumber(tid);
|
||||
if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
|
||||
{
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
if (keep_buf)
|
||||
*userbuf = buffer;
|
||||
else
|
||||
{
|
||||
ReleaseBuffer(buffer);
|
||||
*userbuf = InvalidBuffer;
|
||||
}
|
||||
tuple->t_datamcxt = NULL;
|
||||
tuple->t_data = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the item line pointer corresponding to the requested tid
|
||||
*/
|
||||
dp = (PageHeader) BufferGetPage(buffer);
|
||||
offnum = ItemPointerGetOffsetNumber(tid);
|
||||
lp = PageGetItemId(dp, offnum);
|
||||
|
||||
/*
|
||||
* must check for deleted tuple (see for example analyze.c, which is
|
||||
* careful to pass an offnum in range, but doesn't know if the offnum
|
||||
* actually corresponds to an undeleted tuple).
|
||||
* Must check for deleted tuple.
|
||||
*/
|
||||
if (!ItemIdIsUsed(lp))
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.44 2004/12/31 21:59:19 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.45 2005/03/27 23:52:59 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* many of the old access method routines have been turned into
|
||||
@ -103,6 +103,7 @@ RelationGetIndexScan(Relation indexRelation,
|
||||
|
||||
/* mark cached function lookup data invalid; it will be set later */
|
||||
scan->fn_getnext.fn_oid = InvalidOid;
|
||||
scan->fn_getmulti.fn_oid = InvalidOid;
|
||||
|
||||
scan->unique_tuple_pos = 0;
|
||||
scan->unique_tuple_mark = 0;
|
||||
|
@ -8,20 +8,22 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.78 2005/03/21 01:23:58 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.79 2005/03/27 23:52:59 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
* index_openrv - open an index relation specified by a RangeVar
|
||||
* index_openr - open a system index relation by name
|
||||
* index_close - close an index relation
|
||||
* index_beginscan - start a scan of an index
|
||||
* index_beginscan - start a scan of an index with amgettuple
|
||||
* index_beginscan_multi - start a scan of an index with amgetmulti
|
||||
* index_rescan - restart a scan of an index
|
||||
* index_endscan - end a scan
|
||||
* index_insert - insert an index tuple into a relation
|
||||
* index_markpos - mark a scan position
|
||||
* index_restrpos - restore a scan position
|
||||
* index_getnext - get the next tuple from a scan
|
||||
* index_getmulti - get multiple tuples from a scan
|
||||
* index_bulk_delete - bulk deletion of index tuples
|
||||
* index_vacuum_cleanup - post-deletion cleanup of an index
|
||||
* index_cost_estimator - fetch amcostestimate procedure OID
|
||||
@ -85,24 +87,25 @@
|
||||
AssertMacro(PointerIsValid(scan->indexRelation->rd_am)) \
|
||||
)
|
||||
|
||||
#define GET_REL_PROCEDURE(x,y) \
|
||||
#define GET_REL_PROCEDURE(pname) \
|
||||
( \
|
||||
procedure = indexRelation->rd_am->y, \
|
||||
procedure = indexRelation->rd_am->pname, \
|
||||
(!RegProcedureIsValid(procedure)) ? \
|
||||
elog(ERROR, "index_%s: invalid %s regproc", \
|
||||
CppAsString(x), CppAsString(y)) \
|
||||
elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
|
||||
: (void)NULL \
|
||||
)
|
||||
|
||||
#define GET_SCAN_PROCEDURE(x,y) \
|
||||
#define GET_SCAN_PROCEDURE(pname) \
|
||||
( \
|
||||
procedure = scan->indexRelation->rd_am->y, \
|
||||
procedure = scan->indexRelation->rd_am->pname, \
|
||||
(!RegProcedureIsValid(procedure)) ? \
|
||||
elog(ERROR, "index_%s: invalid %s regproc", \
|
||||
CppAsString(x), CppAsString(y)) \
|
||||
elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
|
||||
: (void)NULL \
|
||||
)
|
||||
|
||||
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
|
||||
int nkeys, ScanKey key);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* index_ interface functions
|
||||
@ -222,7 +225,7 @@ index_insert(Relation indexRelation,
|
||||
RegProcedure procedure;
|
||||
|
||||
RELATION_CHECKS;
|
||||
GET_REL_PROCEDURE(insert, aminsert);
|
||||
GET_REL_PROCEDURE(aminsert);
|
||||
|
||||
/*
|
||||
* have the am's insert proc do all the work.
|
||||
@ -236,15 +239,14 @@ index_insert(Relation indexRelation,
|
||||
BoolGetDatum(check_uniqueness)));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_beginscan - start a scan of an index
|
||||
/*
|
||||
* index_beginscan - start a scan of an index with amgettuple
|
||||
*
|
||||
* Note: heapRelation may be NULL if there is no intention of calling
|
||||
* index_getnext on this scan; index_getnext_indexitem will not use the
|
||||
* heapRelation link (nor the snapshot). However, the caller had better
|
||||
* be holding some kind of lock on the heap relation in any case, to ensure
|
||||
* no one deletes it (or the index) out from under us.
|
||||
* ----------------
|
||||
*/
|
||||
IndexScanDesc
|
||||
index_beginscan(Relation heapRelation,
|
||||
@ -255,8 +257,71 @@ index_beginscan(Relation heapRelation,
|
||||
IndexScanDesc scan;
|
||||
RegProcedure procedure;
|
||||
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, key);
|
||||
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else was
|
||||
* set up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->heapRelation = heapRelation;
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
/*
|
||||
* We want to look up the amgettuple procedure just once per scan, not
|
||||
* once per index_getnext call. So do it here and save the fmgr info
|
||||
* result in the scan descriptor.
|
||||
*/
|
||||
GET_SCAN_PROCEDURE(amgettuple);
|
||||
fmgr_info(procedure, &scan->fn_getnext);
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
/*
|
||||
* index_beginscan_multi - start a scan of an index with amgetmulti
|
||||
*
|
||||
* As above, caller had better be holding some lock on the parent heap
|
||||
* relation, even though it's not explicitly mentioned here.
|
||||
*/
|
||||
IndexScanDesc
|
||||
index_beginscan_multi(Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
RegProcedure procedure;
|
||||
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, key);
|
||||
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else was
|
||||
* set up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
/*
|
||||
* We want to look up the amgetmulti procedure just once per scan, not
|
||||
* once per index_getmulti call. So do it here and save the fmgr info
|
||||
* result in the scan descriptor.
|
||||
*/
|
||||
GET_SCAN_PROCEDURE(amgetmulti);
|
||||
fmgr_info(procedure, &scan->fn_getmulti);
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
/*
|
||||
* index_beginscan_internal --- common code for index_beginscan variants
|
||||
*/
|
||||
static IndexScanDesc
|
||||
index_beginscan_internal(Relation indexRelation,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
RegProcedure procedure;
|
||||
|
||||
RELATION_CHECKS;
|
||||
GET_REL_PROCEDURE(beginscan, ambeginscan);
|
||||
GET_REL_PROCEDURE(ambeginscan);
|
||||
|
||||
RelationIncrementReferenceCount(indexRelation);
|
||||
|
||||
@ -278,21 +343,6 @@ index_beginscan(Relation heapRelation,
|
||||
Int32GetDatum(nkeys),
|
||||
PointerGetDatum(key)));
|
||||
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else was
|
||||
* set up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->heapRelation = heapRelation;
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
/*
|
||||
* We want to look up the amgettuple procedure just once per scan, not
|
||||
* once per index_getnext call. So do it here and save the fmgr info
|
||||
* result in the scan descriptor.
|
||||
*/
|
||||
GET_SCAN_PROCEDURE(beginscan, amgettuple);
|
||||
fmgr_info(procedure, &scan->fn_getnext);
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
@ -314,7 +364,7 @@ index_rescan(IndexScanDesc scan, ScanKey key)
|
||||
RegProcedure procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(rescan, amrescan);
|
||||
GET_SCAN_PROCEDURE(amrescan);
|
||||
|
||||
/* Release any held pin on a heap page */
|
||||
if (BufferIsValid(scan->xs_cbuf))
|
||||
@ -346,7 +396,7 @@ index_endscan(IndexScanDesc scan)
|
||||
RegProcedure procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(endscan, amendscan);
|
||||
GET_SCAN_PROCEDURE(amendscan);
|
||||
|
||||
/* Release any held pin on a heap page */
|
||||
if (BufferIsValid(scan->xs_cbuf))
|
||||
@ -378,7 +428,7 @@ index_markpos(IndexScanDesc scan)
|
||||
RegProcedure procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(markpos, ammarkpos);
|
||||
GET_SCAN_PROCEDURE(ammarkpos);
|
||||
|
||||
scan->unique_tuple_mark = scan->unique_tuple_pos;
|
||||
|
||||
@ -395,7 +445,7 @@ index_restrpos(IndexScanDesc scan)
|
||||
RegProcedure procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(restrpos, amrestrpos);
|
||||
GET_SCAN_PROCEDURE(amrestrpos);
|
||||
|
||||
scan->kill_prior_tuple = false; /* for safety */
|
||||
|
||||
@ -525,9 +575,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
&scan->xs_pgstat_info))
|
||||
break;
|
||||
|
||||
/* Skip if no tuple at this location */
|
||||
/* Skip if no undeleted tuple at this location */
|
||||
if (heapTuple->t_data == NULL)
|
||||
continue; /* should we raise an error instead? */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we can't see it, maybe no one else can either. Check to see
|
||||
@ -595,6 +645,44 @@ index_getnext_indexitem(IndexScanDesc scan,
|
||||
return found;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getmulti - get multiple tuples from an index scan
|
||||
*
|
||||
* Collects the TIDs of multiple heap tuples satisfying the scan keys.
|
||||
* Since there's no interlock between the index scan and the eventual heap
|
||||
* access, this is only safe to use with MVCC-based snapshots: the heap
|
||||
* item slot could have been replaced by a newer tuple by the time we get
|
||||
* to it.
|
||||
*
|
||||
* A TRUE result indicates more calls should occur; a FALSE result says the
|
||||
* scan is done. *returned_tids could be zero or nonzero in either case.
|
||||
* ----------------
|
||||
*/
|
||||
bool
|
||||
index_getmulti(IndexScanDesc scan,
|
||||
ItemPointer tids, int32 max_tids,
|
||||
int32 *returned_tids)
|
||||
{
|
||||
bool found;
|
||||
|
||||
SCAN_CHECKS;
|
||||
|
||||
/* just make sure this is false... */
|
||||
scan->kill_prior_tuple = false;
|
||||
|
||||
/*
|
||||
* have the am's getmulti proc do all the work. index_beginscan_multi
|
||||
* already set up fn_getmulti.
|
||||
*/
|
||||
found = DatumGetBool(FunctionCall4(&scan->fn_getmulti,
|
||||
PointerGetDatum(scan),
|
||||
PointerGetDatum(tids),
|
||||
Int32GetDatum(max_tids),
|
||||
PointerGetDatum(returned_tids)));
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_bulk_delete - do mass deletion of index entries
|
||||
*
|
||||
@ -613,7 +701,7 @@ index_bulk_delete(Relation indexRelation,
|
||||
IndexBulkDeleteResult *result;
|
||||
|
||||
RELATION_CHECKS;
|
||||
GET_REL_PROCEDURE(bulk_delete, ambulkdelete);
|
||||
GET_REL_PROCEDURE(ambulkdelete);
|
||||
|
||||
result = (IndexBulkDeleteResult *)
|
||||
DatumGetPointer(OidFunctionCall3(procedure,
|
||||
@ -644,7 +732,7 @@ index_vacuum_cleanup(Relation indexRelation,
|
||||
if (!RegProcedureIsValid(indexRelation->rd_am->amvacuumcleanup))
|
||||
return stats;
|
||||
|
||||
GET_REL_PROCEDURE(vacuum_cleanup, amvacuumcleanup);
|
||||
GET_REL_PROCEDURE(amvacuumcleanup);
|
||||
|
||||
result = (IndexBulkDeleteResult *)
|
||||
DatumGetPointer(OidFunctionCall3(procedure,
|
||||
@ -671,7 +759,7 @@ index_cost_estimator(Relation indexRelation)
|
||||
RegProcedure procedure;
|
||||
|
||||
RELATION_CHECKS;
|
||||
GET_REL_PROCEDURE(cost_estimator, amcostestimate);
|
||||
GET_REL_PROCEDURE(amcostestimate);
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.126 2005/03/21 01:23:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.127 2005/03/27 23:53:00 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -340,6 +340,79 @@ btgettuple(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* btgetmulti() -- get multiple tuples at once
|
||||
*
|
||||
* This is a somewhat generic implementation: it avoids the _bt_restscan
|
||||
* overhead, but there's no smarts about picking especially good stopping
|
||||
* points such as index page boundaries.
|
||||
*/
|
||||
Datum
|
||||
btgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/*
|
||||
* Restore prior state if we were already called at least once.
|
||||
*/
|
||||
if (ItemPointerIsValid(&(scan->currentItemData)))
|
||||
_bt_restscan(scan);
|
||||
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
/*
|
||||
* Start scan, or advance to next tuple.
|
||||
*/
|
||||
if (ItemPointerIsValid(&(scan->currentItemData)))
|
||||
res = _bt_next(scan, ForwardScanDirection);
|
||||
else
|
||||
res = _bt_first(scan, ForwardScanDirection);
|
||||
/*
|
||||
* Skip killed tuples if asked to.
|
||||
*/
|
||||
if (scan->ignore_killed_tuples)
|
||||
{
|
||||
while (res)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
|
||||
page = BufferGetPage(so->btso_curbuf);
|
||||
if (!ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
break;
|
||||
res = _bt_next(scan, ForwardScanDirection);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
/* Save tuple ID, and continue scanning */
|
||||
tids[ntids] = scan->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save heap TID to use it in _bt_restscan. Then release the read
|
||||
* lock on the buffer so that we aren't blocking other backends.
|
||||
*/
|
||||
if (res)
|
||||
{
|
||||
((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self;
|
||||
LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf,
|
||||
BUFFER_LOCK_UNLOCK);
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* btbeginscan() -- start a scan on a btree index
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.34 2005/01/18 23:25:43 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.35 2005/03/27 23:53:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,15 +29,13 @@ rtgettuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
RTreeScanOpaque so;
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
/*
|
||||
* If we've already produced a tuple and the executor has informed
|
||||
* us that it should be marked "killed", do so know.
|
||||
* us that it should be marked "killed", do so now.
|
||||
*/
|
||||
if (s->kill_prior_tuple && ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
@ -57,7 +55,7 @@ rtgettuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
bool res = rtnext(s, dir);
|
||||
|
||||
if (res == true && s->ignore_killed_tuples)
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
@ -69,6 +67,42 @@ rtgettuple(PG_FUNCTION_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
Datum
|
||||
rtgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/* XXX generic implementation: loop around guts of rtgettuple */
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
res = rtnext(s, ForwardScanDirection);
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
if (ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
tids[ntids] = s->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtnext(IndexScanDesc s, ScanDirection dir)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.139 2005/03/27 06:29:35 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.140 2005/03/27 23:53:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -277,9 +277,8 @@ cost_index(Path *path, Query *root,
|
||||
* index (ie, the fraction of main-table tuples we will have to
|
||||
* retrieve) and its correlation to the main-table tuple order.
|
||||
*/
|
||||
OidFunctionCall8(index->amcostestimate,
|
||||
OidFunctionCall7(index->amcostestimate,
|
||||
PointerGetDatum(root),
|
||||
PointerGetDatum(baserel),
|
||||
PointerGetDatum(index),
|
||||
PointerGetDatum(indexQuals),
|
||||
PointerGetDatum(&indexStartupCost),
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.174 2005/03/26 20:55:39 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.175 2005/03/27 23:53:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -4198,7 +4198,7 @@ string_to_bytea_const(const char *str, size_t str_len)
|
||||
*/
|
||||
|
||||
static void
|
||||
genericcostestimate(Query *root, RelOptInfo *rel,
|
||||
genericcostestimate(Query *root,
|
||||
IndexOptInfo *index, List *indexQuals,
|
||||
Cost *indexStartupCost,
|
||||
Cost *indexTotalCost,
|
||||
@ -4250,7 +4250,7 @@ genericcostestimate(Query *root, RelOptInfo *rel,
|
||||
|
||||
/* Estimate the fraction of main-table tuples that will be visited */
|
||||
*indexSelectivity = clauselist_selectivity(root, selectivityQuals,
|
||||
rel->relid,
|
||||
index->rel->relid,
|
||||
JOIN_INNER);
|
||||
|
||||
/*
|
||||
@ -4259,7 +4259,7 @@ genericcostestimate(Query *root, RelOptInfo *rel,
|
||||
* for partial indexes. We can bound the number of tuples by the
|
||||
* index size, in any case.
|
||||
*/
|
||||
numIndexTuples = *indexSelectivity * rel->tuples;
|
||||
numIndexTuples = *indexSelectivity * index->rel->tuples;
|
||||
|
||||
if (numIndexTuples > index->tuples)
|
||||
numIndexTuples = index->tuples;
|
||||
@ -4328,25 +4328,24 @@ Datum
|
||||
btcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Query *root = (Query *) PG_GETARG_POINTER(0);
|
||||
RelOptInfo *rel = (RelOptInfo *) PG_GETARG_POINTER(1);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(3);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
Oid relid;
|
||||
AttrNumber colnum;
|
||||
HeapTuple tuple;
|
||||
|
||||
genericcostestimate(root, rel, index, indexQuals,
|
||||
genericcostestimate(root, index, indexQuals,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
/*
|
||||
* If we can get an estimate of the first column's ordering
|
||||
* correlation C from pg_statistic, estimate the index correlation as
|
||||
* C for a single- column index, or C * 0.75 for multiple columns.
|
||||
* C for a single-column index, or C * 0.75 for multiple columns.
|
||||
* (The idea here is that multiple columns dilute the importance of
|
||||
* the first column's ordering, but don't negate it entirely. Before
|
||||
* 8.0 we divided the correlation by the number of columns, but that
|
||||
@ -4355,7 +4354,7 @@ btcostestimate(PG_FUNCTION_ARGS)
|
||||
if (index->indexkeys[0] != 0)
|
||||
{
|
||||
/* Simple variable --- look to stats for the underlying table */
|
||||
relid = getrelid(rel->relid, root->rtable);
|
||||
relid = getrelid(index->rel->relid, root->rtable);
|
||||
Assert(relid != InvalidOid);
|
||||
colnum = index->indexkeys[0];
|
||||
}
|
||||
@ -4408,15 +4407,14 @@ Datum
|
||||
rtcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Query *root = (Query *) PG_GETARG_POINTER(0);
|
||||
RelOptInfo *rel = (RelOptInfo *) PG_GETARG_POINTER(1);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(3);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
|
||||
genericcostestimate(root, rel, index, indexQuals,
|
||||
genericcostestimate(root, index, indexQuals,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
@ -4427,15 +4425,14 @@ Datum
|
||||
hashcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Query *root = (Query *) PG_GETARG_POINTER(0);
|
||||
RelOptInfo *rel = (RelOptInfo *) PG_GETARG_POINTER(1);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(3);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
|
||||
genericcostestimate(root, rel, index, indexQuals,
|
||||
genericcostestimate(root, index, indexQuals,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
@ -4446,15 +4443,14 @@ Datum
|
||||
gistcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Query *root = (Query *) PG_GETARG_POINTER(0);
|
||||
RelOptInfo *rel = (RelOptInfo *) PG_GETARG_POINTER(1);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(3);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
|
||||
genericcostestimate(root, rel, index, indexQuals,
|
||||
genericcostestimate(root, index, indexQuals,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.48 2005/03/21 01:24:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.49 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -82,6 +82,9 @@ extern IndexScanDesc index_beginscan(Relation heapRelation,
|
||||
Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key);
|
||||
extern IndexScanDesc index_beginscan_multi(Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key);
|
||||
extern void index_rescan(IndexScanDesc scan, ScanKey key);
|
||||
extern void index_endscan(IndexScanDesc scan);
|
||||
extern void index_markpos(IndexScanDesc scan);
|
||||
@ -89,6 +92,9 @@ extern void index_restrpos(IndexScanDesc scan);
|
||||
extern HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction);
|
||||
extern bool index_getnext_indexitem(IndexScanDesc scan,
|
||||
ScanDirection direction);
|
||||
extern bool index_getmulti(IndexScanDesc scan,
|
||||
ItemPointer tids, int32 max_tids,
|
||||
int32 *returned_tids);
|
||||
|
||||
extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation,
|
||||
IndexBulkDeleteCallback callback,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.43 2004/12/31 22:03:21 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.44 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -196,5 +196,6 @@ extern void gist_desc(char *buf, uint8 xl_info, char *rec);
|
||||
|
||||
/* gistget.c */
|
||||
extern Datum gistgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum gistgetmulti(PG_FUNCTION_ARGS);
|
||||
|
||||
#endif /* GIST_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.60 2005/03/21 01:24:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.61 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* modeled after Margo Seltzer's hash implementation for unix.
|
||||
@ -232,8 +232,9 @@ typedef HashItemData *HashItem;
|
||||
|
||||
extern Datum hashbuild(PG_FUNCTION_ARGS);
|
||||
extern Datum hashinsert(PG_FUNCTION_ARGS);
|
||||
extern Datum hashgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum hashbeginscan(PG_FUNCTION_ARGS);
|
||||
extern Datum hashgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum hashgetmulti(PG_FUNCTION_ARGS);
|
||||
extern Datum hashrescan(PG_FUNCTION_ARGS);
|
||||
extern Datum hashendscan(PG_FUNCTION_ARGS);
|
||||
extern Datum hashmarkpos(PG_FUNCTION_ARGS);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.84 2005/03/21 01:24:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.85 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -404,8 +404,9 @@ typedef BTScanOpaqueData *BTScanOpaque;
|
||||
*/
|
||||
extern Datum btbuild(PG_FUNCTION_ARGS);
|
||||
extern Datum btinsert(PG_FUNCTION_ARGS);
|
||||
extern Datum btgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum btbeginscan(PG_FUNCTION_ARGS);
|
||||
extern Datum btgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum btgetmulti(PG_FUNCTION_ARGS);
|
||||
extern Datum btrescan(PG_FUNCTION_ARGS);
|
||||
extern Datum btendscan(PG_FUNCTION_ARGS);
|
||||
extern Datum btmarkpos(PG_FUNCTION_ARGS);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.37 2004/12/31 22:03:21 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.38 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -38,7 +38,12 @@ typedef struct HeapScanDescData
|
||||
|
||||
typedef HeapScanDescData *HeapScanDesc;
|
||||
|
||||
|
||||
/*
|
||||
* We use the same IndexScanDescData structure for both amgettuple-based
|
||||
* and amgetmulti-based index scans. Which one is being used can be told
|
||||
* by looking at fn_getnext and fn_getmulti, only one of which will be
|
||||
* initialized. Some fields are only relevant in amgettuple-based scans.
|
||||
*/
|
||||
typedef struct IndexScanDescData
|
||||
{
|
||||
/* scan parameters */
|
||||
@ -71,6 +76,7 @@ typedef struct IndexScanDescData
|
||||
/* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
|
||||
|
||||
FmgrInfo fn_getnext; /* cached lookup info for AM's getnext fn */
|
||||
FmgrInfo fn_getmulti; /* cached lookup info for AM's getmulti fn */
|
||||
|
||||
/*
|
||||
* If keys_are_unique and got_tuple are both true, we stop calling the
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.37 2005/01/18 23:25:55 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.38 2005/03/27 23:53:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -116,10 +116,9 @@ extern void freestack(RTSTACK *s);
|
||||
*/
|
||||
extern Datum rtinsert(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbulkdelete(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum rtgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbeginscan(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum rtgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum rtgetmulti(PG_FUNCTION_ARGS);
|
||||
extern Datum rtendscan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtmarkpos(PG_FUNCTION_ARGS);
|
||||
extern Datum rtrestrpos(PG_FUNCTION_ARGS);
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.259 2005/03/21 01:24:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.260 2005/03/27 23:53:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200503201
|
||||
#define CATALOG_VERSION_NO 200503271
|
||||
|
||||
#endif
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_am.h
|
||||
* definition of the system "am" relation (pg_am)
|
||||
* definition of the system "access method" relation (pg_am)
|
||||
* along with the relation's initial contents.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.31 2004/12/31 22:03:24 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.32 2005/03/27 23:53:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -37,7 +37,6 @@
|
||||
CATALOG(pg_am)
|
||||
{
|
||||
NameData amname; /* access method name */
|
||||
int4 amowner; /* usesysid of creator */
|
||||
int2 amstrategies; /* total NUMBER of strategies (operators)
|
||||
* by which we can traverse/search this AM */
|
||||
int2 amsupport; /* total NUMBER of support functions that
|
||||
@ -49,9 +48,10 @@ CATALOG(pg_am)
|
||||
bool amcanmulticol; /* does AM support multi-column indexes? */
|
||||
bool amindexnulls; /* does AM support NULL index entries? */
|
||||
bool amconcurrent; /* does AM support concurrent updates? */
|
||||
regproc amgettuple; /* "next valid tuple" function */
|
||||
regproc aminsert; /* "insert this tuple" function */
|
||||
regproc ambeginscan; /* "start new scan" function */
|
||||
regproc amgettuple; /* "next valid tuple" function */
|
||||
regproc amgetmulti; /* "fetch multiple tuples" function */
|
||||
regproc amrescan; /* "restart this scan" function */
|
||||
regproc amendscan; /* "end this scan" function */
|
||||
regproc ammarkpos; /* "mark current scan position" function */
|
||||
@ -75,17 +75,17 @@ typedef FormData_pg_am *Form_pg_am;
|
||||
*/
|
||||
#define Natts_pg_am 20
|
||||
#define Anum_pg_am_amname 1
|
||||
#define Anum_pg_am_amowner 2
|
||||
#define Anum_pg_am_amstrategies 3
|
||||
#define Anum_pg_am_amsupport 4
|
||||
#define Anum_pg_am_amorderstrategy 5
|
||||
#define Anum_pg_am_amcanunique 6
|
||||
#define Anum_pg_am_amcanmulticol 7
|
||||
#define Anum_pg_am_amindexnulls 8
|
||||
#define Anum_pg_am_amconcurrent 9
|
||||
#define Anum_pg_am_amgettuple 10
|
||||
#define Anum_pg_am_aminsert 11
|
||||
#define Anum_pg_am_ambeginscan 12
|
||||
#define Anum_pg_am_amstrategies 2
|
||||
#define Anum_pg_am_amsupport 3
|
||||
#define Anum_pg_am_amorderstrategy 4
|
||||
#define Anum_pg_am_amcanunique 5
|
||||
#define Anum_pg_am_amcanmulticol 6
|
||||
#define Anum_pg_am_amindexnulls 7
|
||||
#define Anum_pg_am_amconcurrent 8
|
||||
#define Anum_pg_am_aminsert 9
|
||||
#define Anum_pg_am_ambeginscan 10
|
||||
#define Anum_pg_am_amgettuple 11
|
||||
#define Anum_pg_am_amgetmulti 12
|
||||
#define Anum_pg_am_amrescan 13
|
||||
#define Anum_pg_am_amendscan 14
|
||||
#define Anum_pg_am_ammarkpos 15
|
||||
@ -100,15 +100,15 @@ typedef FormData_pg_am *Form_pg_am;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
DATA(insert OID = 402 ( rtree PGUID 8 3 0 f f f f rtgettuple rtinsert rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate ));
|
||||
DATA(insert OID = 402 ( rtree 8 3 0 f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate ));
|
||||
DESCR("r-tree index access method");
|
||||
DATA(insert OID = 403 ( btree PGUID 5 1 1 t t t t btgettuple btinsert btbeginscan btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
||||
DATA(insert OID = 403 ( btree 5 1 1 t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
||||
DESCR("b-tree index access method");
|
||||
#define BTREE_AM_OID 403
|
||||
DATA(insert OID = 405 ( hash PGUID 1 1 0 f f f t hashgettuple hashinsert hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
|
||||
DATA(insert OID = 405 ( hash 1 1 0 f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
|
||||
DESCR("hash index access method");
|
||||
#define HASH_AM_OID 405
|
||||
DATA(insert OID = 783 ( gist PGUID 100 7 0 f t f f gistgettuple gistinsert gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate ));
|
||||
DATA(insert OID = 783 ( gist 100 7 0 f t f f gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate ));
|
||||
DESCR("GiST index access method");
|
||||
#define GIST_AM_OID 783
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.353 2005/03/21 01:24:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.354 2005/03/27 23:53:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -664,6 +664,8 @@ DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ rtgettuple - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 635 ( rtgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ rtgetmulti - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 323 ( rtbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ rtbuild - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 324 ( rtbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ rtbeginscan - _null_ ));
|
||||
@ -678,11 +680,13 @@ DATA(insert OID = 328 ( rtrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 321 ( rtbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ rtbulkdelete - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 1265 ( rtcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ rtcostestimate - _null_ ));
|
||||
DATA(insert OID = 1265 ( rtcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ rtcostestimate - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
|
||||
DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ btgettuple - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 636 ( btgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ btgetmulti - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ btinsert - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 333 ( btbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ btbeginscan - _null_ ));
|
||||
@ -701,7 +705,7 @@ DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ btvacuumcleanup - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ btcostestimate - _null_ ));
|
||||
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ btcostestimate - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
|
||||
DATA(insert OID = 339 ( poly_same PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ poly_same - _null_ ));
|
||||
@ -798,6 +802,8 @@ DESCR("convert char(n) to name");
|
||||
|
||||
DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ hashgettuple - _null_ ));
|
||||
DESCR("hash(internal)");
|
||||
DATA(insert OID = 637 ( hashgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ hashgetmulti - _null_ ));
|
||||
DESCR("hash(internal)");
|
||||
DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ hashinsert - _null_ ));
|
||||
DESCR("hash(internal)");
|
||||
DATA(insert OID = 443 ( hashbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ hashbeginscan - _null_ ));
|
||||
@ -814,7 +820,7 @@ DATA(insert OID = 448 ( hashbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 228
|
||||
DESCR("hash(internal)");
|
||||
DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ hashbulkdelete - _null_ ));
|
||||
DESCR("hash(internal)");
|
||||
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ hashcostestimate - _null_ ));
|
||||
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ hashcostestimate - _null_ ));
|
||||
DESCR("hash(internal)");
|
||||
|
||||
DATA(insert OID = 449 ( hashint2 PGNSP PGUID 12 f f t f i 1 23 "21" _null_ hashint2 - _null_ ));
|
||||
@ -1060,6 +1066,8 @@ DESCR("smaller of two");
|
||||
|
||||
DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ gistgettuple - _null_ ));
|
||||
DESCR("gist(internal)");
|
||||
DATA(insert OID = 638 ( gistgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ gistgetmulti - _null_ ));
|
||||
DESCR("gist(internal)");
|
||||
DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ gistinsert - _null_ ));
|
||||
DESCR("gist(internal)");
|
||||
DATA(insert OID = 777 ( gistbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ gistbeginscan - _null_ ));
|
||||
@ -1076,7 +1084,7 @@ DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 228
|
||||
DESCR("gist(internal)");
|
||||
DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ gistbulkdelete - _null_ ));
|
||||
DESCR("gist(internal)");
|
||||
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ gistcostestimate - _null_ ));
|
||||
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ gistcostestimate - _null_ ));
|
||||
DESCR("gist(internal)");
|
||||
|
||||
DATA(insert OID = 784 ( tintervaleq PGNSP PGUID 12 f f t f i 2 16 "704 704" _null_ tintervaleq - _null_ ));
|
||||
|
Loading…
Reference in New Issue
Block a user