aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2017-09-23 05:04:01 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2017-09-23 05:04:01 +0000
commit774d505946db6b249aad04d8ecac506600731c93 (patch)
treed95e18c8a848684a9324d818120109ded7db59ce
parent8eb5fe91d9f7ad8d5c72429f95979cc3c2061b8d (diff)
downloadjackcess-774d505946db6b249aad04d8ecac506600731c93.tar.gz
jackcess-774d505946db6b249aad04d8ecac506600731c93.zip
long type should be int values; implement more date/time and misc other functions
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/exprs@1120 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/expr/EvalContext.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/expr/Value.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDateValue.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDelayedValue.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java7
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java101
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java122
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java140
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java15
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java30
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java6
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java4
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java18
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java66
17 files changed, 327 insertions, 204 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/EvalContext.java b/src/main/java/com/healthmarketscience/jackcess/expr/EvalContext.java
index 9f442f1..c140594 100644
--- a/src/main/java/com/healthmarketscience/jackcess/expr/EvalContext.java
+++ b/src/main/java/com/healthmarketscience/jackcess/expr/EvalContext.java
@@ -36,5 +36,5 @@ public interface EvalContext
public Value getRowValue(String collectionName, String objName,
String colName);
- public Random getRandom(Long seed);
+ public Random getRandom(Integer seed);
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/Value.java b/src/main/java/com/healthmarketscience/jackcess/expr/Value.java
index 1fd4390..39008f2 100644
--- a/src/main/java/com/healthmarketscience/jackcess/expr/Value.java
+++ b/src/main/java/com/healthmarketscience/jackcess/expr/Value.java
@@ -73,7 +73,7 @@ public interface Value
public Date getAsDateTime(EvalContext ctx);
- public Long getAsLong();
+ public Integer getAsLongInt();
public Double getAsDouble();
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDateValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDateValue.java
index 4bf03af..188416a 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDateValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDateValue.java
@@ -67,8 +67,8 @@ public abstract class BaseDateValue extends BaseValue
}
@Override
- public Long getAsLong() {
- return getNumber().longValue();
+ public Integer getAsLongInt() {
+ return roundToLongInt();
}
@Override
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDelayedValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDelayedValue.java
index c34a914..e8ae339 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDelayedValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseDelayedValue.java
@@ -64,8 +64,8 @@ public abstract class BaseDelayedValue implements Value
return getDelegate().getAsDateTime(ctx);
}
- public Long getAsLong() {
- return getDelegate().getAsLong();
+ public Integer getAsLongInt() {
+ return getDelegate().getAsLongInt();
}
public Double getAsDouble() {
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java
index 585c71e..dd12d7c 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java
@@ -39,8 +39,8 @@ public abstract class BaseNumericValue extends BaseValue
}
@Override
- public Long getAsLong() {
- return getNumber().longValue();
+ public Integer getAsLongInt() {
+ return roundToLongInt();
}
@Override
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java
index e30c303..6107fbc 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java
@@ -44,7 +44,7 @@ public abstract class BaseValue implements Value
throw invalidConversion(Value.Type.DATE_TIME);
}
- public Long getAsLong() {
+ public Integer getAsLongInt() {
throw invalidConversion(Value.Type.LONG);
}
@@ -61,6 +61,11 @@ public abstract class BaseValue implements Value
getType() + " value cannot be converted to " + newType);
}
+ protected Integer roundToLongInt() {
+ return getAsBigDecimal().setScale(0, BuiltinOperators.ROUND_MODE)
+ .intValueExact();
+ }
+
@Override
public String toString() {
return "Value[" + getType() + "] '" + get() + "'";
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 0cf71c4..2037f34 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java
@@ -17,7 +17,7 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
-import java.math.BigInteger;
+import java.math.RoundingMode;
import java.text.DateFormat;
import java.util.Date;
import java.util.regex.Pattern;
@@ -35,6 +35,9 @@ public class BuiltinOperators
{
private static final String DIV_BY_ZERO = "/ by zero";
+ private static final double MIN_INT = Integer.MIN_VALUE;
+ private static final double MAX_INT = Integer.MAX_VALUE;
+
public static final Value NULL_VAL = new BaseValue() {
@Override public boolean isNull() {
return true;
@@ -48,11 +51,13 @@ public class BuiltinOperators
};
// access seems to like -1 for true and 0 for false (boolean values are
// basically an illusion)
- public static final Value TRUE_VAL = new LongValue(-1L);
- public static final Value FALSE_VAL = new LongValue(0L);
+ public static final Value TRUE_VAL = new LongValue(-1);
+ public static final Value FALSE_VAL = new LongValue(0);
public static final Value EMPTY_STR_VAL = new StringValue("");
public static final Value ZERO_VAL = FALSE_VAL;
+ public static final RoundingMode ROUND_MODE = RoundingMode.HALF_EVEN;
+
private enum CoercionType {
SIMPLE(true, true), GENERAL(false, true), COMPARE(false, false);
@@ -95,7 +100,7 @@ public class BuiltinOperators
double result = -param1.getAsDouble();
return toDateValue(ctx, mathType, result, param1, null);
case LONG:
- return toValue(-param1.getAsLong());
+ return toValue(-param1.getAsLongInt());
case DOUBLE:
return toValue(-param1.getAsDouble());
case STRING:
@@ -126,7 +131,7 @@ public class BuiltinOperators
double result = param1.getAsDouble() + param2.getAsDouble();
return toDateValue(ctx, mathType, result, param1, param2);
case LONG:
- return toValue(param1.getAsLong() + param2.getAsLong());
+ return toValue(param1.getAsLongInt() + param2.getAsLongInt());
case DOUBLE:
return toValue(param1.getAsDouble() + param2.getAsDouble());
case BIG_DEC:
@@ -154,7 +159,7 @@ public class BuiltinOperators
double result = param1.getAsDouble() - param2.getAsDouble();
return toDateValue(ctx, mathType, result, param1, param2);
case LONG:
- return toValue(param1.getAsLong() - param2.getAsLong());
+ return toValue(param1.getAsLongInt() - param2.getAsLongInt());
case DOUBLE:
return toValue(param1.getAsDouble() - param2.getAsDouble());
case BIG_DEC:
@@ -179,7 +184,7 @@ public class BuiltinOperators
// case TIME: break; promoted to double
// case DATE_TIME: break; promoted to double
case LONG:
- return toValue(param1.getAsLong() * param2.getAsLong());
+ return toValue(param1.getAsLongInt() * param2.getAsLongInt());
case DOUBLE:
return toValue(param1.getAsDouble() * param2.getAsDouble());
case BIG_DEC:
@@ -204,8 +209,8 @@ public class BuiltinOperators
// case TIME: break; promoted to double
// case DATE_TIME: break; promoted to double
case LONG:
- long lp1 = param1.getAsLong();
- long lp2 = param2.getAsLong();
+ int lp1 = param1.getAsLongInt();
+ int lp2 = param2.getAsLongInt();
if((lp1 % lp2) == 0) {
return toValue(lp1 / lp2);
}
@@ -223,7 +228,6 @@ public class BuiltinOperators
}
}
- @SuppressWarnings("fallthrough")
public static Value intDivide(Value param1, Value param2) {
if(anyParamIsNull(param1, param2)) {
// null propagation
@@ -232,25 +236,10 @@ public class BuiltinOperators
Value.Type mathType = getMathTypePrecedence(param1, param2,
CoercionType.GENERAL);
-
- boolean wasDouble = false;
- switch(mathType) {
- // case STRING: break; unsupported
- // case DATE: break; promoted to double
- // case TIME: break; promoted to double
- // case DATE_TIME: break; promoted to double
- case LONG:
- return toValue(param1.getAsLong() / param2.getAsLong());
- case DOUBLE:
- wasDouble = true;
- // fallthrough
- case BIG_DEC:
- BigInteger result = getAsBigInteger(param1).divide(
- getAsBigInteger(param2));
- return (wasDouble ? toValue(result.longValue()) : toValue(result));
- default:
+ if(mathType == Value.Type.STRING) {
throw new RuntimeException("Unexpected type " + mathType);
}
+ return toValue(param1.getAsLongInt() / param2.getAsLongInt());
}
public static Value exp(Value param1, Value param2) {
@@ -267,13 +256,12 @@ public class BuiltinOperators
// attempt to convert integral types back to integrals if possible
if((mathType == Value.Type.LONG) && isIntegral(result)) {
- return toValue((long)result);
+ return toValue((int)result);
}
return toValue(result);
}
- @SuppressWarnings("fallthrough")
public static Value mod(Value param1, Value param2) {
if(anyParamIsNull(param1, param2)) {
// null propagation
@@ -283,33 +271,10 @@ public class BuiltinOperators
Value.Type mathType = getMathTypePrecedence(param1, param2,
CoercionType.GENERAL);
- boolean wasDouble = false;
- switch(mathType) {
- // case STRING: break; unsupported
- // case DATE: break; promoted to double
- // case TIME: break; promoted to double
- // case DATE_TIME: break; promoted to double
- case LONG:
- return toValue(param1.getAsLong() % param2.getAsLong());
- case DOUBLE:
- wasDouble = true;
- // fallthrough
- case BIG_DEC:
- BigInteger bi1 = getAsBigInteger(param1);
- BigInteger bi2 = getAsBigInteger(param2).abs();
- if(bi2.signum() == 0) {
- throw new ArithmeticException(DIV_BY_ZERO);
- }
- BigInteger result = bi1.mod(bi2);
- // BigInteger.mod differs from % when using negative values, need to
- // make them consistent
- if((bi1.signum() == -1) && (result.signum() == 1)) {
- result = result.subtract(bi2);
- }
- return (wasDouble ? toValue(result.longValue()) : toValue(result));
- default:
+ if(mathType == Value.Type.STRING) {
throw new RuntimeException("Unexpected type " + mathType);
}
+ return toValue(param1.getAsLongInt() % param2.getAsLongInt());
}
public static Value concat(Value param1, Value param2) {
@@ -577,7 +542,7 @@ public class BuiltinOperators
// case TIME: break; promoted to double
// case DATE_TIME: break; promoted to double
case LONG:
- return param1.getAsLong().compareTo(param2.getAsLong());
+ return param1.getAsLongInt().compareTo(param2.getAsLongInt());
case DOUBLE:
return param1.getAsDouble().compareTo(param2.getAsDouble());
case BIG_DEC:
@@ -596,15 +561,11 @@ public class BuiltinOperators
}
public static Value toValue(int i) {
- return new LongValue((long)i);
+ return new LongValue(i);
}
- public static Value toValue(long s) {
- return new LongValue(s);
- }
-
- public static Value toValue(Long s) {
- return new LongValue(s);
+ public static Value toValue(Integer i) {
+ return new LongValue(i);
}
public static Value toValue(float f) {
@@ -619,14 +580,15 @@ public class BuiltinOperators
return new DoubleValue(s);
}
- public static Value toValue(BigInteger s) {
- return toValue(new BigDecimal(s));
- }
-
public static Value toValue(BigDecimal s) {
return new BigDecimalValue(s);
}
+ public static Value toValue(Value.Type type, double dd, DateFormat fmt) {
+ return toValue(type, new Date(ColumnImpl.fromDateDouble(dd, fmt.getCalendar())),
+ fmt);
+ }
+
public static Value toValue(Value.Type type, Date d, DateFormat fmt) {
switch(type) {
case DATE:
@@ -770,10 +732,9 @@ public class BuiltinOperators
}
static boolean isIntegral(double d) {
- return ((d == Math.rint(d)) && !Double.isInfinite(d) && !Double.isNaN(d));
+ double id = Math.rint(d);
+ return ((d == id) && (d >= MIN_INT) && (d <= MAX_INT) &&
+ !Double.isInfinite(d) && !Double.isNaN(d));
}
- private static BigInteger getAsBigInteger(Value v) {
- return v.getAsBigDecimal().toBigInteger();
- }
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
index 2d3a777..1030772 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
@@ -38,6 +38,13 @@ public class DefaultDateFunctions
private static final double MIN_DATE = -657434.0d;
// max, valid, recognizable date: December 31, 9999 A.D. 23:59:59
private static final double MAX_DATE = 2958465.999988426d;
+
+ private static final long SECONDS_PER_DAY = 24L * 60L * 60L;
+ private static final double DSECONDS_PER_DAY = SECONDS_PER_DAY;
+
+ private static final long SECONDS_PER_HOUR = 60L * 60L;
+ private static final long SECONDS_PER_MINUTE = 60L;
+ private static final long MILLIS_PER_SECOND = 1000L;
private DefaultDateFunctions() {}
@@ -47,48 +54,80 @@ public class DefaultDateFunctions
public static final Function DATE = registerFunc(new Func0("Date") {
@Override
- public boolean isPure() {
- return false;
- }
- @Override
protected Value eval0(EvalContext ctx) {
- DateFormat df = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
- double dd = ColumnImpl.toDateDouble(System.currentTimeMillis(), df.getCalendar());
- // the integral part of the date/time double is the date value. discard
- // the fractional portion
- dd = ((long)dd);
- return BuiltinOperators.toValue(Value.Type.DATE, new Date(), df);
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
+ double dd = dateOnly(currentTimeDouble(fmt));
+ return BuiltinOperators.toValue(Value.Type.DATE, dd, fmt);
}
});
- public static final Function NOW = registerFunc(new Func0("Now") {
+ public static final Function DATEVALUE = registerFunc(new Func1NullIsNull("DateValue") {
@Override
- public boolean isPure() {
- return false;
+ protected Value eval1(EvalContext ctx, Value param1) {
+ Value dv = nonNullToDateValue(ctx, param1);
+ if(dv.getType() == Value.Type.DATE) {
+ return dv;
+ }
+ double dd = dateOnly(dv.getAsDouble());
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
+ return BuiltinOperators.toValue(Value.Type.DATE, dd, fmt);
}
+ });
+
+ public static final Function NOW = registerFunc(new Func0("Now") {
@Override
protected Value eval0(EvalContext ctx) {
- DateFormat df = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE_TIME);
- return BuiltinOperators.toValue(Value.Type.DATE_TIME, new Date(), df);
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE_TIME);
+ return BuiltinOperators.toValue(Value.Type.DATE_TIME, new Date(), fmt);
}
});
public static final Function TIME = registerFunc(new Func0("Time") {
@Override
- public boolean isPure() {
- return false;
+ protected Value eval0(EvalContext ctx) {
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
+ double dd = timeOnly(currentTimeDouble(fmt));
+ return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
+ }
+ });
+
+ public static final Function TIMEVALUE = registerFunc(new Func1NullIsNull("TimeValue") {
+ @Override
+ protected Value eval1(EvalContext ctx, Value param1) {
+ Value dv = nonNullToDateValue(ctx, param1);
+ if(dv.getType() == Value.Type.TIME) {
+ return dv;
+ }
+ double dd = timeOnly(dv.getAsDouble());
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
+ return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
}
+ });
+
+ public static final Function TIMER = registerFunc(new Func0("Timer") {
@Override
protected Value eval0(EvalContext ctx) {
- DateFormat df = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
- double dd = ColumnImpl.toDateDouble(System.currentTimeMillis(), df.getCalendar());
- // the fractional part of the date/time double is the time value. discard
- // the integral portion
- dd = Math.IEEEremainder(dd, 1.0d);
- return BuiltinOperators.toValue(Value.Type.TIME, new Date(), df);
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
+ double dd = timeOnly(currentTimeDouble(fmt)) * DSECONDS_PER_DAY;
+ return BuiltinOperators.toValue(dd);
}
});
+ public static final Function TIMESERIAL = registerFunc(new Func3("TimeSerial") {
+ @Override
+ protected Value eval3(EvalContext ctx, Value param1, Value param2, Value param3) {
+ int hours = param1.getAsLongInt();
+ int minutes = param2.getAsLongInt();
+ int seconds = param3.getAsLongInt();
+
+ long totalSeconds = (hours * SECONDS_PER_HOUR) +
+ (minutes * SECONDS_PER_MINUTE) + seconds;
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
+ double dd = totalSeconds / DSECONDS_PER_DAY;
+ return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
+ }
+ });
+
public static final Function HOUR = registerFunc(new Func1NullIsNull("Hour") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
@@ -168,11 +207,7 @@ public class DefaultDateFunctions
throw new IllegalStateException("Invalid date/time expression '" + param + "'");
}
- Calendar cal =
- ((param instanceof BaseDateValue) ?
- ((BaseDateValue)param).getFormat().getCalendar() :
- BuiltinOperators.getDateFormatForType(ctx, param.getType()).getCalendar());
-
+ Calendar cal = getDateValueFormat(ctx, param).getCalendar();
cal.setTime(param.getAsDateTime(ctx));
return cal;
}
@@ -206,13 +241,34 @@ public class DefaultDateFunctions
return null;
}
- boolean hasDate = (((long)dd) != 0L);
- boolean hasTime = (Math.IEEEremainder(dd, 1.0d) != 0.0d);
+ boolean hasDate = (dateOnly(dd) != 0.0d);
+ boolean hasTime = (timeOnly(dd) != 0.0d);
Value.Type type = (hasDate ? (hasTime ? Value.Type.DATE_TIME : Value.Type.DATE) :
Value.Type.TIME);
- DateFormat df = BuiltinOperators.getDateFormatForType(ctx, type);
- Date d = new Date(ColumnImpl.fromDateDouble(dd, df.getCalendar()));
- return BuiltinOperators.toValue(type, d, df);
+ DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, type);
+ return BuiltinOperators.toValue(type, dd, fmt);
+ }
+
+ private static DateFormat getDateValueFormat(EvalContext ctx, Value param) {
+ return ((param instanceof BaseDateValue) ?
+ ((BaseDateValue)param).getFormat() :
+ BuiltinOperators.getDateFormatForType(ctx, param.getType()));
+ }
+
+ private static double dateOnly(double dd) {
+ // the integral part of the date/time double is the date value. discard
+ // the fractional portion
+ return (long)dd;
+ }
+
+ private static double timeOnly(double dd) {
+ // the fractional part of the date/time double is the time value. discard
+ // the integral portion and convert to seconds
+ return new BigDecimal(dd).remainder(BigDecimal.ONE).doubleValue();
+ }
+
+ private static double currentTimeDouble(DateFormat fmt) {
+ return ColumnImpl.toDateDouble(System.currentTimeMillis(), fmt.getCalendar());
}
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
index 9584424..34f0bf6 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
@@ -17,7 +17,6 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -37,7 +36,6 @@ public class DefaultFunctions
new HashMap<String,Function>();
private static final char NON_VAR_SUFFIX = '$';
- static final RoundingMode DEFAULT_ROUND_MODE = RoundingMode.HALF_EVEN;
static {
// load all default functions
@@ -58,11 +56,6 @@ public class DefaultFunctions
private final int _minParams;
private final int _maxParams;
- protected BaseFunction(String name)
- {
- this(name, 0, Integer.MAX_VALUE);
- }
-
protected BaseFunction(String name, int minParams, int maxParams)
{
_name = name;
@@ -111,6 +104,12 @@ public class DefaultFunctions
super(name, 0, 0);
}
+ @Override
+ public boolean isPure() {
+ // 0-arg functions are usually not pure
+ return false;
+ }
+
public final Value eval(EvalContext ctx, Value... params) {
try {
validateNumParams(params);
@@ -202,6 +201,10 @@ public class DefaultFunctions
public static abstract class FuncVar extends BaseFunction
{
+ protected FuncVar(String name) {
+ super(name, 0, Integer.MAX_VALUE);
+ }
+
protected FuncVar(String name, int minParams, int maxParams) {
super(name, minParams, maxParams);
}
@@ -235,8 +238,8 @@ public class DefaultFunctions
(param1.getAsString().length() == 0)) {
return BuiltinOperators.ZERO_VAL;
}
- long lv = param1.getAsLong();
- return BuiltinOperators.toValue(Long.toHexString(lv).toUpperCase());
+ int lv = param1.getAsLongInt();
+ return BuiltinOperators.toValue(Integer.toHexString(lv).toUpperCase());
}
});
@@ -257,6 +260,33 @@ public class DefaultFunctions
}
});
+ public static final Function CHOOSE = registerFunc(new FuncVar("Choose", 1, Integer.MAX_VALUE) {
+ @Override
+ protected Value evalVar(EvalContext ctx, Value[] params) {
+ Value param1 = params[0];
+ int idx = param1.getAsLongInt();
+ if((idx < 1) || (idx >= params.length)) {
+ return BuiltinOperators.NULL_VAL;
+ }
+ return params[idx];
+ }
+ });
+
+ public static final Function SWITCH = registerFunc(new FuncVar("Switch") {
+ @Override
+ protected Value evalVar(EvalContext ctx, Value[] params) {
+ if((params.length % 2) != 0) {
+ throw new IllegalStateException("Odd number of parameters");
+ }
+ for(int i = 0; i < params.length; i+=2) {
+ if(params[i].getAsBoolean()) {
+ return params[i + 1];
+ }
+ }
+ return BuiltinOperators.NULL_VAL;
+ }
+ });
+
public static final Function OCT = registerStringFunc(new Func1NullIsNull("Oct") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
@@ -264,8 +294,8 @@ public class DefaultFunctions
(param1.getAsString().length() == 0)) {
return BuiltinOperators.ZERO_VAL;
}
- long lv = param1.getAsLong();
- return BuiltinOperators.toValue(Long.toOctalString(lv));
+ int lv = param1.getAsLongInt();
+ return BuiltinOperators.toValue(Integer.toOctalString(lv));
}
});
@@ -280,7 +310,7 @@ public class DefaultFunctions
public static final Function CBYTE = registerFunc(new Func1("CByte") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- long lv = roundToLong(param1);
+ int lv = param1.getAsLongInt();
if((lv < 0) || (lv > 255)) {
throw new IllegalStateException("Byte code '" + lv + "' out of range ");
}
@@ -292,7 +322,7 @@ public class DefaultFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
BigDecimal bd = param1.getAsBigDecimal();
- bd = bd.setScale(4, DEFAULT_ROUND_MODE);
+ bd = bd.setScale(4, BuiltinOperators.ROUND_MODE);
return BuiltinOperators.toValue(bd);
}
});
@@ -326,7 +356,7 @@ public class DefaultFunctions
public static final Function CINT = registerFunc(new Func1("CInt") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- long lv = roundToLong(param1);
+ int lv = param1.getAsLongInt();
if((lv < Short.MIN_VALUE) || (lv > Short.MAX_VALUE)) {
throw new IllegalStateException("Int value '" + lv + "' out of range ");
}
@@ -337,10 +367,7 @@ public class DefaultFunctions
public static final Function CLNG = registerFunc(new Func1("CLng") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- long lv = roundToLong(param1);
- if((lv < Integer.MIN_VALUE) || (lv > Integer.MAX_VALUE)) {
- throw new IllegalStateException("Long value '" + lv + "' out of range ");
- }
+ int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(lv);
}
});
@@ -386,14 +413,79 @@ public class DefaultFunctions
}
});
+ public static final Function VARTYPE = registerFunc(new Func1("VarType") {
+ @Override
+ protected Value eval1(EvalContext ctx, Value param1) {
+ Value.Type type = param1.getType();
+ int vType = 0;
+ switch(type) {
+ case NULL:
+ // vbNull
+ vType = 1;
+ break;
+ case STRING:
+ // vbString
+ vType = 8;
+ break;
+ case DATE:
+ case TIME:
+ case DATE_TIME:
+ // vbDate
+ vType = 7;
+ break;
+ case LONG:
+ // vbLong
+ vType = 3;
+ break;
+ case DOUBLE:
+ // vbDouble
+ vType = 5;
+ break;
+ case BIG_DEC:
+ // vbDecimal
+ vType = 14;
+ break;
+ default:
+ throw new RuntimeException("Unknown type " + type);
+ }
+ return BuiltinOperators.toValue(vType);
+ }
+ });
- private static long roundToLong(Value param) {
- if(param.getType().isIntegral()) {
- return param.getAsLong();
+ public static final Function TYPENAME = registerFunc(new Func1("TypeName") {
+ @Override
+ protected Value eval1(EvalContext ctx, Value param1) {
+ Value.Type type = param1.getType();
+ String tName = null;
+ switch(type) {
+ case NULL:
+ tName = "Null";
+ break;
+ case STRING:
+ tName = "String";
+ break;
+ case DATE:
+ case TIME:
+ case DATE_TIME:
+ tName = "Date";
+ break;
+ case LONG:
+ tName = "Long";
+ break;
+ case DOUBLE:
+ tName = "Double";
+ break;
+ case BIG_DEC:
+ tName = "Decimal";
+ break;
+ default:
+ throw new RuntimeException("Unknown type " + type);
+ }
+ return BuiltinOperators.toValue(tName);
}
- return param.getAsBigDecimal().setScale(0, DEFAULT_ROUND_MODE)
- .longValue();
- }
+ });
+
+
// https://www.techonthenet.com/access/functions/
// https://support.office.com/en-us/article/Access-Functions-by-category-b8b136c3-2716-4d39-94a2-658ce330ed83
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 2bd3651..6f71797 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
@@ -49,7 +49,7 @@ public class DefaultNumberFunctions
double result = Math.abs(param1.getAsDouble());
return BuiltinOperators.toDateValue(ctx, mathType, result, param1, null);
case LONG:
- return BuiltinOperators.toValue(Math.abs(param1.getAsLong()));
+ return BuiltinOperators.toValue(Math.abs(param1.getAsLongInt()));
case DOUBLE:
return BuiltinOperators.toValue(Math.abs(param1.getAsDouble()));
case STRING:
@@ -88,7 +88,7 @@ public class DefaultNumberFunctions
if(param1.getType().isIntegral()) {
return param1;
}
- return BuiltinOperators.toValue(param1.getAsDouble().longValue());
+ return BuiltinOperators.toValue(param1.getAsDouble().intValue());
}
});
@@ -98,7 +98,7 @@ public class DefaultNumberFunctions
if(param1.getType().isIntegral()) {
return param1;
}
- return BuiltinOperators.toValue((long)Math.floor(param1.getAsDouble()));
+ return BuiltinOperators.toValue((int)Math.floor(param1.getAsDouble()));
}
});
@@ -116,7 +116,7 @@ public class DefaultNumberFunctions
}
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
- Long seed = ((params.length > 0) ? params[0].getAsLong() : null);
+ Integer seed = ((params.length > 0) ? params[0].getAsLongInt() : null);
return BuiltinOperators.toValue(ctx.getRandom(seed).nextFloat());
}
});
@@ -133,9 +133,10 @@ public class DefaultNumberFunctions
}
int scale = 0;
if(params.length > 1) {
- scale = params[1].getAsLong().intValue();
+ scale = params[1].getAsLongInt();
}
- BigDecimal bd = param1.getAsBigDecimal().setScale(scale, DEFAULT_ROUND_MODE);
+ BigDecimal bd = param1.getAsBigDecimal()
+ .setScale(scale, BuiltinOperators.ROUND_MODE);
return BuiltinOperators.toValue(bd);
}
});
@@ -145,7 +146,7 @@ public class DefaultNumberFunctions
protected Value eval1(EvalContext ctx, Value param1) {
int signum = 0;
if(param1.getType().isIntegral()) {
- long lv = param1.getAsLong();
+ int lv = param1.getAsLongInt();
signum = ((lv > 0) ? 1 : ((lv < 0) ? -1 : 0));
} else {
signum = param1.getAsBigDecimal().signum();
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
index 278ea4e..96c6115 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
@@ -44,7 +44,7 @@ public class DefaultTextFunctions
if(len == 0) {
throw new IllegalStateException("No characters in string");
}
- long lv = str.charAt(0);
+ int lv = str.charAt(0);
if((lv < 0) || (lv > 255)) {
throw new IllegalStateException("Character code '" + lv +
"' out of range ");
@@ -61,7 +61,7 @@ public class DefaultTextFunctions
if(len == 0) {
throw new IllegalStateException("No characters in string");
}
- long lv = str.charAt(0);
+ int lv = str.charAt(0);
return BuiltinOperators.toValue(lv);
}
});
@@ -69,12 +69,12 @@ public class DefaultTextFunctions
public static final Function CHR = registerStringFunc(new Func1("Chr") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- long lv = param1.getAsLong();
+ int lv = param1.getAsLongInt();
if((lv < 0) || (lv > 255)) {
throw new IllegalStateException("Character code '" + lv +
"' out of range ");
}
- char[] cs = Character.toChars((int)lv);
+ char[] cs = Character.toChars(lv);
return BuiltinOperators.toValue(new String(cs));
}
});
@@ -82,8 +82,8 @@ public class DefaultTextFunctions
public static final Function CHRW = registerStringFunc(new Func1("ChrW") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- long lv = param1.getAsLong();
- char[] cs = Character.toChars((int)lv);
+ int lv = param1.getAsLongInt();
+ char[] cs = Character.toChars(lv);
return BuiltinOperators.toValue(new String(cs));
}
});
@@ -107,7 +107,7 @@ public class DefaultTextFunctions
int start = 0;
if(params.length > 2) {
// 1 based offsets
- start = params[0].getAsLong().intValue() - 1;
+ start = params[0].getAsLongInt() - 1;
++idx;
}
Value param1 = params[idx++];
@@ -169,7 +169,7 @@ public class DefaultTextFunctions
return BuiltinOperators.toValue(start + 1);
}
if(params.length > 2) {
- start = params[2].getAsLong().intValue();
+ start = params[2].getAsLongInt();
if(start == -1) {
start = s1Len;
}
@@ -215,7 +215,7 @@ public class DefaultTextFunctions
return param1;
}
String str = param1.getAsString();
- int len = (int)Math.min(str.length(), param2.getAsLong());
+ int len = Math.min(str.length(), param2.getAsLongInt());
return BuiltinOperators.toValue(str.substring(0, len));
}
});
@@ -228,7 +228,7 @@ public class DefaultTextFunctions
}
String str = param1.getAsString();
int strLen = str.length();
- int len = (int)Math.min(strLen, param2.getAsLong());
+ int len = Math.min(strLen, param2.getAsLongInt());
return BuiltinOperators.toValue(str.substring(strLen - len, strLen));
}
});
@@ -243,9 +243,9 @@ public class DefaultTextFunctions
String str = param1.getAsString();
int strLen = str.length();
// 1 based offsets
- int start = (int)Math.max(strLen, params[1].getAsLong() - 1);
+ int start = Math.max(strLen, params[1].getAsLongInt() - 1);
int len = Math.max(
- ((params.length > 2) ? params[2].getAsLong().intValue() : strLen),
+ ((params.length > 2) ? params[2].getAsLongInt() : strLen),
(strLen - start));
return BuiltinOperators.toValue(str.substring(start, start + len));
}
@@ -286,7 +286,7 @@ public class DefaultTextFunctions
public static final Function SPACE = registerStringFunc(new Func1("Space") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
- int lv = param1.getAsLong().intValue();
+ int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(nchars(lv, ' '));
}
});
@@ -317,7 +317,7 @@ public class DefaultTextFunctions
if(param1.isNull() || param2.isNull()) {
return BuiltinOperators.NULL_VAL;
}
- int lv = param1.getAsLong().intValue();
+ int lv = param1.getAsLongInt();
char c = (char)(param2.getAsString().charAt(0) % 256);
return BuiltinOperators.toValue(nchars(lv, c));
}
@@ -359,7 +359,7 @@ public class DefaultTextFunctions
}
private static boolean doIgnoreCase(Value paramCmp) {
- int cmpType = paramCmp.getAsLong().intValue();
+ int cmpType = paramCmp.getAsLongInt();
switch(cmpType) {
case -1:
// vbUseCompareOption -> default is binary
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java
index 563c4bf..0efd21a 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java
@@ -394,7 +394,7 @@ class ExpressionTokenizer
// what number type to use here?
Object num = (isFp ?
(Number)Double.valueOf(numStr) :
- (Number)Long.valueOf(numStr));
+ (Number)Integer.valueOf(numStr));
foundNum = true;
return new Token(TokenType.LITERAL, num, numStr,
(isFp ? Value.Type.DOUBLE : Value.Type.LONG));
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java
index ec464ec..9e65c5e 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java
@@ -1280,7 +1280,7 @@ public class Expressionator
case DATE_TIME:
return new DateTimeValue((Date)value, sdf);
case LONG:
- return new LongValue((Long)value);
+ return new LongValue((Integer)value);
case DOUBLE:
return new DoubleValue((Double)value);
case BIG_DEC:
@@ -1953,7 +1953,7 @@ public class Expressionator
case DATE_TIME:
return val.getAsDateTime(ctx);
case LONG:
- return val.getAsLong();
+ return val.getAsLongInt();
case DOUBLE:
return val.getAsDouble();
case BIG_DEC:
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java
index 16ac83d..217a5ee 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java
@@ -24,9 +24,9 @@ import java.math.BigDecimal;
*/
public class LongValue extends BaseNumericValue
{
- private final Long _val;
+ private final Integer _val;
- public LongValue(Long val)
+ public LongValue(Integer val)
{
_val = val;
}
@@ -50,7 +50,7 @@ public class LongValue extends BaseNumericValue
}
@Override
- public Long getAsLong() {
+ public Integer getAsLongInt() {
return _val;
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
index 6133139..be3cfff 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
@@ -54,8 +54,8 @@ public class StringValue extends BaseValue
}
@Override
- public Long getAsLong() {
- return getNumber().longValue();
+ public Integer getAsLongInt() {
+ return roundToLongInt();
}
@Override
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
index d422b72..ed1aa23 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
@@ -45,8 +45,8 @@ public class DefaultFunctionsTest extends TestCase
{
assertEquals("foo", eval("=IIf(10 > 1, \"foo\", \"bar\")"));
assertEquals("bar", eval("=IIf(10 < 1, \"foo\", \"bar\")"));
- assertEquals(102L, eval("=Asc(\"foo\")"));
- assertEquals(9786L, eval("=AscW(\"\u263A\")"));
+ assertEquals(102, eval("=Asc(\"foo\")"));
+ assertEquals(9786, eval("=AscW(\"\u263A\")"));
assertEquals("f", eval("=Chr(102)"));
assertEquals("\u263A", eval("=ChrW(9786)"));
assertEquals("263A", eval("=Hex(9786)"));
@@ -60,16 +60,16 @@ public class DefaultFunctionsTest extends TestCase
assertEquals(" 9786", eval("=Str(9786)"));
assertEquals("-42", eval("=Str(-42)"));
- assertEquals(-1L, eval("=CBool(\"1\")"));
- assertEquals(13L, eval("=CByte(\"13\")"));
- assertEquals(14L, eval("=CByte(\"13.7\")"));
+ assertEquals(-1, eval("=CBool(\"1\")"));
+ assertEquals(13, eval("=CByte(\"13\")"));
+ assertEquals(14, eval("=CByte(\"13.7\")"));
assertEquals(new BigDecimal("57.1235"), eval("=CCur(\"57.12346\")"));
assertEquals(new Double("57.12345"), eval("=CDbl(\"57.12345\")"));
assertEquals(new BigDecimal("57.123456789"), eval("=CDec(\"57.123456789\")"));
- assertEquals(513L, eval("=CInt(\"513\")"));
- assertEquals(514L, eval("=CInt(\"513.7\")"));
- assertEquals(345513L, eval("=CLng(\"345513\")"));
- assertEquals(345514L, eval("=CLng(\"345513.7\")"));
+ assertEquals(513, eval("=CInt(\"513\")"));
+ assertEquals(514, eval("=CInt(\"513.7\")"));
+ assertEquals(345513, eval("=CLng(\"345513\")"));
+ assertEquals(345514, eval("=CLng(\"345513.7\")"));
assertEquals(new Float("57.12345").doubleValue(),
eval("=CSng(\"57.12345\")"));
assertEquals("9786", eval("=CStr(9786)"));
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 6475c4e..f0e5397 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
@@ -16,6 +16,7 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
+import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
@@ -131,7 +132,7 @@ public class ExpressionatorTest extends TestCase
public void testSimpleMathExpressions() throws Exception
{
- for(long i = -10L; i <= 10L; ++i) {
+ for(int i = -10; i <= 10; ++i) {
assertEquals(-i, eval("=-(" + i + ")"));
}
@@ -139,8 +140,8 @@ public class ExpressionatorTest extends TestCase
assertEquals(-i, eval("=-(" + i + ")"));
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
assertEquals((i + j), eval("=" + i + " + " + j));
}
}
@@ -151,8 +152,8 @@ public class ExpressionatorTest extends TestCase
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
assertEquals((i - j), eval("=" + i + " - " + j));
}
}
@@ -163,8 +164,8 @@ public class ExpressionatorTest extends TestCase
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
assertEquals((i * j), eval("=" + i + " * " + j));
}
}
@@ -175,8 +176,8 @@ public class ExpressionatorTest extends TestCase
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
if(j == 0L) {
evalFail("=" + i + " \\ " + j, ArithmeticException.class);
} else {
@@ -187,17 +188,18 @@ public class ExpressionatorTest extends TestCase
for(double i : DBLS) {
for(double j : DBLS) {
- if((long)j == 0L) {
+ if(roundToLongInt(j) == 0) {
evalFail("=" + i + " \\ " + j, ArithmeticException.class);
} else {
- assertEquals(((long)i / (long)j), eval("=" + i + " \\ " + j));
+ assertEquals((roundToLongInt(i) / roundToLongInt(j)),
+ eval("=" + i + " \\ " + j));
}
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
- if(j == 0L) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
+ if(j == 0) {
evalFail("=" + i + " Mod " + j, ArithmeticException.class);
} else {
assertEquals((i % j), eval("=" + i + " Mod " + j));
@@ -207,22 +209,23 @@ public class ExpressionatorTest extends TestCase
for(double i : DBLS) {
for(double j : DBLS) {
- if((long)j == 0L) {
+ if(roundToLongInt(j) == 0) {
evalFail("=" + i + " Mod " + j, ArithmeticException.class);
} else {
- assertEquals(((long)i % (long)j), eval("=" + i + " Mod " + j));
+ assertEquals((roundToLongInt(i) % roundToLongInt(j)),
+ eval("=" + i + " Mod " + j));
}
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
- if(j == 0L) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
+ if(j == 0) {
evalFail("=" + i + " / " + j, ArithmeticException.class);
} else {
double result = (double)i / (double)j;
- if((long)result == result) {
- assertEquals((long)result, eval("=" + i + " / " + j));
+ if((int)result == result) {
+ assertEquals((int)result, eval("=" + i + " / " + j));
} else {
assertEquals(result, eval("=" + i + " / " + j));
}
@@ -240,11 +243,11 @@ public class ExpressionatorTest extends TestCase
}
}
- for(long i = -10L; i <= 10L; ++i) {
- for(long j = -10L; j <= 10L; ++j) {
+ for(int i = -10; i <= 10; ++i) {
+ for(int j = -10; j <= 10; ++j) {
double result = Math.pow(i, j);
- if((long)result == result) {
- assertEquals((long)result, eval("=" + i + " ^ " + j));
+ if((int)result == result) {
+ assertEquals((int)result, eval("=" + i + " ^ " + j));
} else {
assertEquals(result, eval("=" + i + " ^ " + j));
}
@@ -261,8 +264,8 @@ public class ExpressionatorTest extends TestCase
assertEquals("12foo", eval("=12 + \"foo\""));
assertEquals("foo12", eval("=\"foo\" + 12"));
- assertEquals(37L, eval("=\"25\" + 12"));
- assertEquals(37L, eval("=12 + \"25\""));
+ assertEquals(37, eval("=\"25\" + 12"));
+ assertEquals(37, eval("=12 + \"25\""));
evalFail(("=12 - \"foo\""), RuntimeException.class);
evalFail(("=\"foo\" - 12"), RuntimeException.class);
@@ -273,7 +276,7 @@ public class ExpressionatorTest extends TestCase
assertEquals("25foo12", eval("=\"25foo\" + 12"));
assertEquals(new Date(1485579600000L), eval("=#1/1/2017# + 27"));
- assertEquals(128208L, eval("=#1/1/2017# * 3"));
+ assertEquals(128208, eval("=#1/1/2017# * 3"));
}
public void testLikeExpression() throws Exception
@@ -331,6 +334,11 @@ public class ExpressionatorTest extends TestCase
return (Boolean)expr.eval(new TestEvalContext(BuiltinOperators.toValue(thisVal)));
}
+ static int roundToLongInt(double d) {
+ return new BigDecimal(d).setScale(0, BuiltinOperators.ROUND_MODE)
+ .intValueExact();
+ }
+
private static final class TestParseContext implements Expressionator.ParseContext
{
public TemporalConfig getTemporalConfig() {
@@ -384,7 +392,7 @@ public class ExpressionatorTest extends TestCase
throw new UnsupportedOperationException();
}
- public Random getRandom(Long seed) {
+ public Random getRandom(Integer seed) {
if(seed == null) {
if(_defRnd == null) {
_defRnd = new Random(System.currentTimeMillis());