@@ -38,6 +38,7 @@ static bool scanPage(RumState *rumstate, RumScanEntry entry, ItemPointer item,
38
38
Page page , bool equalOk );
39
39
static void insertScanItem (RumScanOpaque so , bool recheck );
40
40
static int scan_entry_cmp (const void * p1 , const void * p2 );
41
+ static int rum_key_cmp_with_check (const void * p1 , const void * p2 , void * arg );
41
42
static void entryGetItem (RumState * rumstate , RumScanEntry entry );
42
43
43
44
@@ -414,6 +415,41 @@ collectMatchBitmap(RumBtreeData *btree, RumBtreeStack *stack,
414
415
}
415
416
}
416
417
418
+ /*
419
+ * Sort array of RumKey and remove duplicates.
420
+ *
421
+ * Returns new size of the array.
422
+ */
423
+ static uint32
424
+ sortAndUniqRumKeys (RumKey * list , uint32 nlist )
425
+ {
426
+ uint32 i , j ;
427
+ bool haveDups = false;
428
+
429
+ if (nlist < 2 )
430
+ return nlist ;
431
+
432
+ qsort_arg (list , nlist , sizeof (RumKey ), rum_key_cmp_with_check ,
433
+ (void * ) & haveDups );
434
+
435
+ /* There are duplicates, remove them */
436
+ if (haveDups )
437
+ {
438
+ j = 1 ;
439
+ for (i = 1 ; i < nlist ; i ++ )
440
+ {
441
+ if (rumCompareItemPointers (& list [i - 1 ].iptr , & list [i ].iptr ) != 0 )
442
+ {
443
+ list [j ] = list [i ];
444
+ j ++ ;
445
+ }
446
+ }
447
+ return j ;
448
+ }
449
+ else
450
+ return nlist ;
451
+ }
452
+
417
453
static void
418
454
collectMatchRumKey (RumBtreeData * btree , RumBtreeStack * stack ,
419
455
RumScanEntry entry )
@@ -588,14 +624,16 @@ collectMatchRumKey(RumBtreeData *btree, RumBtreeStack *stack,
588
624
}
589
625
else if (RumGetNPosting (itup ) > 0 )
590
626
{
591
- uint32 j ;
627
+ uint32 off , count ;
592
628
593
- j = entry -> nlist ;
594
- entry -> nlist += RumGetNPosting (itup );
595
- entry -> predictNumberResult += RumGetNPosting (itup );
629
+ count = RumGetNPosting (itup );
630
+
631
+ off = entry -> nlist ;
632
+ entry -> nlist += count ;
633
+ entry -> predictNumberResult += count ;
596
634
if (entry -> nalloc == 0 )
597
635
{
598
- entry -> nalloc = Max (RumGetNPosting ( itup ) , 32 );
636
+ entry -> nalloc = Max (count , 32 );
599
637
entry -> list = (RumKey * ) palloc (entry -> nalloc * sizeof (RumKey ));
600
638
}
601
639
else if (entry -> nlist > entry -> nalloc )
@@ -605,7 +643,7 @@ collectMatchRumKey(RumBtreeData *btree, RumBtreeStack *stack,
605
643
repalloc (entry -> list , entry -> nalloc * sizeof (RumKey ));
606
644
}
607
645
608
- rumReadTuple (btree -> rumstate , entry -> attnum , itup , entry -> list + j );
646
+ rumReadTuple (btree -> rumstate , entry -> attnum , itup , entry -> list + off );
609
647
entry -> isFinished = FALSE;
610
648
}
611
649
@@ -696,6 +734,7 @@ startScanEntry(RumState *rumstate, RumScanEntry entry)
696
734
{
697
735
btreeEntry .findItem (& btreeEntry , stackEntry );
698
736
collectMatchRumKey (& btreeEntry , stackEntry , entry );
737
+ entry -> nlist = sortAndUniqRumKeys (entry -> list , entry -> nlist );
699
738
}
700
739
else if (btreeEntry .findItem (& btreeEntry , stackEntry ))
701
740
{
@@ -810,6 +849,22 @@ scan_entry_cmp(const void *p1, const void *p2)
810
849
return - cmpEntries (e1 , e2 );
811
850
}
812
851
852
+ static int
853
+ rum_key_cmp_with_check (const void * p1 , const void * p2 , void * arg )
854
+ {
855
+ const RumKey * k1 = (const RumKey * ) p1 ;
856
+ const RumKey * k2 = (const RumKey * ) p2 ;
857
+ bool * haveDups = (bool * ) arg ;
858
+ int res ;
859
+
860
+ res = rumCompareItemPointers (& k1 -> iptr , & k2 -> iptr );
861
+
862
+ if (res == 0 )
863
+ * haveDups = true;
864
+
865
+ return res ;
866
+ }
867
+
813
868
static void
814
869
startScan (IndexScanDesc scan )
815
870
{
0 commit comments