PHOENIX-1397 RVC combined with OR on first row key column results in NPE
(Samarth Jain)
Conflicts:
phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/989cd9a4
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/989cd9a4
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/989cd9a4
Branch: refs/heads/3.2
Commit: 989cd9a4d31ebb9e96bbb44be4a1ed4678fd3029
Parents: 55795e8
Author: James Taylor <[email protected]>
Authored: Tue Nov 4 20:52:14 2014 -0800
Committer: James Taylor <[email protected]>
Committed: Tue Nov 4 23:09:18 2014 -0800
----------------------------------------------------------------------
.../phoenix/end2end/RowValueConstructorIT.java | 69 ++++++++++++++++++++
.../apache/phoenix/compile/WhereOptimizer.java | 22 ++++---
.../NewerTableAlreadyExistsException.java | 1 +
3 files changed, 84 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/989cd9a4/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
----------------------------------------------------------------------
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
index bf3d9db..9e3a5b0 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
@@ -1280,5 +1280,74 @@ public class RowValueConstructorIT extends
BaseClientManagedTimeIT {
conn.close();
}
}
+
+ // query against non-multitenant table. Salted - yes
+ @Test
+ public void testComparisonAgainstRVCCombinedWithOrAnd_1() throws Exception
{
+ String tableDDL = "CREATE TABLE RVC1 (tenantId char(15) NOT NULL, pk2
char(15) NOT NULL, pk3 INTEGER NOT NULL, c1 INTEGER constraint pk primary key
(tenantId,pk2,pk3)) SALT_BUCKETS = 4";
+ createTestTable(getUrl(), tableDDL, null, nextTimestamp());
+
+ Connection conn = nextConnection(getUrl());
+ conn.createStatement().executeUpdate("upsert into RVC1 (tenantId, pk2,
pk3, c1) values ('ABC', 'helo1', 1, 1)");
+ conn.createStatement().executeUpdate("upsert into RVC1 (tenantId, pk2,
pk3, c1) values ('ABC', 'helo2', 2, 2)");
+ conn.createStatement().executeUpdate("upsert into RVC1 (tenantId, pk2,
pk3, c1) values ('DEF', 'helo3', 3, 3)");
+ conn.commit();
+ conn.close();
+
+ conn = nextConnection(getUrl());
+ PreparedStatement stmt = conn.prepareStatement("select pk2, pk3 from
RVC1 WHERE (tenantId = ? OR tenantId = ?) AND (tenantId, pk2, pk3) > (?, ?, ?)
LIMIT 100");
+ stmt.setString(1, "ABC");
+ stmt.setString(2, "DEF");
+
+ // give back all rows after row 1 - ABC|helo1|1
+ stmt.setString(3, "ABC");
+ stmt.setString(4, "helo1");
+ stmt.setInt(5, 1);
+
+ ResultSet rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("helo2", rs.getString(1));
+ assertEquals(2, rs.getInt(2));
+ assertTrue(rs.next());
+ assertEquals("helo3", rs.getString(1));
+ assertEquals(3, rs.getInt(2));
+ assertFalse(rs.next());
+ }
+
+ // query against tenant specific view. Salted base table.
+ @Test
+ public void testComparisonAgainstRVCCombinedWithOrAnd_2() throws Exception
{
+ String tenantId = "ABC";
+ String tenantSpecificUrl = getUrl() + ";" +
PhoenixRuntime.TENANT_ID_ATTRIB + '=' + tenantId;
+ String baseTableDDL = "CREATE TABLE RVC2 (tenant_id char(15) NOT NULL,
pk2 char(15) NOT NULL, pk3 INTEGER NOT NULL, c1 INTEGER constraint pk primary
key (tenant_id,pk2,pk3)) MULTI_TENANT=true, SALT_BUCKETS = 4";
+ createTestTable(getUrl(), baseTableDDL, null, nextTimestamp());
+ String tenantTableDDL = "CREATE VIEW t_view AS SELECT * FROM RVC2";
+ createTestTable(tenantSpecificUrl, tenantTableDDL, null,
nextTimestamp());
+
+ Connection conn = nextConnection(tenantSpecificUrl);
+ conn.createStatement().executeUpdate("upsert into t_view (pk2, pk3,
c1) values ('helo1', 1, 1)");
+ conn.createStatement().executeUpdate("upsert into t_view (pk2, pk3,
c1) values ('helo2', 2, 2)");
+ conn.createStatement().executeUpdate("upsert into t_view (pk2, pk3,
c1) values ('helo3', 3, 3)");
+ conn.commit();
+ conn.close();
+
+ conn = nextConnection(tenantSpecificUrl);
+ PreparedStatement stmt = conn.prepareStatement("select pk2, pk3 from
t_view WHERE (pk2 = ? OR pk2 = ?) AND (pk2, pk3) > (?, ?) LIMIT 100");
+ stmt.setString(1, "helo1");
+ stmt.setString(2, "helo3");
+
+ // return rows after helo1|1
+ stmt.setString(3, "helo1");
+ stmt.setInt(4, 1);
+
+ ResultSet rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("helo3", rs.getString(1));
+ assertEquals(3, rs.getInt(2));
+ assertFalse(rs.next());
+ conn.close();
+ }
+
+
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/989cd9a4/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git
a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index 94293a4..d6f008e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -106,6 +106,15 @@ public class WhereOptimizer {
PName tenantId = context.getConnection().getTenantId();
PTable table = context.getCurrentTable().getTable();
boolean isEverything = (tenantId == null || !table.isMultiTenant()) &&
table.getViewIndexId() == null;
+
+ Integer nBuckets = table.getBucketNum();
+ boolean isSalted = nBuckets != null;
+ RowKeySchema schema = table.getRowKeySchema();
+ boolean isMultiTenant = tenantId != null && table.isMultiTenant();
+ if (isMultiTenant) {
+ tenantId = ScanUtil.padTenantIdIfNecessary(schema, isSalted,
tenantId);
+ }
+
if (whereClause == null && isEverything) {
context.setScanRanges(ScanRanges.EVERYTHING);
return whereClause;
@@ -146,8 +155,6 @@ public class WhereOptimizer {
int nPKColumns = table.getPKColumns().size();
int[] slotSpan = new int[nPKColumns];
List<Expression> removeFromExtractNodes = null;
- Integer nBuckets = table.getBucketNum();
- RowKeySchema schema = table.getRowKeySchema();
List<List<KeyRange>> cnf =
Lists.newArrayListWithExpectedSize(schema.getMaxFields());
KeyRange minMaxRange = keySlots.getMinMaxRange();
if (minMaxRange == null) {
@@ -156,8 +163,6 @@ public class WhereOptimizer {
boolean hasMinMaxRange = (minMaxRange != KeyRange.EVERYTHING_RANGE);
int minMaxRangeOffset = 0;
byte[] minMaxRangePrefix = null;
- boolean isSalted = nBuckets != null;
- boolean isMultiTenant = tenantId != null && table.isMultiTenant();
boolean hasViewIndex = table.getViewIndexId() != null;
if (hasMinMaxRange) {
int minMaxRangeSize = (isSalted ? SaltingUtil.NUM_SALTING_BYTES :
0)
@@ -182,7 +187,6 @@ public class WhereOptimizer {
// Add tenant data isolation for tenant-specific tables
if (isMultiTenant) {
- tenantId = ScanUtil.padTenantIdIfNecessary(schema, isSalted,
tenantId);
byte[] tenantIdBytes = tenantId.getBytes();
KeyRange tenantIdKeyRange = KeyRange.getKeyRange(tenantIdBytes);
cnf.add(singletonList(tenantIdKeyRange));
@@ -704,9 +708,11 @@ public class WhereOptimizer {
minMaxRange =
minMaxRange.union(childSlot.getMinMaxRange());
thePosition = initialPos;
for (KeySlot slot : childSlot) {
- List<Expression> extractNodes =
slot.getKeyPart().getExtractNodes();
- extractAll &= !extractNodes.isEmpty();
- slotExtractNodes.addAll(extractNodes);
+ if (slot != null) {
+ List<Expression> extractNodes =
slot.getKeyPart().getExtractNodes();
+ extractAll &= !extractNodes.isEmpty();
+ slotExtractNodes.addAll(extractNodes);
+ }
}
} else {
// TODO: Do the same optimization that we do for IN if the
childSlots specify a fully qualified row key
http://git-wip-us.apache.org/repos/asf/phoenix/blob/989cd9a4/phoenix-core/src/main/java/org/apache/phoenix/schema/NewerTableAlreadyExistsException.java
----------------------------------------------------------------------
diff --git
a/phoenix-core/src/main/java/org/apache/phoenix/schema/NewerTableAlreadyExistsException.java
b/phoenix-core/src/main/java/org/apache/phoenix/schema/NewerTableAlreadyExistsException.java
index 5404485..e6b7ffe 100644
---
a/phoenix-core/src/main/java/org/apache/phoenix/schema/NewerTableAlreadyExistsException.java
+++
b/phoenix-core/src/main/java/org/apache/phoenix/schema/NewerTableAlreadyExistsException.java
@@ -30,6 +30,7 @@ public class NewerTableAlreadyExistsException extends
TableAlreadyExistsExceptio
this.table = table;
}
+ @Override
public PTable getTable() {
return table;
}