PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
)

Definition at line 74 of file gistscan.c.

75{
76 IndexScanDesc scan;
77 GISTSTATE *giststate;
79 MemoryContext oldCxt;
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 */
90 oldCxt = MemoryContextSwitchTo(giststate->scanCxt);
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 {
104 scan->xs_orderbyvals = palloc0(sizeof(Datum) * scan->numberOfOrderBys);
105 scan->xs_orderbynulls = palloc(sizeof(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;
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
121 MemoryContextSwitchTo(oldCxt);
122
123 return scan;
124}
#define InvalidBlockNumber
Definition: block.h:33
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
GISTSTATE * initGISTstate(Relation index)
Definition: gist.c:1525
MemoryContext createTempGistContext(void)
Definition: gist.c:123
GISTScanOpaqueData * GISTScanOpaque
Definition: gist_private.h:181
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
uintptr_t Datum
Definition: postgres.h:69
MemoryContext tempCxt
Definition: gist_private.h:78
MemoryContext scanCxt
Definition: gist_private.h:77
OffsetNumber * killedItems
Definition: gist_private.h:168
pairingheap * queue
Definition: gist_private.h:159
GISTSTATE * giststate
Definition: gist_private.h:156
MemoryContext queueCxt
Definition: gist_private.h:160
IndexOrderByDistance * distances
Definition: gist_private.h:165
BlockNumber curBlkno
Definition: gist_private.h:170
bool * xs_orderbynulls
Definition: relscan.h:179
int numberOfOrderBys
Definition: relscan.h:138
Relation indexRelation
Definition: relscan.h:135
Datum * xs_orderbyvals
Definition: relscan.h:178
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References createTempGistContext(), GISTScanOpaqueData::curBlkno, GISTScanOpaqueData::curPageLSN, GISTScanOpaqueData::distances, GISTScanOpaqueData::giststate, IndexScanDescData::indexRelation, initGISTstate(), InvalidBlockNumber, InvalidXLogRecPtr, GISTScanOpaqueData::killedItems, MemoryContextSwitchTo(), IndexScanDescData::numberOfOrderBys, GISTScanOpaqueData::numKilled, IndexScanDescData::opaque, palloc(), palloc0(), GISTScanOpaqueData::qual_ok, GISTScanOpaqueData::queue, GISTScanOpaqueData::queueCxt, RelationGetIndexScan(), GISTSTATE::scanCxt, GISTSTATE::tempCxt, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by gisthandler().

◆ gistendscan()

void gistendscan ( IndexScanDesc  scan)

Definition at line 347 of file gistscan.c.

348{
350
351 /*
352 * freeGISTstate is enough to clean up everything made by gistbeginscan,
353 * as well as the queueCxt if there is a separate context for it.
354 */
356}
void freeGISTstate(GISTSTATE *giststate)
Definition: gist.c:1652

References freeGISTstate(), GISTScanOpaqueData::giststate, and IndexScanDescData::opaque.

Referenced by gisthandler().

◆ gistrescan()

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

Definition at line 127 of file gistscan.c.

129{
130 /* nkeys and norderbys arguments are ignored */
132 bool first_time;
133 int i;
134 MemoryContext oldCxt;
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 */
158 "GiST queue context",
160 first_time = false;
161 }
162 else
163 {
164 /* third or later time through */
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 */
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,
201 attno - 1)->atttypid,
202 -1, 0);
203 }
205
206 /* Also create a memory context that will hold the returned tuples */
208 "GiST page data context",
210 }
211
212 /* create new, empty pairing heap for search queue */
213 oldCxt = MemoryContextSwitchTo(so->queueCxt);
215 MemoryContextSwitchTo(oldCxt);
216
217 so->firstCall = true;
218
219 /* Update scan key, if a new one is given */
220 if (key && scan->numberOfKeys > 0)
221 {
222 void **fn_extras = NULL;
223
224 /*
225 * If this isn't the first time through, preserve the fn_extra
226 * pointers, so that if the consistentFns are using them to cache
227 * data, that data is not leaked across a rescan.
228 */
229 if (!first_time)
230 {
231 fn_extras = (void **) palloc(scan->numberOfKeys * sizeof(void *));
232 for (i = 0; i < scan->numberOfKeys; i++)
233 fn_extras[i] = scan->keyData[i].sk_func.fn_extra;
234 }
235
236 memcpy(scan->keyData, key, scan->numberOfKeys * sizeof(ScanKeyData));
237
238 /*
239 * Modify the scan key so that the Consistent method is called for all
240 * comparisons. The original operator is passed to the Consistent
241 * function in the form of its strategy number, which is available
242 * from the sk_strategy field, and its subtype from the sk_subtype
243 * field.
244 *
245 * Next, if any of keys is a NULL and that key is not marked with
246 * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
247 * assume all indexable operators are strict).
248 */
249 so->qual_ok = true;
250
251 for (i = 0; i < scan->numberOfKeys; i++)
252 {
253 ScanKey skey = scan->keyData + i;
254
255 /*
256 * Copy consistent support function to ScanKey structure instead
257 * of function implementing filtering operator.
258 */
259 fmgr_info_copy(&(skey->sk_func),
260 &(so->giststate->consistentFn[skey->sk_attno - 1]),
261 so->giststate->scanCxt);
262
263 /* Restore prior fn_extra pointers, if not first time */
264 if (!first_time)
265 skey->sk_func.fn_extra = fn_extras[i];
266
267 if (skey->sk_flags & SK_ISNULL)
268 {
269 if (!(skey->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)))
270 so->qual_ok = false;
271 }
272 }
273
274 if (!first_time)
275 pfree(fn_extras);
276 }
277
278 /* Update order-by key, if a new one is given */
279 if (orderbys && scan->numberOfOrderBys > 0)
280 {
281 void **fn_extras = NULL;
282
283 /* As above, preserve fn_extra if not first time through */
284 if (!first_time)
285 {
286 fn_extras = (void **) palloc(scan->numberOfOrderBys * sizeof(void *));
287 for (i = 0; i < scan->numberOfOrderBys; i++)
288 fn_extras[i] = scan->orderByData[i].sk_func.fn_extra;
289 }
290
291 memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData));
292
293 so->orderByTypes = (Oid *) palloc(scan->numberOfOrderBys * sizeof(Oid));
294
295 /*
296 * Modify the order-by key so that the Distance method is called for
297 * all comparisons. The original operator is passed to the Distance
298 * function in the form of its strategy number, which is available
299 * from the sk_strategy field, and its subtype from the sk_subtype
300 * field.
301 */
302 for (i = 0; i < scan->numberOfOrderBys; i++)
303 {
304 ScanKey skey = scan->orderByData + i;
305 FmgrInfo *finfo = &(so->giststate->distanceFn[skey->sk_attno - 1]);
306
307 /* Check we actually have a distance function ... */
308 if (!OidIsValid(finfo->fn_oid))
309 elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
312
313 /*
314 * Look up the datatype returned by the original ordering
315 * operator. GiST always uses a float8 for the distance function,
316 * but the ordering operator could be anything else.
317 *
318 * XXX: The distance function is only allowed to be lossy if the
319 * ordering operator's result type is float4 or float8. Otherwise
320 * we don't know how to return the distance to the executor. But
321 * we cannot check that here, as we won't know if the distance
322 * function is lossy until it returns *recheck = true for the
323 * first time.
324 */
326
327 /*
328 * Copy distance support function to ScanKey structure instead of
329 * function implementing ordering operator.
330 */
331 fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
332
333 /* Restore prior fn_extra pointers, if not first time */
334 if (!first_time)
335 skey->sk_func.fn_extra = fn_extras[i];
336 }
337
338 if (!first_time)
339 pfree(fn_extras);
340 }
341
342 /* any previous xs_hitup will have been pfree'd in context resets above */
343 scan->xs_hitup = NULL;
344}
#define Assert(condition)
Definition: c.h:815
#define OidIsValid(objectId)
Definition: c.h:732
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:580
#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:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1655
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void pfree(void *pointer)
Definition: mcxt.c:1521
#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
Definition: postgres_ext.h:32
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:511
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:524
#define SK_SEARCHNOTNULL
Definition: skey.h:122
#define SK_SEARCHNULL
Definition: skey.h:121
#define SK_ISNULL
Definition: skey.h:115
Definition: fmgr.h:57
void * fn_extra
Definition: fmgr.h:64
Oid fn_oid
Definition: fmgr.h:59
TupleDesc leafTupdesc
Definition: gist_private.h:80
TupleDesc fetchTupdesc
Definition: gist_private.h:83
FmgrInfo distanceFn[INDEX_MAX_KEYS]
Definition: gist_private.h:93
FmgrInfo consistentFn[INDEX_MAX_KEYS]
Definition: gist_private.h:86
MemoryContext pageDataCxt
Definition: gist_private.h:177
struct ScanKeyData * keyData
Definition: relscan.h:139
struct ScanKeyData * orderByData
Definition: relscan.h:140
HeapTuple xs_hitup
Definition: relscan.h:161
struct TupleDescData * xs_hitupdesc
Definition: relscan.h:162
Oid * rd_opcintype
Definition: rel.h:208
int sk_flags
Definition: skey.h:66
FmgrInfo sk_func
Definition: skey.h:71
AttrNumber sk_attno
Definition: skey.h:67
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:164
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:798
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, GISTSTATE::consistentFn, CreateTemplateTupleDesc(), GISTSTATE::distanceFn, elog, ERROR, GISTSTATE::fetchTupdesc, GISTScanOpaqueData::firstCall, fmgr_info_copy(), FmgrInfo::fn_extra, FmgrInfo::fn_oid, get_func_rettype(), GIST_DISTANCE_PROC, GISTScanOpaqueData::giststate, i, if(), IndexScanDescData::indexRelation, IndexRelationGetNumberOfKeyAttributes, sort-test::key, IndexScanDescData::keyData, GISTSTATE::leafTupdesc, MemoryContextReset(), MemoryContextSwitchTo(), IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, OidIsValid, IndexScanDescData::opaque, IndexScanDescData::orderByData, GISTScanOpaqueData::orderByTypes, GISTScanOpaqueData::pageDataCxt, pairingheap_allocate(), pairingheap_GISTSearchItem_cmp(), palloc(), pfree(), GISTScanOpaqueData::qual_ok, GISTScanOpaqueData::queue, GISTScanOpaqueData::queueCxt, RelationData::rd_opcintype, RelationGetNumberOfAttributes, RelationGetRelationName, GISTSTATE::scanCxt, ScanKeyData::sk_attno, ScanKeyData::sk_flags, ScanKeyData::sk_func, SK_ISNULL, SK_SEARCHNOTNULL, SK_SEARCHNULL, TupleDescAttr(), TupleDescInitEntry(), IndexScanDescData::xs_hitup, IndexScanDescData::xs_hitupdesc, and IndexScanDescData::xs_want_itup.

Referenced by gisthandler().