summaryrefslogtreecommitdiff
path: root/src/backend/access/index/indexam.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/index/indexam.c')
-rw-r--r--src/backend/access/index/indexam.c658
1 files changed, 0 insertions, 658 deletions
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
deleted file mode 100644
index fc53aeffb49..00000000000
--- a/src/backend/access/index/indexam.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * indexam.c
- * general index access method routines
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.61 2002/06/20 20:29:25 momjian 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_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_bulk_delete - bulk deletion of index tuples
- * index_cost_estimator - fetch amcostestimate procedure OID
- * index_getprocid - get a support procedure OID
- *
- * NOTES
- * This file contains the index_ routines which used
- * to be a scattered collection of stuff in access/genam.
- *
- *
- * old comments
- * Scans are implemented as follows:
- *
- * `0' represents an invalid item pointer.
- * `-' represents an unknown item pointer.
- * `X' represents a known item pointers.
- * `+' represents known or invalid item pointers.
- * `*' represents any item pointers.
- *
- * State is represented by a triple of these symbols in the order of
- * previous, current, next. Note that the case of reverse scans works
- * identically.
- *
- * State Result
- * (1) + + - + 0 0 (if the next item pointer is invalid)
- * (2) + X - (otherwise)
- * (3) * 0 0 * 0 0 (no change)
- * (4) + X 0 X 0 0 (shift)
- * (5) * + X + X - (shift, add unknown)
- *
- * All other states cannot occur.
- *
- * Note: It would be possible to cache the status of the previous and
- * next item pointer using the flags.
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "access/genam.h"
-#include "access/heapam.h"
-#include "utils/relcache.h"
-
-#include "pgstat.h"
-
-/* ----------------------------------------------------------------
- * macros used in index_ routines
- * ----------------------------------------------------------------
- */
-#define RELATION_CHECKS \
-( \
- AssertMacro(RelationIsValid(indexRelation)), \
- AssertMacro(PointerIsValid(indexRelation->rd_am)) \
-)
-
-#define SCAN_CHECKS \
-( \
- AssertMacro(IndexScanIsValid(scan)), \
- AssertMacro(RelationIsValid(scan->indexRelation)), \
- AssertMacro(PointerIsValid(scan->indexRelation->rd_am)) \
-)
-
-#define GET_REL_PROCEDURE(x,y) \
-( \
- procedure = indexRelation->rd_am->y, \
- (!RegProcedureIsValid(procedure)) ? \
- elog(ERROR, "index_%s: invalid %s regproc", \
- CppAsString(x), CppAsString(y)) \
- : (void)NULL \
-)
-
-#define GET_SCAN_PROCEDURE(x,y) \
-( \
- procedure = scan->indexRelation->rd_am->y, \
- (!RegProcedureIsValid(procedure)) ? \
- elog(ERROR, "index_%s: invalid %s regproc", \
- CppAsString(x), CppAsString(y)) \
- : (void)NULL \
-)
-
-
-/* ----------------------------------------------------------------
- * index_ interface functions
- * ----------------------------------------------------------------
- */
-
-/* ----------------
- * index_open - open an index relation by relation OID
- *
- * Note: we acquire no lock on the index. An AccessShareLock is
- * acquired by index_beginscan (and released by index_endscan).
- * Generally, the caller should already hold some type of lock on
- * the parent relation to ensure that the index doesn't disappear.
- *
- * This is a convenience routine adapted for indexscan use.
- * Some callers may prefer to use relation_open directly.
- * ----------------
- */
-Relation
-index_open(Oid relationId)
-{
- Relation r;
-
- r = relation_open(relationId, NoLock);
-
- if (r->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "%s is not an index relation",
- RelationGetRelationName(r));
-
- pgstat_initstats(&r->pgstat_info, r);
-
- return r;
-}
-
-/* ----------------
- * index_openrv - open an index relation specified
- * by a RangeVar node
- *
- * As above, but relation is specified by a RangeVar.
- * ----------------
- */
-Relation
-index_openrv(const RangeVar *relation)
-{
- Relation r;
-
- r = relation_openrv(relation, NoLock);
-
- if (r->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "%s is not an index relation",
- RelationGetRelationName(r));
-
- pgstat_initstats(&r->pgstat_info, r);
-
- return r;
-}
-
-/* ----------------
- * index_openr - open a system index relation specified by name.
- *
- * As above, but the relation is specified by an unqualified name;
- * it is assumed to live in the system catalog namespace.
- * ----------------
- */
-Relation
-index_openr(const char *sysRelationName)
-{
- Relation r;
-
- r = relation_openr(sysRelationName, NoLock);
-
- if (r->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "%s is not an index relation",
- RelationGetRelationName(r));
-
- pgstat_initstats(&r->pgstat_info, r);
-
- return r;
-}
-
-/* ----------------
- * index_close - close a index relation
- *
- * presently the relcache routines do all the work we need
- * to open/close index relations.
- * ----------------
- */
-void
-index_close(Relation relation)
-{
- RelationClose(relation);
-}
-
-/* ----------------
- * index_insert - insert an index tuple into a relation
- * ----------------
- */
-InsertIndexResult
-index_insert(Relation indexRelation,
- Datum *datums,
- char *nulls,
- ItemPointer heap_t_ctid,
- Relation heapRelation,
- bool check_uniqueness)
-{
- RegProcedure procedure;
- InsertIndexResult specificResult;
-
- RELATION_CHECKS;
- GET_REL_PROCEDURE(insert, aminsert);
-
- /*
- * have the am's insert proc do all the work.
- */
- specificResult = (InsertIndexResult)
- DatumGetPointer(OidFunctionCall6(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum(datums),
- PointerGetDatum(nulls),
- PointerGetDatum(heap_t_ctid),
- PointerGetDatum(heapRelation),
- BoolGetDatum(check_uniqueness)));
-
- /* must be pfree'ed */
- return specificResult;
-}
-
-/* ----------------
- * index_beginscan - start a scan of an index
- *
- * 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,
- Relation indexRelation,
- Snapshot snapshot,
- int nkeys, ScanKey key)
-{
- IndexScanDesc scan;
- RegProcedure procedure;
-
- RELATION_CHECKS;
- GET_REL_PROCEDURE(beginscan, ambeginscan);
-
- RelationIncrementReferenceCount(indexRelation);
-
- /*
- * Acquire AccessShareLock for the duration of the scan
- *
- * Note: we could get an SI inval message here and consequently have to
- * rebuild the relcache entry. The refcount increment above ensures
- * that we will rebuild it and not just flush it...
- */
- LockRelation(indexRelation, AccessShareLock);
-
- /*
- * Tell the AM to open a scan.
- */
- scan = (IndexScanDesc)
- DatumGetPointer(OidFunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- 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;
-}
-
-/* ----------------
- * index_rescan - (re)start a scan of an index
- *
- * The caller may specify a new set of scankeys (but the number of keys
- * cannot change). Note that this is also called when first starting
- * an indexscan; see RelationGetIndexScan.
- * ----------------
- */
-void
-index_rescan(IndexScanDesc scan, ScanKey key)
-{
- RegProcedure procedure;
-
- SCAN_CHECKS;
- GET_SCAN_PROCEDURE(rescan, amrescan);
-
- scan->kill_prior_tuple = false; /* for safety */
- scan->keys_are_unique = false; /* may be set by amrescan */
- scan->got_tuple = false;
-
- OidFunctionCall2(procedure,
- PointerGetDatum(scan),
- PointerGetDatum(key));
-
- pgstat_reset_index_scan(&scan->xs_pgstat_info);
-}
-
-/* ----------------
- * index_endscan - end a scan
- * ----------------
- */
-void
-index_endscan(IndexScanDesc scan)
-{
- RegProcedure procedure;
-
- SCAN_CHECKS;
- GET_SCAN_PROCEDURE(endscan, 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 */
- OidFunctionCall1(procedure, PointerGetDatum(scan));
-
- /* Release index lock and refcount acquired by index_beginscan */
-
- UnlockRelation(scan->indexRelation, AccessShareLock);
-
- RelationDecrementReferenceCount(scan->indexRelation);
-
- /* Release the scan data structure itself */
- IndexScanEnd(scan);
-}
-
-/* ----------------
- * index_markpos - mark a scan position
- * ----------------
- */
-void
-index_markpos(IndexScanDesc scan)
-{
- RegProcedure procedure;
-
- SCAN_CHECKS;
- GET_SCAN_PROCEDURE(markpos, ammarkpos);
-
- OidFunctionCall1(procedure, PointerGetDatum(scan));
-}
-
-/* ----------------
- * index_restrpos - restore a scan position
- * ----------------
- */
-void
-index_restrpos(IndexScanDesc scan)
-{
- RegProcedure procedure;
-
- SCAN_CHECKS;
- GET_SCAN_PROCEDURE(restrpos, amrestrpos);
-
- scan->kill_prior_tuple = false; /* for safety */
- scan->got_tuple = false;
-
- OidFunctionCall1(procedure, PointerGetDatum(scan));
-}
-
-/* ----------------
- * index_getnext - get the next heap tuple from a scan
- *
- * The result is the next heap tuple satisfying the scan keys and the
- * snapshot, or NULL if no more matching tuples exist. On success,
- * the buffer containing the heap tuple is pinned (the pin will be dropped
- * at the next index_getnext or index_endscan). The index TID corresponding
- * to the heap tuple can be obtained if needed from scan->currentItemData.
- * ----------------
- */
-HeapTuple
-index_getnext(IndexScanDesc scan, ScanDirection direction)
-{
- HeapTuple heapTuple = &scan->xs_ctup;
-
- SCAN_CHECKS;
-
- /* Release any previously held pin */
- if (BufferIsValid(scan->xs_cbuf))
- {
- ReleaseBuffer(scan->xs_cbuf);
- scan->xs_cbuf = InvalidBuffer;
- }
-
- /* just make sure this is false... */
- scan->kill_prior_tuple = false;
-
- /*
- * Can skip entering the index AM if we already got a tuple
- * and it must be unique.
- */
- if (scan->keys_are_unique && scan->got_tuple)
- return NULL;
-
- for (;;)
- {
- bool found;
- uint16 sv_infomask;
-
- pgstat_count_index_scan(&scan->xs_pgstat_info);
-
- /*
- * The AM's gettuple proc finds the next tuple matching the scan
- * keys. index_beginscan already set up fn_getnext.
- */
- found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
- PointerGetDatum(scan),
- Int32GetDatum(direction)));
-
- /* Reset kill flag immediately for safety */
- scan->kill_prior_tuple = false;
-
- if (!found)
- return NULL; /* failure exit */
-
- /*
- * Fetch the heap tuple and see if it matches the snapshot.
- */
- if (heap_fetch(scan->heapRelation, scan->xs_snapshot,
- heapTuple, &scan->xs_cbuf, true,
- &scan->xs_pgstat_info))
- break;
-
- /* Skip if no tuple at this location */
- if (heapTuple->t_data == NULL)
- continue; /* should we raise an error instead? */
-
- /*
- * If we can't see it, maybe no one else can either. Check to see
- * if the tuple is dead to all transactions. If so, signal the
- * index AM to not return it on future indexscans.
- *
- * We told heap_fetch to keep a pin on the buffer, so we can
- * re-access the tuple here. But we must re-lock the buffer first.
- * Also, it's just barely possible for an update of hint bits to
- * occur here.
- */
- LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
- sv_infomask = heapTuple->t_data->t_infomask;
-
- if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin) ==
- HEAPTUPLE_DEAD)
- scan->kill_prior_tuple = true;
-
- if (sv_infomask != heapTuple->t_data->t_infomask)
- SetBufferCommitInfoNeedsSave(scan->xs_cbuf);
- LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
- ReleaseBuffer(scan->xs_cbuf);
- scan->xs_cbuf = InvalidBuffer;
- }
-
- /* Success exit */
- scan->got_tuple = true;
-
- pgstat_count_index_getnext(&scan->xs_pgstat_info);
-
- return heapTuple;
-}
-
-/* ----------------
- * index_getnext_indexitem - get the next index tuple from a scan
- *
- * Finds the next index tuple satisfying the scan keys. Note that the
- * corresponding heap tuple is not accessed, and thus no time qual (snapshot)
- * check is done, other than the index AM's internal check for killed tuples
- * (which most callers of this routine will probably want to suppress by
- * setting scan->ignore_killed_tuples = false).
- *
- * On success (TRUE return), the found index TID is in scan->currentItemData,
- * and its heap TID is in scan->xs_ctup.t_self. scan->xs_cbuf is untouched.
- * ----------------
- */
-bool
-index_getnext_indexitem(IndexScanDesc scan,
- ScanDirection direction)
-{
- bool found;
-
- SCAN_CHECKS;
-
- /* just make sure this is false... */
- scan->kill_prior_tuple = false;
-
- /*
- * have the am's gettuple proc do all the work. index_beginscan
- * already set up fn_getnext.
- */
- found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
- PointerGetDatum(scan),
- Int32GetDatum(direction)));
-
- return found;
-}
-
-/* ----------------
- * index_bulk_delete - do mass deletion of index entries
- *
- * callback routine tells whether a given main-heap tuple is
- * to be deleted
- *
- * return value is an optional palloc'd struct of statistics
- * ----------------
- */
-IndexBulkDeleteResult *
-index_bulk_delete(Relation indexRelation,
- IndexBulkDeleteCallback callback,
- void *callback_state)
-{
- RegProcedure procedure;
- IndexBulkDeleteResult *result;
-
- RELATION_CHECKS;
- GET_REL_PROCEDURE(bulk_delete, ambulkdelete);
-
- result = (IndexBulkDeleteResult *)
- DatumGetPointer(OidFunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum((Pointer) callback),
- PointerGetDatum(callback_state)));
-
- return result;
-}
-
-/* ----------------
- * index_cost_estimator
- *
- * Fetch the amcostestimate procedure OID for an index.
- *
- * We could combine fetching and calling the procedure,
- * as index_insert does for example; but that would require
- * importing a bunch of planner/optimizer stuff into this file.
- * ----------------
- */
-RegProcedure
-index_cost_estimator(Relation indexRelation)
-{
- RegProcedure procedure;
-
- RELATION_CHECKS;
- GET_REL_PROCEDURE(cost_estimator, amcostestimate);
-
- return procedure;
-}
-
-/* ----------------
- * index_getprocid
- *
- * Some indexed access methods may require support routines that are
- * not in the operator class/operator model imposed by pg_am. These
- * access methods may store the OIDs of registered procedures they
- * need in pg_amproc. These registered procedure OIDs are ordered in
- * a way that makes sense to the access method, and used only by the
- * access method. The general index code doesn't know anything about
- * the routines involved; it just builds an ordered list of them for
- * each attribute on which an index is defined.
- *
- * This routine returns the requested procedure OID for a particular
- * indexed attribute.
- * ----------------
- */
-RegProcedure
-index_getprocid(Relation irel,
- AttrNumber attnum,
- uint16 procnum)
-{
- 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];
-}
-
-/* ----------------
- * index_getprocinfo
- *
- * This routine allows index AMs to keep fmgr lookup info for
- * support procs in the relcache.
- * ----------------
- */
-struct FmgrInfo *
-index_getprocinfo(Relation irel,
- AttrNumber attnum,
- uint16 procnum)
-{
- 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;
-}