Repository: phoenix Updated Branches: refs/heads/4.x-HBase-1.1 314f4b46a -> 8ed5d1c2d
PHOENIX-3918 Ensure all function implementations handle null args correctly Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8ed5d1c2 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8ed5d1c2 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8ed5d1c2 Branch: refs/heads/4.x-HBase-1.1 Commit: 8ed5d1c2d5ca5e741f25e0c841ec6bfb1392e882 Parents: 314f4b4 Author: Thomas <[email protected]> Authored: Thu Jun 8 11:20:28 2017 -0700 Committer: Thomas <[email protected]> Committed: Wed Jun 14 15:29:43 2017 -0700 ---------------------------------------------------------------------- .../phoenix/end2end/CoalesceFunctionIT.java | 15 +++++++++++ .../phoenix/end2end/EncodeFunctionIT.java | 20 +++++++++++++++ .../end2end/OctetLengthFunctionEnd2EndIT.java | 9 ++++--- .../org/apache/phoenix/end2end/StringIT.java | 27 ++++++++++++++++++++ .../expression/function/CoalesceFunction.java | 2 +- .../function/FloorDateExpression.java | 11 +++++--- .../expression/function/GetBitFunction.java | 1 + .../expression/function/GetByteFunction.java | 1 + .../expression/function/LowerFunction.java | 6 +++-- .../expression/function/LpadFunction.java | 11 +++++--- .../expression/function/MD5Function.java | 3 ++- .../function/OctetLengthFunction.java | 1 + .../function/RegexpReplaceFunction.java | 9 +++++++ .../function/RoundDecimalExpression.java | 9 ++++--- .../function/RoundTimestampExpression.java | 11 +++++--- .../expression/function/SetBitFunction.java | 3 +++ .../expression/function/SetByteFunction.java | 2 ++ .../expression/function/SignFunction.java | 3 +++ .../expression/function/SubstrFunction.java | 13 ++++++++-- .../expression/OctetLengthFunctionTest.java | 7 ++++- 20 files changed, 138 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/it/java/org/apache/phoenix/end2end/CoalesceFunctionIT.java ---------------------------------------------------------------------- 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 @@ public class CoalesceFunctionIT extends ParallelStatsDisabledIT { 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()); + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/it/java/org/apache/phoenix/end2end/EncodeFunctionIT.java ---------------------------------------------------------------------- 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.DriverManager; 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 @@ public class EncodeFunctionIT extends ParallelStatsDisabledIT { 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 { http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java ---------------------------------------------------------------------- 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 @@ public class OctetLengthFunctionEnd2EndIT extends ParallelStatsDisabledIT { 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 class OctetLengthFunctionEnd2EndIT extends ParallelStatsDisabledIT { 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 @@ public class OctetLengthFunctionEnd2EndIT extends ParallelStatsDisabledIT { 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()); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/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 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 @@ public class StringIT extends ParallelStatsDisabledIT { 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 http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CoalesceFunction.java ---------------------------------------------------------------------- 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 @@ public class CoalesceFunction extends ScalarFunction { 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(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java ---------------------------------------------------------------------- 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.hadoop.hbase.io.ImmutableBytesWritable; 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 @@ public class FloorDateExpression extends RoundDateExpression { @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); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java ---------------------------------------------------------------------- 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 @@ public class GetBitFunction extends PrefixFunction { 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 http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java ---------------------------------------------------------------------- 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 @@ public class GetByteFunction extends PrefixFunction { 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 http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LowerFunction.java ---------------------------------------------------------------------- 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.sql.SQLException; 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 @@ public class LowerFunction extends ScalarFunction { if (!getStrExpression().evaluate(tuple, ptr)) { return false; } + if (ptr.getLength()==0) { + return true; + } String sourceStr = (String) PVarchar.INSTANCE.toObject(ptr, getStrExpression().getSortOrder()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java ---------------------------------------------------------------------- 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.PChar; 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 @@ public class LpadFunction extends ScalarFunction { 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 @@ public class LpadFunction extends ScalarFunction { 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 http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MD5Function.java ---------------------------------------------------------------------- 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.hadoop.hbase.io.ImmutableBytesWritable; 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 @@ public class MD5Function extends ScalarFunction { @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()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java ---------------------------------------------------------------------- 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 @@ public class OctetLengthFunction extends ScalarFunction { // 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; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java ---------------------------------------------------------------------- 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 @@ public abstract class RegexpReplaceFunction extends ScalarFunction { 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 @@ public abstract class RegexpReplaceFunction extends ScalarFunction { 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 @@ public abstract class RegexpReplaceFunction extends ScalarFunction { 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); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java ---------------------------------------------------------------------- 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.compile.KeyPart; 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.PDecimal; 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 class RoundDecimalExpression extends ScalarFunction { 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)); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundTimestampExpression.java ---------------------------------------------------------------------- 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.hadoop.hbase.io.ImmutableBytesWritable; 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 @@ public class RoundTimestampExpression extends RoundDateExpression { @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); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java ---------------------------------------------------------------------- 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 @@ public class SetBitFunction extends ScalarFunction { // 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; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java ---------------------------------------------------------------------- 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 @@ public class SetByteFunction extends ScalarFunction { // 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 http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java ---------------------------------------------------------------------- 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 @@ public class SignFunction extends ScalarFunction { 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; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SubstrFunction.java ---------------------------------------------------------------------- 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.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.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 @@ public class SubstrFunction extends PrefixFunction { 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 @@ public class SubstrFunction extends PrefixFunction { 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 @@ public class SubstrFunction extends PrefixFunction { if (!getStrExpression().evaluate(tuple, ptr)) { return false; } + if (ptr.getLength()==0) { + return true; + } boolean isCharType = getStrExpression().getDataType() == PChar.INSTANCE; SortOrder sortOrder = getStrExpression().getSortOrder(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8ed5d1c2/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java ---------------------------------------------------------------------- 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 @@ public class OctetLengthFunctionTest { 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)
