Permalink
Browse files

[#1334] Fix inaccurate simulation of TRUNC(number, decimals) for Derby

  • Loading branch information...
1 parent e53a757 commit c1ae59160b35a7b1d4a6c60fd7a59dff3033201f @lukaseder lukaseder committed May 11, 2012
@@ -603,6 +603,15 @@ public void testFunctionsOnNumbers() throws Exception {
Field<Double> f3d = floor(-2.0);
Field<Double> f4d = ceil(-2.0);
+ Field<Float> f1e = round(0.0f);
+ Field<Float> f2e = round(0.0f, 2);
+ Field<Float> f3e = floor(0.0f);
+ Field<Float> f4e = ceil(0.0f);
+ Field<Float> f1f = round(0.0f);
+ Field<Float> f2f = round(0.0f, 2);
+ Field<Float> f3f = floor(0.0f);
+ Field<Float> f4f = ceil(0.0f);
+
// Some arbitrary checks on having multiple select clauses
Record record =
create().select(f1a)
@@ -611,7 +620,10 @@ public void testFunctionsOnNumbers() throws Exception {
.select(f5a, f6a, f7a)
.select(f1b, f2b, f3b, f4b, f6b, f6b, f7b)
.select(f1c, f2c, f3c, f4c)
- .select(f1d, f2d, f3d, f4d).fetchOne();
+ .select(f1d, f2d, f3d, f4d)
+ .select(f1e, f2e, f3e, f4e)
+ .select(f1f, f2f, f3f, f4f)
+ .fetchOne();
assertNotNull(record);
assertEquals("1.0", record.getValueAsString(f1a));
@@ -640,6 +652,16 @@ public void testFunctionsOnNumbers() throws Exception {
assertEquals("-2.0", record.getValueAsString(f3d));
assertEquals("-2.0", record.getValueAsString(f4d));
+ assertEquals("0.0", record.getValueAsString(f1e));
+ assertEquals("0.0", record.getValueAsString(f2e));
+ assertEquals("0.0", record.getValueAsString(f3e));
+ assertEquals("0.0", record.getValueAsString(f4e));
+
+ assertEquals("0.0", record.getValueAsString(f1f));
+ assertEquals("0.0", record.getValueAsString(f2f));
+ assertEquals("0.0", record.getValueAsString(f3f));
+ assertEquals("0.0", record.getValueAsString(f4f));
+
// Greatest and least
record = create().select(
greatest(1, 2, 3, 4),
@@ -35,12 +35,15 @@
*/
package org.jooq.impl;
+import static java.math.BigDecimal.TEN;
import static org.jooq.impl.Factory.field;
import static org.jooq.impl.Factory.inline;
import static org.jooq.impl.Factory.one;
import static org.jooq.impl.Factory.zero;
+import static org.jooq.impl.Util.extractVal;
import java.math.BigDecimal;
+import java.math.MathContext;
import org.jooq.Configuration;
import org.jooq.Field;
@@ -82,10 +85,18 @@
private final Field<T> getNumericFunction(Configuration configuration) {
switch (configuration.getDialect()) {
case ASE:
-
- // This calculation is inaccurate for Derby
case DERBY: {
- Field<BigDecimal> power = Factory.power(inline(new BigDecimal("10.0")), decimals);
+ Field<BigDecimal> power;
+
+ // [#1334] if possible, calculate the power in Java to prevent
+ // inaccurate arithmetics in the Derby database
+ Integer decimalsVal = extractVal(decimals);
+ if (decimalsVal != null) {
+ power = inline(TEN.pow(decimalsVal, MathContext.DECIMAL128));
+ }
+ else {
+ power = Factory.power(inline(TEN), decimals);
+ }
return Factory.decode()
.when(field.sign().greaterOrEqual(zero()),
@@ -1028,4 +1028,23 @@ static final String convertBytesToPostgresOctal(byte[] binary) {
return field.cast(String.class);
}
}
+
+ /**
+ * Utility method to check whether a field is a {@link Param}
+ */
+ static final boolean isVal(Field<?> field) {
+ return field instanceof Param;
+ }
+
+ /**
+ * Utility method to extract a value from a field
+ */
+ static final <T> T extractVal(Field<T> field) {
+ if (isVal(field)) {
+ return ((Param<T>) field).getValue();
+ }
+ else {
+ return null;
+ }
+ }
}

0 comments on commit c1ae591

Please sign in to comment.