PHOENIX-3918 Ensure all function implementations handle null args correctly
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CoalesceFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CoalesceFunctionIT.java
index c6d7db9..4a32424 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CoalesceFunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CoalesceFunctionIT.java
@@ -322,5 +322,20 @@
         assertFalse(rs.next());
     }
 
+    @Test
+    public void testNull() throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String tableName = generateUniqueName();
+        conn.createStatement().execute("CREATE TABLE " + tableName + "(k1 decimal, k2 decimal, constraint pk primary key (k1))");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES (1,1)");
+        conn.commit();
+        
+        ResultSet rs = conn.createStatement().executeQuery("SELECT coalesce(null, null) FROM " + tableName);
+        assertTrue(rs.next());
+        rs.getInt(1);
+        assertTrue(rs.wasNull());
+        assertFalse(rs.next());
+    }
 
 }
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/EncodeFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/EncodeFunctionIT.java
index 7517dd6..d0f1d5c 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/EncodeFunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/EncodeFunctionIT.java
@@ -26,6 +26,7 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.Collections;
 import java.util.List;
 
@@ -121,6 +122,25 @@
         ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM " + tableName + " WHERE pk = ENCODE(1, NULL)");
         assertFalse(rs.next());
     }
+    
+    @Test
+    public void testNullValue() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String tableName = generateUniqueName();
+        String ddl = "CREATE TABLE " + tableName + " ( pk VARCHAR(10) NOT NULL, val INTEGER CONSTRAINT PK PRIMARY KEY (pk))";
+        conn.createStatement().execute(ddl);
+        PreparedStatement ps = conn.prepareStatement("UPSERT INTO " + tableName + " (pk,val) VALUES (?,?)");
+        ps.setString(1, "1");
+        ps.setNull(2, Types.INTEGER);
+        ps.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("SELECT ENCODE(val, 'BASE62') FROM " + tableName);
+        assertTrue(rs.next());
+        rs.getInt(1);
+        assertTrue(rs.wasNull());
+        assertFalse(rs.next());
+    }
 
     @Test
     public void testUnsupportedEncodingType() throws Exception {
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
index 78ebfaa..48451c6 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
@@ -46,7 +46,7 @@
             conn = DriverManager.getConnection(getUrl());
             String ddl;
             ddl = "CREATE TABLE " + TABLE_NAME
-                + " (k VARCHAR NOT NULL PRIMARY KEY, b BINARY(4), vb VARBINARY)";
+                + " (k VARCHAR NOT NULL PRIMARY KEY, b BINARY(4), vb1 VARBINARY, vb2 VARBINARY)";
             conn.createStatement().execute(ddl);
             conn.commit();
         } finally {
@@ -58,7 +58,7 @@
     public void test() throws Exception {
         Connection conn = DriverManager.getConnection(getUrl());
         PreparedStatement stmt = conn.prepareStatement(
-            "UPSERT INTO " + TABLE_NAME + " VALUES (?, ?, ?)");
+            "UPSERT INTO " + TABLE_NAME + "(k,b,vb1) VALUES (?, ?, ?)");
         stmt.setString(1, KEY);
         stmt.setBytes(2, new byte[] { 1, 2, 3, 4 });
         stmt.setBytes(3, new byte[] { 1, 2, 3, 4 });
@@ -66,11 +66,12 @@
         conn.commit();
         ResultSet rs =
                 conn.createStatement()
-                        .executeQuery("SELECT OCTET_LENGTH(vb), OCTET_LENGTH(b) FROM " + TABLE_NAME
-                            + " WHERE OCTET_LENGTH(vb)=4 and OCTET_LENGTH(b)=4");
+                        .executeQuery("SELECT OCTET_LENGTH(vb1), OCTET_LENGTH(b), OCTET_LENGTH(vb2) FROM " + TABLE_NAME);
         assertTrue(rs.next());
         assertEquals(4, rs.getInt(1));
         assertEquals(4, rs.getInt(2));
+        rs.getInt(3);
+        assertTrue(rs.wasNull());
         assertTrue(!rs.next());
     }
 }
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
index 680935b..fe2e3b4 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringIT.java
@@ -255,4 +255,31 @@
         assertEquals(0, rs.getInt(1));
         assertFalse(rs.next());
     }
