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