Postgres中有关GiST索引的某些调用流程
|||
提炼出的GiST调用流程方面的代码
1.请查看pdf附件
portal_run_printed.pdf
2.粉红色与蓝色线部分,为了实现特定的功能而扩展GiST的时候需要格外关注
ExecutePlan
{
/*Loop until we've processed the proper number of tuples from the plan*/
for(;;){
planSlot = ExecProcNode(planstate);
if(TupIsNull(planSlot)) return result = NULL;
slot = planSlot;
ExecSelect(slot, dest, estate);------>返回结果给dest,或伴随着Projection操作
current_tuple_count++;
if(numberTuples && numberTuples == current_tuple_count)
break;
}
}
ExecprocNode(PlanState *node) return TupleTableSlot*
{ return ExecIndexScan(
(IndexScanState*)node); }
ExecIndexScan(IndexScanState *node) return TupleTableSlot *
{ return ExecScan(
&node->ss,(ExecScanAccessMtd)IndexNext); }
ExecScan(ScanState *node, ExecScanAccessMtd* accessMtd) return TupleTableSlot*
{
for(;;)
{
TupleTableSlot * slot;
slot = (*accessMtd)(node);------>equal to slot = IndexNext(node);
if(TupIsNull(slot))
return projInfo ? ExecClearTuple(projInfo->pi_slot) : slot;
return projInfo ? resultSlot = ExecProject(projInfo, &isDone) : slot;
}
}
IndexNext(IndexScanState *node) return TupleTableSlot*
{
IndexScanDesc
scandesc = node->iss_ScanDesc;
HeapTuple tuple;
TupleTableSlot *
slot = node->ss.ss_ScanTupleSlot;
if((tuple = index_getnext(scandesc, direction) != NULL)
{
ExecStoreTuple(
tuple, slot, scandesc->xs_cbuf,false);
return slot;
}
}
index_getnext(IndexScanDesc scan, ScanDirection direction) return
HeapTuple
------>find return non-null or nomore tuple return null
{
HeapTuple
heapTuple = &scan->xs_ctup;------------------------------------------------------
FmgrInfo *procedure;
procedure = gistgettuple;
for(;;)
{
gistgettuple(scan, direction);
if(heap_release_fetch(
scan->heapRelation, scan->xs_snapshot,
heapTuple, &scan->xs_cbuf, true, &scan->xs_pgstat_info))
break;
if(heapTuple->t_data == NULL)
continue;
}
//Success exit
return
heapTuple;
//
return &scan->xs_ctup;---------------------------------------------------------------------
}
gistgettuple(IndexScandesc scan, ...) return bool ------>not gistgetmulti
{
ItemPointData tid;---------------------------->局部变量,基本无用
return gistnext(
scan,direction,
&tid, 1, ...);
}
gistnext(
IndexScanDesc scan,ScanDirection dir,
ItemPoint tids, int maxtids,...) return
int/bool
------>return true if and only if a matching tuple was found
{
OffsetNumber n;
int ntids = 0;
for(;;)
{
make a stack for the page tree seeking
and
ether
find a gist page stored in p variant.
of
return ntids = 0 , when the stack is empey
for(;;)
{
n = gistfindnext(scan, n, dir);
if(!OffsetNumberIsValid(n)) break;
if(GistPageIsLeaf(p))
{
IndexTuple it = (IndexTuple) PageGetItem(p,pageGetItemId(p,n));
tids[ntids++] = scan->xs_ctup.t_self = it->t_tid;------------------------------
------>tids在gistgettuple中没有使用,基本上依赖scan->xs_ctup,
并且是HeapTupleData中的一个字段,
我们可以充分利用其余字段的
if(ntids == maxtids) return ntids;
}//end of if
}//end of inner for
}//end of outer for
}//end of function
gistfindnext(
IndexScanDesc scan, OffsetNumber n, ScanDirection dir) return
OffsetNumber
------>在当前页面中,在偏移量n之后,返回第一个满足条件的偏移量
{
IndexTuple it;
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
Page p = BufferGetPage(
so->curbuf);
while( n >= FirstOffsetNumber && n <=maxoff)
{
it = (IndexTuple)PageGetItem(p, PageGetItem(p, n));
if(gistindex_keytest(it,scan,n)) break;
n = forward ? OffsetNumberNext(n) : OffsetNumberPre(n);
}//end of while
return (n >= FirstOffsetNumber && n<= maxoff) ? n: InvalidOffsetNumber;
}
gistindex_keytest(IndexTuple tuple, IndexScanDesc scan, OffsetNumber offset) return
bool
{
int keySize = scan->numberOfKeys;
ScanKey key = scan->keyData;
GISTScanOpaque so = (GISTScanOpaque)scan->opaque;
GISTSTATE *giststate = so->giststate;
page p = BufferGetPage(so->curbuf);
Relation r = scan->indexRelation;
while( keySize >0)
{
Datum datum;
GISTENTRY de
;-------------------->里面存储有HeapTuple的页面信息
可以考虑暂时存储在IndexScanDesc中去,
毕竟scan在多个函数中“穿越”
datum = index_getattr(tuple,key->sk_attno, giststate->tupdesc,...);
gistdentryinit(giststate, key->sk_attno - 1, &de, datum, r, p, offset, ...);
Datum test = gistconsistent(&de, key->sk_argument ,
key->sk_strategy,key->sk_subtype);
//Datum test = gistconsistent(&de, scan->keyData->sk_argument,
key->sk_strategy,key->sk_subtype);
keySize--;
key++;
}//end of while
}
http://blog.sciencenet.cn/home.php?mod=space&uid=643407&do=blog&id=517652