1818#include "access/relscan.h"
1919#include "miscadmin.h"
2020#include "pgstat.h"
21+ #include "lib/pairingheap.h"
2122#include "utils/builtins.h"
2223#include "utils/memutils.h"
2324#include "utils/rel.h"
@@ -243,8 +244,6 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
243244 GISTPageOpaque opaque ;
244245 OffsetNumber maxoff ;
245246 OffsetNumber i ;
246- GISTSearchTreeItem * tmpItem = so -> tmpTreeItem ;
247- bool isNew ;
248247 MemoryContext oldcxt ;
249248
250249 Assert (!GISTSearchItemIsHeap (* pageItem ));
@@ -275,18 +274,15 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
275274 oldcxt = MemoryContextSwitchTo (so -> queueCxt );
276275
277276 /* Create new GISTSearchItem for the right sibling index page */
278- item = palloc (sizeof (GISTSearchItem ));
279- item -> next = NULL ;
277+ item = palloc (SizeOfGISTSearchItem (scan -> numberOfOrderBys ));
280278 item -> blkno = opaque -> rightlink ;
281279 item -> data .parentlsn = pageItem -> data .parentlsn ;
282280
283281 /* Insert it into the queue using same distances as for this page */
284- tmpItem -> head = item ;
285- tmpItem -> lastHeap = NULL ;
286- memcpy (tmpItem -> distances , myDistances ,
282+ memcpy (item -> distances , myDistances ,
287283 sizeof (double ) * scan -> numberOfOrderBys );
288284
289- ( void ) rb_insert ( so -> queue , ( RBNode * ) tmpItem , & isNew );
285+ pairingheap_add ( so -> queue , & item -> phNode );
290286
291287 MemoryContextSwitchTo (oldcxt );
292288 }
@@ -348,8 +344,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
348344 oldcxt = MemoryContextSwitchTo (so -> queueCxt );
349345
350346 /* Create new GISTSearchItem for this item */
351- item = palloc (sizeof (GISTSearchItem ));
352- item -> next = NULL ;
347+ item = palloc (SizeOfGISTSearchItem (scan -> numberOfOrderBys ));
353348
354349 if (GistPageIsLeaf (page ))
355350 {
@@ -372,12 +367,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
372367 }
373368
374369 /* Insert it into the queue using new distance data */
375- tmpItem -> head = item ;
376- tmpItem -> lastHeap = GISTSearchItemIsHeap (* item ) ? item : NULL ;
377- memcpy (tmpItem -> distances , so -> distances ,
370+ memcpy (item -> distances , so -> distances ,
378371 sizeof (double ) * scan -> numberOfOrderBys );
379372
380- ( void ) rb_insert ( so -> queue , ( RBNode * ) tmpItem , & isNew );
373+ pairingheap_add ( so -> queue , & item -> phNode );
381374
382375 MemoryContextSwitchTo (oldcxt );
383376 }
@@ -390,44 +383,24 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
390383 * Extract next item (in order) from search queue
391384 *
392385 * Returns a GISTSearchItem or NULL. Caller must pfree item when done with it.
393- *
394- * NOTE: on successful return, so->curTreeItem is the GISTSearchTreeItem that
395- * contained the result item. Callers can use so->curTreeItem->distances as
396- * the distances value for the item.
397386 */
398387static GISTSearchItem *
399388getNextGISTSearchItem (GISTScanOpaque so )
400389{
401- for (;;)
402- {
403- GISTSearchItem * item ;
404-
405- /* Update curTreeItem if we don't have one */
406- if (so -> curTreeItem == NULL )
407- {
408- so -> curTreeItem = (GISTSearchTreeItem * ) rb_leftmost (so -> queue );
409- /* Done when tree is empty */
410- if (so -> curTreeItem == NULL )
411- break ;
412- }
390+ GISTSearchItem * item ;
413391
414- item = so -> curTreeItem -> head ;
415- if (item != NULL )
416- {
417- /* Delink item from chain */
418- so -> curTreeItem -> head = item -> next ;
419- if (item == so -> curTreeItem -> lastHeap )
420- so -> curTreeItem -> lastHeap = NULL ;
421- /* Return item; caller is responsible to pfree it */
422- return item ;
423- }
424-
425- /* curTreeItem is exhausted, so remove it from rbtree */
426- rb_delete (so -> queue , (RBNode * ) so -> curTreeItem );
427- so -> curTreeItem = NULL ;
392+ if (!pairingheap_is_empty (so -> queue ))
393+ {
394+ item = (GISTSearchItem * ) pairingheap_remove_first (so -> queue );
395+ }
396+ else
397+ {
398+ /* Done when both heaps are empty */
399+ item = NULL ;
428400 }
429401
430- return NULL ;
402+ /* Return item; caller is responsible to pfree it */
403+ return item ;
431404}
432405
433406/*
@@ -458,7 +431,7 @@ getNextNearest(IndexScanDesc scan)
458431 /* visit an index page, extract its items into queue */
459432 CHECK_FOR_INTERRUPTS ();
460433
461- gistScanPage (scan , item , so -> curTreeItem -> distances , NULL , NULL );
434+ gistScanPage (scan , item , item -> distances , NULL , NULL );
462435 }
463436
464437 pfree (item );
@@ -491,7 +464,6 @@ gistgettuple(PG_FUNCTION_ARGS)
491464 pgstat_count_index_scan (scan -> indexRelation );
492465
493466 so -> firstCall = false;
494- so -> curTreeItem = NULL ;
495467 so -> curPageData = so -> nPageData = 0 ;
496468
497469 fakeItem .blkno = GIST_ROOT_BLKNO ;
@@ -534,7 +506,7 @@ gistgettuple(PG_FUNCTION_ARGS)
534506 * this page, we fall out of the inner "do" and loop around to
535507 * return them.
536508 */
537- gistScanPage (scan , item , so -> curTreeItem -> distances , NULL , NULL );
509+ gistScanPage (scan , item , item -> distances , NULL , NULL );
538510
539511 pfree (item );
540512 } while (so -> nPageData == 0 );
@@ -560,7 +532,6 @@ gistgetbitmap(PG_FUNCTION_ARGS)
560532 pgstat_count_index_scan (scan -> indexRelation );
561533
562534 /* Begin the scan by processing the root page */
563- so -> curTreeItem = NULL ;
564535 so -> curPageData = so -> nPageData = 0 ;
565536
566537 fakeItem .blkno = GIST_ROOT_BLKNO ;
@@ -580,7 +551,7 @@ gistgetbitmap(PG_FUNCTION_ARGS)
580551
581552 CHECK_FOR_INTERRUPTS ();
582553
583- gistScanPage (scan , item , so -> curTreeItem -> distances , tbm , & ntids );
554+ gistScanPage (scan , item , item -> distances , tbm , & ntids );
584555
585556 pfree (item );
586557 }
0 commit comments