OSDN Git Service

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