PostgreSQL Source Code git master
Loading...
Searching...
No Matches
gistscan.h File Reference
#include "access/amapi.h"
Include dependency graph for gistscan.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

IndexScanDesc gistbeginscan (Relation r, int nkeys, int norderbys)
 
void gistrescan (IndexScanDesc scan, ScanKey key, int nkeys, ScanKey orderbys, int norderbys)
 
void gistendscan (IndexScanDesc scan)
 

Function Documentation

◆ gistbeginscan()

IndexScanDesc gistbeginscan ( Relation  r,
int  nkeys,
int  norderbys 
)
extern

Definition at line 74 of file gistscan.c.

75{
76 IndexScanDesc scan;
77 GISTSTATE *giststate;
80
81 scan = RelationGetIndexScan(r, nkeys, norderbys);
82
83 /* First, set up a GISTSTATE with a scan-lifespan memory context */
84 giststate = initGISTstate(scan->indexRelation);
85
86 /*
87 * Everything made below is in the scanCxt, or is a child of the scanCxt,
88 * so it'll all go away automatically in gistendscan.
89 */
91
92 /* initialize opaque data */
94 so->giststate = giststate;
95 giststate->tempCxt = createTempGistContext();
96 so->queue = NULL;
97 so->queueCxt = giststate->scanCxt; /* see gistrescan */
98
99 /* workspaces with size dependent on numberOfOrderBys: */
100 so->distances = palloc(sizeof(so->distances[0]) * scan->numberOfOrderBys);
101 so->qual_ok = true; /* in case there are zero keys */
102 if (scan->numberOfOrderBys > 0)
103 {
105 scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
106 memset(scan->xs_orderbynulls, true, sizeof(bool) * scan->numberOfOrderBys);
107 }
108
109 so->killedItems = NULL; /* until needed */
110 so->numKilled = 0;
111 so->curBlkno = InvalidBlockNumber;
112 so->curPageLSN = InvalidXLogRecPtr;
113
114 scan->opaque = so;
115
116 /*
117 * All fields required for index-only scans are initialized in gistrescan,
118 * as we don't know yet if we're doing an index-only scan or not.
119 */
120
122
123 return scan;
124}
#define InvalidBlockNumber
Definition block.h:33
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define palloc0_object(type)
Definition fe_memutils.h:75
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition genam.c:80
GISTSTATE * initGISTstate(Relation index)
Definition gist.c:1537
MemoryContext createTempGistContext(void)
Definition gist.c:129
void * palloc(Size size)
Definition mcxt.c:1387
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
MemoryContext tempCxt
MemoryContext scanCxt
bool * xs_orderbynulls
Definition relscan.h:188
Relation indexRelation
Definition relscan.h:138
Datum * xs_orderbyvals
Definition relscan.h:187
#define InvalidXLogRecPtr
Definition xlogdefs.h:28

