You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2016/07/23 19:52:01 UTC
phoenix git commit: PHOENIX-2900 Unable to find hash cache once a
salted table 's first region has split (chenglei)
Repository: phoenix
Updated Branches:
refs/heads/master f071365b9 -> 59497d525
PHOENIX-2900 Unable to find hash cache once a salted table 's first region has split (chenglei)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/59497d52
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/59497d52
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/59497d52
Branch: refs/heads/master
Commit: 59497d525d94addd9c9faf51ea64329c64149938
Parents: f071365
Author: James Taylor <ja...@apache.org>
Authored: Sat Jul 23 09:49:33 2016 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Sat Jul 23 11:53:00 2016 -0700
----------------------------------------------------------------------
.../end2end/BaseTenantSpecificViewIndexIT.java | 2 +-
.../org/apache/phoenix/end2end/BaseViewIT.java | 4 +-
.../phoenix/end2end/index/SaltedIndexIT.java | 4 +-
.../apache/phoenix/cache/ServerCacheClient.java | 5 +-
.../org/apache/phoenix/compile/ScanRanges.java | 88 +++----
.../phoenix/compile/SaltedScanRangesTest.java | 231 +++++++++++++++++++
.../apache/phoenix/compile/ScanRangesTest.java | 8 +-
.../org/apache/phoenix/query/QueryPlanTest.java | 4 +-
8 files changed, 291 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
index 11a33da..04f4268 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
@@ -142,7 +142,7 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
String expected = saltBuckets == null ?
"CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T [-32768,'" + tenantId + "','" + valuePrefix + "v2-1']\n"
+ " SERVER FILTER BY FIRST KEY ONLY" :
- "CLIENT PARALLEL 3-WAY RANGE SCAN OVER _IDX_T [0,-32768,'" + tenantId + "','" + valuePrefix + "v2-1']\n"
+ "CLIENT PARALLEL 3-WAY RANGE SCAN OVER _IDX_T [0,-32768,'" + tenantId + "','" + valuePrefix + "v2-1'] - ["+(saltBuckets.intValue()-1)+",-32768,'" + tenantId + "','" + valuePrefix + "v2-1']\n"
+ " SERVER FILTER BY FIRST KEY ONLY\n"
+ "CLIENT MERGE SORT";
assertEquals(expected, QueryUtil.getExplainPlan(rs));
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseViewIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseViewIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseViewIT.java
index 6d8d889..d9a59a9 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseViewIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseViewIT.java
@@ -210,7 +210,7 @@ public abstract class BaseViewIT extends BaseOwnClusterHBaseManagedTimeIT {
} else {
assertEquals(saltBuckets == null
? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_" + tableName +" [" + Short.MIN_VALUE + ",51]"
- : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER _IDX_T" + (transactional ? "_TXN" : "") + " [0," + Short.MIN_VALUE + ",51]\nCLIENT MERGE SORT",
+ : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER _IDX_T" + (transactional ? "_TXN" : "") + " [0," + Short.MIN_VALUE + ",51] - ["+(saltBuckets.intValue()-1)+"," + Short.MIN_VALUE + ",51]\nCLIENT MERGE SORT",
queryPlan);
}
@@ -251,7 +251,7 @@ public abstract class BaseViewIT extends BaseOwnClusterHBaseManagedTimeIT {
assertEquals(saltBuckets == null
? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + htableName +" [" + (Short.MIN_VALUE+1) + ",'foo']\n"
+ " SERVER FILTER BY FIRST KEY ONLY"
- : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER " + htableName + " [0," + (Short.MIN_VALUE+1) + ",'foo']\n"
+ : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER " + htableName + " [0," + (Short.MIN_VALUE+1) + ",'foo'] - ["+(saltBuckets.intValue()-1)+"," + (Short.MIN_VALUE+1) + ",'foo']\n"
+ " SERVER FILTER BY FIRST KEY ONLY\n"
+ "CLIENT MERGE SORT",
QueryUtil.getExplainPlan(rs));
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SaltedIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SaltedIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SaltedIndexIT.java
index b5c8477..5b2b15a 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SaltedIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SaltedIndexIT.java
@@ -143,7 +143,7 @@ public class SaltedIndexIT extends BaseHBaseManagedTimeIT {
expectedPlan = indexSaltBuckets == null ?
"CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [~'y']\n" +
" SERVER FILTER BY FIRST KEY ONLY" :
- ("CLIENT PARALLEL 4-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [0,~'y']\n" +
+ ("CLIENT PARALLEL 4-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [0,~'y'] - ["+(indexSaltBuckets.intValue()-1)+",~'y']\n" +
" SERVER FILTER BY FIRST KEY ONLY\n" +
"CLIENT MERGE SORT");
assertEquals(expectedPlan,QueryUtil.getExplainPlan(rs));
@@ -164,7 +164,7 @@ public class SaltedIndexIT extends BaseHBaseManagedTimeIT {
expectedPlan = indexSaltBuckets == null ?
"CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [*] - [~'x']\n"
+ " SERVER FILTER BY FIRST KEY ONLY" :
- ("CLIENT PARALLEL 4-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [0,*] - [0,~'x']\n"
+ ("CLIENT PARALLEL 4-WAY RANGE SCAN OVER " + TestUtil.DEFAULT_INDEX_TABLE_FULL_NAME + " [0,*] - ["+(indexSaltBuckets.intValue()-1)+",~'x']\n"
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
"CLIENT MERGE SORT");
assertEquals(expectedPlan,QueryUtil.getExplainPlan(rs));
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java b/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
index d88b094..67fc410 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
@@ -172,9 +172,8 @@ public class ServerCacheClient {
byte[] regionStartKey = entry.getRegionInfo().getStartKey();
byte[] regionEndKey = entry.getRegionInfo().getEndKey();
if ( ! servers.contains(entry) &&
- keyRanges.intersects(regionStartKey, regionEndKey,
- cacheUsingTable.getIndexType() == IndexType.LOCAL ?
- ScanUtil.getRowKeyOffset(regionStartKey, regionEndKey) : 0, true)) {
+ keyRanges.intersectRegion(regionStartKey, regionEndKey,
+ cacheUsingTable.getIndexType() == IndexType.LOCAL)) {
// Call RPC once per server
servers.add(entry);
if (LOG.isDebugEnabled()) {LOG.debug(addCustomAnnotations("Adding cache entry to be sent for " + entry, connection));}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
index 6f0adb0..f3d5bba 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
@@ -68,6 +68,11 @@ public class ScanRanges {
return create(schema, ranges, ScanUtil.getDefaultSlotSpans(ranges.size()), KeyRange.EVERYTHING_RANGE, null, true, -1);
}
+ // For testing
+ public static ScanRanges createSingleSpan(RowKeySchema schema, List<List<KeyRange>> ranges, Integer nBuckets, boolean useSkipSan) {
+ return create(schema, ranges, ScanUtil.getDefaultSlotSpans(ranges.size()), KeyRange.EVERYTHING_RANGE, nBuckets, useSkipSan, -1);
+ }
+
public static ScanRanges create(RowKeySchema schema, List<List<KeyRange>> ranges, int[] slotSpan, KeyRange minMaxRange, Integer nBuckets, boolean useSkipScan, int rowTimestampColIndex) {
int offset = nBuckets == null ? 0 : SaltingUtil.NUM_SALTING_BYTES;
int nSlots = ranges.size();
@@ -170,12 +175,8 @@ public class ScanRanges {
this.minMaxRange = minMaxRange;
this.rowTimestampRange = rowTimestampRange;
- // Only blow out the bucket values if we're using the skip scan. We need all the
- // bucket values in this case because we use intersect against a key that may have
- // any of the possible bucket values. Otherwise, we can pretty easily ignore the
- // bucket values.
- if (useSkipScanFilter && isSalted && !isPointLookup) {
- ranges.set(0, SaltingUtil.generateAllSaltingRanges(bucketNum));
+ if (isSalted && !isPointLookup) {
+ ranges.set(0, SaltingUtil.generateAllSaltingRanges(bucketNum));
}
this.ranges = ImmutableList.copyOf(ranges);
this.slotSpan = slotSpan;
@@ -243,7 +244,6 @@ public class ScanRanges {
if (stopKey.length > 0 && Bytes.compareTo(startKey, stopKey) >= 0) {
return null;
}
- boolean mayHaveRows = false;
// Keep the keys as they are if we have a point lookup, as we've already resolved the
// salt bytes in that case.
final int scanKeyOffset = this.isSalted && !this.isPointLookup ? SaltingUtil.NUM_SALTING_BYTES : 0;
@@ -268,49 +268,53 @@ public class ScanRanges {
}
}
int scanStartKeyOffset = scanKeyOffset;
- byte[] scanStartKey = scan == null ? ByteUtil.EMPTY_BYTE_ARRAY : scan.getStartRow();
+ byte[] scanStartKey = scan == null ? this.scanRange.getLowerRange() : scan.getStartRow();
// Compare ignoring key prefix and salt byte
- if (scanStartKey.length > 0) {
- if (startKey.length > 0 && Bytes.compareTo(scanStartKey, scanKeyOffset, scanStartKey.length - scanKeyOffset, startKey, totalKeyOffset, startKey.length - totalKeyOffset) < 0) {
- scanStartKey = startKey;
- scanStartKeyOffset = totalKeyOffset;
+ if (scanStartKey.length - scanKeyOffset > 0) {
+ if (startKey.length - totalKeyOffset > 0) {
+ if (Bytes.compareTo(scanStartKey, scanKeyOffset, scanStartKey.length - scanKeyOffset, startKey, totalKeyOffset, startKey.length - totalKeyOffset) < 0) {
+ scanStartKey = startKey;
+ scanStartKeyOffset = totalKeyOffset;
+ }
}
} else {
- scanStartKey = startKey;
+ scanStartKey = startKey;
scanStartKeyOffset = totalKeyOffset;
- mayHaveRows = true;
}
int scanStopKeyOffset = scanKeyOffset;
- byte[] scanStopKey = scan == null ? ByteUtil.EMPTY_BYTE_ARRAY : scan.getStopRow();
- if (scanStopKey.length > 0) {
- if (stopKey.length > 0 && Bytes.compareTo(scanStopKey, scanKeyOffset, scanStopKey.length - scanKeyOffset, stopKey, totalKeyOffset, stopKey.length - totalKeyOffset) > 0) {
- scanStopKey = stopKey;
- scanStopKeyOffset = totalKeyOffset;
+ byte[] scanStopKey = scan == null ? this.scanRange.getUpperRange() : scan.getStopRow();
+ if (scanStopKey.length - scanKeyOffset > 0) {
+ if (stopKey.length - totalKeyOffset > 0) {
+ if (Bytes.compareTo(scanStopKey, scanKeyOffset, scanStopKey.length - scanKeyOffset, stopKey, totalKeyOffset, stopKey.length - totalKeyOffset) > 0) {
+ scanStopKey = stopKey;
+ scanStopKeyOffset = totalKeyOffset;
+ }
}
} else {
- scanStopKey = stopKey;
+ scanStopKey = stopKey;
scanStopKeyOffset = totalKeyOffset;
- mayHaveRows = true;
}
- mayHaveRows = mayHaveRows || Bytes.compareTo(scanStartKey, scanStartKeyOffset, scanStartKey.length - scanStartKeyOffset, scanStopKey, scanStopKeyOffset, scanStopKey.length - scanStopKeyOffset) < 0;
- if (!mayHaveRows) {
+ // If not scanning anything, return null
+ if (scanStopKey.length - scanStopKeyOffset > 0 &&
+ Bytes.compareTo(scanStartKey, scanStartKeyOffset, scanStartKey.length - scanStartKeyOffset,
+ scanStopKey, scanStopKeyOffset, scanStopKey.length - scanStopKeyOffset) >= 0) {
return null;
}
if (originalStopKey.length != 0 && scanStopKey.length == 0) {
scanStopKey = originalStopKey;
}
Filter newFilter = null;
- // If the scan is using skip scan filter, intersect and replace the filter.
- if (scan == null || this.useSkipScanFilter()) {
+ // Only if the scan is using skip scan filter, intersect and replace the filter.
+ // For example, we may be forcing a range scan, in which case we do not want to
+ // intersect the start/stop with the filter. Instead, we rely only on the scan
+ // start/stop or the scanRanges start/stop.
+ if (this.useSkipScanFilter()) {
byte[] skipScanStartKey = scanStartKey;
byte[] skipScanStopKey = scanStopKey;
// If we have a keyOffset and we've used the startKey/stopKey that
// were passed in (which have the prefix) for the above range check,
// we need to remove the prefix before running our intersect method.
- // TODO: we could use skipScanFilter.setOffset(keyOffset) if both
- // the startKey and stopKey were used above *and* our intersect
- // method honored the skipScanFilter.offset variable.
if (scanKeyOffset > 0) {
if (skipScanStartKey != originalStartKey) { // original already has correct salt byte
skipScanStartKey = replaceSaltByte(skipScanStartKey, prefixBytes);
@@ -360,6 +364,10 @@ public class ScanRanges {
scanStopKey = ScanUtil.getMaxKey(schema, newSkipScanFilter.getSlots(), slotSpan);
}
}
+ // If we've got this far, we know we have an intersection
+ if (scan == null) {
+ return HAS_INTERSECTION;
+ }
if (newFilter == null) {
newFilter = scan.getFilter();
}
@@ -391,29 +399,27 @@ public class ScanRanges {
}
/**
- * Return true if the range formed by the lowerInclusiveKey and upperExclusiveKey
- * intersects with the scan ranges and false otherwise. We cannot pass in
- * a KeyRange here, because the underlying compare functions expect lower inclusive
- * and upper exclusive keys. We cannot get their next key because the key must
- * conform to the row key schema and if a null byte is added to a lower inclusive
- * key, it's no longer a valid, real key.
- * @param lowerInclusiveKey lower inclusive key
- * @param upperExclusiveKey upper exclusive key
- * @param crossesRegionBoundary whether or not the upperExclusiveKey spans upto
- * or after the next region.
+ * Return true if the region with the start and end key
+ * intersects with the scan ranges and false otherwise.
+ * @param regionStartKey lower inclusive key
+ * @param regionEndKey upper exclusive key
+ * @param isLocalIndex true if the table being scanned is a local index
* @return true if the scan range intersects with the specified lower/upper key
* range
*/
- public boolean intersects(byte[] lowerInclusiveKey, byte[] upperExclusiveKey, int keyOffset, boolean crossesRegionBoundary) {
+ public boolean intersectRegion(byte[] regionStartKey, byte[] regionEndKey, boolean isLocalIndex) {
if (isEverything()) {
return true;
}
if (isDegenerate()) {
return false;
}
+ // Every range intersects all regions of a local index table
+ if (isLocalIndex) {
+ return true;
+ }
- //return filter.hasIntersect(lowerInclusiveKey, upperExclusiveKey);
- return intersectScan(null, lowerInclusiveKey, upperExclusiveKey, keyOffset, crossesRegionBoundary) == HAS_INTERSECTION;
+ return intersectScan(null, regionStartKey, regionEndKey, 0, false) == HAS_INTERSECTION;
}
public SkipScanFilter getSkipScanFilter() {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/test/java/org/apache/phoenix/compile/SaltedScanRangesTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/SaltedScanRangesTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/SaltedScanRangesTest.java
new file mode 100644
index 0000000..f8eb3a0
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/SaltedScanRangesTest.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.PDatum;
+import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder;
+import org.apache.phoenix.schema.SaltingUtil;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PChar;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.util.ByteUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
+
+/**
+ * Test for intersect method in {@link ScanRanges} over salted data
+ */
+@RunWith(Parameterized.class)
+public class SaltedScanRangesTest {
+
+ private static Integer nBuckets = 3;
+ private final ScanRanges scanRanges;
+ private final KeyRange keyRange;
+ private final boolean expectedResult;
+
+ public SaltedScanRangesTest(ScanRanges scanRanges, int[] widths,
+ KeyRange keyRange, boolean expectedResult) {
+ this.keyRange = keyRange;
+ this.scanRanges = scanRanges;
+ this.expectedResult = expectedResult;
+ }
+
+ @Test
+ public void test() {
+ byte[] lowerInclusiveKey = keyRange.getLowerRange();
+ if (!keyRange.isLowerInclusive() && !Bytes.equals(lowerInclusiveKey, KeyRange.UNBOUND)) {
+ // This assumes the last key is fixed length, otherwise the results may be incorrect
+ // since there's no terminating 0 byte for a variable length key and thus we may be
+ // incrementing the key too much.
+ lowerInclusiveKey = ByteUtil.nextKey(lowerInclusiveKey);
+ }
+ byte[] upperExclusiveKey = keyRange.getUpperRange();
+ if (keyRange.isUpperInclusive()) {
+ // This assumes the last key is fixed length, otherwise the results may be incorrect
+ // since there's no terminating 0 byte for a variable length key and thus we may be
+ // incrementing the key too much.
+ upperExclusiveKey = ByteUtil.nextKey(upperExclusiveKey);
+ }
+ assertEquals(expectedResult, scanRanges.intersectRegion(lowerInclusiveKey,upperExclusiveKey,false));
+ }
+
+ @Parameters(name="{0} {2}")
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(KeyRange.UNBOUND, new byte[]{1}),
+ false,
+ true));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(new byte[]{1},new byte[]{2}),
+ false,
+ true));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(new byte[]{2},KeyRange.UNBOUND),
+ false,
+ true));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(new byte[]{1},ByteUtil.concat(new byte[]{1}, Bytes.toBytes("c"))),
+ false,
+ false));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(ByteUtil.concat(new byte[]{1}, Bytes.toBytes("e")), new byte[]{2}),
+ false,
+ false));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(ByteUtil.concat(new byte[]{1}, Bytes.toBytes("d")), new byte[]{2}),
+ false,
+ true));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("h"), true, Bytes.toBytes("i"), false),
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("m"), true, Bytes.toBytes("p"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(ByteUtil.concat(new byte[]{1}, Bytes.toBytes("f")), ByteUtil.concat(new byte[]{1}, Bytes.toBytes("g"))),
+ false,
+ true));
+ testCases.addAll(
+ foreach(new KeyRange[][]{{
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("c"), true, Bytes.toBytes("e"), false),
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("h"), true, Bytes.toBytes("i"), false),
+ PVarchar.INSTANCE.getKeyRange(Bytes.toBytes("m"), true, Bytes.toBytes("p"), false),
+ }},
+ new int[] {0},
+ KeyRange.getKeyRange(ByteUtil.concat(new byte[]{1}, Bytes.toBytes("f")), ByteUtil.concat(new byte[]{1}, Bytes.toBytes("g"))),
+ true,
+ false));
+ return testCases;
+ }
+
+ private static Collection<?> foreach(ScanRanges ranges, int[] widths, KeyRange keyRange,
+ boolean expectedResult) {
+ List<Object> ret = Lists.newArrayList();
+ ret.add(new Object[] {ranges, widths, keyRange, expectedResult});
+ return ret;
+ }
+
+ private static Collection<?> foreach(KeyRange[][] ranges, int[] widths, KeyRange keyRange, boolean useSkipScan,
+ boolean expectedResult) {
+ List<List<KeyRange>> slots = Lists.transform(Lists.newArrayList(ranges), ARRAY_TO_LIST);
+ slots = new ArrayList<>(slots);
+ slots.add(0, Collections.singletonList(KeyRange.getKeyRange(new byte[]{0})));
+ RowKeySchemaBuilder builder = new RowKeySchemaBuilder(10);
+ builder.addField(SaltingUtil.SALTING_COLUMN, false, SortOrder.getDefault());
+ for (final int width : widths) {
+ if (width > 0) {
+ builder.addField(new PDatum() {
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+ @Override
+ public PDataType getDataType() {
+ return PChar.INSTANCE;
+ }
+ @Override
+ public Integer getMaxLength() {
+ return width;
+ }
+ @Override
+ public Integer getScale() {
+ return null;
+ }
+ @Override
+ public SortOrder getSortOrder() {
+ return SortOrder.getDefault();
+ }
+ }, false, SortOrder.getDefault());
+ } else {
+ builder.addField(new PDatum() {
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+ @Override
+ public PDataType getDataType() {
+ return PVarchar.INSTANCE;
+ }
+ @Override
+ public Integer getMaxLength() {
+ return width;
+ }
+ @Override
+ public Integer getScale() {
+ return null;
+ }
+ @Override
+ public SortOrder getSortOrder() {
+ return SortOrder.getDefault();
+ }
+ }, false, SortOrder.getDefault());
+ }
+ }
+ ScanRanges scanRanges = ScanRanges.createSingleSpan(builder.build(), slots, nBuckets , useSkipScan);
+ return foreach(scanRanges, widths, keyRange, expectedResult);
+ }
+
+ private static final Function<KeyRange[], List<KeyRange>> ARRAY_TO_LIST =
+ new Function<KeyRange[], List<KeyRange>>() {
+ @Override
+ public List<KeyRange> apply(KeyRange[] input) {
+ return Lists.newArrayList(input);
+ }
+ };
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/test/java/org/apache/phoenix/compile/ScanRangesTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/ScanRangesTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/ScanRangesTest.java
index 0292244..44aac4d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/ScanRangesTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/ScanRangesTest.java
@@ -24,12 +24,12 @@ import java.util.List;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.schema.types.PChar;
-import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.PDatum;
-import org.apache.phoenix.schema.types.PVarchar;
import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder;
import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PChar;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PVarchar;
import org.apache.phoenix.util.ByteUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,7 +73,7 @@ public class ScanRangesTest {
// incrementing the key too much.
upperExclusiveKey = ByteUtil.nextKey(upperExclusiveKey);
}
- assertEquals(expectedResult, scanRanges.intersects(lowerInclusiveKey,upperExclusiveKey,0, true));
+ assertEquals(expectedResult, scanRanges.intersectRegion(lowerInclusiveKey,upperExclusiveKey,false));
}
@Parameters(name="{0} {2}")
http://git-wip-us.apache.org/repos/asf/phoenix/blob/59497d52/phoenix-core/src/test/java/org/apache/phoenix/query/QueryPlanTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/QueryPlanTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/QueryPlanTest.java
index 8af832b..37010b3 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/QueryPlanTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/QueryPlanTest.java
@@ -245,7 +245,7 @@ public class QueryPlanTest extends BaseConnectionlessQueryTest {
ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
String queryPlan = QueryUtil.getExplainPlan(rs);
assertEquals(
- "CLIENT PARALLEL 20-WAY RANGE SCAN OVER FOO [0,'a',~'2016-01-28 23:59:59.999'] - [0,'a',~'2016-01-28 00:00:00.000']\n" +
+ "CLIENT PARALLEL 20-WAY RANGE SCAN OVER FOO [0,'a',~'2016-01-28 23:59:59.999'] - [19,'a',~'2016-01-28 00:00:00.000']\n" +
" SERVER FILTER BY FIRST KEY ONLY\n" +
"CLIENT MERGE SORT", queryPlan);
} finally {
@@ -271,7 +271,7 @@ public class QueryPlanTest extends BaseConnectionlessQueryTest {
ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
String queryPlan = QueryUtil.getExplainPlan(rs);
assertEquals(
- "CLIENT PARALLEL 20-WAY ROUND ROBIN RANGE SCAN OVER " + tableName + " [0,'a',~'2016-01-28 23:59:59.999'] - [0,'a',~'2016-01-28 00:00:00.000']\n" +
+ "CLIENT PARALLEL 20-WAY ROUND ROBIN RANGE SCAN OVER " + tableName + " [0,'a',~'2016-01-28 23:59:59.999'] - [19,'a',~'2016-01-28 00:00:00.000']\n" +
" SERVER FILTER BY FIRST KEY ONLY", queryPlan);
} finally {
conn.close();