Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

indexam.c File Reference

#include "postgres.h"
#include "access/relscan.h"
#include "access/transam.h"
#include "catalog/index.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
Include dependency graph for indexam.c:

Go to the source code of this file.

Defines

#define RELATION_CHECKS
#define SCAN_CHECKS
#define GET_REL_PROCEDURE(pname)
#define GET_UNCACHED_REL_PROCEDURE(pname)
#define GET_SCAN_PROCEDURE(pname)

Functions

static IndexScanDesc index_beginscan_internal (Relation indexRelation, int nkeys, int norderbys, Snapshot snapshot)
Relation index_open (Oid relationId, LOCKMODE lockmode)
void index_close (Relation relation, LOCKMODE lockmode)
bool index_insert (Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique)
IndexScanDesc index_beginscan (Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, int norderbys)
IndexScanDesc index_beginscan_bitmap (Relation indexRelation, Snapshot snapshot, int nkeys)
void index_rescan (IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
void index_endscan (IndexScanDesc scan)
void index_markpos (IndexScanDesc scan)
void index_restrpos (IndexScanDesc scan)
ItemPointer index_getnext_tid (IndexScanDesc scan, ScanDirection direction)
HeapTuple index_fetch_heap (IndexScanDesc scan)
HeapTuple index_getnext (IndexScanDesc scan, ScanDirection direction)
int64 index_getbitmap (IndexScanDesc scan, TIDBitmap *bitmap)
IndexBulkDeleteResultindex_bulk_delete (IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
IndexBulkDeleteResultindex_vacuum_cleanup (IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
bool index_can_return (Relation indexRelation)
RegProcedure index_getprocid (Relation irel, AttrNumber attnum, uint16 procnum)
FmgrInfoindex_getprocinfo (Relation irel, AttrNumber attnum, uint16 procnum)

Define Documentation

#define GET_REL_PROCEDURE (   pname  ) 
Value:
do { \
    procedure = &indexRelation->rd_aminfo->pname; \
    if (!OidIsValid(procedure->fn_oid)) \
    { \
        RegProcedure    procOid = indexRelation->rd_am->pname; \
        if (!RegProcedureIsValid(procOid)) \
            elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
        fmgr_info_cxt(procOid, procedure, indexRelation->rd_indexcxt); \
    } \
} while(0)

Definition at line 105 of file indexam.c.

Referenced by index_beginscan_internal(), index_can_return(), and index_insert().

#define GET_SCAN_PROCEDURE (   pname  ) 
Value:
do { \
    procedure = &scan->indexRelation->rd_aminfo->pname; \
    if (!OidIsValid(procedure->fn_oid)) \
    { \
        RegProcedure    procOid = scan->indexRelation->rd_am->pname; \
        if (!RegProcedureIsValid(procOid)) \
            elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
        fmgr_info_cxt(procOid, procedure, scan->indexRelation->rd_indexcxt); \
    } \
} while(0)

Definition at line 124 of file indexam.c.

Referenced by index_endscan(), index_getbitmap(), index_getnext_tid(), index_markpos(), index_rescan(), and index_restrpos().

#define GET_UNCACHED_REL_PROCEDURE (   pname  ) 
Value:
do { \
    if (!RegProcedureIsValid(indexRelation->rd_am->pname)) \
        elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
    fmgr_info(indexRelation->rd_am->pname, &procedure); \
} while(0)

Definition at line 117 of file indexam.c.

Referenced by index_bulk_delete(), and index_vacuum_cleanup().

#define RELATION_CHECKS
Value:
( \
    AssertMacro(RelationIsValid(indexRelation)), \
    AssertMacro(PointerIsValid(indexRelation->rd_am)), \
    AssertMacro(!ReindexIsProcessingIndex(RelationGetRelid(indexRelation))) \
)

Definition at line 91 of file indexam.c.

#define SCAN_CHECKS
Value:
( \
    AssertMacro(IndexScanIsValid(scan)), \
    AssertMacro(RelationIsValid(scan->indexRelation)), \
    AssertMacro(PointerIsValid(scan->indexRelation->rd_am)) \
)

Definition at line 98 of file indexam.c.


Function Documentation

IndexScanDesc index_beginscan ( Relation  heapRelation,
Relation  indexRelation,
Snapshot  snapshot,
int  nkeys,
int  norderbys 
)

Definition at line 238 of file indexam.c.

References IndexScanDescData::heapRelation, index_beginscan_internal(), and IndexScanDescData::xs_snapshot.

Referenced by check_exclusion_constraint(), copy_heap_data(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), get_actual_variable_range(), systable_beginscan(), and systable_beginscan_ordered().

{
    IndexScanDesc scan;

    scan = index_beginscan_internal(indexRelation, nkeys, norderbys, snapshot);

    /*
     * Save additional parameters into the scandesc.  Everything else was set
     * up by RelationGetIndexScan.
     */
    scan->heapRelation = heapRelation;
    scan->xs_snapshot = snapshot;

    return scan;
}

IndexScanDesc index_beginscan_bitmap ( Relation  indexRelation,
Snapshot  snapshot,
int  nkeys 
)

Definition at line 264 of file indexam.c.

References index_beginscan_internal(), and IndexScanDescData::xs_snapshot.

Referenced by ExecInitBitmapIndexScan().

{
    IndexScanDesc scan;

    scan = index_beginscan_internal(indexRelation, nkeys, 0, snapshot);

    /*
     * Save additional parameters into the scandesc.  Everything else was set
     * up by RelationGetIndexScan.
     */
    scan->xs_snapshot = snapshot;

    return scan;
}

static IndexScanDesc index_beginscan_internal ( Relation  indexRelation,
int  nkeys,
int  norderbys,
Snapshot  snapshot 
) [static]

Definition at line 285 of file indexam.c.

References DatumGetPointer, FunctionCall3, GET_REL_PROCEDURE, Int32GetDatum, PointerGetDatum, PredicateLockRelation(), RelationData::rd_am, and RelationIncrementReferenceCount().

Referenced by index_beginscan(), and index_beginscan_bitmap().

{
    IndexScanDesc scan;
    FmgrInfo   *procedure;

    RELATION_CHECKS;
    GET_REL_PROCEDURE(ambeginscan);

    if (!(indexRelation->rd_am->ampredlocks))
        PredicateLockRelation(indexRelation, snapshot);

    /*
     * We hold a reference count to the relcache entry throughout the scan.
     */
    RelationIncrementReferenceCount(indexRelation);

    /*
     * Tell the AM to open a scan.
     */
    scan = (IndexScanDesc)
        DatumGetPointer(FunctionCall3(procedure,
                                      PointerGetDatum(indexRelation),
                                      Int32GetDatum(nkeys),
                                      Int32GetDatum(norderbys)));

    return scan;
}

IndexBulkDeleteResult* index_bulk_delete ( IndexVacuumInfo info,
IndexBulkDeleteResult stats,
IndexBulkDeleteCallback  callback,
void *  callback_state 
)

Definition at line 675 of file indexam.c.

References DatumGetPointer, FunctionCall4, GET_UNCACHED_REL_PROCEDURE, IndexVacuumInfo::index, and PointerGetDatum.

Referenced by lazy_vacuum_index(), and validate_index().

{
    Relation    indexRelation = info->index;
    FmgrInfo    procedure;
    IndexBulkDeleteResult *result;

    RELATION_CHECKS;
    GET_UNCACHED_REL_PROCEDURE(ambulkdelete);

    result = (IndexBulkDeleteResult *)
        DatumGetPointer(FunctionCall4(&procedure,
                                      PointerGetDatum(info),
                                      PointerGetDatum(stats),
                                      PointerGetDatum((Pointer) callback),
                                      PointerGetDatum(callback_state)));

    return result;
}

bool index_can_return ( Relation  indexRelation  ) 

Definition at line 727 of file indexam.c.

References DatumGetBool, FunctionCall1, GET_REL_PROCEDURE, PointerGetDatum, RelationData::rd_am, and RegProcedureIsValid.

Referenced by get_relation_info().

{
    FmgrInfo   *procedure;

    RELATION_CHECKS;

    /* amcanreturn is optional; assume FALSE if not provided by AM */
    if (!RegProcedureIsValid(indexRelation->rd_am->amcanreturn))
        return false;

    GET_REL_PROCEDURE(amcanreturn);

    return DatumGetBool(FunctionCall1(procedure,
                                      PointerGetDatum(indexRelation)));
}

void index_close ( Relation  relation,
LOCKMODE  lockmode 
)
void index_endscan ( IndexScanDesc  scan  ) 

Definition at line 363 of file indexam.c.

References BufferIsValid, FunctionCall1, GET_SCAN_PROCEDURE, IndexScanDescData::indexRelation, IndexScanEnd(), PointerGetDatum, RelationDecrementReferenceCount(), ReleaseBuffer(), and IndexScanDescData::xs_cbuf.

Referenced by check_exclusion_constraint(), copy_heap_data(), ExecEndBitmapIndexScan(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), get_actual_variable_range(), systable_endscan(), and systable_endscan_ordered().

{
    FmgrInfo   *procedure;

    SCAN_CHECKS;
    GET_SCAN_PROCEDURE(amendscan);

    /* Release any held pin on a heap page */
    if (BufferIsValid(scan->xs_cbuf))
    {
        ReleaseBuffer(scan->xs_cbuf);
        scan->xs_cbuf = InvalidBuffer;
    }

    /* End the AM's scan */
    FunctionCall1(procedure, PointerGetDatum(scan));

    /* Release index refcount acquired by index_beginscan */
    RelationDecrementReferenceCount(scan->indexRelation);

    /* Release the scan data structure itself */
    IndexScanEnd(scan);
}

HeapTuple index_fetch_heap ( IndexScanDesc  scan  ) 

Definition at line 503 of file indexam.c.

References BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, heap_hot_search_buffer(), heap_page_prune_opt(), IndexScanDescData::heapRelation, IndexScanDescData::indexRelation, IsMVCCSnapshot, ItemPointerGetBlockNumber, IndexScanDescData::kill_prior_tuple, LockBuffer(), pgstat_count_heap_fetch, RecentGlobalXmin, ReleaseAndReadBuffer(), HeapTupleData::t_self, IndexScanDescData::xactStartedInRecovery, IndexScanDescData::xs_cbuf, IndexScanDescData::xs_continue_hot, IndexScanDescData::xs_ctup, and IndexScanDescData::xs_snapshot.

Referenced by index_getnext(), and IndexOnlyNext().

{
    ItemPointer tid = &scan->xs_ctup.t_self;
    bool        all_dead = false;
    bool        got_heap_tuple;

    /* We can skip the buffer-switching logic if we're in mid-HOT chain. */
    if (!scan->xs_continue_hot)
    {
        /* Switch to correct buffer if we don't have it already */
        Buffer      prev_buf = scan->xs_cbuf;

        scan->xs_cbuf = ReleaseAndReadBuffer(scan->xs_cbuf,
                                             scan->heapRelation,
                                             ItemPointerGetBlockNumber(tid));

        /*
         * Prune page, but only if we weren't already on this page
         */
        if (prev_buf != scan->xs_cbuf)
            heap_page_prune_opt(scan->heapRelation, scan->xs_cbuf,
                                RecentGlobalXmin);
    }

    /* Obtain share-lock on the buffer so we can examine visibility */
    LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
    got_heap_tuple = heap_hot_search_buffer(tid, scan->heapRelation,
                                            scan->xs_cbuf,
                                            scan->xs_snapshot,
                                            &scan->xs_ctup,
                                            &all_dead,
                                            !scan->xs_continue_hot);
    LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);

    if (got_heap_tuple)
    {
        /*
         * Only in a non-MVCC snapshot can more than one member of the HOT
         * chain be visible.
         */
        scan->xs_continue_hot = !IsMVCCSnapshot(scan->xs_snapshot);
        pgstat_count_heap_fetch(scan->indexRelation);
        return &scan->xs_ctup;
    }

    /* We've reached the end of the HOT chain. */
    scan->xs_continue_hot = false;

    /*
     * If we scanned a whole HOT chain and found only dead tuples, tell index
     * AM to kill its entry for that TID (this will take effect in the next
     * amgettuple call, in index_getnext_tid).  We do not do this when in
     * recovery because it may violate MVCC to do so.  See comments in
     * RelationGetIndexScan().
     */
    if (!scan->xactStartedInRecovery)
        scan->kill_prior_tuple = all_dead;

    return NULL;
}

int64 index_getbitmap ( IndexScanDesc  scan,
TIDBitmap bitmap 
)

Definition at line 634 of file indexam.c.

References DatumGetInt64, DatumGetPointer, FunctionCall2, GET_SCAN_PROCEDURE, IndexScanDescData::indexRelation, IndexScanDescData::kill_prior_tuple, pfree(), pgstat_count_index_tuples, and PointerGetDatum.

Referenced by MultiExecBitmapIndexScan().

{
    FmgrInfo   *procedure;
    int64       ntids;
    Datum       d;

    SCAN_CHECKS;
    GET_SCAN_PROCEDURE(amgetbitmap);

    /* just make sure this is false... */
    scan->kill_prior_tuple = false;

    /*
     * have the am's getbitmap proc do all the work.
     */
    d = FunctionCall2(procedure,
                      PointerGetDatum(scan),
                      PointerGetDatum(bitmap));

    ntids = DatumGetInt64(d);

    /* If int8 is pass-by-ref, must free the result to avoid memory leak */
#ifndef USE_FLOAT8_BYVAL
    pfree(DatumGetPointer(d));
#endif

    pgstat_count_index_tuples(scan->indexRelation, ntids);

    return ntids;
}

HeapTuple index_getnext ( IndexScanDesc  scan,
ScanDirection  direction 
)

Definition at line 580 of file indexam.c.

References Assert, BufferGetBlockNumber(), BufferIsValid, index_fetch_heap(), index_getnext_tid(), ItemPointerGetBlockNumber, NULL, HeapTupleData::t_self, IndexScanDescData::xs_cbuf, IndexScanDescData::xs_continue_hot, and IndexScanDescData::xs_ctup.

Referenced by check_exclusion_constraint(), copy_heap_data(), get_actual_variable_range(), IndexNext(), systable_getnext(), and systable_getnext_ordered().

{
    HeapTuple   heapTuple;
    ItemPointer tid;

    for (;;)
    {
        if (scan->xs_continue_hot)
        {
            /*
             * We are resuming scan of a HOT chain after having returned an
             * earlier member.  Must still hold pin on current heap page.
             */
            Assert(BufferIsValid(scan->xs_cbuf));
            Assert(ItemPointerGetBlockNumber(&scan->xs_ctup.t_self) ==
                   BufferGetBlockNumber(scan->xs_cbuf));
        }
        else
        {
            /* Time to fetch the next TID from the index */
            tid = index_getnext_tid(scan, direction);

            /* If we're out of index entries, we're done */
            if (tid == NULL)
                break;
        }

        /*
         * Fetch the next (or only) visible heap tuple for this index entry.
         * If we don't find anything, loop around and grab the next TID from
         * the index.
         */
        heapTuple = index_fetch_heap(scan);
        if (heapTuple != NULL)
            return heapTuple;
    }

    return NULL;                /* failure exit */
}

ItemPointer index_getnext_tid ( IndexScanDesc  scan,
ScanDirection  direction 
)

Definition at line 443 of file indexam.c.

References Assert, BufferIsValid, DatumGetBool, FunctionCall2, GET_SCAN_PROCEDURE, IndexScanDescData::indexRelation, Int32GetDatum, IndexScanDescData::kill_prior_tuple, pgstat_count_index_tuples, PointerGetDatum, RecentGlobalXmin, ReleaseBuffer(), HeapTupleData::t_self, TransactionIdIsValid, IndexScanDescData::xs_cbuf, and IndexScanDescData::xs_ctup.

Referenced by index_getnext(), and IndexOnlyNext().

{
    FmgrInfo   *procedure;
    bool        found;

    SCAN_CHECKS;
    GET_SCAN_PROCEDURE(amgettuple);

    Assert(TransactionIdIsValid(RecentGlobalXmin));

    /*
     * The AM's amgettuple proc finds the next index entry matching the scan
     * keys, and puts the TID into scan->xs_ctup.t_self.  It should also set
     * scan->xs_recheck and possibly scan->xs_itup, though we pay no attention
     * to those fields here.
     */
    found = DatumGetBool(FunctionCall2(procedure,
                                       PointerGetDatum(scan),
                                       Int32GetDatum(direction)));

    /* Reset kill flag immediately for safety */
    scan->kill_prior_tuple = false;

    /* If we're out of index entries, we're done */
    if (!found)
    {
        /* ... but first, release any held pin on a heap page */
        if (BufferIsValid(scan->xs_cbuf))
        {
            ReleaseBuffer(scan->xs_cbuf);
            scan->xs_cbuf = InvalidBuffer;
        }
        return NULL;
    }

    pgstat_count_index_tuples(scan->indexRelation, 1);

    /* Return the TID of the tuple we found. */
    return &scan->xs_ctup.t_self;
}

RegProcedure index_getprocid ( Relation  irel,
AttrNumber  attnum,
uint16  procnum 
)

Definition at line 770 of file indexam.c.

References Assert, NULL, RelationData::rd_am, and RelationData::rd_support.

Referenced by _hash_metapinit(), initGinState(), and initGISTstate().

{
    RegProcedure *loc;
    int         nproc;
    int         procindex;

    nproc = irel->rd_am->amsupport;

    Assert(procnum > 0 && procnum <= (uint16) nproc);

    procindex = (nproc * (attnum - 1)) + (procnum - 1);

    loc = irel->rd_support;

    Assert(loc != NULL);

    return loc[procindex];
}

FmgrInfo* index_getprocinfo ( Relation  irel,
AttrNumber  attnum,
uint16  procnum 
)

Definition at line 804 of file indexam.c.

References Assert, elog, ERROR, fmgr_info_cxt(), FmgrInfo::fn_oid, InvalidOid, NULL, RelationData::rd_am, RelationData::rd_indexcxt, RelationData::rd_support, RelationData::rd_supportinfo, RegProcedureIsValid, and RelationGetRelationName.

Referenced by _bt_first(), _bt_mkscankey(), _bt_mkscankey_nodata(), _hash_datum2hashkey(), doPickSplit(), initGinState(), initGISTstate(), spgdoinsert(), spgGetCache(), spgLeafTest(), and spgWalk().

{
    FmgrInfo   *locinfo;
    int         nproc;
    int         procindex;

    nproc = irel->rd_am->amsupport;

    Assert(procnum > 0 && procnum <= (uint16) nproc);

    procindex = (nproc * (attnum - 1)) + (procnum - 1);

    locinfo = irel->rd_supportinfo;

    Assert(locinfo != NULL);

    locinfo += procindex;

    /* Initialize the lookup info if first time through */
    if (locinfo->fn_oid == InvalidOid)
    {
        RegProcedure *loc = irel->rd_support;
        RegProcedure procId;

        Assert(loc != NULL);

        procId = loc[procindex];

        /*
         * Complain if function was not found during IndexSupportInitialize.
         * This should not happen unless the system tables contain bogus
         * entries for the index opclass.  (If an AM wants to allow a support
         * function to be optional, it can use index_getprocid.)
         */
        if (!RegProcedureIsValid(procId))
            elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
                 procnum, attnum, RelationGetRelationName(irel));

        fmgr_info_cxt(procId, locinfo, irel->rd_indexcxt);
    }

    return locinfo;
}

bool index_insert ( Relation  indexRelation,
Datum values,
bool isnull,
ItemPointer  heap_t_ctid,
Relation  heapRelation,
IndexUniqueCheck  checkUnique 
)

Definition at line 203 of file indexam.c.

References CheckForSerializableConflictIn(), DatumGetBool, FunctionCall6, GET_REL_PROCEDURE, Int32GetDatum, InvalidBuffer, NULL, PointerGetDatum, and RelationData::rd_am.

Referenced by CatalogIndexInsert(), ExecInsertIndexTuples(), toast_save_datum(), and validate_index_heapscan().

{
    FmgrInfo   *procedure;

    RELATION_CHECKS;
    GET_REL_PROCEDURE(aminsert);

    if (!(indexRelation->rd_am->ampredlocks))
        CheckForSerializableConflictIn(indexRelation,
                                       (HeapTuple) NULL,
                                       InvalidBuffer);

    /*
     * have the am's insert proc do all the work.
     */
    return DatumGetBool(FunctionCall6(procedure,
                                      PointerGetDatum(indexRelation),
                                      PointerGetDatum(values),
                                      PointerGetDatum(isnull),
                                      PointerGetDatum(heap_t_ctid),
                                      PointerGetDatum(heapRelation),
                                      Int32GetDatum((int32) checkUnique)));
}

void index_markpos ( IndexScanDesc  scan  ) 

Definition at line 392 of file indexam.c.

References FunctionCall1, GET_SCAN_PROCEDURE, and PointerGetDatum.

Referenced by ExecIndexMarkPos(), and ExecIndexOnlyMarkPos().

{
    FmgrInfo   *procedure;

    SCAN_CHECKS;
    GET_SCAN_PROCEDURE(ammarkpos);

    FunctionCall1(procedure, PointerGetDatum(scan));
}

Relation index_open ( Oid  relationId,
LOCKMODE  lockmode 
)
void index_rescan ( IndexScanDesc  scan,
ScanKey  keys,
int  nkeys,
ScanKey  orderbys,
int  norderbys 
)
void index_restrpos ( IndexScanDesc  scan  ) 
IndexBulkDeleteResult* index_vacuum_cleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)

Definition at line 704 of file indexam.c.

References DatumGetPointer, FunctionCall2, GET_UNCACHED_REL_PROCEDURE, IndexVacuumInfo::index, and PointerGetDatum.

Referenced by do_analyze_rel(), and lazy_cleanup_index().

{
    Relation    indexRelation = info->index;
    FmgrInfo    procedure;
    IndexBulkDeleteResult *result;

    RELATION_CHECKS;
    GET_UNCACHED_REL_PROCEDURE(amvacuumcleanup);

    result = (IndexBulkDeleteResult *)
        DatumGetPointer(FunctionCall2(&procedure,
                                      PointerGetDatum(info),
                                      PointerGetDatum(stats)));

    return result;
}