@@ -38,6 +38,7 @@ static bool scanPage(RumState *rumstate, RumScanEntry entry, ItemPointer item,
3838Page page ,bool equalOk );
3939static void insertScanItem (RumScanOpaque so ,bool recheck );
4040static 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 );
4142static void entryGetItem (RumState * rumstate ,RumScanEntry entry );
4243
4344
@@ -414,6 +415,41 @@ collectMatchBitmap(RumBtreeData *btree, RumBtreeStack *stack,
414415}
415416}
416417
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+
417453static void
418454collectMatchRumKey (RumBtreeData * btree ,RumBtreeStack * stack ,
419455RumScanEntry entry )
@@ -588,14 +624,16 @@ collectMatchRumKey(RumBtreeData *btree, RumBtreeStack *stack,
588624}
589625else if (RumGetNPosting (itup )> 0 )
590626{
591- uint32 j ;
627+ uint32 off , count ;
592628
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 ;
596634if (entry -> nalloc == 0 )
597635{
598- entry -> nalloc = Max (RumGetNPosting ( itup ) ,32 );
636+ entry -> nalloc = Max (count ,32 );
599637entry -> list = (RumKey * )palloc (entry -> nalloc * sizeof (RumKey ));
600638}
601639else if (entry -> nlist > entry -> nalloc )
@@ -605,7 +643,7 @@ collectMatchRumKey(RumBtreeData *btree, RumBtreeStack *stack,
605643repalloc (entry -> list ,entry -> nalloc * sizeof (RumKey ));
606644}
607645
608- rumReadTuple (btree -> rumstate ,entry -> attnum ,itup ,entry -> list + j );
646+ rumReadTuple (btree -> rumstate ,entry -> attnum ,itup ,entry -> list + off );
609647entry -> isFinished = FALSE;
610648}
611649
@@ -696,6 +734,7 @@ startScanEntry(RumState *rumstate, RumScanEntry entry)
696734{
697735btreeEntry .findItem (& btreeEntry ,stackEntry );
698736collectMatchRumKey (& btreeEntry ,stackEntry ,entry );
737+ entry -> nlist = sortAndUniqRumKeys (entry -> list ,entry -> nlist );
699738}
700739else if (btreeEntry .findItem (& btreeEntry ,stackEntry ))
701740{
@@ -810,6 +849,22 @@ scan_entry_cmp(const void *p1, const void *p2)
810849return - cmpEntries (e1 ,e2 );
811850}
812851
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+
813868static void
814869startScan (IndexScanDesc scan )
815870{