aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/index/indexam.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-03-27 23:53:05 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-03-27 23:53:05 +0000
commitbf3dbb5881e9b886ee9fe84bca2153c698eea885 (patch)
treeeaaf385364adebc2489c72f30e533f5fe60748ec /src/backend/access/index/indexam.c
parent351519affcffb636de68c4872521c9ac22faa228 (diff)
downloadpostgresql-bf3dbb5881e9b886ee9fe84bca2153c698eea885.tar.gz
postgresql-bf3dbb5881e9b886ee9fe84bca2153c698eea885.zip
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.
Diffstat (limited to 'src/backend/access/index/indexam.c')
-rw-r--r--src/backend/access/index/indexam.c166
1 files changed, 127 insertions, 39 deletions
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 6d7a874aac8..f6f4a065cfb 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -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
@@ -596,6 +646,44 @@ index_getnext_indexitem(IndexScanDesc scan,
}
/* ----------------
+ * 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
*
* callback routine tells whether a given main-heap tuple is
@@ -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;
}