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/02/10 18:13:58 UTC
[1/8] Fix failing unit test, rename tests for consistency
Updated Branches:
refs/heads/master fe18e96ae -> 0ea954eae
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
index 2816023..a5d7d1e 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
@@ -215,8 +215,8 @@ public class TestUtil {
return new ComparisonExpression(op, Arrays.asList(e, LiteralExpression.newConstant(o)));
}
- public static Expression columnComparison(CompareOp op, PColumn c1, PColumn c2) {
- return new ComparisonExpression(op, Arrays.<Expression>asList(new KeyValueColumnExpression(c1), new KeyValueColumnExpression(c2)));
+ public static Expression columnComparison(CompareOp op, Expression c1, Expression c2) {
+ return new ComparisonExpression(op, Arrays.<Expression>asList(c1, c2));
}
public static SingleKeyValueComparisonFilter singleKVFilter(Expression e) {
[3/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java
new file mode 100644
index 0000000..82f3bcd
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java
@@ -0,0 +1,931 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.ATABLE_NAME;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.apache.phoenix.util.TestUtil.and;
+import static org.apache.phoenix.util.TestUtil.assertDegenerate;
+import static org.apache.phoenix.util.TestUtil.columnComparison;
+import static org.apache.phoenix.util.TestUtil.constantComparison;
+import static org.apache.phoenix.util.TestUtil.in;
+import static org.apache.phoenix.util.TestUtil.multiKVFilter;
+import static org.apache.phoenix.util.TestUtil.not;
+import static org.apache.phoenix.util.TestUtil.or;
+import static org.apache.phoenix.util.TestUtil.singleKVFilter;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.text.Format;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.expression.RowKeyColumnExpression;
+import org.apache.phoenix.expression.function.SubstrFunction;
+import org.apache.phoenix.filter.RowKeyComparisonFilter;
+import org.apache.phoenix.filter.SkipScanFilter;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.RowKeyValueAccessor;
+import org.apache.phoenix.schema.SaltingUtil;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.NumberUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.StringUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+
+public class WhereCompilerTest extends BaseConnectionlessQueryTest {
+
+ @Test
+ public void testSingleEqualFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0)),
+ filter);
+ }
+
+ @Test
+ public void testSingleFixedFullPkSalted() throws SQLException {
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ pconn.createStatement().execute("CREATE TABLE t (k bigint not null primary key, v varchar) SALT_BUCKETS=20");
+ String query = "select * from t where k=" + 1;
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertNull(filter);
+ byte[] key = new byte[PDataType.LONG.getByteSize() + 1];
+ PDataType.LONG.toBytes(1L, key, 1);
+ key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
+ byte[] expectedStartKey = key;
+ byte[] expectedEndKey = ByteUtil.concat(key, QueryConstants.SEPARATOR_BYTE_ARRAY);
+ byte[] startKey = scan.getStartRow();
+ byte[] stopKey = scan.getStopRow();
+ assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
+ assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
+ }
+
+ @Test
+ public void testSingleVariableFullPkSalted() throws SQLException {
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ pconn.createStatement().execute("CREATE TABLE t (k varchar primary key, v varchar) SALT_BUCKETS=20");
+ String query = "select * from t where k='a'";
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertNull(filter);
+ byte[] key = new byte[2];
+ PDataType.VARCHAR.toBytes("a", key, 1);
+ key[0] = SaltingUtil.getSaltingByte(key, 1, 1, 20);
+ byte[] expectedStartKey = key;
+ byte[] expectedEndKey = ByteUtil.concat(key, QueryConstants.SEPARATOR_BYTE_ARRAY);
+ byte[] startKey = scan.getStartRow();
+ byte[] stopKey = scan.getStopRow();
+ assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
+ assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
+ }
+
+ @Test
+ public void testMultiFixedFullPkSalted() throws SQLException {
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ pconn.createStatement().execute("CREATE TABLE t (k bigint not null primary key, v varchar) SALT_BUCKETS=20");
+ String query = "select * from t where k in (1,3)";
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ byte[] key = new byte[PDataType.LONG.getByteSize() + 1];
+ PDataType.LONG.toBytes(1L, key, 1);
+ key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
+ byte[] startKey1 = key;
+
+ key = new byte[PDataType.LONG.getByteSize() + 1];
+ PDataType.LONG.toBytes(3L, key, 1);
+ key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
+ byte[] startKey2 = key;
+
+ byte[] startKey = scan.getStartRow();
+ byte[] stopKey = scan.getStopRow();
+
+ // Due to salting byte, the 1 key may be after the 3 key
+ byte[] expectedStartKey;
+ byte[] expectedEndKey;
+ List<List<KeyRange>> expectedRanges = Collections.singletonList(
+ Arrays.asList(KeyRange.getKeyRange(startKey1),
+ KeyRange.getKeyRange(startKey2)));
+ if (Bytes.compareTo(startKey1, startKey2) > 0) {
+ expectedStartKey = startKey2;
+ expectedEndKey = ByteUtil.concat(startKey1, QueryConstants.SEPARATOR_BYTE_ARRAY);
+ Collections.reverse(expectedRanges.get(0));
+ } else {
+ expectedStartKey = startKey1;
+ expectedEndKey = ByteUtil.concat(startKey2, QueryConstants.SEPARATOR_BYTE_ARRAY);;
+ }
+ assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
+ assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
+
+ assertNotNull(filter);
+ assertTrue(filter instanceof SkipScanFilter);
+ StatementContext context = plan.getContext();
+ ScanRanges scanRanges = context.getScanRanges();
+ List<List<KeyRange>> ranges = scanRanges.getRanges();
+ assertEquals(expectedRanges, ranges);
+ }
+
+ @Test
+ public void testMultiColumnEqualFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_string=b_string";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ multiKVFilter(columnComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_STRING,
+ BaseConnectionlessQueryTest.B_STRING)),
+ filter);
+ }
+
+ @Test
+ public void testCollapseFunctionToNull() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,null) = 'foo'";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertNull(filter);
+
+ assertArrayEquals(scan.getStartRow(),KeyRange.EMPTY_RANGE.getLowerRange());
+ assertArrayEquals(scan.getStopRow(),KeyRange.EMPTY_RANGE.getUpperRange());
+ }
+
+ private static void bindParams(PhoenixPreparedStatement stmt, List<Object> binds) throws SQLException {
+ for (int i = 0; i < binds.size(); i++) {
+ stmt.setObject(i+1, binds.get(i));
+ }
+ }
+
+ @Test
+ public void testAndFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id=? and a_integer=0 and a_string='foo'";
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ multiKVFilter(and(
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0),
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_STRING,
+ "foo"))),
+ filter);
+ }
+
+ @Test
+ public void testRHSLiteral() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and 0 >= a_integer";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.LESS_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0)),
+ filter);
+ }
+
+ @Test
+ public void testToDateFilter() throws Exception {
+ String tenantId = "000000000000001";
+ String dateStr = "2012-01-01 12:00:00";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_date >= to_date('" + dateStr + "')";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ Format format = DateUtil.getDateParser(DateUtil.DEFAULT_DATE_FORMAT);
+ Object date = format.parseObject(dateStr);
+
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.GREATER_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_DATE,
+ date)),
+ filter);
+ }
+
+ private void helpTestToNumberFilter(String toNumberClause, BigDecimal expectedDecimal) throws Exception {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and x_decimal >= " + toNumberClause;
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.GREATER_OR_EQUAL,
+ BaseConnectionlessQueryTest.X_DECIMAL,
+ expectedDecimal)),
+ filter);
+}
+
+ private void helpTestToNumberFilterWithNoPattern(String stringValue) throws Exception {
+ String toNumberClause = "to_number('" + stringValue + "')";
+ BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal(stringValue));
+ helpTestToNumberFilter(toNumberClause, expectedDecimal);
+ }
+
+ @Test
+ public void testToNumberFilterWithInteger() throws Exception {
+ String stringValue = "123";
+ helpTestToNumberFilterWithNoPattern(stringValue);
+ }
+
+ @Test
+ public void testToNumberFilterWithDecimal() throws Exception {
+ String stringValue = "123.33";
+ helpTestToNumberFilterWithNoPattern(stringValue);
+ }
+
+ @Test
+ public void testToNumberFilterWithNegativeDecimal() throws Exception {
+ String stringValue = "-123.33";
+ helpTestToNumberFilterWithNoPattern(stringValue);
+ }
+
+ @Test
+ public void testToNumberFilterWithPatternParam() throws Exception {
+ String toNumberClause = "to_number('$1.23333E2', '\u00A40.00000E0')";
+ BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal("123.333"));
+ helpTestToNumberFilter(toNumberClause, expectedDecimal);
+ }
+
+ @Test(expected=AssertionError.class) // compileStatement() fails because zero rows are found by to_number()
+ public void testToNumberFilterWithPatternParamNegativeTest() throws Exception {
+ String toNumberClause = "to_number('$123.33', '000.00')"; // no currency sign in pattern param
+ BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal("123.33"));
+ helpTestToNumberFilter(toNumberClause, expectedDecimal);
+ }
+
+ @Test
+ public void testRowKeyFilter() throws SQLException {
+ String keyPrefix = "foo";
+ String query = "select * from atable where substr(entity_id,1,3)=?";
+ List<Object> binds = Arrays.<Object>asList(keyPrefix);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ new RowKeyComparisonFilter(
+ constantComparison(CompareOp.EQUAL,
+ new SubstrFunction(
+ Arrays.<Expression>asList(
+ new RowKeyColumnExpression(BaseConnectionlessQueryTest.ENTITY_ID,new RowKeyValueAccessor(BaseConnectionlessQueryTest.ATABLE.getPKColumns(),1)),
+ LiteralExpression.newConstant(1),
+ LiteralExpression.newConstant(3))
+ ),
+ keyPrefix),
+ QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES),
+ filter);
+ }
+
+ @Test
+ public void testPaddedRowKeyFilter() throws SQLException {
+ String keyPrefix = "fo";
+ String query = "select * from atable where entity_id=?";
+ List<Object> binds = Arrays.<Object>asList(keyPrefix);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ assertEquals(0,scan.getStartRow().length);
+ assertEquals(0,scan.getStopRow().length);
+ assertNotNull(scan.getFilter());
+ }
+
+ @Test
+ public void testPaddedStartStopKey() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "fo";
+ String query = "select * from atable where organization_id=? AND entity_id=?";
+ List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] expectedStartRow = ByteUtil.concat(Bytes.toBytes(tenantId), StringUtil.padChar(Bytes.toBytes(keyPrefix), 15));
+ assertArrayEquals(expectedStartRow,scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(expectedStartRow,QueryConstants.SEPARATOR_BYTE_ARRAY),scan.getStopRow());
+ }
+
+ @Test
+ public void testDegenerateRowKeyFilter() throws SQLException {
+ String keyPrefix = "foobar";
+ String query = "select * from atable where substr(entity_id,1,3)=?";
+ List<Object> binds = Arrays.<Object>asList(keyPrefix);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ // Degenerate b/c "foobar" is more than 3 characters
+ assertDegenerate(plan.getContext());
+ }
+
+ @Test
+ public void testDegenerateBiggerThanMaxLengthVarchar() throws SQLException {
+ byte[] tooBigValue = new byte[101];
+ Arrays.fill(tooBigValue, (byte)50);
+ String aString = (String)PDataType.VARCHAR.toObject(tooBigValue);
+ String query = "select * from atable where a_string=?";
+ List<Object> binds = Arrays.<Object>asList(aString);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ // Degenerate b/c a_string length is 100
+ assertDegenerate(plan.getContext());
+ }
+
+ @Test
+ public void testOrFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "foo";
+ int aInt = 2;
+ String query = "select * from atable where organization_id=? and (substr(entity_id,1,3)=? or a_integer=?)";
+ List<Object> binds = Arrays.<Object>asList(tenantId, keyPrefix, aInt);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ bindParams(pstmt, binds);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter( // single b/c one column is a row key column
+ or(
+ constantComparison(
+ CompareOp.EQUAL,
+ new SubstrFunction(Arrays.<Expression> asList(
+ new RowKeyColumnExpression(
+ BaseConnectionlessQueryTest.ENTITY_ID,
+ new RowKeyValueAccessor(BaseConnectionlessQueryTest.ATABLE.getPKColumns(), 1)),
+ LiteralExpression.newConstant(1),
+ LiteralExpression.newConstant(3))),
+ keyPrefix),
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ aInt))),
+ filter);
+ }
+
+ @Test
+ public void testTypeMismatch() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer > 'foo'";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+
+ try {
+ pstmt.optimizeQuery();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Type mismatch"));
+ }
+ }
+
+ @Test
+ public void testAndFalseFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0 and 2=3";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ assertDegenerate(plan.getContext());
+ }
+
+ @Test
+ public void testFalseFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and 2=3";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ assertDegenerate(plan.getContext());
+ }
+
+ @Test
+ public void testTrueFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and 2<=2";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ assertNull(scan.getFilter());
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testAndTrueFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0 and 2<3";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0)),
+ filter);
+
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testOrFalseFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer=0 or 3!=3)";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0)),
+ filter);
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testOrTrueFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer=0 or 3>2)";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertNull(filter);
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testInFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_string IN ('a','b')";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(in(
+ BaseConnectionlessQueryTest.A_STRING,
+ "a",
+ "b")),
+ filter);
+ }
+
+ @Test
+ public void testInListFilter() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s','%s')",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId3);
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+
+ Filter filter = scan.getFilter();
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.of(Arrays.asList(
+ pointRange(tenantId1),
+ pointRange(tenantId2),
+ pointRange(tenantId3))),
+ plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
+ filter);
+ }
+
+ @Test @Ignore("OR not yet optimized")
+ public void testOr2InFilter() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String query = String.format("select * from %s where organization_id='%s' OR organization_id='%s' OR organization_id='%s'",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+
+ Filter filter = scan.getFilter();
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.of(Arrays.asList(
+ pointRange(tenantId1),
+ pointRange(tenantId2),
+ pointRange(tenantId3))),
+ plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
+ filter);
+
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId3);
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testSecondPkColInListFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String entityId1 = "00000000000000X";
+ String entityId2 = "00000000000000Y";
+ String query = String.format("select * from %s where organization_id='%s' AND entity_id IN ('%s','%s')",
+ ATABLE_NAME, tenantId, entityId1, entityId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId + entityId1);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId + entityId2);
+ assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.of(
+ Arrays.asList(
+ pointRange(tenantId,entityId1),
+ pointRange(tenantId,entityId2))),
+ SchemaUtil.VAR_BINARY_SCHEMA),
+ filter);
+ }
+
+ @Test
+ public void testInListWithAnd1GTEFilter() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String entityId1 = "00000000000000X";
+ String entityId2 = "00000000000000Y";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id>='%s' AND entity_id<='%s'",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId1, entityId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.of(
+ Arrays.asList(
+ pointRange(tenantId1),
+ pointRange(tenantId2),
+ pointRange(tenantId3)),
+ Arrays.asList(PDataType.CHAR.getKeyRange(
+ Bytes.toBytes(entityId1),
+ true,
+ Bytes.toBytes(entityId2),
+ true))),
+ plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
+ filter);
+ }
+
+ @Test
+ public void testInListWithAnd1Filter() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String entityId = "00000000000000X";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id='%s'",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.of(
+ Arrays.asList(
+ pointRange(tenantId1, entityId),
+ pointRange(tenantId2, entityId),
+ pointRange(tenantId3, entityId))),
+ SchemaUtil.VAR_BINARY_SCHEMA),
+ filter);
+ }
+ @Test
+ public void testInListWithAnd1FilterScankey() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String entityId = "00000000000000X";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id='%s'",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId1), PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId3), PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ // TODO: validate scan ranges
+ }
+
+ private static KeyRange pointRange(String... ids) {
+ byte[] theKey = ByteUtil.EMPTY_BYTE_ARRAY;
+ for (String id : ids) {
+ theKey = ByteUtil.concat(theKey, Bytes.toBytes(id));
+ }
+ return pointRange(theKey);
+ }
+ private static KeyRange pointRange(byte[] bytes) {
+ return KeyRange.POINT.apply(bytes);
+ }
+
+ @Test
+ public void testInListWithAnd2Filter() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String entityId1 = "00000000000000X";
+ String entityId2 = "00000000000000Y";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s') AND entity_id IN ('%s', '%s')",
+ ATABLE_NAME, tenantId1, tenantId2, entityId1, entityId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+
+ Filter filter = scan.getFilter();
+ assertEquals(
+ new SkipScanFilter(
+ ImmutableList.<List<KeyRange>>of(ImmutableList.of(
+ pointRange(tenantId1, entityId1),
+ pointRange(tenantId1, entityId2),
+ pointRange(tenantId2, entityId1),
+ pointRange(tenantId2, entityId2))),
+ SchemaUtil.VAR_BINARY_SCHEMA),
+ filter);
+ }
+
+ @Test
+ public void testPartialRangeFilter() throws SQLException {
+ // I know these id's are ridiculous, but users can write queries that look like this
+ String tenantId1 = "001";
+ String tenantId2 = "02";
+ String query = String.format("select * from %s where organization_id > '%s' AND organization_id < '%s'",
+ ATABLE_NAME, tenantId1, tenantId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+
+ assertNull(scan.getFilter());
+ byte[] wideLower = ByteUtil.nextKey(StringUtil.padChar(Bytes.toBytes(tenantId1), 15));
+ byte[] wideUpper = StringUtil.padChar(Bytes.toBytes(tenantId2), 15);
+ assertArrayEquals(wideLower, scan.getStartRow());
+ assertArrayEquals(wideUpper, scan.getStopRow());
+ }
+
+ @Test
+ public void testInListWithAnd2FilterScanKey() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000002";
+ String tenantId3 = "000000000000003";
+ String entityId1 = "00000000000000X";
+ String entityId2 = "00000000000000Y";
+ String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id IN ('%s', '%s')",
+ ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId1, entityId2);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId1),PDataType.VARCHAR.toBytes(entityId1));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId3),PDataType.VARCHAR.toBytes(entityId2));
+ assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ // TODO: validate scan ranges
+ }
+
+ @Test
+ public void testBetweenFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer between 0 and 10";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(and(
+ constantComparison(
+ CompareOp.GREATER_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0),
+ constantComparison(
+ CompareOp.LESS_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 10))),
+ filter);
+ }
+
+ @Test
+ public void testNotBetweenFilter() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and a_integer not between 0 and 10";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+ assertEquals(
+ singleKVFilter(not(and(
+ constantComparison(
+ CompareOp.GREATER_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0),
+ constantComparison(
+ CompareOp.LESS_OR_EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 10)))).toString(),
+ filter.toString());
+ }
+
+ @Test
+ public void testTenantConstraintsAddedToScan() throws SQLException {
+ String tenantTypeId = "5678";
+ String tenantId = "000000000000123";
+ String url = getUrl(tenantId);
+ createTestTable(getUrl(), "create table base_table_for_tenant_filter_test (tenant_id char(15) not null, type_id char(4) not null, " +
+ "id char(5) not null, a_integer integer, a_string varchar(100) constraint pk primary key (tenant_id, type_id, id)) multi_tenant=true");
+ createTestTable(url, "create view tenant_filter_test (tenant_col integer) AS SELECT * FROM BASE_TABLE_FOR_TENANT_FILTER_TEST WHERE type_id= '" + tenantTypeId + "'");
+
+ String query = "select * from tenant_filter_test where a_integer=0 and a_string='foo'";
+ PhoenixConnection pconn = DriverManager.getConnection(url, TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ multiKVFilter(and(
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0),
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_STRING,
+ "foo"))),
+ filter);
+
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId + tenantTypeId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testTenantConstraintsAddedToScanWithNullTenantTypeId() throws SQLException {
+ String tenantId = "000000000000123";
+ createTestTable(getUrl(), "create table base_table_for_tenant_filter_test (tenant_id char(15) not null, " +
+ "id char(5) not null, a_integer integer, a_string varchar(100) constraint pk primary key (tenant_id, id)) multi_tenant=true");
+ createTestTable(getUrl(tenantId), "create view tenant_filter_test (tenant_col integer) AS SELECT * FROM BASE_TABLE_FOR_TENANT_FILTER_TEST");
+
+ String query = "select * from tenant_filter_test where a_integer=0 and a_string='foo'";
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(tenantId), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
+ QueryPlan plan = pstmt.optimizeQuery();
+ Scan scan = plan.getContext().getScan();
+ Filter filter = scan.getFilter();
+
+ assertEquals(
+ multiKVFilter(and(
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_INTEGER,
+ 0),
+ constantComparison(
+ CompareOp.EQUAL,
+ BaseConnectionlessQueryTest.A_STRING,
+ "foo"))),
+ filter);
+
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = startRow;
+ assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
+ }
+}
[5/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseCompileTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseCompileTest.java
deleted file mode 100644
index 50854a2..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseCompileTest.java
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.ATABLE_NAME;
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.apache.phoenix.util.TestUtil.and;
-import static org.apache.phoenix.util.TestUtil.assertDegenerate;
-import static org.apache.phoenix.util.TestUtil.columnComparison;
-import static org.apache.phoenix.util.TestUtil.constantComparison;
-import static org.apache.phoenix.util.TestUtil.in;
-import static org.apache.phoenix.util.TestUtil.kvColumn;
-import static org.apache.phoenix.util.TestUtil.multiKVFilter;
-import static org.apache.phoenix.util.TestUtil.not;
-import static org.apache.phoenix.util.TestUtil.or;
-import static org.apache.phoenix.util.TestUtil.singleKVFilter;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.math.BigDecimal;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.text.Format;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
-import org.apache.hadoop.hbase.filter.Filter;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.expression.Expression;
-import org.apache.phoenix.expression.LiteralExpression;
-import org.apache.phoenix.expression.RowKeyColumnExpression;
-import org.apache.phoenix.expression.function.SubstrFunction;
-import org.apache.phoenix.filter.RowKeyComparisonFilter;
-import org.apache.phoenix.filter.SkipScanFilter;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.PDataType;
-import org.apache.phoenix.schema.RowKeyValueAccessor;
-import org.apache.phoenix.schema.SaltingUtil;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.DateUtil;
-import org.apache.phoenix.util.NumberUtil;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.StringUtil;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableList;
-
-
-public class WhereClauseCompileTest extends BaseConnectionlessQueryTest {
-
- @Test
- public void testSingleEqualFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0)),
- filter);
- }
-
- @Test
- public void testSingleFixedFullPkSalted() throws SQLException {
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- pconn.createStatement().execute("CREATE TABLE t (k bigint not null primary key, v varchar) SALT_BUCKETS=20");
- String query = "select * from t where k=" + 1;
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertNull(filter);
- byte[] key = new byte[PDataType.LONG.getByteSize() + 1];
- PDataType.LONG.toBytes(1L, key, 1);
- key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
- byte[] expectedStartKey = key;
- byte[] expectedEndKey = ByteUtil.concat(key, QueryConstants.SEPARATOR_BYTE_ARRAY);
- byte[] startKey = scan.getStartRow();
- byte[] stopKey = scan.getStopRow();
- assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
- assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
- }
-
- @Test
- public void testSingleVariableFullPkSalted() throws SQLException {
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- pconn.createStatement().execute("CREATE TABLE t (k varchar primary key, v varchar) SALT_BUCKETS=20");
- String query = "select * from t where k='a'";
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertNull(filter);
- byte[] key = new byte[2];
- PDataType.VARCHAR.toBytes("a", key, 1);
- key[0] = SaltingUtil.getSaltingByte(key, 1, 1, 20);
- byte[] expectedStartKey = key;
- byte[] expectedEndKey = ByteUtil.concat(key, QueryConstants.SEPARATOR_BYTE_ARRAY);
- byte[] startKey = scan.getStartRow();
- byte[] stopKey = scan.getStopRow();
- assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
- assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
- }
-
- @Test
- public void testMultiFixedFullPkSalted() throws SQLException {
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- pconn.createStatement().execute("CREATE TABLE t (k bigint not null primary key, v varchar) SALT_BUCKETS=20");
- String query = "select * from t where k in (1,3)";
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- byte[] key = new byte[PDataType.LONG.getByteSize() + 1];
- PDataType.LONG.toBytes(1L, key, 1);
- key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
- byte[] startKey1 = key;
-
- key = new byte[PDataType.LONG.getByteSize() + 1];
- PDataType.LONG.toBytes(3L, key, 1);
- key[0] = SaltingUtil.getSaltingByte(key, 1, PDataType.LONG.getByteSize(), 20);
- byte[] startKey2 = key;
-
- byte[] startKey = scan.getStartRow();
- byte[] stopKey = scan.getStopRow();
-
- // Due to salting byte, the 1 key may be after the 3 key
- byte[] expectedStartKey;
- byte[] expectedEndKey;
- List<List<KeyRange>> expectedRanges = Collections.singletonList(
- Arrays.asList(KeyRange.getKeyRange(startKey1),
- KeyRange.getKeyRange(startKey2)));
- if (Bytes.compareTo(startKey1, startKey2) > 0) {
- expectedStartKey = startKey2;
- expectedEndKey = ByteUtil.concat(startKey1, QueryConstants.SEPARATOR_BYTE_ARRAY);
- Collections.reverse(expectedRanges.get(0));
- } else {
- expectedStartKey = startKey1;
- expectedEndKey = ByteUtil.concat(startKey2, QueryConstants.SEPARATOR_BYTE_ARRAY);;
- }
- assertTrue(Bytes.compareTo(expectedStartKey, startKey) == 0);
- assertTrue(Bytes.compareTo(expectedEndKey, stopKey) == 0);
-
- assertNotNull(filter);
- assertTrue(filter instanceof SkipScanFilter);
- StatementContext context = plan.getContext();
- ScanRanges scanRanges = context.getScanRanges();
- List<List<KeyRange>> ranges = scanRanges.getRanges();
- assertEquals(expectedRanges, ranges);
- }
-
- @Test
- public void testMultiColumnEqualFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_string=b_string";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- multiKVFilter(columnComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_STRING,
- BaseConnectionlessQueryTest.B_STRING)),
- filter);
- }
-
- @Test
- public void testCollapseFunctionToNull() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,null) = 'foo'";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertNull(filter);
-
- assertArrayEquals(scan.getStartRow(),KeyRange.EMPTY_RANGE.getLowerRange());
- assertArrayEquals(scan.getStopRow(),KeyRange.EMPTY_RANGE.getUpperRange());
- }
-
- private static void bindParams(PhoenixPreparedStatement stmt, List<Object> binds) throws SQLException {
- for (int i = 0; i < binds.size(); i++) {
- stmt.setObject(i+1, binds.get(i));
- }
- }
-
- @Test
- public void testAndFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id=? and a_integer=0 and a_string='foo'";
- List<Object> binds = Arrays.<Object>asList(tenantId);
-
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- assertEquals(
- multiKVFilter(and(
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0),
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_STRING,
- "foo"))),
- filter);
- }
-
- @Test
- public void testRHSLiteral() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and 0 >= a_integer";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
-
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.LESS_OR_EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0)),
- filter);
- }
-
- @Test
- public void testToDateFilter() throws Exception {
- String tenantId = "000000000000001";
- String dateStr = "2012-01-01 12:00:00";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_date >= to_date('" + dateStr + "')";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- Format format = DateUtil.getDateParser(DateUtil.DEFAULT_DATE_FORMAT);
- Object date = format.parseObject(dateStr);
-
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.GREATER_OR_EQUAL,
- BaseConnectionlessQueryTest.A_DATE,
- date)),
- filter);
- }
-
- private void helpTestToNumberFilter(String toNumberClause, BigDecimal expectedDecimal) throws Exception {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and x_decimal >= " + toNumberClause;
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.GREATER_OR_EQUAL,
- BaseConnectionlessQueryTest.X_DECIMAL,
- expectedDecimal)),
- filter);
-}
-
- private void helpTestToNumberFilterWithNoPattern(String stringValue) throws Exception {
- String toNumberClause = "to_number('" + stringValue + "')";
- BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal(stringValue));
- helpTestToNumberFilter(toNumberClause, expectedDecimal);
- }
-
- @Test
- public void testToNumberFilterWithInteger() throws Exception {
- String stringValue = "123";
- helpTestToNumberFilterWithNoPattern(stringValue);
- }
-
- @Test
- public void testToNumberFilterWithDecimal() throws Exception {
- String stringValue = "123.33";
- helpTestToNumberFilterWithNoPattern(stringValue);
- }
-
- @Test
- public void testToNumberFilterWithNegativeDecimal() throws Exception {
- String stringValue = "-123.33";
- helpTestToNumberFilterWithNoPattern(stringValue);
- }
-
- @Test
- public void testToNumberFilterWithPatternParam() throws Exception {
- String toNumberClause = "to_number('$1.23333E2', '\u00A40.00000E0')";
- BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal("123.333"));
- helpTestToNumberFilter(toNumberClause, expectedDecimal);
- }
-
- @Test(expected=AssertionError.class) // compileStatement() fails because zero rows are found by to_number()
- public void testToNumberFilterWithPatternParamNegativeTest() throws Exception {
- String toNumberClause = "to_number('$123.33', '000.00')"; // no currency sign in pattern param
- BigDecimal expectedDecimal = NumberUtil.normalize(new BigDecimal("123.33"));
- helpTestToNumberFilter(toNumberClause, expectedDecimal);
- }
-
- @Test
- public void testRowKeyFilter() throws SQLException {
- String keyPrefix = "foo";
- String query = "select * from atable where substr(entity_id,1,3)=?";
- List<Object> binds = Arrays.<Object>asList(keyPrefix);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- assertEquals(
- new RowKeyComparisonFilter(
- constantComparison(CompareOp.EQUAL,
- new SubstrFunction(
- Arrays.<Expression>asList(
- new RowKeyColumnExpression(BaseConnectionlessQueryTest.ENTITY_ID,new RowKeyValueAccessor(BaseConnectionlessQueryTest.ATABLE.getPKColumns(),1)),
- LiteralExpression.newConstant(1),
- LiteralExpression.newConstant(3))
- ),
- keyPrefix),
- QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES),
- filter);
- }
-
- @Test
- public void testPaddedRowKeyFilter() throws SQLException {
- String keyPrefix = "fo";
- String query = "select * from atable where entity_id=?";
- List<Object> binds = Arrays.<Object>asList(keyPrefix);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- assertEquals(0,scan.getStartRow().length);
- assertEquals(0,scan.getStopRow().length);
- assertNotNull(scan.getFilter());
- }
-
- @Test
- public void testPaddedStartStopKey() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "fo";
- String query = "select * from atable where organization_id=? AND entity_id=?";
- List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] expectedStartRow = ByteUtil.concat(Bytes.toBytes(tenantId), StringUtil.padChar(Bytes.toBytes(keyPrefix), 15));
- assertArrayEquals(expectedStartRow,scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(expectedStartRow,QueryConstants.SEPARATOR_BYTE_ARRAY),scan.getStopRow());
- }
-
- @Test
- public void testDegenerateRowKeyFilter() throws SQLException {
- String keyPrefix = "foobar";
- String query = "select * from atable where substr(entity_id,1,3)=?";
- List<Object> binds = Arrays.<Object>asList(keyPrefix);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- // Degenerate b/c "foobar" is more than 3 characters
- assertDegenerate(plan.getContext());
- }
-
- @Test
- public void testDegenerateBiggerThanMaxLengthVarchar() throws SQLException {
- byte[] tooBigValue = new byte[101];
- Arrays.fill(tooBigValue, (byte)50);
- String aString = (String)PDataType.VARCHAR.toObject(tooBigValue);
- String query = "select * from atable where a_string=?";
- List<Object> binds = Arrays.<Object>asList(aString);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- // Degenerate b/c a_string length is 100
- assertDegenerate(plan.getContext());
- }
-
- @Test
- public void testOrFilter() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "foo";
- int aInt = 2;
- String query = "select * from atable where organization_id=? and (substr(entity_id,1,3)=? or a_integer=?)";
- List<Object> binds = Arrays.<Object>asList(tenantId, keyPrefix, aInt);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- bindParams(pstmt, binds);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter( // single b/c one column is a row key column
- or(
- constantComparison(
- CompareOp.EQUAL,
- new SubstrFunction(Arrays.<Expression> asList(
- new RowKeyColumnExpression(
- BaseConnectionlessQueryTest.ENTITY_ID,
- new RowKeyValueAccessor(BaseConnectionlessQueryTest.ATABLE.getPKColumns(), 1)),
- LiteralExpression.newConstant(1),
- LiteralExpression.newConstant(3))),
- keyPrefix),
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- aInt))),
- filter);
- }
-
- @Test
- public void testTypeMismatch() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer > 'foo'";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
-
- try {
- pstmt.optimizeQuery();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Type mismatch"));
- }
- }
-
- @Test
- public void testAndFalseFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0 and 2=3";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- assertDegenerate(plan.getContext());
- }
-
- @Test
- public void testFalseFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and 2=3";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- assertDegenerate(plan.getContext());
- }
-
- @Test
- public void testTrueFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and 2<=2";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- assertNull(scan.getFilter());
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testAndTrueFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer=0 and 2<3";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0)),
- filter);
-
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testOrFalseFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer=0 or 3!=3)";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0)),
- filter);
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testOrTrueFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer=0 or 3>2)";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertNull(filter);
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testInFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_string IN ('a','b')";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
-
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(in(
- kvColumn(BaseConnectionlessQueryTest.A_STRING),
- "a",
- "b")),
- filter);
- }
-
- @Test
- public void testInListFilter() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String query = String.format("select * from %s where organization_id IN ('%s','%s','%s')",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId3);
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
-
- Filter filter = scan.getFilter();
- assertEquals(
- new SkipScanFilter(
- ImmutableList.of(Arrays.asList(
- pointRange(tenantId1),
- pointRange(tenantId2),
- pointRange(tenantId3))),
- plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
- filter);
- }
-
- @Test @Ignore("OR not yet optimized")
- public void testOr2InFilter() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String query = String.format("select * from %s where organization_id='%s' OR organization_id='%s' OR organization_id='%s'",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
-
- Filter filter = scan.getFilter();
- assertEquals(
- new SkipScanFilter(
- ImmutableList.of(Arrays.asList(
- pointRange(tenantId1),
- pointRange(tenantId2),
- pointRange(tenantId3))),
- plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
- filter);
-
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId3);
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testSecondPkColInListFilter() throws SQLException {
- String tenantId = "000000000000001";
- String entityId1 = "00000000000000X";
- String entityId2 = "00000000000000Y";
- String query = String.format("select * from %s where organization_id='%s' AND entity_id IN ('%s','%s')",
- ATABLE_NAME, tenantId, entityId1, entityId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId + entityId1);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = PDataType.VARCHAR.toBytes(tenantId + entityId2);
- assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
-
- Filter filter = scan.getFilter();
-
- assertEquals(
- new SkipScanFilter(
- ImmutableList.of(
- Arrays.asList(
- pointRange(tenantId,entityId1),
- pointRange(tenantId,entityId2))),
- SchemaUtil.VAR_BINARY_SCHEMA),
- filter);
- }
-
- @Test
- public void testInListWithAnd1GTEFilter() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String entityId1 = "00000000000000X";
- String entityId2 = "00000000000000Y";
- String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id>='%s' AND entity_id<='%s'",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId1, entityId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- new SkipScanFilter(
- ImmutableList.of(
- Arrays.asList(
- pointRange(tenantId1),
- pointRange(tenantId2),
- pointRange(tenantId3)),
- Arrays.asList(PDataType.CHAR.getKeyRange(
- Bytes.toBytes(entityId1),
- true,
- Bytes.toBytes(entityId2),
- true))),
- plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()),
- filter);
- }
-
- @Test
- public void testInListWithAnd1Filter() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String entityId = "00000000000000X";
- String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id='%s'",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- new SkipScanFilter(
- ImmutableList.of(
- Arrays.asList(
- pointRange(tenantId1, entityId),
- pointRange(tenantId2, entityId),
- pointRange(tenantId3, entityId))),
- SchemaUtil.VAR_BINARY_SCHEMA),
- filter);
- }
- @Test
- public void testInListWithAnd1FilterScankey() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String entityId = "00000000000000X";
- String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id='%s'",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId1), PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId3), PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- // TODO: validate scan ranges
- }
-
- private static KeyRange pointRange(String... ids) {
- byte[] theKey = ByteUtil.EMPTY_BYTE_ARRAY;
- for (String id : ids) {
- theKey = ByteUtil.concat(theKey, Bytes.toBytes(id));
- }
- return pointRange(theKey);
- }
- private static KeyRange pointRange(byte[] bytes) {
- return KeyRange.POINT.apply(bytes);
- }
-
- @Test
- public void testInListWithAnd2Filter() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String entityId1 = "00000000000000X";
- String entityId2 = "00000000000000Y";
- String query = String.format("select * from %s where organization_id IN ('%s','%s') AND entity_id IN ('%s', '%s')",
- ATABLE_NAME, tenantId1, tenantId2, entityId1, entityId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
-
- Filter filter = scan.getFilter();
- assertEquals(
- new SkipScanFilter(
- ImmutableList.<List<KeyRange>>of(ImmutableList.of(
- pointRange(tenantId1, entityId1),
- pointRange(tenantId1, entityId2),
- pointRange(tenantId2, entityId1),
- pointRange(tenantId2, entityId2))),
- SchemaUtil.VAR_BINARY_SCHEMA),
- filter);
- }
-
- @Test
- public void testPartialRangeFilter() throws SQLException {
- // I know these id's are ridiculous, but users can write queries that look like this
- String tenantId1 = "001";
- String tenantId2 = "02";
- String query = String.format("select * from %s where organization_id > '%s' AND organization_id < '%s'",
- ATABLE_NAME, tenantId1, tenantId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
-
- assertNull(scan.getFilter());
- byte[] wideLower = ByteUtil.nextKey(StringUtil.padChar(Bytes.toBytes(tenantId1), 15));
- byte[] wideUpper = StringUtil.padChar(Bytes.toBytes(tenantId2), 15);
- assertArrayEquals(wideLower, scan.getStartRow());
- assertArrayEquals(wideUpper, scan.getStopRow());
- }
-
- @Test
- public void testInListWithAnd2FilterScanKey() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000002";
- String tenantId3 = "000000000000003";
- String entityId1 = "00000000000000X";
- String entityId2 = "00000000000000Y";
- String query = String.format("select * from %s where organization_id IN ('%s','%s','%s') AND entity_id IN ('%s', '%s')",
- ATABLE_NAME, tenantId1, tenantId3, tenantId2, entityId1, entityId2);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId1),PDataType.VARCHAR.toBytes(entityId1));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId3),PDataType.VARCHAR.toBytes(entityId2));
- assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- // TODO: validate scan ranges
- }
-
- @Test
- public void testBetweenFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer between 0 and 10";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(and(
- constantComparison(
- CompareOp.GREATER_OR_EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0),
- constantComparison(
- CompareOp.LESS_OR_EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 10))),
- filter);
- }
-
- @Test
- public void testNotBetweenFilter() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and a_integer not between 0 and 10";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
- assertEquals(
- singleKVFilter(not(and(
- constantComparison(
- CompareOp.GREATER_OR_EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0),
- constantComparison(
- CompareOp.LESS_OR_EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 10)))).toString(),
- filter.toString());
- }
-
- @Test
- public void testTenantConstraintsAddedToScan() throws SQLException {
- String tenantTypeId = "5678";
- String tenantId = "000000000000123";
- String url = getUrl(tenantId);
- createTestTable(getUrl(), "create table base_table_for_tenant_filter_test (tenant_id char(15) not null, type_id char(4) not null, " +
- "id char(5) not null, a_integer integer, a_string varchar(100) constraint pk primary key (tenant_id, type_id, id)) multi_tenant=true");
- createTestTable(url, "create view tenant_filter_test (tenant_col integer) AS SELECT * FROM BASE_TABLE_FOR_TENANT_FILTER_TEST WHERE type_id= '" + tenantTypeId + "'");
-
- String query = "select * from tenant_filter_test where a_integer=0 and a_string='foo'";
- PhoenixConnection pconn = DriverManager.getConnection(url, TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- assertEquals(
- multiKVFilter(and(
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0),
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_STRING,
- "foo"))),
- filter);
-
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId + tenantTypeId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-
- @Test
- public void testTenantConstraintsAddedToScanWithNullTenantTypeId() throws SQLException {
- String tenantId = "000000000000123";
- createTestTable(getUrl(), "create table base_table_for_tenant_filter_test (tenant_id char(15) not null, " +
- "id char(5) not null, a_integer integer, a_string varchar(100) constraint pk primary key (tenant_id, id)) multi_tenant=true");
- createTestTable(getUrl(tenantId), "create view tenant_filter_test (tenant_col integer) AS SELECT * FROM BASE_TABLE_FOR_TENANT_FILTER_TEST");
-
- String query = "select * from tenant_filter_test where a_integer=0 and a_string='foo'";
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(tenantId), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- PhoenixPreparedStatement pstmt = new PhoenixPreparedStatement(pconn, query);
- QueryPlan plan = pstmt.optimizeQuery();
- Scan scan = plan.getContext().getScan();
- Filter filter = scan.getFilter();
-
- assertEquals(
- multiKVFilter(and(
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_INTEGER,
- 0),
- constantComparison(
- CompareOp.EQUAL,
- BaseConnectionlessQueryTest.A_STRING,
- "foo"))),
- filter);
-
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = startRow;
- assertArrayEquals(ByteUtil.nextKey(stopRow), scan.getStopRow());
- }
-}
[4/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseOptimizerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseOptimizerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseOptimizerTest.java
deleted file mode 100644
index 925bcc2..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereClauseOptimizerTest.java
+++ /dev/null
@@ -1,1620 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.apache.phoenix.util.TestUtil.assertDegenerate;
-import static org.apache.phoenix.util.TestUtil.assertEmptyScanKey;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.filter.Filter;
-import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
-import org.apache.phoenix.expression.Expression;
-import org.apache.phoenix.expression.OrExpression;
-import org.apache.phoenix.filter.RowKeyComparisonFilter;
-import org.apache.phoenix.filter.SkipScanFilter;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.SQLParser;
-import org.apache.phoenix.parse.SelectStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.ColumnNotFoundException;
-import org.apache.phoenix.schema.PDataType;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.DateUtil;
-import org.apache.phoenix.util.TestUtil;
-import org.junit.Test;
-
-import com.google.common.collect.Sets;
-
-
-
-public class WhereClauseOptimizerTest extends BaseConnectionlessQueryTest {
-
- private static StatementContext compileStatement(String query, Scan scan, List<Object> binds) throws SQLException {
- return compileStatement(query, scan, binds, null, null);
- }
-
- private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Integer limit) throws SQLException {
- return compileStatement(query, scan, binds, limit, null);
- }
-
- private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Set<Expression> extractedNodes) throws SQLException {
- return compileStatement(query, scan, binds, null, extractedNodes);
- }
-
- // TODO: remove this and replace checks on extractedNodes with tests for the scan filter
- private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Integer limit, Set<Expression> extractedNodes) throws SQLException {
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- statement = StatementNormalizer.normalize(statement, resolver);
- StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
-
- Integer actualLimit = LimitCompiler.compile(context, statement);
- assertEquals(limit, actualLimit);
- GroupBy groupBy = GroupByCompiler.compile(context, statement);
- statement = HavingCompiler.rewrite(context, statement, groupBy);
- WhereCompiler.compileWhereClause(context, statement, extractedNodes);
- return context;
- }
-
- @Test
- public void testSingleKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- compileStatement(query, scan, binds);
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testReverseSingleKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where '" + tenantId + "' = organization_id";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- compileStatement(query, scan, binds);
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testStartKeyStopKey() throws SQLException {
- Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE start_stop_test (pk char(2) not null primary key)");
- conn.close();
-
- String query = "select * from start_stop_test where pk >= 'EA' and pk < 'EZ'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- assertArrayEquals(PDataType.VARCHAR.toBytes("EA"), scan.getStartRow());
- assertArrayEquals(PDataType.VARCHAR.toBytes("EZ"), scan.getStopRow());
- }
-
- @Test
- public void testConcatSingleKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id || 'foo' ='" + tenantId + "'||'foo'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- // The || operator cannot currently be used to form the start/stop key
- assertNotNull(scan.getFilter());
- assertEquals(0, scan.getStartRow().length);
- assertEquals(0, scan.getStopRow().length);
- }
-
- @Test
- public void testLiteralConcatExpression() throws SQLException {
- String query = "select * from atable where null||'foo'||'bar' = 'foobar'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- assertEquals(0, scan.getStartRow().length);
- assertEquals(0, scan.getStopRow().length);
- }
-
- @Test
- public void testSingleKeyNotExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where not organization_id='" + tenantId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNotNull(scan.getFilter());
-
- assertEquals(0, scan.getStartRow().length);
- assertEquals(0, scan.getStopRow().length);
- }
-
- @Test
- public void testMultiKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)), 15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testMultiKeyBindExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id=? and substr(entity_id,1,3)=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testEqualRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(startDate));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testDegenerateRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testBoundaryGreaterThanRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testBoundaryGreaterThanOrEqualRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
- Date endDate = DateUtil.parseDate("2012-01-01 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testGreaterThanRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLessThanRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testBoundaryLessThanRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
- Date endDate = DateUtil.parseDate("2012-01-01 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLessThanOrEqualRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testBoundaryLessThanOrEqualRound() throws Exception {
- String inst = "a";
- String host = "b";
- Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
- Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
- String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<=?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
- compileStatement(query, scan, binds);
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
- PDataType.DATE.toBytes(endDate));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testOverlappingKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String entityId = "002333333333333";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "' and entity_id='" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(startRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- }
-
- @Test
- public void testTrailingSubstrExpression() throws SQLException {
- String tenantId = "0xD000000000001";
- String entityId = "002333333333333";
- String query = "select * from atable where substr(organization_id,1,3)='" + tenantId.substring(0, 3) + "' and entity_id='" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNotNull(scan.getFilter());
-
- byte[] startRow = ByteUtil.concat(ByteUtil.fillKey(PDataType.VARCHAR.toBytes(tenantId.substring(0,3)),15),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(startRow, scan.getStartRow());
- // Even though the first slot is a non inclusive range, we need to do a next key
- // on the second slot because of the algorithm we use to seek to and terminate the
- // loop during skip scan. We could end up having a first slot just under the upper
- // limit of slot one and a value equal to the value in slot two and we need this to
- // be less than the upper range that would get formed.
- byte[] stopRow = ByteUtil.concat(ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId.substring(0,3))),15),ByteUtil.nextKey(PDataType.VARCHAR.toBytes(entityId)));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testBasicRangeExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id <= '" + tenantId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNull(scan.getFilter());
-
- assertTrue(scan.getStartRow().length == 0);
- byte[] stopRow = ByteUtil.concat(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression1() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String keyPrefix2= "004";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,3) < '" + keyPrefix2 + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNull(scan.getFilter());
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix2),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression2() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String keyPrefix2= "004";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,3) <= '" + keyPrefix2 + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNull(scan.getFilter());
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression3() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String keyPrefix2= "004";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and substr(entity_id,1,3) <= '" + keyPrefix2 + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix1)),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression4() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String entityId= "002000000000002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and substr(entity_id,1,3) = '" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testKeyRangeExpression5() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String entityId= "002000000000002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) <= '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression6() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String entityId= "002000000000002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) < '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testKeyRangeExpression7() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String entityId= "002000000000002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) < '" + keyPrefix1 + "' and entity_id < '" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertNull(scan.getFilter());
-
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(keyPrefix1),new byte[entityId.length() - keyPrefix1.length()]);
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression8() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "001";
- String entityId= "002000000000002";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
- assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- }
-
- @Test
- public void testKeyRangeExpression9() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix1 = "002";
- String keyPrefix2 = "0033";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,4) <= '" + keyPrefix2 + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15)); // extra byte is due to implicit internal padding
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- /**
- * This is testing the degenerate case where nothing will match because the overlapping keys (keyPrefix and entityId) don't match.
- * @throws SQLException
- */
- @Test
- public void testUnequalOverlappingKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String entityId = "001333333333333";
- String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "' and entity_id='" + entityId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testTopLevelOrKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' or a_integer=2";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNotNull(scan.getFilter());
- assertEquals(0, scan.getStartRow().length);
- assertEquals(0, scan.getStopRow().length);
- }
-
- @Test
- public void testSiblingOrKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer = 2 or a_integer = 3)";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNotNull(scan.getFilter());
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testColumnNotFound() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where bar='" + tenantId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- try {
- compileStatement(query, scan, binds);
- fail();
- } catch (ColumnNotFoundException e) {
- // expected
- }
- }
-
- @Test
- public void testNotContiguousPkColumn() throws SQLException {
- String keyPrefix = "002";
- String query = "select * from atable where substr(entity_id,1,3)='" + keyPrefix + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNotNull(scan.getFilter());
- assertEquals(0, scan.getStartRow().length);
- assertEquals(0, scan.getStopRow().length);
- }
-
- @Test
- public void testMultipleNonEqualitiesPkColumn() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id >= '" + tenantId + "' AND substr(entity_id,1,3) > '" + keyPrefix + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds);
-
- assertNotNull(scan.getFilter());
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testRHSLiteral() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' and 0 >= a_integer limit 1000";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- compileStatement(query, scan, binds, 1000);
-
- assertNotNull(scan.getFilter());
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
-
- @Test
- public void testKeyTypeMismatch() {
- String query = "select * from atable where organization_id=5";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- try {
- compileStatement(query, scan, binds);
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Type mismatch"));
- }
- }
-
- @Test
- public void testLikeExtractAllKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLikeExtractAllAsEqKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id LIKE ? and entity_id LIKE '" + keyPrefix + "%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- compileStatement(query, scan, binds);
-
- assertNull(scan.getFilter());
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testDegenerateLikeNoWildcard() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id LIKE ? and entity_id LIKE '" + keyPrefix + "'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- compileStatement(query, scan, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testLikeExtractKeyExpression2() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- // TODO: verify that _ at end of like doesn't go to equals
- String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "_'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- compileStatement(query, scan, binds);
-
- assertNotNull(scan.getFilter());
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLikeOptKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "%003%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertNotNull(scan.getFilter());
- assertEquals(1, extractedNodes.size());
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- assertArrayEquals(startRow, scan.getStartRow());
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLikeOptKeyExpression2() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and substr(entity_id,1,10) LIKE '" + keyPrefix + "%003%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertNotNull(scan.getFilter());
- assertEquals(1, extractedNodes.size());
-
-
- byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
- byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(stopRow, scan.getStopRow());
- }
-
- @Test
- public void testLikeNoOptKeyExpression3() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and substr(entity_id,4,10) LIKE '" + keyPrefix + "%003%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertNotNull(scan.getFilter());
- assertEquals(1, extractedNodes.size());
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
- }
-
- @Test
- public void testLikeDegenerate() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id = ? and entity_id LIKE '0000000000000012%003%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateDivision1() throws SQLException {
- String query = "select * from atable where a_integer = 3 / null";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateDivision2() throws SQLException {
- String query = "select * from atable where a_integer / null = 3";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateMult1() throws SQLException {
- String query = "select * from atable where a_integer = 3 * null";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateMult2() throws SQLException {
- String query = "select * from atable where a_integer * null = 3";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateAdd1() throws SQLException {
- String query = "select * from atable where a_integer = 3 + null";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateAdd2() throws SQLException {
- String query = "select * from atable where a_integer + null = 3";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateSub1() throws SQLException {
- String query = "select * from atable where a_integer = 3 - null";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testDegenerateSub2() throws SQLException {
- String query = "select * from atable where a_integer - null = 3";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertDegenerate(scan);
- }
-
- @Test
- public void testLikeNoOptKeyExpression() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and entity_id LIKE '%001%" + keyPrefix + "%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertNotNull(scan.getFilter());
- assertEquals(1, extractedNodes.size());
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
- }
-
- @Test
- public void testLikeNoOptKeyExpression2() throws SQLException {
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select * from atable where organization_id = ? and entity_id NOT LIKE '" + keyPrefix + "%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
-
- assertNotNull(scan.getFilter());
- assertEquals(1, extractedNodes.size());
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
- }
- /*
- * The following 5 tests are testing the comparison in where clauses under the case when the rhs
- * cannot be coerced into the lhs. We need to confirm the decision make by expression compilation
- * returns correct decisions.
- */
- @Test
- public void testValueComparisonInt() throws SQLException {
- ensureTableCreated(getUrl(),"PKIntValueTest");
- String query;
- // int <-> long
- // Case 1: int = long, comparison always false, key is degenerated.
- query = "SELECT * FROM PKintValueTest where pk = " + Long.MAX_VALUE;
- assertQueryConditionAlwaysFalse(query);
- // Case 2: int != long, comparison always true, no key set since we need to do a full
- // scan all the time.
- query = "SELECT * FROM PKintValueTest where pk != " + Long.MAX_VALUE;
- assertQueryConditionAlwaysTrue(query);
- // Case 3: int > positive long, comparison always false;
- query = "SELECT * FROM PKintValueTest where pk >= " + Long.MAX_VALUE;
- assertQueryConditionAlwaysFalse(query);
- // Case 4: int <= Integer.MAX_VALUE < positive long, always true;
- query = "SELECT * FROM PKintValueTest where pk <= " + Long.MAX_VALUE;
- assertQueryConditionAlwaysTrue(query);
- // Case 5: int >= Integer.MIN_VALUE > negative long, always true;
- query = "SELECT * FROM PKintValueTest where pk >= " + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysTrue(query);
- // Case 6: int < negative long, comparison always false;
- query = "SELECT * FROM PKintValueTest where pk <= " + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysFalse(query);
- }
-
- @Test
- public void testValueComparisonUnsignedInt() throws SQLException {
- ensureTableCreated(getUrl(), "PKUnsignedIntValueTest");
- String query;
- // unsigned_int <-> negative int/long
- // Case 1: unsigned_int = negative int, always false;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk = -1";
- assertQueryConditionAlwaysFalse(query);
- // Case 2: unsigned_int != negative int, always true;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk != -1";
- assertQueryConditionAlwaysTrue(query);
- // Case 3: unsigned_int > negative int, always true;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk > " + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysTrue(query);
- // Case 4: unsigned_int < negative int, always false;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk < " + + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysFalse(query);
- // unsigned_int <-> big positive long
- // Case 1: unsigned_int = big positive long, always false;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk = " + Long.MAX_VALUE;
- assertQueryConditionAlwaysFalse(query);
- // Case 2: unsigned_int != big positive long, always true;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk != " + Long.MAX_VALUE;
- assertQueryConditionAlwaysTrue(query);
- // Case 3: unsigned_int > big positive long, always false;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk >= " + Long.MAX_VALUE;
- assertQueryConditionAlwaysFalse(query);
- // Case 4: unsigned_int < big positive long, always true;
- query = "SELECT * FROM PKUnsignedIntValueTest where pk <= " + Long.MAX_VALUE;
- assertQueryConditionAlwaysTrue(query);
- }
-
- @Test
- public void testValueComparisonUnsignedLong() throws SQLException {
- ensureTableCreated(getUrl(), "PKUnsignedLongValueTest");
- String query;
- // unsigned_long <-> positive int/long
- // Case 1: unsigned_long = negative int/long, always false;
- query = "SELECT * FROM PKUnsignedLongValueTest where pk = -1";
- assertQueryConditionAlwaysFalse(query);
- // Case 2: unsigned_long = negative int/long, always true;
- query = "SELECT * FROM PKUnsignedLongValueTest where pk != " + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysTrue(query);
- // Case 3: unsigned_long > negative int/long, always true;
- query = "SELECT * FROM PKUnsignedLongValueTest where pk > -1";
- assertQueryConditionAlwaysTrue(query);
- // Case 4: unsigned_long < negative int/long, always false;
- query = "SELECT * FROM PKUnsignedLongValueTest where pk < " + (Long.MIN_VALUE + 1);
- assertQueryConditionAlwaysFalse(query);
- }
-
- private void assertQueryConditionAlwaysTrue(String query) throws SQLException {
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression> extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
- assertEmptyScanKey(scan);
- }
-
- private void assertQueryConditionAlwaysFalse(String query) throws SQLException {
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList();
- Set<Expression> extractedNodes = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedNodes);
- assertDegenerate(scan);
- }
-
- @Test
- public void testOrSameColExpression() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000003";
- String query = "select * from atable where organization_id = ? or organization_id = ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId1,tenantId2);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- StatementContext context = compileStatement(query, scan, binds, extractedNodes);
-
- Filter filter = scan.getFilter();
- assertNotNull(filter);
- assertTrue(filter instanceof SkipScanFilter);
- ScanRanges scanRanges = context.getScanRanges();
- assertNotNull(scanRanges);
- List<List<KeyRange>> ranges = scanRanges.getRanges();
- assertEquals(1,ranges.size());
- List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList(
- PDataType.CHAR.getKeyRange(PDataType.CHAR.toBytes(tenantId1), true, PDataType.CHAR.toBytes(tenantId1), true),
- PDataType.CHAR.getKeyRange(PDataType.CHAR.toBytes(tenantId2), true, PDataType.CHAR.toBytes(tenantId2), true)));
- assertEquals(expectedRanges, ranges);
- assertEquals(1, extractedNodes.size());
- assertTrue(extractedNodes.iterator().next() instanceof OrExpression);
- byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
- assertArrayEquals(startRow, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId2)), scan.getStopRow());
- }
-
- @Test
- public void testAndOrExpression() throws SQLException {
- String tenantId1 = "000000000000001";
- String tenantId2 = "000000000000003";
- String entityId1 = "002333333333331";
- String entityId2 = "002333333333333";
- String query = "select * from atable where (organization_id = ? and entity_id = ?) or (organization_id = ? and entity_id = ?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1,tenantId2,entityId2);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- StatementContext context = compileStatement(query, scan, binds, extractedNodes);
-
- Filter filter = scan.getFilter();
- assertNotNull(filter);
- assertTrue(filter instanceof RowKeyComparisonFilter);
- ScanRanges scanRanges = context.getScanRanges();
- assertEquals(ScanRanges.EVERYTHING,scanRanges);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testOrDiffColExpression() throws SQLException {
- String tenantId1 = "000000000000001";
- String entityId1 = "002333333333331";
- String query = "select * from atable where organization_id = ? or entity_id = ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1);
- Set<Expression>extractedNodes = new HashSet<Expression>();
- StatementContext context = compileStatement(query, scan, binds, extractedNodes);
-
- Filter filter = scan.getFilter();
- assertNotNull(filter);
- assertTrue(filter instanceof RowKeyComparisonFilter);
- ScanRanges scanRanges = context.getScanRanges();
- assertEquals(ScanRanges.EVERYTHING,scanRanges);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testOrSameColRangeExpression() throws SQLException {
- String query = "select * from atable where substr(organization_id,1,3) = ? or organization_id LIKE 'foo%'";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList("00D");
- Set<Expression>extractedNodes = new HashSet<Expression>();
- StatementContext context = compileStatement(query, scan, binds, extractedNodes);
-
- Filter filter = scan.getFilter();
- assertNotNull(filter);
- assertTrue(filter instanceof SkipScanFilter);
- ScanRanges scanRanges = context.getScanRanges();
- assertNotNull(scanRanges);
- List<List<KeyRange>> ranges = scanRanges.getRanges();
- assertEquals(1,ranges.size());
- List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList(
- PDataType.CHAR.getKeyRange(
- ByteUtil.fillKey(PDataType.CHAR.toBytes("00D"),15), true,
- ByteUtil.fillKey(ByteUtil.nextKey(PDataType.CHAR.toBytes("00D")),15), false),
- PDataType.CHAR.getKeyRange(
- ByteUtil.fillKey(PDataType.CHAR.toBytes("foo"),15), true,
- ByteUtil.fillKey(ByteUtil.nextKey(PDataType.CHAR.toBytes("foo")),15), false)));
- assertEquals(expectedRanges, ranges);
- assertEquals(1, extractedNodes.size());
- assertTrue(extractedNodes.iterator().next() instanceof OrExpression);
- }
-
- @Test
- public void testForceSkipScanOnSaltedTable() throws SQLException {
- Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE IF NOT EXISTS user_messages (\n" +
- " SENDER_ID UNSIGNED_LONG NOT NULL,\n" +
- " RECIPIENT_ID UNSIGNED_LONG NOT NULL,\n" +
- " SENDER_IP VARCHAR,\n" +
- " IS_READ VARCHAR,\n" +
- " IS_DELETED VARCHAR,\n" +
- " M_TEXT VARCHAR,\n" +
- " M_TIMESTAMP timestamp NOT NULL,\n" +
- " ROW_ID UNSIGNED_LONG NOT NULL\n" +
- " constraint rowkey primary key (SENDER_ID,RECIPIENT_ID,M_TIMESTAMP DESC,ROW_ID))\n" +
- "SALT_BUCKETS=12\n");
- String query = "select /*+ SKIP_SCAN */ count(*) from user_messages where is_read='N' and recipient_id=5399179882";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- Set<Expression> extractedNodes = Sets.newHashSet();
- StatementContext context = compileStatement(query, scan, binds, null, extractedNodes);
- ScanRanges scanRanges = context.getScanRanges();
- assertNotNull(scanRanges);
- assertEquals(3,scanRanges.getRanges().size());
- assertEquals(1,scanRanges.getRanges().get(1).size());
- assertEquals(KeyRange.EVERYTHING_RANGE,scanRanges.getRanges().get(1).get(0));
- assertEquals(1,scanRanges.getRanges().get(2).size());
- assertTrue(scanRanges.getRanges().get(2).get(0).isSingleKey());
- assertEquals(Long.valueOf(5399179882L), PDataType.UNSIGNED_LONG.toObject(scanRanges.getRanges().get(2).get(0).getLowerRange()));
- assertEquals(1, extractedNodes.size());
- assertNotNull(scan.getFilter());
- }
-
- @Test
- public void testForceRangeScanKeepsFilters() throws SQLException {
- ensureTableCreated(getUrl(), TestUtil.ENTITY_HISTORY_TABLE_NAME);
- String tenantId = "000000000000001";
- String keyPrefix = "002";
- String query = "select /*+ RANGE_SCAN */ ORGANIZATION_ID, PARENT_ID, CREATED_DATE, ENTITY_HISTORY_ID from " + TestUtil.ENTITY_HISTORY_TABLE_NAME +
- " where ORGANIZATION_ID=? and SUBSTR(PARENT_ID, 1, 3) = ? and CREATED_DATE >= ? and CREATED_DATE < ? order by ORGANIZATION_ID, PARENT_ID, CREATED_DATE, ENTITY_HISTORY_ID limit 6";
- Scan scan = new Scan();
- Date startTime = new Date(System.currentTimeMillis());
- Date stopTime = new Date(startTime.getTime() + TestUtil.MILLIS_IN_DAY);
- List<Object> binds = Arrays.<Object>asList(tenantId, keyPrefix, startTime, stopTime);
- Set<Expression> extractedNodes = Sets.newHashSet();
- compileStatement(query, scan, binds, 6, extractedNodes);
- assertEquals(2, extractedNodes.size());
- assertNotNull(scan.getFilter());
-
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15), PDataType.DATE.toBytes(startTime));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- byte[] expectedStopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15), PDataType.DATE.toBytes(stopTime));
- assertArrayEquals(expectedStopRow, scan.getStopRow());
- }
-
- @Test
- public void testBasicRVCExpression() throws SQLException {
- String tenantId = "000000000000001";
- String entityId = "002333333333331";
- String query = "select * from atable where (organization_id,entity_id) >= (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, entityId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.CHAR.toBytes(tenantId), PDataType.CHAR.toBytes(entityId));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
-
- @Test
- public void testRVCExpressionThroughOr() throws SQLException {
- String tenantId = "000000000000001";
- String entityId = "002333333333331";
- String entityId1 = "002333333333330";
- String entityId2 = "002333333333332";
- String query = "select * from atable where (organization_id,entity_id) >= (?,?) and organization_id = ? and (entity_id = ? or entity_id = ?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, entityId, tenantId, entityId1, entityId2);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 3);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(entityId));
- byte[] expectedStopRow = ByteUtil.concat(ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(entityId2)), QueryConstants.SEPARATOR_BYTE_ARRAY);
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(expectedStopRow, scan.getStopRow());
- }
-
- /**
- * With only a subset of row key cols present (which includes the leading key),
- * Phoenix should have optimized the start row for the scan to include the
- * row keys cols that occur contiguously in the RVC.
- *
- * Table entity_history has the row key defined as (organization_id, parent_id, created_date, entity_history_id).
- * This test uses (organization_id, parent_id, entity_id) in RVC. So the start row should be comprised of
- * organization_id and parent_id.
- * @throws SQLException
- */
- @Test
- public void testRVCExpressionWithSubsetOfPKCols() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000002";
- String entityHistId = "000000000000003";
-
- String query = "select * from entity_history where (organization_id, parent_id, entity_history_id) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId, entityHistId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(parentId));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- /**
- * With the leading row key col missing Phoenix won't be able to optimize
- * and provide the start row for the scan.
- *
- * Table entity_history has the row key defined as (organization_id, parent_id, created_date, entity_history_id).
- * This test uses (parent_id, entity_id) in RVC. Start row should be empty.
- * @throws SQLException
- */
-
- @Test
- public void testRVCExpressionWithoutLeadingColOfRowKey() throws SQLException {
-
- String parentId = "000000000000002";
- String entityHistId = "000000000000003";
-
- String query = "select * from entity_history where (parent_id, entity_history_id) >= (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(parentId, entityHistId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testMultiRVCExpressionsCombinedWithAnd() throws SQLException {
- String lowerTenantId = "000000000000001";
- String lowerParentId = "000000000000002";
- Date lowerCreatedDate = new Date(System.currentTimeMillis());
- String upperTenantId = "000000000000008";
- String upperParentId = "000000000000009";
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?, ?, ?) AND (organization_id, parent_id) <= (?, ?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(lowerTenantId, lowerParentId, lowerCreatedDate, upperTenantId, upperParentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 2);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(lowerTenantId), PDataType.VARCHAR.toBytes(lowerParentId), PDataType.DATE.toBytes(lowerCreatedDate));
- byte[] expectedStopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(upperTenantId), PDataType.VARCHAR.toBytes(upperParentId)));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(expectedStopRow, scan.getStopRow());
- }
-
- @Test
- public void testMultiRVCExpressionsCombinedUsingLiteralExpressions() throws SQLException {
- String lowerTenantId = "000000000000001";
- String lowerParentId = "000000000000002";
- Date lowerCreatedDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?, ?, ?) AND (organization_id, parent_id) <= ('7', '7')";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(lowerTenantId, lowerParentId, lowerCreatedDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 2);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(lowerTenantId), PDataType.VARCHAR.toBytes(lowerParentId), PDataType.DATE.toBytes(lowerCreatedDate));
- byte[] expectedStopRow = ByteUtil.nextKey(ByteUtil.concat(ByteUtil.fillKey(PDataType.VARCHAR.toBytes("7"),15), ByteUtil.fillKey(PDataType.VARCHAR.toBytes("7"), 15)));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(expectedStopRow, scan.getStopRow());
- }
-
- @Test
- public void testUseOfFunctionOnLHSInRVC() throws SQLException {
- String tenantId = "000000000000001";
- String subStringTenantId = tenantId.substring(0, 3);
- String parentId = "000000000000002";
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (substr(organization_id, 1, 3), parent_id, created_date) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(subStringTenantId, parentId, createdDate);
- Set<Expression> extractedFilters = new HashSet<Expression>(2);
- compileStatement(query, scan, binds, extractedFilters);
- byte[] expectedStartRow = PDataType.VARCHAR.toBytes(subStringTenantId);
- assertTrue(extractedFilters.size() == 0);
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testUseOfFunctionOnLHSInMiddleOfRVC() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000002";
- String subStringParentId = parentId.substring(0, 3);
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, substr(parent_id, 1, 3), created_date) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, subStringParentId, createdDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(subStringParentId));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testUseOfFunctionOnLHSInMiddleOfRVCForLTE() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000002";
- String subStringParentId = parentId.substring(0, 3);
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, substr(parent_id, 1, 3), created_date) <= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, subStringParentId, createdDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- byte[] expectedStopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.nextKey(PDataType.VARCHAR.toBytes(subStringParentId)));
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStartRow());
- assertArrayEquals(expectedStopRow, scan.getStopRow());
- }
-
- @Test
- public void testNullAtEndOfRVC() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000002";
- Date createdDate = null;
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(parentId));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testNullInMiddleOfRVC() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = null;
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- byte[] expectedStartRow = ByteUtil.concat(PDataType.CHAR.toBytes(tenantId), new byte[15], ByteUtil.previousKey(PDataType.DATE.toBytes(createdDate)));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testNullAtStartOfRVC() throws SQLException {
- String tenantId = null;
- String parentId = "000000000000002";
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- byte[] expectedStartRow = ByteUtil.concat(new byte[15], ByteUtil.previousKey(PDataType.CHAR.toBytes(parentId)), PDataType.DATE.toBytes(createdDate));
- assertArrayEquals(expectedStartRow, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testRVCInCombinationWithOtherNonRVC() throws SQLException {
- String firstOrgId = "000000000000001";
- String secondOrgId = "000000000000008";
-
- String parentId = "000000000000002";
- Date createdDate = new Date(System.currentTimeMillis());
-
- String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?) AND organization_id <= ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstOrgId, parentId, createdDate, secondOrgId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 2);
- assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstOrgId), PDataType.VARCHAR.toBytes(parentId), PDataType.DATE.toBytes(createdDate)), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(secondOrgId)), scan.getStopRow());
- }
-
- @Test
- public void testGreaterThanEqualTo_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000008";
-
- String query = "select * from entity_history where organization_id >= (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testGreaterThan_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000008";
-
- String query = "select * from entity_history where organization_id > (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testGreaterThan() throws SQLException {
- String tenantId = "000000000000001";
-
- String query = "select * from entity_history where organization_id >?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testLessThanEqualTo_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000008";
-
- String query = "select * from entity_history where organization_id <= (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testLessThan_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
- String tenantId = "000000000000001";
- String parentId = "000000000000008";
-
- String query = "select * from entity_history where organization_id < (?,?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testCombiningRVCUsingOr() throws SQLException {
- String firstTenantId = "000000000000001";
- String secondTenantId = "000000000000005";
- String firstParentId = "000000000000011";
- String secondParentId = "000000000000015";
-
- String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR (organization_id, parent_id) <= (?, ?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId, secondParentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1); // extracts the entire OR
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testCombiningRVCUsingOr2() throws SQLException {
- String firstTenantId = "000000000000001";
- String secondTenantId = "000000000000005";
- String firstParentId = "000000000000011";
- String secondParentId = "000000000000015";
-
- String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR (organization_id, parent_id) >= (?, ?)";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId, secondParentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstTenantId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testCombiningRVCWithNonRVCUsingOr() throws SQLException {
- String firstTenantId = "000000000000001";
- String secondTenantId = "000000000000005";
- String firstParentId = "000000000000011";
-
- String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id >= ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstTenantId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testCombiningRVCWithNonRVCUsingOr2() throws SQLException {
- String firstTenantId = "000000000000001";
- String secondTenantId = "000000000000005";
- String firstParentId = "000000000000011";
-
- String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id <= ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testCombiningRVCWithNonRVCUsingOr3() throws SQLException {
- String firstTenantId = "000000000000005";
- String secondTenantId = "000000000000001";
- String firstParentId = "000000000000011";
- String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id <= ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
- assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
- }
-
- @Test
- public void testUsingRVCNonFullyQualifiedInClause() throws Exception {
- String firstOrgId = "000000000000001";
- String secondOrgId = "000000000000009";
- String firstParentId = "000000000000011";
- String secondParentId = "000000000000021";
- String query = "select * from entity_history where (organization_id, parent_id) IN ((?, ?), (?, ?))";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 0);
- assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstOrgId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(secondOrgId), PDataType.VARCHAR.toBytes(secondParentId))), scan.getStopRow());
- }
-
- @Test
- public void testUsingRVCFullyQualifiedInClause() throws Exception {
- String firstOrgId = "000000000000001";
- String secondOrgId = "000000000000009";
- String firstParentId = "000000000000011";
- String secondParentId = "000000000000021";
- String query = "select * from atable where (organization_id, entity_id) IN ((?, ?), (?, ?))";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId);
- HashSet<Expression> extractedFilters = new HashSet<Expression>();
- StatementContext context = compileStatement(query, scan, binds, extractedFilters);
- assertTrue(extractedFilters.size() == 1);
- List<List<KeyRange>> skipScanRanges = Collections.singletonList(Arrays.asList(
- KeyRange.getKeyRange(ByteUtil.concat(PDataType.CHAR.toBytes(firstOrgId), PDataType.CHAR.toBytes(firstParentId))),
- KeyRange.getKeyRange(ByteUtil.concat(PDataType.CHAR.toBytes(secondOrgId), PDataType.CHAR.toBytes(secondParentId)))));
- assertEquals(skipScanRanges, context.getScanRanges().getRanges());
- assertArrayEquals(ByteUtil.concat(PDataType.CHAR.toBytes(firstOrgId), PDataType.CHAR.toBytes(firstParentId)), scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(PDataType.CHAR.toBytes(secondOrgId), PDataType.CHAR.toBytes(secondParentId), QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- }
-}
[6/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
new file mode 100644
index 0000000..ac2c458
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
@@ -0,0 +1,1313 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.apache.phoenix.util.TestUtil.assertDegenerate;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.coprocessor.GroupedAggregateRegionObserver;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.CountAggregator;
+import org.apache.phoenix.expression.aggregator.ServerAggregators;
+import org.apache.phoenix.expression.function.TimeUnit;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.AmbiguousColumnException;
+import org.apache.phoenix.schema.ColumnAlreadyExistsException;
+import org.apache.phoenix.schema.ColumnNotFoundException;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+
+
+/**
+ *
+ * Tests for compiling a query
+ * The compilation stage finds additional errors that can't be found at parse
+ * time so this is a good place for negative tests (since the mini-cluster
+ * is not necessary enabling the tests to run faster).
+ *
+ *
+ * @since 0.1
+ */
+@edu.umd.cs.findbugs.annotations.SuppressWarnings(
+ value="RV_RETURN_VALUE_IGNORED",
+ justification="Test code.")
+public class QueryCompilerTest extends BaseConnectionlessQueryTest {
+
+ @Test
+ public void testParameterUnbound() throws Exception {
+ try {
+ String query = "SELECT a_string, b_string FROM atable WHERE organization_id=? and a_integer = ?";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Parameter 2 is unbound"));
+ }
+ }
+
+ @Test
+ public void testMultiPKDef() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (pk1 integer not null primary key, pk2 bigint not null primary key)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 510 (42889): The table already has a primary key. columnName=PK2"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testPKDefAndPKConstraint() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (pk integer not null primary key, col1 decimal, col2 decimal constraint my_pk primary key (col1,col2))";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 510 (42889): The table already has a primary key. columnName=PK"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testFamilyNameInPK() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (a.pk integer not null primary key, col1 decimal, col2 decimal)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertEquals(e.getErrorCode(), SQLExceptionCode.PRIMARY_KEY_WITH_FAMILY_NAME.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSameColumnNameInPKAndNonPK() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE t1 (k integer not null primary key, a.k decimal, b.k decimal)";
+ conn.createStatement().execute(query);
+ PColumn c = conn.unwrap(PhoenixConnection.class).getPMetaData().getTable("T1").getColumn("K");
+ assertTrue(SchemaUtil.isPKColumn(c));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testVarBinaryInMultipartPK() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ // When the VARBINARY key is the last column, it is allowed.
+ String query = "CREATE TABLE foo (a_string varchar not null, b_string varchar not null, a_binary varbinary not null, " +
+ "col1 decimal, col2 decimal CONSTRAINT pk PRIMARY KEY (a_string, b_string, a_binary))";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ try {
+ // VARBINARY key is not allowed in the middle of the key.
+ query = "CREATE TABLE foo (a_binary varbinary not null, a_string varchar not null, col1 decimal, col2 decimal CONSTRAINT pk PRIMARY KEY (a_binary, a_string))";
+ statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1005 (42J03): The VARBINARY type can only be used as the last part of a multi-part row key. columnName=FOO.A_BINARY"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testNoPK() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (pk integer not null, col1 decimal, col2 decimal)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 509 (42888): The table does not have a primary key. tableName=FOO"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUnknownFamilyNameInTableOption() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (pk integer not null primary key, a.col1 decimal, b.col2 decimal) c.my_property='foo'";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Properties may not be defined for an unused family name"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInvalidGroupedAggregation() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT count(1),a_integer FROM atable WHERE organization_id=? GROUP BY a_string";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
+ }
+ }
+
+ @Test
+ public void testInvalidGroupExpressionAggregation() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT sum(a_integer) + a_integer FROM atable WHERE organization_id=? GROUP BY a_string";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
+ }
+ }
+
+ @Test
+ public void testAggInWhereClause() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT a_integer FROM atable WHERE organization_id=? AND count(1) > 2";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1017 (42Y26): Aggregate may not be used in WHERE."));
+ }
+ }
+
+ @Test
+ public void testHavingAggregateQuery() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING count(1) > 2";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
+ }
+ }
+
+ @Test
+ public void testNonAggInHavingClause() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING a_integer = 5";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1019 (42Y26): Only aggregate maybe used in the HAVING clause."));
+ }
+ }
+
+ @Test
+ public void testTypeMismatchInCase() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING CASE WHEN a_integer <= 2 THEN 'foo' WHEN a_integer = 3 THEN 2 WHEN a_integer <= 5 THEN 5 ELSE 5 END = 5";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Case expressions must have common type"));
+ }
+ }
+
+ @Test
+ public void testNonBooleanWhereExpression() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "SELECT a_integer FROM atable WHERE organization_id=? and CASE WHEN a_integer <= 2 THEN 'foo' WHEN a_integer = 3 THEN 'bar' WHEN a_integer <= 5 THEN 'bas' ELSE 'blah' END";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("ERROR 203 (22005): Type mismatch. BOOLEAN and VARCHAR for CASE WHEN A_INTEGER <= 2 THEN 'foo'WHEN A_INTEGER = 3 THEN 'bar'WHEN A_INTEGER <= 5 THEN 'bas' ELSE 'blah' END"));
+ }
+ }
+
+ @Test
+ public void testNoSCNInConnectionProps() throws Exception {
+ Properties props = new Properties();
+ DriverManager.getConnection(getUrl(), props);
+ }
+
+
+ @Test
+ public void testPercentileWrongQueryWithMixOfAggrAndNonAggrExps() throws Exception {
+ String query = "select a_integer, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
+ try {
+ compileQuery(query, Collections.emptyList());
+ fail();
+ } catch (SQLException e) {
+ assertEquals("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testPercentileWrongQuery1() throws Exception {
+ String query = "select PERCENTILE_CONT('*') WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
+ try {
+ compileQuery(query, Collections.emptyList());
+ fail();
+ } catch (SQLException e) {
+ assertEquals(
+ "ERROR 203 (22005): Type mismatch. expected: [DECIMAL] but was: VARCHAR at PERCENTILE_CONT argument 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testPercentileWrongQuery2() throws Exception {
+ String query = "select PERCENTILE_CONT(1.1) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
+ try {
+ compileQuery(query, Collections.emptyList());
+ fail();
+ } catch (SQLException e) {
+ assertEquals(
+ "ERROR 213 (22003): Value outside range. expected: [0 , 1] but was: 1.1 at PERCENTILE_CONT argument 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testPercentileWrongQuery3() throws Exception {
+ String query = "select PERCENTILE_CONT(-1) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
+ try {
+ compileQuery(query, Collections.emptyList());
+ fail();
+ } catch (Exception e) {
+ assertEquals(
+ "ERROR 213 (22003): Value outside range. expected: [0 , 1] but was: -1 at PERCENTILE_CONT argument 3",
+ e.getMessage());
+ }
+ }
+
+ private Scan compileQuery(String query, List<Object> binds) throws SQLException {
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PhoenixPreparedStatement statement = conn.prepareStatement(query).unwrap(PhoenixPreparedStatement.class);
+ for (Object bind : binds) {
+ statement.setObject(1, bind);
+ }
+ QueryPlan plan = statement.compileQuery(query);
+ return plan.getContext().getScan();
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testKeyOrderedGroupByOptimization() throws Exception {
+ // Select columns in PK
+ String[] queries = new String[] {
+ "SELECT count(1) FROM atable GROUP BY organization_id,entity_id",
+ "SELECT count(1) FROM atable GROUP BY organization_id,substr(entity_id,1,3),entity_id",
+ "SELECT count(1) FROM atable GROUP BY entity_id,organization_id",
+ "SELECT count(1) FROM atable GROUP BY substr(entity_id,1,3),organization_id",
+ "SELECT count(1) FROM ptsdb GROUP BY host,inst,round(date,'HOUR')",
+ "SELECT count(1) FROM atable GROUP BY organization_id",
+ };
+ List<Object> binds = Collections.emptyList();
+ for (String query : queries) {
+ Scan scan = compileQuery(query, binds);
+ assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS) != null);
+ assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS) == null);
+ }
+ }
+
+ @Test
+ public void testNullInScanKey() throws Exception {
+ // Select columns in PK
+ String query = "select val from ptsdb where inst is null and host='a'";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ // Projects column family with not null column
+ assertNull(scan.getFilter());
+ assertEquals(1,scan.getFamilyMap().keySet().size());
+ assertArrayEquals(Bytes.toBytes(SchemaUtil.normalizeIdentifier(QueryConstants.DEFAULT_COLUMN_FAMILY)), scan.getFamilyMap().keySet().iterator().next());
+ }
+
+ @Test
+ public void testOnlyNullInScanKey() throws Exception {
+ // Select columns in PK
+ String query = "select val from ptsdb where inst is null";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ // Projects column family with not null column
+ assertEquals(1,scan.getFamilyMap().keySet().size());
+ assertArrayEquals(Bytes.toBytes(SchemaUtil.normalizeIdentifier(QueryConstants.DEFAULT_COLUMN_FAMILY)), scan.getFamilyMap().keySet().iterator().next());
+ }
+
+ @Test
+ public void testIsNullOnNotNullable() throws Exception {
+ // Select columns in PK
+ String query = "select a_string from atable where entity_id is null";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testIsNotNullOnNotNullable() throws Exception {
+ // Select columns in PK
+ String query = "select a_string from atable where entity_id is not null";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ assertNull(scan.getFilter());
+ assertTrue(scan.getStartRow().length == 0);
+ assertTrue(scan.getStopRow().length == 0);
+ }
+
+ @Test
+ public void testUpsertTypeMismatch() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "upsert into ATABLE VALUES (?, ?, ?)";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.setString(2, "00D300000000XHP");
+ statement.setInt(3, 1);
+ statement.executeUpdate();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) { // TODO: use error codes
+ assertTrue(e.getMessage().contains("Type mismatch"));
+ }
+ }
+
+ @Test
+ public void testUpsertMultiByteIntoChar() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "upsert into ATABLE VALUES (?, ?, ?)";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, "00D300000000XHP");
+ statement.setString(2, "繰り返し曜日マスク");
+ statement.setInt(3, 1);
+ statement.executeUpdate();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 201 (22000): Illegal data."));
+ assertTrue(e.getCause().getMessage().contains("CHAR types may only contain single byte characters"));
+ }
+ }
+
+ @Test
+ public void testSelectStarOnGroupBy() throws Exception {
+ try {
+ // Select non agg column in aggregate query
+ String query = "select * from ATABLE group by a_string";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY."));
+ }
+ }
+
+ @Test
+ public void testOrderByAggSelectNonAgg() throws Exception {
+ try {
+ // Order by in select with no limit or group by
+ String query = "select a_string from ATABLE order by max(b_string)";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_STRING"));
+ }
+ }
+
+ @Test
+ public void testOrderByAggAndNonAgg() throws Exception {
+ try {
+ // Order by in select with no limit or group by
+ String query = "select max(a_string) from ATABLE order by max(b_string),a_string";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_STRING"));
+ }
+ }
+
+ @Test
+ public void testOrderByNonAggSelectAgg() throws Exception {
+ try {
+ // Order by in select with no limit or group by
+ String query = "select max(a_string) from ATABLE order by b_string LIMIT 5";
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. B_STRING"));
+ }
+ }
+
+ @Test
+ public void testNotKeyOrderedGroupByOptimization() throws Exception {
+ // Select columns in PK
+ String[] queries = new String[] {
+ "SELECT count(1) FROM atable GROUP BY entity_id",
+ "SELECT count(1) FROM atable GROUP BY substr(organization_id,2,3)",
+ "SELECT count(1) FROM atable GROUP BY substr(entity_id,1,3)",
+ "SELECT count(1) FROM atable GROUP BY to_date(organization_id)",
+ "SELECT count(1) FROM atable GROUP BY regexp_substr(organization_id, '.*foo.*'),entity_id",
+ "SELECT count(1) FROM atable GROUP BY substr(organization_id,1),entity_id",
+ };
+ List<Object> binds = Collections.emptyList();
+ for (String query : queries) {
+ Scan scan = compileQuery(query, binds);
+ assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS) == null);
+ assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS) != null);
+ }
+ }
+
+ @Test
+ public void testFunkyColumnNames() throws Exception {
+ // Select columns in PK
+ String[] queries = new String[] {
+ "SELECT \"foo!\",\"foo.bar-bas\",\"#@$\",\"_blah^\" FROM FUNKY_NAMES",
+ "SELECT count(\"foo!\"),\"_blah^\" FROM FUNKY_NAMES WHERE \"foo.bar-bas\"='x' GROUP BY \"#@$\",\"_blah^\"",
+ };
+ List<Object> binds = Collections.emptyList();
+ for (String query : queries) {
+ compileQuery(query, binds);
+ }
+ }
+
+ @Test
+ public void testCountAggregatorFirst() throws Exception {
+ String[] queries = new String[] {
+ "SELECT sum(2.5),organization_id FROM atable GROUP BY organization_id,entity_id",
+ "SELECT avg(a_integer) FROM atable GROUP BY organization_id,substr(entity_id,1,3),entity_id",
+ "SELECT count(a_string) FROM atable GROUP BY substr(organization_id,1),entity_id",
+ "SELECT min('foo') FROM atable GROUP BY entity_id,organization_id",
+ "SELECT min('foo'),sum(a_integer),avg(2.5),4.5,max(b_string) FROM atable GROUP BY substr(organization_id,1),entity_id",
+ "SELECT sum(2.5) FROM atable",
+ "SELECT avg(a_integer) FROM atable",
+ "SELECT count(a_string) FROM atable",
+ "SELECT min('foo') FROM atable LIMIT 5",
+ "SELECT min('foo'),sum(a_integer),avg(2.5),4.5,max(b_string) FROM atable",
+ };
+ List<Object> binds = Collections.emptyList();
+ String query = null;
+ try {
+ for (int i = 0; i < queries.length; i++) {
+ query = queries[i];
+ Scan scan = compileQuery(query, binds);
+ ServerAggregators aggregators = ServerAggregators.deserialize(scan.getAttribute(GroupedAggregateRegionObserver.AGGREGATORS), null);
+ Aggregator aggregator = aggregators.getAggregators()[0];
+ assertTrue(aggregator instanceof CountAggregator);
+ }
+ } catch (Exception e) {
+ throw new Exception(query, e);
+ }
+ }
+
+ @Test
+ public void testInvalidArithmetic() throws Exception {
+ String[] queries = new String[] {
+ "SELECT entity_id,organization_id FROM atable where A_STRING - 5.5 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_DATE - 'transaction' < 0",
+ "SELECT entity_id,organization_id FROM atable where A_DATE * 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_DATE / 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where 45 - A_DATE < 0",
+ "SELECT entity_id,organization_id FROM atable where A_DATE - to_date('2000-01-01 12:00:00') < to_date('2000-02-01 12:00:00')", // RHS must be number
+ "SELECT entity_id,organization_id FROM atable where A_DATE - A_DATE + 1 < A_DATE", // RHS must be number
+ "SELECT entity_id,organization_id FROM atable where A_DATE + 2 < 0", // RHS must be date
+ "SELECT entity_id,organization_id FROM atable where 45.5 - A_DATE < 0",
+ "SELECT entity_id,organization_id FROM atable where 1 + A_DATE + A_DATE < A_DATE",
+ "SELECT entity_id,organization_id FROM atable where A_STRING - 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_STRING / 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_STRING * 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_STRING + 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_STRING - 45 < 0",
+ "SELECT entity_id,organization_id FROM atable where A_STRING - 'transaction' < 0", };
+
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ for (String query : queries) {
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail(query);
+ } catch (SQLException e) {
+ if (e.getMessage().contains("ERROR 203 (22005): Type mismatch.")) {
+ continue;
+ }
+ throw new IllegalStateException("Didn't find type mismatch: " + query, e);
+ }
+ }
+ }
+
+
+ @Test
+ public void testAmbiguousColumn() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT * from multi_cf G where RESPONSE_TIME = 2222";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (AmbiguousColumnException e) { // expected
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testTableAliasMatchesCFName() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT F.RESPONSE_TIME,G.RESPONSE_TIME from multi_cf G where G.RESPONSE_TIME-1 = F.RESPONSE_TIME";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (AmbiguousColumnException e) { // expected
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testCoelesceFunctionTypeMismatch() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT coalesce(x_integer,'foo') from atable";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 507 (42846): Cannot convert type. COALESCE expected INTEGER, but got VARCHAR"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testOrderByNotInSelectDistinct() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT distinct a_string,b_string from atable order by x_integer";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertEquals(SQLExceptionCode.ORDER_BY_NOT_IN_SELECT_DISTINCT.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectDistinctAndAll() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT all distinct a_string,b_string from atable order by x_integer";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertEquals(SQLExceptionCode.PARSER_ERROR.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testOrderByNotInSelectDistinctAgg() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT distinct count(1) from atable order by x_integer";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertEquals(SQLExceptionCode.ORDER_BY_NOT_IN_SELECT_DISTINCT.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectDistinctWithAggregation() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT distinct a_string,count(*) from atable";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertEquals(SQLExceptionCode.AGGREGATE_WITH_NOT_GROUP_BY_COLUMN.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRegexpSubstrSetScanKeys() throws Exception {
+ // First test scan keys are set when the offset is 0 or 1.
+ String query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+') = 'abc'";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ assertTrue(scan.getFilter() != null);
+
+ query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+', 0) = 'abc'";
+ binds = Collections.emptyList();
+ scan = compileQuery(query, binds);
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ assertTrue(scan.getFilter() != null);
+
+ // Test scan keys are not set when the offset is not 0 or 1.
+ query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+', 3) = 'abc'";
+ binds = Collections.emptyList();
+ scan = compileQuery(query, binds);
+ assertTrue(scan.getStartRow().length == 0);
+ assertTrue(scan.getStopRow().length == 0);
+ assertTrue(scan.getFilter() != null);
+ }
+
+ @Test
+ public void testStringConcatExpression() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT entity_id,a_string FROM atable where 2 || a_integer || ? like '2%'";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Properties props = new Properties(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(url, props);
+ byte []x=new byte[]{127,127,0,0};//Binary data
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setBytes(1, x);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getMessage().contains("Concatenation does not support"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDivideByBigDecimalZero() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT a_integer/x_integer/0.0 FROM atable";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getMessage().contains("Divide by zero"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDivideByIntegerZero() throws Exception {
+ long ts = nextTimestamp();
+ String query = "SELECT a_integer/0 FROM atable";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getMessage().contains("Divide by zero"));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testCreateNullableInPKMiddle() throws Exception {
+ long ts = nextTimestamp();
+ String query = "CREATE TABLE foo(i integer not null, j integer null, k integer not null CONSTRAINT pk PRIMARY KEY(i,j,k))";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getMessage().contains("PK columns may not be both fixed width and nullable"));
+ }
+ }
+
+ @Test
+ public void testSetSaltBucketOnAlterTable() throws Exception {
+ long ts = nextTimestamp();
+ String query = "ALTER TABLE atable ADD xyz INTEGER SALT_BUCKETS=4";
+ String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) { // expected
+ assertTrue(e.getErrorCode() == SQLExceptionCode.SALT_ONLY_ON_CREATE_TABLE.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSubstrSetScanKey() throws Exception {
+ String query = "SELECT inst FROM ptsdb WHERE substr(inst, 0, 3) = 'abc'";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abd"),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ assertTrue(scan.getFilter() == null); // Extracted.
+ }
+
+ @Test
+ public void testRTrimSetScanKey() throws Exception {
+ String query = "SELECT inst FROM ptsdb WHERE rtrim(inst) = 'abc'";
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery(query, binds);
+ assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc ")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ assertNotNull(scan.getFilter());
+ }
+
+ @Test
+ public void testCastingIntegerToDecimalInSelect() throws Exception {
+ String query = "SELECT CAST a_integer AS DECIMAL/2 FROM aTable WHERE 5=a_integer";
+ List<Object> binds = Collections.emptyList();
+ compileQuery(query, binds);
+ }
+
+ @Test
+ public void testCastingStringToDecimalInSelect() throws Exception {
+ String query = "SELECT CAST b_string AS DECIMAL/2 FROM aTable WHERE 5=a_integer";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a string to decimal isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testCastingStringToDecimalInWhere() throws Exception {
+ String query = "SELECT a_integer FROM aTable WHERE 2.5=CAST b_string AS DECIMAL/2 ";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a string to decimal isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUsingNonComparableDataTypesInRowValueConstructorFails() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE (a_integer, x_integer) > (2, 'abc')";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a integer to string isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUsingNonComparableDataTypesOfColumnRefOnLHSAndRowValueConstructorFails() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE a_integer > ('abc', 2)";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a integer to string isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUsingNonComparableDataTypesOfLiteralOnLHSAndRowValueConstructorFails() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE 'abc' > (a_integer, x_integer)";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a integer to string isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUsingNonComparableDataTypesOfColumnRefOnRHSAndRowValueConstructorFails() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE ('abc', 2) < a_integer ";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a integer to string isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUsingNonComparableDataTypesOfLiteralOnRHSAndRowValueConstructorFails() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE (a_integer, x_integer) < 'abc'";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since casting a integer to string isn't supported");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testNonConstantInList() throws Exception {
+ String query = "SELECT a_integer, x_integer FROM aTable WHERE a_integer IN (x_integer)";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since non constants in IN is not valid");
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.VALUE_IN_LIST_NOT_CONSTANT.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testKeyValueColumnInPKConstraint() throws Exception {
+ String ddl = "CREATE TABLE t (a.k VARCHAR, b.v VARCHAR CONSTRAINT pk PRIMARY KEY(k))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getErrorCode() == SQLExceptionCode.PRIMARY_KEY_WITH_FAMILY_NAME.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testUnknownColumnInPKConstraint() throws Exception {
+ String ddl = "CREATE TABLE t (k1 VARCHAR, b.v VARCHAR CONSTRAINT pk PRIMARY KEY(k1, k2))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (ColumnNotFoundException e) {
+ assertEquals("K2",e.getColumnName());
+ }
+ }
+
+
+ @Test
+ public void testDuplicatePKColumn() throws Exception {
+ String ddl = "CREATE TABLE t (k1 VARCHAR, k1 VARCHAR CONSTRAINT pk PRIMARY KEY(k1))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (ColumnAlreadyExistsException e) {
+ assertEquals("K1",e.getColumnName());
+ }
+ }
+
+
+ @Test
+ public void testDuplicateKVColumn() throws Exception {
+ String ddl = "CREATE TABLE t (k1 VARCHAR, v1 VARCHAR, v2 VARCHAR, v1 INTEGER CONSTRAINT pk PRIMARY KEY(k1))";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (ColumnAlreadyExistsException e) {
+ assertEquals("V1",e.getColumnName());
+ }
+ }
+
+ @Test
+ public void testDeleteFromImmutableWithKV() throws Exception {
+ String ddl = "CREATE TABLE t (k1 VARCHAR, v1 VARCHAR, v2 VARCHAR CONSTRAINT pk PRIMARY KEY(k1)) immutable_rows=true";
+ String indexDDL = "CREATE INDEX i ON t (v1)";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute(indexDDL);
+ conn.createStatement().execute("DELETE FROM t");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NO_DELETE_IF_IMMUTABLE_INDEX.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testInvalidNegativeArrayIndex() throws Exception {
+ String query = "SELECT a_double_array[-20] FROM table_with_array";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(query);
+ fail();
+ } catch (Exception e) {
+
+ }
+ }
+ @Test
+ public void testWrongDataTypeInRoundFunction() throws Exception {
+ String query = "SELECT ROUND(a_string, 'day', 1) FROM aTable";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since VARCHAR is not a valid data type for ROUND");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testNonArrayColumnWithIndex() throws Exception {
+ String query = "SELECT a_float[1] FROM table_with_array";
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute(query);
+ fail();
+ } catch (Exception e) {
+ }
+ }
+
+ public void testWrongTimeUnitInRoundDateFunction() throws Exception {
+ String query = "SELECT ROUND(a_date, 'dayss', 1) FROM aTable";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since dayss is not a valid time unit type");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains(TimeUnit.VALID_VALUES));
+ }
+ }
+
+ @Test
+ public void testWrongMultiplierInRoundDateFunction() throws Exception {
+ String query = "SELECT ROUND(a_date, 'days', 1.23) FROM aTable";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since multiplier can be an INTEGER only");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testTypeMismatchForArrayElem() throws Exception {
+ String query = "SELECT (a_string,a_date)[1] FROM aTable";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since a row value constructor is not an array");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testTypeMismatch2ForArrayElem() throws Exception {
+ String query = "SELECT ROUND(a_date, 'days', 1.23)[1] FROM aTable";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since ROUND does not return an array");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testInvalidArrayTypeAsPK () throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (col1 INTEGER[10] NOT NULL PRIMARY KEY)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.ARRAY_NOT_ALLOWED_IN_PRIMARY_KEY.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+
+ conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (col1 VARCHAR, col2 INTEGER ARRAY[10] CONSTRAINT pk PRIMARY KEY (col1, col2))";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.ARRAY_NOT_ALLOWED_IN_PRIMARY_KEY.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInvalidArraySize() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ String query = "CREATE TABLE foo (col1 INTEGER[-1] NOT NULL PRIMARY KEY)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.execute();
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.MISMATCHED_TOKEN.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInvalidArrayInQuery () throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k VARCHAR PRIMARY KEY, a INTEGER[10], B INTEGER[10])");
+ try {
+ conn.createStatement().execute("SELECT * FROM t ORDER BY a");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.ORDER_BY_ARRAY_NOT_SUPPORTED.getErrorCode(), e.getErrorCode());
+ }
+ try {
+ conn.createStatement().execute("SELECT * FROM t WHERE a < b");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NON_EQUALITY_ARRAY_COMPARISON.getErrorCode(), e.getErrorCode());
+ }
+ conn.close();
+ }
+
+ @Test
+ public void testInvalidArrayElemRefInUpsert() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k VARCHAR PRIMARY KEY, a INTEGER[10], B INTEGER[10])");
+ try {
+ conn.createStatement().execute("UPSERT INTO t(k,a[2]) VALUES('A', 5)");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.PARSER_ERROR.getErrorCode(), e.getErrorCode());
+ }
+ conn.close();
+ }
+
+ @Test
+ public void testInvalidNextValueFor() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE SEQUENCE alpha.zeta");
+ String[] queries = {
+ "SELECT * FROM aTable WHERE a_integer < next value for alpha.zeta",
+ "SELECT * FROM aTable GROUP BY a_string,next value for alpha.zeta",
+ "SELECT * FROM aTable GROUP BY 1 + next value for alpha.zeta",
+ "SELECT * FROM aTable GROUP BY a_integer HAVING a_integer < next value for alpha.zeta",
+ "SELECT * FROM aTable WHERE a_integer < 3 GROUP BY a_integer HAVING a_integer < next value for alpha.zeta",
+ "SELECT * FROM aTable ORDER BY next value for alpha.zeta",
+ "SELECT max(next value for alpha.zeta) FROM aTable",
+ };
+ for (String query : queries) {
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileQuery(query, binds);
+ fail("Compilation should have failed since this is an invalid usage of NEXT VALUE FOR: " + query);
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.INVALID_USE_OF_NEXT_VALUE_FOR.getErrorCode(), e.getErrorCode());
+ }
+ }
+ }
+
+ @Test
+ public void testNoCachingHint() throws Exception {
+ List<Object> binds = Collections.emptyList();
+ Scan scan = compileQuery("select val from ptsdb", binds);
+ assertTrue(scan.getCacheBlocks());
+ scan = compileQuery("select /*+ NO_CACHE */ val from ptsdb", binds);
+ assertFalse(scan.getCacheBlocks());
+ scan = compileQuery("select /*+ NO_CACHE */ p1.val from ptsdb p1 inner join ptsdb p2 on p1.inst = p2.inst", binds);
+ assertFalse(scan.getCacheBlocks());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompileTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompileTest.java
deleted file mode 100644
index 58db078..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompileTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Properties;
-
-import org.junit.Test;
-
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.schema.ColumnNotFoundException;
-import org.apache.phoenix.schema.PTable;
-import org.apache.phoenix.schema.PTable.ViewType;
-import org.apache.phoenix.schema.PTableType;
-import org.apache.phoenix.util.TestUtil;
-
-public class ViewCompileTest extends BaseConnectionlessQueryTest {
- @Test
- public void testViewTypeCalculation() throws Exception {
- assertViewType(new String[] {
- "CREATE VIEW v1 AS SELECT * FROM t WHERE k1 = 1 AND k2 = 'foo'",
- "CREATE VIEW v2 AS SELECT * FROM t WHERE k2 = 'foo'",
- "CREATE VIEW v3 AS SELECT * FROM t WHERE v = 'bar'||'bas'",
- "CREATE VIEW v4 AS SELECT * FROM t WHERE 'bar'=v and 5+3/2 = k1",
- }, ViewType.UPDATABLE);
- assertViewType(new String[] {
- "CREATE VIEW v1 AS SELECT * FROM t WHERE k1 < 1 AND k2 = 'foo'",
- "CREATE VIEW v2 AS SELECT * FROM t WHERE substr(k2,0,3) = 'foo'",
- "CREATE VIEW v3 AS SELECT * FROM t WHERE v = TO_CHAR(CURRENT_DATE())",
- "CREATE VIEW v4 AS SELECT * FROM t WHERE 'bar'=v or 3 = k1",
- }, ViewType.READ_ONLY);
- }
-
- public void assertViewType(String[] views, ViewType viewType) throws Exception {
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
- String ct = "CREATE TABLE t (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))";
- conn.createStatement().execute(ct);
-
- for (String view : views) {
- conn.createStatement().execute(view);
- }
-
- int count = 0;
- for (PTable table : conn.getPMetaData().getTables().values()) {
- if (table.getType() == PTableType.VIEW) {
- assertEquals(viewType, table.getViewType());
- conn.createStatement().execute("DROP VIEW " + table.getName().getString());
- count++;
- }
- }
- assertEquals(views.length, count);
- }
-
- @Test
- public void testViewInvalidation() throws Exception {
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
- String ct = "CREATE TABLE t (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))";
- conn.createStatement().execute(ct);
- conn.createStatement().execute("CREATE VIEW v3 AS SELECT * FROM t WHERE v = 'bar'");
-
- // TODO: should it be an error to remove columns from a VIEW that we're defined there?
- // TOOD: should we require an ALTER VIEW instead of ALTER TABLE?
- conn.createStatement().execute("ALTER VIEW v3 DROP COLUMN v");
- try {
- conn.createStatement().executeQuery("SELECT * FROM v3");
- fail();
- } catch (ColumnNotFoundException e) {
-
- }
-
- // No error, as v still exists in t
- conn.createStatement().execute("CREATE VIEW v4 AS SELECT * FROM t WHERE v = 'bas'");
-
- // No error, even though view is invalid
- conn.createStatement().execute("DROP VIEW v3");
- }
-
-
- @Test
- public void testInvalidUpsertSelect() throws Exception {
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
- conn.createStatement().execute("CREATE TABLE t1 (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))");
- conn.createStatement().execute("CREATE TABLE t2 (k3 INTEGER NOT NULL, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k3))");
- conn.createStatement().execute("CREATE VIEW v1 AS SELECT * FROM t1 WHERE k1 = 1");
-
- try {
- conn.createStatement().executeUpdate("UPSERT INTO v1 SELECT k3,'foo',v FROM t2");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN.getErrorCode(), e.getErrorCode());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompilerTest.java
new file mode 100644
index 0000000..8af9f28
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/ViewCompilerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.junit.Test;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.schema.ColumnNotFoundException;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTable.ViewType;
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.util.TestUtil;
+
+public class ViewCompilerTest extends BaseConnectionlessQueryTest {
+ @Test
+ public void testViewTypeCalculation() throws Exception {
+ assertViewType(new String[] {
+ "CREATE VIEW v1 AS SELECT * FROM t WHERE k1 = 1 AND k2 = 'foo'",
+ "CREATE VIEW v2 AS SELECT * FROM t WHERE k2 = 'foo'",
+ "CREATE VIEW v3 AS SELECT * FROM t WHERE v = 'bar'||'bas'",
+ "CREATE VIEW v4 AS SELECT * FROM t WHERE 'bar'=v and 5+3/2 = k1",
+ }, ViewType.UPDATABLE);
+ assertViewType(new String[] {
+ "CREATE VIEW v1 AS SELECT * FROM t WHERE k1 < 1 AND k2 = 'foo'",
+ "CREATE VIEW v2 AS SELECT * FROM t WHERE substr(k2,0,3) = 'foo'",
+ "CREATE VIEW v3 AS SELECT * FROM t WHERE v = TO_CHAR(CURRENT_DATE())",
+ "CREATE VIEW v4 AS SELECT * FROM t WHERE 'bar'=v or 3 = k1",
+ }, ViewType.READ_ONLY);
+ }
+
+ public void assertViewType(String[] views, ViewType viewType) throws Exception {
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
+ String ct = "CREATE TABLE t (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))";
+ conn.createStatement().execute(ct);
+
+ for (String view : views) {
+ conn.createStatement().execute(view);
+ }
+
+ int count = 0;
+ for (PTable table : conn.getPMetaData().getTables().values()) {
+ if (table.getType() == PTableType.VIEW) {
+ assertEquals(viewType, table.getViewType());
+ conn.createStatement().execute("DROP VIEW " + table.getName().getString());
+ count++;
+ }
+ }
+ assertEquals(views.length, count);
+ }
+
+ @Test
+ public void testViewInvalidation() throws Exception {
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
+ String ct = "CREATE TABLE t (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))";
+ conn.createStatement().execute(ct);
+ conn.createStatement().execute("CREATE VIEW v3 AS SELECT * FROM t WHERE v = 'bar'");
+
+ // TODO: should it be an error to remove columns from a VIEW that we're defined there?
+ // TOOD: should we require an ALTER VIEW instead of ALTER TABLE?
+ conn.createStatement().execute("ALTER VIEW v3 DROP COLUMN v");
+ try {
+ conn.createStatement().executeQuery("SELECT * FROM v3");
+ fail();
+ } catch (ColumnNotFoundException e) {
+
+ }
+
+ // No error, as v still exists in t
+ conn.createStatement().execute("CREATE VIEW v4 AS SELECT * FROM t WHERE v = 'bas'");
+
+ // No error, even though view is invalid
+ conn.createStatement().execute("DROP VIEW v3");
+ }
+
+
+ @Test
+ public void testInvalidUpsertSelect() throws Exception {
+ Properties props = new Properties(TestUtil.TEST_PROPERTIES);
+ PhoenixConnection conn = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class);
+ conn.createStatement().execute("CREATE TABLE t1 (k1 INTEGER NOT NULL, k2 VARCHAR, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))");
+ conn.createStatement().execute("CREATE TABLE t2 (k3 INTEGER NOT NULL, v VARCHAR, CONSTRAINT pk PRIMARY KEY (k3))");
+ conn.createStatement().execute("CREATE VIEW v1 AS SELECT * FROM t1 WHERE k1 = 1");
+
+ try {
+ conn.createStatement().executeUpdate("UPSERT INTO v1 SELECT k3,'foo',v FROM t2");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN.getErrorCode(), e.getErrorCode());
+ }
+ }
+}
[2/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/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
new file mode 100644
index 0000000..96a8cef
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
@@ -0,0 +1,1620 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.apache.phoenix.util.TestUtil.assertDegenerate;
+import static org.apache.phoenix.util.TestUtil.assertEmptyScanKey;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.OrExpression;
+import org.apache.phoenix.filter.RowKeyComparisonFilter;
+import org.apache.phoenix.filter.SkipScanFilter;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.SQLParser;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.ColumnNotFoundException;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+
+
+public class WhereOptimizerTest extends BaseConnectionlessQueryTest {
+
+ private static StatementContext compileStatement(String query, Scan scan, List<Object> binds) throws SQLException {
+ return compileStatement(query, scan, binds, null, null);
+ }
+
+ private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Integer limit) throws SQLException {
+ return compileStatement(query, scan, binds, limit, null);
+ }
+
+ private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Set<Expression> extractedNodes) throws SQLException {
+ return compileStatement(query, scan, binds, null, extractedNodes);
+ }
+
+ // TODO: remove this and replace checks on extractedNodes with tests for the scan filter
+ private static StatementContext compileStatement(String query, Scan scan, List<Object> binds, Integer limit, Set<Expression> extractedNodes) throws SQLException {
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ statement = StatementNormalizer.normalize(statement, resolver);
+ StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+
+ Integer actualLimit = LimitCompiler.compile(context, statement);
+ assertEquals(limit, actualLimit);
+ GroupBy groupBy = GroupByCompiler.compile(context, statement);
+ statement = HavingCompiler.rewrite(context, statement, groupBy);
+ WhereCompiler.compileWhereClause(context, statement, extractedNodes);
+ return context;
+ }
+
+ @Test
+ public void testSingleKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ compileStatement(query, scan, binds);
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testReverseSingleKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where '" + tenantId + "' = organization_id";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ compileStatement(query, scan, binds);
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testStartKeyStopKey() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE start_stop_test (pk char(2) not null primary key)");
+ conn.close();
+
+ String query = "select * from start_stop_test where pk >= 'EA' and pk < 'EZ'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ assertArrayEquals(PDataType.VARCHAR.toBytes("EA"), scan.getStartRow());
+ assertArrayEquals(PDataType.VARCHAR.toBytes("EZ"), scan.getStopRow());
+ }
+
+ @Test
+ public void testConcatSingleKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id || 'foo' ='" + tenantId + "'||'foo'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ // The || operator cannot currently be used to form the start/stop key
+ assertNotNull(scan.getFilter());
+ assertEquals(0, scan.getStartRow().length);
+ assertEquals(0, scan.getStopRow().length);
+ }
+
+ @Test
+ public void testLiteralConcatExpression() throws SQLException {
+ String query = "select * from atable where null||'foo'||'bar' = 'foobar'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ assertEquals(0, scan.getStartRow().length);
+ assertEquals(0, scan.getStopRow().length);
+ }
+
+ @Test
+ public void testSingleKeyNotExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where not organization_id='" + tenantId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNotNull(scan.getFilter());
+
+ assertEquals(0, scan.getStartRow().length);
+ assertEquals(0, scan.getStopRow().length);
+ }
+
+ @Test
+ public void testMultiKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)), 15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testMultiKeyBindExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id=? and substr(entity_id,1,3)=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testEqualRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(startDate));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testDegenerateRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testBoundaryGreaterThanRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testBoundaryGreaterThanOrEqualRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testGreaterThanRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')>?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLessThanRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testBoundaryLessThanRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLessThanOrEqualRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 01:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testBoundaryLessThanOrEqualRound() throws Exception {
+ String inst = "a";
+ String host = "b";
+ Date startDate = DateUtil.parseDate("2012-01-01 00:00:00");
+ Date endDate = DateUtil.parseDate("2012-01-02 00:00:00");
+ String query = "select * from ptsdb where inst=? and host=? and round(date,'DAY')<=?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(inst,host,startDate);
+ compileStatement(query, scan, binds);
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(inst),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.VARCHAR.toBytes(host),QueryConstants.SEPARATOR_BYTE_ARRAY,
+ PDataType.DATE.toBytes(endDate));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testOverlappingKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String entityId = "002333333333333";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "' and entity_id='" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(startRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
+
+ @Test
+ public void testTrailingSubstrExpression() throws SQLException {
+ String tenantId = "0xD000000000001";
+ String entityId = "002333333333333";
+ String query = "select * from atable where substr(organization_id,1,3)='" + tenantId.substring(0, 3) + "' and entity_id='" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNotNull(scan.getFilter());
+
+ byte[] startRow = ByteUtil.concat(ByteUtil.fillKey(PDataType.VARCHAR.toBytes(tenantId.substring(0,3)),15),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(startRow, scan.getStartRow());
+ // Even though the first slot is a non inclusive range, we need to do a next key
+ // on the second slot because of the algorithm we use to seek to and terminate the
+ // loop during skip scan. We could end up having a first slot just under the upper
+ // limit of slot one and a value equal to the value in slot two and we need this to
+ // be less than the upper range that would get formed.
+ byte[] stopRow = ByteUtil.concat(ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId.substring(0,3))),15),ByteUtil.nextKey(PDataType.VARCHAR.toBytes(entityId)));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testBasicRangeExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id <= '" + tenantId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNull(scan.getFilter());
+
+ assertTrue(scan.getStartRow().length == 0);
+ byte[] stopRow = ByteUtil.concat(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression1() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String keyPrefix2= "004";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,3) < '" + keyPrefix2 + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNull(scan.getFilter());
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix2),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression2() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String keyPrefix2= "004";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,3) <= '" + keyPrefix2 + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNull(scan.getFilter());
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression3() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String keyPrefix2= "004";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and substr(entity_id,1,3) <= '" + keyPrefix2 + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix1)),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression4() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String entityId= "002000000000002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and substr(entity_id,1,3) = '" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testKeyRangeExpression5() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String entityId= "002000000000002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) <= '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression6() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String entityId= "002000000000002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) < '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testKeyRangeExpression7() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String entityId= "002000000000002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) < '" + keyPrefix1 + "' and entity_id < '" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertNull(scan.getFilter());
+
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(keyPrefix1),new byte[entityId.length() - keyPrefix1.length()]);
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression8() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "001";
+ String entityId= "002000000000002";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) > '" + keyPrefix1 + "' and entity_id = '" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),PDataType.VARCHAR.toBytes(entityId));
+ assertArrayEquals(ByteUtil.concat(stopRow, QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
+
+ @Test
+ public void testKeyRangeExpression9() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix1 = "002";
+ String keyPrefix2 = "0033";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3) >= '" + keyPrefix1 + "' and substr(entity_id,1,4) <= '" + keyPrefix2 + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix1),15)); // extra byte is due to implicit internal padding
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix2)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ /**
+ * This is testing the degenerate case where nothing will match because the overlapping keys (keyPrefix and entityId) don't match.
+ * @throws SQLException
+ */
+ @Test
+ public void testUnequalOverlappingKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String entityId = "001333333333333";
+ String query = "select * from atable where organization_id='" + tenantId + "' and substr(entity_id,1,3)='" + keyPrefix + "' and entity_id='" + entityId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testTopLevelOrKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' or a_integer=2";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(0, scan.getStartRow().length);
+ assertEquals(0, scan.getStopRow().length);
+ }
+
+ @Test
+ public void testSiblingOrKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and (a_integer = 2 or a_integer = 3)";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNotNull(scan.getFilter());
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testColumnNotFound() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where bar='" + tenantId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileStatement(query, scan, binds);
+ fail();
+ } catch (ColumnNotFoundException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testNotContiguousPkColumn() throws SQLException {
+ String keyPrefix = "002";
+ String query = "select * from atable where substr(entity_id,1,3)='" + keyPrefix + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(0, scan.getStartRow().length);
+ assertEquals(0, scan.getStopRow().length);
+ }
+
+ @Test
+ public void testMultipleNonEqualitiesPkColumn() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id >= '" + tenantId + "' AND substr(entity_id,1,3) > '" + keyPrefix + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds);
+
+ assertNotNull(scan.getFilter());
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testRHSLiteral() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' and 0 >= a_integer limit 1000";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ compileStatement(query, scan, binds, 1000);
+
+ assertNotNull(scan.getFilter());
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+
+ @Test
+ public void testKeyTypeMismatch() {
+ String query = "select * from atable where organization_id=5";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileStatement(query, scan, binds);
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Type mismatch"));
+ }
+ }
+
+ @Test
+ public void testLikeExtractAllKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeExtractAllAsEqKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id LIKE ? and entity_id LIKE '" + keyPrefix + "%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ compileStatement(query, scan, binds);
+
+ assertNull(scan.getFilter());
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testDegenerateLikeNoWildcard() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id LIKE ? and entity_id LIKE '" + keyPrefix + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ compileStatement(query, scan, binds);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testLikeExtractKeyExpression2() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ // TODO: verify that _ at end of like doesn't go to equals
+ String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "_'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ compileStatement(query, scan, binds);
+
+ assertNotNull(scan.getFilter());
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeOptKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and entity_id LIKE '" + keyPrefix + "%003%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(1, extractedNodes.size());
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeOptKeyExpression2() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and substr(entity_id,1,10) LIKE '" + keyPrefix + "%003%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(1, extractedNodes.size());
+
+
+ byte[] startRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15));
+ byte[] stopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId),ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15));
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(stopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeNoOptKeyExpression3() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and substr(entity_id,4,10) LIKE '" + keyPrefix + "%003%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(1, extractedNodes.size());
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeDegenerate() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id = ? and entity_id LIKE '0000000000000012%003%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateDivision1() throws SQLException {
+ String query = "select * from atable where a_integer = 3 / null";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateDivision2() throws SQLException {
+ String query = "select * from atable where a_integer / null = 3";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateMult1() throws SQLException {
+ String query = "select * from atable where a_integer = 3 * null";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateMult2() throws SQLException {
+ String query = "select * from atable where a_integer * null = 3";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateAdd1() throws SQLException {
+ String query = "select * from atable where a_integer = 3 + null";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateAdd2() throws SQLException {
+ String query = "select * from atable where a_integer + null = 3";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateSub1() throws SQLException {
+ String query = "select * from atable where a_integer = 3 - null";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testDegenerateSub2() throws SQLException {
+ String query = "select * from atable where a_integer - null = 3";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testLikeNoOptKeyExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and entity_id LIKE '%001%" + keyPrefix + "%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(1, extractedNodes.size());
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
+ }
+
+ @Test
+ public void testLikeNoOptKeyExpression2() throws SQLException {
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select * from atable where organization_id = ? and entity_id NOT LIKE '" + keyPrefix + "%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+
+ assertNotNull(scan.getFilter());
+ assertEquals(1, extractedNodes.size());
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId);
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(startRow), scan.getStopRow());
+ }
+ /*
+ * The following 5 tests are testing the comparison in where clauses under the case when the rhs
+ * cannot be coerced into the lhs. We need to confirm the decision make by expression compilation
+ * returns correct decisions.
+ */
+ @Test
+ public void testValueComparisonInt() throws SQLException {
+ ensureTableCreated(getUrl(),"PKIntValueTest");
+ String query;
+ // int <-> long
+ // Case 1: int = long, comparison always false, key is degenerated.
+ query = "SELECT * FROM PKintValueTest where pk = " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysFalse(query);
+ // Case 2: int != long, comparison always true, no key set since we need to do a full
+ // scan all the time.
+ query = "SELECT * FROM PKintValueTest where pk != " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysTrue(query);
+ // Case 3: int > positive long, comparison always false;
+ query = "SELECT * FROM PKintValueTest where pk >= " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysFalse(query);
+ // Case 4: int <= Integer.MAX_VALUE < positive long, always true;
+ query = "SELECT * FROM PKintValueTest where pk <= " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysTrue(query);
+ // Case 5: int >= Integer.MIN_VALUE > negative long, always true;
+ query = "SELECT * FROM PKintValueTest where pk >= " + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysTrue(query);
+ // Case 6: int < negative long, comparison always false;
+ query = "SELECT * FROM PKintValueTest where pk <= " + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysFalse(query);
+ }
+
+ @Test
+ public void testValueComparisonUnsignedInt() throws SQLException {
+ ensureTableCreated(getUrl(), "PKUnsignedIntValueTest");
+ String query;
+ // unsigned_int <-> negative int/long
+ // Case 1: unsigned_int = negative int, always false;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk = -1";
+ assertQueryConditionAlwaysFalse(query);
+ // Case 2: unsigned_int != negative int, always true;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk != -1";
+ assertQueryConditionAlwaysTrue(query);
+ // Case 3: unsigned_int > negative int, always true;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk > " + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysTrue(query);
+ // Case 4: unsigned_int < negative int, always false;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk < " + + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysFalse(query);
+ // unsigned_int <-> big positive long
+ // Case 1: unsigned_int = big positive long, always false;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk = " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysFalse(query);
+ // Case 2: unsigned_int != big positive long, always true;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk != " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysTrue(query);
+ // Case 3: unsigned_int > big positive long, always false;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk >= " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysFalse(query);
+ // Case 4: unsigned_int < big positive long, always true;
+ query = "SELECT * FROM PKUnsignedIntValueTest where pk <= " + Long.MAX_VALUE;
+ assertQueryConditionAlwaysTrue(query);
+ }
+
+ @Test
+ public void testValueComparisonUnsignedLong() throws SQLException {
+ ensureTableCreated(getUrl(), "PKUnsignedLongValueTest");
+ String query;
+ // unsigned_long <-> positive int/long
+ // Case 1: unsigned_long = negative int/long, always false;
+ query = "SELECT * FROM PKUnsignedLongValueTest where pk = -1";
+ assertQueryConditionAlwaysFalse(query);
+ // Case 2: unsigned_long = negative int/long, always true;
+ query = "SELECT * FROM PKUnsignedLongValueTest where pk != " + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysTrue(query);
+ // Case 3: unsigned_long > negative int/long, always true;
+ query = "SELECT * FROM PKUnsignedLongValueTest where pk > -1";
+ assertQueryConditionAlwaysTrue(query);
+ // Case 4: unsigned_long < negative int/long, always false;
+ query = "SELECT * FROM PKUnsignedLongValueTest where pk < " + (Long.MIN_VALUE + 1);
+ assertQueryConditionAlwaysFalse(query);
+ }
+
+ private void assertQueryConditionAlwaysTrue(String query) throws SQLException {
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression> extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+ assertEmptyScanKey(scan);
+ }
+
+ private void assertQueryConditionAlwaysFalse(String query) throws SQLException {
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList();
+ Set<Expression> extractedNodes = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedNodes);
+ assertDegenerate(scan);
+ }
+
+ @Test
+ public void testOrSameColExpression() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000003";
+ String query = "select * from atable where organization_id = ? or organization_id = ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId1,tenantId2);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ StatementContext context = compileStatement(query, scan, binds, extractedNodes);
+
+ Filter filter = scan.getFilter();
+ assertNotNull(filter);
+ assertTrue(filter instanceof SkipScanFilter);
+ ScanRanges scanRanges = context.getScanRanges();
+ assertNotNull(scanRanges);
+ List<List<KeyRange>> ranges = scanRanges.getRanges();
+ assertEquals(1,ranges.size());
+ List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList(
+ PDataType.CHAR.getKeyRange(PDataType.CHAR.toBytes(tenantId1), true, PDataType.CHAR.toBytes(tenantId1), true),
+ PDataType.CHAR.getKeyRange(PDataType.CHAR.toBytes(tenantId2), true, PDataType.CHAR.toBytes(tenantId2), true)));
+ assertEquals(expectedRanges, ranges);
+ assertEquals(1, extractedNodes.size());
+ assertTrue(extractedNodes.iterator().next() instanceof OrExpression);
+ byte[] startRow = PDataType.VARCHAR.toBytes(tenantId1);
+ assertArrayEquals(startRow, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId2)), scan.getStopRow());
+ }
+
+ @Test
+ public void testAndOrExpression() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String tenantId2 = "000000000000003";
+ String entityId1 = "002333333333331";
+ String entityId2 = "002333333333333";
+ String query = "select * from atable where (organization_id = ? and entity_id = ?) or (organization_id = ? and entity_id = ?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1,tenantId2,entityId2);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ StatementContext context = compileStatement(query, scan, binds, extractedNodes);
+
+ Filter filter = scan.getFilter();
+ assertNotNull(filter);
+ assertTrue(filter instanceof RowKeyComparisonFilter);
+ ScanRanges scanRanges = context.getScanRanges();
+ assertEquals(ScanRanges.EVERYTHING,scanRanges);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testOrDiffColExpression() throws SQLException {
+ String tenantId1 = "000000000000001";
+ String entityId1 = "002333333333331";
+ String query = "select * from atable where organization_id = ? or entity_id = ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1);
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ StatementContext context = compileStatement(query, scan, binds, extractedNodes);
+
+ Filter filter = scan.getFilter();
+ assertNotNull(filter);
+ assertTrue(filter instanceof RowKeyComparisonFilter);
+ ScanRanges scanRanges = context.getScanRanges();
+ assertEquals(ScanRanges.EVERYTHING,scanRanges);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testOrSameColRangeExpression() throws SQLException {
+ String query = "select * from atable where substr(organization_id,1,3) = ? or organization_id LIKE 'foo%'";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList("00D");
+ Set<Expression>extractedNodes = new HashSet<Expression>();
+ StatementContext context = compileStatement(query, scan, binds, extractedNodes);
+
+ Filter filter = scan.getFilter();
+ assertNotNull(filter);
+ assertTrue(filter instanceof SkipScanFilter);
+ ScanRanges scanRanges = context.getScanRanges();
+ assertNotNull(scanRanges);
+ List<List<KeyRange>> ranges = scanRanges.getRanges();
+ assertEquals(1,ranges.size());
+ List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList(
+ PDataType.CHAR.getKeyRange(
+ ByteUtil.fillKey(PDataType.CHAR.toBytes("00D"),15), true,
+ ByteUtil.fillKey(ByteUtil.nextKey(PDataType.CHAR.toBytes("00D")),15), false),
+ PDataType.CHAR.getKeyRange(
+ ByteUtil.fillKey(PDataType.CHAR.toBytes("foo"),15), true,
+ ByteUtil.fillKey(ByteUtil.nextKey(PDataType.CHAR.toBytes("foo")),15), false)));
+ assertEquals(expectedRanges, ranges);
+ assertEquals(1, extractedNodes.size());
+ assertTrue(extractedNodes.iterator().next() instanceof OrExpression);
+ }
+
+ @Test
+ public void testForceSkipScanOnSaltedTable() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE IF NOT EXISTS user_messages (\n" +
+ " SENDER_ID UNSIGNED_LONG NOT NULL,\n" +
+ " RECIPIENT_ID UNSIGNED_LONG NOT NULL,\n" +
+ " SENDER_IP VARCHAR,\n" +
+ " IS_READ VARCHAR,\n" +
+ " IS_DELETED VARCHAR,\n" +
+ " M_TEXT VARCHAR,\n" +
+ " M_TIMESTAMP timestamp NOT NULL,\n" +
+ " ROW_ID UNSIGNED_LONG NOT NULL\n" +
+ " constraint rowkey primary key (SENDER_ID,RECIPIENT_ID,M_TIMESTAMP DESC,ROW_ID))\n" +
+ "SALT_BUCKETS=12\n");
+ String query = "select /*+ SKIP_SCAN */ count(*) from user_messages where is_read='N' and recipient_id=5399179882";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ Set<Expression> extractedNodes = Sets.newHashSet();
+ StatementContext context = compileStatement(query, scan, binds, null, extractedNodes);
+ ScanRanges scanRanges = context.getScanRanges();
+ assertNotNull(scanRanges);
+ assertEquals(3,scanRanges.getRanges().size());
+ assertEquals(1,scanRanges.getRanges().get(1).size());
+ assertEquals(KeyRange.EVERYTHING_RANGE,scanRanges.getRanges().get(1).get(0));
+ assertEquals(1,scanRanges.getRanges().get(2).size());
+ assertTrue(scanRanges.getRanges().get(2).get(0).isSingleKey());
+ assertEquals(Long.valueOf(5399179882L), PDataType.UNSIGNED_LONG.toObject(scanRanges.getRanges().get(2).get(0).getLowerRange()));
+ assertEquals(1, extractedNodes.size());
+ assertNotNull(scan.getFilter());
+ }
+
+ @Test
+ public void testForceRangeScanKeepsFilters() throws SQLException {
+ ensureTableCreated(getUrl(), TestUtil.ENTITY_HISTORY_TABLE_NAME);
+ String tenantId = "000000000000001";
+ String keyPrefix = "002";
+ String query = "select /*+ RANGE_SCAN */ ORGANIZATION_ID, PARENT_ID, CREATED_DATE, ENTITY_HISTORY_ID from " + TestUtil.ENTITY_HISTORY_TABLE_NAME +
+ " where ORGANIZATION_ID=? and SUBSTR(PARENT_ID, 1, 3) = ? and CREATED_DATE >= ? and CREATED_DATE < ? order by ORGANIZATION_ID, PARENT_ID, CREATED_DATE, ENTITY_HISTORY_ID limit 6";
+ Scan scan = new Scan();
+ Date startTime = new Date(System.currentTimeMillis());
+ Date stopTime = new Date(startTime.getTime() + TestUtil.MILLIS_IN_DAY);
+ List<Object> binds = Arrays.<Object>asList(tenantId, keyPrefix, startTime, stopTime);
+ Set<Expression> extractedNodes = Sets.newHashSet();
+ compileStatement(query, scan, binds, 6, extractedNodes);
+ assertEquals(2, extractedNodes.size());
+ assertNotNull(scan.getFilter());
+
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.fillKey(PDataType.VARCHAR.toBytes(keyPrefix),15), PDataType.DATE.toBytes(startTime));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ byte[] expectedStopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.fillKey(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(keyPrefix)),15), PDataType.DATE.toBytes(stopTime));
+ assertArrayEquals(expectedStopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testBasicRVCExpression() throws SQLException {
+ String tenantId = "000000000000001";
+ String entityId = "002333333333331";
+ String query = "select * from atable where (organization_id,entity_id) >= (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, entityId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.CHAR.toBytes(tenantId), PDataType.CHAR.toBytes(entityId));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+
+ @Test
+ public void testRVCExpressionThroughOr() throws SQLException {
+ String tenantId = "000000000000001";
+ String entityId = "002333333333331";
+ String entityId1 = "002333333333330";
+ String entityId2 = "002333333333332";
+ String query = "select * from atable where (organization_id,entity_id) >= (?,?) and organization_id = ? and (entity_id = ? or entity_id = ?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, entityId, tenantId, entityId1, entityId2);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 3);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(entityId));
+ byte[] expectedStopRow = ByteUtil.concat(ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(entityId2)), QueryConstants.SEPARATOR_BYTE_ARRAY);
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(expectedStopRow, scan.getStopRow());
+ }
+
+ /**
+ * With only a subset of row key cols present (which includes the leading key),
+ * Phoenix should have optimized the start row for the scan to include the
+ * row keys cols that occur contiguously in the RVC.
+ *
+ * Table entity_history has the row key defined as (organization_id, parent_id, created_date, entity_history_id).
+ * This test uses (organization_id, parent_id, entity_id) in RVC. So the start row should be comprised of
+ * organization_id and parent_id.
+ * @throws SQLException
+ */
+ @Test
+ public void testRVCExpressionWithSubsetOfPKCols() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000002";
+ String entityHistId = "000000000000003";
+
+ String query = "select * from entity_history where (organization_id, parent_id, entity_history_id) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId, entityHistId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(parentId));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ /**
+ * With the leading row key col missing Phoenix won't be able to optimize
+ * and provide the start row for the scan.
+ *
+ * Table entity_history has the row key defined as (organization_id, parent_id, created_date, entity_history_id).
+ * This test uses (parent_id, entity_id) in RVC. Start row should be empty.
+ * @throws SQLException
+ */
+
+ @Test
+ public void testRVCExpressionWithoutLeadingColOfRowKey() throws SQLException {
+
+ String parentId = "000000000000002";
+ String entityHistId = "000000000000003";
+
+ String query = "select * from entity_history where (parent_id, entity_history_id) >= (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(parentId, entityHistId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testMultiRVCExpressionsCombinedWithAnd() throws SQLException {
+ String lowerTenantId = "000000000000001";
+ String lowerParentId = "000000000000002";
+ Date lowerCreatedDate = new Date(System.currentTimeMillis());
+ String upperTenantId = "000000000000008";
+ String upperParentId = "000000000000009";
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?, ?, ?) AND (organization_id, parent_id) <= (?, ?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(lowerTenantId, lowerParentId, lowerCreatedDate, upperTenantId, upperParentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 2);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(lowerTenantId), PDataType.VARCHAR.toBytes(lowerParentId), PDataType.DATE.toBytes(lowerCreatedDate));
+ byte[] expectedStopRow = ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(upperTenantId), PDataType.VARCHAR.toBytes(upperParentId)));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(expectedStopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testMultiRVCExpressionsCombinedUsingLiteralExpressions() throws SQLException {
+ String lowerTenantId = "000000000000001";
+ String lowerParentId = "000000000000002";
+ Date lowerCreatedDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?, ?, ?) AND (organization_id, parent_id) <= ('7', '7')";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(lowerTenantId, lowerParentId, lowerCreatedDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 2);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(lowerTenantId), PDataType.VARCHAR.toBytes(lowerParentId), PDataType.DATE.toBytes(lowerCreatedDate));
+ byte[] expectedStopRow = ByteUtil.nextKey(ByteUtil.concat(ByteUtil.fillKey(PDataType.VARCHAR.toBytes("7"),15), ByteUtil.fillKey(PDataType.VARCHAR.toBytes("7"), 15)));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(expectedStopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testUseOfFunctionOnLHSInRVC() throws SQLException {
+ String tenantId = "000000000000001";
+ String subStringTenantId = tenantId.substring(0, 3);
+ String parentId = "000000000000002";
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (substr(organization_id, 1, 3), parent_id, created_date) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(subStringTenantId, parentId, createdDate);
+ Set<Expression> extractedFilters = new HashSet<Expression>(2);
+ compileStatement(query, scan, binds, extractedFilters);
+ byte[] expectedStartRow = PDataType.VARCHAR.toBytes(subStringTenantId);
+ assertTrue(extractedFilters.size() == 0);
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testUseOfFunctionOnLHSInMiddleOfRVC() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000002";
+ String subStringParentId = parentId.substring(0, 3);
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, substr(parent_id, 1, 3), created_date) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, subStringParentId, createdDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(subStringParentId));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testUseOfFunctionOnLHSInMiddleOfRVCForLTE() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000002";
+ String subStringParentId = parentId.substring(0, 3);
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, substr(parent_id, 1, 3), created_date) <= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, subStringParentId, createdDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ byte[] expectedStopRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), ByteUtil.nextKey(PDataType.VARCHAR.toBytes(subStringParentId)));
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStartRow());
+ assertArrayEquals(expectedStopRow, scan.getStopRow());
+ }
+
+ @Test
+ public void testNullAtEndOfRVC() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000002";
+ Date createdDate = null;
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.VARCHAR.toBytes(tenantId), PDataType.VARCHAR.toBytes(parentId));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testNullInMiddleOfRVC() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = null;
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ byte[] expectedStartRow = ByteUtil.concat(PDataType.CHAR.toBytes(tenantId), new byte[15], ByteUtil.previousKey(PDataType.DATE.toBytes(createdDate)));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testNullAtStartOfRVC() throws SQLException {
+ String tenantId = null;
+ String parentId = "000000000000002";
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId, createdDate);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ byte[] expectedStartRow = ByteUtil.concat(new byte[15], ByteUtil.previousKey(PDataType.CHAR.toBytes(parentId)), PDataType.DATE.toBytes(createdDate));
+ assertArrayEquals(expectedStartRow, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testRVCInCombinationWithOtherNonRVC() throws SQLException {
+ String firstOrgId = "000000000000001";
+ String secondOrgId = "000000000000008";
+
+ String parentId = "000000000000002";
+ Date createdDate = new Date(System.currentTimeMillis());
+
+ String query = "select * from entity_history where (organization_id, parent_id, created_date) >= (?,?,?) AND organization_id <= ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstOrgId, parentId, createdDate, secondOrgId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 2);
+ assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstOrgId), PDataType.VARCHAR.toBytes(parentId), PDataType.DATE.toBytes(createdDate)), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(secondOrgId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testGreaterThanEqualTo_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000008";
+
+ String query = "select * from entity_history where organization_id >= (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testGreaterThan_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000008";
+
+ String query = "select * from entity_history where organization_id > (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testGreaterThan() throws SQLException {
+ String tenantId = "000000000000001";
+
+ String query = "select * from entity_history where organization_id >?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testLessThanEqualTo_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000008";
+
+ String query = "select * from entity_history where organization_id <= (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testLessThan_NonRVCOnLHSAndRVCOnRHS_WithNonNullBindParams() throws SQLException {
+ String tenantId = "000000000000001";
+ String parentId = "000000000000008";
+
+ String query = "select * from entity_history where organization_id < (?,?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(tenantId, parentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testCombiningRVCUsingOr() throws SQLException {
+ String firstTenantId = "000000000000001";
+ String secondTenantId = "000000000000005";
+ String firstParentId = "000000000000011";
+ String secondParentId = "000000000000015";
+
+ String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR (organization_id, parent_id) <= (?, ?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId, secondParentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1); // extracts the entire OR
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testCombiningRVCUsingOr2() throws SQLException {
+ String firstTenantId = "000000000000001";
+ String secondTenantId = "000000000000005";
+ String firstParentId = "000000000000011";
+ String secondParentId = "000000000000015";
+
+ String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR (organization_id, parent_id) >= (?, ?)";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId, secondParentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstTenantId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testCombiningRVCWithNonRVCUsingOr() throws SQLException {
+ String firstTenantId = "000000000000001";
+ String secondTenantId = "000000000000005";
+ String firstParentId = "000000000000011";
+
+ String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id >= ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstTenantId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testCombiningRVCWithNonRVCUsingOr2() throws SQLException {
+ String firstTenantId = "000000000000001";
+ String secondTenantId = "000000000000005";
+ String firstParentId = "000000000000011";
+
+ String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id <= ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testCombiningRVCWithNonRVCUsingOr3() throws SQLException {
+ String firstTenantId = "000000000000005";
+ String secondTenantId = "000000000000001";
+ String firstParentId = "000000000000011";
+ String query = "select * from entity_history where (organization_id, parent_id) >= (?,?) OR organization_id <= ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstTenantId, firstParentId, secondTenantId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow());
+ assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow());
+ }
+
+ @Test
+ public void testUsingRVCNonFullyQualifiedInClause() throws Exception {
+ String firstOrgId = "000000000000001";
+ String secondOrgId = "000000000000009";
+ String firstParentId = "000000000000011";
+ String secondParentId = "000000000000021";
+ String query = "select * from entity_history where (organization_id, parent_id) IN ((?, ?), (?, ?))";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 0);
+ assertArrayEquals(ByteUtil.concat(PDataType.VARCHAR.toBytes(firstOrgId), PDataType.VARCHAR.toBytes(firstParentId)), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(ByteUtil.concat(PDataType.VARCHAR.toBytes(secondOrgId), PDataType.VARCHAR.toBytes(secondParentId))), scan.getStopRow());
+ }
+
+ @Test
+ public void testUsingRVCFullyQualifiedInClause() throws Exception {
+ String firstOrgId = "000000000000001";
+ String secondOrgId = "000000000000009";
+ String firstParentId = "000000000000011";
+ String secondParentId = "000000000000021";
+ String query = "select * from atable where (organization_id, entity_id) IN ((?, ?), (?, ?))";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId);
+ HashSet<Expression> extractedFilters = new HashSet<Expression>();
+ StatementContext context = compileStatement(query, scan, binds, extractedFilters);
+ assertTrue(extractedFilters.size() == 1);
+ List<List<KeyRange>> skipScanRanges = Collections.singletonList(Arrays.asList(
+ KeyRange.getKeyRange(ByteUtil.concat(PDataType.CHAR.toBytes(firstOrgId), PDataType.CHAR.toBytes(firstParentId))),
+ KeyRange.getKeyRange(ByteUtil.concat(PDataType.CHAR.toBytes(secondOrgId), PDataType.CHAR.toBytes(secondParentId)))));
+ assertEquals(skipScanRanges, context.getScanRanges().getRanges());
+ assertArrayEquals(ByteUtil.concat(PDataType.CHAR.toBytes(firstOrgId), PDataType.CHAR.toBytes(firstParentId)), scan.getStartRow());
+ assertArrayEquals(ByteUtil.concat(PDataType.CHAR.toBytes(secondOrgId), PDataType.CHAR.toBytes(secondParentId), QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/query/BaseConnectionlessQueryTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseConnectionlessQueryTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseConnectionlessQueryTest.java
index 41c4716..f5f7928 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseConnectionlessQueryTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseConnectionlessQueryTest.java
@@ -35,29 +35,30 @@ import static org.apache.phoenix.util.TestUtil.TABLE_WITH_ARRAY;
import java.sql.DriverManager;
import java.util.Properties;
-import org.junit.BeforeClass;
-
import org.apache.phoenix.coprocessor.MetaDataProtocol;
+import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.ColumnRef;
import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.TableRef;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.TestUtil;
+import org.junit.BeforeClass;
public class BaseConnectionlessQueryTest extends BaseTest {
public static PTable ATABLE;
- public static PColumn ORGANIZATION_ID;
- public static PColumn ENTITY_ID;
- public static PColumn A_INTEGER;
- public static PColumn A_STRING;
- public static PColumn B_STRING;
- public static PColumn A_DATE;
- public static PColumn A_TIME;
- public static PColumn A_TIMESTAMP;
- public static PColumn X_DECIMAL;
+ public static Expression ORGANIZATION_ID;
+ public static Expression ENTITY_ID;
+ public static Expression A_INTEGER;
+ public static Expression A_STRING;
+ public static Expression B_STRING;
+ public static Expression A_DATE;
+ public static Expression A_TIME;
+ public static Expression A_TIMESTAMP;
+ public static Expression X_DECIMAL;
protected static String getUrl() {
return TestUtil.PHOENIX_CONNECTIONLESS_JDBC_URL;
@@ -86,16 +87,15 @@ public class BaseConnectionlessQueryTest extends BaseTest {
try {
PTable table = conn.getPMetaData().getTable(ATABLE_NAME);
ATABLE = table;
- ORGANIZATION_ID = table.getColumn("ORGANIZATION_ID");
- ENTITY_ID = table.getColumn("ENTITY_ID");
- A_INTEGER = table.getColumn("A_INTEGER");
- A_STRING = table.getColumn("A_STRING");
- B_STRING = table.getColumn("B_STRING");
- ENTITY_ID = table.getColumn("ENTITY_ID");
- A_DATE = table.getColumn("A_DATE");
- A_TIME = table.getColumn("A_TIME");
- A_TIMESTAMP = table.getColumn("A_TIMESTAMP");
- X_DECIMAL = table.getColumn("X_DECIMAL");
+ ORGANIZATION_ID = new ColumnRef(new TableRef(table), table.getColumn("ORGANIZATION_ID").getPosition()).newColumnExpression();
+ ENTITY_ID = new ColumnRef(new TableRef(table), table.getColumn("ENTITY_ID").getPosition()).newColumnExpression();
+ A_INTEGER = new ColumnRef(new TableRef(table), table.getColumn("A_INTEGER").getPosition()).newColumnExpression();
+ A_STRING = new ColumnRef(new TableRef(table), table.getColumn("A_STRING").getPosition()).newColumnExpression();
+ B_STRING = new ColumnRef(new TableRef(table), table.getColumn("B_STRING").getPosition()).newColumnExpression();
+ A_DATE = new ColumnRef(new TableRef(table), table.getColumn("A_DATE").getPosition()).newColumnExpression();
+ A_TIME = new ColumnRef(new TableRef(table), table.getColumn("A_TIME").getPosition()).newColumnExpression();
+ A_TIMESTAMP = new ColumnRef(new TableRef(table), table.getColumn("A_TIMESTAMP").getPosition()).newColumnExpression();
+ X_DECIMAL = new ColumnRef(new TableRef(table), table.getColumn("X_DECIMAL").getPosition()).newColumnExpression();
} finally {
conn.close();
}
[7/8] Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompileTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompileTest.java
deleted file mode 100644
index e9c34e0..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompileTest.java
+++ /dev/null
@@ -1,1313 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.apache.phoenix.util.TestUtil.assertDegenerate;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.coprocessor.GroupedAggregateRegionObserver;
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.expression.aggregator.Aggregator;
-import org.apache.phoenix.expression.aggregator.CountAggregator;
-import org.apache.phoenix.expression.aggregator.ServerAggregators;
-import org.apache.phoenix.expression.function.TimeUnit;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.AmbiguousColumnException;
-import org.apache.phoenix.schema.ColumnAlreadyExistsException;
-import org.apache.phoenix.schema.ColumnNotFoundException;
-import org.apache.phoenix.schema.PColumn;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.PhoenixRuntime;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TestUtil;
-import org.junit.Test;
-
-
-
-/**
- *
- * Tests for compiling a query
- * The compilation stage finds additional errors that can't be found at parse
- * time so this is a good place for negative tests (since the mini-cluster
- * is not necessary enabling the tests to run faster).
- *
- *
- * @since 0.1
- */
-@edu.umd.cs.findbugs.annotations.SuppressWarnings(
- value="RV_RETURN_VALUE_IGNORED",
- justification="Test code.")
-public class QueryCompileTest extends BaseConnectionlessQueryTest {
-
- @Test
- public void testParameterUnbound() throws Exception {
- try {
- String query = "SELECT a_string, b_string FROM atable WHERE organization_id=? and a_integer = ?";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Parameter 2 is unbound"));
- }
- }
-
- @Test
- public void testMultiPKDef() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (pk1 integer not null primary key, pk2 bigint not null primary key)";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 510 (42889): The table already has a primary key. columnName=PK2"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testPKDefAndPKConstraint() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (pk integer not null primary key, col1 decimal, col2 decimal constraint my_pk primary key (col1,col2))";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 510 (42889): The table already has a primary key. columnName=PK"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testFamilyNameInPK() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (a.pk integer not null primary key, col1 decimal, col2 decimal)";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertEquals(e.getErrorCode(), SQLExceptionCode.PRIMARY_KEY_WITH_FAMILY_NAME.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSameColumnNameInPKAndNonPK() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE t1 (k integer not null primary key, a.k decimal, b.k decimal)";
- conn.createStatement().execute(query);
- PColumn c = conn.unwrap(PhoenixConnection.class).getPMetaData().getTable("T1").getColumn("K");
- assertTrue(SchemaUtil.isPKColumn(c));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testVarBinaryInMultipartPK() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- // When the VARBINARY key is the last column, it is allowed.
- String query = "CREATE TABLE foo (a_string varchar not null, b_string varchar not null, a_binary varbinary not null, " +
- "col1 decimal, col2 decimal CONSTRAINT pk PRIMARY KEY (a_string, b_string, a_binary))";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- try {
- // VARBINARY key is not allowed in the middle of the key.
- query = "CREATE TABLE foo (a_binary varbinary not null, a_string varchar not null, col1 decimal, col2 decimal CONSTRAINT pk PRIMARY KEY (a_binary, a_string))";
- statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1005 (42J03): The VARBINARY type can only be used as the last part of a multi-part row key. columnName=FOO.A_BINARY"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testNoPK() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (pk integer not null, col1 decimal, col2 decimal)";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 509 (42888): The table does not have a primary key. tableName=FOO"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testUnknownFamilyNameInTableOption() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (pk integer not null primary key, a.col1 decimal, b.col2 decimal) c.my_property='foo'";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Properties may not be defined for an unused family name"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInvalidGroupedAggregation() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT count(1),a_integer FROM atable WHERE organization_id=? GROUP BY a_string";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
- }
- }
-
- @Test
- public void testInvalidGroupExpressionAggregation() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT sum(a_integer) + a_integer FROM atable WHERE organization_id=? GROUP BY a_string";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
- }
- }
-
- @Test
- public void testAggInWhereClause() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT a_integer FROM atable WHERE organization_id=? AND count(1) > 2";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1017 (42Y26): Aggregate may not be used in WHERE."));
- }
- }
-
- @Test
- public void testHavingAggregateQuery() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING count(1) > 2";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER"));
- }
- }
-
- @Test
- public void testNonAggInHavingClause() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING a_integer = 5";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1019 (42Y26): Only aggregate maybe used in the HAVING clause."));
- }
- }
-
- @Test
- public void testTypeMismatchInCase() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT a_integer FROM atable WHERE organization_id=? HAVING CASE WHEN a_integer <= 2 THEN 'foo' WHEN a_integer = 3 THEN 2 WHEN a_integer <= 5 THEN 5 ELSE 5 END = 5";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Case expressions must have common type"));
- }
- }
-
- @Test
- public void testNonBooleanWhereExpression() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "SELECT a_integer FROM atable WHERE organization_id=? and CASE WHEN a_integer <= 2 THEN 'foo' WHEN a_integer = 3 THEN 'bar' WHEN a_integer <= 5 THEN 'bas' ELSE 'blah' END";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("ERROR 203 (22005): Type mismatch. BOOLEAN and VARCHAR for CASE WHEN A_INTEGER <= 2 THEN 'foo'WHEN A_INTEGER = 3 THEN 'bar'WHEN A_INTEGER <= 5 THEN 'bas' ELSE 'blah' END"));
- }
- }
-
- @Test
- public void testNoSCNInConnectionProps() throws Exception {
- Properties props = new Properties();
- DriverManager.getConnection(getUrl(), props);
- }
-
-
- @Test
- public void testPercentileWrongQueryWithMixOfAggrAndNonAggrExps() throws Exception {
- String query = "select a_integer, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
- try {
- compileQuery(query, Collections.emptyList());
- fail();
- } catch (SQLException e) {
- assertEquals("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_INTEGER",
- e.getMessage());
- }
- }
-
- @Test
- public void testPercentileWrongQuery1() throws Exception {
- String query = "select PERCENTILE_CONT('*') WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
- try {
- compileQuery(query, Collections.emptyList());
- fail();
- } catch (SQLException e) {
- assertEquals(
- "ERROR 203 (22005): Type mismatch. expected: [DECIMAL] but was: VARCHAR at PERCENTILE_CONT argument 3",
- e.getMessage());
- }
- }
-
- @Test
- public void testPercentileWrongQuery2() throws Exception {
- String query = "select PERCENTILE_CONT(1.1) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
- try {
- compileQuery(query, Collections.emptyList());
- fail();
- } catch (SQLException e) {
- assertEquals(
- "ERROR 213 (22003): Value outside range. expected: [0 , 1] but was: 1.1 at PERCENTILE_CONT argument 3",
- e.getMessage());
- }
- }
-
- @Test
- public void testPercentileWrongQuery3() throws Exception {
- String query = "select PERCENTILE_CONT(-1) WITHIN GROUP (ORDER BY a_integer ASC) from ATABLE";
- try {
- compileQuery(query, Collections.emptyList());
- fail();
- } catch (Exception e) {
- assertEquals(
- "ERROR 213 (22003): Value outside range. expected: [0 , 1] but was: -1 at PERCENTILE_CONT argument 3",
- e.getMessage());
- }
- }
-
- private Scan compileQuery(String query, List<Object> binds) throws SQLException {
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PhoenixPreparedStatement statement = conn.prepareStatement(query).unwrap(PhoenixPreparedStatement.class);
- for (Object bind : binds) {
- statement.setObject(1, bind);
- }
- QueryPlan plan = statement.compileQuery(query);
- return plan.getContext().getScan();
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testKeyOrderedGroupByOptimization() throws Exception {
- // Select columns in PK
- String[] queries = new String[] {
- "SELECT count(1) FROM atable GROUP BY organization_id,entity_id",
- "SELECT count(1) FROM atable GROUP BY organization_id,substr(entity_id,1,3),entity_id",
- "SELECT count(1) FROM atable GROUP BY entity_id,organization_id",
- "SELECT count(1) FROM atable GROUP BY substr(entity_id,1,3),organization_id",
- "SELECT count(1) FROM ptsdb GROUP BY host,inst,round(date,'HOUR')",
- "SELECT count(1) FROM atable GROUP BY organization_id",
- };
- List<Object> binds = Collections.emptyList();
- for (String query : queries) {
- Scan scan = compileQuery(query, binds);
- assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS) != null);
- assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS) == null);
- }
- }
-
- @Test
- public void testNullInScanKey() throws Exception {
- // Select columns in PK
- String query = "select val from ptsdb where inst is null and host='a'";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- // Projects column family with not null column
- assertNull(scan.getFilter());
- assertEquals(1,scan.getFamilyMap().keySet().size());
- assertArrayEquals(Bytes.toBytes(SchemaUtil.normalizeIdentifier(QueryConstants.DEFAULT_COLUMN_FAMILY)), scan.getFamilyMap().keySet().iterator().next());
- }
-
- @Test
- public void testOnlyNullInScanKey() throws Exception {
- // Select columns in PK
- String query = "select val from ptsdb where inst is null";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- // Projects column family with not null column
- assertEquals(1,scan.getFamilyMap().keySet().size());
- assertArrayEquals(Bytes.toBytes(SchemaUtil.normalizeIdentifier(QueryConstants.DEFAULT_COLUMN_FAMILY)), scan.getFamilyMap().keySet().iterator().next());
- }
-
- @Test
- public void testIsNullOnNotNullable() throws Exception {
- // Select columns in PK
- String query = "select a_string from atable where entity_id is null";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- assertDegenerate(scan);
- }
-
- @Test
- public void testIsNotNullOnNotNullable() throws Exception {
- // Select columns in PK
- String query = "select a_string from atable where entity_id is not null";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- assertNull(scan.getFilter());
- assertTrue(scan.getStartRow().length == 0);
- assertTrue(scan.getStopRow().length == 0);
- }
-
- @Test
- public void testUpsertTypeMismatch() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "upsert into ATABLE VALUES (?, ?, ?)";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.setString(2, "00D300000000XHP");
- statement.setInt(3, 1);
- statement.executeUpdate();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) { // TODO: use error codes
- assertTrue(e.getMessage().contains("Type mismatch"));
- }
- }
-
- @Test
- public void testUpsertMultiByteIntoChar() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "upsert into ATABLE VALUES (?, ?, ?)";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, "00D300000000XHP");
- statement.setString(2, "繰り返し曜日マスク");
- statement.setInt(3, 1);
- statement.executeUpdate();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 201 (22000): Illegal data."));
- assertTrue(e.getCause().getMessage().contains("CHAR types may only contain single byte characters"));
- }
- }
-
- @Test
- public void testSelectStarOnGroupBy() throws Exception {
- try {
- // Select non agg column in aggregate query
- String query = "select * from ATABLE group by a_string";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY."));
- }
- }
-
- @Test
- public void testOrderByAggSelectNonAgg() throws Exception {
- try {
- // Order by in select with no limit or group by
- String query = "select a_string from ATABLE order by max(b_string)";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_STRING"));
- }
- }
-
- @Test
- public void testOrderByAggAndNonAgg() throws Exception {
- try {
- // Order by in select with no limit or group by
- String query = "select max(a_string) from ATABLE order by max(b_string),a_string";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. A_STRING"));
- }
- }
-
- @Test
- public void testOrderByNonAggSelectAgg() throws Exception {
- try {
- // Order by in select with no limit or group by
- String query = "select max(a_string) from ATABLE order by b_string LIMIT 5";
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } finally {
- conn.close();
- }
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1018 (42Y27): Aggregate may not contain columns not in GROUP BY. B_STRING"));
- }
- }
-
- @Test
- public void testNotKeyOrderedGroupByOptimization() throws Exception {
- // Select columns in PK
- String[] queries = new String[] {
- "SELECT count(1) FROM atable GROUP BY entity_id",
- "SELECT count(1) FROM atable GROUP BY substr(organization_id,2,3)",
- "SELECT count(1) FROM atable GROUP BY substr(entity_id,1,3)",
- "SELECT count(1) FROM atable GROUP BY to_date(organization_id)",
- "SELECT count(1) FROM atable GROUP BY regexp_substr(organization_id, '.*foo.*'),entity_id",
- "SELECT count(1) FROM atable GROUP BY substr(organization_id,1),entity_id",
- };
- List<Object> binds = Collections.emptyList();
- for (String query : queries) {
- Scan scan = compileQuery(query, binds);
- assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS) == null);
- assertTrue(query, scan.getAttribute(GroupedAggregateRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS) != null);
- }
- }
-
- @Test
- public void testFunkyColumnNames() throws Exception {
- // Select columns in PK
- String[] queries = new String[] {
- "SELECT \"foo!\",\"foo.bar-bas\",\"#@$\",\"_blah^\" FROM FUNKY_NAMES",
- "SELECT count(\"foo!\"),\"_blah^\" FROM FUNKY_NAMES WHERE \"foo.bar-bas\"='x' GROUP BY \"#@$\",\"_blah^\"",
- };
- List<Object> binds = Collections.emptyList();
- for (String query : queries) {
- compileQuery(query, binds);
- }
- }
-
- @Test
- public void testCountAggregatorFirst() throws Exception {
- String[] queries = new String[] {
- "SELECT sum(2.5),organization_id FROM atable GROUP BY organization_id,entity_id",
- "SELECT avg(a_integer) FROM atable GROUP BY organization_id,substr(entity_id,1,3),entity_id",
- "SELECT count(a_string) FROM atable GROUP BY substr(organization_id,1),entity_id",
- "SELECT min('foo') FROM atable GROUP BY entity_id,organization_id",
- "SELECT min('foo'),sum(a_integer),avg(2.5),4.5,max(b_string) FROM atable GROUP BY substr(organization_id,1),entity_id",
- "SELECT sum(2.5) FROM atable",
- "SELECT avg(a_integer) FROM atable",
- "SELECT count(a_string) FROM atable",
- "SELECT min('foo') FROM atable LIMIT 5",
- "SELECT min('foo'),sum(a_integer),avg(2.5),4.5,max(b_string) FROM atable",
- };
- List<Object> binds = Collections.emptyList();
- String query = null;
- try {
- for (int i = 0; i < queries.length; i++) {
- query = queries[i];
- Scan scan = compileQuery(query, binds);
- ServerAggregators aggregators = ServerAggregators.deserialize(scan.getAttribute(GroupedAggregateRegionObserver.AGGREGATORS), null);
- Aggregator aggregator = aggregators.getAggregators()[0];
- assertTrue(aggregator instanceof CountAggregator);
- }
- } catch (Exception e) {
- throw new Exception(query, e);
- }
- }
-
- @Test
- public void testInvalidArithmetic() throws Exception {
- String[] queries = new String[] {
- "SELECT entity_id,organization_id FROM atable where A_STRING - 5.5 < 0",
- "SELECT entity_id,organization_id FROM atable where A_DATE - 'transaction' < 0",
- "SELECT entity_id,organization_id FROM atable where A_DATE * 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_DATE / 45 < 0",
- "SELECT entity_id,organization_id FROM atable where 45 - A_DATE < 0",
- "SELECT entity_id,organization_id FROM atable where A_DATE - to_date('2000-01-01 12:00:00') < to_date('2000-02-01 12:00:00')", // RHS must be number
- "SELECT entity_id,organization_id FROM atable where A_DATE - A_DATE + 1 < A_DATE", // RHS must be number
- "SELECT entity_id,organization_id FROM atable where A_DATE + 2 < 0", // RHS must be date
- "SELECT entity_id,organization_id FROM atable where 45.5 - A_DATE < 0",
- "SELECT entity_id,organization_id FROM atable where 1 + A_DATE + A_DATE < A_DATE",
- "SELECT entity_id,organization_id FROM atable where A_STRING - 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_STRING / 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_STRING * 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_STRING + 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_STRING - 45 < 0",
- "SELECT entity_id,organization_id FROM atable where A_STRING - 'transaction' < 0", };
-
- Properties props = new Properties(TestUtil.TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- for (String query : queries) {
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail(query);
- } catch (SQLException e) {
- if (e.getMessage().contains("ERROR 203 (22005): Type mismatch.")) {
- continue;
- }
- throw new IllegalStateException("Didn't find type mismatch: " + query, e);
- }
- }
- }
-
-
- @Test
- public void testAmbiguousColumn() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT * from multi_cf G where RESPONSE_TIME = 2222";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (AmbiguousColumnException e) { // expected
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testTableAliasMatchesCFName() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT F.RESPONSE_TIME,G.RESPONSE_TIME from multi_cf G where G.RESPONSE_TIME-1 = F.RESPONSE_TIME";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (AmbiguousColumnException e) { // expected
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testCoelesceFunctionTypeMismatch() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT coalesce(x_integer,'foo') from atable";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 507 (42846): Cannot convert type. COALESCE expected INTEGER, but got VARCHAR"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testOrderByNotInSelectDistinct() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT distinct a_string,b_string from atable order by x_integer";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertEquals(SQLExceptionCode.ORDER_BY_NOT_IN_SELECT_DISTINCT.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectDistinctAndAll() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT all distinct a_string,b_string from atable order by x_integer";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertEquals(SQLExceptionCode.PARSER_ERROR.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testOrderByNotInSelectDistinctAgg() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT distinct count(1) from atable order by x_integer";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertEquals(SQLExceptionCode.ORDER_BY_NOT_IN_SELECT_DISTINCT.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectDistinctWithAggregation() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT distinct a_string,count(*) from atable";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertEquals(SQLExceptionCode.AGGREGATE_WITH_NOT_GROUP_BY_COLUMN.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testRegexpSubstrSetScanKeys() throws Exception {
- // First test scan keys are set when the offset is 0 or 1.
- String query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+') = 'abc'";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- assertTrue(scan.getFilter() != null);
-
- query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+', 0) = 'abc'";
- binds = Collections.emptyList();
- scan = compileQuery(query, binds);
- assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- assertTrue(scan.getFilter() != null);
-
- // Test scan keys are not set when the offset is not 0 or 1.
- query = "SELECT host FROM ptsdb WHERE regexp_substr(inst, '[a-zA-Z]+', 3) = 'abc'";
- binds = Collections.emptyList();
- scan = compileQuery(query, binds);
- assertTrue(scan.getStartRow().length == 0);
- assertTrue(scan.getStopRow().length == 0);
- assertTrue(scan.getFilter() != null);
- }
-
- @Test
- public void testStringConcatExpression() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT entity_id,a_string FROM atable where 2 || a_integer || ? like '2%'";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Properties props = new Properties(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(url, props);
- byte []x=new byte[]{127,127,0,0};//Binary data
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setBytes(1, x);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getMessage().contains("Concatenation does not support"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testDivideByBigDecimalZero() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT a_integer/x_integer/0.0 FROM atable";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Connection conn = DriverManager.getConnection(url);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getMessage().contains("Divide by zero"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testDivideByIntegerZero() throws Exception {
- long ts = nextTimestamp();
- String query = "SELECT a_integer/0 FROM atable";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Connection conn = DriverManager.getConnection(url);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getMessage().contains("Divide by zero"));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testCreateNullableInPKMiddle() throws Exception {
- long ts = nextTimestamp();
- String query = "CREATE TABLE foo(i integer not null, j integer null, k integer not null CONSTRAINT pk PRIMARY KEY(i,j,k))";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Connection conn = DriverManager.getConnection(url);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getMessage().contains("PK columns may not be both fixed width and nullable"));
- }
- }
-
- @Test
- public void testSetSaltBucketOnAlterTable() throws Exception {
- long ts = nextTimestamp();
- String query = "ALTER TABLE atable ADD xyz INTEGER SALT_BUCKETS=4";
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5); // Run query at timestamp 5
- Connection conn = DriverManager.getConnection(url);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) { // expected
- assertTrue(e.getErrorCode() == SQLExceptionCode.SALT_ONLY_ON_CREATE_TABLE.getErrorCode());
- }
- }
-
- @Test
- public void testSubstrSetScanKey() throws Exception {
- String query = "SELECT inst FROM ptsdb WHERE substr(inst, 0, 3) = 'abc'";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abd"),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- assertTrue(scan.getFilter() == null); // Extracted.
- }
-
- @Test
- public void testRTrimSetScanKey() throws Exception {
- String query = "SELECT inst FROM ptsdb WHERE rtrim(inst) = 'abc'";
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery(query, binds);
- assertArrayEquals(ByteUtil.concat(Bytes.toBytes("abc")), scan.getStartRow());
- assertArrayEquals(ByteUtil.concat(ByteUtil.nextKey(Bytes.toBytes("abc ")),QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow());
- assertNotNull(scan.getFilter());
- }
-
- @Test
- public void testCastingIntegerToDecimalInSelect() throws Exception {
- String query = "SELECT CAST a_integer AS DECIMAL/2 FROM aTable WHERE 5=a_integer";
- List<Object> binds = Collections.emptyList();
- compileQuery(query, binds);
- }
-
- @Test
- public void testCastingStringToDecimalInSelect() throws Exception {
- String query = "SELECT CAST b_string AS DECIMAL/2 FROM aTable WHERE 5=a_integer";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a string to decimal isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testCastingStringToDecimalInWhere() throws Exception {
- String query = "SELECT a_integer FROM aTable WHERE 2.5=CAST b_string AS DECIMAL/2 ";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a string to decimal isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testUsingNonComparableDataTypesInRowValueConstructorFails() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE (a_integer, x_integer) > (2, 'abc')";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a integer to string isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testUsingNonComparableDataTypesOfColumnRefOnLHSAndRowValueConstructorFails() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE a_integer > ('abc', 2)";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a integer to string isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testUsingNonComparableDataTypesOfLiteralOnLHSAndRowValueConstructorFails() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE 'abc' > (a_integer, x_integer)";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a integer to string isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testUsingNonComparableDataTypesOfColumnRefOnRHSAndRowValueConstructorFails() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE ('abc', 2) < a_integer ";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a integer to string isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testUsingNonComparableDataTypesOfLiteralOnRHSAndRowValueConstructorFails() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE (a_integer, x_integer) < 'abc'";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since casting a integer to string isn't supported");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- }
- }
-
- @Test
- public void testNonConstantInList() throws Exception {
- String query = "SELECT a_integer, x_integer FROM aTable WHERE a_integer IN (x_integer)";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since non constants in IN is not valid");
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.VALUE_IN_LIST_NOT_CONSTANT.getErrorCode());
- }
- }
-
- @Test
- public void testKeyValueColumnInPKConstraint() throws Exception {
- String ddl = "CREATE TABLE t (a.k VARCHAR, b.v VARCHAR CONSTRAINT pk PRIMARY KEY(k))";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertTrue(e.getErrorCode() == SQLExceptionCode.PRIMARY_KEY_WITH_FAMILY_NAME.getErrorCode());
- }
- }
-
- @Test
- public void testUnknownColumnInPKConstraint() throws Exception {
- String ddl = "CREATE TABLE t (k1 VARCHAR, b.v VARCHAR CONSTRAINT pk PRIMARY KEY(k1, k2))";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(ddl);
- fail();
- } catch (ColumnNotFoundException e) {
- assertEquals("K2",e.getColumnName());
- }
- }
-
-
- @Test
- public void testDuplicatePKColumn() throws Exception {
- String ddl = "CREATE TABLE t (k1 VARCHAR, k1 VARCHAR CONSTRAINT pk PRIMARY KEY(k1))";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(ddl);
- fail();
- } catch (ColumnAlreadyExistsException e) {
- assertEquals("K1",e.getColumnName());
- }
- }
-
-
- @Test
- public void testDuplicateKVColumn() throws Exception {
- String ddl = "CREATE TABLE t (k1 VARCHAR, v1 VARCHAR, v2 VARCHAR, v1 INTEGER CONSTRAINT pk PRIMARY KEY(k1))";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(ddl);
- fail();
- } catch (ColumnAlreadyExistsException e) {
- assertEquals("V1",e.getColumnName());
- }
- }
-
- @Test
- public void testDeleteFromImmutableWithKV() throws Exception {
- String ddl = "CREATE TABLE t (k1 VARCHAR, v1 VARCHAR, v2 VARCHAR CONSTRAINT pk PRIMARY KEY(k1)) immutable_rows=true";
- String indexDDL = "CREATE INDEX i ON t (v1)";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement().execute(indexDDL);
- conn.createStatement().execute("DELETE FROM t");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.NO_DELETE_IF_IMMUTABLE_INDEX.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testInvalidNegativeArrayIndex() throws Exception {
- String query = "SELECT a_double_array[-20] FROM table_with_array";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(query);
- fail();
- } catch (Exception e) {
-
- }
- }
- @Test
- public void testWrongDataTypeInRoundFunction() throws Exception {
- String query = "SELECT ROUND(a_string, 'day', 1) FROM aTable";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since VARCHAR is not a valid data type for ROUND");
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testNonArrayColumnWithIndex() throws Exception {
- String query = "SELECT a_float[1] FROM table_with_array";
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- conn.createStatement().execute(query);
- fail();
- } catch (Exception e) {
- }
- }
-
- public void testWrongTimeUnitInRoundDateFunction() throws Exception {
- String query = "SELECT ROUND(a_date, 'dayss', 1) FROM aTable";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since dayss is not a valid time unit type");
- } catch (IllegalArgumentException e) {
- assertTrue(e.getMessage().contains(TimeUnit.VALID_VALUES));
- }
- }
-
- @Test
- public void testWrongMultiplierInRoundDateFunction() throws Exception {
- String query = "SELECT ROUND(a_date, 'days', 1.23) FROM aTable";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since multiplier can be an INTEGER only");
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testTypeMismatchForArrayElem() throws Exception {
- String query = "SELECT (a_string,a_date)[1] FROM aTable";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since a row value constructor is not an array");
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testTypeMismatch2ForArrayElem() throws Exception {
- String query = "SELECT ROUND(a_date, 'days', 1.23)[1] FROM aTable";
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since ROUND does not return an array");
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.TYPE_MISMATCH.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testInvalidArrayTypeAsPK () throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (col1 INTEGER[10] NOT NULL PRIMARY KEY)";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.ARRAY_NOT_ALLOWED_IN_PRIMARY_KEY.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
-
- conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (col1 VARCHAR, col2 INTEGER ARRAY[10] CONSTRAINT pk PRIMARY KEY (col1, col2))";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.ARRAY_NOT_ALLOWED_IN_PRIMARY_KEY.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInvalidArraySize() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- String query = "CREATE TABLE foo (col1 INTEGER[-1] NOT NULL PRIMARY KEY)";
- PreparedStatement statement = conn.prepareStatement(query);
- statement.execute();
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.MISMATCHED_TOKEN.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInvalidArrayInQuery () throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE t (k VARCHAR PRIMARY KEY, a INTEGER[10], B INTEGER[10])");
- try {
- conn.createStatement().execute("SELECT * FROM t ORDER BY a");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.ORDER_BY_ARRAY_NOT_SUPPORTED.getErrorCode(), e.getErrorCode());
- }
- try {
- conn.createStatement().execute("SELECT * FROM t WHERE a < b");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.NON_EQUALITY_ARRAY_COMPARISON.getErrorCode(), e.getErrorCode());
- }
- conn.close();
- }
-
- @Test
- public void testInvalidArrayElemRefInUpsert() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE t (k VARCHAR PRIMARY KEY, a INTEGER[10], B INTEGER[10])");
- try {
- conn.createStatement().execute("UPSERT INTO t(k,a[2]) VALUES('A', 5)");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.PARSER_ERROR.getErrorCode(), e.getErrorCode());
- }
- conn.close();
- }
-
- @Test
- public void testInvalidNextValueFor() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE SEQUENCE alpha.zeta");
- String[] queries = {
- "SELECT * FROM aTable WHERE a_integer < next value for alpha.zeta",
- "SELECT * FROM aTable GROUP BY a_string,next value for alpha.zeta",
- "SELECT * FROM aTable GROUP BY 1 + next value for alpha.zeta",
- "SELECT * FROM aTable GROUP BY a_integer HAVING a_integer < next value for alpha.zeta",
- "SELECT * FROM aTable WHERE a_integer < 3 GROUP BY a_integer HAVING a_integer < next value for alpha.zeta",
- "SELECT * FROM aTable ORDER BY next value for alpha.zeta",
- "SELECT max(next value for alpha.zeta) FROM aTable",
- };
- for (String query : queries) {
- List<Object> binds = Collections.emptyList();
- try {
- compileQuery(query, binds);
- fail("Compilation should have failed since this is an invalid usage of NEXT VALUE FOR: " + query);
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.INVALID_USE_OF_NEXT_VALUE_FOR.getErrorCode(), e.getErrorCode());
- }
- }
- }
-
- @Test
- public void testNoCachingHint() throws Exception {
- List<Object> binds = Collections.emptyList();
- Scan scan = compileQuery("select val from ptsdb", binds);
- assertTrue(scan.getCacheBlocks());
- scan = compileQuery("select /*+ NO_CACHE */ val from ptsdb", binds);
- assertFalse(scan.getCacheBlocks());
- scan = compileQuery("select /*+ NO_CACHE */ p1.val from ptsdb p1 inner join ptsdb p2 on p1.inst = p2.inst", binds);
- assertFalse(scan.getCacheBlocks());
- }
-
-}
[8/8] git commit: Fix failing unit test, rename tests for consistency
Posted by ja...@apache.org.
Fix failing unit test, rename tests for consistency
Project: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/commit/0ea954ea
Tree: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/tree/0ea954ea
Diff: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/diff/0ea954ea
Branch: refs/heads/master
Commit: 0ea954eaeaf8a5543ea2c5bae6baa61cbb508381
Parents: fe18e96
Author: James Taylor <ja...@apache.org>
Authored: Mon Feb 10 09:13:55 2014 -0800
Committer: James Taylor <ja...@apache.org>
Committed: Mon Feb 10 09:13:55 2014 -0800
----------------------------------------------------------------------
.../TrackOrderPreservingExpressionCompiler.java | 6 +-
.../phoenix/expression/InListExpression.java | 6 +-
.../org/apache/phoenix/schema/PDataType.java | 10 +-
.../phoenix/compile/HavingClauseTest.java | 194 ---
.../phoenix/compile/HavingCompilerTest.java | 191 +++
.../phoenix/compile/JoinQueryCompileTest.java | 146 --
.../phoenix/compile/JoinQueryCompilerTest.java | 146 ++
.../apache/phoenix/compile/LimitClauseTest.java | 157 --
.../phoenix/compile/LimitCompilerTest.java | 157 ++
.../phoenix/compile/QueryCompileTest.java | 1313 --------------
.../phoenix/compile/QueryCompilerTest.java | 1313 ++++++++++++++
.../apache/phoenix/compile/ViewCompileTest.java | 119 --
.../phoenix/compile/ViewCompilerTest.java | 119 ++
.../phoenix/compile/WhereClauseCompileTest.java | 932 ----------
.../compile/WhereClauseOptimizerTest.java | 1620 ------------------
.../phoenix/compile/WhereCompilerTest.java | 931 ++++++++++
.../phoenix/compile/WhereOptimizerTest.java | 1620 ++++++++++++++++++
.../query/BaseConnectionlessQueryTest.java | 44 +-
.../java/org/apache/phoenix/util/TestUtil.java | 4 +-
19 files changed, 4506 insertions(+), 4522 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/main/java/org/apache/phoenix/compile/TrackOrderPreservingExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TrackOrderPreservingExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TrackOrderPreservingExpressionCompiler.java
index 9600e55..a167fe6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TrackOrderPreservingExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TrackOrderPreservingExpressionCompiler.java
@@ -5,8 +5,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import com.google.common.base.Objects;
-import com.google.common.collect.Lists;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.LiteralExpression;
@@ -17,10 +15,12 @@ import org.apache.phoenix.parse.ColumnParseNode;
import org.apache.phoenix.parse.DivideParseNode;
import org.apache.phoenix.parse.MultiplyParseNode;
import org.apache.phoenix.parse.SubtractParseNode;
-import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.ColumnRef;
+import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.util.SchemaUtil;
+import com.google.common.collect.Lists;
+
/**
* Visitor that builds the expressions of a GROUP BY and ORDER BY clause. While traversing
* the parse node tree, the visitor also determines if the natural key order of the scan
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
index dfd073a..8a49999 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
@@ -33,11 +33,6 @@ import org.apache.hadoop.hbase.index.util.ImmutableBytesPtr;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.WritableUtils;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import org.apache.hadoop.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.expression.visitor.ExpressionVisitor;
import org.apache.phoenix.schema.ConstraintViolationException;
import org.apache.phoenix.schema.PDataType;
@@ -48,6 +43,7 @@ import org.apache.phoenix.util.ByteUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+
/*
* Implementation of a SQL foo IN (a,b,c) expression. Other than the first
* expression, child expressions must be constants.
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
index b2b4af6..fd21e09 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
@@ -33,14 +33,6 @@ import java.util.Map;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Base64;
import org.apache.hadoop.hbase.util.Bytes;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.math.LongMath;
-import com.google.common.primitives.Booleans;
-import com.google.common.primitives.Doubles;
-import com.google.common.primitives.Longs;
-
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.util.ByteUtil;
@@ -48,13 +40,13 @@ import org.apache.phoenix.util.DateUtil;
import org.apache.phoenix.util.NumberUtil;
import org.apache.phoenix.util.StringUtil;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.math.LongMath;
import com.google.common.primitives.Booleans;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Longs;
-
/**
* The data types of PColumns
*
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingClauseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingClauseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingClauseTest.java
deleted file mode 100644
index 0a36e8b..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingClauseTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.apache.phoenix.util.TestUtil.and;
-import static org.apache.phoenix.util.TestUtil.constantComparison;
-import static org.apache.phoenix.util.TestUtil.kvColumn;
-import static org.apache.phoenix.util.TestUtil.or;
-import static org.apache.phoenix.util.TestUtil.pkColumn;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
-import org.junit.Test;
-
-import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
-import org.apache.phoenix.expression.Expression;
-import org.apache.phoenix.expression.LiteralExpression;
-import org.apache.phoenix.expression.function.CountAggregateFunction;
-import org.apache.phoenix.expression.function.RoundDateExpression;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.SQLParser;
-import org.apache.phoenix.parse.SelectStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-
-
-public class HavingClauseTest extends BaseConnectionlessQueryTest {
- private static StatementContext context;
-
- private static class Expressions {
- private Expression whereClause;
- private Expression havingClause;
-
- private Expressions(Expression whereClause, Expression havingClause) {
- this.whereClause = whereClause;
- this.havingClause = havingClause;
- }
- }
-
- private static Expressions compileStatement(String query, List<Object> binds) throws SQLException {
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- Scan scan = new Scan();
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- statement = StatementNormalizer.normalize(statement, resolver);
- context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
-
- GroupBy groupBy = GroupByCompiler.compile(context, statement);
- // Optimize the HAVING clause by finding any group by expressions that can be moved
- // to the WHERE clause
- statement = HavingCompiler.rewrite(context, statement, groupBy);
- Expression having = HavingCompiler.compile(context, statement, groupBy);
- Expression where = WhereCompiler.compile(context, statement);
- where = WhereOptimizer.pushKeyExpressionsToScan(context, statement, where);
- return new Expressions(where,having);
- }
-
- @Test
- public void testHavingToWhere() throws SQLException {
- String query = "select count(1) from atable group by a_string having a_string = 'foo'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression w = constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo");
- assertEquals(w, expressions.whereClause);
- assertNull(expressions.havingClause);
- }
-
- @Test
- public void testHavingFuncToWhere() throws SQLException {
- // TODO: confirm that this is a valid optimization
- String query = "select count(1) from atable group by a_date having round(a_date, 'hour') > ?";
- Date date = new Date(System.currentTimeMillis());
- List<Object> binds = Arrays.<Object>asList(date);
- Expressions expressions = compileStatement(query,binds);
- Expression w = constantComparison(CompareOp.GREATER, RoundDateExpression.create(Arrays.asList(kvColumn(BaseConnectionlessQueryTest.A_DATE),LiteralExpression.newConstant("hour"),LiteralExpression.newConstant(1))), date);
- assertEquals(w, expressions.whereClause);
- assertNull(expressions.havingClause);
- }
-
- @Test
- public void testHavingToAndWhere() throws SQLException {
- String query = "select count(1) from atable where b_string > 'bar' group by a_string having a_string = 'foo'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression w = and(constantComparison(CompareOp.GREATER, BaseConnectionlessQueryTest.B_STRING,"bar"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo"));
- assertEquals(w, expressions.whereClause);
- assertNull(expressions.havingClause);
- }
-
-
- @Test
- public void testAndHavingToAndWhere() throws SQLException {
- String query = "select count(1) from atable where b_string > 'bar' group by a_string having count(1) >= 1 and a_string = 'foo'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L);
- Expression w = and(constantComparison(CompareOp.GREATER, BaseConnectionlessQueryTest.B_STRING,"bar"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo"));
- assertEquals(w, expressions.whereClause);
- assertEquals(h, expressions.havingClause);
- }
-
- @Test
- public void testAndHavingToWhere() throws SQLException {
- String query = "select count(1) from atable group by a_string having count(1) >= 1 and a_string = 'foo'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L);
- Expression w = constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo");
- assertEquals(w, expressions.whereClause);
- assertEquals(h, expressions.havingClause);
- }
-
- @Test
- public void testAggFuncInHaving() throws SQLException {
- String query = "select count(1) from atable group by a_string having count(a_string) >= 1";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(Arrays.asList(kvColumn(BaseConnectionlessQueryTest.A_STRING))),1L);
- assertTrue(LiteralExpression.isTrue(expressions.whereClause));
- assertEquals(h, expressions.havingClause);
- }
-
- @Test
- public void testOrAggFuncInHaving() throws SQLException {
- String query = "select count(1) from atable group by a_string having count(1) >= 1 or a_string = 'foo'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression h = or(constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L),constantComparison(CompareOp.EQUAL, pkColumn(BaseConnectionlessQueryTest.A_STRING,Arrays.asList(BaseConnectionlessQueryTest.A_STRING)),"foo"));
- assertTrue(LiteralExpression.isTrue(expressions.whereClause));
- assertEquals(h, expressions.havingClause);
- }
-
- @Test
- public void testAndAggColsInHaving() throws SQLException {
- String query = "select count(1) from atable group by a_string,b_string having a_string = 'a' and b_string = 'b'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression w = and(constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"a"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.B_STRING,"b"));
- assertEquals(w, expressions.whereClause);
- assertNull(expressions.havingClause);
- }
-
- @Test
- public void testOrAggColsInHaving() throws SQLException {
- String query = "select count(1) from atable group by a_string,b_string having a_string = 'a' or b_string = 'b'";
- List<Object> binds = Collections.emptyList();
- Expressions expressions = compileStatement(query,binds);
- Expression w = or(constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"a"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.B_STRING,"b"));
- assertEquals(w, expressions.whereClause);
- assertNull(expressions.havingClause);
- }
-
- @Test
- public void testNonAggColInHaving() throws SQLException {
- String query = "select count(1) from atable group by a_string having b_string = 'bar'";
- List<Object> binds = Collections.emptyList();
- try {
- compileStatement(query,binds);
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1019 (42Y26): Only aggregate maybe used in the HAVING clause."));
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
new file mode 100644
index 0000000..65e13ab
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.apache.phoenix.util.TestUtil.and;
+import static org.apache.phoenix.util.TestUtil.constantComparison;
+import static org.apache.phoenix.util.TestUtil.or;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.expression.function.CountAggregateFunction;
+import org.apache.phoenix.expression.function.RoundDateExpression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.SQLParser;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.junit.Test;
+
+
+public class HavingCompilerTest extends BaseConnectionlessQueryTest {
+ private static StatementContext context;
+
+ private static class Expressions {
+ private Expression whereClause;
+ private Expression havingClause;
+
+ private Expressions(Expression whereClause, Expression havingClause) {
+ this.whereClause = whereClause;
+ this.havingClause = havingClause;
+ }
+ }
+
+ private static Expressions compileStatement(String query, List<Object> binds) throws SQLException {
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ Scan scan = new Scan();
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ statement = StatementNormalizer.normalize(statement, resolver);
+ context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+
+ GroupBy groupBy = GroupByCompiler.compile(context, statement);
+ // Optimize the HAVING clause by finding any group by expressions that can be moved
+ // to the WHERE clause
+ statement = HavingCompiler.rewrite(context, statement, groupBy);
+ Expression having = HavingCompiler.compile(context, statement, groupBy);
+ Expression where = WhereCompiler.compile(context, statement);
+ where = WhereOptimizer.pushKeyExpressionsToScan(context, statement, where);
+ return new Expressions(where,having);
+ }
+
+ @Test
+ public void testHavingToWhere() throws SQLException {
+ String query = "select count(1) from atable group by a_string having a_string = 'foo'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression w = constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo");
+ assertEquals(w, expressions.whereClause);
+ assertNull(expressions.havingClause);
+ }
+
+ @Test
+ public void testHavingFuncToWhere() throws SQLException {
+ // TODO: confirm that this is a valid optimization
+ String query = "select count(1) from atable group by a_date having round(a_date, 'hour') > ?";
+ Date date = new Date(System.currentTimeMillis());
+ List<Object> binds = Arrays.<Object>asList(date);
+ Expressions expressions = compileStatement(query,binds);
+ Expression w = constantComparison(CompareOp.GREATER, RoundDateExpression.create(Arrays.asList(BaseConnectionlessQueryTest.A_DATE,LiteralExpression.newConstant("hour"),LiteralExpression.newConstant(1))), date);
+ assertEquals(w, expressions.whereClause);
+ assertNull(expressions.havingClause);
+ }
+
+ @Test
+ public void testHavingToAndWhere() throws SQLException {
+ String query = "select count(1) from atable where b_string > 'bar' group by a_string having a_string = 'foo'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression w = and(constantComparison(CompareOp.GREATER, BaseConnectionlessQueryTest.B_STRING,"bar"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo"));
+ assertEquals(w, expressions.whereClause);
+ assertNull(expressions.havingClause);
+ }
+
+
+ @Test
+ public void testAndHavingToAndWhere() throws SQLException {
+ String query = "select count(1) from atable where b_string > 'bar' group by a_string having count(1) >= 1 and a_string = 'foo'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L);
+ Expression w = and(constantComparison(CompareOp.GREATER, BaseConnectionlessQueryTest.B_STRING,"bar"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo"));
+ assertEquals(w, expressions.whereClause);
+ assertEquals(h, expressions.havingClause);
+ }
+
+ @Test
+ public void testAndHavingToWhere() throws SQLException {
+ String query = "select count(1) from atable group by a_string having count(1) >= 1 and a_string = 'foo'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L);
+ Expression w = constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo");
+ assertEquals(w, expressions.whereClause);
+ assertEquals(h, expressions.havingClause);
+ }
+
+ @Test
+ public void testAggFuncInHaving() throws SQLException {
+ String query = "select count(1) from atable group by a_string having count(a_string) >= 1";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression h = constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(Arrays.asList(BaseConnectionlessQueryTest.A_STRING)),1L);
+ assertTrue(LiteralExpression.isTrue(expressions.whereClause));
+ assertEquals(h, expressions.havingClause);
+ }
+
+ @Test
+ public void testOrAggFuncInHaving() throws SQLException {
+ String query = "select count(1) from atable group by a_string having count(1) >= 1 or a_string = 'foo'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression h = or(constantComparison(CompareOp.GREATER_OR_EQUAL, new CountAggregateFunction(),1L),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"foo"));
+ assertTrue(LiteralExpression.isTrue(expressions.whereClause));
+ assertEquals(h, expressions.havingClause);
+ }
+
+ @Test
+ public void testAndAggColsInHaving() throws SQLException {
+ String query = "select count(1) from atable group by a_string,b_string having a_string = 'a' and b_string = 'b'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression w = and(constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"a"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.B_STRING,"b"));
+ assertEquals(w, expressions.whereClause);
+ assertNull(expressions.havingClause);
+ }
+
+ @Test
+ public void testOrAggColsInHaving() throws SQLException {
+ String query = "select count(1) from atable group by a_string,b_string having a_string = 'a' or b_string = 'b'";
+ List<Object> binds = Collections.emptyList();
+ Expressions expressions = compileStatement(query,binds);
+ Expression w = or(constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.A_STRING,"a"),constantComparison(CompareOp.EQUAL, BaseConnectionlessQueryTest.B_STRING,"b"));
+ assertEquals(w, expressions.whereClause);
+ assertNull(expressions.havingClause);
+ }
+
+ @Test
+ public void testNonAggColInHaving() throws SQLException {
+ String query = "select count(1) from atable group by a_string having b_string = 'bar'";
+ List<Object> binds = Collections.emptyList();
+ try {
+ compileStatement(query,binds);
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1019 (42Y26): Only aggregate maybe used in the HAVING clause."));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java
deleted file mode 100644
index b515697..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE;
-import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_NORMALIZED;
-import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE;
-import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_NORMALIZED;
-import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE;
-import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_NORMALIZED;
-import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE;
-import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_NORMALIZED;
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.Test;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.phoenix.compile.JoinCompiler.JoinSpec;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.SQLParser;
-import org.apache.phoenix.parse.SelectStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.util.QueryUtil;
-
-/**
- * Test compilation of queries containing joins.
- */
-public class JoinQueryCompileTest extends BaseConnectionlessQueryTest {
-
- @Test
- public void testExplainPlan() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
- String query = "EXPLAIN SELECT s.\"supplier_id\", \"order_id\", c.name, i.name, quantity, o.date FROM " + JOIN_ORDER_TABLE + " o LEFT JOIN "
- + JOIN_CUSTOMER_TABLE + " c ON o.\"customer_id\" = c.\"customer_id\" AND c.name LIKE 'C%' LEFT JOIN "
- + JOIN_ITEM_TABLE + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
- + JOIN_SUPPLIER_TABLE + " s ON s.\"supplier_id\" = i.\"supplier_id\" WHERE i.name LIKE 'T%'";
- ResultSet rs = conn.createStatement().executeQuery(query);
- assertEquals(
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_NORMALIZED + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL EQUI-JOIN 1 HASH TABLES:\n" +
- " BUILD HASH TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_NORMALIZED + "\n" +
- " PARALLEL EQUI-JOIN 2 HASH TABLES:\n" +
- " BUILD HASH TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_NORMALIZED + "\n" +
- " SERVER FILTER BY NAME LIKE 'C%'\n" +
- " BUILD HASH TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_NORMALIZED + "\n" +
- " AFTER-JOIN SERVER FILTER BY I.NAME LIKE 'T%'", QueryUtil.getExplainPlan(rs));
- }
-
- @Test
- public void testWhereClauseOptimization() throws Exception {
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- String queryTemplate = "SELECT t1.\"item_id\", t2.\"item_id\", t3.\"item_id\" FROM " + JOIN_ITEM_TABLE + " t1 "
- + "%s JOIN " + JOIN_ITEM_TABLE + " t2 ON t1.\"item_id\" = t2.\"item_id\" "
- + "%s JOIN " + JOIN_ITEM_TABLE + " t3 ON t1.\"item_id\" = t3.\"item_id\" "
- + "WHERE t1.\"item_id\" = '0000000001' AND t2.\"item_id\" = '0000000002' AND t3.\"item_id\" = '0000000003'";
-
- String query = String.format(queryTemplate, "INNER", "INNER");
- JoinSpec joinSpec = getJoinSpec(query, pconn);
- assertEquals(1, joinSpec.getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "INNER", "LEFT");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(1, joinSpec.getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "INNER", "RIGHT");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(0, joinSpec.getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "LEFT", "INNER");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(1, joinSpec.getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "LEFT", "LEFT");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(1, joinSpec.getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "LEFT", "RIGHT");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(0, joinSpec.getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "RIGHT", "INNER");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(0, joinSpec.getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
-
- query = String.format(queryTemplate, "RIGHT", "RIGHT");
- joinSpec = getJoinSpec(query, pconn);
- assertEquals(0, joinSpec.getPreFilters().size());
- assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
- assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
- }
-
- private static JoinSpec getJoinSpec(String query, PhoenixConnection connection) throws SQLException {
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- SQLParser parser = new SQLParser(query);
- SelectStatement select = parser.parseQuery();
- ColumnResolver resolver = FromCompiler.getResolver(select, connection);
- select = StatementNormalizer.normalize(select, resolver);
- StatementContext context = new StatementContext(new PhoenixStatement(connection), resolver, binds, scan);
- return JoinCompiler.getJoinSpec(context, select);
- }
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompilerTest.java
new file mode 100644
index 0000000..2c1d1ab
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompilerTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE;
+import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_NORMALIZED;
+import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE;
+import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_NORMALIZED;
+import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE;
+import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_NORMALIZED;
+import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE;
+import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_NORMALIZED;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.JoinCompiler.JoinSpec;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.SQLParser;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.util.QueryUtil;
+
+/**
+ * Test compilation of queries containing joins.
+ */
+public class JoinQueryCompilerTest extends BaseConnectionlessQueryTest {
+
+ @Test
+ public void testExplainPlan() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String query = "EXPLAIN SELECT s.\"supplier_id\", \"order_id\", c.name, i.name, quantity, o.date FROM " + JOIN_ORDER_TABLE + " o LEFT JOIN "
+ + JOIN_CUSTOMER_TABLE + " c ON o.\"customer_id\" = c.\"customer_id\" AND c.name LIKE 'C%' LEFT JOIN "
+ + JOIN_ITEM_TABLE + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + JOIN_SUPPLIER_TABLE + " s ON s.\"supplier_id\" = i.\"supplier_id\" WHERE i.name LIKE 'T%'";
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_NORMALIZED + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL EQUI-JOIN 1 HASH TABLES:\n" +
+ " BUILD HASH TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_NORMALIZED + "\n" +
+ " PARALLEL EQUI-JOIN 2 HASH TABLES:\n" +
+ " BUILD HASH TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_NORMALIZED + "\n" +
+ " SERVER FILTER BY NAME LIKE 'C%'\n" +
+ " BUILD HASH TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_NORMALIZED + "\n" +
+ " AFTER-JOIN SERVER FILTER BY I.NAME LIKE 'T%'", QueryUtil.getExplainPlan(rs));
+ }
+
+ @Test
+ public void testWhereClauseOptimization() throws Exception {
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ String queryTemplate = "SELECT t1.\"item_id\", t2.\"item_id\", t3.\"item_id\" FROM " + JOIN_ITEM_TABLE + " t1 "
+ + "%s JOIN " + JOIN_ITEM_TABLE + " t2 ON t1.\"item_id\" = t2.\"item_id\" "
+ + "%s JOIN " + JOIN_ITEM_TABLE + " t3 ON t1.\"item_id\" = t3.\"item_id\" "
+ + "WHERE t1.\"item_id\" = '0000000001' AND t2.\"item_id\" = '0000000002' AND t3.\"item_id\" = '0000000003'";
+
+ String query = String.format(queryTemplate, "INNER", "INNER");
+ JoinSpec joinSpec = getJoinSpec(query, pconn);
+ assertEquals(1, joinSpec.getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "INNER", "LEFT");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(1, joinSpec.getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "INNER", "RIGHT");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(0, joinSpec.getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "LEFT", "INNER");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(1, joinSpec.getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "LEFT", "LEFT");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(1, joinSpec.getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "LEFT", "RIGHT");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(0, joinSpec.getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "RIGHT", "INNER");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(0, joinSpec.getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+
+ query = String.format(queryTemplate, "RIGHT", "RIGHT");
+ joinSpec = getJoinSpec(query, pconn);
+ assertEquals(0, joinSpec.getPreFilters().size());
+ assertEquals(0, joinSpec.getJoinTables().get(0).getPreFilters().size());
+ assertEquals(1, joinSpec.getJoinTables().get(1).getPreFilters().size());
+ }
+
+ private static JoinSpec getJoinSpec(String query, PhoenixConnection connection) throws SQLException {
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ SQLParser parser = new SQLParser(query);
+ SelectStatement select = parser.parseQuery();
+ ColumnResolver resolver = FromCompiler.getResolver(select, connection);
+ select = StatementNormalizer.normalize(select, resolver);
+ StatementContext context = new StatementContext(new PhoenixStatement(connection), resolver, binds, scan);
+ return JoinCompiler.getJoinSpec(context, select);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitClauseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitClauseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitClauseTest.java
deleted file mode 100644
index 9aa3249..0000000
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitClauseTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.phoenix.compile;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.hbase.client.Scan;
-import org.junit.Test;
-
-import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
-import org.apache.phoenix.expression.Expression;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.SQLParser;
-import org.apache.phoenix.parse.SelectStatement;
-import org.apache.phoenix.query.BaseConnectionlessQueryTest;
-import org.apache.phoenix.schema.PDataType;
-import org.apache.phoenix.util.ByteUtil;
-
-
-public class LimitClauseTest extends BaseConnectionlessQueryTest {
-
- private static Integer compileStatement(String query, List<Object> binds, Scan scan) throws SQLException {
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- statement = StatementNormalizer.normalize(statement, resolver);
- StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
-
- Integer limit = LimitCompiler.compile(context, statement);
- GroupBy groupBy = GroupByCompiler.compile(context, statement);
- statement = HavingCompiler.rewrite(context, statement, groupBy);
- HavingCompiler.compile(context, statement, groupBy);
- Expression where = WhereCompiler.compile(context, statement);
- assertNull(where);
- return limit;
- }
-
- @Test
- public void testLimit() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' limit 5";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- Integer limit = compileStatement(query, binds, scan);
-
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- assertEquals(limit,Integer.valueOf(5));
- }
-
- @Test
- public void testNoLimit() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "'";
- Scan scan = new Scan();
- List<Object> binds = Collections.emptyList();
- Integer limit = compileStatement(query, binds, scan);
-
- assertNull(limit);
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- }
-
- @Test
- public void testBoundLimit() throws SQLException {
- String tenantId = "000000000000001";
- String query = "select * from atable where organization_id='" + tenantId + "' limit ?";
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(5);
- Integer limit = compileStatement(query, binds, scan);
-
- assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
- assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
- assertEquals(limit,Integer.valueOf(5));
- }
-
- @Test
- public void testTypeMismatchBoundLimit() throws SQLException {
- String query = "select * from atable limit ?";
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList("foo");
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
- try {
- LimitCompiler.compile(context, statement);
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage().contains("Type mismatch"));
- }
- }
-
- @Test
- public void testNegativeBoundLimit() throws SQLException {
- String query = "select * from atable limit ?";
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- Scan scan = new Scan();
- List<Object> binds = Arrays.<Object>asList(-1);
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
- assertNull(LimitCompiler.compile(context, statement));
- }
-
- @Test
- public void testBindTypeMismatch() throws SQLException {
- Long tenantId = Long.valueOf(0);
- String keyPrefix = "002";
- List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
- String query = "select * from atable where organization_id=? and substr(entity_id,1,3)=?";
- SQLParser parser = new SQLParser(query);
- SelectStatement statement = parser.parseQuery();
- Scan scan = new Scan();
- PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
- ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
- StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
- try {
- WhereCompiler.compile(context, statement);
- fail();
- } catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 203 (22005): Type mismatch."));
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/0ea954ea/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitCompilerTest.java
new file mode 100644
index 0000000..ff7e690
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/LimitCompilerTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.compile;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.junit.Test;
+
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.SQLParser;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.util.ByteUtil;
+
+
+public class LimitCompilerTest extends BaseConnectionlessQueryTest {
+
+ private static Integer compileStatement(String query, List<Object> binds, Scan scan) throws SQLException {
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ statement = StatementNormalizer.normalize(statement, resolver);
+ StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+
+ Integer limit = LimitCompiler.compile(context, statement);
+ GroupBy groupBy = GroupByCompiler.compile(context, statement);
+ statement = HavingCompiler.rewrite(context, statement, groupBy);
+ HavingCompiler.compile(context, statement, groupBy);
+ Expression where = WhereCompiler.compile(context, statement);
+ assertNull(where);
+ return limit;
+ }
+
+ @Test
+ public void testLimit() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' limit 5";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ Integer limit = compileStatement(query, binds, scan);
+
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ assertEquals(limit,Integer.valueOf(5));
+ }
+
+ @Test
+ public void testNoLimit() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "'";
+ Scan scan = new Scan();
+ List<Object> binds = Collections.emptyList();
+ Integer limit = compileStatement(query, binds, scan);
+
+ assertNull(limit);
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ }
+
+ @Test
+ public void testBoundLimit() throws SQLException {
+ String tenantId = "000000000000001";
+ String query = "select * from atable where organization_id='" + tenantId + "' limit ?";
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(5);
+ Integer limit = compileStatement(query, binds, scan);
+
+ assertArrayEquals(PDataType.VARCHAR.toBytes(tenantId), scan.getStartRow());
+ assertArrayEquals(ByteUtil.nextKey(PDataType.VARCHAR.toBytes(tenantId)), scan.getStopRow());
+ assertEquals(limit,Integer.valueOf(5));
+ }
+
+ @Test
+ public void testTypeMismatchBoundLimit() throws SQLException {
+ String query = "select * from atable limit ?";
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList("foo");
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+ try {
+ LimitCompiler.compile(context, statement);
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Type mismatch"));
+ }
+ }
+
+ @Test
+ public void testNegativeBoundLimit() throws SQLException {
+ String query = "select * from atable limit ?";
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ Scan scan = new Scan();
+ List<Object> binds = Arrays.<Object>asList(-1);
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+ assertNull(LimitCompiler.compile(context, statement));
+ }
+
+ @Test
+ public void testBindTypeMismatch() throws SQLException {
+ Long tenantId = Long.valueOf(0);
+ String keyPrefix = "002";
+ List<Object> binds = Arrays.<Object>asList(tenantId,keyPrefix);
+ String query = "select * from atable where organization_id=? and substr(entity_id,1,3)=?";
+ SQLParser parser = new SQLParser(query);
+ SelectStatement statement = parser.parseQuery();
+ Scan scan = new Scan();
+ PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class);
+ ColumnResolver resolver = FromCompiler.getResolver(statement, pconn);
+ StatementContext context = new StatementContext(new PhoenixStatement(pconn), resolver, binds, scan);
+ try {
+ WhereCompiler.compile(context, statement);
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 203 (22005): Type mismatch."));
+ }
+ }
+}