mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03: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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user