This is an automated email from the ASF dual-hosted git repository. gokcen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/master by this push: new 74e4548 PHOENIX-6659 RVC query fix for variable column + fixed column 74e4548 is described below commit 74e4548117c7e26715d2b14dd3768b1043801aca Author: Gokcen Iskender <gisken...@salesforce.com> AuthorDate: Wed Mar 2 19:30:11 2022 -0800 PHOENIX-6659 RVC query fix for variable column + fixed column Signed-off-by: Gokcen Iskender <gokc...@gmail.com> --- .../phoenix/end2end/RowValueConstructorIT.java | 2 +- .../apache/phoenix/end2end/SkipScanQueryIT.java | 97 ++++++++++++++++++++++ .../org/apache/phoenix/compile/WhereOptimizer.java | 13 +-- 3 files changed, 106 insertions(+), 6 deletions(-) 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 f03e436..47d6327 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 @@ -369,7 +369,7 @@ public class RowValueConstructorIT extends ParallelStatsDisabledIT { count++; } // we have key values (7,5) (8,4) and (9,3) present in aTable. So the query should return the 3 records. - assertTrue(count == 3); + assertEquals(3, count); } finally { conn.close(); } diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanQueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanQueryIT.java index 3c835a5..74c9300 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanQueryIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanQueryIT.java @@ -42,8 +42,10 @@ import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.FilterList; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.phoenix.compile.ExplainPlan; import org.apache.phoenix.compile.QueryPlan; import org.apache.phoenix.filter.SkipScanFilter; +import org.apache.phoenix.jdbc.PhoenixPreparedStatement; import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.util.TestUtil; import org.apache.phoenix.util.SchemaUtil; @@ -717,6 +719,101 @@ public class SkipScanQueryIT extends ParallelStatsDisabledIT { } @Test + public void testRVCBug6659() throws Exception { + String tableName = generateUniqueName(); + String ddl = "CREATE TABLE " + tableName + " (PK1 VARCHAR NOT NULL, PK2 INTEGER NOT NULL, " + + "PK3 BIGINT NOT NULL CONSTRAINT PK PRIMARY KEY (PK1,PK2,PK3))"; + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement().execute(ddl); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',0,1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',1,1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',2,1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',3,1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',3,2)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a',4,1)"); + conn.commit(); + String query = "SELECT * FROM " + tableName + + " WHERE (PK1 = 'a') AND (PK1,PK2,PK3) <= ('a',3,1)"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + int rowCnt = 0; + do { + rowCnt++; + } while (rs.next()); + assertEquals(4, rowCnt); + } + } + + @Test + public void testRVCBug6659_Delete() throws Exception { + String tableName = generateUniqueName(); + String ddl = "CREATE TABLE " + tableName + " (PK1 DOUBLE NOT NULL, PK2 INTEGER NOT NULL, " + + " CONSTRAINT PK PRIMARY KEY (PK1,PK2))"; + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement().execute(ddl); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(10.0,10)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(20.0,20)"); + conn.commit(); + String query = "DELETE FROM " + tableName + + " WHERE (PK1,PK2) IN ((10.0, 10),(20.0, 20))"; + conn.createStatement().execute(query); + conn.commit(); + ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM " + tableName); + assertFalse(rs.next()); + } + } + + @Test + public void testRVCBug6659_AllVarchar() throws Exception { + String tableName = generateUniqueName(); + String ddl = "CREATE TABLE " + tableName + " (PK1 VARCHAR NOT NULL, PK2 VARCHAR NOT NULL, " + + "PK3 BIGINT NOT NULL CONSTRAINT PK PRIMARY KEY (PK1,PK2,PK3))"; + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement().execute(ddl); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a','0',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a','1',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a','3',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a','3',2)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a','4',1)"); + conn.commit(); + String query = "SELECT * FROM " + tableName + + " WHERE (PK1 = 'a') AND (PK1,PK2,PK3) <= ('a','3',1)"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + int rowCnt = 0; + do { + rowCnt++; + } while (rs.next()); + assertEquals(3, rowCnt); + } + } + + @Test + public void testRVCBug6659_IntVarcharBigint() throws Exception { + String tableName = generateUniqueName(); + String ddl = "CREATE TABLE " + tableName + " (PK1 INTEGER NOT NULL, PK2 VARCHAR NOT NULL, " + + "PK3 BIGINT NOT NULL CONSTRAINT PK PRIMARY KEY (PK1,PK2,PK3))"; + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement().execute(ddl); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(1,'0',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(1,'1',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(1,'3',1)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(1,'3',2)"); + conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES(1,'4',1)"); + conn.commit(); + String query = "SELECT * FROM " + tableName + + " WHERE (PK1 = 1) AND (PK1,PK2,PK3) <= (1,'3',1)"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + int rowCnt = 0; + do { + rowCnt++; + } while (rs.next()); + assertEquals(3, rowCnt); + } + } + + @Test public void testKeyRangesContainsAllValues() throws Exception { String tableName = generateUniqueName(); String ddl = "CREATE TABLE IF NOT EXISTS " + tableName + "(" + 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 65bbbfd..e0f5da3 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 @@ -29,6 +29,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import org.apache.phoenix.expression.DelegateExpression; import org.apache.phoenix.thirdparty.com.google.common.base.Optional; import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; @@ -361,8 +362,10 @@ public class WhereOptimizer { } } - private static KeyRange getTrailingRange(RowKeySchema rowKeySchema, int pkPos, KeyRange range, KeyRange clippedResult, ImmutableBytesWritable ptr) { - int separatorLength = rowKeySchema.getField(pkPos).getDataType().isFixedWidth() ? 0 : 1; + private static KeyRange getTrailingRange(RowKeySchema rowKeySchema, int clippedPkPos, KeyRange range, KeyRange clippedResult, ImmutableBytesWritable ptr) { + // We are interested in the clipped part's Seperator. Since we combined first part, we need to + // remove its separator from the trailing parts' start + int clippedSepLength= rowKeySchema.getField(clippedPkPos).getDataType().isFixedWidth() ? 0 : 1; byte[] lowerRange = KeyRange.UNBOUND; boolean lowerInclusive = false; // Lower range of trailing part of RVC must be true, so we can form a new range to intersect going forward @@ -370,7 +373,7 @@ public class WhereOptimizer { && range.getLowerRange().length > clippedResult.getLowerRange().length && Bytes.startsWith(range.getLowerRange(), clippedResult.getLowerRange())) { lowerRange = range.getLowerRange(); - int offset = clippedResult.getLowerRange().length + separatorLength; + int offset = clippedResult.getLowerRange().length + clippedSepLength; ptr.set(lowerRange, offset, lowerRange.length - offset); lowerRange = ptr.copyBytes(); lowerInclusive = range.isLowerInclusive(); @@ -381,7 +384,7 @@ public class WhereOptimizer { && range.getUpperRange().length > clippedResult.getUpperRange().length && Bytes.startsWith(range.getUpperRange(), clippedResult.getUpperRange())) { upperRange = range.getUpperRange(); - int offset = clippedResult.getUpperRange().length + separatorLength; + int offset = clippedResult.getUpperRange().length + clippedSepLength; ptr.set(upperRange, offset, upperRange.length - offset); upperRange = ptr.copyBytes(); upperInclusive = range.isUpperInclusive(); @@ -1307,7 +1310,7 @@ public class WhereOptimizer { // code doesn't work correctly for WhereOptimizerTest.testMultiSlotTrailingIntersect() if (result.isSingleKey() && !(range.isSingleKey() && otherRange.isSingleKey())) { int trailingPkPos = pkPos + Math.min(minSpan, otherMinSpan); - KeyRange trailingRange = getTrailingRange(rowKeySchema, trailingPkPos, minSpan > otherMinSpan ? range : otherRange, result, ptr); + KeyRange trailingRange = getTrailingRange(rowKeySchema, pkPos, minSpan > otherMinSpan ? range : otherRange, result, ptr); trailingRanges[trailingPkPos] = trailingRanges[trailingPkPos].intersect(trailingRange); } else { // Add back clipped part of range