This is an automated email from the ASF dual-hosted git repository.

stoty pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/4.x by this push:
     new 0d4a3f2  PHOENIX-5884 Join query return empty result when filters for 
both the tables are present
0d4a3f2 is described below

commit 0d4a3f2415dd75d46f3800d6e0e8777ae6c88063
Author: Ankit Singhal <[email protected]>
AuthorDate: Fri May 22 16:30:20 2020 +0200

    PHOENIX-5884 Join query return empty result when filters for both the 
tables are present
---
 .../java/org/apache/phoenix/end2end/InListIT.java  | 18 ++++++
 .../join/WhereOptimizerForJoinFiltersIT.java       | 73 ++++++++++++++++++++++
 .../org/apache/phoenix/compile/WhereOptimizer.java | 23 ++++---
 3 files changed, 104 insertions(+), 10 deletions(-)

diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
index 68d27cb..b0aee8f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
@@ -434,6 +434,24 @@ public class InListIT extends ParallelStatsDisabledIT {
         testWithIntegerTypesWithVariedSaltingAndTenancy(DEFAULT_UPSERT_BODIES, 
whereClause, expecteds);
     }
 
+    @Test public void testOverlappingRVCWithMiddleColumn() throws Exception {
+        String whereClause =
+            "WHERE pk2=3 and (pk1, pk2, pk3, pk4) IN ((2, 3, 6, 6), (2, 3, 4, 
5)) ";
+        List<String> expecteds = singletonList("row2");
+
+        testWithIntegerTypesWithVariedSaltingAndTenancy(DEFAULT_UPSERT_BODIES, 
whereClause,
+            expecteds);
+    }
+
+    @Test public void testOverlappingRVCWithMultipleMiddleColumn() throws 
Exception {
+        String whereClause =
+            "WHERE (pk2,pk3) in ((3,4)) and (pk1, pk2, pk3, pk4) IN ((2, 3, 6, 
6), (2, 3, 4, 5)) ";
+        List<String> expecteds = singletonList("row2");
+
+        testWithIntegerTypesWithVariedSaltingAndTenancy(DEFAULT_UPSERT_BODIES, 
whereClause,
+            expecteds);
+    }
+
     @Test
     public void testOverlappingRVCAndRVCPartiallyQualifiedBegin() throws 
