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

Reply via email to