@@ -276,39 +276,63 @@ btgettuple(PG_FUNCTION_ARGS)
276276scan -> 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 'tdone so yet, wecall 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 'tdo this in btrescan because wedon'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
313337PG_RETURN_BOOL (res );
314338}
@@ -325,35 +349,50 @@ btgetbitmap(PG_FUNCTION_ARGS)
325349int64 ntids = 0 ;
326350ItemPointer 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
358397PG_RETURN_INT64 (ntids );
359398}
@@ -383,6 +422,12 @@ btbeginscan(PG_FUNCTION_ARGS)
383422so -> keyData = (ScanKey )palloc (scan -> numberOfKeys * sizeof (ScanKeyData ));
384423else
385424so -> 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+
386431so -> killedItems = NULL ;/* until needed */
387432so -> numKilled = 0 ;
388433
@@ -460,6 +505,9 @@ btrescan(PG_FUNCTION_ARGS)
460505scan -> numberOfKeys * sizeof (ScanKeyData ));
461506so -> 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+
463511PG_RETURN_VOID ();
464512}
465513
@@ -490,10 +538,13 @@ btendscan(PG_FUNCTION_ARGS)
490538so -> markItemIndex = -1 ;
491539
492540/* Release storage */
493- if (so -> killedItems != NULL )
494- pfree (so -> killedItems );
495541if (so -> keyData != NULL )
496542pfree (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 );
497548if (so -> currTuples != NULL )
498549pfree (so -> currTuples );
499550/* so->markTuples should not be pfree'd, see btrescan */