src/backend/access/index/indexam.c 索引访问方法集合
- INTERFACE ROUTINES
-
index_open - open an index relation by relation OID
-
index_close - close an index relation
-
index_beginscan - start a scan of an index with amgettuple
-
index_beginscan_bitmap - start a scan of an index with amgetbitmap
-
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_parallelscan_estimate - estimate shared memory for parallel scan
-
index_parallelscan_initialize - initialize parallel scan
-
index_parallelrescan - (re)start a parallel scan of an index
-
index_beginscan_parallel - join parallel index scan
-
index_getnext_tid - get the next TID from a scan
-
index_fetch_heap - get the scan's next heap tuple
-
index_getnext_slot - get the next tuple from a scan
-
index_getbitmap - get all tuples from a scan
-
index_bulk_delete - bulk deletion of index tuples
-
index_vacuum_cleanup - post-deletion cleanup of an index
-
index_can_return - does index support index-only scans?
-
index_getprocid - get a support procedure OID
-
index_getprocinfo - get a support procedure's lookup info
index_open函数通过relation OID打开一个index relation,主要是通过调用relation.c中函数获取RelationData结构体,PostgreSQL数据库RelationAM——relation related routines。
Relation index_open(Oid relationId, LOCKMODE lockmode) {
Relation r;
r = relation_open(relationId, lockmode);
if (r->rd_rel->relkind != RELKIND_INDEX &&
r->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
ereport(ERROR,(errcode(ERRCODE_WRONG_OBJECT_TYPE),errmsg(""%s" is not an index",RelationGetRelationName(r))));
return r;
}
void index_close(Relation relation, LOCKMODE lockmode) {
LockRelId relid = relation->rd_lockInfo.lockRelId;
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
RelationClose(relation);
if (lockmode != NoLock) UnlockRelationId(&relid, lockmode);
}
index_insert函数想relation中插入一个Index元组
bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, IndexInfo *indexInfo) {
RELATION_CHECKS;
CHECK_REL_PROCEDURE(aminsert);
if (!(indexRelation->rd_indam->ampredlocks))
CheckForSerializableConflictIn(indexRelation, (HeapTuple) NULL, InvalidBuffer);
return indexRelation->rd_indam->aminsert(indexRelation, values, isnull, heap_t_ctid, heapRelation, checkUnique, indexInfo);
}
IndexAmRoutine
src/include/access/amapi.h
typedef struct IndexAmRoutine {
NodeTag type;
uint16 amstrategies;
uint16 amsupport;
bool amcanorder;
bool amcanorderbyop;
bool amcanbackward;
bool amcanunique;
bool amcanmulticol;
bool amoptionalkey;
bool amsearcharray;
bool amsearchnulls;
bool amstorage;
bool amclusterable;
bool ampredlocks;
bool amcanparallel;
bool amcaninclude;
Oid amkeytype;
ambuild_function ambuild;
ambuildempty_function ambuildempty;
aminsert_function aminsert;
ambulkdelete_function ambulkdelete;
amvacuumcleanup_function amvacuumcleanup;
amcanreturn_function amcanreturn;
amcostestimate_function amcostestimate;
amoptions_function amoptions;
amproperty_function amproperty;
ambuildphasename_function ambuildphasename;
amvalidate_function amvalidate;
ambeginscan_function ambeginscan;
amrescan_function amrescan;
amgettuple_function amgettuple;
amgetbitmap_function amgetbitmap;
amendscan_function amendscan;
ammarkpos_function ammarkpos;
amrestrpos_function amrestrpos;
amestimateparallelscan_function amestimateparallelscan;
aminitparallelscan_function aminitparallelscan;
amparallelrescan_function amparallelrescan;
} IndexAmRoutine;
src/backend/access/index/amapi.c
GetIndexAmRoutine函数调用指定的access method handler routine获取IndexAmRoutine结构体。
IndexAmRoutine *GetIndexAmRoutine(Oid amhandler) {
Datum datum;
IndexAmRoutine *routine;
datum = OidFunctionCall0(amhandler);
routine = (IndexAmRoutine *) DatumGetPointer(datum);
if (routine == NULL || !IsA(routine, IndexAmRoutine))
elog(ERROR, "index access method handler function %u did not return an IndexAmRoutine struct", amhandler);
return routine;
}
GetIndexAmRoutineByAmId函数通过OID查找索引访问方法handler并获取其IndexAmRoutine结构体。
IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror){
HeapTuple tuple;
Form_pg_am amform;
regproc amhandler;
tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid));
if (!HeapTupleIsValid(tuple)){
if (noerror)
return NULL;
elog(ERROR, "cache lookup failed for access method %u",amoid);
}
amform = (Form_pg_am) GETSTRUCT(tuple);
if (amform->amtype != AMTYPE_INDEX){
if (noerror){
ReleaseSysCache(tuple);
return NULL;
}
ereport(ERROR,(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),errmsg("access method "%s" is not of type %s",NameStr(amform->amname), "INDEX")));
}
amhandler = amform->amhandler;
if (!RegProcedureIsValid(amhandler)){
if (noerror){
ReleaseSysCache(tuple);
return NULL;
}
ereport(ERROR,(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),errmsg("index access method "%s" does not have a handler",NameStr(amform->amname))));
}
ReleaseSysCache(tuple);
return GetIndexAmRoutine(amhandler);
}



