OSDN Git Service

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