PostgreSQL在何处处理 sql查询之三十八

这里又遇到了函数指针:

executor.h头文件中,定义了 ExecScanAccessMtd 指针,或者定义了一个ExecScanAccessMtd 函数原型的指针

/*
 * prototypes from functions in execScan.c
 */
typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);

之后,在NodeSeqScan.c处有一个实现:

/* ----------------------------------------------------------------
 *        SeqNext
 *
 *        This is a workhorse for ExecSeqScan
 * ----------------------------------------------------------------
 */
static TupleTableSlot *
SeqNext(SeqScanState *node)
{
    HeapTuple    tuple;
    HeapScanDesc scandesc;
    EState       *estate;
    ScanDirection direction;
    TupleTableSlot *slot;

    /*
     * get information from the estate and scan state
     */
    scandesc = node->ss_currentScanDesc;
    estate = node->ps.state;
    direction = estate->es_direction;
    slot = node->ss_ScanTupleSlot;

    /*
     * get the next tuple from the table
     */
    tuple = heap_getnext(scandesc, direction);

    /*
     * save the tuple and the buffer returned to us by the access methods in
     * our scan tuple slot and return the slot.  Note: we pass 'false' because
     * tuples returned by heap_getnext() are pointers onto disk pages and were
     * not created with palloc() and so should not be pfree()'d.  Note also
     * that ExecStoreTuple will increment the refcount of the buffer; the
     * refcount will not be dropped until the tuple table slot is cleared.
     */
    if (tuple)
        ExecStoreTuple(tuple,    /* tuple to store */
                       slot,    /* slot to store in */
                       scandesc->rs_cbuf,        /* buffer associated with this
                                                 * tuple */
                       false);    /* don't pfree this pointer */
    else
        ExecClearTuple(slot);

    return slot;
}

之后,在下列方法中, 把函数指针当作参数进行传递:

TupleTableSlot *
ExecScan(ScanState *node,
         ExecScanAccessMtd accessMtd,    /* function returning a tuple */
         ExecScanRecheckMtd recheckMtd)
{
   ...
}

调用:

TupleTableSlot *
ExecSeqScan(SeqScanState *node)
{
    return ExecScan((ScanState *) node,
                    (ExecScanAccessMtd) SeqNext,
                    (ExecScanRecheckMtd) SeqRecheck);
}
原文地址:https://www.cnblogs.com/gaojian/p/3110306.html