OSDN Git Service

Cleanup of code for creating index entries. Functional indexes with
[pg-rex/syncrep.git] / src / backend / access / index / indexam.c
index aa2d944..dc18b0d 100644 (file)
@@ -1,13 +1,14 @@
 /*-------------------------------------------------------------------------
  *
- * indexam.c--
+ * 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.28 1998/10/02 16:27: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 <fmgr.h>
-#include <storage/lmgr.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;
 }
 
 /* ----------------
@@ -188,7 +195,12 @@ index_insert(Relation relation,
         * ----------------
         */
        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;
@@ -206,7 +218,9 @@ index_delete(Relation relation, ItemPointer indexItem)
        RELATION_CHECKS;
        GET_REL_PROCEDURE(delete, amdelete);
 
-       fmgr(procedure, relation, indexItem);
+       OidFunctionCall2(procedure,
+                                        PointerGetDatum(relation),
+                                        PointerGetDatum(indexItem));
 }
 
 /* ----------------
@@ -225,10 +239,24 @@ index_beginscan(Relation relation,
        RELATION_CHECKS;
        GET_REL_PROCEDURE(beginscan, ambeginscan);
 
-       RelationSetRIntentLock(relation);
+       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;
 }
@@ -245,7 +273,10 @@ index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(rescan, amrescan);
 
-       fmgr(procedure, scan, scanFromEnd, key);
+       OidFunctionCall3(procedure,
+                                        PointerGetDatum(scan),
+                                        BoolGetDatum(scanFromEnd),
+                                        PointerGetDatum(key));
 }
 
 /* ----------------
@@ -260,9 +291,16 @@ index_endscan(IndexScanDesc scan)
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(endscan, amendscan);
 
-       fmgr(procedure, scan);
+       OidFunctionCall1(procedure, PointerGetDatum(scan));
 
-       RelationUnsetRIntentLock(scan->relation);
+       /* Release lock and refcount acquired by index_beginscan */
+
+       UnlockRelation(scan->relation, AccessShareLock);
+
+       RelationDecrementReferenceCount(scan->relation);
+
+       /* Release the scan data structure itself */
+       IndexScanEnd(scan);
 }
 
 /* ----------------
@@ -277,7 +315,7 @@ index_markpos(IndexScanDesc scan)
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(markpos, ammarkpos);
 
-       fmgr(procedure, scan);
+       OidFunctionCall1(procedure, PointerGetDatum(scan));
 }
 
 /* ----------------
@@ -292,7 +330,7 @@ index_restrpos(IndexScanDesc scan)
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(restrpos, amrestrpos);
 
-       fmgr(procedure, scan);
+       OidFunctionCall1(procedure, PointerGetDatum(scan));
 }
 
 /* ----------------
@@ -305,22 +343,56 @@ RetrieveIndexResult
 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
@@ -352,41 +424,3 @@ index_getprocid(Relation irel,
 
        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;
-}