use of org.apache.phoenix.filter.SkipScanFilter in project phoenix by apache.
the class WhereCompilerTest method testSecondPkColInListFilter.
@Test
public void testSecondPkColInListFilter() throws SQLException {
String tenantId = "000000000000001";
String entityId1 = "00000000000000X";
String entityId2 = "00000000000000Y";
String query = String.format("select * from %s where organization_id='%s' AND entity_id IN ('%s','%s')", ATABLE_NAME, tenantId, entityId1, entityId2);
PhoenixConnection pconn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES)).unwrap(PhoenixConnection.class);
PhoenixPreparedStatement pstmt = newPreparedStatement(pconn, query);
QueryPlan plan = pstmt.optimizeQuery();
Scan scan = plan.getContext().getScan();
byte[] startRow = PVarchar.INSTANCE.toBytes(tenantId + entityId1);
assertArrayEquals(startRow, scan.getStartRow());
byte[] stopRow = PVarchar.INSTANCE.toBytes(tenantId + entityId2);
assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
Filter filter = scan.getFilter();
assertEquals(new SkipScanFilter(ImmutableList.of(Arrays.asList(pointRange(tenantId, entityId1), pointRange(tenantId, entityId2))), SchemaUtil.VAR_BINARY_SCHEMA), filter);
}
use of org.apache.phoenix.filter.SkipScanFilter in project phoenix by apache.
the class WhereCompilerTest method testInListWithAnd2Filter.
@Test
public void testInListWithAnd2Filter() throws SQLException {
String tenantId1 = "000000000000001";
String tenantId2 = "000000000000002";
String entityId1 = "00000000000000X";
String entityId2 = "00000000000000Y";
String query = String.format("select * from %s where organization_id IN ('%s','%s') AND entity_id IN ('%s', '%s')", ATABLE_NAME, tenantId1, tenantId2, entityId1, entityId2);
PhoenixConnection pconn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES)).unwrap(PhoenixConnection.class);
PhoenixPreparedStatement pstmt = newPreparedStatement(pconn, query);
QueryPlan plan = pstmt.optimizeQuery();
Scan scan = plan.getContext().getScan();
Filter filter = scan.getFilter();
assertEquals(new SkipScanFilter(ImmutableList.<List<KeyRange>>of(ImmutableList.of(pointRange(tenantId1, entityId1), pointRange(tenantId1, entityId2), pointRange(tenantId2, entityId1), pointRange(tenantId2, entityId2))), SchemaUtil.VAR_BINARY_SCHEMA), filter);
}
use of org.apache.phoenix.filter.SkipScanFilter in project phoenix by apache.
the class WhereCompilerTest method testInListWithAnd1GTEFilter.
@Test
public void testInListWithAnd1GTEFilter() throws SQLException {
String tenantId1 = "000000000000001";
String tenantId2 = "000000000000002";
String tenantId3 = "000000000000003";
String entityId1 = "00000000000000X";
String entityId2 = "00000000000000Y";
String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id>='%s' AND entity_id<='%s'", ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId1, entityId2);
PhoenixConnection pconn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES)).unwrap(PhoenixConnection.class);
PhoenixPreparedStatement pstmt = newPreparedStatement(pconn, query);
QueryPlan plan = pstmt.optimizeQuery();
Scan scan = plan.getContext().getScan();
Filter filter = scan.getFilter();
assertEquals(new SkipScanFilter(ImmutableList.of(Arrays.asList(pointRange(tenantId1), pointRange(tenantId2), pointRange(tenantId3)), Arrays.asList(PChar.INSTANCE.getKeyRange(Bytes.toBytes(entityId1), true, Bytes.toBytes(entityId2), true))), plan.getTableRef().getTable().getRowKeySchema()), filter);
}
use of org.apache.phoenix.filter.SkipScanFilter in project phoenix by apache.
the class ParallelIteratorsSplitTest method foreach.
private static Collection<?> foreach(KeyRange[][] ranges, int[] widths, KeyRange[] expectedSplits) {
RowKeySchema schema = buildSchema(widths);
List<List<KeyRange>> slots = Lists.transform(Lists.newArrayList(ranges), ARRAY_TO_LIST);
SkipScanFilter filter = new SkipScanFilter(slots, schema);
// Always set start and stop key to max to verify we are using the information in skipscan
// filter over the scan's KMIN and KMAX.
Scan scan = new Scan().setFilter(filter);
ScanRanges scanRanges = ScanRanges.createSingleSpan(schema, slots);
List<Object> ret = Lists.newArrayList();
ret.add(new Object[] { scan, scanRanges, Arrays.<KeyRange>asList(expectedSplits) });
return ret;
}
use of org.apache.phoenix.filter.SkipScanFilter in project phoenix by apache.
the class ScanRanges method intersectScan.
public Scan intersectScan(Scan scan, final byte[] originalStartKey, final byte[] originalStopKey, final int keyOffset, boolean crossesRegionBoundary) {
byte[] startKey = originalStartKey;
byte[] stopKey = originalStopKey;
if (stopKey.length > 0 && Bytes.compareTo(startKey, stopKey) >= 0) {
return null;
}
// 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;
assert (scanKeyOffset == 0 || keyOffset == 0);
// Total offset for startKey/stopKey. Either 1 for salted tables or the prefix length
// of the current region for local indexes. We'll never have a case where a table is
// both salted and local.
final int totalKeyOffset = scanKeyOffset + keyOffset;
byte[] prefixBytes = ByteUtil.EMPTY_BYTE_ARRAY;
if (totalKeyOffset > 0) {
prefixBytes = ScanUtil.getPrefix(startKey, totalKeyOffset);
/*
* If our startKey to stopKey crosses a region boundary consider everything after the startKey as our scan
* is always done within a single region. This prevents us from having to prefix the key prior to knowing
* whether or not there may be an intersection. We can't calculate whether or not we've crossed a region
* boundary for local indexes, because we don't know the key offset of the next region, but only for the
* current one (which is the one passed in). If the next prefix happened to be a subset of the previous
* prefix, then this wouldn't detect that we crossed a region boundary.
*/
if (crossesRegionBoundary) {
stopKey = ByteUtil.EMPTY_BYTE_ARRAY;
}
}
int scanStartKeyOffset = scanKeyOffset;
byte[] scanStartKey = scan == null ? this.scanRange.getLowerRange() : scan.getStartRow();
// Compare ignoring key prefix and salt byte
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;
scanStartKeyOffset = totalKeyOffset;
}
int scanStopKeyOffset = scanKeyOffset;
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;
scanStopKeyOffset = totalKeyOffset;
}
// 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;
// start/stop or the scanRanges start/stop.
if (this.useSkipScanFilter()) {
byte[] skipScanStartKey = scanStartKey;
byte[] skipScanStopKey = scanStopKey;
// we need to remove the prefix before running our intersect method.
if (scanKeyOffset > 0) {
if (skipScanStartKey != originalStartKey) {
// original already has correct salt byte
skipScanStartKey = replaceSaltByte(skipScanStartKey, prefixBytes);
}
if (skipScanStopKey != originalStopKey) {
skipScanStopKey = replaceSaltByte(skipScanStopKey, prefixBytes);
}
} else if (keyOffset > 0) {
if (skipScanStartKey == originalStartKey) {
skipScanStartKey = stripPrefix(skipScanStartKey, keyOffset);
}
if (skipScanStopKey == originalStopKey) {
skipScanStopKey = stripPrefix(skipScanStopKey, keyOffset);
}
}
if (scan == null) {
return filter.hasIntersect(skipScanStartKey, skipScanStopKey) ? HAS_INTERSECTION : null;
}
Filter filter = scan.getFilter();
SkipScanFilter newSkipScanFilter = null;
if (filter instanceof SkipScanFilter) {
SkipScanFilter oldSkipScanFilter = (SkipScanFilter) filter;
newFilter = newSkipScanFilter = oldSkipScanFilter.intersect(skipScanStartKey, skipScanStopKey);
if (newFilter == null) {
return null;
}
} else if (filter instanceof FilterList) {
FilterList oldList = (FilterList) filter;
FilterList newList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
newFilter = newList;
for (Filter f : oldList.getFilters()) {
if (f instanceof SkipScanFilter) {
newSkipScanFilter = ((SkipScanFilter) f).intersect(skipScanStartKey, skipScanStopKey);
if (newSkipScanFilter == null) {
return null;
}
newList.addFilter(newSkipScanFilter);
} else {
newList.addFilter(f);
}
}
}
// have an enclosing range when we do a point lookup.
if (isPointLookup) {
scanStartKey = ScanUtil.getMinKey(schema, newSkipScanFilter.getSlots(), slotSpan);
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();
}
Scan newScan = ScanUtil.newScan(scan);
newScan.setFilter(newFilter);
// for it.
if (totalKeyOffset > 0) {
if (scanStartKey != originalStartKey) {
scanStartKey = prefixKey(scanStartKey, scanKeyOffset, prefixBytes, keyOffset);
}
if (scanStopKey != originalStopKey) {
scanStopKey = prefixKey(scanStopKey, scanKeyOffset, prefixBytes, keyOffset);
}
}
// Don't let the stopRow of the scan go beyond the originalStopKey
if (originalStopKey.length > 0 && Bytes.compareTo(scanStopKey, originalStopKey) > 0) {
scanStopKey = originalStopKey;
}
if (scanStopKey.length > 0 && Bytes.compareTo(scanStartKey, scanStopKey) >= 0) {
return null;
}
newScan.setAttribute(SCAN_ACTUAL_START_ROW, scanStartKey);
newScan.setStartRow(scanStartKey);
newScan.setStopRow(scanStopKey);
return newScan;
}
Aggregations