]> granicus.if.org Git - postgresql/blob - src/backend/access/index/indexam.c
Removal of CppConcat from indexam.c.
[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.9 1996/12/26 17:44:46 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     (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              bool is_update)
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, is_update, 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     (void) 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     (void) 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     (void) fmgr(procedure, scan);
270     
271     RelationUnsetRIntentLock(scan->relation);
272 }
273
274 /* ----------------
275  *      index_markpos  - mark a scan position
276  * ----------------
277  */
278 void
279 index_markpos(IndexScanDesc scan)
280 {
281     RegProcedure        procedure;
282     
283     SCAN_CHECKS;
284     GET_SCAN_PROCEDURE(markpos,ammarkpos);
285     
286     (void) fmgr(procedure, scan);
287 }
288
289 /* ----------------
290  *      index_restrpos  - restore a scan position
291  * ----------------
292  */
293 void
294 index_restrpos(IndexScanDesc scan)
295 {
296     RegProcedure        procedure;
297     
298     SCAN_CHECKS;
299     GET_SCAN_PROCEDURE(restrpos,amrestrpos);
300     
301     (void) fmgr(procedure, scan);
302 }
303
304 /* ----------------
305  *      index_getnext - get the next tuple from a scan
306  *
307  *      A RetrieveIndexResult is a index tuple/heap tuple pair
308  * ----------------
309  */
310 RetrieveIndexResult
311 index_getnext(IndexScanDesc scan,
312               ScanDirection direction)
313 {
314     RegProcedure                procedure;
315     RetrieveIndexResult         result;
316     
317     SCAN_CHECKS;
318     GET_SCAN_PROCEDURE(getnext,amgettuple);
319     
320     /* ----------------
321      *  have the am's gettuple proc do all the work.  
322      * ----------------
323      */
324     result = (RetrieveIndexResult)
325         fmgr(procedure, scan, direction);
326     
327     return result;
328 }
329
330 /* ----------------
331  *      index_getprocid
332  *
333  *      Some indexed access methods may require support routines that are
334  *      not in the operator class/operator model imposed by pg_am.  These
335  *      access methods may store the OIDs of registered procedures they
336  *      need in pg_amproc.  These registered procedure OIDs are ordered in
337  *      a way that makes sense to the access method, and used only by the
338  *      access method.  The general index code doesn't know anything about
339  *      the routines involved; it just builds an ordered list of them for
340  *      each attribute on which an index is defined.
341  *
342  *      This routine returns the requested procedure OID for a particular
343  *      indexed attribute.
344  * ----------------
345  */
346 RegProcedure
347 index_getprocid(Relation irel,
348                 AttrNumber attnum,
349                 uint16 procnum)
350 {
351     RegProcedure *loc;
352     int natts;
353     
354     natts = irel->rd_rel->relnatts;
355     
356     loc = irel->rd_support;
357
358     Assert(loc != NULL);
359     
360     return (loc[(natts * (procnum - 1)) + (attnum - 1)]);
361 }
362
363 Datum
364 GetIndexValue(HeapTuple tuple,
365               TupleDesc hTupDesc,
366               int attOff,
367               AttrNumber attrNums[],
368               FuncIndexInfo *fInfo,
369               bool *attNull,
370               Buffer buffer)
371 {
372     Datum returnVal;
373     bool        isNull;
374     
375     if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) {
376         int i;
377         Datum *attData = (Datum *)palloc(FIgetnArgs(fInfo)*sizeof(Datum));
378         
379         for (i = 0; i < FIgetnArgs(fInfo); i++) {
380             attData[i] = (Datum) heap_getattr(tuple, 
381                                               buffer, 
382                                               attrNums[i], 
383                                               hTupDesc,
384                                               attNull);
385         }
386         returnVal = (Datum)fmgr_array_args(FIgetProcOid(fInfo),
387                                            FIgetnArgs(fInfo),
388                                            (char **) attData,
389                                            &isNull);
390         pfree(attData);
391         *attNull = FALSE;
392     }else {
393         returnVal = (Datum) heap_getattr(tuple, buffer, attrNums[attOff], 
394                                          hTupDesc, attNull);
395     }
396     return returnVal;
397 }