PHOENIX-1690 IndexOutOfBoundsException during SkipScanFilter interesect

Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/49f06b33
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/49f06b33
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/49f06b33

Branch: refs/heads/calcite
Commit: 49f06b331c2b364f176d77548d04a4eb9d15c5c9
Parents: 3f82975
Author: James Taylor <jtay...@salesforce.com>
Authored: Tue Mar 3 12:07:56 2015 -0800
Committer: James Taylor <jtay...@salesforce.com>
Committed: Tue Mar 3 12:07:56 2015 -0800

----------------------------------------------------------------------
 .../apache/phoenix/filter/SkipScanFilter.java   |  31 +-
 .../org/apache/phoenix/schema/PTableImpl.java   |   9 +
 .../phoenix/filter/SkipScanBigFilterTest.java   | 717 +++++++++++++++++++
 .../filter/SkipScanFilterIntersectTest.java     |  69 +-
 4 files changed, 821 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/49f06b33/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java 
b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
index 0aafdbb..1923856 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
@@ -195,7 +195,7 @@ public class SkipScanFilter extends FilterBase implements 
Writable {
         Arrays.fill(position, 0);
     }
     
-    private boolean intersect(byte[] lowerInclusiveKey, byte[] 
upperExclusiveKey, List<List<KeyRange>> newSlots) {
+    private boolean intersect(final byte[] lowerInclusiveKey, final byte[] 
upperExclusiveKey, List<List<KeyRange>> newSlots) {
         resetState();
         boolean lowerUnbound = (lowerInclusiveKey.length == 0);
         int startPos = 0;
@@ -262,6 +262,9 @@ public class SkipScanFilter extends FilterBase implements 
Writable {
         }
         int[] lowerPosition = Arrays.copyOf(position, position.length);
         // Navigate to the upperExclusiveKey, but not past it
+        // TODO: We're including everything between the lowerPosition and end 
position, which is
+        // more than we need. We can optimize this by tracking whether each 
range in each slot position
+        // intersects.
         ReturnCode endCode = navigate(upperExclusiveKey, 0, 
upperExclusiveKey.length, Terminate.AT);
         if (endCode == ReturnCode.INCLUDE) {
             setStartKey();
@@ -286,6 +289,11 @@ public class SkipScanFilter extends FilterBase implements 
Writable {
                 position[i] = slots.get(i).size() - 1;
             }
         }
+        int prevRowKeyPos = -1;
+        ImmutableBytesWritable lowerPtr = new ImmutableBytesWritable();
+        ImmutableBytesWritable upperPtr = new ImmutableBytesWritable();
+        schema.iterator(lowerInclusiveKey, lowerPtr);
+        schema.iterator(upperExclusiveKey, upperPtr);
         // Copy inclusive all positions 
         for (int i = 0; i <= lastSlot; i++) {
             List<KeyRange> newRanges = slots.get(i).subList(lowerPosition[i], 
Math.min(position[i] + 1, slots.get(i).size()));
@@ -295,12 +303,33 @@ public class SkipScanFilter extends FilterBase implements 
Writable {
             if (newSlots != null) {
                 newSlots.add(newRanges);
             }
+            // Must include all "less-significant" slot values if:
+            // 1) a more-significant slot was incremented
             if (position[i] > lowerPosition[i]) {
                 if (newSlots != null) {
                     newSlots.addAll(slots.subList(i+1, slots.size()));
                 }
                 break;
             }
+            // 2) we're at a slot containing a range and the values differ 
between the lower and upper range,
+            //    since less-significant slots may be lower after traversal 
than where they started.
+            if (!slots.get(i).get(position[i]).isSingleKey()) {
+                int rowKeyPos = ScanUtil.getRowKeyPosition(slotSpan, i);
+                // Position lowerPtr/upperPtr within 
lowerInclusiveKey/upperExclusiveKey at value for slot i
+                // The reposition method will do this incrementally, where we 
we're initially have prevRowKeyPos = -1. 
+                schema.reposition(lowerPtr, prevRowKeyPos, rowKeyPos, 0, 
lowerInclusiveKey.length, slotSpan[i]);
+                schema.reposition(upperPtr, prevRowKeyPos, rowKeyPos, 0, 
upperExclusiveKey.length, slotSpan[i]);
+                // If we have a range and the values differ, we must include 
all slots that are less significant.
+                // For example: [A-D][1,23], the lower/upper keys could be 
B5/C2, where the C is in range and the
+                // next slot value of 2 is less than the next corresponding 
slot value of the 5.
+                if (lowerPtr.compareTo(upperPtr) != 0) {
+                    if (newSlots != null) {
+                        newSlots.addAll(slots.subList(i+1, slots.size()));
+                    }
+                    break;
+                }
+                prevRowKeyPos = rowKeyPos;
+            }
         }
         return true;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/49f06b33/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index e14565d..658ff23 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -236,6 +236,15 @@ public class PTableImpl implements PTable {
                 table.isWALDisabled(), table.isMultiTenant(), 
table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), 
table.getIndexType(), table.getTableStats());
     }
 
+    public static PTableImpl makePTable(PTable table, PTableStats stats) 
throws SQLException {
+        return new PTableImpl(
+                table.getTenantId(), table.getSchemaName(), 
table.getTableName(), table.getType(), table.getIndexState(), 
table.getTimeStamp(),
+                table.getSequenceNumber(), table.getPKName(), 
table.getBucketNum(), getColumnsToClone(table),
+                table.getParentSchemaName(), table.getParentTableName(), 
table.getIndexes(),
+                table.isImmutableRows(), table.getPhysicalNames(), 
table.getDefaultFamilyName(), table.getViewStatement(),
+                table.isWALDisabled(), table.isMultiTenant(), 
table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), 
table.getIndexType(), stats);
+    }
+
     public static PTableImpl makePTable(PName tenantId, PName schemaName, 
PName tableName, PTableType type, PIndexState state, long timeStamp, long 
sequenceNumber,
             PName pkName, Integer bucketNum, List<PColumn> columns, PName 
dataSchemaName, PName dataTableName, List<PTable> indexes,
             boolean isImmutableRows, List<PName> physicalNames, PName 
defaultFamilyName, String viewExpression, boolean disableWAL, boolean 
multiTenant,

Reply via email to