Repository: nationalsecurityagency/datawave
Issue: Intersection can return inconsistent shard after seeking

When an intersection contains days only and is seeked with a day_shard the following next call will return just the day that was returned with the day_shard rather than the next day. Add consistent checks when calling next to ensure the underlying iterators have been advanced beyond the last returned value.

Changed files:
warehouse/query-core/src/test/java/datawave/query/index/lookup/IntersectionTest.java
warehouse/query-core/src/main/java/datawave/query/index/lookup/Intersection.java

diff --git a/warehouse/query-core/src/main/java/datawave/query/index/lookup/Intersection.java b/warehouse/query-core/src/main/java/datawave/query/index/lookup/Intersection.java
index 5f42ecf9e4..3501c03daf 100644
--- a/warehouse/query-core/src/main/java/datawave/query/index/lookup/Intersection.java
+++ b/warehouse/query-core/src/main/java/datawave/query/index/lookup/Intersection.java
@@ -210,6 +210,13 @@ public class Intersection extends BaseIndexStream {
             final SortedSet<String> keys = children.keySet();
             if (keys.size() == 1) {
                 intersect(keys);
+                
+                // ensure consistency with current state since underlying iterators may not be updated to reflect previous seek calls
+                // the next key should be beyond the current key, otherwise look again
+                if (next != null && ret != null && next.first().compareTo(ret.first()) <= 0) {
+                    // force it to compute again
+                    next = null;
+                }
             } else {
                 // Seek all child IndexStreams to the highest top key.
                 String max = children.keySet().last();
diff --git a/warehouse/query-core/src/test/java/datawave/query/index/lookup/IntersectionTest.java b/warehouse/query-core/src/test/java/datawave/query/index/lookup/IntersectionTest.java
index c2b5533b3f..dd8f08cfb2 100644
--- a/warehouse/query-core/src/test/java/datawave/query/index/lookup/IntersectionTest.java
+++ b/warehouse/query-core/src/test/java/datawave/query/index/lookup/IntersectionTest.java
@@ -165,6 +165,49 @@ public class IntersectionTest {
         assertFalse(intersection.hasNext());
     }
     
+    /**
+     * Following a seek of a day_shard against day only tuples calling next would result in the last returned day being returned again rather than the next one
+     */
+    @Test
+    public void testIntersectionAfterSeek() {
+        // Build a peeking iterator for a left side term
+        List<IndexMatch> leftMatches = buildIndexMatches("FIELD", "VALUE", "doc1", "doc2", "doc3");
+        IndexInfo left = new IndexInfo(leftMatches);
+        left.setNode(JexlNodeFactory.buildEQNode("FIELD", "VALUE"));
+        
+        List<Tuple2<String,IndexInfo>> tupleList = new ArrayList();
+        tupleList.add(Tuples.tuple("20190314", left));
+        tupleList.add(Tuples.tuple("20190315", left));
+        tupleList.add(Tuples.tuple("20190316", left));
+        
+        PeekingIterator<Tuple2<String,IndexInfo>> leftIter = Iterators.peekingIterator(tupleList.iterator());
+        
+        // Build a peeking iterator for a right side term.
+        List<IndexMatch> rightMatches = buildIndexMatches("FIELD", "VALUE", "doc2", "doc3", "doc4");
+        IndexInfo right = new IndexInfo(rightMatches);
+        right.setNode(JexlNodeFactory.buildEQNode("FIELD", "VALUE"));
+        
+        tupleList = new ArrayList();
+        tupleList.add(Tuples.tuple("20190314", right));
+        tupleList.add(Tuples.tuple("20190315", right));
+        tupleList.add(Tuples.tuple("20190316", right));
+        
+        PeekingIterator<Tuple2<String,IndexInfo>> rightIter = Iterators.peekingIterator(tupleList.iterator());
+        
+        // Build the Intersection.
+        IndexStream leftStream = ScannerStream.withData(leftIter, JexlNodeFactory.buildEQNode("FIELD", "VALUE"));
+        IndexStream rightStream = ScannerStream.withData(rightIter, JexlNodeFactory.buildEQNode("FIELD", "VALUE"));
+        List<IndexStream> indexStreams = Lists.newArrayList(leftStream, rightStream);
+        
+        Intersection intersection = new Intersection(indexStreams, new IndexInfo());
+        assertTrue(intersection.hasNext());
+        assertEquals("20190314", intersection.peek().first());
+        assertEquals("20190315_11", intersection.seek("20190315_11"));
+        assertTrue(intersection.hasNext());
+        intersection.next();
+        assertEquals("20190316", intersection.peek().first());
+    }
+    
     /**
      * Intersection of day range with a shard range within the day range is possible.
      */