@@ -276,39 +276,63 @@ btgettuple(PG_FUNCTION_ARGS)
276276 scan -> xs_recheck = false;
277277
278278 /*
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 .
282282 */
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
284294 {
285295 /*
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.
287299 */
288- if (scan -> kill_prior_tuple )
300+ if (!BTScanPosIsValid (so -> currPos ))
301+ res = _bt_first (scan , dir );
302+ else
289303 {
290304 /*
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.
297306 */
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 );
303329 }
304330
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 ));
312336
313337 PG_RETURN_BOOL (res );
314338}
@@ -325,35 +349,50 @@ btgetbitmap(PG_FUNCTION_ARGS)
325349 int64 ntids = 0 ;
326350 ItemPointer heapTid ;
327351
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 )
330356 {
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 );
333362 }
334- /* Save tuple ID, and continue scanning */
335- heapTid = & scan -> xs_ctup .t_self ;
336- tbm_add_tuples (tbm , heapTid , 1 , false);
337- ntids ++ ;
338363
339- for (;;)
364+ /* This loop handles advancing to the next array elements, if any */
365+ do
340366 {
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 ))
346369 {
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 ++ ;
351374
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 ));
357396
358397 PG_RETURN_INT64 (ntids );
359398}
@@ -383,6 +422,12 @@ btbeginscan(PG_FUNCTION_ARGS)
383422 so -> keyData = (ScanKey ) palloc (scan -> numberOfKeys * sizeof (ScanKeyData ));
384423 else
385424 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+
386431 so -> killedItems = NULL ; /* until needed */
387432 so -> numKilled = 0 ;
388433
@@ -460,6 +505,9 @@ btrescan(PG_FUNCTION_ARGS)
460505 scan -> numberOfKeys * sizeof (ScanKeyData ));
461506 so -> numberOfKeys = 0 ; /* until _bt_preprocess_keys sets it */
462507
508+ /* If any keys are SK_SEARCHARRAY type, set up array-key info */
509+ _bt_preprocess_array_keys (scan );
510+
463511 PG_RETURN_VOID ();
464512}
465513
@@ -490,10 +538,13 @@ btendscan(PG_FUNCTION_ARGS)
490538 so -> markItemIndex = -1 ;
491539
492540 /* Release storage */
493- if (so -> killedItems != NULL )
494- pfree (so -> killedItems );
495541 if (so -> keyData != NULL )
496542 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 );
497548 if (so -> currTuples != NULL )
498549 pfree (so -> currTuples );
499550 /* so->markTuples should not be pfree'd, see btrescan */
0 commit comments