]> granicus.if.org Git - postgresql/blob - src/backend/access/index/indexam.c
There, now we support GiST...now what? :)
[postgresql] / src / backend / access / index / indexam.c
1 /*-------------------------------------------------------------------------
2  *
3  * indexam.c--
4  *    general index access method routines
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *    $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.2 1996/08/26 06:27:48 scrappy Exp $
11  *
12  * INTERFACE ROUTINES
13  *      index_open      - open an index relation by relationId
14  *      index_openr     - open a index relation by name
15  *      index_close     - close a index relation
16  *      index_beginscan - start a scan of an index
17  *      index_rescan    - restart a scan of an index
18  *      index_endscan   - end a scan
19  *      index_insert    - insert an index tuple into a relation
20  *      index_delete    - delete an item from an index relation
21  *      index_markpos   - mark a scan position
22  *      index_restrpos  - restore a scan position
23  *      index_getnext   - get the next tuple from a scan
24  * **   index_fetch     - retrieve tuple with tid
25  * **   index_replace   - replace a tuple
26  * **   index_getattr   - get an attribute from an index tuple
27  *      index_getprocid - get a support procedure id from the rel tuple
28  *      
29  *      IndexScanIsValid - check index scan
30  *
31  * NOTES
32  *      This file contains the index_ routines which used
33  *      to be a scattered collection of stuff in access/genam.
34  *
35  *      The ** routines: index_fetch, index_replace, and index_getattr
36  *      have not yet been implemented.  They may not be needed.
37  *
38  * old comments
39  *      Scans are implemented as follows:
40  *
41  *      `0' represents an invalid item pointer.
42  *      `-' represents an unknown item pointer.
43  *      `X' represents a known item pointers.
44  *      `+' represents known or invalid item pointers.
45  *      `*' represents any item pointers.
46  *
47  *      State is represented by a triple of these symbols in the order of
48  *      previous, current, next.  Note that the case of reverse scans works
49  *      identically.
50  *
51  *              State   Result
52  *      (1)     + + -   + 0 0           (if the next item pointer is invalid)
53  *      (2)             + X -           (otherwise)
54  *      (3)     * 0 0   * 0 0           (no change)
55  *      (4)     + X 0   X 0 0           (shift)
56  *      (5)     * + X   + X -           (shift, add unknown)
57  *
58  *      All other states cannot occur.
59  *
60  *      Note: It would be possible to cache the status of the previous and
61  *            next item pointer using the flags.
62  *
63  *-------------------------------------------------------------------------
64  */
65 #include "postgres.h"
66
67 #include "access/attnum.h"
68 #include "access/genam.h"
69 #include "access/heapam.h"
70 #include "access/itup.h"
71 #include "access/relscan.h"
72 #include "access/sdir.h"
73 #include "access/skey.h"
74 #include "access/funcindex.h"
75
76 #include "storage/lmgr.h"
77 #include "utils/elog.h"
78 #include "utils/palloc.h"
79 #include "utils/rel.h"
80 #include "utils/relcache.h"
81
82 #include "catalog/catname.h"
83 #include "catalog/pg_attribute.h"
84 #include "catalog/pg_index.h"
85 #include "catalog/pg_proc.h"
86
87 #include "catalog/index.h"
88
89 #include "fmgr.h"
90
91 /* ----------------
92  *   undefine macros we aren't going to use that would otherwise
93  *   get in our way..  delete is defined in c.h and the am's are
94  *   defined in heapam.h
95  * ----------------
96  */
97 #undef delete
98 #undef aminsert
99 #undef amdelete
100 #undef ambeginscan
101 #undef amrescan
102 #undef amendscan
103 #undef ammarkpos
104 #undef amrestrpos
105 #undef amgettuple
106
107 /* ----------------------------------------------------------------
108  *                  macros used in index_ routines
109  * ----------------------------------------------------------------
110  */
111 #define RELATION_CHECKS \
112 Assert(RelationIsValid(relation)); \
113          Assert(PointerIsValid(relation->rd_am))
114      
115 #define SCAN_CHECKS \
116      Assert(IndexScanIsValid(scan)); \
117          Assert(RelationIsValid(scan->relation)); \
118          Assert(PointerIsValid(scan->relation->rd_am))
119      
120 #define GET_REL_PROCEDURE(x,y) \
121          CppConcat(procedure = relation->rd_am->,y); \
122          if (! RegProcedureIsValid(procedure)) \
123          elog(WARN, "index_%s: invalid %s regproc", \
124               CppAsString(x), CppAsString(y))
125      
126 #define GET_SCAN_PROCEDURE(x,y) \
127          CppConcat(procedure = scan->relation->rd_am->,y); \
128          if (! RegProcedureIsValid(procedure)) \
129          elog(WARN, "index_%s: invalid %s regproc", \
130               CppAsString(x), CppAsString(y))
131      
132      
133 /* ----------------------------------------------------------------
134  *                 index_ interface functions
135  * ----------------------------------------------------------------
136  */
137 /* ----------------
138  *      index_open - open an index relation by relationId
139  *
140  *      presently the relcache routines do all the work we need
141  *      to open/close index relations.
142  * ----------------
143  */
144 Relation
145 index_open(Oid relationId)
146 {
147     return RelationIdGetRelation(relationId);
148 }
149
150 /* ----------------
151  *      index_openr - open a index relation by name
152  *
153  *      presently the relcache routines do all the work we need
154  *      to open/close index relations.
155  * ----------------
156  */
157 Relation
158 index_openr(char *relationName)
159 {
160     return RelationNameGetRelation(relationName);
161 }
162
163 /* ----------------
164  *      index_close - close a index relation
165  *
166  *      presently the relcache routines do all the work we need
167  *      to open/close index relations.
168  * ----------------
169  */
170 void
171 index_close(Relation relation)
172 {
173     (void) RelationClose(relation);
174 }
175
176 /* ----------------
177  *      index_insert - insert an index tuple into a relation
178  * ----------------
179  */
180 InsertIndexResult
181 index_insert(Relation relation,
182              Datum *datum,
183              char *nulls,
184              ItemPointer heap_t_ctid)
185 {
186     RegProcedure                procedure;
187     InsertIndexResult           specificResult;
188     
189     RELATION_CHECKS;
190     GET_REL_PROCEDURE(insert,aminsert);
191     
192     /* ----------------
193      *  have the am's insert proc do all the work.  
194      * ----------------
195      */
196     specificResult = (InsertIndexResult)
197         fmgr(procedure, relation, datum, nulls, heap_t_ctid, NULL);
198     
199     /* ----------------
200      *  the insert proc is supposed to return a "specific result" and
201      *  this routine has to return a "general result" so after we get
202      *  something back from the insert proc, we allocate a
203      *  "general result" and copy some crap between the two.
204      *
205      *  As far as I'm concerned all this result shit is needlessly c
206      *  omplicated and should be eliminated.  -cim 1/19/91
207      *
208      *  mao concurs.  regardless of how we feel here, however, it is
209      *  important to free memory we don't intend to return to anyone.
210      *  2/28/91
211      *
212      *  this "general result" crap is now gone. -ay 3/6/95
213      * ----------------
214      */
215     
216     return (specificResult);
217 }
218
219 /* ----------------
220  *      index_delete - delete an item from an index relation
221  * ----------------
222  */
223 void
224 index_delete(Relation relation, ItemPointer indexItem)
225 {
226     RegProcedure        procedure;
227     
228     RELATION_CHECKS;
229     GET_REL_PROCEDURE(delete,amdelete);
230     
231     (void) fmgr(procedure, relation, indexItem);    
232 }
233
234 /* ----------------
235  *      index_beginscan - start a scan of an index
236  * ----------------
237  */
238 IndexScanDesc
239 index_beginscan(Relation relation,
240                 bool scanFromEnd,
241                 uint16 numberOfKeys,
242                 ScanKey key)
243 {
244     IndexScanDesc       scandesc;
245     RegProcedure        procedure;
246     
247     RELATION_CHECKS;
248     GET_REL_PROCEDURE(beginscan,ambeginscan);
249     
250     RelationSetRIntentLock(relation);
251     
252     scandesc = (IndexScanDesc)
253         fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
254     
255     return scandesc;
256 }
257
258 /* ----------------
259  *      index_rescan  - restart a scan of an index
260  * ----------------
261  */
262 void
263 index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
264 {
265     RegProcedure        procedure;
266     
267     SCAN_CHECKS;
268     GET_SCAN_PROCEDURE(rescan,amrescan);
269     
270     (void) fmgr(procedure, scan, scanFromEnd, key);
271 }
272
273 /* ----------------
274  *      index_endscan - end a scan
275  * ----------------
276  */
277 void
278 index_endscan(IndexScanDesc scan)
279 {
280     RegProcedure        procedure;
281     
282     SCAN_CHECKS;
283     GET_SCAN_PROCEDURE(endscan,amendscan);
284     
285     (void) fmgr(procedure, scan);
286     
287     RelationUnsetRIntentLock(scan->relation);
288 }
289
290 /* ----------------
291  *      index_markpos  - mark a scan position
292  * ----------------
293  */
294 void
295 index_markpos(IndexScanDesc scan)
296 {
297     RegProcedure        procedure;
298     
299     SCAN_CHECKS;
300     GET_SCAN_PROCEDURE(markpos,ammarkpos);
301     
302     (void) fmgr(procedure, scan);
303 }
304
305 /* ----------------
306  *      index_restrpos  - restore a scan position
307  * ----------------
308  */
309 void
310 index_restrpos(IndexScanDesc scan)
311 {
312     RegProcedure        procedure;
313     
314     SCAN_CHECKS;
315     GET_SCAN_PROCEDURE(restrpos,amrestrpos);
316     
317     (void) fmgr(procedure, scan);
318 }
319
320 /* ----------------
321  *      index_getnext - get the next tuple from a scan
322  *
323  *      A RetrieveIndexResult is a index tuple/heap tuple pair
324  * ----------------
325  */
326 RetrieveIndexResult
327 index_getnext(IndexScanDesc scan,
328               ScanDirection direction)
329 {
330     RegProcedure                procedure;
331     RetrieveIndexResult         result;
332     
333     SCAN_CHECKS;
334     GET_SCAN_PROCEDURE(getnext,amgettuple);
335     
336     /* ----------------
337      *  have the am's gettuple proc do all the work.  
338      * ----------------
339      */
340     result = (RetrieveIndexResult)
341         fmgr(procedure, scan, direction);
342     
343     return result;
344 }
345
346 /* ----------------
347  *      index_getprocid
348  *
349  *      Some indexed access methods may require support routines that are
350  *      not in the operator class/operator model imposed by pg_am.  These
351  *      access methods may store the OIDs of registered procedures they
352  *      need in pg_amproc.  These registered procedure OIDs are ordered in
353  *      a way that makes sense to the access method, and used only by the
354  *      access method.  The general index code doesn't know anything about
355  *      the routines involved; it just builds an ordered list of them for
356  *      each attribute on which an index is defined.
357  *
358  *      This routine returns the requested procedure OID for a particular
359  *      indexed attribute.
360  * ----------------
361  */
362 RegProcedure
363 index_getprocid(Relation irel,
364                 AttrNumber attnum,
365                 uint16 procnum)
366 {
367     RegProcedure *loc;
368     int natts;
369     
370     natts = irel->rd_rel->relnatts;
371     
372     loc = irel->rd_support;
373
374     Assert(loc != NULL);
375     
376     return (loc[(natts * (procnum - 1)) + (attnum - 1)]);
377 }
378
379 Datum
380 GetIndexValue(HeapTuple tuple,
381               TupleDesc hTupDesc,
382               int attOff,
383               AttrNumber attrNums[],
384               FuncIndexInfo *fInfo,
385               bool *attNull,
386               Buffer buffer)
387 {
388     Datum returnVal;
389     bool        isNull;
390     
391     if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) {
392         int i;
393         Datum *attData = (Datum *)palloc(FIgetnArgs(fInfo)*sizeof(Datum));
394         
395         for (i = 0; i < FIgetnArgs(fInfo); i++) {
396             attData[i] = (Datum) heap_getattr(tuple, 
397                                               buffer, 
398                                               attrNums[i], 
399                                               hTupDesc,
400                                               attNull);
401         }
402         returnVal = (Datum)fmgr_array_args(FIgetProcOid(fInfo),
403                                            FIgetnArgs(fInfo),
404                                            (char **) attData,
405                                            &isNull);
406         pfree(attData);
407         *attNull = FALSE;
408     }else {
409         returnVal = (Datum) heap_getattr(tuple, buffer, attrNums[attOff], 
410                                          hTupDesc, attNull);
411     }
412     return returnVal;
413 }