aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2018-05-30 01:19:41 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2018-05-30 01:19:41 +0000
commit09d03800ceffacff220148aac5664e1dfd6e56f4 (patch)
tree8e4af51bd066dd223b8cb38cc193576b7d5d3d15 /src
parent2ff5d06acd02969b0dc5a6dd2dacf971a1df19e2 (diff)
downloadjackcess-09d03800ceffacff220148aac5664e1dfd6e56f4.tar.gz
jackcess-09d03800ceffacff220148aac5664e1dfd6e56f4.zip
use decimal math context which matches access precision; tweak string to number conversion to match access
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/exprs@1156 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java40
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java7
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java7
3 files changed, 36 insertions, 18 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java
index 8400a7c..6d768a1 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java
@@ -17,6 +17,7 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
+import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.util.Date;
@@ -58,7 +59,8 @@ public class BuiltinOperators
public static final Value ZERO_VAL = FALSE_VAL;
public static final RoundingMode ROUND_MODE = RoundingMode.HALF_EVEN;
- private static final int MAX_NUMERIC_SCALE = 28;
+ public static final MathContext MATH_CONTEXT =
+ new MathContext(28, ROUND_MODE);
private enum CoercionType {
SIMPLE(true, true), GENERAL(false, true), COMPARE(false, false);
@@ -107,7 +109,7 @@ public class BuiltinOperators
return toValue(-param1.getAsDouble());
case STRING:
case BIG_DEC:
- return toValue(param1.getAsBigDecimal().negate());
+ return toValue(param1.getAsBigDecimal().negate(MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
}
@@ -137,7 +139,8 @@ public class BuiltinOperators
case DOUBLE:
return toValue(param1.getAsDouble() + param2.getAsDouble());
case BIG_DEC:
- return toValue(param1.getAsBigDecimal().add(param2.getAsBigDecimal()));
+ return toValue(param1.getAsBigDecimal().add(
+ param2.getAsBigDecimal(), MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
}
@@ -165,7 +168,8 @@ public class BuiltinOperators
case DOUBLE:
return toValue(param1.getAsDouble() - param2.getAsDouble());
case BIG_DEC:
- return toValue(param1.getAsBigDecimal().subtract(param2.getAsBigDecimal()));
+ return toValue(param1.getAsBigDecimal().subtract(
+ param2.getAsBigDecimal(), MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
}
@@ -190,7 +194,8 @@ public class BuiltinOperators
case DOUBLE:
return toValue(param1.getAsDouble() * param2.getAsDouble());
case BIG_DEC:
- return toValue(param1.getAsBigDecimal().multiply(param2.getAsBigDecimal()));
+ return toValue(param1.getAsBigDecimal().multiply(
+ param2.getAsBigDecimal(), MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
}
@@ -253,6 +258,18 @@ public class BuiltinOperators
Value.Type mathType = getMathTypePrecedence(param1, param2,
CoercionType.GENERAL);
+ if(mathType == Value.Type.BIG_DEC) {
+ // see if we can handle the limited options supported for BigDecimal
+ // (must be a positive int exponent)
+ try {
+ BigDecimal result = param1.getAsBigDecimal().pow(
+ param2.getAsBigDecimal().intValueExact(), MATH_CONTEXT);
+ return toValue(result);
+ } catch(ArithmeticException ae) {
+ // fall back to general handling via doubles...
+ }
+ }
+
// jdk only supports general pow() as doubles, let's go with that
double result = Math.pow(param1.getAsDouble(), param2.getAsDouble());
@@ -727,13 +744,12 @@ public class BuiltinOperators
try {
// see if string can be coerced to a number
- BigDecimal num = strParam.getAsBigDecimal();
+ strParam.getAsBigDecimal();
if(prefType.isNumeric()) {
- // re-evaluate the numeric type choice based on the type of the parsed
- // number
- Value.Type numType = ((num.scale() > 0) ?
- Value.Type.BIG_DEC : Value.Type.LONG);
- prefType = getPreferredNumericType(numType, prefType);
+ // seems like when strings are coerced to numbers, they are usually
+ // doubles, unless the current context is decimal
+ prefType = ((prefType == Value.Type.BIG_DEC) ?
+ Value.Type.BIG_DEC : Value.Type.DOUBLE);
}
return prefType;
} catch(NumberFormatException ignored) {
@@ -748,7 +764,7 @@ public class BuiltinOperators
}
static BigDecimal divide(BigDecimal num, BigDecimal denom) {
- return num.divide(denom, MAX_NUMERIC_SCALE, ROUND_MODE);
+ return num.divide(denom, MATH_CONTEXT);
}
static boolean isIntegral(double d) {
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
index b2a4546..33ab133 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
@@ -28,7 +28,7 @@ import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
*
* @author James Ahlborn
*/
-public class DefaultNumberFunctions
+public class DefaultNumberFunctions
{
private DefaultNumberFunctions() {}
@@ -36,7 +36,7 @@ public class DefaultNumberFunctions
static void init() {
// dummy method to ensure this class is loaded
}
-
+
public static final Function ABS = registerFunc(new Func1NullIsNull("Abs") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
@@ -55,7 +55,8 @@ public class DefaultNumberFunctions
return BuiltinOperators.toValue(Math.abs(param1.getAsDouble()));
case STRING:
case BIG_DEC:
- return BuiltinOperators.toValue(param1.getAsBigDecimal().abs());
+ return BuiltinOperators.toValue(param1.getAsBigDecimal().abs(
+ BuiltinOperators.MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
}
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
index f20179a..714421e 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
@@ -281,7 +281,8 @@ public class ExpressionatorTest extends TestCase
assertEquals(100, eval("=-10^2"));
assertEquals(-100, eval("=-(10)^2"));
- assertEquals(-100, eval("=-\"10\"^2"));
+ assertEquals(-100d, eval("=-\"10\"^2"));
+ assertEquals(toBD(-98.9d), eval("=1.1+(-\"10\"^2)"));
assertEquals(toBD(99d), eval("=-10E-1+10e+1"));
assertEquals(toBD(-101d), eval("=-10E-1-10e+1"));
@@ -294,8 +295,8 @@ public class ExpressionatorTest extends TestCase
assertEquals("12foo", eval("=12 + \"foo\""));
assertEquals("foo12", eval("=\"foo\" + 12"));
- assertEquals(37, eval("=\"25\" + 12"));
- assertEquals(37, eval("=12 + \"25\""));
+ assertEquals(37d, eval("=\"25\" + 12"));
+ assertEquals(37d, eval("=12 + \"25\""));
evalFail(("=12 - \"foo\""), RuntimeException.class);
evalFail(("=\"foo\" - 12"), RuntimeException.class);