1 /*-------------------------------------------------------------------------
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
13 *-------------------------------------------------------------------------
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
);
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);
34 scan
= RelationGetIndexScan(r
, nkeys
, key
);
36 PG_RETURN_POINTER(scan
);
40 gistrescan(PG_FUNCTION_ARGS
)
42 IndexScanDesc scan
= (IndexScanDesc
) PG_GETARG_POINTER(0);
43 ScanKey key
= (ScanKey
) PG_GETARG_POINTER(1);
47 so
= (GISTScanOpaque
) scan
->opaque
;
50 /* rescan an existing indexscan --- reset state */
51 gistfreestack(so
->stack
);
52 gistfreestack(so
->markstk
);
53 so
->stack
= so
->markstk
= NULL
;
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
;
70 /* initialize opaque data */
71 so
= (GISTScanOpaque
) palloc(sizeof(GISTScanOpaqueData
));
72 so
->stack
= so
->markstk
= NULL
;
74 so
->tempCxt
= createTempGistContext();
75 so
->curbuf
= so
->markbuf
= InvalidBuffer
;
76 so
->giststate
= (GISTSTATE
*) palloc(sizeof(GISTSTATE
));
77 initGISTstate(so
->giststate
, scan
->indexRelation
);
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
102 for (i
= 0; i
< scan
->numberOfKeys
; i
++)
103 scan
->keyData
[i
].sk_func
= so
->giststate
->consistentFn
[scan
->keyData
[i
].sk_attno
- 1];
110 gistmarkpos(PG_FUNCTION_ARGS
)
112 IndexScanDesc scan
= (IndexScanDesc
) PG_GETARG_POINTER(0);
118 so
= (GISTScanOpaque
) scan
->opaque
;
119 so
->markpos
= so
->curpos
;
120 if (so
->flags
& GS_CURBEFORE
)
121 so
->flags
|= GS_MRKBEFORE
;
123 so
->flags
&= ~GS_MRKBEFORE
;
128 /* copy the parent stack from the current item data */
131 tmp
= (GISTSearchStack
*) palloc(sizeof(GISTSearchStack
));
133 tmp
->parentlsn
= n
->parentlsn
;
134 tmp
->block
= n
->block
;
140 gistfreestack(so
->markstk
);
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
);
164 gistrestrpos(PG_FUNCTION_ARGS
)
166 IndexScanDesc scan
= (IndexScanDesc
) PG_GETARG_POINTER(0);
172 so
= (GISTScanOpaque
) scan
->opaque
;
173 so
->curpos
= so
->markpos
;
174 if (so
->flags
& GS_MRKBEFORE
)
175 so
->flags
|= GS_CURBEFORE
;
177 so
->flags
&= ~GS_CURBEFORE
;
182 /* copy the parent stack from the current item data */
185 tmp
= (GISTSearchStack
*) palloc(sizeof(GISTSearchStack
));
187 tmp
->parentlsn
= n
->parentlsn
;
188 tmp
->block
= n
->block
;
194 gistfreestack(so
->stack
);
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
);
218 gistendscan(PG_FUNCTION_ARGS
)
220 IndexScanDesc scan
= (IndexScanDesc
) PG_GETARG_POINTER(0);
223 so
= (GISTScanOpaque
) scan
->opaque
;
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
);
244 gistfreestack(GISTSearchStack
*s
)
248 GISTSearchStack
*p
= s
->next
;