129{
130 /* nkeys and norderbys arguments are ignored */
132 bool first_time;
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 */
149 {
150 /* first time through */
152 first_time = true;
153 }
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 */
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 {
193 -1, 0);
194 }
195
196 for (; attno <= natts; attno++)
197 {
198 /* taking opcintype from giststate->tupdesc */
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 */
216
218
219 /* Update scan key, if a new one is given */
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 {
234 }
235
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 */
250
252 {
254
255 /*
256 * Copy consistent support function to ScanKey structure instead
257 * of function implementing filtering operator.
258 */
262
263 /* Restore prior fn_extra pointers, if not first time */
264 if (!first_time)
266
268 {
271 }
272 }
273
274 if (!first_time)
276 }
277
278 /* Update order-by key, if a new one is given */
280 {
281 void **fn_extras = NULL;
282
283 /* As above, preserve fn_extra if not first time through */
284 if (!first_time)
285 {
289 }
290
292
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 */
303 {
306
307 /* Check we actually have a distance function ... */
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 */
332
333 /* Restore prior fn_extra pointers, if not first time */
334 if (!first_time)
336 }
337
338 if (!first_time)
340 }
341
342 /* any previous xs_hitup will have been pfree'd in context resets above */
344}
#define OidIsValid(objectId)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define GIST_DISTANCE_PROC
static int pairingheap_GISTSearchItem_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
Oid get_func_rettype(Oid funcid)
void MemoryContextReset(MemoryContext context)
void pfree(void *pointer)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
#define RelationGetNumberOfAttributes(relation)
#define RelationGetRelationName(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
FmgrInfo distanceFn[INDEX_MAX_KEYS]
FmgrInfo consistentFn[INDEX_MAX_KEYS]
MemoryContext pageDataCxt
struct ScanKeyData * keyData
struct ScanKeyData * orderByData
struct TupleDescData * xs_hitupdesc
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)