]> granicus.if.org Git - postgresql/blob - src/backend/access/index/indexam.c
Make functions static where possible, enclose unused functions in #ifdef NOT_USED.
[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.12 1997/08/19 21:29:30 momjian 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          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          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     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              Relation heapRel)
169 {
170     RegProcedure                procedure;
171     InsertIndexResult           specificResult;
172     
173     RELATION_CHECKS;
174     GET_REL_PROCEDURE(insert,aminsert);
175     
176     /* ----------------
177      *  have the am's insert proc do all the work.  
178      * ----------------
179      */
180     specificResult = (InsertIndexResult)
181         fmgr(procedure, relation, datum, nulls, heap_t_ctid, heapRel, NULL);
182     
183     /* ----------------
184      *  the insert proc is supposed to return a "specific result" and
185      *  this routine has to return a "general result" so after we get
186      *  something back from the insert proc, we allocate a
187      *  "general result" and copy some crap between the two.
188      *
189      *  As far as I'm concerned all this result shit is needlessly c
190      *  omplicated and should be eliminated.  -cim 1/19/91
191      *
192      *  mao concurs.  regardless of how we feel here, however, it is
193      *  important to free memory we don't intend to return to anyone.
194      *  2/28/91
195      *
196      *  this "general result" crap is now gone. -ay 3/6/95
197      * ----------------
198      */
199     
200     return (specificResult);
201 }
202
203 /* ----------------
204  *      index_delete - delete an item from an index relation
205  * ----------------
206  */
207 void
208 index_delete(Relation relation, ItemPointer indexItem)
209 {
210     RegProcedure        procedure;
211     
212     RELATION_CHECKS;
213     GET_REL_PROCEDURE(delete,amdelete);
214     
215     fmgr(procedure, relation, indexItem);    
216 }
217
218 /* ----------------
219  *      index_beginscan - start a scan of an index
220  * ----------------
221  */
222 IndexScanDesc
223 index_beginscan(Relation relation,
224                 bool scanFromEnd,
225                 uint16 numberOfKeys,
226                 ScanKey key)
227 {
228     IndexScanDesc       scandesc;
229     RegProcedure        procedure;
230     
231     RELATION_CHECKS;
232     GET_REL_PROCEDURE(beginscan,ambeginscan);
233     
234     RelationSetRIntentLock(relation);
235     
236     scandesc = (IndexScanDesc)
237         fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
238     
239     return scandesc;
240 }
241
242 /* ----------------
243  *      index_rescan  - restart a scan of an index
244  * ----------------
245  */
246 void
247 index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
248 {
249     RegProcedure        procedure;
250     
251     SCAN_CHECKS;
252     GET_SCAN_PROCEDURE(rescan,amrescan);
253     
254     fmgr(procedure, scan, scanFromEnd, key);
255 }
256
257 /* ----------------
258  *      index_endscan - end a scan
259  * ----------------
260  */
261 void
262 index_endscan(IndexScanDesc scan)
263 {
264     RegProcedure        procedure;
265     
266     SCAN_CHECKS;
267     GET_SCAN_PROCEDURE(endscan,amendscan);
268     
269     fmgr(procedure, scan);
270     
271     RelationUnsetRIntentLock(scan->relation);
272 }
273
274 #ifdef NOT_USED
275 /* ----------------
276  *      index_markpos  - mark a scan position
277  * ----------------
278  */
279 void
280 index_markpos(IndexScanDesc scan)
281 {
282     RegProcedure        procedure;
283     
284     SCAN_CHECKS;
285     GET_SCAN_PROCEDURE(markpos,ammarkpos);
286     
287     fmgr(procedure, scan);
288 }
289 #endif
290
291 #ifdef NOT_USED
292 /* ----------------
293  *      index_restrpos  - restore a scan position
294  * ----------------
295  */
296 void
297 index_restrpos(IndexScanDesc scan)
298 {
299     RegProcedure        procedure;
300     
301     SCAN_CHECKS;
302     GET_SCAN_PROCEDURE(restrpos,amrestrpos);
303     
304     fmgr(procedure, scan);
305 }
306 #endif
307
308 /* ----------------
309  *      index_getnext - get the next tuple from a scan
310  *
311  *      A RetrieveIndexResult is a index tuple/heap tuple pair
312  * ----------------
313  */
314 RetrieveIndexResult
315 index_getnext(IndexScanDesc scan,
316               ScanDirection direction)
317 {
318     RegProcedure                procedure;
319     RetrieveIndexResult         result;
320     
321     SCAN_CHECKS;
322     GET_SCAN_PROCEDURE(getnext,amgettuple);
323     
324     /* ----------------
325      *  have the am's gettuple proc do all the work.  
326      * ----------------
327      */
328     result = (RetrieveIndexResult)
329         fmgr(procedure, scan, direction);
330     
331     return result;
332 }
333
334 /* ----------------
335  *      index_getprocid
336  *
337  *      Some indexed access methods may require support routines that are
338  *      not in the operator class/operator model imposed by pg_am.  These
339  *      access methods may store the OIDs of registered procedures they
340  *      need in pg_amproc.  These registered procedure OIDs are ordered in
341  *      a way that makes sense to the access method, and used only by the
342  *      access method.  The general index code doesn't know anything about
343  *      the routines involved; it just builds an ordered list of them for
344  *      each attribute on which an index is defined.
345  *
346  *      This routine returns the requested procedure OID for a particular
347  *      indexed attribute.
348  * ----------------
349  */
350 RegProcedure
351 index_getprocid(Relation irel,
352                 AttrNumber attnum,
353                 uint16 procnum)
354 {
355     RegProcedure *loc;
356     int natts;
357     
358     natts = irel->rd_rel->relnatts;
359     
360     loc = irel->rd_support;
361
362     Assert(loc != NULL);
363     
364     return (loc[(natts * (procnum - 1)) + (attnum - 1)]);
365 }
366
367 Datum
368 GetIndexValue(HeapTuple tuple,
369               TupleDesc hTupDesc,
370               int attOff,
371               AttrNumber attrNums[],
372               FuncIndexInfo *fInfo,
373               bool *attNull,
374               Buffer buffer)
375 {
376     Datum returnVal;
377     bool        isNull;
378     
379     if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) {
380         int i;
381         Datum *attData = (Datum *)palloc(FIgetnArgs(fInfo)*sizeof(Datum));
382         
383         for (i = 0; i < FIgetnArgs(fInfo); i++) {
384             attData[i] = (Datum) heap_getattr(tuple, 
385                                               buffer, 
386                                               attrNums[i], 
387                                               hTupDesc,
388                                               attNull);
389         }
390         returnVal = (Datum)fmgr_array_args(FIgetProcOid(fInfo),
391                                            FIgetnArgs(fInfo),
392                                            (char **) attData,
393                                            &isNull);
394         pfree(attData);
395         *attNull = FALSE;
396     }else {
397         returnVal = (Datum) heap_getattr(tuple, buffer, attrNums[attOff], 
398                                          hTupDesc, attNull);
399     }
400     return returnVal;
401 }