phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamestay...@apache.org
Subject [1/4] phoenix git commit: PHOENIX-2920 Incorrect Queries on Multi-tenant tables with WHERE clause containing Row Value Constructor
Date Tue, 14 Jun 2016 01:02:39 GMT
Repository: phoenix
Updated Branches:
  refs/heads/4.x-HBase-1.1 95b4a7b23 -> 9f0736f8d


PHOENIX-2920 Incorrect Queries on Multi-tenant tables with WHERE clause containing Row Value
Constructor


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

Branch: refs/heads/4.x-HBase-1.1
Commit: 9f0736f8d668695ee180d4dc0a8f1597cd0b05eb
Parents: 22b1c9e
Author: James Taylor <jamestaylor@apache.org>
Authored: Mon Jun 13 09:08:47 2016 -0700
Committer: James Taylor <jamestaylor@apache.org>
Committed: Mon Jun 13 18:05:14 2016 -0700

----------------------------------------------------------------------
 .../phoenix/end2end/RowValueConstructorIT.java  | 48 ++++++++++++++++++++
 .../apache/phoenix/compile/WhereOptimizer.java  | 27 +++++++++--
 .../phoenix/compile/WhereOptimizerTest.java     | 33 ++++++++++++++
 3 files changed, 103 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f0736f8/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 ea91f4f..ce38fcf 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
@@ -42,6 +42,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.Date;
 import java.sql.DriverManager;
@@ -1652,4 +1653,51 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT
{
 		assertEquals("403", rs.getString(4));
 	}
 
+    @Test
+    public void testMultiTenantRVC() throws Exception {
+        Connection conn = nextConnection(getUrl());
+        String tableName = "mtRVC";
+        String ddl = "CREATE TABLE " + tableName 
+                + " (\n" + 
+                "    pk1 VARCHAR NOT NULL,\n" + 
+                "    pk2 DECIMAL NOT NULL,\n" + 
+                "    v1 VARCHAR\n" + 
+                "    CONSTRAINT PK PRIMARY KEY \n" + 
+                "    (\n" + 
+                "        pk1,\n" + 
+                "        pk2\n" + 
+                "    )\n" + 
+                ") MULTI_TENANT=true,IMMUTABLE_ROWS=true";
+        conn.createStatement().execute(ddl);
+
+        conn = nextConnection(getUrl());
+        ddl = "CREATE INDEX  " + tableName + "_idx"
+                + " ON " + tableName + " (v1)";
+        conn.createStatement().execute(ddl);
+        
+        conn = nextConnection(getUrl());
+        String upsert = "UPSERT INTO " + tableName + " VALUES(?, ?, ?)";
+        PreparedStatement stmt = conn.prepareStatement(upsert);
+        stmt.setString(1, "a");
+        stmt.setInt(2, 1);
+        stmt.setString(3, "value");
+        stmt.execute();
+        stmt.setString(1, "a");
+        stmt.setInt(2, 2);
+        stmt.setString(3, "value");
+        stmt.execute();
+        conn.commit();
+
+        conn = nextConnection(getUrl());
+        String query = "SELECT pk1, pk2, v1 FROM " + tableName + " WHERE pk1 = 'a' AND\n"
+ 
+                "(pk1, pk2) > ('a', 1)\n" + 
+                "ORDER BY PK1, PK2\n" + 
+                "LIMIT 2";
+        ResultSet rs = conn.createStatement().executeQuery(query);
+        assertTrue(rs.next());
+        assertEquals("a", rs.getString(1));
+        assertTrue(new BigDecimal("2").compareTo(rs.getBigDecimal(2)) == 0);
+        assertEquals("value", rs.getString(3));
+        assertFalse(rs.next());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f0736f8/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 0122712..e1e3c53 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
@@ -1330,11 +1330,28 @@ public class WhereOptimizer {
                     // For example: a < (1,2) is true if a = 1, so we need to switch
                     // the compare op to <= like this: a <= 1. Since we strip trailing
nulls
                     // in the rvc, we don't need to worry about the a < (1,null) case.
-                    if (usedAllOfLHS && rvc.getChildren().size() < rhs.getChildren().size())
{
-                        if (op == CompareOp.LESS) {
-                            op = CompareOp.LESS_OR_EQUAL;
-                        } else if (op == CompareOp.GREATER_OR_EQUAL) {
-                            op = CompareOp.GREATER;
+                    if (usedAllOfLHS) {
+                        if (rvc.getChildren().size() < rhs.getChildren().size()) {
+                            if (op == CompareOp.LESS) {
+                                op = CompareOp.LESS_OR_EQUAL;
+                            } else if (op == CompareOp.GREATER_OR_EQUAL) {
+                                op = CompareOp.GREATER;
+                            }
+                        }
+                    } else {
+                        // If we're not using all of the LHS, we need to expand the range
on either
+                        // side to take into account the rest of the LHS. For example:
+                        // WHERE (pk1, pk3) > ('a',1) AND pk1 = 'a'. In this case, we'll
end up
+                        // only using (pk1) and ('a'), so if we use a > operator the expression
+                        // would end up as degenerate since we'd have a non inclusive range
for
+                        // ('a'). By switching the operator to extend the range, we end up
with
+                        // an ('a') inclusive range which is correct.
+                        if (rvc.getChildren().size() < rhs.getChildren().size()) {
+                            if (op == CompareOp.LESS) {
+                                op = CompareOp.LESS_OR_EQUAL;
+                            } else if (op == CompareOp.GREATER) {
+                                op = CompareOp.GREATER_OR_EQUAL;
+                            }
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f0736f8/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
index 05fea8d..353b88f 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
@@ -1625,6 +1625,39 @@ public class WhereOptimizerTest extends BaseConnectionlessQueryTest
{
     }
     
     @Test
+    public void testQueryMoreRVC() throws SQLException {
+        String tenantId = "000000000000001";
+        String parentId = "000000000000008";
+        
+        String ddl = "CREATE TABLE rvcTestIdx "
+                + " (\n" + 
+                "    pk1 VARCHAR NOT NULL,\n" + 
+                "    v1 VARCHAR,\n" + 
+                "    pk2 DECIMAL NOT NULL,\n" + 
+                "    CONSTRAINT PK PRIMARY KEY \n" + 
+                "    (\n" + 
+                "        pk1,\n" + 
+                "        v1,\n" + 
+                "        pk2\n" + 
+                "    )\n" + 
+                ") MULTI_TENANT=true,IMMUTABLE_ROWS=true";
+        Connection conn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES));
+        conn.createStatement().execute(ddl);
+        String query = "SELECT pk1, pk2, v1 FROM rvcTestIdx WHERE pk1 = 'a' AND\n" + 
+                "(pk1, pk2) > ('a', 1)\n" + 
+                "ORDER BY PK1, PK2\n" + 
+                "LIMIT 2";
+        StatementContext context = compileStatement(query, 2);
+        Scan scan = context.getScan();
+        Filter filter = scan.getFilter();
+        assertNotNull(filter);
+        byte[] startRow = Bytes.toBytes("a");
+        byte[] stopRow = ByteUtil.concat(startRow, ByteUtil.nextKey(QueryConstants.SEPARATOR_BYTE_ARRAY));
+        assertArrayEquals(startRow, scan.getStartRow());
+        assertArrayEquals(stopRow, scan.getStopRow());
+    }
+    
+    @Test
     public void testCombiningRVCUsingOr() throws SQLException {
         String firstTenantId = "000000000000001";
         String secondTenantId = "000000000000005";


Mime
View raw message