+    
+    @Test
+    public void testLpadWithNullArgs() throws Exception {
+        ResultSet rs;
+        Connection conn = DriverManager.getConnection(getUrl());
+        String tableName = generateUniqueName();
+        conn.createStatement().execute("CREATE TABLE " + tableName + " (k CHAR(3) PRIMARY KEY, v1 VARCHAR, v2 INTEGER)");
+        conn.createStatement().execute("UPSERT INTO " + tableName + "(k) VALUES('a')");
+        conn.commit();
+        
+        rs = conn.createStatement().executeQuery("SELECT LPAD(v1, 5, 'ab') FROM " + tableName );
+        assertTrue(rs.next());
+        assertEquals("ababa", rs.getString(1));
+        assertFalse(rs.next());
+        
+        rs = conn.createStatement().executeQuery("SELECT LPAD('abc', v2, 'a') FROM " + tableName );
+        assertTrue(rs.next());
+        rs.getString(1);
+        assertTrue(rs.wasNull());
+        assertFalse(rs.next());
+        
+        rs = conn.createStatement().executeQuery("SELECT LPAD('abc', 5, v1) FROM " + tableName );
+        assertTrue(rs.next());
+        rs.getString(1);
+        assertTrue(rs.wasNull());
+        assertFalse(rs.next());
+    }
 }
\ No newline at end of file
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CoalesceFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CoalesceFunction.java
index cf1fcd1..71d5156 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CoalesceFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CoalesceFunction.java
@@ -65,7 +65,7 @@
             ImmutableBytesWritable ptr = new ImmutableBytesPtr();
             secondChild.evaluate(null, ptr);
 
