head 1.11; access; symbols release_4_2:1.11 aix_ok:1.9 Version_2_1:1.4; locks; strict; comment @ * @; 1.11 date 94.02.07.11.30.01; author aoki; state Exp; branches; next 1.10; 1.10 date 93.11.03.08.24.31; author aoki; state Exp; branches; next 1.9; 1.9 date 92.11.19.23.58.20; author jolly; state Exp; branches; next 1.8; 1.8 date 92.03.06.00.17.12; author mer; state Exp; branches; next 1.7; 1.7 date 92.02.25.21.41.46; author mer; state Exp; branches; next 1.6; 1.6 date 91.05.01.02.49.24; author cimarron; state Exp; branches; next 1.5; 1.5 date 91.03.29.00.19.41; author mao; state Exp; branches; next 1.4; 1.4 date 91.02.27.16.03.31; author mao; state Exp; branches; next 1.3; 1.3 date 91.02.24.09.01.44; author mao; state Exp; branches; next 1.2; 1.2 date 91.02.06.18.03.36; author cimarron; state Exp; branches; next 1.1; 1.1 date 91.01.29.15.20.10; author cimarron; state Exp; branches; next ; desc @reorganization of access method code 1/28/91 -cim @ 1.11 log @proto fixes @ text @/* ---------------------------------------------------------------- * FILE * genam.c * * DESCRIPTION * general index access method routines * * INTERFACE ROUTINES * * NOTES * many of the old access method routines have been turned into * macros and moved to genam.h -cim 4/30/91 * * 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 "tmp/postgres.h" RcsId("$Header: /import/faerie/faerie/aoki/postgres/src/backend/access/index/RCS/genam.c,v 1.10 1993/11/03 08:24:31 aoki Exp aoki $"); #include "access/attnum.h" #include "access/genam.h" #include "access/heapam.h" #include "access/itup.h" #include "access/relscan.h" #include "access/sdir.h" #include "access/skey.h" #include "storage/form.h" #include "utils/log.h" #include "utils/palloc.h" #include "utils/rel.h" #include "catalog/catname.h" #include "catalog/pg_attribute.h" #include "catalog/pg_index.h" #include "catalog/pg_proc.h" #include "lib/index.h" /* ---------------------------------------------------------------- * general access method routines * * All indexed access methods use an identical scan structure. * We don't know how the various AMs do locking, however, so we don't * do anything about that here. * * The intent is that an AM implementor will define a front-end routine * that calls this one, to fill in the scan, and then does whatever kind * of locking he wants. * ---------------------------------------------------------------- */ /* ---------------- * RelationGetIndexScan -- Create and fill an IndexScanDesc. * * This routine creates an index scan structure and sets its contents * up correctly. This routine calls AMrescan to set up the scan with * the passed key. * * Parameters: * relation -- index relation for scan. * scanFromEnd -- if true, begin scan at one of the index's * endpoints. * numberOfKeys -- count of scan keys (more than one won't * necessarily do anything useful, yet). * key -- the ScanKey for the starting position of the scan. * * Returns: * An initialized IndexScanDesc. * * Side Effects: * Bumps the ref count on the relation to keep it in the cache. * * ---------------- */ IndexScanDesc RelationGetIndexScan(relation, scanFromEnd, numberOfKeys, key) Relation relation; Boolean scanFromEnd; uint16 numberOfKeys; ScanKey key; { IndexScanDesc scan; if (! RelationIsValid(relation)) elog(WARN, "RelationGetIndexScan: relation invalid"); scan = (IndexScanDesc) palloc(sizeof *scan + (numberOfKeys - 1) * sizeof key->data[0]); scan->relation = relation; scan->opaque = (Pointer) NULL; scan->numberOfKeys = numberOfKeys; ItemPointerSetInvalid(&scan->previousItemData); ItemPointerSetInvalid(&scan->currentItemData); ItemPointerSetInvalid(&scan->nextItemData); ItemPointerSetInvalid(&scan->previousMarkData); ItemPointerSetInvalid(&scan->currentMarkData); ItemPointerSetInvalid(&scan->nextMarkData); index_rescan(scan, scanFromEnd, key); return (scan); } /* ---------------- * IndexScanRestart -- Restart an index scan. * * This routine isn't used by any existing access method. It's * appropriate if relation level locks are what you want. * * Returns: * None. * * Side Effects: * None. * ---------------- */ void IndexScanRestart(scan, scanFromEnd, key) IndexScanDesc scan; bool scanFromEnd; ScanKey key; { if (! IndexScanIsValid(scan)) elog(WARN, "IndexScanRestart: invalid scan"); ItemPointerSetInvalid(&scan->previousItemData); ItemPointerSetInvalid(&scan->currentItemData); ItemPointerSetInvalid(&scan->nextItemData); if (RelationGetNumberOfBlocks(scan->relation) == 0) scan->flags = ScanUnmarked; else if (scanFromEnd) scan->flags = ScanUnmarked | ScanUncheckedPrevious; else scan->flags = ScanUnmarked | ScanUncheckedNext; scan->scanFromEnd = (Boolean) scanFromEnd; if (scan->numberOfKeys > 0) bcopy((Pointer)& key->data[0], (Pointer)& scan->keyData.data[0], scan->numberOfKeys * sizeof key->data[0]); } /* ---------------- * IndexScanEnd -- End and index scan. * * This routine is not used by any existing access method, but is * suitable for use if you don't want to do sophisticated locking. * * Returns: * None. * * Side Effects: * None. * ---------------- */ void IndexScanEnd(scan) IndexScanDesc scan; { if (! IndexScanIsValid(scan)) elog(WARN, "IndexScanEnd: invalid scan"); pfree((Pointer) scan); } /* ---------------- * IndexScanMarkPosition -- Mark current position in a scan. * * This routine isn't used by any existing access method, but is the * one that AM implementors should use, if they don't want to do any * special locking. If relation-level locking is sufficient, this is * the routine for you. * * Returns: * None. * * Side Effects: * None. * ---------------- */ void IndexScanMarkPosition(scan) IndexScanDesc scan; { RetrieveIndexResult result; if (scan->flags & ScanUncheckedPrevious) { result = (RetrieveIndexResult) index_getnext(scan, BackwardScanDirection); if (RetrieveIndexResultIsValid(result)) { scan->previousItemData = *RetrieveIndexResultGetIndexItemPointer(result); } else { ItemPointerSetInvalid(&scan->previousItemData); } } else if (scan->flags & ScanUncheckedNext) { result = (RetrieveIndexResult) index_getnext(scan, ForwardScanDirection); if (RetrieveIndexResultIsValid(result)) { scan->nextItemData = *RetrieveIndexResultGetIndexItemPointer(result); } else { ItemPointerSetInvalid(&scan->nextItemData); } } scan->previousMarkData = scan->previousItemData; scan->currentMarkData = scan->currentItemData; scan->nextMarkData = scan->nextItemData; scan->flags = 0x0; /* XXX should have a symbolic name */ } /* ---------------- * IndexScanRestorePosition -- Restore position on a marked scan. * * This routine isn't used by any existing access method, but is the * one that AM implementors should use if they don't want to do any * special locking. If relation-level locking is sufficient, then * this is the one you want. * * Returns: * None. * * Side Effects: * None. * ---------------- */ void IndexScanRestorePosition(scan) IndexScanDesc scan; { RetrieveIndexResult result; if (scan->flags & ScanUnmarked) elog(WARN, "IndexScanRestorePosition: no mark to restore"); scan->previousItemData = scan->previousMarkData; scan->currentItemData = scan->currentMarkData; scan->nextItemData = scan->nextMarkData; scan->flags = 0x0; /* XXX should have a symbolic name */ } /* ---------------- * IndexScanGetRetrieveIndexResult * * Return a RetrieveIndexResult for the next tuple in the index scan. * A RetrieveIndexResult (see itup.h) is a index tuple/heap tuple pair. * This routine is used primarily by the vacuum daemon, so that it can * delete index tuples associated with zapped heap tuples. * * Parameters: * scan -- Index scan to use. * direction -- Forward, backward, or no movement. * * Returns: * RetrieveIndexResult for the tuple in the scan that's next * in the specified direction. * * Side Effects: None. * ---------------- */ RetrieveIndexResult IndexScanGetRetrieveIndexResult(scan, direction) IndexScanDesc scan; ScanDirection direction; { return (RetrieveIndexResult) index_getnext(scan, direction); } /* ---------------- * IndexScanGetGeneralRetrieveIndexResult * * A GeneralRetrieveIndexResult (see itup.h) is a index tuple * rule lock pair. But currently we don't support index rule * lock results so this routine is pretty bogus. * ---------------- */ GeneralRetrieveIndexResult IndexScanGetGeneralRetrieveIndexResult(scan, direction) IndexScanDesc scan; ScanDirection direction; { RetrieveIndexResult result; ItemPointer heapItemPointer; GeneralRetrieveIndexResult generalResult; /* ---------------- * use index_getnext to get the "RetrieveIndexResult" * ---------------- */ result = (RetrieveIndexResult) index_getnext(scan, direction); if (! RetrieveIndexResultIsValid(result)) return (GeneralRetrieveIndexResult) NULL; /* ---------------- * silly crap to convert a "RetrieveIndexResult" to a * "GeneralRetrieveIndexResult". * ---------------- */ heapItemPointer = RetrieveIndexResultGetHeapItemPointer(result); generalResult = (GeneralRetrieveIndexResult) palloc(sizeof *result); generalResult->heapItemData = *heapItemPointer; pfree(result); return generalResult; } @ 1.10 log @fix broken prs2 protos remove rules/rlock.h, access/xcxt.h, access/newam.h (dead headers with residual dependencies) @ text @d44 1 a44 1 RcsId("$Header: /faerie/aoki/postgres/src/backend/access/index/RCS/genam.c,v 1.9 1992/11/19 23:58:20 jolly Exp aoki $"); d56 1 @ 1.9 log @*** empty log message *** @ text @d44 2 a49 1 #include "access/newam.h" d63 1 a63 1 RcsId("$Header: /usr/local/devel/postgres/src/backend/access/index/RCS/genam.c,v 1.8 1992/03/06 00:17:12 mer Exp jolly $"); @ 1.8 log @don't play with reldesc refcnts (they must be accurate now) @ text @d37 1 a37 1 * It would be possible to cache the status of the previous and d62 1 a62 1 RcsId("$Header: /users/mer/pg/src/access/index/RCS/genam.c,v 1.7 1992/02/25 21:41:46 mer Exp mer $"); @ 1.7 log @free storage *after* we're done reading it, not before (purify) @ text @d62 1 a62 1 RcsId("$Header: /users/mer/pg/src/access/index/RCS/genam.c,v 1.6 1991/05/01 02:49:24 cimarron Exp mer $"); a111 2 RelationIncrementReferenceCount(relation); a192 1 RelationDecrementReferenceCount(scan->relation); @ 1.6 log @round II of converting simple functions to macros + code cleaning in general @ text @d62 1 a62 1 RcsId("$Header: RCS/genam.c,v 1.5 91/03/29 00:19:41 mao Exp Locker: cimarron $"); a340 1 pfree(result); d345 1 @ 1.5 log @plug another memory leak @ text @d11 2 d62 1 a62 1 RcsId("$Header: RCS/genam.c,v 1.4 91/02/27 16:03:31 mao Exp Locker: mao $"); a346 219 } /* ---------------------------------------------------------------- * old interface routines - see access/index/indexam.c for * new index_ interface functions. * ---------------------------------------------------------------- */ /* ---------------- * old create / destroy interface * * Note: index_create and index_destroy are in lib/catalog/index.c * ---------------- */ void DestroyIndexRelationById(indexId) ObjectId indexId; { index_destroy(indexId); } void AMdestroy(indexId) ObjectId indexId; { index_destroy(indexId); } /* ---------------- * old open / close interface * * Note: index_open, index_openr, and index_close are all * in access/index/indexam.c * ---------------- */ Relation ObjectIdOpenIndexRelation(relationObjectId) ObjectId relationObjectId; { return (Relation) index_open(relationObjectId); } Relation AMopen(relationObjectId) ObjectId relationObjectId; { return (Relation) index_open(relationObjectId); } Relation AMopenr(relationName) Name relationName; { return (Relation) index_openr(relationName); } void RelationCloseIndexRelation(relation) Relation relation; { (void) index_close(relation); } void AMclose(relation) Relation relation; { (void) index_close(relation); } /* ---------------- * old insert / delete routines * ---------------- */ GeneralInsertIndexResult RelationInsertIndexTuple(relation, indexTuple, scan, offsetOutP) Relation relation; IndexTuple indexTuple; char *scan; double *offsetOutP; { return (GeneralInsertIndexResult) index_insert(relation, indexTuple, offsetOutP); } GeneralInsertIndexResult AMinsert(relation, indexTuple, scan, offsetOutP) Relation relation; IndexTuple indexTuple; char *scan; double *offsetOutP; { return (GeneralInsertIndexResult) index_insert(relation, indexTuple, offsetOutP); } void RelationDeleteIndexTuple(relation, indexItem) Relation relation; ItemPointer indexItem; { (void) index_delete(relation, indexItem); } void AMdelete(relation, indexItem) Relation relation; ItemPointer indexItem; { (void) index_delete(relation, indexItem); } /* ---------------- * old index scan support * ---------------- */ IndexScanDesc AMbeginscan(relation, scanFromEnd, numberOfKeys, key) Relation relation; Boolean scanFromEnd; uint16 numberOfKeys; ScanKey key; { return (IndexScanDesc) index_beginscan(relation, scanFromEnd, numberOfKeys, key); } void AMrescan(scan, scanFromEnd, key) IndexScanDesc scan; bool scanFromEnd; ScanKey key; { (void) index_rescan(scan, scanFromEnd, key); } void AMendscan(scan) IndexScanDesc scan; { (void) index_endscan(scan); } void AMmarkpos(scan) IndexScanDesc scan; { (void) index_markpos(scan); } void AMrestrpos(scan) IndexScanDesc scan; { (void) index_restrpos(scan); } GeneralRetrieveIndexResult AMgettuple(scan, direction) IndexScanDesc scan; /* the scan on the index reln */ ScanDirection direction; /* -1 back, 0 no move, 1 fwd */ { return (GeneralRetrieveIndexResult) IndexScanGetGeneralRetrieveIndexResult(scan, direction); } /* ---------------------------------------------------------------- * unimplemented crap * ---------------------------------------------------------------- */ void RelationSetIndexRuleLock(relation, indexItem, lock) Relation relation; ItemPointer indexItem; RuleLock lock; { elog(DEBUG, "RelationSetIndexRuleLock; unimplemented"); } void AMsetlock(relation, indexItem, lock) Relation relation; ItemPointer indexItem; RuleLock lock; { elog(DEBUG, "AMsetlock; unimplemented"); } void RelationSetIndexItemPointer(relation, indexItem, heapItem) Relation relation; ItemPointer indexItem; ItemPointer heapItem; { elog(DEBUG, "RelationSetIndexItemPointer: unimplemented"); } void AMsettid(relation, indexItem, heapItem) Relation relation; ItemPointer indexItem; ItemPointer heapItem; { elog(DEBUG, "AMsettid: unimplemented"); } extern IndexTupleFree() { elog(DEBUG, "IndexTupleFree: unimplemented"); } extern AMfreetuple() { elog(DEBUG, "AMfreetuple: unimplemented"); @ 1.4 log @pass parameters on from AMbeginscan @ text @d60 1 a60 1 RcsId("$Header: RCS/genam.c,v 1.3 91/02/24 09:01:44 mao Exp Locker: mao $"); d323 1 a323 1 d328 1 a328 2 result = (RetrieveIndexResult) index_getnext(scan, direction); d339 1 a339 3 generalResult = (GeneralRetrieveIndexResult) palloc(sizeof *result); d341 1 d343 1 a343 1 @ 1.3 log @index scan descriptors now have an opaque entry for use by the access method. @ text @d60 1 a60 1 RcsId("$Header: RCS/genam.c,v 1.2 91/02/06 18:03:36 cimarron Exp Locker: mao $"); d473 1 a473 1 index_beginscan(); @ 1.2 log @removed reference to AMrescan @ text @d60 1 a60 1 RcsId("$Header: RCS/genam.c,v 1.1 91/01/29 15:20:10 cimarron Exp Locker: cimarron $"); d116 1 @ 1.1 log @Initial revision @ text @d60 1 a60 1 #include "internal.h" a61 2 RcsId("$Header: RCS/genam.c,v 1.16 90/09/25 17:16:05 kemnitz Exp Locker: cimarron $"); d125 1 a125 1 AMrescan(scan, scanFromEnd, key); @