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