]> granicus.if.org Git - postgresql/blob - src/backend/access/index/indexam.c
More cleanups
[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.7 1996/11/05 10:02:03 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
66 #include <postgres.h>
67  
68 #include <access/genam.h>  
69 #include <utils/relcache.h>
70 #include <fmgr.h>
71 #include <storage/lmgr.h>
72 #include <access/heaptuple.h>
73
74 /* ----------------
75  *   undefine macros we aren't going to use that would otherwise
76  *   get in our way..  delete is defined in c.h and the am's are
77  *   defined in heapam.h
78  * ----------------
79  */
80 #undef delete
81 #undef aminsert
82 #undef amdelete
83 #undef ambeginscan
84 #undef amrescan
85 #undef amendscan
86 #undef ammarkpos
87 #undef amrestrpos
88 #undef amgettuple
89
90 /* ----------------------------------------------------------------
91  *                  macros used in index_ routines
92  * ----------------------------------------------------------------
93  */
94 #define RELATION_CHECKS \
95 Assert(RelationIsValid(relation)); \
96          Assert(PointerIsValid(relation->rd_am))
97      
98 #define SCAN_CHECKS \
99      Assert(IndexScanIsValid(scan)); \
100          Assert(RelationIsValid(scan->relation)); \
101          Assert(PointerIsValid(scan->relation->rd_am))
102      
103 #define GET_REL_PROCEDURE(x,y) \
104          CppConcat(procedure = relation->rd_am->,y); \
105          if (! RegProcedureIsValid(procedure)) \
106          elog(WARN, "index_%s: invalid %s regproc", \
107               CppAsString(x), CppAsString(y))
108      
109 #define GET_SCAN_PROCEDURE(x,y) \
110          CppConcat(procedure = scan->relation->rd_am->,y); \
111          if (! RegProcedureIsValid(procedure)) \
112          elog(WARN, "index_%s: invalid %s regproc", \
113               CppAsString(x), CppAsString(y))
114      
115      
116 /* ----------------------------------------------------------------
117  *                 index_ interface functions
118  * ----------------------------------------------------------------
119  */
120 /* ----------------
121  *      index_open - open an index relation by relationId
122  *
123  *      presently the relcache routines do all the work we need
124  *      to open/close index relations.
125  * ----------------
126  */
127 Relation
128 index_open(Oid relationId)
129 {
130     return RelationIdGetRelation(relationId);
131 }
132
133 /* ----------------
134  *      index_openr - open a index relation by name
135  *
136  *      presently the relcache routines do all the work we need
137  *      to open/close index relations.
138  * ----------------
139  */
140 Relation
141 index_openr(char *relationName)
142 {
143     return RelationNameGetRelation(relationName);
144 }
145
146 /* ----------------
147  *      index_close - close a index relation
148  *
149  *      presently the relcache routines do all the work we need
150  *      to open/close index relations.
151  * ----------------
152  */
153 void
154 index_close(Relation relation)
155 {
156     (void) RelationClose(relation);
157 }
158
159 /* ----------------
160  *      index_insert - insert an index tuple into a relation
161  * ----------------
162  */
163 InsertIndexResult
164 index_insert(Relation relation,
165              Datum *datum,
166              char *nulls,
167              ItemPointer heap_t_ctid)
168 {
169     RegProcedure                procedure;
170     InsertIndexResult           specificResult;
171     
172     RELATION_CHECKS;
173     GET_REL_PROCEDURE(insert,aminsert);
174     
175     /* ----------------
176      *  have the am's insert proc do all the work.  
177      * ----------------
178      */
179     specificResult = (InsertIndexResult)
180         fmgr(procedure, relation, datum, nulls, heap_t_ctid, NULL);
181     
182     /* ----------------
183      *  the insert proc is supposed to return a "specific result" and
184      *  this routine has to return a "general result" so after we get
185      *  something back from the insert proc, we allocate a
186      *  "general result" and copy some crap between the two.
187      *
188      *  As far as I'm concerned all this result shit is needlessly c
189      *  omplicated and should be eliminated.  -cim 1/19/91
190      *
191      *  mao concurs.  regardless of how we feel here, however, it is
192      *  important to free memory we don't intend to return to anyone.
193      *  2/28/91
194      *
195      *  this "general result" crap is now gone. -ay 3/6/95
196      * ----------------
197      */
198     
199     return (specificResult);
200 }
201
202 /* ----------------
203  *      index_delete - delete an item from an index relation
204  * ----------------
205  */
206 void
207 index_delete(Relation relation, ItemPointer indexItem)
208 {
209     RegProcedure        procedure;
210     
211     RELATION_CHECKS;
212     GET_REL_PROCEDURE(delete,amdelete);
213     
214     (void) fmgr(procedure, relation, indexItem);    
215 }
216
217 /* ----------------
218  *      index_beginscan - start a scan of an index
219  * ----------------
220  */
221 IndexScanDesc
222 index_beginscan(Relation relation,
223                 bool scanFromEnd,
224                 uint16 numberOfKeys,
225                 ScanKey key)
226 {
227     IndexScanDesc       scandesc;
228     RegProcedure        procedure;
229     
230     RELATION_CHECKS;
231     GET_REL_PROCEDURE(beginscan,ambeginscan);
232     
233     RelationSetRIntentLock(relation);
234     
235     scandesc = (IndexScanDesc)
236         fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
237     
238     return scandesc;
239 }
240
241 /* ----------------
242  *      index_rescan  - restart a scan of an index
243  * ----------------
244  */
245 void
246 index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
247 {
248     RegProcedure        procedure;
249     
250     SCAN_CHECKS;
251     GET_SCAN_PROCEDURE(rescan,amrescan);
252     
253     (void) fmgr(procedure, scan, scanFromEnd, key);
254 }
255
256 /* ----------------
257  *      index_endscan - end a scan
258  * ----------------
259  */
260 void
261 index_endscan(IndexScanDesc scan)
262 {
263     RegProcedure        procedure;
264     
265     SCAN_CHECKS;
266     GET_SCAN_PROCEDURE(endscan,amendscan);
267     
268     (void) fmgr(procedure, scan);
269     
270     RelationUnsetRIntentLock(scan->relation);
271 }
272
273 /* ----------------
274  *      index_markpos  - mark a scan position
275  * ----------------
276  */
277 void
278 index_markpos(IndexScanDesc scan)
279 {
280     RegProcedure        procedure;
281     
282     SCAN_CHECKS;
283     GET_SCAN_PROCEDURE(markpos,ammarkpos);
284     
285     (void) fmgr(procedure, scan);
286 }
287
288 /* ----------------
289  *      index_restrpos  - restore a scan position
290  * ----------------
291  */
292 void
293 index_restrpos(IndexScanDesc scan)
294 {
295     RegProcedure        procedure;
296     
297     SCAN_CHECKS;
298     GET_SCAN_PROCEDURE(restrpos,amrestrpos);
299     
300     (void) fmgr(procedure, scan);
301 }
302
303 /* ----------------
304  *      index_getnext - get the next tuple from a scan
305  *
306  *      A RetrieveIndexResult is a index tuple/heap tuple pair
307  * ----------------
308  */
309 RetrieveIndexResult
310 index_getnext(IndexScanDesc scan,
311               ScanDirection direction)
312 {
313     RegProcedure                procedure;
314     RetrieveIndexResult         result;
315     
316     SCAN_CHECKS;
317     GET_SCAN_PROCEDURE(getnext,amgettuple);
318     
319     /* ----------------
320      *  have the am's gettuple proc do all the work.  
321      * ----------------
322      */
323     result = (RetrieveIndexResult)
324         fmgr(procedure, scan, direction);
325     
326     return result;
327 }
328
329 /* ----------------
330  *      index_getprocid
331  *
332  *      Some indexed access methods may require support routines that are
333  *      not in the operator class/operator model imposed by pg_am.  These
334  *      access methods may store the OIDs of registered procedures they
335  *      need in pg_amproc.  These registered procedure OIDs are ordered in
336  *      a way that makes sense to the access method, and used only by the
337  *      access method.  The general index code doesn't know anything about
338  *      the routines involved; it just builds an ordered list of them for
339  *      each attribute on which an index is defined.
340  *
341  *      This routine returns the requested procedure OID for a particular
342  *      indexed attribute.
343  * ----------------
344  */
345 RegProcedure
346 index_getprocid(Relation irel,
347                 AttrNumber attnum,
348                 uint16 procnum)
349 {
350     RegProcedure *loc;
351     int natts;
352     
353     natts = irel->rd_rel->relnatts;
354     
355     loc = irel->rd_support;
356
357     Assert(loc != NULL);
358     
359     return (loc[(natts * (procnum - 1)) + (attnum - 1)]);
360 }
361
362 Datum
363 GetIndexValue(HeapTuple tuple,
364               TupleDesc hTupDesc,
365               int attOff,
366               AttrNumber attrNums[],
367               FuncIndexInfo *fInfo,
368               bool *attNull,
369               Buffer buffer)
370 {
371     Datum returnVal;
372     bool        isNull;
373     
374     if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) {
375         int i;
376         Datum *attData = (Datum *)palloc(FIgetnArgs(fInfo)*sizeof(Datum));
377         
378         for (i = 0; i < FIgetnArgs(fInfo); i++) {
379             attData[i] = (Datum) heap_getattr(tuple, 
380                                               buffer, 
381                                               attrNums[i], 
382                                               hTupDesc,
383                                               attNull);
384         }
385         returnVal = (Datum)fmgr_array_args(FIgetProcOid(fInfo),
386                                            FIgetnArgs(fInfo),
387                                            (char **) attData,
388                                            &isNull);
389         pfree(attData);
390         *attNull = FALSE;
391     }else {
392         returnVal = (Datum) heap_getattr(tuple, buffer, attrNums[attOff], 
393                                          hTupDesc, attNull);
394     }
395     return returnVal;
396 }