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