OSDN Git Service

Remove RelationGetBufferWithBuffer(), which is horribly confused about
[pg-rex/syncrep.git] / src / backend / access / index / genam.c
1 /*-------------------------------------------------------------------------
2  *
3  * genam.c
4  *        general index access method routines
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.27 2001/06/09 18:16:56 tgl Exp $
12  *
13  * NOTES
14  *        many of the old access method routines have been turned into
15  *        macros and moved to genam.h -cim 4/30/91
16  *
17  *-------------------------------------------------------------------------
18  */
19 /*
20  * OLD COMMENTS
21  * Scans are implemented as follows:
22  *
23  * `0' represents an invalid item pointer.
24  * `-' represents an unknown item pointer.
25  * `X' represents a known item pointers.
26  * `+' represents known or invalid item pointers.
27  * `*' represents any item pointers.
28  *
29  * State is represented by a triple of these symbols in the order of
30  * previous, current, next.  Note that the case of reverse scans works
31  * identically.
32  *
33  *              State   Result
34  * (1)  + + -   + 0 0                   (if the next item pointer is invalid)
35  * (2)                  + X -                   (otherwise)
36  * (3)  * 0 0   * 0 0                   (no change)
37  * (4)  + X 0   X 0 0                   (shift)
38  * (5)  * + X   + X -                   (shift, add unknown)
39  *
40  * All other states cannot occur.
41  *
42  * Note:
43  *              It would be possible to cache the status of the previous and
44  *              next item pointer using the flags.
45  * ----------------------------------------------------------------
46  */
47
48 #include "postgres.h"
49 #include "access/genam.h"
50
51
52 /* ----------------------------------------------------------------
53  *              general access method routines
54  *
55  *              All indexed access methods use an identical scan structure.
56  *              We don't know how the various AMs do locking, however, so we don't
57  *              do anything about that here.
58  *
59  *              The intent is that an AM implementor will define a beginscan routine
60  *              that calls RelationGetIndexScan, to fill in the scan, and then does
61  *              whatever kind of locking he wants.
62  *
63  *              At the end of a scan, the AM's endscan routine undoes the locking,
64  *              but does *not* call IndexScanEnd --- the higher-level index_endscan
65  *              routine does that.      (We can't do it in the AM because index_endscan
66  *              still needs to touch the IndexScanDesc after calling the AM.)
67  *
68  *              Because of this, the AM does not have a choice whether to call
69  *              RelationGetIndexScan or not; its beginscan routine must return an
70  *              object made by RelationGetIndexScan.  This is kinda ugly but not
71  *              worth cleaning up now.
72  * ----------------------------------------------------------------
73  */
74
75 /* ----------------
76  *      RelationGetIndexScan -- Create and fill an IndexScanDesc.
77  *
78  *              This routine creates an index scan structure and sets its contents
79  *              up correctly. This routine calls AMrescan to set up the scan with
80  *              the passed key.
81  *
82  *              Parameters:
83  *                              relation -- index relation for scan.
84  *                              scanFromEnd -- if true, begin scan at one of the index's
85  *                                                         endpoints.
86  *                              numberOfKeys -- count of scan keys.
87  *                              key -- the ScanKey for the starting position of the scan.
88  *
89  *              Returns:
90  *                              An initialized IndexScanDesc.
91  * ----------------
92  */
93 IndexScanDesc
94 RelationGetIndexScan(Relation relation,
95                                          bool scanFromEnd,
96                                          uint16 numberOfKeys,
97                                          ScanKey key)
98 {
99         IndexScanDesc scan;
100
101         if (!RelationIsValid(relation))
102                 elog(ERROR, "RelationGetIndexScan: relation invalid");
103
104         scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
105
106         scan->relation = relation;
107         scan->opaque = NULL;
108         scan->numberOfKeys = numberOfKeys;
109
110         ItemPointerSetInvalid(&scan->currentItemData);
111         ItemPointerSetInvalid(&scan->currentMarkData);
112
113         /*
114          * mark cached function lookup data invalid; it will be set on first
115          * use
116          */
117         scan->fn_getnext.fn_oid = InvalidOid;
118
119         if (numberOfKeys > 0)
120                 scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * numberOfKeys);
121         else
122                 scan->keyData = NULL;
123
124         index_rescan(scan, scanFromEnd, key);
125
126         return scan;
127 }
128
129 /* ----------------
130  *      IndexScanEnd -- End an index scan.
131  *
132  *              This routine just releases the storage acquired by
133  *              RelationGetIndexScan().  Any AM-level resources are
134  *              assumed to already have been released by the AM's
135  *              endscan routine.
136  *
137  *      Returns:
138  *              None.
139  * ----------------
140  */
141 void
142 IndexScanEnd(IndexScanDesc scan)
143 {
144         if (!IndexScanIsValid(scan))
145                 elog(ERROR, "IndexScanEnd: invalid scan");
146
147         if (scan->keyData != NULL)
148                 pfree(scan->keyData);
149
150         pfree(scan);
151 }
152
153 #ifdef NOT_USED
154 /* ----------------
155  *      IndexScanRestart -- Restart an index scan.
156  *
157  *              This routine isn't used by any existing access method.  It's
158  *              appropriate if relation level locks are what you want.
159  *
160  *      Returns:
161  *              None.
162  *
163  *      Side Effects:
164  *              None.
165  * ----------------
166  */
167 void
168 IndexScanRestart(IndexScanDesc scan,
169                                  bool scanFromEnd,
170                                  ScanKey key)
171 {
172         if (!IndexScanIsValid(scan))
173                 elog(ERROR, "IndexScanRestart: invalid scan");
174
175         ItemPointerSetInvalid(&scan->currentItemData);
176
177         if (RelationGetNumberOfBlocks(scan->relation) == 0)
178                 scan->flags = ScanUnmarked;
179         else if (scanFromEnd)
180                 scan->flags = ScanUnmarked | ScanUncheckedPrevious;
181         else
182                 scan->flags = ScanUnmarked | ScanUncheckedNext;
183
184         scan->scanFromEnd = (bool) scanFromEnd;
185
186         if (scan->numberOfKeys > 0)
187                 memmove(scan->keyData,
188                                 key,
189                                 scan->numberOfKeys * sizeof(ScanKeyData));
190 }
191
192 /* ----------------
193  *      IndexScanMarkPosition -- Mark current position in a scan.
194  *
195  *              This routine isn't used by any existing access method, but is the
196  *              one that AM implementors should use, if they don't want to do any
197  *              special locking.  If relation-level locking is sufficient, this is
198  *              the routine for you.
199  *
200  *      Returns:
201  *              None.
202  *
203  *      Side Effects:
204  *              None.
205  * ----------------
206  */
207 void
208 IndexScanMarkPosition(IndexScanDesc scan)
209 {
210         scan->currentMarkData = scan->currentItemData;
211
212         scan->flags = 0x0;                      /* XXX should have a symbolic name */
213 }
214
215 /* ----------------
216  *      IndexScanRestorePosition -- Restore position on a marked scan.
217  *
218  *              This routine isn't used by any existing access method, but is the
219  *              one that AM implementors should use if they don't want to do any
220  *              special locking.  If relation-level locking is sufficient, then
221  *              this is the one you want.
222  *
223  *      Returns:
224  *              None.
225  *
226  *      Side Effects:
227  *              None.
228  * ----------------
229  */
230 void
231 IndexScanRestorePosition(IndexScanDesc scan)
232 {
233         if (scan->flags & ScanUnmarked)
234                 elog(ERROR, "IndexScanRestorePosition: no mark to restore");
235
236         scan->currentItemData = scan->currentMarkData;
237
238         scan->flags = 0x0;                      /* XXX should have a symbolic name */
239 }
240
241 #endif