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 2014/11/07 07:46:28 UTC
[2/5] phoenix git commit: PHOENIX-1416 Given a schema name,
DatabaseMetadata.getTables and getColumns calls erroneously match
tables without schema
PHOENIX-1416 Given a schema name, DatabaseMetadata.getTables and getColumns calls erroneously match tables without schema
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/6abe4df0
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/6abe4df0
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/6abe4df0
Branch: refs/heads/3.0
Commit: 6abe4df01e4c298a16f029c40e3b8cb120702f18
Parents: c971557
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Nov 6 17:57:57 2014 -0800
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Nov 6 22:38:19 2014 -0800
----------------------------------------------------------------------
.../end2end/QueryDatabaseMetaDataIT.java | 43 ++++++++++++++++++
.../org/apache/phoenix/compile/ScanRanges.java | 8 +++-
.../phoenix/expression/AndExpression.java | 4 +-
.../phoenix/expression/AndOrExpression.java | 11 +----
.../apache/phoenix/expression/OrExpression.java | 4 +-
.../phoenix/compile/WhereOptimizerTest.java | 47 ++++++++++++++++++++
6 files changed, 102 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryDatabaseMetaDataIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryDatabaseMetaDataIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryDatabaseMetaDataIT.java
index 9bf2b0c..83bb91d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryDatabaseMetaDataIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryDatabaseMetaDataIT.java
@@ -1058,4 +1058,47 @@ public class QueryDatabaseMetaDataIT extends BaseClientManagedTimeIT {
}
conn5.close();
}
+
+
+ @Test
+ public void testTableWithScemaMetadataScan() throws SQLException {
+ long ts = nextTimestamp();
+ Properties props = new Properties();
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+
+ conn.createStatement().execute("create table foo.bar(k varchar primary key)");
+ conn.createStatement().execute("create table bar(k varchar primary key)");
+ conn.close();
+
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+ conn = DriverManager.getConnection(getUrl(), props);
+
+ DatabaseMetaData metaData = conn.getMetaData();
+ ResultSet rs;
+
+ // Tricky case that requires returning false for null AND true expression
+ rs = metaData.getTables(null, "FOO", "BAR", null);
+ assertTrue(rs.next());
+ assertEquals("FOO",rs.getString("TABLE_SCHEM"));
+ assertEquals("BAR", rs.getString("TABLE_NAME"));
+ assertFalse(rs.next());
+
+ // Tricky case that requires end key to maintain trailing nulls
+ rs = metaData.getTables("", "FOO", "BAR", null);
+ assertTrue(rs.next());
+ assertEquals("FOO",rs.getString("TABLE_SCHEM"));
+ assertEquals("BAR", rs.getString("TABLE_NAME"));
+ assertFalse(rs.next());
+
+ rs = metaData.getTables("", null, "BAR", null);
+ assertTrue(rs.next());
+ assertEquals(null,rs.getString("TABLE_SCHEM"));
+ assertEquals("BAR", rs.getString("TABLE_NAME"));
+ assertTrue(rs.next());
+ assertEquals("FOO",rs.getString("TABLE_SCHEM"));
+ assertEquals("BAR", rs.getString("TABLE_NAME"));
+ assertFalse(rs.next());
+ }
+
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/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 d60a288..61b6451 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
@@ -440,9 +440,13 @@ public class ScanRanges {
if (ScanUtil.getTotalSpan(ranges, slotSpan) < schema.getMaxFields()) {
return false;
}
- for (List<KeyRange> orRanges : ranges) {
+ int lastIndex = ranges.size()-1;
+ for (int i = lastIndex; i >= 0; i--) {
+ List<KeyRange> orRanges = ranges.get(i);
for (KeyRange keyRange : orRanges) {
- if (!keyRange.isSingleKey()) {
+ // Special case for single trailing IS NULL. We cannot consider this as a point key because
+ // we strip trailing nulls when we form the key.
+ if (!keyRange.isSingleKey() || (i == lastIndex && keyRange == KeyRange.IS_NULL_RANGE)) {
return false;
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
index e9c2740..bb2dc7e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
@@ -79,8 +79,8 @@ public class AndExpression extends AndOrExpression {
}
@Override
- protected boolean getStopValue() {
- return Boolean.FALSE;
+ protected boolean isStopValue(Boolean value) {
+ return !Boolean.TRUE.equals(value);
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
index eebcd34..89ad02e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
@@ -21,7 +21,6 @@ import java.util.BitSet;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-
import org.apache.phoenix.schema.PDataType;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -45,11 +44,6 @@ public abstract class AndOrExpression extends BaseCompoundExpression {
}
@Override
- public int hashCode() {
- return 31 * super.hashCode() + Boolean.valueOf(this.getStopValue()).hashCode();
- }
-
- @Override
public PDataType getDataType() {
return PDataType.BOOLEAN;
}
@@ -67,7 +61,6 @@ public abstract class AndOrExpression extends BaseCompoundExpression {
@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
boolean isNull = false;
- boolean stopValue = getStopValue();
for (int i = 0; i < children.size(); i++) {
Expression child = children.get(i);
// If partial state is available, then use that to know we've already evaluated this
@@ -77,7 +70,7 @@ public abstract class AndOrExpression extends BaseCompoundExpression {
// evaluate versus getValue code path.
if (child.evaluate(tuple, ptr)) {
// Short circuit if we see our stop value
- if (Boolean.valueOf(stopValue).equals(PDataType.BOOLEAN.toObject(ptr, child.getDataType()))) {
+ if (isStopValue((Boolean)PDataType.BOOLEAN.toObject(ptr, child.getDataType()))) {
return true;
} else if (partialEvalState != null) {
partialEvalState.set(i);
@@ -93,5 +86,5 @@ public abstract class AndOrExpression extends BaseCompoundExpression {
return true;
}
- protected abstract boolean getStopValue();
+ protected abstract boolean isStopValue(Boolean value);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/phoenix-core/src/main/java/org/apache/phoenix/expression/OrExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/OrExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/OrExpression.java
index e8565c5..5b1b62e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/OrExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/OrExpression.java
@@ -38,8 +38,8 @@ public class OrExpression extends AndOrExpression {
}
@Override
- protected boolean getStopValue() {
- return Boolean.TRUE;
+ protected boolean isStopValue(Boolean value) {
+ return Boolean.TRUE.equals(value);
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/6abe4df0/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 032768b..1ce6c02 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
@@ -45,6 +45,7 @@ import org.apache.hadoop.hbase.HConstants;
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.filter.RowKeyComparisonFilter;
import org.apache.phoenix.filter.SingleKeyValueComparisonFilter;
import org.apache.phoenix.filter.SkipScanFilter;
@@ -1734,4 +1735,50 @@ public class WhereOptimizerTest extends BaseConnectionlessQueryTest {
return conn;
}
+ @Test
+ public void testTrailingIsNull() throws Exception {
+ String baseTableDDL = "CREATE TABLE t(\n " +
+ " a VARCHAR,\n" +
+ " b VARCHAR,\n" +
+ " CONSTRAINT pk PRIMARY KEY (a, b))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute(baseTableDDL);
+ conn.close();
+
+ String query = "SELECT * FROM t WHERE a = 'a' and b is null";
+ StatementContext context = compileStatement(query, Collections.<Object>emptyList());
+ Scan scan = context.getScan();
+ Filter filter = scan.getFilter();
+ assertNull(filter);
+ assertArrayEquals(Bytes.toBytes("a"), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
+
+
+ @Test
+ public void testTrailingIsNullWithOr() throws Exception {
+ String baseTableDDL = "CREATE TABLE t(\n " +
+ " a VARCHAR,\n" +
+ " b VARCHAR,\n" +
+ " CONSTRAINT pk PRIMARY KEY (a, b))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute(baseTableDDL);
+ conn.close();
+
+ String query = "SELECT * FROM t WHERE a = 'a' and (b is null or b = 'b')";
+ StatementContext context = compileStatement(query, Collections.<Object>emptyList());
+ Scan scan = context.getScan();
+ Filter filter = scan.getFilter();
+ assertTrue(filter instanceof SkipScanFilter);
+ SkipScanFilter skipScan = (SkipScanFilter)filter;
+ List<List<KeyRange>>slots = skipScan.getSlots();
+ assertEquals(2,slots.size());
+ assertEquals(1,slots.get(0).size());
+ assertEquals(2,slots.get(1).size());
+ assertEquals(KeyRange.getKeyRange(Bytes.toBytes("a")), slots.get(0).get(0));
+ assertTrue(KeyRange.IS_NULL_RANGE == slots.get(1).get(0));
+ assertEquals(KeyRange.getKeyRange(Bytes.toBytes("b")), slots.get(1).get(1));
+ assertArrayEquals(Bytes.toBytes("a"), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, Bytes.toBytes("b"), QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
}