* indexam.c
* general index access method routines
*
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.33 1999/07/15 22:38:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.46 2000/07/14 22:17:30 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relationId
*-------------------------------------------------------------------------
*/
-#include <postgres.h>
+#include "postgres.h"
-#include <access/genam.h>
-#include <utils/relcache.h>
-#include <access/heapam.h>
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "utils/relcache.h"
-/* ----------------
- * undefine macros we aren't going to use that would otherwise
- * get in our way.. delete is defined in c.h and the am's are
- * defined in heapam.h
- * ----------------
- */
-#undef delete
-#undef aminsert
-#undef amdelete
-#undef ambeginscan
-#undef amrescan
-#undef amendscan
-#undef ammarkpos
-#undef amrestrpos
-#undef amgettuple
/* ----------------------------------------------------------------
* macros used in index_ routines
* index_open - open an index relation by relationId
*
* presently the relcache routines do all the work we need
- * to open/close index relations.
+ * to open/close index relations. However, callers of index_open
+ * expect it to succeed, so we need to check for a failure return.
+ *
+ * Note: we acquire no lock on the index. An AccessShareLock is
+ * acquired by index_beginscan (and released by index_endscan).
* ----------------
*/
Relation
index_open(Oid relationId)
{
- return RelationIdGetRelation(relationId);
+ Relation r;
+
+ r = RelationIdGetRelation(relationId);
+
+ if (!RelationIsValid(r))
+ elog(ERROR, "Index %u does not exist", relationId);
+
+ if (r->rd_rel->relkind != RELKIND_INDEX)
+ elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
+
+ return r;
}
/* ----------------
* index_openr - open a index relation by name
*
- * presently the relcache routines do all the work we need
- * to open/close index relations.
+ * As above, but lookup by name instead of OID.
* ----------------
*/
Relation
index_openr(char *relationName)
{
- return RelationNameGetRelation(relationName);
+ Relation r;
+
+ r = RelationNameGetRelation(relationName);
+
+ if (!RelationIsValid(r))
+ elog(ERROR, "Index '%s' does not exist", relationName);
+
+ if (r->rd_rel->relkind != RELKIND_INDEX)
+ elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
+
+ return r;
}
/* ----------------
* ----------------
*/
specificResult = (InsertIndexResult)
- fmgr(procedure, relation, datum, nulls, heap_t_ctid, heapRel, NULL);
+ DatumGetPointer(OidFunctionCall5(procedure,
+ PointerGetDatum(relation),
+ PointerGetDatum(datum),
+ PointerGetDatum(nulls),
+ PointerGetDatum(heap_t_ctid),
+ PointerGetDatum(heapRel)));
/* must be pfree'ed */
return specificResult;
RELATION_CHECKS;
GET_REL_PROCEDURE(delete, amdelete);
- fmgr(procedure, relation, indexItem);
+ OidFunctionCall2(procedure,
+ PointerGetDatum(relation),
+ PointerGetDatum(indexItem));
}
/* ----------------
RELATION_CHECKS;
GET_REL_PROCEDURE(beginscan, ambeginscan);
+ RelationIncrementReferenceCount(relation);
+
+ /* ----------------
+ * 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(relation, AccessShareLock);
scandesc = (IndexScanDesc)
- fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
+ DatumGetPointer(OidFunctionCall4(procedure,
+ PointerGetDatum(relation),
+ BoolGetDatum(scanFromEnd),
+ UInt16GetDatum(numberOfKeys),
+ PointerGetDatum(key)));
return scandesc;
}
SCAN_CHECKS;
GET_SCAN_PROCEDURE(rescan, amrescan);
- fmgr(procedure, scan, scanFromEnd, key);
+ OidFunctionCall3(procedure,
+ PointerGetDatum(scan),
+ BoolGetDatum(scanFromEnd),
+ PointerGetDatum(key));
}
/* ----------------
SCAN_CHECKS;
GET_SCAN_PROCEDURE(endscan, amendscan);
- fmgr(procedure, scan);
+ OidFunctionCall1(procedure, PointerGetDatum(scan));
+
+ /* Release lock and refcount acquired by index_beginscan */
UnlockRelation(scan->relation, AccessShareLock);
+
+ RelationDecrementReferenceCount(scan->relation);
+
+ /* Release the scan data structure itself */
+ IndexScanEnd(scan);
}
/* ----------------
SCAN_CHECKS;
GET_SCAN_PROCEDURE(markpos, ammarkpos);
- fmgr(procedure, scan);
+ OidFunctionCall1(procedure, PointerGetDatum(scan));
}
/* ----------------
SCAN_CHECKS;
GET_SCAN_PROCEDURE(restrpos, amrestrpos);
- fmgr(procedure, scan);
+ OidFunctionCall1(procedure, PointerGetDatum(scan));
}
/* ----------------
index_getnext(IndexScanDesc scan,
ScanDirection direction)
{
- RegProcedure procedure;
RetrieveIndexResult result;
SCAN_CHECKS;
- GET_SCAN_PROCEDURE(getnext, amgettuple);
+
+ /* ----------------
+ * 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);
+ }
/* ----------------
* have the am's gettuple proc do all the work.
* ----------------
*/
- result = (RetrieveIndexResult) fmgr(procedure, scan, direction);
+ result = (RetrieveIndexResult)
+ DatumGetPointer(FunctionCall2(&scan->fn_getnext,
+ PointerGetDatum(scan),
+ Int32GetDatum(direction)));
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 relation)
+{
+ RegProcedure procedure;
+
+ RELATION_CHECKS;
+ GET_REL_PROCEDURE(cost_estimator, amcostestimate);
+
+ return procedure;
+}
+
+/* ----------------
* index_getprocid
*
* Some indexed access methods may require support routines that are
return loc[(natts * (procnum - 1)) + (attnum - 1)];
}
-
-Datum
-GetIndexValue(HeapTuple tuple,
- TupleDesc hTupDesc,
- int attOff,
- AttrNumber *attrNums,
- FuncIndexInfo *fInfo,
- bool *attNull)
-{
- Datum returnVal;
- bool isNull = FALSE;
-
- if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid)
- {
- int i;
- Datum *attData = (Datum *) palloc(FIgetnArgs(fInfo) * sizeof(Datum));
-
- for (i = 0; i < FIgetnArgs(fInfo); i++)
- {
- attData[i] = heap_getattr(tuple,
- attrNums[i],
- hTupDesc,
- attNull);
- if (*attNull)
- isNull = TRUE;
- }
- returnVal = (Datum) fmgr_array_args(FIgetProcOid(fInfo),
- FIgetnArgs(fInfo),
- (char **) attData,
- &isNull);
- pfree(attData);
- *attNull = isNull;
- }
- else
- returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull);
-
- return returnVal;
-}