1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* indexam.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* general index access method routines
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2001-01-24 20:43:33 +01:00
|
|
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2001-01-24 20:43:33 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.47 2001/01/24 19:42:48 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* INTERFACE ROUTINES
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_open - open an index relation by relationId
|
|
|
|
* index_openr - open a index relation by name
|
|
|
|
* index_close - close a 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_delete - delete an item from an index relation
|
|
|
|
* index_markpos - mark a scan position
|
|
|
|
* index_restrpos - restore a scan position
|
|
|
|
* index_getnext - get the next tuple from a scan
|
|
|
|
* ** index_fetch - retrieve tuple with tid
|
1996-07-09 08:22:35 +02:00
|
|
|
* ** index_replace - replace a tuple
|
|
|
|
* ** index_getattr - get an attribute from an index tuple
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_getprocid - get a support procedure id from the rel tuple
|
|
|
|
*
|
|
|
|
* IndexScanIsValid - check index scan
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* This file contains the index_ routines which used
|
|
|
|
* to be a scattered collection of stuff in access/genam.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* The ** routines: index_fetch, index_replace, and index_getattr
|
|
|
|
* have not yet been implemented. They may not be needed.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* old comments
|
1997-09-07 07:04:48 +02:00
|
|
|
* Scans are implemented as follows:
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* `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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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)
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* All other states cannot occur.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Note: It would be possible to cache the status of the previous and
|
|
|
|
* next item pointer using the flags.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "postgres.h"
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "access/genam.h"
|
|
|
|
#include "access/heapam.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "utils/relcache.h"
|
1996-10-21 09:38:20 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* macros used in index_ routines
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#define RELATION_CHECKS \
|
1998-06-15 20:40:05 +02:00
|
|
|
( \
|
|
|
|
AssertMacro(RelationIsValid(relation)), \
|
|
|
|
AssertMacro(PointerIsValid(relation->rd_am)) \
|
|
|
|
)
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#define SCAN_CHECKS \
|
1998-06-15 20:40:05 +02:00
|
|
|
( \
|
|
|
|
AssertMacro(IndexScanIsValid(scan)), \
|
|
|
|
AssertMacro(RelationIsValid(scan->relation)), \
|
|
|
|
AssertMacro(PointerIsValid(scan->relation->rd_am)) \
|
|
|
|
)
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#define GET_REL_PROCEDURE(x,y) \
|
1998-06-15 20:40:05 +02:00
|
|
|
( \
|
|
|
|
procedure = relation->rd_am->y, \
|
|
|
|
(!RegProcedureIsValid(procedure)) ? \
|
|
|
|
elog(ERROR, "index_%s: invalid %s regproc", \
|
|
|
|
CppAsString(x), CppAsString(y)) \
|
|
|
|
: (void)NULL \
|
|
|
|
)
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#define GET_SCAN_PROCEDURE(x,y) \
|
1998-06-15 20:40:05 +02:00
|
|
|
( \
|
|
|
|
procedure = scan->relation->rd_am->y, \
|
|
|
|
(!RegProcedureIsValid(procedure)) ? \
|
|
|
|
elog(ERROR, "index_%s: invalid %s regproc", \
|
|
|
|
CppAsString(x), CppAsString(y)) \
|
|
|
|
: (void)NULL \
|
|
|
|
)
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_ interface functions
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_open - open an index relation by relationId
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* presently the relcache routines do all the work we need
|
2000-04-12 19:17:23 +02:00
|
|
|
* to open/close index relations. However, callers of index_open
|
1999-09-18 21:08:25 +02:00
|
|
|
* expect it to succeed, so we need to check for a failure return.
|
|
|
|
*
|
2000-04-12 19:17:23 +02:00
|
|
|
* Note: we acquire no lock on the index. An AccessShareLock is
|
1999-09-18 21:08:25 +02:00
|
|
|
* acquired by index_beginscan (and released by index_endscan).
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
Relation
|
|
|
|
index_open(Oid relationId)
|
|
|
|
{
|
1999-09-18 21:08:25 +02:00
|
|
|
Relation r;
|
|
|
|
|
|
|
|
r = RelationIdGetRelation(relationId);
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!RelationIsValid(r))
|
1999-09-18 21:08:25 +02:00
|
|
|
elog(ERROR, "Index %u does not exist", relationId);
|
|
|
|
|
|
|
|
if (r->rd_rel->relkind != RELKIND_INDEX)
|
1999-11-08 00:08:36 +01:00
|
|
|
elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
|
1999-09-18 21:08:25 +02:00
|
|
|
|
|
|
|
return r;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_openr - open a index relation by name
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-09-18 21:08:25 +02:00
|
|
|
* As above, but lookup by name instead of OID.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
Relation
|
|
|
|
index_openr(char *relationName)
|
|
|
|
{
|
1999-09-18 21:08:25 +02:00
|
|
|
Relation r;
|
|
|
|
|
|
|
|
r = RelationNameGetRelation(relationName);
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!RelationIsValid(r))
|
1999-09-18 21:08:25 +02:00
|
|
|
elog(ERROR, "Index '%s' does not exist", relationName);
|
|
|
|
|
|
|
|
if (r->rd_rel->relkind != RELKIND_INDEX)
|
1999-11-08 00:08:36 +01:00
|
|
|
elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
|
1999-09-18 21:08:25 +02:00
|
|
|
|
|
|
|
return r;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_close - close a index relation
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* presently the relcache routines do all the work we need
|
|
|
|
* to open/close index relations.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_close(Relation relation)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
RelationClose(relation);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_insert - insert an index tuple into a relation
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
InsertIndexResult
|
|
|
|
index_insert(Relation relation,
|
1997-09-08 23:56:23 +02:00
|
|
|
Datum *datum,
|
1997-09-07 07:04:48 +02:00
|
|
|
char *nulls,
|
|
|
|
ItemPointer heap_t_ctid,
|
|
|
|
Relation heapRel)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
InsertIndexResult specificResult;
|
|
|
|
|
|
|
|
RELATION_CHECKS;
|
|
|
|
GET_REL_PROCEDURE(insert, aminsert);
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* have the am's insert proc do all the work.
|
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
specificResult = (InsertIndexResult)
|
2000-06-13 09:35:40 +02:00
|
|
|
DatumGetPointer(OidFunctionCall5(procedure,
|
2000-05-30 06:25:00 +02:00
|
|
|
PointerGetDatum(relation),
|
|
|
|
PointerGetDatum(datum),
|
|
|
|
PointerGetDatum(nulls),
|
|
|
|
PointerGetDatum(heap_t_ctid),
|
2000-06-13 09:35:40 +02:00
|
|
|
PointerGetDatum(heapRel)));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-09-03 01:05:37 +02:00
|
|
|
/* must be pfree'ed */
|
1998-09-01 05:29:17 +02:00
|
|
|
return specificResult;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_delete - delete an item from an index relation
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_delete(Relation relation, ItemPointer indexItem)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
RELATION_CHECKS;
|
|
|
|
GET_REL_PROCEDURE(delete, amdelete);
|
|
|
|
|
2000-05-30 06:25:00 +02:00
|
|
|
OidFunctionCall2(procedure,
|
|
|
|
PointerGetDatum(relation),
|
|
|
|
PointerGetDatum(indexItem));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_beginscan - start a scan of an index
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
IndexScanDesc
|
|
|
|
index_beginscan(Relation relation,
|
1997-09-07 07:04:48 +02:00
|
|
|
bool scanFromEnd,
|
|
|
|
uint16 numberOfKeys,
|
|
|
|
ScanKey key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
IndexScanDesc scandesc;
|
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
RELATION_CHECKS;
|
|
|
|
GET_REL_PROCEDURE(beginscan, ambeginscan);
|
|
|
|
|
1999-09-18 21:08:25 +02:00
|
|
|
RelationIncrementReferenceCount(relation);
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* Acquire AccessShareLock for the duration of the scan
|
|
|
|
*
|
|
|
|
* Note: we could get an SI inval message here and consequently have
|
2000-04-12 19:17:23 +02:00
|
|
|
* to rebuild the relcache entry. The refcount increment above
|
1999-09-18 21:08:25 +02:00
|
|
|
* ensures that we will rebuild it and not just flush it...
|
|
|
|
* ----------------
|
|
|
|
*/
|
1998-12-15 13:47:01 +01:00
|
|
|
LockRelation(relation, AccessShareLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
scandesc = (IndexScanDesc)
|
2000-05-30 06:25:00 +02:00
|
|
|
DatumGetPointer(OidFunctionCall4(procedure,
|
|
|
|
PointerGetDatum(relation),
|
|
|
|
BoolGetDatum(scanFromEnd),
|
|
|
|
UInt16GetDatum(numberOfKeys),
|
|
|
|
PointerGetDatum(key)));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
return scandesc;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_rescan - restart a scan of an index
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
SCAN_CHECKS;
|
|
|
|
GET_SCAN_PROCEDURE(rescan, amrescan);
|
|
|
|
|
2000-05-30 06:25:00 +02:00
|
|
|
OidFunctionCall3(procedure,
|
|
|
|
PointerGetDatum(scan),
|
|
|
|
BoolGetDatum(scanFromEnd),
|
|
|
|
PointerGetDatum(key));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_endscan - end a scan
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_endscan(IndexScanDesc scan)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
SCAN_CHECKS;
|
|
|
|
GET_SCAN_PROCEDURE(endscan, amendscan);
|
|
|
|
|
2000-05-30 06:25:00 +02:00
|
|
|
OidFunctionCall1(procedure, PointerGetDatum(scan));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-09-18 21:08:25 +02:00
|
|
|
/* Release lock and refcount acquired by index_beginscan */
|
|
|
|
|
1998-12-15 13:47:01 +01:00
|
|
|
UnlockRelation(scan->relation, AccessShareLock);
|
1999-09-18 21:08:25 +02:00
|
|
|
|
|
|
|
RelationDecrementReferenceCount(scan->relation);
|
1999-12-30 06:05:13 +01:00
|
|
|
|
|
|
|
/* Release the scan data structure itself */
|
|
|
|
IndexScanEnd(scan);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_markpos - mark a scan position
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_markpos(IndexScanDesc scan)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
SCAN_CHECKS;
|
|
|
|
GET_SCAN_PROCEDURE(markpos, ammarkpos);
|
|
|
|
|
2000-05-30 06:25:00 +02:00
|
|
|
OidFunctionCall1(procedure, PointerGetDatum(scan));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_restrpos - restore a scan position
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
index_restrpos(IndexScanDesc scan)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure procedure;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
SCAN_CHECKS;
|
|
|
|
GET_SCAN_PROCEDURE(restrpos, amrestrpos);
|
|
|
|
|
2000-05-30 06:25:00 +02:00
|
|
|
OidFunctionCall1(procedure, PointerGetDatum(scan));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_getnext - get the next tuple from a scan
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* A RetrieveIndexResult is a index tuple/heap tuple pair
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
RetrieveIndexResult
|
|
|
|
index_getnext(IndexScanDesc scan,
|
1997-09-07 07:04:48 +02:00
|
|
|
ScanDirection direction)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
RetrieveIndexResult result;
|
|
|
|
|
|
|
|
SCAN_CHECKS;
|
2000-03-15 00:52:01 +01:00
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* Look up the access procedure only once per scan.
|
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
if (scan->fn_getnext.fn_oid == InvalidOid)
|
|
|
|
{
|
|
|
|
RegProcedure procedure;
|
|
|
|
|
|
|
|
GET_SCAN_PROCEDURE(getnext, amgettuple);
|
|
|
|
fmgr_info(procedure, &scan->fn_getnext);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* have the am's gettuple proc do all the work.
|
|
|
|
* ----------------
|
|
|
|
*/
|
2000-03-15 00:52:01 +01:00
|
|
|
result = (RetrieveIndexResult)
|
2000-05-30 06:25:00 +02:00
|
|
|
DatumGetPointer(FunctionCall2(&scan->fn_getnext,
|
|
|
|
PointerGetDatum(scan),
|
|
|
|
Int32GetDatum(direction)));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-01-23 00:50:30 +01:00
|
|
|
/* ----------------
|
|
|
|
* 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 relation)
|
|
|
|
{
|
|
|
|
RegProcedure procedure;
|
|
|
|
|
|
|
|
RELATION_CHECKS;
|
|
|
|
GET_REL_PROCEDURE(cost_estimator, amcostestimate);
|
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* index_getprocid
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* This routine returns the requested procedure OID for a particular
|
|
|
|
* indexed attribute.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
RegProcedure
|
|
|
|
index_getprocid(Relation irel,
|
1997-09-07 07:04:48 +02:00
|
|
|
AttrNumber attnum,
|
|
|
|
uint16 procnum)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
RegProcedure *loc;
|
|
|
|
int natts;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
natts = irel->rd_rel->relnatts;
|
|
|
|
|
|
|
|
loc = irel->rd_support;
|
|
|
|
|
|
|
|
Assert(loc != NULL);
|
|
|
|
|
1998-09-01 05:29:17 +02:00
|
|
|
return loc[(natts * (procnum - 1)) + (attnum - 1)];
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|