aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/index/genam.c7
-rw-r--r--src/backend/access/index/indexam.c149
-rw-r--r--src/backend/utils/cache/relcache.c14
-rw-r--r--src/include/access/genam.h4
-rw-r--r--src/include/access/relscan.h11
-rw-r--r--src/include/utils/rel.h29
6 files changed, 118 insertions, 96 deletions
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index d2504de2190..90e910f343f 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -8,7 +8,7 @@
*
*
* 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
* many of the old access method routines have been turned into
@@ -86,6 +86,7 @@ RelationGetIndexScan(Relation indexRelation,
else
scan->keyData = NULL;
+ scan->is_multiscan = false; /* caller may change this */
scan->kill_prior_tuple = false;
scan->ignore_killed_tuples = true; /* default setting */
scan->keys_are_unique = false; /* may be set by index AM */
@@ -101,10 +102,6 @@ RelationGetIndexScan(Relation indexRelation,
scan->xs_ctup.t_data = NULL;
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_mark = 0;
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 13b04a06b17..81c2114976e 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
*
*
* 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
* index_open - open an index relation by relation OID
@@ -27,6 +27,7 @@
* index_vacuum_cleanup - post-deletion cleanup of an index
* index_cost_estimator - fetch amcostestimate procedure OID
* index_getprocid - get a support procedure OID
+ * index_getprocinfo - get a support procedure's lookup info
*
* NOTES
* This file contains the index_ routines which used
@@ -87,20 +88,28 @@
)
#define GET_REL_PROCEDURE(pname) \
-( \
- procedure = indexRelation->rd_am->pname, \
- (!RegProcedureIsValid(procedure)) ? \
- elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
- : (void)NULL \
-)
+do { \
+ procedure = &indexRelation->rd_aminfo->pname; \
+ if (!OidIsValid(procedure->fn_oid)) \
+ { \
+ 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) \
-( \
- procedure = scan->indexRelation->rd_am->pname, \
- (!RegProcedureIsValid(procedure)) ? \
- elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
- : (void)NULL \
-)
+do { \
+ procedure = &scan->indexRelation->rd_aminfo->pname; \
+ if (!OidIsValid(procedure->fn_oid)) \
+ { \
+ 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,
int nkeys, ScanKey key);
@@ -196,7 +205,7 @@ index_insert(Relation indexRelation,
Relation heapRelation,
bool check_uniqueness)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
RELATION_CHECKS;
GET_REL_PROCEDURE(aminsert);
@@ -204,13 +213,13 @@ index_insert(Relation indexRelation,
/*
* have the am's insert proc do all the work.
*/
- return DatumGetBool(OidFunctionCall6(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum(values),
- PointerGetDatum(isnull),
- PointerGetDatum(heap_t_ctid),
- PointerGetDatum(heapRelation),
- BoolGetDatum(check_uniqueness)));
+ return DatumGetBool(FunctionCall6(procedure,
+ PointerGetDatum(indexRelation),
+ PointerGetDatum(values),
+ PointerGetDatum(isnull),
+ PointerGetDatum(heap_t_ctid),
+ PointerGetDatum(heapRelation),
+ BoolGetDatum(check_uniqueness)));
}
/*
@@ -229,7 +238,6 @@ index_beginscan(Relation heapRelation,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
- RegProcedure procedure;
scan = index_beginscan_internal(indexRelation, nkeys, key);
@@ -237,17 +245,10 @@ index_beginscan(Relation heapRelation,
* Save additional parameters into the scandesc. Everything else was
* set up by RelationGetIndexScan.
*/
+ scan->is_multiscan = false;
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;
}
@@ -263,7 +264,6 @@ index_beginscan_multi(Relation indexRelation,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
- RegProcedure procedure;
scan = index_beginscan_internal(indexRelation, nkeys, key);
@@ -271,16 +271,9 @@ index_beginscan_multi(Relation indexRelation,
* Save additional parameters into the scandesc. Everything else was
* set up by RelationGetIndexScan.
*/
+ scan->is_multiscan = true;
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;
}
@@ -292,7 +285,7 @@ index_beginscan_internal(Relation indexRelation,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
- RegProcedure procedure;
+ FmgrInfo *procedure;
RELATION_CHECKS;
GET_REL_PROCEDURE(ambeginscan);
@@ -312,10 +305,10 @@ index_beginscan_internal(Relation indexRelation,
* Tell the AM to open a scan.
*/
scan = (IndexScanDesc)
- DatumGetPointer(OidFunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- Int32GetDatum(nkeys),
- PointerGetDatum(key)));
+ DatumGetPointer(FunctionCall3(procedure,
+ PointerGetDatum(indexRelation),
+ Int32GetDatum(nkeys),
+ PointerGetDatum(key)));
return scan;
}
@@ -335,7 +328,7 @@ index_beginscan_internal(Relation indexRelation,
void
index_rescan(IndexScanDesc scan, ScanKey key)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
SCAN_CHECKS;
GET_SCAN_PROCEDURE(amrescan);
@@ -353,9 +346,9 @@ index_rescan(IndexScanDesc scan, ScanKey key)
scan->unique_tuple_pos = 0;
scan->unique_tuple_mark = 0;
- OidFunctionCall2(procedure,
- PointerGetDatum(scan),
- PointerGetDatum(key));
+ FunctionCall2(procedure,
+ PointerGetDatum(scan),
+ PointerGetDatum(key));
pgstat_reset_index_scan(&scan->xs_pgstat_info);
}
@@ -367,7 +360,7 @@ index_rescan(IndexScanDesc scan, ScanKey key)
void
index_endscan(IndexScanDesc scan)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
SCAN_CHECKS;
GET_SCAN_PROCEDURE(amendscan);
@@ -380,7 +373,7 @@ index_endscan(IndexScanDesc scan)
}
/* End the AM's scan */
- OidFunctionCall1(procedure, PointerGetDatum(scan));
+ FunctionCall1(procedure, PointerGetDatum(scan));
/* Release index lock and refcount acquired by index_beginscan */
@@ -399,14 +392,14 @@ index_endscan(IndexScanDesc scan)
void
index_markpos(IndexScanDesc scan)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
SCAN_CHECKS;
GET_SCAN_PROCEDURE(ammarkpos);
scan->unique_tuple_mark = scan->unique_tuple_pos;
- OidFunctionCall1(procedure, PointerGetDatum(scan));
+ FunctionCall1(procedure, PointerGetDatum(scan));
}
/* ----------------
@@ -420,7 +413,7 @@ index_markpos(IndexScanDesc scan)
void
index_restrpos(IndexScanDesc scan)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
SCAN_CHECKS;
GET_SCAN_PROCEDURE(amrestrpos);
@@ -434,7 +427,7 @@ index_restrpos(IndexScanDesc scan)
*/
scan->unique_tuple_pos = scan->unique_tuple_mark;
- OidFunctionCall1(procedure, PointerGetDatum(scan));
+ FunctionCall1(procedure, PointerGetDatum(scan));
}
/* ----------------
@@ -451,8 +444,10 @@ HeapTuple
index_getnext(IndexScanDesc scan, ScanDirection direction)
{
HeapTuple heapTuple = &scan->xs_ctup;
+ FmgrInfo *procedure;
SCAN_CHECKS;
+ GET_SCAN_PROCEDURE(amgettuple);
/*
* 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)
/*
* 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),
Int32GetDatum(direction)));
@@ -605,18 +600,19 @@ bool
index_getnext_indexitem(IndexScanDesc scan,
ScanDirection direction)
{
+ FmgrInfo *procedure;
bool found;
SCAN_CHECKS;
+ GET_SCAN_PROCEDURE(amgettuple);
/* just make sure this is false... */
scan->kill_prior_tuple = false;
/*
- * have the am's gettuple proc do all the work. index_beginscan
- * already set up fn_getnext.
+ * have the am's gettuple proc do all the work.
*/
- found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
+ found = DatumGetBool(FunctionCall2(procedure,
PointerGetDatum(scan),
Int32GetDatum(direction)));
@@ -641,18 +637,19 @@ index_getmulti(IndexScanDesc scan,
ItemPointer tids, int32 max_tids,
int32 *returned_tids)
{
+ FmgrInfo *procedure;
bool found;
SCAN_CHECKS;
+ GET_SCAN_PROCEDURE(amgetmulti);
/* 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.
+ * have the am's getmulti proc do all the work.
*/
- found = DatumGetBool(FunctionCall4(&scan->fn_getmulti,
+ found = DatumGetBool(FunctionCall4(procedure,
PointerGetDatum(scan),
PointerGetDatum(tids),
Int32GetDatum(max_tids),
@@ -675,17 +672,17 @@ index_bulk_delete(Relation indexRelation,
IndexBulkDeleteCallback callback,
void *callback_state)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
IndexBulkDeleteResult *result;
RELATION_CHECKS;
GET_REL_PROCEDURE(ambulkdelete);
result = (IndexBulkDeleteResult *)
- DatumGetPointer(OidFunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum((Pointer) callback),
- PointerGetDatum(callback_state)));
+ DatumGetPointer(FunctionCall3(procedure,
+ PointerGetDatum(indexRelation),
+ PointerGetDatum((Pointer) callback),
+ PointerGetDatum(callback_state)));
return result;
}
@@ -701,7 +698,7 @@ index_vacuum_cleanup(Relation indexRelation,
IndexVacuumCleanupInfo *info,
IndexBulkDeleteResult *stats)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
IndexBulkDeleteResult *result;
RELATION_CHECKS;
@@ -713,9 +710,9 @@ index_vacuum_cleanup(Relation indexRelation,
GET_REL_PROCEDURE(amvacuumcleanup);
result = (IndexBulkDeleteResult *)
- DatumGetPointer(OidFunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum((Pointer) info),
+ DatumGetPointer(FunctionCall3(procedure,
+ PointerGetDatum(indexRelation),
+ PointerGetDatum((Pointer) info),
PointerGetDatum((Pointer) stats)));
return result;
@@ -734,12 +731,12 @@ index_vacuum_cleanup(Relation indexRelation,
RegProcedure
index_cost_estimator(Relation indexRelation)
{
- RegProcedure procedure;
+ FmgrInfo *procedure;
RELATION_CHECKS;
GET_REL_PROCEDURE(amcostestimate);
- return procedure;
+ return procedure->fn_oid;
}
/* ----------------
@@ -785,9 +782,13 @@ index_getprocid(Relation irel,
*
* This routine allows index AMs to keep fmgr lookup info for
* 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,
AttrNumber attnum,
uint16 procnum)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index c4dc65f784a..3123eca518e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* 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)
/*
* Allocate arrays to hold data
*/
+ relation->rd_aminfo = (RelationAmInfo *)
+ MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
+
if (amstrategies > 0)
operator = (Oid *)
MemoryContextAllocZero(indexcxt,
@@ -931,8 +934,8 @@ RelationInitIndexAccessInfo(Relation relation)
relation->rd_supportinfo = supportinfo;
/*
- * Fill the operator and support procedure OID arrays. (supportinfo is
- * left as zeroes, and is filled on-the-fly when used)
+ * Fill the operator and support procedure OID arrays. (aminfo and
+ * supportinfo are left as zeroes, and are filled on-the-fly when used)
*/
IndexSupportInitialize(relation->rd_indclass,
operator, support,
@@ -3015,7 +3018,9 @@ load_relcache_init_file(void)
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;
rel->rd_supportinfo = (FmgrInfo *)
MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
@@ -3031,6 +3036,7 @@ load_relcache_init_file(void)
Assert(rel->rd_indclass == NULL);
Assert(rel->rd_am == NULL);
Assert(rel->rd_indexcxt == NULL);
+ Assert(rel->rd_aminfo == NULL);
Assert(rel->rd_operator == NULL);
Assert(rel->rd_support == NULL);
Assert(rel->rd_supportinfo == NULL);
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 422e107ec51..3ad0a3d4b2c 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.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/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,
extern RegProcedure index_cost_estimator(Relation indexRelation);
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum);
-extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
+extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
uint16 procnum);
/*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 1cb40445ea4..f84a84b6f7e 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.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/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;
/*
* 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.
+ * and amgetmulti-based index scans. Some fields are only relevant in
+ * amgettuple-based scans.
*/
typedef struct IndexScanDescData
{
@@ -52,6 +51,7 @@ typedef struct IndexScanDescData
Snapshot xs_snapshot; /* snapshot to see */
int numberOfKeys; /* number of scan keys */
ScanKey keyData; /* array of scan key descriptors */
+ bool is_multiscan; /* TRUE = using amgetmulti */
/* signaling to index AM about killing index tuples */
bool kill_prior_tuple; /* last-returned tuple is dead */
@@ -75,9 +75,6 @@ typedef struct IndexScanDescData
Buffer xs_cbuf; /* current heap buffer in scan, if any */
/* 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
* index AM; it is then necessary for index_getnext to keep track of
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index b6a1712efa7..e3f636b83d8 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.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/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 @@
#include "catalog/pg_am.h"
#include "catalog/pg_class.h"
#include "catalog/pg_index.h"
+#include "fmgr.h"
#include "rewrite/prs2lock.h"
#include "storage/block.h"
#include "storage/relfilenode.h"
@@ -100,6 +101,27 @@ typedef struct 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.
*/
@@ -150,11 +172,10 @@ typedef struct RelationData
* that restriction.
*/
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 */
RegProcedure *rd_support; /* OIDs of support procedures */
- struct FmgrInfo *rd_supportinfo; /* lookup info for support
- * procedures */
- /* "struct FmgrInfo" avoids need to include fmgr.h here */
+ FmgrInfo *rd_supportinfo; /* lookup info for support procedures */
List *rd_indexprs; /* index expression trees, if any */
List *rd_indpred; /* index predicate tree, if any */