From f930cdb42bfd5c888956281bade21dadb823d1b7 Mon Sep 17 00:00:00 2001 From: guojn1 Date: Wed, 20 Aug 2025 15:30:41 +0800 Subject: [PATCH] [fix][runtime] Arithmetric is compatible with different data types --- .../expr/runtime/op/arithmetic/DivOp.java | 2 +- .../runtime/op/arithmetic/DivOpFactory.java | 247 ++++++++++++++++++ .../expr/runtime/op/arithmetic/MulOp.java | 2 +- .../runtime/op/arithmetic/MulOpFactory.java | 233 +++++++++++++++++ .../expr/runtime/op/arithmetic/SubOp.java | 2 +- .../runtime/op/arithmetic/SubOpFactory.java | 233 +++++++++++++++++ 6 files changed, 716 insertions(+), 3 deletions(-) create mode 100644 runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOpFactory.java create mode 100644 runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOpFactory.java create mode 100644 runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOpFactory.java diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOp.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOp.java index 2ad44c14..ffed4f41 100644 --- a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOp.java +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOp.java @@ -25,7 +25,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; -@Operators +//@Operators abstract class DivOp extends BinaryNumericOp { private static final long serialVersionUID = 5716662239372671267L; diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOpFactory.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOpFactory.java new file mode 100644 index 00000000..40c5200c --- /dev/null +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/DivOpFactory.java @@ -0,0 +1,247 @@ +/* + * Copyright 2021 DataCanvas + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dingodb.expr.runtime.op.arithmetic; + +import io.dingodb.expr.common.type.Type; +import io.dingodb.expr.common.type.Types; +import io.dingodb.expr.runtime.ExprConfig; +import io.dingodb.expr.runtime.op.BinaryOp; +import io.dingodb.expr.runtime.op.OpKey; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class DivOpFactory extends DivOp { + private static final long serialVersionUID = -6469594318220686032L; + public static final DivOpFactory INSTANCE = new DivOpFactory(); + private final Map opMap = new HashMap(); + private static final DivAnyAny divAnyAny = new DivAnyAny(); + + private DivOpFactory() { + this.opMap.put(this.keyOf(Types.FLOAT, Types.FLOAT), new DivFloatFloat()); + this.opMap.put(this.keyOf(Types.DECIMAL, Types.DECIMAL), new DivDecimalDecimal()); + this.opMap.put(this.keyOf(Types.INT, Types.INT), new DivIntInt()); + this.opMap.put(this.keyOf(Types.LONG, Types.LONG), new DivLongLong()); + this.opMap.put(this.keyOf(Types.DOUBLE, Types.DOUBLE), new DivDoubleDouble()); + } + + public BinaryOp getOp(OpKey key) { + return (BinaryOp)this.opMap.get(key); + } + + public static final class DivFloatFloat extends DivOp { + private static final long serialVersionUID = 4754785335734613362L; + + public DivFloatFloat() { + } + + protected Float evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = divAnyAny.evalNonNullValue(value0, value1, config); + if (val == null) { + return null; + } + return val instanceof Float ? (Float)val : (new BigDecimal(val.toString())).floatValue(); + } + + public Type getType() { + return Types.FLOAT; + } + + public OpKey getKey() { + return this.keyOf(Types.FLOAT, Types.FLOAT); + } + } + + public static final class DivDecimalDecimal extends DivOp { + private static final long serialVersionUID = -1353437752763383432L; + + public DivDecimalDecimal() { + } + + protected BigDecimal evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = divAnyAny.evalNonNullValue(value0, value1, config); + if (val == null) { + return null; + } + return val instanceof BigDecimal ? (BigDecimal)val : new BigDecimal(val.toString()); + } + + public Type getType() { + return Types.DECIMAL; + } + + public OpKey getKey() { + return this.keyOf(Types.DECIMAL, Types.DECIMAL); + } + } + + public static final class DivIntInt extends DivOp { + private static final long serialVersionUID = 1969065905399287590L; + + public DivIntInt() { + } + + protected Double evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = divAnyAny.evalNonNullValue(value0, value1, config); + if (val == null) { + return null; + } + return val instanceof Double ? (Double)val : (new BigDecimal(val.toString())).doubleValue(); + } + + public Type getType() { + return Types.DOUBLE; + } + + public OpKey getKey() { + return this.keyOf(Types.INT, Types.INT); + } + } + + public static final class DivLongLong extends DivOp { + private static final long serialVersionUID = -1062167998258980495L; + + public DivLongLong() { + } + + protected Double evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = divAnyAny.evalNonNullValue(value0, value1, config); + if (val == null) { + return null; + } + return val instanceof Double ? (Double)val : (new BigDecimal(val.toString())).doubleValue(); + } + + public Type getType() { + return Types.DOUBLE; + } + + public OpKey getKey() { + return this.keyOf(Types.LONG, Types.LONG); + } + } + + public static final class DivDoubleDouble extends DivOp { + private static final long serialVersionUID = -4438406023339517679L; + + public DivDoubleDouble() { + } + + protected Double evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = divAnyAny.evalNonNullValue(value0, value1, config); + if (val == null) { + return null; + } + return val instanceof Double ? (Double)val : (new BigDecimal(val.toString())).doubleValue(); + } + + public Type getType() { + return Types.DOUBLE; + } + + public OpKey getKey() { + return this.keyOf(Types.DOUBLE, Types.DOUBLE); + } + } + + public static final class DivAnyAny extends DivOp { + private static final long serialVersionUID = -4438406023339517679L; + + public DivAnyAny() { + } + + protected Object evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + if (value0 instanceof Integer) { + int value0Tmp = (int) value0; + if (value1 instanceof Integer) { + return div(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return div(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return div(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return div(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return div(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Long) { + long value0Tmp = (long) value0; + if (value1 instanceof Integer) { + return div(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return div(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return div(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return div(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return div(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Double) { + double value0Tmp = (double) value0; + if (value1 instanceof Integer) { + return div(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return div(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return div(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return div(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return div(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Float) { + float value0Tmp = (float) value0; + if (value1 instanceof Integer) { + return div(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return div(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return div(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return div(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return div(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof BigDecimal) { + BigDecimal value0Tmp = (BigDecimal) value0; + try { + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return div(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + try { + BigDecimal value0Tmp = new BigDecimal(value0.toString()); + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return div(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + + public Type getType() { + return Types.ANY; + } + + public OpKey getKey() { + return this.keyOf(Types.ANY, Types.ANY); + } + } +} diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOp.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOp.java index a5ec9928..3be05c16 100644 --- a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOp.java +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOp.java @@ -23,7 +23,7 @@ import java.math.BigDecimal; -@Operators +//@Operators abstract class MulOp extends BinaryNumericOp { private static final long serialVersionUID = 4677892788590745542L; diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOpFactory.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOpFactory.java new file mode 100644 index 00000000..d9721406 --- /dev/null +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/MulOpFactory.java @@ -0,0 +1,233 @@ +/* + * Copyright 2021 DataCanvas + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dingodb.expr.runtime.op.arithmetic; + +import io.dingodb.expr.common.type.Type; +import io.dingodb.expr.common.type.Types; +import io.dingodb.expr.runtime.ExprConfig; +import io.dingodb.expr.runtime.op.BinaryOp; +import io.dingodb.expr.runtime.op.OpKey; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class MulOpFactory extends MulOp { + private static final long serialVersionUID = -6877045657103337642L; + public static final MulOpFactory INSTANCE = new MulOpFactory(); + private final Map opMap = new HashMap(); + private static final MulAnyAny mulAnyAny = new MulAnyAny(); + + private MulOpFactory() { + this.opMap.put(this.keyOf(Types.FLOAT, Types.FLOAT), new MulFloatFloat()); + this.opMap.put(this.keyOf(Types.DECIMAL, Types.DECIMAL), new MulDecimalDecimal()); + this.opMap.put(this.keyOf(Types.INT, Types.INT), new MulIntInt()); + this.opMap.put(this.keyOf(Types.LONG, Types.LONG), new MulLongLong()); + this.opMap.put(this.keyOf(Types.DOUBLE, Types.DOUBLE), new MulDoubleDouble()); + } + + public BinaryOp getOp(OpKey key) { + return (BinaryOp)this.opMap.get(key); + } + + public static final class MulFloatFloat extends MulOp { + private static final long serialVersionUID = 6449699704213092098L; + + public MulFloatFloat() { + } + + protected Float evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = mulAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Float ? (Float)val : (new BigDecimal(val.toString())).floatValue(); + } + + public Type getType() { + return Types.FLOAT; + } + + public OpKey getKey() { + return this.keyOf(Types.FLOAT, Types.FLOAT); + } + } + + public static final class MulDecimalDecimal extends MulOp { + private static final long serialVersionUID = -3523883902432545426L; + + public MulDecimalDecimal() { + } + + protected BigDecimal evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = mulAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof BigDecimal ? (BigDecimal)val : new BigDecimal(val.toString()); + } + + public Type getType() { + return Types.DECIMAL; + } + + public OpKey getKey() { + return this.keyOf(Types.DECIMAL, Types.DECIMAL); + } + } + + public static final class MulIntInt extends MulOp { + private static final long serialVersionUID = 8731086743972245127L; + + public MulIntInt() { + } + + protected Integer evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = mulAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Integer ? (Integer) val : new BigDecimal(val.toString()).intValue(); + } + + public Type getType() { + return Types.INT; + } + + public OpKey getKey() { + return this.keyOf(Types.INT, Types.INT); + } + } + + public static final class MulLongLong extends MulOp { + private static final long serialVersionUID = -5301176117146093072L; + + public MulLongLong() { + } + + protected Long evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = mulAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Long ? (Long) val : new BigDecimal(val.toString()).longValue(); + } + + public Type getType() { + return Types.LONG; + } + + public OpKey getKey() { + return this.keyOf(Types.LONG, Types.LONG); + } + } + + public static final class MulDoubleDouble extends MulOp { + private static final long serialVersionUID = -3529870722382357307L; + + public MulDoubleDouble() { + } + + protected Double evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = mulAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Double ? (Double) val : new BigDecimal(val.toString()).doubleValue(); + } + + public Type getType() { + return Types.DOUBLE; + } + + public OpKey getKey() { + return this.keyOf(Types.DOUBLE, Types.DOUBLE); + } + } + + public static final class MulAnyAny extends MulOp { + private static final long serialVersionUID = -3529870722382357307L; + + public MulAnyAny() { + } + + protected Object evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + if (value0 instanceof Integer) { + int value0Tmp = (int) value0; + if (value1 instanceof Integer) { + return mul(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return mul(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return mul(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return mul(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return mul(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Long) { + long value0Tmp = (long) value0; + if (value1 instanceof Integer) { + return mul(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return mul(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return mul(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return mul(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return mul(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Double) { + double value0Tmp = (double) value0; + if (value1 instanceof Integer) { + return mul(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return mul(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return mul(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return mul(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return mul(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Float) { + float value0Tmp = (float) value0; + if (value1 instanceof Integer) { + return mul(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return mul(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return mul(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return mul(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return mul(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof BigDecimal) { + BigDecimal value0Tmp = (BigDecimal) value0; + try { + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return mul(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + try { + BigDecimal value0Tmp = new BigDecimal(value0.toString()); + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return mul(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + + public Type getType() { + return Types.ANY; + } + + public OpKey getKey() { + return this.keyOf(Types.ANY, Types.ANY); + } + } +} + diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOp.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOp.java index 06c2b7d9..a900c172 100644 --- a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOp.java +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOp.java @@ -23,7 +23,7 @@ import java.math.BigDecimal; -@Operators +//@Operators abstract class SubOp extends BinaryNumericOp { private static final long serialVersionUID = 3767909097007274581L; diff --git a/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOpFactory.java b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOpFactory.java new file mode 100644 index 00000000..80094130 --- /dev/null +++ b/runtime/src/main/java/io/dingodb/expr/runtime/op/arithmetic/SubOpFactory.java @@ -0,0 +1,233 @@ +/* + * Copyright 2021 DataCanvas + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.dingodb.expr.runtime.op.arithmetic; + +import io.dingodb.expr.common.type.Type; +import io.dingodb.expr.common.type.Types; +import io.dingodb.expr.runtime.ExprConfig; +import io.dingodb.expr.runtime.op.BinaryOp; +import io.dingodb.expr.runtime.op.OpKey; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class SubOpFactory extends SubOp { + private static final long serialVersionUID = 6784963294675340840L; + public static final SubOpFactory INSTANCE = new SubOpFactory(); + private final Map opMap = new HashMap(); + private static final SubAnyAny subAnyAny = new SubAnyAny(); + + private SubOpFactory() { + this.opMap.put(this.keyOf(Types.FLOAT, Types.FLOAT), new SubFloatFloat()); + this.opMap.put(this.keyOf(Types.DECIMAL, Types.DECIMAL), new SubDecimalDecimal()); + this.opMap.put(this.keyOf(Types.INT, Types.INT), new SubIntInt()); + this.opMap.put(this.keyOf(Types.LONG, Types.LONG), new SubLongLong()); + this.opMap.put(this.keyOf(Types.DOUBLE, Types.DOUBLE), new SubDoubleDouble()); + } + + public BinaryOp getOp(OpKey key) { + return (BinaryOp)this.opMap.get(key); + } + + public static final class SubFloatFloat extends SubOp { + private static final long serialVersionUID = 907844066737946569L; + + public SubFloatFloat() { + } + + protected Float evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = subAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Float ? (Float)val : (new BigDecimal(val.toString())).floatValue(); + } + + public Type getType() { + return Types.FLOAT; + } + + public OpKey getKey() { + return this.keyOf(Types.FLOAT, Types.FLOAT); + } + } + + public static final class SubDecimalDecimal extends SubOp { + private static final long serialVersionUID = 456896626235990403L; + + public SubDecimalDecimal() { + } + + protected BigDecimal evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = subAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof BigDecimal ? (BigDecimal)val : new BigDecimal(val.toString()); + } + + public Type getType() { + return Types.DECIMAL; + } + + public OpKey getKey() { + return this.keyOf(Types.DECIMAL, Types.DECIMAL); + } + } + + public static final class SubIntInt extends SubOp { + private static final long serialVersionUID = 5122318645409829077L; + + public SubIntInt() { + } + + protected Integer evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = subAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Integer ? (Integer) val : new BigDecimal(val.toString()).intValue(); + } + + public Type getType() { + return Types.INT; + } + + public OpKey getKey() { + return this.keyOf(Types.INT, Types.INT); + } + } + + public static final class SubLongLong extends SubOp { + private static final long serialVersionUID = -4594083197714144603L; + + public SubLongLong() { + } + + protected Long evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = subAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Long ? (Long) val : new BigDecimal(val.toString()).longValue(); + } + + public Type getType() { + return Types.LONG; + } + + public OpKey getKey() { + return this.keyOf(Types.LONG, Types.LONG); + } + } + + public static final class SubDoubleDouble extends SubOp { + private static final long serialVersionUID = 4455773545183109883L; + + public SubDoubleDouble() { + } + + protected Double evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + Object val = subAnyAny.evalNonNullValue(value0, value1, config); + return val instanceof Double ? (Double) val : new BigDecimal(val.toString()).doubleValue(); + } + + public Type getType() { + return Types.DOUBLE; + } + + public OpKey getKey() { + return this.keyOf(Types.DOUBLE, Types.DOUBLE); + } + } + + public static final class SubAnyAny extends SubOp { + private static final long serialVersionUID = 4455773545183109883L; + + public SubAnyAny() { + } + + protected Object evalNonNullValue(@NonNull Object value0, @NonNull Object value1, ExprConfig config) { + if (value0 instanceof Integer) { + int value0Tmp = (int) value0; + if (value1 instanceof Integer) { + return sub(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return sub(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return sub(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return sub(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return sub(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Long) { + long value0Tmp = (long) value0; + if (value1 instanceof Integer) { + return sub(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return sub(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return sub(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return sub(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return sub(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Double) { + double value0Tmp = (double) value0; + if (value1 instanceof Integer) { + return sub(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return sub(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return sub(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return sub(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return sub(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof Float) { + float value0Tmp = (float) value0; + if (value1 instanceof Integer) { + return sub(value0Tmp, (Integer) value1); + } else if (value1 instanceof Long) { + return sub(value0Tmp, (Long) value1); + } else if (value1 instanceof Double) { + return sub(value0Tmp, (Double)value1); + } else if (value1 instanceof Float) { + return sub(value0Tmp, (Float)value1); + } else if (value1 instanceof BigDecimal) { + return sub(new BigDecimal(value0Tmp), (BigDecimal)value1); + } + } else if (value0 instanceof BigDecimal) { + BigDecimal value0Tmp = (BigDecimal) value0; + try { + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return sub(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + try { + BigDecimal value0Tmp = new BigDecimal(value0.toString()); + BigDecimal value1Tmp = new BigDecimal(value1.toString()); + return sub(value0Tmp, value1Tmp); + } catch (Exception e) { + return 0; + } + } + + public Type getType() { + return Types.ANY; + } + + public OpKey getKey() { + return this.keyOf(Types.ANY, Types.ANY); + } + } +} +