References createTempGistContext(), fb(), IndexScanDescData::indexRelation, initGISTstate(), InvalidBlockNumber, InvalidXLogRecPtr, MemoryContextSwitchTo(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, palloc(), palloc0_array, palloc0_object, palloc_array, RelationGetIndexScan(), GISTSTATE::scanCxt, GISTSTATE::tempCxt, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by gisthandler().

◆ gistendscan()

void gistendscan ( IndexScanDesc  scan)
extern

Definition at line 348 of file gistscan.c.

349{
351
352 /*
353 * freeGISTstate is enough to clean up everything made by gistbeginscan,
354 * as well as the queueCxt if there is a separate context for it.
355 */
356 freeGISTstate(so->giststate);
357}
void freeGISTstate(GISTSTATE *giststate)
Definition gist.c:1664
GISTScanOpaqueData * GISTScanOpaque

References fb(), freeGISTstate(), and IndexScanDescData::opaque.

Referenced by gisthandler().

◆ gistrescan()

void gistrescan ( IndexScanDesc  scan,
ScanKey  key,
int  nkeys,
ScanKey  orderbys,
int  norderbys 
)
extern

Definition at line 127 of file gistscan.c.

129{
130 /* nkeys and norderbys arguments are ignored */
132 bool first_time;
133 int i;
135
136 /* rescan an existing indexscan --- reset state */
137
138 /*
139 * The first time through, we create the search queue in the scanCxt.
140 * Subsequent times through, we create the queue in a separate queueCxt,
141 * which is created on the second call and reset on later calls. Thus, in
142 * the common case where a scan is only rescan'd once, we just put the
143 * queue in scanCxt and don't pay the overhead of making a second memory
144 * context. If we do rescan more than once, the first queue is just left
145 * for dead until end of scan; this small wastage seems worth the savings
146 * in the common case.
147 */
148 if (so->queue == NULL)
149 {
150 /* first time through */
151 Assert(so->queueCxt == so->giststate->scanCxt);
152 first_time = true;
153 }
154 else if (so->queueCxt == so->giststate->scanCxt)
155 {
156 /* second time through */
157 so->queueCxt = AllocSetContextCreate(so->giststate->scanCxt,
158 "GiST queue context",
160 first_time = false;
161 }
162 else
163 {
164 /* third or later time through */
165 MemoryContextReset(so->queueCxt);
166 first_time = false;
167 }
168
169 /*
170 * If we're doing an index-only scan, on the first call, also initialize a
171 * tuple descriptor to represent the returned index tuples and create a
172 * memory context to hold them during the scan.
173 */
174 if (scan->xs_want_itup && !scan->xs_hitupdesc)
175 {
176 int natts;
177 int nkeyatts;
178 int attno;
179
180 /*
181 * The storage type of the index can be different from the original
182 * datatype being indexed, so we cannot just grab the index's tuple
183 * descriptor. Instead, construct a descriptor with the original data
184 * types.
185 */
188 so->giststate->fetchTupdesc = CreateTemplateTupleDesc(natts);
189 for (attno = 1; attno <= nkeyatts; attno++)
190 {
191 TupleDescInitEntry(so->giststate->fetchTupdesc, attno, NULL,
192 scan->indexRelation->rd_opcintype[attno - 1],
193 -1, 0);
194 }
195
196 for (; attno <= natts; attno++)
197 {
198 /* taking opcintype from giststate->tupdesc */
199 TupleDescInitEntry(so->giststate->fetchTupdesc, attno, NULL,
200 TupleDescAttr(so->giststate->leafTupdesc,
201 attno - 1)->atttypid,
202 -1, 0);
203 }
204 TupleDescFinalize(so->giststate->fetchTupdesc);
205 scan->xs_hitupdesc = so->giststate->fetchTupdesc;
206
207 /* Also create a memory context that will hold the returned tuples */
208 so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
209 "GiST page data context",
211 }
212
213 /* create new, empty pairing heap for search queue */
214 oldCxt = MemoryContextSwitchTo(so->queueCxt);
217
218 so->firstCall = true;
219
220 /* Update scan key, if a new one is given */
221 if (key && scan->numberOfKeys > 0)
222 {
223 void **fn_extras = NULL;
224
225 /*
226 * If this isn't the first time through, preserve the fn_extra
227 * pointers, so that if the consistentFns are using them to cache
228 * data, that data is not leaked across a rescan.
229 */
230 if (!first_time)
231 {
232 fn_extras = (void **) palloc(scan->numberOfKeys * sizeof(void *));
233 for (i = 0; i < scan->numberOfKeys; i++)
235 }
236
237 memcpy(scan->keyData, key, scan->numberOfKeys * sizeof(ScanKeyData));
238
239 /*
240 * Modify the scan key so that the Consistent method is called for all
241 * comparisons. The original operator is passed to the Consistent
242 * function in the form of its strategy number, which is available
243 * from the sk_strategy field, and its subtype from the sk_subtype
244 * field.
245 *
246 * Next, if any of keys is a NULL and that key is not marked with
247 * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
248 * assume all indexable operators are strict).
249 */
250 so->qual_ok = true;
251
252 for (i = 0; i < scan->numberOfKeys; i++)
253 {
254 ScanKey skey = scan->keyData + i;
255
256 /*
257 * Copy consistent support function to ScanKey structure instead
258 * of function implementing filtering operator.
259 */
260 fmgr_info_copy(&(skey->sk_func),
261 &(so->giststate->consistentFn[skey->sk_attno - 1]),
262 so->giststate->scanCxt);
263
264 /* Restore prior fn_extra pointers, if not first time */
265 if (!first_time)
266 skey->sk_func.fn_extra = fn_extras[i];
267
268 if (skey->sk_flags & SK_ISNULL)
269 {
270 if (!(skey->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)))
271 so->qual_ok = false;
272 }
273 }
274
275 if (!first_time)
277 }
278
279 /* Update order-by key, if a new one is given */
280 if (orderbys && scan->numberOfOrderBys > 0)
281 {
282 void **fn_extras = NULL;
283
284 /* As above, preserve fn_extra if not first time through */
285 if (!first_time)
286 {
287 fn_extras = (void **) palloc(scan->numberOfOrderBys * sizeof(void *));
288 for (i = 0; i < scan->numberOfOrderBys; i++)
290 }
291
292 memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData));
293
294 so->orderByTypes = (Oid *) palloc(scan->numberOfOrderBys * sizeof(Oid));
295
296 /*
297 * Modify the order-by key so that the Distance method is called for
298 * all comparisons. The original operator is passed to the Distance
299 * function in the form of its strategy number, which is available
300 * from the sk_strategy field, and its subtype from the sk_subtype
301 * field.
302 */
303 for (i = 0; i < scan->numberOfOrderBys; i++)
304 {
305 ScanKey skey = scan->orderByData + i;
306 FmgrInfo *finfo = &(so->giststate->distanceFn[skey->sk_attno - 1]);
307
308 /* Check we actually have a distance function ... */
309 if (!OidIsValid(finfo->fn_oid))
310 elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
311 GIST_DISTANCE_PROC, skey->sk_attno,
313
314 /*
315 * Look up the datatype returned by the original ordering
316 * operator. GiST always uses a float8 for the distance function,
317 * but the ordering operator could be anything else.
318 *
319 * XXX: The distance function is only allowed to be lossy if the
320 * ordering operator's result type is float4 or float8. Otherwise
321 * we don't know how to return the distance to the executor. But
322 * we cannot check that here, as we won't know if the distance
323 * function is lossy until it returns *recheck = true for the
324 * first time.
325 */
326 so->orderByTypes[i] = get_func_rettype(skey->sk_func.fn_oid);
327
328 /*
329 * Copy distance support function to ScanKey structure instead of
330 * function implementing ordering operator.
331 */
332 fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
333
334 /* Restore prior fn_extra pointers, if not first time */
335 if (!first_time)
336 skey->sk_func.fn_extra = fn_extras[i];
337 }
338
339 if (!first_time)
341 }
342
343 /* any previous xs_hitup will have been pfree'd in context resets above */
344 scan->xs_hitup = NULL;
345}
#define Assert(condition)
Definition c.h:945
#define OidIsValid(objectId)
Definition c.h:860
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition fmgr.c:582
#define GIST_DISTANCE_PROC
Definition gist.h:39
static int pairingheap_GISTSearchItem_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Definition gistscan.c:30
int i
Definition isn.c:77
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1875
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void pfree(void *pointer)
Definition mcxt.c:1616
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition pairingheap.c:42
unsigned int Oid
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:520
#define RelationGetRelationName(relation)
Definition rel.h:548
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
#define SK_SEARCHNOTNULL
Definition skey.h:122
#define SK_SEARCHNULL
Definition skey.h:121
#define SK_ISNULL
Definition skey.h:115
void * fn_extra
Definition fmgr.h:64
Oid fn_oid
Definition fmgr.h:59
struct ScanKeyData * keyData
Definition relscan.h:142
struct ScanKeyData * orderByData
Definition relscan.h:143
HeapTuple xs_hitup
Definition relscan.h:170
struct TupleDescData * xs_hitupdesc
Definition relscan.h:171
Oid * rd_opcintype
Definition rel.h:208
FmgrInfo sk_func
Definition skey.h:71
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:508
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:897
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CreateTemplateTupleDesc(), elog, ERROR, fb(), fmgr_info_copy(), FmgrInfo::fn_extra, FmgrInfo::fn_oid, get_func_rettype(), GIST_DISTANCE_PROC, i, IndexScanDescData::indexRelation, IndexRelationGetNumberOfKeyAttributes, IndexScanDescData::keyData, MemoryContextReset(), MemoryContextSwitchTo(), IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, OidIsValid, IndexScanDescData::opaque, IndexScanDescData::orderByData, pairingheap_allocate(), pairingheap_GISTSearchItem_cmp(), palloc(), pfree(), RelationData::rd_opcintype, RelationGetNumberOfAttributes, RelationGetRelationName, ScanKeyData::sk_func, SK_ISNULL, SK_SEARCHNOTNULL, SK_SEARCHNULL, TupleDescAttr(), TupleDescFinalize(), TupleDescInitEntry(), IndexScanDescData::xs_hitup, IndexScanDescData::xs_hitupdesc, and IndexScanDescData::xs_want_itup.

Referenced by gisthandler().