Exception {
         String whereClause = "WHERE (pk1, pk2) IN ((1, 2), (2, 3)) AND (pk2, 
pk3) IN ((3, 4), (3, 6))";
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/WhereOptimizerForJoinFiltersIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/WhereOptimizerForJoinFiltersIT.java
new file mode 100644
index 0000000..33f1bd8
--- /dev/null
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/WhereOptimizerForJoinFiltersIT.java
@@ -0,0 +1,73 @@
+package org.apache.phoenix.end2end.join;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.junit.Test;
+
+public class WhereOptimizerForJoinFiltersIT extends ParallelStatsDisabledIT {
+
+  String allValues =
+      
"('201904','ID2_VAL','ID3_VAL','01','000000','ID4_VAL','ID5_VAL','2019-05-30 
22:41:37.000')\n"
+          + 
"('201905','ID2_VAL','ID3_VAL','01','000000','ID4_VAL','ID5_VAL','2019-12-31 
22:59:59.000') \n"
+          + 
"('201905','ID2_VAL','ID3_VAL','30','000000','ID4_VAL','ID5_VAL','2019-12-31 
22:59:59.000') \n"
+          + 
"('201904','ID2_VAL','ID3_VAL2','01','000000','ID4_VAL','ID5_VAL','2019-05-30 
22:41:37.000')\n"
+          + 
"('201905','ID2_VAL','ID3_VAL2','30','000000','ID4_VAL','ID5_VAL','2019-12-31 
22:59:59.000')";
+
+  private void createTable(Connection conn, String tableName) throws 
SQLException {
+    conn.createStatement().execute("CREATE TABLE " + tableName + " (" + "    
id1 CHAR(6) NOT NULL,"
+        + "    id2 VARCHAR(22) NOT NULL," + "    id3 VARCHAR(12) NOT NULL,"
+        + "    id4 CHAR(2) NOT NULL," + "    id5 CHAR(6) NOT NULL, "
+        + "    id6 VARCHAR(200) NOT NULL," + "    id7 VARCHAR(50) NOT NULL," + 
"    ts TIMESTAMP ,"
+        + "    CONSTRAINT PK_JOIN_AND_INTERSECTION_TABLE PRIMARY 
KEY(id1,id2,id3,id4,id5,id6,id7)"
+        + ")");
+  }
+
+  @Test public void testJoin() throws SQLException {
+    String leftTable = generateUniqueName();
+    String rightTable = generateUniqueName();
+    Connection conn = DriverManager.getConnection(getUrl());
+    createTable(conn, leftTable);
+    createTable(conn, rightTable);
+    for (String values : allValues.split("\n")) {
+      conn.createStatement().execute(
+          "UPSERT INTO " + leftTable + "(id1,id2,id3,id4, id5, id6, id7,ts) 
VALUES" + values);
+      conn.createStatement().execute(
+          "UPSERT INTO " + rightTable + "(id1,id2,id3,id4, id5, id6, id7,ts) 
VALUES" + values);
+    }
+    conn.commit();
+    ResultSet rs =
+        conn.createStatement().executeQuery("select count(*) from "+leftTable);
+    assertTrue(rs.next());
+    assertEquals(5, rs.getInt(1));
+    String query =
+        "SELECT m.*,r.* FROM "+leftTable+" m join "+rightTable+" r "
+            + " on m.id3 = r.id3  and m.id2 = r.id2 "
+            + " and m.id4 = r.id4 and m.id5 = r.id5 "
+            + " and m.id1 = r.id1 and m.ts = r.ts "
+            + " where m.id1 IN ('201904','201905') "
+            + " and r.id1 IN ('201904','201905') and r.id2 = 'ID2_VAL' and 
m.id2 = 'ID2_VAL' "
+            + "            and m.id3 IN ('ID3_VAL','ID3_VAL2') "
+            + " and r.id3 IN ('ID3_VAL','ID3_VAL2') LIMIT 1000000000";
+    rs = conn.createStatement().executeQuery(query);
+    assertTrue(rs.next());
+    query =
+        "SELECT m.*,r.* FROM "+leftTable+" m join "+rightTable+" r "
+            + " on m.id3 = r.id3 and m.id2 = r.id2 "
+            + " and m.id4 = r.id4  and m.id5 = r.id5 "
+            + " and m.id1 = r.id1  and m.ts = r.ts "
+            + " where  r.id1 IN ('201904','201905') "
+            + " and r.id2 = 'ID2_VAL' "
+            + " and r.id3 IN ('ID3_VAL','ID3_VAL2') LIMIT 1000000000";
+    rs = conn.createStatement().executeQuery(query);
+    assertTrue(rs.next());
+    conn.close();
+  }
+
+}
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 34b75dc..b1fd238 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
@@ -1370,19 +1370,22 @@ public class WhereOptimizer {
                 // will never overlap. We do not need to process both the 
lower and upper
                 // ranges since they are the same.
                 if (result.isSingleKey() && otherRange.isSingleKey()) {
-                    // Find the span of the trailing bytes as it could be more 
than one.
-                    // We need this to determine if the slot at the last 
position would
-                    // have a separator byte (i.e. is variable length).
-                    int pos = otherPKPos;
-                    rowKeySchema.iterator(trailingBytes, ptr, otherPKPos);
-                    while (rowKeySchema.next(ptr, pos, trailingBytes.length) 
!= null) {
-                        pos++;
+                    int minSpan = rowKeySchema.computeMinSpan(pkPos, result, 
ptr);
+                    int otherMinSpan =
+                        rowKeySchema.computeMinSpan(otherPKPos, otherRange, 
ptr);
+                    byte[] otherLowerRange;
+                    boolean isFixedWidthAtEnd;
+                    if (pkPos + minSpan <= otherPKPos + otherMinSpan) {
+                        otherLowerRange = otherRange.getLowerRange();
+                        isFixedWidthAtEnd = table.getPKColumns().get(pkPos + 
minSpan -1).getDataType().isFixedWidth();
+                    } else {
+                        otherLowerRange = trailingBytes;
+                        trailingBytes = otherRange.getLowerRange();
+                        isFixedWidthAtEnd = 
table.getPKColumns().get(otherPKPos + otherMinSpan 
-1).getDataType().isFixedWidth();
                     }
-                    byte[] otherLowerRange = otherRange.getLowerRange();
-                    boolean isFixedWidthAtEnd = 
table.getPKColumns().get(pos).getDataType().isFixedWidth();
                     // If the otherRange starts with the overlapping trailing 
byte *and* we're comparing
                     // the entire key (i.e. not just a leading subset), then 
we have an intersection.
-                    if (Bytes.startsWith(otherLowerRange, trailingBytes) && 
+                    if (Bytes.startsWith(otherLowerRange, trailingBytes) &&
                             (isFixedWidthAtEnd || 
                              otherLowerRange.length == trailingBytes.length || 
                              otherLowerRange[trailingBytes.length] == 
QueryConstants.SEPARATOR_BYTE)) {

Reply via email to