-            if (!secondChild.getDataType().isCoercibleTo(firstChild.getDataType(), secondChild.getDataType().toObject(ptr))) {
+            if (ptr.getLength()!=0 && !secondChild.getDataType().isCoercibleTo(firstChild.getDataType(), secondChild.getDataType().toObject(ptr))) {
                 throw new SQLExceptionInfo.Builder(SQLExceptionCode.TYPE_MISMATCH)
                     .setMessage(getName() + " expected " + firstChild.getDataType() + ", but got " + secondChild.getDataType())
                     .build().buildException();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
index 9c0b874..44cb3a3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
@@ -25,17 +25,17 @@
 import org.apache.phoenix.expression.CoerceExpression;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDate;
+import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PTimestamp;
 import org.apache.phoenix.schema.types.PUnsignedDate;
 import org.apache.phoenix.schema.types.PUnsignedTimestamp;
 import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.types.PInteger;
-import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
-import org.apache.phoenix.parse.FunctionParseNode.Argument;
-import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 
 import com.google.common.collect.Lists;
 
@@ -122,6 +122,9 @@
     @Override
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         if (children.get(0).evaluate(tuple, ptr)) {
+            if (ptr.getLength()==0) {
+                return true;
+            }
             PDataType dataType = getDataType();
             long time = dataType.getCodec().decodeLong(ptr, children.get(0).getSortOrder());
             long value = roundTime(time);
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
index 011841f..b6f2ac1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
@@ -61,6 +61,7 @@
         if (offsetPreCompute == null) {
             Expression offsetExpr = children.get(1);
             if (!offsetExpr.evaluate(tuple, ptr)) return false;
+            if (ptr.getLength() == 0) return true;
             offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
         } else offset = offsetPreCompute;
         // get binary data parameter
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
index 8e455ae..44f61a8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
@@ -61,6 +61,7 @@
         if (offsetPreCompute == null) {
             Expression offsetExpr = children.get(1);
             if (!offsetExpr.evaluate(tuple, ptr)) return false;
+            if (ptr.getLength() == 0) return true;
             offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
         } else offset = offsetPreCompute;
         // get binary data parameter
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LowerFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LowerFunction.java
index 0d8d817..8b79fe5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LowerFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LowerFunction.java
@@ -22,12 +22,11 @@
 import java.util.List;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.parse.FunctionParseNode;
+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.schema.tuple.Tuple;
 
 @FunctionParseNode.BuiltInFunction(name=LowerFunction.NAME,  args={
         @FunctionParseNode.Argument(allowedTypes={PVarchar.class})} )
@@ -46,6 +45,9 @@
         if (!getStrExpression().evaluate(tuple, ptr)) {
             return false;
         }
+        if (ptr.getLength()==0) {
+            return true;
+        }
 
         String sourceStr = (String) PVarchar.INSTANCE.toObject(ptr, getStrExpression().getSortOrder());
 
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
index eee03bf..6f0f262 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
@@ -28,6 +28,7 @@
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.StringUtil;
 
 /**
@@ -90,6 +91,9 @@
         if (!outputStrLenExpr.evaluate(tuple, ptr)) {
             return false;
         }
+        if (ptr.getLength()==0) {
+            return true;
+        }
         int outputStrLen = outputStrLenExpr.getDataType().getCodec().decodeInt(ptr, outputStrLenExpr.getSortOrder());
         if (outputStrLen < 0) {
             return false;
@@ -123,10 +127,9 @@
         if (!fillExpr.evaluate(tuple, fillPtr)) {
             return false;
         }
-        int fillExprLen = fillPtr.getLength();
-        if (fillExprLen < 1) {
-            // return if fill is empty
-            return false;
+        if (fillPtr.getLength()==0) {
+            ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+            return true;
         }
 
         // if the padding to be added is not a multiple of the length of the
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MD5Function.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MD5Function.java
index e4c3c98..0ed3010 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MD5Function.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MD5Function.java
@@ -26,9 +26,9 @@
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.parse.FunctionParseNode.Argument;
 import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PDataType;
-import org.apache.phoenix.schema.tuple.Tuple;
 
 @BuiltInFunction(name = MD5Function.NAME, args = { @Argument() })
 public class MD5Function extends ScalarFunction {
@@ -57,6 +57,7 @@
     @Override
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         if (!getChildExpression().evaluate(tuple, ptr)) { return false; }
+        if (ptr.getLength()==0) { return true; }
 
         // Update the digest value
         messageDigest.update(ptr.get(), ptr.getOffset(), ptr.getLength());
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
index ef20734..7372c80 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
@@ -54,6 +54,7 @@
         // get binary data parameter
         Expression dataExpr = children.get(0);
         if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         // set result
         ((PBinaryBase) dataExpr.getDataType()).octetLength(ptr, dataExpr.getSortOrder(), ptr);
         return true;
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
index f2ab8f3..265b860 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
@@ -101,6 +101,9 @@
             if (!e.evaluate(tuple, ptr)) {
                 return false;
             }
+            if (ptr.getLength()==0) {
+                return true;
+            }
             String patternStr = (String) TYPE.toObject(ptr, e.getDataType(), e.getSortOrder());
             if (patternStr == null) {
                 return false;
@@ -116,6 +119,9 @@
             if (!replaceStrExpression.evaluate(tuple, ptr)) {
                 return false;
             }
+            if (ptr.getLength()==0) {
+                return true;
+            }
             TYPE.coerceBytes(ptr, TYPE, replaceStrExpression.getSortOrder(), SortOrder.ASC);
             rStrBytes = ptr.get();
             rStrOffset = ptr.getOffset();
@@ -126,6 +132,9 @@
         if (!sourceStrExpression.evaluate(tuple, ptr)) {
             return false;
         }
+        if (ptr.getLength()==0) {
+            return true;
+        }
         TYPE.coerceBytes(ptr, TYPE, sourceStrExpression.getSortOrder(), SortOrder.ASC);
 
         pattern.replaceAll(ptr, rStrBytes, rStrOffset, rStrLen);
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
index 324d655..ab525f1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
@@ -33,6 +33,9 @@
 import org.apache.phoenix.expression.Determinism;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.PColumn;
@@ -43,9 +46,6 @@
 import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
-import org.apache.phoenix.parse.FunctionParseNode.Argument;
-import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 
 import com.google.common.collect.Lists;
 
@@ -125,6 +125,9 @@
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         Expression childExpr = children.get(0);
         if(childExpr.evaluate(tuple, ptr)) {
+            if (ptr.getLength()==0) {
+                return true;
+            }
             BigDecimal value = (BigDecimal) PDecimal.INSTANCE.toObject(ptr, childExpr.getDataType(), childExpr.getSortOrder());
             BigDecimal scaledValue = value.setScale(scale, getRoundingMode());
             ptr.set(PDecimal.INSTANCE.toBytes(scaledValue));
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundTimestampExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundTimestampExpression.java
index 51537b4..2ccd0df 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundTimestampExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundTimestampExpression.java
@@ -25,19 +25,19 @@
 import org.apache.phoenix.expression.CoerceExpression;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDataType.PDataCodec;
 import org.apache.phoenix.schema.types.PDate;
+import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PTimestamp;
 import org.apache.phoenix.schema.types.PUnsignedDate;
 import org.apache.phoenix.schema.types.PUnsignedTimestamp;
 import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.types.PInteger;
-import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
-import org.apache.phoenix.parse.FunctionParseNode.Argument;
-import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType;
 
 import com.google.common.collect.Lists;
 
@@ -104,6 +104,9 @@
     @Override
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         if (children.get(0).evaluate(tuple, ptr)) {
+            if (ptr.getLength()==0) {
+                return true;
+            }
             SortOrder sortOrder = children.get(0).getSortOrder();
             PDataType dataType = getDataType();
             int nanos = dataType.getNanos(ptr, sortOrder);
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
index a19ce80..756fc9a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
@@ -56,15 +56,18 @@
         // get offset parameter
         Expression offsetExpr = children.get(1);
         if (!offsetExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         int offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
         // get newValue parameter
         Expression newValueExpr = children.get(2);
         if (!newValueExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         int newValue = (Integer) PInteger.INSTANCE.toObject(ptr, newValueExpr.getSortOrder());
         byte newByteValue = (byte) (newValue & 0x1);
         // get binary data parameter
         Expression dataExpr = children.get(0);
         if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         if (ptr.getLength() == 0) return true;
         int len = ptr.getLength() * Byte.SIZE;
         offset = (offset % len + len) % len;
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
index e38ee18..0dc9ad5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
@@ -56,10 +56,12 @@
         // get offset parameter
         Expression offsetExpr = children.get(1);
         if (!offsetExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         int offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
         // get newValue parameter
         Expression newValueExpr = children.get(2);
         if (!newValueExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength()==0) return true;
         int newValue = (Integer) PInteger.INSTANCE.toObject(ptr, newValueExpr.getSortOrder());
         byte newByteValue = (byte) (newValue & 0xff);
         // get binary data parameter
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java
index a11eaff..1fd108e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java
@@ -55,6 +55,9 @@
         Expression childExpr = children.get(0);
         PDataType dataType = childExpr.getDataType();
         if (childExpr.evaluate(tuple, ptr)) {
+            if (ptr.getLength()==0) {
+                return true;
+            }
             int ret = ((PNumericType) dataType).signum(ptr, childExpr.getSortOrder());
             ptr.set(RESULT[ret + 1]);
             return true;
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SubstrFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SubstrFunction.java
index 4b21736..feaa07a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SubstrFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SubstrFunction.java
@@ -26,12 +26,12 @@
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.parse.FunctionParseNode.Argument;
 import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.util.StringUtil;
 
 
@@ -99,6 +99,9 @@
         if (!offsetExpression.evaluate(tuple,  ptr)) {
             return false;
         }
+        if (ptr.getLength()==0) {
+            return true;
+        }
         int offset = offsetExpression.getDataType().getCodec().decodeInt(ptr, offsetExpression.getSortOrder());
         
         int length = -1;
@@ -107,6 +110,9 @@
             if (!lengthExpression.evaluate(tuple, ptr)) {
                 return false;
             }
+            if (ptr.getLength()==0) {
+                return true;
+            }
             length = lengthExpression.getDataType().getCodec().decodeInt(ptr, lengthExpression.getSortOrder());
             if (length <= 0) {
                 return false;
@@ -116,6 +122,9 @@
         if (!getStrExpression().evaluate(tuple, ptr)) {
             return false;
         }
+        if (ptr.getLength()==0) {
+            return true;
+        }
     
         boolean isCharType = getStrExpression().getDataType() == PChar.INSTANCE;
         SortOrder sortOrder = getStrExpression().getSortOrder();
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
index 9211777..9e00e50 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.expression;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import java.sql.SQLException;
 import java.util.List;
@@ -44,7 +45,11 @@
         Integer result =
                 (Integer) octetLengthFunction.getDataType().toObject(ptr,
                     octetLengthFunction.getSortOrder());
-        assertEquals(expected, result.intValue());
+        if (expected == 0) {
+            assertNull(result);
+        } else {
+            assertEquals(expected, result.intValue());
+        }
     }
 
     private void testOctetLength(byte[] bytes, PBinaryBase dataType, int expected)