1 : /*-------------------------------------------------------------------------
2 : *
3 : * gistscan.c
4 : * routines to manage scans on GiST index relations
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * IDENTIFICATION
11 : * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.67 2007/01/20 18:43:35 neilc Exp $
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/genam.h"
18 : #include "access/gist_private.h"
19 : #include "access/gistscan.h"
20 : #include "utils/memutils.h"
21 :
22 : static void gistfreestack(GISTSearchStack *s);
23 :
24 : Datum
25 : gistbeginscan(PG_FUNCTION_ARGS)
26 17 : {
27 17 : Relation r = (Relation) PG_GETARG_POINTER(0);
28 17 : int nkeys = PG_GETARG_INT32(1);
29 17 : ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
30 : IndexScanDesc scan;
31 :
32 17 : scan = RelationGetIndexScan(r, nkeys, key);
33 :
34 17 : PG_RETURN_POINTER(scan);
35 : }
36 :
37 : Datum
38 : gistrescan(PG_FUNCTION_ARGS)
39 17 : {
40 17 : IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
41 17 : ScanKey key = (ScanKey) PG_GETARG_POINTER(1);
42 : GISTScanOpaque so;
43 : int i;
44 :
45 17 : so = (GISTScanOpaque) scan->opaque;
46 17 : if (so != NULL)
47 : {
48 : /* rescan an existing indexscan --- reset state */
49 0 : gistfreestack(so->stack);
50 0 : gistfreestack(so->markstk);
51 0 : so->stack = so->markstk = NULL;
52 0 : so->flags = 0x0;
53 : /* drop pins on buffers -- no locks held */
54 0 : if (BufferIsValid(so->curbuf))
55 : {
56 0 : ReleaseBuffer(so->curbuf);
57 0 : so->curbuf = InvalidBuffer;
58 : }
59 0 : if (BufferIsValid(so->markbuf))
60 : {
61 0 : ReleaseBuffer(so->markbuf);
62 0 : so->markbuf = InvalidBuffer;
63 : }
64 : }
65 : else
66 : {
67 : /* initialize opaque data */
68 17 : so = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData));
69 17 : so->stack = so->markstk = NULL;
70 17 : so->flags = 0x0;
71 17 : so->tempCxt = createTempGistContext();
72 17 : so->curbuf = so->markbuf = InvalidBuffer;
73 17 : so->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
74 17 : initGISTstate(so->giststate, scan->indexRelation);
75 :
76 17 : scan->opaque = so;
77 : }
78 :
79 : /*
80 : * Clear all the pointers.
81 : */
82 17 : ItemPointerSetInvalid(&so->curpos);
83 17 : ItemPointerSetInvalid(&so->markpos);
84 :
85 : /* Update scan key, if a new one is given */
86 17 : if (key && scan->numberOfKeys > 0)
87 : {
88 17 : memmove(scan->keyData, key,
89 : scan->numberOfKeys * sizeof(ScanKeyData));
90 :
91 : /*
92 : * Modify the scan key so that all the Consistent method is called for
93 : * all comparisons. The original operator is passed to the Consistent
94 : * function in the form of its strategy number, which is available
95 : * from the sk_strategy field, and its subtype from the sk_subtype
96 : * field.
97 : */
98 34 : for (i = 0; i < scan->numberOfKeys; i++)
99 17 : scan->keyData[i].sk_func = so->giststate->consistentFn[scan->keyData[i].sk_attno - 1];
100 : }
101 :
102 17 : PG_RETURN_VOID();
103 : }
104 :
105 : Datum
106 : gistmarkpos(PG_FUNCTION_ARGS)
107 0 : {
108 0 : IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
109 : GISTScanOpaque so;
110 : GISTSearchStack *o,
111 : *n,
112 : *tmp;
113 :
114 0 : so = (GISTScanOpaque) scan->opaque;
115 0 : so->markpos = so->curpos;
116 0 : if (so->flags & GS_CURBEFORE)
117 0 : so->flags |= GS_MRKBEFORE;
118 : else
119 0 : so->flags &= ~GS_MRKBEFORE;
120 :
121 0 : o = NULL;
122 0 : n = so->stack;
123 :
124 : /* copy the parent stack from the current item data */
125 0 : while (n != NULL)
126 : {
127 0 : tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
128 0 : tmp->lsn = n->lsn;
129 0 : tmp->parentlsn = n->parentlsn;
130 0 : tmp->block = n->block;
131 0 : tmp->next = o;
132 0 : o = tmp;
133 0 : n = n->next;
134 : }
135 :
136 0 : gistfreestack(so->markstk);
137 0 : so->markstk = o;
138 :
139 : /* Update markbuf: make sure to bump ref count on curbuf */
140 0 : if (BufferIsValid(so->markbuf))
141 : {
142 0 : ReleaseBuffer(so->markbuf);
143 0 : so->markbuf = InvalidBuffer;
144 : }
145 0 : if (BufferIsValid(so->curbuf))
146 : {
147 0 : IncrBufferRefCount(so->curbuf);
148 0 : so->markbuf = so->curbuf;
149 : }
150 :
151 0 : PG_RETURN_VOID();
152 : }
153 :
154 : Datum
155 : gistrestrpos(PG_FUNCTION_ARGS)
156 0 : {
157 0 : IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
158 : GISTScanOpaque so;
159 : GISTSearchStack *o,
160 : *n,
161 : *tmp;
162 :
163 0 : so = (GISTScanOpaque) scan->opaque;
164 0 : so->curpos = so->markpos;
165 0 : if (so->flags & GS_MRKBEFORE)
166 0 : so->flags |= GS_CURBEFORE;
167 : else
168 0 : so->flags &= ~GS_CURBEFORE;
169 :
170 0 : o = NULL;
171 0 : n = so->markstk;
172 :
173 : /* copy the parent stack from the current item data */
174 0 : while (n != NULL)
175 : {
176 0 : tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
177 0 : tmp->lsn = n->lsn;
178 0 : tmp->parentlsn = n->parentlsn;
179 0 : tmp->block = n->block;
180 0 : tmp->next = o;
181 0 : o = tmp;
182 0 : n = n->next;
183 : }
184 :
185 0 : gistfreestack(so->stack);
186 0 : so->stack = o;
187 :
188 : /* Update curbuf: be sure to bump ref count on markbuf */
189 0 : if (BufferIsValid(so->curbuf))
190 : {
191 0 : ReleaseBuffer(so->curbuf);
192 0 : so->curbuf = InvalidBuffer;
193 : }
194 0 : if (BufferIsValid(so->markbuf))
195 : {
196 0 : IncrBufferRefCount(so->markbuf);
197 0 : so->curbuf = so->markbuf;
198 : }
199 :
200 0 : PG_RETURN_VOID();
201 : }
202 :
203 : Datum
204 : gistendscan(PG_FUNCTION_ARGS)
205 17 : {
206 17 : IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
207 : GISTScanOpaque so;
208 :
209 17 : so = (GISTScanOpaque) scan->opaque;
210 :
211 17 : if (so != NULL)
212 : {
213 17 : gistfreestack(so->stack);
214 17 : gistfreestack(so->markstk);
215 17 : if (so->giststate != NULL)
216 17 : freeGISTstate(so->giststate);
217 : /* drop pins on buffers -- we aren't holding any locks */
218 17 : if (BufferIsValid(so->curbuf))
219 0 : ReleaseBuffer(so->curbuf);
220 17 : if (BufferIsValid(so->markbuf))
221 0 : ReleaseBuffer(so->markbuf);
222 17 : MemoryContextDelete(so->tempCxt);
223 17 : pfree(scan->opaque);
224 : }
225 :
226 17 : PG_RETURN_VOID();
227 : }
228 :
229 : static void
230 : gistfreestack(GISTSearchStack *s)
231 34 : {
232 68 : while (s != NULL)
233 : {
234 0 : GISTSearchStack *p = s->next;
235 :
236 0 : pfree(s);
237 0 : s = p;
238 : }
239 34 : }
|