Fix possible duplicate tuples while GiST scan. Now page is processed
[PostgreSQL.git] / src / backend / access / gist / gistscan.c
blob5e982a844845ecb4d5837ba04245f031510b3501
1 /*-------------------------------------------------------------------------
3 * gistscan.c
4 * routines to manage scans on GiST index relations
7 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include "access/genam.h"
18 #include "access/gist_private.h"
19 #include "access/gistscan.h"
20 #include "access/relscan.h"
21 #include "storage/bufmgr.h"
22 #include "utils/memutils.h"
24 static void gistfreestack(GISTSearchStack *s);
26 Datum
27 gistbeginscan(PG_FUNCTION_ARGS)
29 Relation r = (Relation) PG_GETARG_POINTER(0);
30 int nkeys = PG_GETARG_INT32(1);
31 ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
32 IndexScanDesc scan;
34 scan = RelationGetIndexScan(r, nkeys, key);
36 PG_RETURN_POINTER(scan);
39 Datum
40 gistrescan(PG_FUNCTION_ARGS)
42 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
43 ScanKey key = (ScanKey) PG_GETARG_POINTER(1);
44 GISTScanOpaque so;
45 int i;
47 so = (GISTScanOpaque) scan->opaque;
48 if (so != NULL)
50 /* rescan an existing indexscan --- reset state */
51 gistfreestack(so->stack);
52 gistfreestack(so->markstk);
53 so->stack = so->markstk = NULL;
54 so->flags = 0x0;
55 /* drop pins on buffers -- no locks held */
56 if (BufferIsValid(so->curbuf))
58 ReleaseBuffer(so->curbuf);
59 so->curbuf = InvalidBuffer;
61 if (BufferIsValid(so->markbuf))
63 ReleaseBuffer(so->markbuf);
64 so->markbuf = InvalidBuffer;
68 else
70 /* initialize opaque data */
71 so = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData));
72 so->stack = so->markstk = NULL;
73 so->flags = 0x0;
74 so->tempCxt = createTempGistContext();
75 so->curbuf = so->markbuf = InvalidBuffer;
76 so->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
77 initGISTstate(so->giststate, scan->indexRelation);
79 scan->opaque = so;
83 * Clear all the pointers.
85 ItemPointerSetInvalid(&so->curpos);
86 ItemPointerSetInvalid(&so->markpos);
87 so->nPageData = so->curPageData = 0;
89 /* Update scan key, if a new one is given */
90 if (key && scan->numberOfKeys > 0)
92 memmove(scan->keyData, key,
93 scan->numberOfKeys * sizeof(ScanKeyData));
96 * Modify the scan key so that all the Consistent method is called for
97 * all comparisons. The original operator is passed to the Consistent
98 * function in the form of its strategy number, which is available
99 * from the sk_strategy field, and its subtype from the sk_subtype
100 * field.
102 for (i = 0; i < scan->numberOfKeys; i++)
103 scan->keyData[i].sk_func = so->giststate->consistentFn[scan->keyData[i].sk_attno - 1];
106 PG_RETURN_VOID();
109 Datum
110 gistmarkpos(PG_FUNCTION_ARGS)
112 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
113 GISTScanOpaque so;
114 GISTSearchStack *o,
116 *tmp;
118 so = (GISTScanOpaque) scan->opaque;
119 so->markpos = so->curpos;
120 if (so->flags & GS_CURBEFORE)
121 so->flags |= GS_MRKBEFORE;
122 else
123 so->flags &= ~GS_MRKBEFORE;
125 o = NULL;
126 n = so->stack;
128 /* copy the parent stack from the current item data */
129 while (n != NULL)
131 tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
132 tmp->lsn = n->lsn;
133 tmp->parentlsn = n->parentlsn;
134 tmp->block = n->block;
135 tmp->next = o;
136 o = tmp;
137 n = n->next;
140 gistfreestack(so->markstk);
141 so->markstk = o;
143 /* Update markbuf: make sure to bump ref count on curbuf */
144 if (BufferIsValid(so->markbuf))
146 ReleaseBuffer(so->markbuf);
147 so->markbuf = InvalidBuffer;
149 if (BufferIsValid(so->curbuf))
151 IncrBufferRefCount(so->curbuf);
152 so->markbuf = so->curbuf;
155 so->markNPageData = so->nPageData;
156 so->markCurPageData = so->curPageData;
157 if ( so->markNPageData > 0 )
158 memcpy( so->markPageData, so->pageData, sizeof(ItemResult) * so->markNPageData );
160 PG_RETURN_VOID();
163 Datum
164 gistrestrpos(PG_FUNCTION_ARGS)
166 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
167 GISTScanOpaque so;
168 GISTSearchStack *o,
170 *tmp;
172 so = (GISTScanOpaque) scan->opaque;
173 so->curpos = so->markpos;
174 if (so->flags & GS_MRKBEFORE)
175 so->flags |= GS_CURBEFORE;
176 else
177 so->flags &= ~GS_CURBEFORE;
179 o = NULL;
180 n = so->markstk;
182 /* copy the parent stack from the current item data */
183 while (n != NULL)
185 tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
186 tmp->lsn = n->lsn;
187 tmp->parentlsn = n->parentlsn;
188 tmp->block = n->block;
189 tmp->next = o;
190 o = tmp;
191 n = n->next;
194 gistfreestack(so->stack);
195 so->stack = o;
197 /* Update curbuf: be sure to bump ref count on markbuf */
198 if (BufferIsValid(so->curbuf))
200 ReleaseBuffer(so->curbuf);
201 so->curbuf = InvalidBuffer;
203 if (BufferIsValid(so->markbuf))
205 IncrBufferRefCount(so->markbuf);
206 so->curbuf = so->markbuf;
209 so->nPageData = so->markNPageData;
210 so->curPageData = so->markNPageData;
211 if ( so->markNPageData > 0 )
212 memcpy( so->pageData, so->markPageData, sizeof(ItemResult) * so->markNPageData );
214 PG_RETURN_VOID();
217 Datum
218 gistendscan(PG_FUNCTION_ARGS)
220 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
221 GISTScanOpaque so;
223 so = (GISTScanOpaque) scan->opaque;
225 if (so != NULL)
227 gistfreestack(so->stack);
228 gistfreestack(so->markstk);
229 if (so->giststate != NULL)
230 freeGISTstate(so->giststate);
231 /* drop pins on buffers -- we aren't holding any locks */
232 if (BufferIsValid(so->curbuf))
233 ReleaseBuffer(so->curbuf);
234 if (BufferIsValid(so->markbuf))
235 ReleaseBuffer(so->markbuf);
236 MemoryContextDelete(so->tempCxt);
237 pfree(scan->opaque);
240 PG_RETURN_VOID();
243 static void
244 gistfreestack(GISTSearchStack *s)
246 while (s != NULL)
248 GISTSearchStack *p = s->next;
250 pfree(s);
251 s = p;