Commit 32e8fc4a authored by Tom Lane's avatar Tom Lane

Arrange to cache fmgr lookup information for an index's access method

routines in the index's relcache entry, instead of doing a fresh fmgr_info
on every index access.  We were already doing this for the index's opclass
support functions; not sure why we didn't think to do it for the AM
functions too.  This supersedes the former method of caching (only)
amgettuple in indexscan scan descriptors; it's an improvement because the
function lookup can be amortized across multiple statements instead of
being repeated for each statement.  Even though lookup for builtin
functions is pretty cheap, this seems to drop a percent or two off some
simple benchmarks.
parent dd67cf36
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.47 2005/04/14 20:03:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.48 2005/05/27 23:31:20 tgl Exp $
* *
* NOTES * NOTES
* many of the old access method routines have been turned into * many of the old access method routines have been turned into
...@@ -86,6 +86,7 @@ RelationGetIndexScan(Relation indexRelation, ...@@ -86,6 +86,7 @@ RelationGetIndexScan(Relation indexRelation,
else else
scan->keyData = NULL; scan->keyData = NULL;
scan->is_multiscan = false; /* caller may change this */
scan->kill_prior_tuple = false; scan->kill_prior_tuple = false;
scan->ignore_killed_tuples = true; /* default setting */ scan->ignore_killed_tuples = true; /* default setting */
scan->keys_are_unique = false; /* may be set by index AM */ scan->keys_are_unique = false; /* may be set by index AM */
...@@ -101,10 +102,6 @@ RelationGetIndexScan(Relation indexRelation, ...@@ -101,10 +102,6 @@ RelationGetIndexScan(Relation indexRelation,
scan->xs_ctup.t_data = NULL; scan->xs_ctup.t_data = NULL;
scan->xs_cbuf = InvalidBuffer; scan->xs_cbuf = InvalidBuffer;
/* 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_pos = 0;
scan->unique_tuple_mark = 0; scan->unique_tuple_mark = 0;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.81 2005/05/15 21:19:54 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.82 2005/05/27 23:31:20 tgl Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relation OID * index_open - open an index relation by relation OID
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
* index_vacuum_cleanup - post-deletion cleanup of an index * index_vacuum_cleanup - post-deletion cleanup of an index
* index_cost_estimator - fetch amcostestimate procedure OID * index_cost_estimator - fetch amcostestimate procedure OID
* index_getprocid - get a support procedure OID * index_getprocid - get a support procedure OID
* index_getprocinfo - get a support procedure's lookup info
* *
* NOTES * NOTES
* This file contains the index_ routines which used * This file contains the index_ routines which used
...@@ -87,20 +88,28 @@ ...@@ -87,20 +88,28 @@
) )
#define GET_REL_PROCEDURE(pname) \ #define GET_REL_PROCEDURE(pname) \
( \ do { \
procedure = indexRelation->rd_am->pname, \ procedure = &indexRelation->rd_aminfo->pname; \
(!RegProcedureIsValid(procedure)) ? \ if (!OidIsValid(procedure->fn_oid)) \
elog(ERROR, "invalid %s regproc", CppAsString(pname)) \ { \
: (void)NULL \ RegProcedure procOid = indexRelation->rd_am->pname; \
) if (!RegProcedureIsValid(procOid)) \
elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
fmgr_info_cxt(procOid, procedure, indexRelation->rd_indexcxt); \
} \
} while(0)
#define GET_SCAN_PROCEDURE(pname) \ #define GET_SCAN_PROCEDURE(pname) \
( \ do { \
procedure = scan->indexRelation->rd_am->pname, \ procedure = &scan->indexRelation->rd_aminfo->pname; \
(!RegProcedureIsValid(procedure)) ? \ if (!OidIsValid(procedure->fn_oid)) \
elog(ERROR, "invalid %s regproc", CppAsString(pname)) \ { \
: (void)NULL \ RegProcedure procOid = scan->indexRelation->rd_am->pname; \
) if (!RegProcedureIsValid(procOid)) \
elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
fmgr_info_cxt(procOid, procedure, scan->indexRelation->rd_indexcxt); \
} \
} while(0)
static IndexScanDesc index_beginscan_internal(Relation indexRelation, static IndexScanDesc index_beginscan_internal(Relation indexRelation,
int nkeys, ScanKey key); int nkeys, ScanKey key);
...@@ -196,7 +205,7 @@ index_insert(Relation indexRelation, ...@@ -196,7 +205,7 @@ index_insert(Relation indexRelation,
Relation heapRelation, Relation heapRelation,
bool check_uniqueness) bool check_uniqueness)
{ {
RegProcedure procedure; FmgrInfo *procedure;
RELATION_CHECKS; RELATION_CHECKS;
GET_REL_PROCEDURE(aminsert); GET_REL_PROCEDURE(aminsert);
...@@ -204,7 +213,7 @@ index_insert(Relation indexRelation, ...@@ -204,7 +213,7 @@ index_insert(Relation indexRelation,
/* /*
* have the am's insert proc do all the work. * have the am's insert proc do all the work.
*/ */
return DatumGetBool(OidFunctionCall6(procedure, return DatumGetBool(FunctionCall6(procedure,
PointerGetDatum(indexRelation), PointerGetDatum(indexRelation),
PointerGetDatum(values), PointerGetDatum(values),
PointerGetDatum(isnull), PointerGetDatum(isnull),
...@@ -229,7 +238,6 @@ index_beginscan(Relation heapRelation, ...@@ -229,7 +238,6 @@ index_beginscan(Relation heapRelation,
int nkeys, ScanKey key) int nkeys, ScanKey key)
{ {
IndexScanDesc scan; IndexScanDesc scan;
RegProcedure procedure;
scan = index_beginscan_internal(indexRelation, nkeys, key); scan = index_beginscan_internal(indexRelation, nkeys, key);
...@@ -237,17 +245,10 @@ index_beginscan(Relation heapRelation, ...@@ -237,17 +245,10 @@ index_beginscan(Relation heapRelation,
* Save additional parameters into the scandesc. Everything else was * Save additional parameters into the scandesc. Everything else was
* set up by RelationGetIndexScan. * set up by RelationGetIndexScan.
*/ */
scan->is_multiscan = false;
scan->heapRelation = heapRelation; scan->heapRelation = heapRelation;
scan->xs_snapshot = snapshot; 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; return scan;
} }
...@@ -263,7 +264,6 @@ index_beginscan_multi(Relation indexRelation, ...@@ -263,7 +264,6 @@ index_beginscan_multi(Relation indexRelation,
int nkeys, ScanKey key) int nkeys, ScanKey key)
{ {
IndexScanDesc scan; IndexScanDesc scan;
RegProcedure procedure;
scan = index_beginscan_internal(indexRelation, nkeys, key); scan = index_beginscan_internal(indexRelation, nkeys, key);
...@@ -271,16 +271,9 @@ index_beginscan_multi(Relation indexRelation, ...@@ -271,16 +271,9 @@ index_beginscan_multi(Relation indexRelation,
* Save additional parameters into the scandesc. Everything else was * Save additional parameters into the scandesc. Everything else was
* set up by RelationGetIndexScan. * set up by RelationGetIndexScan.
*/ */
scan->is_multiscan = true;
scan->xs_snapshot = snapshot; 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; return scan;
} }
...@@ -292,7 +285,7 @@ index_beginscan_internal(Relation indexRelation, ...@@ -292,7 +285,7 @@ index_beginscan_internal(Relation indexRelation,
int nkeys, ScanKey key) int nkeys, ScanKey key)
{ {
IndexScanDesc scan; IndexScanDesc scan;
RegProcedure procedure; FmgrInfo *procedure;
RELATION_CHECKS; RELATION_CHECKS;
GET_REL_PROCEDURE(ambeginscan); GET_REL_PROCEDURE(ambeginscan);
...@@ -312,7 +305,7 @@ index_beginscan_internal(Relation indexRelation, ...@@ -312,7 +305,7 @@ index_beginscan_internal(Relation indexRelation,
* Tell the AM to open a scan. * Tell the AM to open a scan.
*/ */
scan = (IndexScanDesc) scan = (IndexScanDesc)
DatumGetPointer(OidFunctionCall3(procedure, DatumGetPointer(FunctionCall3(procedure,
PointerGetDatum(indexRelation), PointerGetDatum(indexRelation),
Int32GetDatum(nkeys), Int32GetDatum(nkeys),
PointerGetDatum(key))); PointerGetDatum(key)));
...@@ -335,7 +328,7 @@ index_beginscan_internal(Relation indexRelation, ...@@ -335,7 +328,7 @@ index_beginscan_internal(Relation indexRelation,
void void
index_rescan(IndexScanDesc scan, ScanKey key) index_rescan(IndexScanDesc scan, ScanKey key)
{ {
RegProcedure procedure; FmgrInfo *procedure;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amrescan); GET_SCAN_PROCEDURE(amrescan);
...@@ -353,7 +346,7 @@ index_rescan(IndexScanDesc scan, ScanKey key) ...@@ -353,7 +346,7 @@ index_rescan(IndexScanDesc scan, ScanKey key)
scan->unique_tuple_pos = 0; scan->unique_tuple_pos = 0;
scan->unique_tuple_mark = 0; scan->unique_tuple_mark = 0;
OidFunctionCall2(procedure, FunctionCall2(procedure,
PointerGetDatum(scan), PointerGetDatum(scan),
PointerGetDatum(key)); PointerGetDatum(key));
...@@ -367,7 +360,7 @@ index_rescan(IndexScanDesc scan, ScanKey key) ...@@ -367,7 +360,7 @@ index_rescan(IndexScanDesc scan, ScanKey key)
void void
index_endscan(IndexScanDesc scan) index_endscan(IndexScanDesc scan)
{ {
RegProcedure procedure; FmgrInfo *procedure;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amendscan); GET_SCAN_PROCEDURE(amendscan);
...@@ -380,7 +373,7 @@ index_endscan(IndexScanDesc scan) ...@@ -380,7 +373,7 @@ index_endscan(IndexScanDesc scan)
} }
/* End the AM's scan */ /* End the AM's scan */
OidFunctionCall1(procedure, PointerGetDatum(scan)); FunctionCall1(procedure, PointerGetDatum(scan));
/* Release index lock and refcount acquired by index_beginscan */ /* Release index lock and refcount acquired by index_beginscan */
...@@ -399,14 +392,14 @@ index_endscan(IndexScanDesc scan) ...@@ -399,14 +392,14 @@ index_endscan(IndexScanDesc scan)
void void
index_markpos(IndexScanDesc scan) index_markpos(IndexScanDesc scan)
{ {
RegProcedure procedure; FmgrInfo *procedure;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(ammarkpos); GET_SCAN_PROCEDURE(ammarkpos);
scan->unique_tuple_mark = scan->unique_tuple_pos; scan->unique_tuple_mark = scan->unique_tuple_pos;
OidFunctionCall1(procedure, PointerGetDatum(scan)); FunctionCall1(procedure, PointerGetDatum(scan));
} }
/* ---------------- /* ----------------
...@@ -420,7 +413,7 @@ index_markpos(IndexScanDesc scan) ...@@ -420,7 +413,7 @@ index_markpos(IndexScanDesc scan)
void void
index_restrpos(IndexScanDesc scan) index_restrpos(IndexScanDesc scan)
{ {
RegProcedure procedure; FmgrInfo *procedure;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amrestrpos); GET_SCAN_PROCEDURE(amrestrpos);
...@@ -434,7 +427,7 @@ index_restrpos(IndexScanDesc scan) ...@@ -434,7 +427,7 @@ index_restrpos(IndexScanDesc scan)
*/ */
scan->unique_tuple_pos = scan->unique_tuple_mark; scan->unique_tuple_pos = scan->unique_tuple_mark;
OidFunctionCall1(procedure, PointerGetDatum(scan)); FunctionCall1(procedure, PointerGetDatum(scan));
} }
/* ---------------- /* ----------------
...@@ -451,8 +444,10 @@ HeapTuple ...@@ -451,8 +444,10 @@ HeapTuple
index_getnext(IndexScanDesc scan, ScanDirection direction) index_getnext(IndexScanDesc scan, ScanDirection direction)
{ {
HeapTuple heapTuple = &scan->xs_ctup; HeapTuple heapTuple = &scan->xs_ctup;
FmgrInfo *procedure;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amgettuple);
/* /*
* If we already got a tuple and it must be unique, there's no need to * If we already got a tuple and it must be unique, there's no need to
...@@ -525,9 +520,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction) ...@@ -525,9 +520,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
/* /*
* The AM's gettuple proc finds the next tuple matching the scan * The AM's gettuple proc finds the next tuple matching the scan
* keys. index_beginscan already set up fn_getnext. * keys.
*/ */
found = DatumGetBool(FunctionCall2(&scan->fn_getnext, found = DatumGetBool(FunctionCall2(procedure,
PointerGetDatum(scan), PointerGetDatum(scan),
Int32GetDatum(direction))); Int32GetDatum(direction)));
...@@ -605,18 +600,19 @@ bool ...@@ -605,18 +600,19 @@ bool
index_getnext_indexitem(IndexScanDesc scan, index_getnext_indexitem(IndexScanDesc scan,
ScanDirection direction) ScanDirection direction)
{ {
FmgrInfo *procedure;
bool found; bool found;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amgettuple);
/* just make sure this is false... */ /* just make sure this is false... */
scan->kill_prior_tuple = false; scan->kill_prior_tuple = false;
/* /*
* have the am's gettuple proc do all the work. index_beginscan * have the am's gettuple proc do all the work.
* already set up fn_getnext.
*/ */
found = DatumGetBool(FunctionCall2(&scan->fn_getnext, found = DatumGetBool(FunctionCall2(procedure,
PointerGetDatum(scan), PointerGetDatum(scan),
Int32GetDatum(direction))); Int32GetDatum(direction)));
...@@ -641,18 +637,19 @@ index_getmulti(IndexScanDesc scan, ...@@ -641,18 +637,19 @@ index_getmulti(IndexScanDesc scan,
ItemPointer tids, int32 max_tids, ItemPointer tids, int32 max_tids,
int32 *returned_tids) int32 *returned_tids)
{ {
FmgrInfo *procedure;
bool found; bool found;
SCAN_CHECKS; SCAN_CHECKS;
GET_SCAN_PROCEDURE(amgetmulti);
/* just make sure this is false... */ /* just make sure this is false... */
scan->kill_prior_tuple = false; scan->kill_prior_tuple = false;
/* /*
* have the am's getmulti proc do all the work. index_beginscan_multi * have the am's getmulti proc do all the work.
* already set up fn_getmulti.
*/ */
found = DatumGetBool(FunctionCall4(&scan->fn_getmulti, found = DatumGetBool(FunctionCall4(procedure,
PointerGetDatum(scan), PointerGetDatum(scan),
PointerGetDatum(tids), PointerGetDatum(tids),
Int32GetDatum(max_tids), Int32GetDatum(max_tids),
...@@ -675,14 +672,14 @@ index_bulk_delete(Relation indexRelation, ...@@ -675,14 +672,14 @@ index_bulk_delete(Relation indexRelation,
IndexBulkDeleteCallback callback, IndexBulkDeleteCallback callback,
void *callback_state) void *callback_state)
{ {
RegProcedure procedure; FmgrInfo *procedure;
IndexBulkDeleteResult *result; IndexBulkDeleteResult *result;
RELATION_CHECKS; RELATION_CHECKS;
GET_REL_PROCEDURE(ambulkdelete); GET_REL_PROCEDURE(ambulkdelete);
result = (IndexBulkDeleteResult *) result = (IndexBulkDeleteResult *)
DatumGetPointer(OidFunctionCall3(procedure, DatumGetPointer(FunctionCall3(procedure,
PointerGetDatum(indexRelation), PointerGetDatum(indexRelation),
PointerGetDatum((Pointer) callback), PointerGetDatum((Pointer) callback),
PointerGetDatum(callback_state))); PointerGetDatum(callback_state)));
...@@ -701,7 +698,7 @@ index_vacuum_cleanup(Relation indexRelation, ...@@ -701,7 +698,7 @@ index_vacuum_cleanup(Relation indexRelation,
IndexVacuumCleanupInfo *info, IndexVacuumCleanupInfo *info,
IndexBulkDeleteResult *stats) IndexBulkDeleteResult *stats)
{ {
RegProcedure procedure; FmgrInfo *procedure;
IndexBulkDeleteResult *result; IndexBulkDeleteResult *result;
RELATION_CHECKS; RELATION_CHECKS;
...@@ -713,7 +710,7 @@ index_vacuum_cleanup(Relation indexRelation, ...@@ -713,7 +710,7 @@ index_vacuum_cleanup(Relation indexRelation,
GET_REL_PROCEDURE(amvacuumcleanup); GET_REL_PROCEDURE(amvacuumcleanup);
result = (IndexBulkDeleteResult *) result = (IndexBulkDeleteResult *)
DatumGetPointer(OidFunctionCall3(procedure, DatumGetPointer(FunctionCall3(procedure,
PointerGetDatum(indexRelation), PointerGetDatum(indexRelation),
PointerGetDatum((Pointer) info), PointerGetDatum((Pointer) info),
PointerGetDatum((Pointer) stats))); PointerGetDatum((Pointer) stats)));
...@@ -734,12 +731,12 @@ index_vacuum_cleanup(Relation indexRelation, ...@@ -734,12 +731,12 @@ index_vacuum_cleanup(Relation indexRelation,
RegProcedure RegProcedure
index_cost_estimator(Relation indexRelation) index_cost_estimator(Relation indexRelation)
{ {
RegProcedure procedure; FmgrInfo *procedure;
RELATION_CHECKS; RELATION_CHECKS;
GET_REL_PROCEDURE(amcostestimate); GET_REL_PROCEDURE(amcostestimate);
return procedure; return procedure->fn_oid;
} }
/* ---------------- /* ----------------
...@@ -785,9 +782,13 @@ index_getprocid(Relation irel, ...@@ -785,9 +782,13 @@ index_getprocid(Relation irel,
* *
* This routine allows index AMs to keep fmgr lookup info for * This routine allows index AMs to keep fmgr lookup info for
* support procs in the relcache. * support procs in the relcache.
*
* Note: the return value points into cached data that will be lost during
* any relcache rebuild! Therefore, either use the callinfo right away,
* or save it only after having acquired some type of lock on the index rel.
* ---------------- * ----------------
*/ */
struct FmgrInfo * FmgrInfo *
index_getprocinfo(Relation irel, index_getprocinfo(Relation irel,
AttrNumber attnum, AttrNumber attnum,
uint16 procnum) uint16 procnum)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.223 2005/05/11 01:26:02 neilc Exp $ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.224 2005/05/27 23:31:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -904,6 +904,9 @@ RelationInitIndexAccessInfo(Relation relation) ...@@ -904,6 +904,9 @@ RelationInitIndexAccessInfo(Relation relation)
/* /*
* Allocate arrays to hold data * Allocate arrays to hold data
*/ */
relation->rd_aminfo = (RelationAmInfo *)
MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
if (amstrategies > 0) if (amstrategies > 0)
operator = (Oid *) operator = (Oid *)
MemoryContextAllocZero(indexcxt, MemoryContextAllocZero(indexcxt,
...@@ -931,8 +934,8 @@ RelationInitIndexAccessInfo(Relation relation) ...@@ -931,8 +934,8 @@ RelationInitIndexAccessInfo(Relation relation)
relation->rd_supportinfo = supportinfo; relation->rd_supportinfo = supportinfo;
/* /*
* Fill the operator and support procedure OID arrays. (supportinfo is * Fill the operator and support procedure OID arrays. (aminfo and
* left as zeroes, and is filled on-the-fly when used) * supportinfo are left as zeroes, and are filled on-the-fly when used)
*/ */
IndexSupportInitialize(relation->rd_indclass, IndexSupportInitialize(relation->rd_indclass,
operator, support, operator, support,
...@@ -3015,7 +3018,9 @@ load_relcache_init_file(void) ...@@ -3015,7 +3018,9 @@ load_relcache_init_file(void)
rel->rd_support = support; rel->rd_support = support;
/* add a zeroed support-fmgr-info vector */ /* set up zeroed fmgr-info vectors */
rel->rd_aminfo = (RelationAmInfo *)
MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
nsupport = relform->relnatts * am->amsupport; nsupport = relform->relnatts * am->amsupport;
rel->rd_supportinfo = (FmgrInfo *) rel->rd_supportinfo = (FmgrInfo *)
MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo)); MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
...@@ -3031,6 +3036,7 @@ load_relcache_init_file(void) ...@@ -3031,6 +3036,7 @@ load_relcache_init_file(void)
Assert(rel->rd_indclass == NULL); Assert(rel->rd_indclass == NULL);
Assert(rel->rd_am == NULL); Assert(rel->rd_am == NULL);
Assert(rel->rd_indexcxt == NULL); Assert(rel->rd_indexcxt == NULL);
Assert(rel->rd_aminfo == NULL);
Assert(rel->rd_operator == NULL); Assert(rel->rd_operator == NULL);
Assert(rel->rd_support == NULL); Assert(rel->rd_support == NULL);
Assert(rel->rd_supportinfo == NULL); Assert(rel->rd_supportinfo == NULL);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.50 2005/04/14 20:03:27 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.51 2005/05/27 23:31:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -104,7 +104,7 @@ extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation, ...@@ -104,7 +104,7 @@ extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation,
extern RegProcedure index_cost_estimator(Relation indexRelation); extern RegProcedure index_cost_estimator(Relation indexRelation);
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum); uint16 procnum);
extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
uint16 procnum); uint16 procnum);
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.38 2005/03/27 23:53:04 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.39 2005/05/27 23:31:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,9 +40,8 @@ typedef HeapScanDescData *HeapScanDesc; ...@@ -40,9 +40,8 @@ typedef HeapScanDescData *HeapScanDesc;
/* /*
* We use the same IndexScanDescData structure for both amgettuple-based * We use the same IndexScanDescData structure for both amgettuple-based
* and amgetmulti-based index scans. Which one is being used can be told * and amgetmulti-based index scans. Some fields are only relevant in
* by looking at fn_getnext and fn_getmulti, only one of which will be * amgettuple-based scans.
* initialized. Some fields are only relevant in amgettuple-based scans.
*/ */
typedef struct IndexScanDescData typedef struct IndexScanDescData
{ {
...@@ -52,6 +51,7 @@ typedef struct IndexScanDescData ...@@ -52,6 +51,7 @@ typedef struct IndexScanDescData
Snapshot xs_snapshot; /* snapshot to see */ Snapshot xs_snapshot; /* snapshot to see */
int numberOfKeys; /* number of scan keys */ int numberOfKeys; /* number of scan keys */
ScanKey keyData; /* array of scan key descriptors */ ScanKey keyData; /* array of scan key descriptors */
bool is_multiscan; /* TRUE = using amgetmulti */
/* signaling to index AM about killing index tuples */ /* signaling to index AM about killing index tuples */
bool kill_prior_tuple; /* last-returned tuple is dead */ bool kill_prior_tuple; /* last-returned tuple is dead */
...@@ -75,9 +75,6 @@ typedef struct IndexScanDescData ...@@ -75,9 +75,6 @@ typedef struct IndexScanDescData
Buffer xs_cbuf; /* current heap buffer in scan, if any */ Buffer xs_cbuf; /* current heap buffer in scan, if any */
/* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */ /* 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 * If keys_are_unique and got_tuple are both true, we stop calling the
* index AM; it is then necessary for index_getnext to keep track of * index AM; it is then necessary for index_getnext to keep track of
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.83 2005/03/29 00:17:18 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.84 2005/05/27 23:31:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "catalog/pg_am.h" #include "catalog/pg_am.h"
#include "catalog/pg_class.h" #include "catalog/pg_class.h"
#include "catalog/pg_index.h" #include "catalog/pg_index.h"
#include "fmgr.h"
#include "rewrite/prs2lock.h" #include "rewrite/prs2lock.h"
#include "storage/block.h" #include "storage/block.h"
#include "storage/relfilenode.h" #include "storage/relfilenode.h"
...@@ -99,6 +100,27 @@ typedef struct PgStat_Info ...@@ -99,6 +100,27 @@ typedef struct PgStat_Info
} PgStat_Info; } PgStat_Info;
/*
* Cached lookup information for the index access method functions defined
* by the pg_am row associated with an index relation.
*/
typedef struct RelationAmInfo
{
FmgrInfo aminsert;
FmgrInfo ambeginscan;
FmgrInfo amgettuple;
FmgrInfo amgetmulti;
FmgrInfo amrescan;
FmgrInfo amendscan;
FmgrInfo ammarkpos;
FmgrInfo amrestrpos;
FmgrInfo ambuild;
FmgrInfo ambulkdelete;
FmgrInfo amvacuumcleanup;
FmgrInfo amcostestimate;
} RelationAmInfo;
/* /*
* Here are the contents of a relation cache entry. * Here are the contents of a relation cache entry.
*/ */
...@@ -150,11 +172,10 @@ typedef struct RelationData ...@@ -150,11 +172,10 @@ typedef struct RelationData
* that restriction. * that restriction.
*/ */
MemoryContext rd_indexcxt; /* private memory cxt for this stuff */ MemoryContext rd_indexcxt; /* private memory cxt for this stuff */
RelationAmInfo *rd_aminfo; /* lookup info for funcs found in pg_am */
Oid *rd_operator; /* OIDs of index operators */ Oid *rd_operator; /* OIDs of index operators */
RegProcedure *rd_support; /* OIDs of support procedures */ RegProcedure *rd_support; /* OIDs of support procedures */
struct FmgrInfo *rd_supportinfo; /* lookup info for support FmgrInfo *rd_supportinfo; /* lookup info for support procedures */
* procedures */
/* "struct FmgrInfo" avoids need to include fmgr.h here */
List *rd_indexprs; /* index expression trees, if any */ List *rd_indexprs; /* index expression trees, if any */
List *rd_indpred; /* index predicate tree, if any */ List *rd_indpred; /* index predicate tree, if any */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment