@@ -276,39 +276,63 @@ btgettuple(PG_FUNCTION_ARGS)
276
276
scan -> xs_recheck = false;
277
277
278
278
/*
279
- * If we've already initialized this scan, we can just advance it in the
280
- * appropriate direction . If we haven 't done so yet, we call a routine to
281
- * get the first item in the scan .
279
+ * If we have any array keys, initialize them during first call for a
280
+ * scan . We can 't do this in btrescan because we don't know the scan
281
+ * direction at that time .
282
282
*/
283
- if (BTScanPosIsValid (so -> currPos ))
283
+ if (so -> numArrayKeys && !BTScanPosIsValid (so -> currPos ))
284
+ {
285
+ /* punt if we have any unsatisfiable array keys */
286
+ if (so -> numArrayKeys < 0 )
287
+ PG_RETURN_BOOL (false);
288
+
289
+ _bt_start_array_keys (scan , dir );
290
+ }
291
+
292
+ /* This loop handles advancing to the next array elements, if any */
293
+ do
284
294
{
285
295
/*
286
- * Check to see if we should kill the previously-fetched tuple.
296
+ * If we've already initialized this scan, we can just advance it in
297
+ * the appropriate direction. If we haven't done so yet, we call
298
+ * _bt_first() to get the first item in the scan.
287
299
*/
288
- if (scan -> kill_prior_tuple )
300
+ if (!BTScanPosIsValid (so -> currPos ))
301
+ res = _bt_first (scan , dir );
302
+ else
289
303
{
290
304
/*
291
- * Yes, remember it for later. (We'll deal with all such tuples
292
- * at once right before leaving the index page.) The test for
293
- * numKilled overrun is not just paranoia: if the caller reverses
294
- * direction in the indexscan then the same item might get entered
295
- * multiple times. It's not worth trying to optimize that, so we
296
- * don't detect it, but instead just forget any excess entries.
305
+ * Check to see if we should kill the previously-fetched tuple.
297
306
*/
298
- if (so -> killedItems == NULL )
299
- so -> killedItems = (int * )
300
- palloc (MaxIndexTuplesPerPage * sizeof (int ));
301
- if (so -> numKilled < MaxIndexTuplesPerPage )
302
- so -> killedItems [so -> numKilled ++ ] = so -> currPos .itemIndex ;
307
+ if (scan -> kill_prior_tuple )
308
+ {
309
+ /*
310
+ * Yes, remember it for later. (We'll deal with all such
311
+ * tuples at once right before leaving the index page.) The
312
+ * test for numKilled overrun is not just paranoia: if the
313
+ * caller reverses direction in the indexscan then the same
314
+ * item might get entered multiple times. It's not worth
315
+ * trying to optimize that, so we don't detect it, but instead
316
+ * just forget any excess entries.
317
+ */
318
+ if (so -> killedItems == NULL )
319
+ so -> killedItems = (int * )
320
+ palloc (MaxIndexTuplesPerPage * sizeof (int ));
321
+ if (so -> numKilled < MaxIndexTuplesPerPage )
322
+ so -> killedItems [so -> numKilled ++ ] = so -> currPos .itemIndex ;
323
+ }
324
+
325
+ /*
326
+ * Now continue the scan.
327
+ */
328
+ res = _bt_next (scan , dir );
303
329
}
304
330
305
- /*
306
- * Now continue the scan.
307
- */
308
- res = _bt_next (scan , dir );
309
- }
310
- else
311
- res = _bt_first (scan , dir );
331
+ /* If we have a tuple, return it ... */
332
+ if (res )
333
+ break ;
334
+ /* ... otherwise see if we have more array keys to deal with */
335
+ } while (so -> numArrayKeys && _bt_advance_array_keys (scan , dir ));
312
336
313
337
PG_RETURN_BOOL (res );
314
338
}
@@ -325,35 +349,50 @@ btgetbitmap(PG_FUNCTION_ARGS)
325
349
int64 ntids = 0 ;
326
350
ItemPointer heapTid ;
327
351
328
- /* Fetch the first page & tuple. */
329
- if (!_bt_first (scan , ForwardScanDirection ))
352
+ /*
353
+ * If we have any array keys, initialize them.
354
+ */
355
+ if (so -> numArrayKeys )
330
356
{
331
- /* empty scan */
332
- PG_RETURN_INT64 (0 );
357
+ /* punt if we have any unsatisfiable array keys */
358
+ if (so -> numArrayKeys < 0 )
359
+ PG_RETURN_INT64 (ntids );
360
+
361
+ _bt_start_array_keys (scan , ForwardScanDirection );
333
362
}
334
- /* Save tuple ID, and continue scanning */
335
- heapTid = & scan -> xs_ctup .t_self ;
336
- tbm_add_tuples (tbm , heapTid , 1 , false);
337
- ntids ++ ;
338
363
339
- for (;;)
364
+ /* This loop handles advancing to the next array elements, if any */
365
+ do
340
366
{
341
- /*
342
- * Advance to next tuple within page. This is the same as the easy
343
- * case in _bt_next().
344
- */
345
- if (++ so -> currPos .itemIndex > so -> currPos .lastItem )
367
+ /* Fetch the first page & tuple */
368
+ if (_bt_first (scan , ForwardScanDirection ))
346
369
{
347
- /* let _bt_next do the heavy lifting */
348
- if (! _bt_next ( scan , ForwardScanDirection ))
349
- break ;
350
- }
370
+ /* Save tuple ID, and continue scanning */
371
+ heapTid = & scan -> xs_ctup . t_self ;
372
+ tbm_add_tuples ( tbm , heapTid , 1 , false) ;
373
+ ntids ++ ;
351
374
352
- /* Save tuple ID, and continue scanning */
353
- heapTid = & so -> currPos .items [so -> currPos .itemIndex ].heapTid ;
354
- tbm_add_tuples (tbm , heapTid , 1 , false);
355
- ntids ++ ;
356
- }
375
+ for (;;)
376
+ {
377
+ /*
378
+ * Advance to next tuple within page. This is the same as the
379
+ * easy case in _bt_next().
380
+ */
381
+ if (++ so -> currPos .itemIndex > so -> currPos .lastItem )
382
+ {
383
+ /* let _bt_next do the heavy lifting */
384
+ if (!_bt_next (scan , ForwardScanDirection ))
385
+ break ;
386
+ }
387
+
388
+ /* Save tuple ID, and continue scanning */
389
+ heapTid = & so -> currPos .items [so -> currPos .itemIndex ].heapTid ;
390
+ tbm_add_tuples (tbm , heapTid , 1 , false);
391
+ ntids ++ ;
392
+ }
393
+ }
394
+ /* Now see if we have more array keys to deal with */
395
+ } while (so -> numArrayKeys && _bt_advance_array_keys (scan , ForwardScanDirection ));
357
396
358
397
PG_RETURN_INT64 (ntids );
359
398
}
@@ -383,6 +422,12 @@ btbeginscan(PG_FUNCTION_ARGS)
383
422
so -> keyData = (ScanKey ) palloc (scan -> numberOfKeys * sizeof (ScanKeyData ));
384
423
else
385
424
so -> keyData = NULL ;
425
+
426
+ so -> arrayKeyData = NULL ; /* assume no array keys for now */
427
+ so -> numArrayKeys = 0 ;
428
+ so -> arrayKeys = NULL ;
429
+ so -> arrayContext = NULL ;
430
+
386
431
so -> killedItems = NULL ; /* until needed */
387
432
so -> numKilled = 0 ;
388
433
@@ -460,6 +505,9 @@ btrescan(PG_FUNCTION_ARGS)
460
505
scan -> numberOfKeys * sizeof (ScanKeyData ));
461
506
so -> numberOfKeys = 0 ; /* until _bt_preprocess_keys sets it */
462
507
508
+ /* If any keys are SK_SEARCHARRAY type, set up array-key info */
509
+ _bt_preprocess_array_keys (scan );
510
+
463
511
PG_RETURN_VOID ();
464
512
}
465
513
@@ -490,10 +538,13 @@ btendscan(PG_FUNCTION_ARGS)
490
538
so -> markItemIndex = -1 ;
491
539
492
540
/* Release storage */
493
- if (so -> killedItems != NULL )
494
- pfree (so -> killedItems );
495
541
if (so -> keyData != NULL )
496
542
pfree (so -> keyData );
543
+ /* so->arrayKeyData and so->arrayKeys are in arrayContext */
544
+ if (so -> arrayContext != NULL )
545
+ MemoryContextDelete (so -> arrayContext );
546
+ if (so -> killedItems != NULL )
547
+ pfree (so -> killedItems );
497
548
if (so -> currTuples != NULL )
498
549
pfree (so -> currTuples );
499
550
/* so->markTuples should not be pfree'd, see btrescan */
0 commit comments