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 2018/05/22 20:39:54 UTC
[11/22] phoenix git commit: PHOENIX-4734 SQL Query with an RVC
expression lexographically higher than all values in an OR clause causes
query to blow up
PHOENIX-4734 SQL Query with an RVC expression lexographically higher than all values in an OR clause causes query to blow up
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/72fa8749
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/72fa8749
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/72fa8749
Branch: refs/heads/omid2
Commit: 72fa8749eb443b6fb9cb6436b06891642eff0440
Parents: 5dc873d
Author: Thomas D'Silva <td...@apache.org>
Authored: Thu May 10 16:30:36 2018 -0700
Committer: Thomas D'Silva <td...@apache.org>
Committed: Fri May 11 09:33:35 2018 -0700
----------------------------------------------------------------------
.../phoenix/end2end/RowValueConstructorIT.java | 120 +++++++++++++++++++
.../org/apache/phoenix/compile/ScanRanges.java | 5 +
2 files changed, 125 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/72fa8749/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 df7603a..fb04261 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
@@ -48,6 +48,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
+import java.util.List;
import java.util.Properties;
import org.apache.phoenix.util.DateUtil;
@@ -57,6 +58,9 @@ import org.apache.phoenix.util.QueryUtil;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.Test;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
public class RowValueConstructorIT extends ParallelStatsDisabledIT {
@@ -1646,4 +1650,120 @@ public class RowValueConstructorIT extends ParallelStatsDisabledIT {
assertEquals("value", rs.getString(3));
assertFalse(rs.next());
}
+
+ @Test
+ /**
+ * Verifies that a query with a RVC expression lexographically higher than all values in an OR
+ * clause causes query works see PHOENIX-4734
+ */
+ public void testRVCWithAndClause() throws Exception {
+ final int numItemsInClause = 5;
+ Properties tenantProps = new Properties();
+ tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "tenant1");
+ String fullTableName = SchemaUtil.getTableName("S", "T_" + generateUniqueName());
+ String fullViewName = SchemaUtil.getTableName("S", "V_" + generateUniqueName());
+ try (Connection tenantConn = DriverManager.getConnection(getUrl(), tenantProps)) {
+ tenantConn.setAutoCommit(false);
+ createBaseTableAndTenantView(tenantConn, fullTableName, fullViewName);
+ loadDataIntoTenantView(tenantConn, fullViewName);
+ List<String> objectIdsList =
+ selectObjectIdsForInClause(tenantConn, fullViewName, numItemsInClause);
+ StringBuilder querySb = generateQueryToTest(numItemsInClause, fullViewName);
+ PreparedStatement ps = tenantConn.prepareStatement(querySb.toString());
+ int numbBindVarsSet = 0;
+ String objectId = null;
+ for (int i = 0; i < numItemsInClause; i++) {
+ objectId = objectIdsList.get(i);
+ ps.setString((i + 1), objectId);
+ numbBindVarsSet++;
+ }
+ assertEquals(numItemsInClause, numbBindVarsSet);
+ assertEquals("v1000", objectId);
+ ps.setString(numItemsInClause + 1, "z00");
+ ps.setString(numItemsInClause + 2, "v1000"); // This value must match or be
+ // lexographically higher than the highest
+ // value in the IN clause
+ // Query should execute and return 0 results
+ ResultSet rs = ps.executeQuery();
+ assertFalse(
+ "Query should return no results as IN clause and RVC clause are disjoint sets",
+ rs.next());
+ }
+ }
+
+ private StringBuilder generateQueryToTest(int numItemsInClause, String fullViewName) {
+ StringBuilder querySb =
+ new StringBuilder("SELECT OBJECT_ID,OBJECT_DATA2,OBJECT_DATA FROM " + fullViewName);
+ querySb.append(" WHERE ((");
+ List<String> orClauses = Lists.newArrayList();
+ for (int i = 1; i < (numItemsInClause + 1); i++) {
+ orClauses.add("OBJECT_ID = ?");
+ }
+ querySb.append(Joiner.on(" OR ").join(orClauses));
+ querySb.append(") AND (KEY_PREFIX,OBJECT_ID) > (?,?)) ORDER BY OBJECT_ID LIMIT 125");
+ System.out.println(querySb);
+ return querySb;
+ }
+
+ private List<String> selectObjectIdsForInClause(Connection tenantConn, String fullViewName,
+ int numItemsInClause) throws SQLException {
+ String sqlForObjIds =
+ "SELECT OBJECT_ID FROM " + fullViewName + " ORDER BY OBJECT_ID LIMIT "
+ + numItemsInClause;
+ PreparedStatement ps = tenantConn.prepareStatement(sqlForObjIds);
+ ResultSet rs = ps.executeQuery();
+ List<String> objectIdsList = Lists.newArrayList();
+ System.out.println("ObjectIds: ");
+ while (rs.next()) {
+ System.out.println("Object Id: " + rs.getString("OBJECT_ID"));
+ objectIdsList.add(rs.getString("OBJECT_ID"));
+ }
+ assertEquals(numItemsInClause, objectIdsList.size());
+ return objectIdsList;
+ }
+
+ private void loadDataIntoTenantView(Connection tenantConn, String fullViewName)
+ throws SQLException {
+ for (int i = 0; i < 2000; i++) {
+ String objectId = "v" + i;
+ String upsert =
+ "UPSERT INTO " + fullViewName
+ + " (OBJECT_ID, OBJECT_DATA, OBJECT_DATA2) VALUES ('" + objectId
+ + "', 'data','data2')";
+ PreparedStatement ps = tenantConn.prepareStatement(upsert);
+ ps.executeUpdate();
+ }
+ tenantConn.commit();
+
+ // Validate Data was loaded correctly
+ PreparedStatement selectStatement =
+ tenantConn.prepareStatement(
+ "SELECT OBJECT_ID FROM " + fullViewName + " ORDER BY OBJECT_ID");
+ ResultSet rs = selectStatement.executeQuery();
+ int count = 0;
+ while (rs.next()) {
+ count++;
+ }
+ assertEquals(2000, count);
+ }
+
+ private void createBaseTableAndTenantView(Connection tenantConn, String fulTableName,
+ String fullViewName) throws SQLException {
+ String ddl =
+ "CREATE TABLE IF NOT EXISTS " + fulTableName + " (TENANT_ID CHAR(15) NOT NULL,"
+ + " KEY_PREFIX CHAR(3) NOT NULL," + " CREATED_DATE DATE,"
+ + " CREATED_BY CHAR(15)," + " SYSTEM_MODSTAMP DATE"
+ + " CONSTRAINT PK PRIMARY KEY (TENANT_ID,KEY_PREFIX)"
+ + ") VERSIONS=1, MULTI_TENANT=true, IMMUTABLE_ROWS=TRUE, REPLICATION_SCOPE=1";
+ createTestTable(getUrl(), ddl);
+
+ String tenantViewDdl =
+ "CREATE VIEW IF NOT EXISTS " + fullViewName + " (OBJECT_ID VARCHAR(18) NOT NULL, "
+ + "OBJECT_DATA VARCHAR(131072), " + "OBJECT_DATA2 VARCHAR(131072), "
+ + "CONSTRAINT PK PRIMARY KEY (OBJECT_ID)) " + "AS SELECT * FROM "
+ + fulTableName + " WHERE KEY_PREFIX = 'z00'";
+ // Get tenant specific connection
+ PreparedStatement stmt2 = tenantConn.prepareStatement(tenantViewDdl);
+ stmt2.execute();
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/72fa8749/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 8c71248..019f15d 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
@@ -105,6 +105,11 @@ public class ScanRanges {
keyRanges.add(KeyRange.getKeyRange(key));
}
}
+ // while doing a point look up if after intersecting with the MinMaxrange there are
+ // no more keyranges left then just return
+ if (keyRanges.isEmpty()) {
+ return NOTHING;
+ }
ranges = Collections.singletonList(keyRanges);
useSkipScan = keyRanges.size() > 1;
// Treat as binary if descending because we've got a separator byte at the end