From 6e11d7bc23a397bc884a1f80b4ba7fc272b4127c Mon Sep 17 00:00:00 2001 From: yakolee Date: Mon, 26 May 2014 16:36:22 +0800 Subject: [PATCH] bugfix for sql Eval --- .../sql/visitor/SQLEvalVisitorUtils.java | 89 +++++++++++++++++-- .../bvt/sql/eval/SQLEvalVisitorUtilsTest.java | 7 ++ 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 10e5359333..54f2b39b41 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -1273,6 +1273,49 @@ public class SQLEvalVisitorUtils { return BigInteger.valueOf(((Number) val).longValue()); } + + public static Number castToNumber(String val) { + if (val == null) { + return null; + } + + try { + return Byte.parseByte(val); + } catch (NumberFormatException e) { + } + + try { + return Short.parseShort(val); + } catch (NumberFormatException e) { + } + + try { + return Integer.parseInt(val); + } catch (NumberFormatException e) { + } + + try { + return Long.parseLong(val); + } catch (NumberFormatException e) { + } + + try { + return Float.parseFloat(val); + } catch (NumberFormatException e) { + } + + try { + return Double.parseDouble(val); + } catch (NumberFormatException e) { + } + + try { + return new BigInteger(val); + } catch (NumberFormatException e) { + } + + return new BigDecimal(val); + } public static Date castToDate(Object val) { if (val == null) { @@ -1378,6 +1421,14 @@ public class SQLEvalVisitorUtils { if (a == null || b == null) { return null; } + + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { BigDecimal decimalA = castToDecimal(a); @@ -1655,6 +1706,14 @@ public class SQLEvalVisitorUtils { if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) { return EVAL_VALUE_NULL; } + + if (a instanceof String && !(b instanceof String)) { + a = castToNumber((String) a); + } + + if (b instanceof String && !(a instanceof String)) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).add(castToDecimal(b)); @@ -1695,7 +1754,7 @@ public class SQLEvalVisitorUtils { return castToByte(a) + castToByte(b); } - if (a instanceof String || b instanceof String) { + if (a instanceof String && b instanceof String) { return castToString(a) + castToString(b); } @@ -1718,6 +1777,14 @@ public class SQLEvalVisitorUtils { if (a instanceof Date || b instanceof Date) { return SQLEvalVisitor.EVAL_ERROR; } + + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).subtract(castToDecimal(b)); @@ -1758,10 +1825,6 @@ public class SQLEvalVisitorUtils { return castToByte(a) - castToByte(b); } - if (a instanceof String && b instanceof String) { - return castToLong(a) - castToLong(b); - } - // return SQLEvalVisitor.EVAL_ERROR; throw new IllegalArgumentException(a.getClass() + " and " + b.getClass() + " not supported."); } @@ -1771,6 +1834,14 @@ public class SQLEvalVisitorUtils { return null; } + if (a instanceof String) { + a = castToNumber((String) a); + } + + if (b instanceof String) { + b = castToNumber((String) b); + } + if (a instanceof BigDecimal || b instanceof BigDecimal) { return castToDecimal(a).multiply(castToDecimal(b)); } @@ -1778,6 +1849,14 @@ public class SQLEvalVisitorUtils { if (a instanceof BigInteger || b instanceof BigInteger) { return castToBigInteger(a).multiply(castToBigInteger(b)); } + + if (a instanceof Double || b instanceof Double) { + return castToDouble(a) * castToDouble(b); + } + + if (a instanceof Float || b instanceof Float) { + return castToFloat(a) * castToFloat(b); + } if (a instanceof Long || b instanceof Long) { return castToLong(a) * castToLong(b); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java index 9c5e1c59e1..66fe661d09 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java @@ -29,6 +29,13 @@ public class SQLEvalVisitorUtilsTest extends TestCase { Assert.assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? - ?", Arrays. asList(2, 3))); Assert.assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? / ?", Arrays. asList(6, 3))); } + + public void test_evalExpr_3() throws Exception { + Assert.assertEquals(5.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? + ?", "2.0", 3)); + Assert.assertEquals(6.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? * ?", "2.0", 3)); + Assert.assertEquals(-1.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? - ?", "2.0", 3)); + Assert.assertEquals(2.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? / ?", "6.0", 3)); + } public void test_add() throws Exception { Assert.assertEquals(5, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, "? + ?", Arrays. asList(2, 3)));