PHOENIX-2689 VARCHAR Field Not Working With String Concatenation
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/45a9d670 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/45a9d670 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/45a9d670 Branch: refs/heads/calcite Commit: 45a9d670bbb5e659fb967cfdbc6fc1ced43fba12 Parents: 7d90e88 Author: James Taylor <jtay...@salesforce.com> Authored: Thu Feb 18 12:16:27 2016 -0800 Committer: James Taylor <jtay...@salesforce.com> Committed: Thu Feb 18 12:16:27 2016 -0800 ---------------------------------------------------------------------- .../apache/phoenix/end2end/LpadFunctionIT.java | 242 ------------------ .../org/apache/phoenix/end2end/StringIT.java | 254 +++++++++++++++++++ .../expression/StringConcatExpression.java | 21 +- 3 files changed, 271 insertions(+), 246 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/45a9d670/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java deleted file mode 100644 index 4070103..0000000 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * 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.end2end; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.List; - -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.phoenix.query.QueryConstants; -import org.apache.phoenix.util.ByteUtil; -import org.apache.phoenix.util.TestUtil; -import org.junit.Test; - -import com.google.common.collect.Lists; - -/** - * Tests for the LPAD built-in function. - */ - -public class LpadFunctionIT extends BaseHBaseManagedTimeIT { - - /** - * Helper to test LPAD function - * - * @param conn - * connection to be used - * @param colName - * name of column to query - * @param length - * length of the output string - * @param fillString - * fill characters to be used while prepending - * @param sortOrder - * sort order of the pk column - * @param expectedOutput - * expected output of LPAD function - */ - private void testLpadHelper(Connection conn, String colName, int length, List<String> fillStringList, - List<String> expectedOutputList, String sortOrder) throws Exception { - assertEquals("fillStringList and expectedOutputList should be of equal size", fillStringList.size(), - expectedOutputList.size()); - for (int id = 0; id < fillStringList.size(); ++id) { - String fillString = fillStringList.get(id); - String lPadExpr = fillString != null ? "LPAD(%s,?,?)" : "LPAD(%s,?)"; - String sql = String.format("SELECT " + lPadExpr + " FROM TEST_TABLE_%s WHERE id=?", colName, sortOrder); - PreparedStatement stmt = conn.prepareStatement(sql); - int index = 1; - stmt.setInt(index++, length); - if (fillString != null) - stmt.setString(index++, fillString); - stmt.setInt(index++, id); - - ResultSet rs = stmt.executeQuery(); - assertTrue("Expected exactly one row to be returned ", rs.next()); - assertEquals("LPAD returned incorrect result ", expectedOutputList.get(id), rs.getString(1)); - assertFalse("Expected exactly one row to be returned ", rs.next()); - } - } - - /** - * Helper to test LPAD function - * - * @param conn - * connection to phoenix - * @param inputList - * list of values to test - * @param length - * length to be used in lpad function - * @param fillStringList - * list of fill string to be used while testing - * @param colName - * name of column to be used as function input - * @param expecetedOutputList - * list of expected output values - * @param expectedOutputList - * expected output of lpad function - */ - private void testLpad(Connection conn, List<String> inputList, int length, List<String> fillStringList, - String colName, List<String> expectedOutputList) throws Exception { - TestUtil.initTables(conn, "VARCHAR", new ArrayList<Object>(inputList)); - testLpadHelper(conn, colName, length, fillStringList, expectedOutputList, "ASC"); - testLpadHelper(conn, colName, length, fillStringList, expectedOutputList, "DESC"); - } - - private void testLpad(Connection conn, List<String> inputList, int length, List<String> fillStringList, - List<String> expectedOutputList) throws Exception { - testLpad(conn, inputList, length, fillStringList, "pk", expectedOutputList); - } - - @Test - public void testCharPadding() throws Exception { - ResultSet rs; - Connection conn = DriverManager.getConnection(getUrl()); - - conn.createStatement().execute("CREATE TABLE t (k CHAR(3) PRIMARY KEY)"); - conn.createStatement().execute("UPSERT INTO t VALUES('a')"); - conn.createStatement().execute("UPSERT INTO t VALUES('ab')"); - conn.commit(); - rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k"); - assertTrue(rs.next()); - assertEquals("a", rs.getString(1)); - assertTrue(rs.next()); - assertEquals("ab", rs.getString(1)); - assertFalse(rs.next()); - - conn.createStatement().execute("CREATE TABLE tdesc (k CHAR(3) PRIMARY KEY DESC)"); - conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')"); - conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')"); - conn.commit(); - rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC"); - assertTrue(rs.next()); - assertEquals("ab", rs.getString(1)); - assertTrue(rs.next()); - assertEquals("a", rs.getString(1)); - assertFalse(rs.next()); - } - - @Test - public void testBinaryPadding() throws Exception { - ResultSet rs; - Connection conn = DriverManager.getConnection(getUrl()); - - conn.createStatement().execute("CREATE TABLE t (k BINARY(3) PRIMARY KEY)"); - conn.createStatement().execute("UPSERT INTO t VALUES('a')"); - conn.createStatement().execute("UPSERT INTO t VALUES('ab')"); - conn.commit(); - rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k"); - assertTrue(rs.next()); - assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); - assertTrue(rs.next()); - assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); - assertFalse(rs.next()); - - conn.createStatement().execute("CREATE TABLE tdesc (k BINARY(3) PRIMARY KEY DESC)"); - conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')"); - conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')"); - conn.commit(); - rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC"); - assertTrue(rs.next()); - assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); - assertTrue(rs.next()); - assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); - assertFalse(rs.next()); - } - - @Test - public void testNullInputStringSB() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("X", "X"), 4, Lists.newArrayList("", ""), "kv", - Lists.<String> newArrayList(null, null)); - } - - @Test - public void testEmptyFillExpr() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ"), 6, Lists.newArrayList("", ""), - Lists.<String> newArrayList(null, null)); - } - - @Test - public void testDefaultFill() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ"), 6, Lists.<String> newArrayList(null, null), - Lists.newArrayList(" ABCD", " ണഫɰɸ")); - } - - @Test - public void testLpadFillLengthGreaterThanPadLength() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 8, - Lists.newArrayList("123456", "ÉÉɦÉÉɦ", "123456", "ണഫɰɸണഫ"), - Lists.newArrayList("1234ABCD", "ÉÉɦÉണഫɰɸ", "1234ണഫɰɸ", "ണഫɰɸABCD")); - } - - @Test - public void testLpadFillLengthLessThanPadLength() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ɰɸɰɸ", "ɰɸɰɸ", "ABCD"), 8, - Lists.newArrayList("12", "à´«É°", "12", "à´«É°"), - Lists.newArrayList("1212ABCD", "ഫɰഫɰɰɸɰɸ", "1212ɰɸɰɸ", "à´«É°à´«É°ABCD")); - } - - @Test - public void testLpadFillLengthEqualPadLength() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ɰɸɰɸ", "ɰɸɰɸ", "ABCD"), 8, - Lists.newArrayList("1234", "ണഫɰɸ", "1234", "ണഫɰɸ"), - Lists.newArrayList("1234ABCD", "ണഫɰɸɰɸɰɸ", "1234ɰɸɰɸ", "ണഫɰɸABCD")); - } - - @Test - public void testLpadZeroPadding() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - ArrayList<String> inputList = Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"); - testLpad(conn, inputList, 4, Lists.newArrayList("1234", "ÉɦÉɦ", "1234", "ÉɦÉɦ"), inputList); - } - - @Test - public void testLpadTrucate() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 2, - Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.newArrayList("AB", "ണഫ", "ണഫ", "AB")); - } - - @Test - public void testLpadZeroOutputStringLength() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 0, - Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.<String> newArrayList(null, null, null, null)); - } - - @Test - public void testNegativeOutputStringLength() throws Exception { - Connection conn = DriverManager.getConnection(getUrl()); - testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), -1, - Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.<String> newArrayList(null, null, null, null)); - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/45a9d670/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java new file mode 100644 index 0000000..b315d7d --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java @@ -0,0 +1,254 @@ +/** + * 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.end2end; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.util.ByteUtil; +import org.apache.phoenix.util.TestUtil; +import org.junit.Test; + +import com.google.common.collect.Lists; + +/** + * Tests for the LPAD built-in function. + */ + +public class StringIT extends BaseHBaseManagedTimeIT { + + /** + * Helper to test LPAD function + * + * @param conn + * connection to be used + * @param colName + * name of column to query + * @param length + * length of the output string + * @param fillString + * fill characters to be used while prepending + * @param sortOrder + * sort order of the pk column + * @param expectedOutput + * expected output of LPAD function + */ + private void testLpadHelper(Connection conn, String colName, int length, List<String> fillStringList, + List<String> expectedOutputList, String sortOrder) throws Exception { + assertEquals("fillStringList and expectedOutputList should be of equal size", fillStringList.size(), + expectedOutputList.size()); + for (int id = 0; id < fillStringList.size(); ++id) { + String fillString = fillStringList.get(id); + String lPadExpr = fillString != null ? "LPAD(%s,?,?)" : "LPAD(%s,?)"; + String sql = String.format("SELECT " + lPadExpr + " FROM TEST_TABLE_%s WHERE id=?", colName, sortOrder); + PreparedStatement stmt = conn.prepareStatement(sql); + int index = 1; + stmt.setInt(index++, length); + if (fillString != null) + stmt.setString(index++, fillString); + stmt.setInt(index++, id); + + ResultSet rs = stmt.executeQuery(); + assertTrue("Expected exactly one row to be returned ", rs.next()); + assertEquals("LPAD returned incorrect result ", expectedOutputList.get(id), rs.getString(1)); + assertFalse("Expected exactly one row to be returned ", rs.next()); + } + } + + /** + * Helper to test LPAD function + * + * @param conn + * connection to phoenix + * @param inputList + * list of values to test + * @param length + * length to be used in lpad function + * @param fillStringList + * list of fill string to be used while testing + * @param colName + * name of column to be used as function input + * @param expecetedOutputList + * list of expected output values + * @param expectedOutputList + * expected output of lpad function + */ + private void testLpad(Connection conn, List<String> inputList, int length, List<String> fillStringList, + String colName, List<String> expectedOutputList) throws Exception { + TestUtil.initTables(conn, "VARCHAR", new ArrayList<Object>(inputList)); + testLpadHelper(conn, colName, length, fillStringList, expectedOutputList, "ASC"); + testLpadHelper(conn, colName, length, fillStringList, expectedOutputList, "DESC"); + } + + private void testLpad(Connection conn, List<String> inputList, int length, List<String> fillStringList, + List<String> expectedOutputList) throws Exception { + testLpad(conn, inputList, length, fillStringList, "pk", expectedOutputList); + } + + @Test + public void testCharPadding() throws Exception { + ResultSet rs; + Connection conn = DriverManager.getConnection(getUrl()); + + conn.createStatement().execute("CREATE TABLE t (k CHAR(3) PRIMARY KEY)"); + conn.createStatement().execute("UPSERT INTO t VALUES('a')"); + conn.createStatement().execute("UPSERT INTO t VALUES('ab')"); + conn.commit(); + rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k"); + assertTrue(rs.next()); + assertEquals("a", rs.getString(1)); + assertTrue(rs.next()); + assertEquals("ab", rs.getString(1)); + assertFalse(rs.next()); + + conn.createStatement().execute("CREATE TABLE tdesc (k CHAR(3) PRIMARY KEY DESC)"); + conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')"); + conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')"); + conn.commit(); + rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC"); + assertTrue(rs.next()); + assertEquals("ab", rs.getString(1)); + assertTrue(rs.next()); + assertEquals("a", rs.getString(1)); + assertFalse(rs.next()); + } + + @Test + public void testBinaryPadding() throws Exception { + ResultSet rs; + Connection conn = DriverManager.getConnection(getUrl()); + + conn.createStatement().execute("CREATE TABLE t (k BINARY(3) PRIMARY KEY)"); + conn.createStatement().execute("UPSERT INTO t VALUES('a')"); + conn.createStatement().execute("UPSERT INTO t VALUES('ab')"); + conn.commit(); + rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k"); + assertTrue(rs.next()); + assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); + assertTrue(rs.next()); + assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); + assertFalse(rs.next()); + + conn.createStatement().execute("CREATE TABLE tdesc (k BINARY(3) PRIMARY KEY DESC)"); + conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')"); + conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')"); + conn.commit(); + rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC"); + assertTrue(rs.next()); + assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); + assertTrue(rs.next()); + assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1)); + assertFalse(rs.next()); + } + + @Test + public void testNullInputStringSB() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("X", "X"), 4, Lists.newArrayList("", ""), "kv", + Lists.<String> newArrayList(null, null)); + } + + @Test + public void testEmptyFillExpr() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ"), 6, Lists.newArrayList("", ""), + Lists.<String> newArrayList(null, null)); + } + + @Test + public void testDefaultFill() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ"), 6, Lists.<String> newArrayList(null, null), + Lists.newArrayList(" ABCD", " ണഫɰɸ")); + } + + @Test + public void testLpadFillLengthGreaterThanPadLength() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 8, + Lists.newArrayList("123456", "ÉÉɦÉÉɦ", "123456", "ണഫɰɸണഫ"), + Lists.newArrayList("1234ABCD", "ÉÉɦÉണഫɰɸ", "1234ണഫɰɸ", "ണഫɰɸABCD")); + } + + @Test + public void testLpadFillLengthLessThanPadLength() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ɰɸɰɸ", "ɰɸɰɸ", "ABCD"), 8, + Lists.newArrayList("12", "à´«É°", "12", "à´«É°"), + Lists.newArrayList("1212ABCD", "ഫɰഫɰɰɸɰɸ", "1212ɰɸɰɸ", "à´«É°à´«É°ABCD")); + } + + @Test + public void testLpadFillLengthEqualPadLength() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ɰɸɰɸ", "ɰɸɰɸ", "ABCD"), 8, + Lists.newArrayList("1234", "ണഫɰɸ", "1234", "ണഫɰɸ"), + Lists.newArrayList("1234ABCD", "ണഫɰɸɰɸɰɸ", "1234ɰɸɰɸ", "ണഫɰɸABCD")); + } + + @Test + public void testLpadZeroPadding() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + ArrayList<String> inputList = Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"); + testLpad(conn, inputList, 4, Lists.newArrayList("1234", "ÉɦÉɦ", "1234", "ÉɦÉɦ"), inputList); + } + + @Test + public void testLpadTrucate() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 2, + Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.newArrayList("AB", "ണഫ", "ണഫ", "AB")); + } + + @Test + public void testLpadZeroOutputStringLength() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), 0, + Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.<String> newArrayList(null, null, null, null)); + } + + @Test + public void testNegativeOutputStringLength() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + testLpad(conn, Lists.newArrayList("ABCD", "ണഫɰɸ", "ണഫɰɸ", "ABCD"), -1, + Lists.newArrayList("12", "Éɦ", "12", "Éɦ"), Lists.<String> newArrayList(null, null, null, null)); + } + + @Test + public void testStrConcat() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + conn.createStatement().execute("create table T (PK1 integer, F1 varchar, F2 varchar, F3 varchar, F4 varchar, constraint PK primary key (PK1))"); + conn.createStatement().execute("upsert into T(PK1, F1,F3) values(0, 'tortilla', 'chip')"); + conn.commit(); + + ResultSet rs = conn.createStatement().executeQuery("select * from T where (F1||F2||F3||F4)='tortillachip'"); + assertTrue(rs.next()); + assertEquals(0, rs.getInt(1)); + assertFalse(rs.next()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/45a9d670/phoenix-core/src/main/java/org/apache/phoenix/expression/StringConcatExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/StringConcatExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/StringConcatExpression.java index b8fcd41..85eb0f3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/StringConcatExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/StringConcatExpression.java @@ -21,12 +21,11 @@ package org.apache.phoenix.expression; import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; - import org.apache.phoenix.expression.visitor.ExpressionVisitor; -import org.apache.phoenix.schema.types.PVarchar; import org.apache.phoenix.schema.SortOrder; -import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PVarchar; import org.apache.phoenix.util.ByteUtil; @@ -67,12 +66,26 @@ public class StringConcatExpression extends BaseCompoundExpression { } @Override + public boolean requiresFinalEvaluation() { + return true; + } + + @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { byte[] result = ByteUtil.EMPTY_BYTE_ARRAY; for (int i=0; i<children.size(); i++) { - if (children.get(i).getDataType() == null || !children.get(i).evaluate(tuple, ptr)) { + if (children.get(i).getDataType() == null) { continue; } + if (!children.get(i).evaluate(tuple, ptr)) { + // If not incremental evaluation, skip null children + if (tuple.isImmutable()) { + continue; + } + // Otherwise, return false as an indication that we don't + // have enough information yet. + return false; + } PDataType childType = children.get(i).getDataType(); SortOrder sortOrder = children.get(i).getSortOrder(); // We could potentially not invert the bytes, but we might as well since we're allocating