This is an automated email from the ASF dual-hosted git repository.
lgbo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-gluten.git
The following commit(s) were added to refs/heads/main by this push:
new e99b519274 [GLUTEN-9790][Flink] Support resolving different converters
for Rex calls that share the same operator name (#9792)
e99b519274 is described below
commit e99b5192744c431bfd9ff6c8ea39ae83f3c50873
Author: lgbo <[email protected]>
AuthorDate: Fri May 30 08:32:14 2025 +0800
[GLUTEN-9790][Flink] Support resolving different converters for Rex calls
that share the same operator name (#9792)
* [GLUTEN-9790][Flink] Support resolving different converters for Rex calls
that share the same operator name
* extend compare operators
---
.../apache/gluten/rexnode/RexNodeConverter.java | 3 +-
.../gluten/rexnode/{Utils.java => TypeUtils.java} | 41 +++-------
.../main/java/org/apache/gluten/rexnode/Utils.java | 48 ------------
.../rexnode/functions/BaseRexCallConverters.java | 22 +++++-
.../functions/BasicCompareOperatorConverters.java | 90 ++++++++++++++++++++++
.../rexnode/functions/ModRexCallConverter.java | 12 ++-
.../gluten/rexnode/functions/RexCallConverter.java | 2 +
.../rexnode/functions/RexCallConverterFactory.java | 81 ++++++++++++++-----
.../runtime/stream/custom/ScalarFunctionsTest.java | 68 +++++++++++-----
9 files changed, 240 insertions(+), 127 deletions(-)
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/RexNodeConverter.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/RexNodeConverter.java
index 5c9178b31e..7fa7d8f414 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/RexNodeConverter.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/RexNodeConverter.java
@@ -58,8 +58,7 @@ public class RexNodeConverter {
return new ConstantTypedExpr(toType(literal.getType()),
toVariant(literal), null);
} else if (rexNode instanceof RexCall) {
RexCall rexCall = (RexCall) rexNode;
- String operatorName = rexCall.getOperator().getName();
- RexCallConverter converter =
RexCallConverterFactory.getConverter(operatorName);
+ RexCallConverter converter =
RexCallConverterFactory.getConverter(rexCall, context);
return converter.toTypedExpr(rexCall, context);
} else if (rexNode instanceof RexInputRef) {
RexInputRef inputRef = (RexInputRef) rexNode;
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/TypeUtils.java
similarity index 70%
copy from
gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
copy to
gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/TypeUtils.java
index d88e5dedb6..7e9ea5808a 100644
--- a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/TypeUtils.java
@@ -18,45 +18,14 @@ package org.apache.gluten.rexnode;
import io.github.zhztheplayer.velox4j.expression.CastTypedExpr;
import io.github.zhztheplayer.velox4j.expression.TypedExpr;
-import io.github.zhztheplayer.velox4j.serializable.ISerializableRegistry;
import io.github.zhztheplayer.velox4j.type.*;
-import io.github.zhztheplayer.velox4j.variant.VariantRegistry;
import org.apache.flink.api.java.tuple.Tuple2;
-import org.apache.flink.table.types.logical.LogicalType;
-import org.apache.flink.table.types.logical.RowType;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.stream.Collectors;
-/** Utility to store some useful functions. */
-public class Utils {
- private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
-
- private static boolean registryInitialized = false;
-
- // Get names for project node.
- public static List<String> getNamesFromRowType(LogicalType logicalType) {
- if (logicalType instanceof RowType) {
- RowType rowType = (RowType) logicalType;
- return rowType.getFieldNames();
- } else {
- throw new RuntimeException("Output type is not row type: " +
logicalType);
- }
- }
-
- // Init serialize related registries.
- public static void registerRegistry() {
- if (!registryInitialized) {
- registryInitialized = true;
- VariantRegistry.registerAll();
- ISerializableRegistry.registerAll();
- }
- }
-
+public class TypeUtils {
private static final List<Class<?>> NUMERIC_TYPE_PRIORITY_LIST =
List.of(
TinyIntType.class,
@@ -75,6 +44,14 @@ public class Utils {
return index;
}
+ public static boolean isNumericType(Type type) {
+ return NUMERIC_TYPE_PRIORITY_LIST.contains(type.getClass());
+ }
+
+ public static boolean isStringType(Type type) {
+ return type instanceof VarCharType;
+ }
+
public static List<TypedExpr>
promoteTypeForArithmeticExpressions(List<TypedExpr> expressions) {
Type targetType =
expressions.stream()
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
index d88e5dedb6..7ea26dfd16 100644
--- a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
+++ b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/Utils.java
@@ -16,25 +16,17 @@
*/
package org.apache.gluten.rexnode;
-import io.github.zhztheplayer.velox4j.expression.CastTypedExpr;
-import io.github.zhztheplayer.velox4j.expression.TypedExpr;
import io.github.zhztheplayer.velox4j.serializable.ISerializableRegistry;
import io.github.zhztheplayer.velox4j.type.*;
import io.github.zhztheplayer.velox4j.variant.VariantRegistry;
-import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.RowType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.util.List;
-import java.util.stream.Collectors;
/** Utility to store some useful functions. */
public class Utils {
- private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
private static boolean registryInitialized = false;
@@ -56,44 +48,4 @@ public class Utils {
ISerializableRegistry.registerAll();
}
}
-
- private static final List<Class<?>> NUMERIC_TYPE_PRIORITY_LIST =
- List.of(
- TinyIntType.class,
- SmallIntType.class,
- IntegerType.class,
- BigIntType.class,
- RealType.class,
- DoubleType.class);
-
- private static int getNumericTypePriority(Type type) {
- int index = NUMERIC_TYPE_PRIORITY_LIST.indexOf(type.getClass());
- if (index == -1) {
- // If the type is not found in the list, throw an exception
- throw new RuntimeException("Unsupported type: " +
type.getClass().getName());
- }
- return index;
- }
-
- public static List<TypedExpr>
promoteTypeForArithmeticExpressions(List<TypedExpr> expressions) {
- Type targetType =
- expressions.stream()
- .map(
- expr -> {
- Type returnType = expr.getReturnType();
- int priority = getNumericTypePriority(returnType);
- return new Tuple2<>(priority, returnType);
- })
- .max((t1, t2) -> Integer.compare(t1.f0, t2.f0))
- .orElseThrow(() -> new RuntimeException("No expressions found"))
- .f1;
-
- return expressions.stream()
- .map(
- expr ->
- expr.getReturnType().equals(targetType)
- ? expr
- : CastTypedExpr.create(targetType, expr, false))
- .collect(Collectors.toList());
- }
}
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BaseRexCallConverters.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BaseRexCallConverters.java
index 036c650f1a..c8f2d66348 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BaseRexCallConverters.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BaseRexCallConverters.java
@@ -18,7 +18,7 @@ package org.apache.gluten.rexnode.functions;
import org.apache.gluten.rexnode.RexConversionContext;
import org.apache.gluten.rexnode.RexNodeConverter;
-import org.apache.gluten.rexnode.Utils;
+import org.apache.gluten.rexnode.TypeUtils;
import io.github.zhztheplayer.velox4j.expression.CallTypedExpr;
import io.github.zhztheplayer.velox4j.expression.TypedExpr;
@@ -42,6 +42,13 @@ abstract class BaseRexCallConverter implements
RexCallConverter {
protected Type getResultType(RexCall callNode) {
return RexNodeConverter.toType(callNode.getType());
}
+
+ @Override
+ public boolean isSupported(RexCall callNode, RexConversionContext context) {
+ // Default implementation assumes all RexCall nodes are supported.
+ // Subclasses can override this method to provide specific support checks.
+ return true;
+ }
}
class DefaultRexCallConverter extends BaseRexCallConverter {
@@ -57,15 +64,22 @@ class DefaultRexCallConverter extends BaseRexCallConverter {
}
}
-class AlignInputsTypeRexCallConverter extends BaseRexCallConverter {
- public AlignInputsTypeRexCallConverter(String functionName) {
+class BasicArithmeticOperatorRexCallConverter extends BaseRexCallConverter {
+ public BasicArithmeticOperatorRexCallConverter(String functionName) {
super(functionName);
}
+ @Override
+ public boolean isSupported(RexCall callNode, RexConversionContext context) {
+ return callNode.getOperands().stream()
+ .allMatch(param ->
TypeUtils.isNumericType(RexNodeConverter.toType(param.getType())));
+ }
+
@Override
public TypedExpr toTypedExpr(RexCall callNode, RexConversionContext context)
{
List<TypedExpr> params = getParams(callNode, context);
- List<TypedExpr> alignedParams =
Utils.promoteTypeForArithmeticExpressions(params);
+ // If types are different, align them
+ List<TypedExpr> alignedParams =
TypeUtils.promoteTypeForArithmeticExpressions(params);
Type resultType = getResultType(callNode);
return new CallTypedExpr(resultType, alignedParams, functionName);
}
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BasicCompareOperatorConverters.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BasicCompareOperatorConverters.java
new file mode 100644
index 0000000000..0c0d6b1642
--- /dev/null
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/BasicCompareOperatorConverters.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.gluten.rexnode.functions;
+
+import org.apache.gluten.rexnode.RexConversionContext;
+import org.apache.gluten.rexnode.RexNodeConverter;
+import org.apache.gluten.rexnode.TypeUtils;
+
+import io.github.zhztheplayer.velox4j.expression.CallTypedExpr;
+import io.github.zhztheplayer.velox4j.expression.CastTypedExpr;
+import io.github.zhztheplayer.velox4j.expression.TypedExpr;
+import io.github.zhztheplayer.velox4j.type.Type;
+
+import org.apache.calcite.rex.RexCall;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+class StringCompareRexCallConverter extends BaseRexCallConverter {
+
+ public StringCompareRexCallConverter(String functionName) {
+ super(functionName);
+ }
+
+ @Override
+ public boolean isSupported(RexCall callNode, RexConversionContext context) {
+ // This converter supports string comparison functions.
+ return callNode.getOperands().stream()
+ .allMatch(param ->
TypeUtils.isStringType(RexNodeConverter.toType(param.getType())));
+ }
+
+ @Override
+ public TypedExpr toTypedExpr(RexCall callNode, RexConversionContext context)
{
+ List<TypedExpr> params = getParams(callNode, context);
+ Type resultType = getResultType(callNode);
+ return new CallTypedExpr(resultType, params, functionName);
+ }
+}
+
+class StringNumberCompareRexCallConverter extends BaseRexCallConverter {
+
+ public StringNumberCompareRexCallConverter(String functionName) {
+ super(functionName);
+ }
+
+ @Override
+ public boolean isSupported(RexCall callNode, RexConversionContext context) {
+ // This converter supports string and numeric comparison functions.
+ List<Type> paramTypes =
+ callNode.getOperands().stream()
+ .map(param -> RexNodeConverter.toType(param.getType()))
+ .collect(Collectors.toList());
+ if ((TypeUtils.isNumericType(paramTypes.get(0)) &&
TypeUtils.isStringType(paramTypes.get(1)))
+ || (TypeUtils.isStringType(paramTypes.get(0))
+ && TypeUtils.isNumericType(paramTypes.get(1)))) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public TypedExpr toTypedExpr(RexCall callNode, RexConversionContext context)
{
+ List<TypedExpr> params = getParams(callNode, context);
+ Type resultType = getResultType(callNode);
+ TypedExpr leftExpr =
+ TypeUtils.isNumericType(params.get(0).getReturnType())
+ ? params.get(0)
+ : CastTypedExpr.create(params.get(1).getReturnType(),
params.get(0), false);
+ TypedExpr rightExpr =
+ TypeUtils.isNumericType(params.get(1).getReturnType())
+ ? params.get(1)
+ : CastTypedExpr.create(params.get(0).getReturnType(),
params.get(1), false);
+ return new CallTypedExpr(resultType, Arrays.asList(leftExpr, rightExpr),
functionName);
+ }
+}
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/ModRexCallConverter.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/ModRexCallConverter.java
index bc7658268f..d2dc8a1788 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/ModRexCallConverter.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/ModRexCallConverter.java
@@ -17,7 +17,8 @@
package org.apache.gluten.rexnode.functions;
import org.apache.gluten.rexnode.RexConversionContext;
-import org.apache.gluten.rexnode.Utils;
+import org.apache.gluten.rexnode.RexNodeConverter;
+import org.apache.gluten.rexnode.TypeUtils;
import io.github.zhztheplayer.velox4j.expression.CallTypedExpr;
import io.github.zhztheplayer.velox4j.expression.TypedExpr;
@@ -34,10 +35,17 @@ public class ModRexCallConverter extends
BaseRexCallConverter {
super(FUNCTION_NAME);
}
+ @Override
+ public boolean isSupported(RexCall callNode, RexConversionContext context) {
+ // Modulus operation is supported for numeric types.
+ return callNode.getOperands().size() == 2
+ &&
TypeUtils.isNumericType(RexNodeConverter.toType(callNode.getType()));
+ }
+
@Override
public TypedExpr toTypedExpr(RexCall callNode, RexConversionContext context)
{
List<TypedExpr> params = getParams(callNode, context);
- List<TypedExpr> alignedParams =
Utils.promoteTypeForArithmeticExpressions(params);
+ List<TypedExpr> alignedParams =
TypeUtils.promoteTypeForArithmeticExpressions(params);
// Use the divisor's type as the result type
Type resultType = params.get(1).getReturnType();
return new CallTypedExpr(resultType, params, functionName);
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverter.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverter.java
index 5c0f5a4728..794f4c4eec 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverter.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverter.java
@@ -25,4 +25,6 @@ import org.apache.calcite.rex.RexCall;
public interface RexCallConverter {
// Let the Converter decide how to build the arguments.
TypedExpr toTypedExpr(RexCall callNode, RexConversionContext context);
+
+ boolean isSupported(RexCall callNode, RexConversionContext context);
}
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverterFactory.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverterFactory.java
index e82c567d92..010a78f044 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverterFactory.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/functions/RexCallConverterFactory.java
@@ -16,31 +16,74 @@
*/
package org.apache.gluten.rexnode.functions;
+import org.apache.gluten.rexnode.RexConversionContext;
+
+import org.apache.calcite.rex.RexCall;
+
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
public class RexCallConverterFactory {
- // Better to new Converter for each call. Reusing an object can easily
introduce potential
- // issues.
- private static Map<String, RexCallConverterBuilder> converters =
- Map.of(
- ">", () -> new AlignInputsTypeRexCallConverter("greaterthan"),
- "<", () -> new AlignInputsTypeRexCallConverter("lessthan"),
- "=", () -> new AlignInputsTypeRexCallConverter("equalto"),
- "*", () -> new AlignInputsTypeRexCallConverter("multiply"),
- "-", () -> new AlignInputsTypeRexCallConverter("subtract"),
- "+", () -> new AlignInputsTypeRexCallConverter("add"),
- "MOD", () -> new ModRexCallConverter(),
- "CAST", () -> new DefaultRexCallConverter("cast"),
- "CASE", () -> new DefaultRexCallConverter("if"),
- "AND", () -> new DefaultRexCallConverter("and"));
-
- public static RexCallConverter getConverter(String operatorName) {
- RexCallConverterBuilder builder = converters.get(operatorName);
- if (builder == null) {
+ /**
+ * Better to new Converter for each call. Reusing an object can easily
introduce potential issues.
+ *
+ * <p>A single operator (e.g., '+') may map to multiple converters, such as
arithmetic addition
+ * and timestamp interval addition, which require distinct implementations.
We need to find the
+ * only suitable converter for the given RexCall node.
+ */
+ private static Map<String, List<RexCallConverterBuilder>> converters =
+ Map.ofEntries(
+ Map.entry(
+ ">",
+ Arrays.asList(
+ () -> new
BasicArithmeticOperatorRexCallConverter("greaterthan"),
+ () -> new StringCompareRexCallConverter("greaterthan"),
+ () -> new
StringNumberCompareRexCallConverter("greaterthan"))),
+ Map.entry(
+ "<",
+ Arrays.asList(
+ () -> new
BasicArithmeticOperatorRexCallConverter("lessthan"),
+ () -> new StringCompareRexCallConverter("lessthan"),
+ () -> new StringNumberCompareRexCallConverter("lessthan"))),
+ Map.entry(
+ "=",
+ Arrays.asList(
+ () -> new BasicArithmeticOperatorRexCallConverter("equalto"),
+ () -> new StringCompareRexCallConverter("equalto"),
+ () -> new StringNumberCompareRexCallConverter("equalto"))),
+ Map.entry(
+ "*", Arrays.asList(() -> new
BasicArithmeticOperatorRexCallConverter("multiply"))),
+ Map.entry(
+ "-", Arrays.asList(() -> new
BasicArithmeticOperatorRexCallConverter("subtract"))),
+ Map.entry("+", Arrays.asList(() -> new
BasicArithmeticOperatorRexCallConverter("add"))),
+ Map.entry("MOD", Arrays.asList(() -> new ModRexCallConverter())),
+ Map.entry("CAST", Arrays.asList(() -> new
DefaultRexCallConverter("cast"))),
+ Map.entry("CASE", Arrays.asList(() -> new
DefaultRexCallConverter("if"))),
+ Map.entry("AND", Arrays.asList(() -> new
DefaultRexCallConverter("and"))));
+
+ public static RexCallConverter getConverter(RexCall callNode,
RexConversionContext context) {
+ String operatorName = callNode.getOperator().getName();
+ List<RexCallConverterBuilder> builders = converters.get(operatorName);
+ if (builders == null) {
throw new RuntimeException("Function not supported: " + operatorName);
}
- return builder.build();
+
+ List<RexCallConverter> converterList =
+ builders.stream()
+ .map(RexCallConverterBuilder::build)
+ .filter(c -> c.isSupported(callNode, context))
+ .collect(Collectors.toList());
+
+ if (converterList.size() > 1) {
+ throw new RuntimeException("Multiple converters found for: " +
operatorName);
+ } else if (converterList.isEmpty()) {
+ throw new RuntimeException("No suitable converter found for: " +
operatorName);
+ }
+
+ return converterList.get(0);
}
private interface RexCallConverterBuilder {
diff --git
a/gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/ScalarFunctionsTest.java
b/gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/ScalarFunctionsTest.java
index 0a1f3cd23b..0574fd55ce 100644
---
a/gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/ScalarFunctionsTest.java
+++
b/gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/ScalarFunctionsTest.java
@@ -32,67 +32,95 @@ class ScalarFunctionsTest extends GlutenStreamingTestBase {
@BeforeEach
public void before() throws Exception {
super.before();
- List<Row> rows =
- Arrays.asList(
- Row.of(1, 1L, "1", 100, 10L), Row.of(2, 2L, "2", 3, 11L),
Row.of(3, 3L, "3", 5, 12L));
- createSimpleBoundedValuesTable("t1", "a int, b bigint, c string, d int, e
bigint", rows);
-
- List<Row> rows2 =
- Arrays.asList(Row.of(1, 2L, 3.0, "12"), Row.of(2, 3L, 4.0, "13"),
Row.of(3, 4L, 5.0, "14"));
- createSimpleBoundedValuesTable("t2", "a int, b bigint, c double, d
string", rows2);
}
@Test
void testAdd() {
- String query1 = "select a + b as x from t1 where a > 0";
+ List<Row> rows = Arrays.asList(Row.of(1, 1L), Row.of(2, 2L), Row.of(3,
3L));
+ createSimpleBoundedValuesTable("tblAdd", "a int, b bigint", rows);
+
+ String query1 = "select a + b as x from tblAdd where a > 0";
runAndCheck(query1, Arrays.asList("+I[2]", "+I[4]", "+I[6]"));
- String query2 = "select a + 1 as x from t1 where a > 0";
+ String query2 = "select a + 1 as x from tblAdd where a > 0";
runAndCheck(query2, Arrays.asList("+I[2]", "+I[3]", "+I[4]"));
}
@Test
void testSubtract() {
- String query1 = "select a - b as x from t1 where a > 0";
+ List<Row> rows = Arrays.asList(Row.of(1, 1L), Row.of(2, 2L), Row.of(3,
3L));
+ createSimpleBoundedValuesTable("tblSub", "a int, b bigint", rows);
+ String query1 = "select a - b as x from tblSub where a > 0";
runAndCheck(query1, Arrays.asList("+I[0]", "+I[0]", "+I[0]"));
- String query2 = "select a - 1 as x from t1 where a > 0";
+ String query2 = "select a - 1 as x from tblSub where a > 0";
runAndCheck(query2, Arrays.asList("+I[0]", "+I[1]", "+I[2]"));
}
@Test
void testMod() {
- String query1 = "select d % a as x from t1 where a > 0";
+ List<Row> rows = Arrays.asList(Row.of(1, 100), Row.of(2, 3), Row.of(3, 5));
+ createSimpleBoundedValuesTable("tblMod", "a int, d int", rows);
+ String query1 = "select d % a as x from tblMod where a > 0";
runAndCheck(query1, Arrays.asList("+I[0]", "+I[1]", "+I[2]"));
- String query2 = "select d % 3 as x from t1 where a > 0";
+ String query2 = "select d % 3 as x from tblMod where a > 0";
runAndCheck(query2, Arrays.asList("+I[1]", "+I[0]", "+I[2]"));
}
@Test
void testLargerThen() {
- String query1 = "select a > 1 as x from t1 where a > 0";
+ List<Row> rows =
+ Arrays.asList(Row.of(1, 1L, "2", "1"), Row.of(2, 2L, "2", "2"),
Row.of(3, 3L, "2", "1"));
+ createSimpleBoundedValuesTable("tblLarger", "a int, b bigint, c string, d
string", rows);
+ String query1 = "select a > 1 as x from tblLarger where a > 0";
runAndCheck(query1, Arrays.asList("+I[false]", "+I[true]", "+I[true]"));
- String query2 = "select b > 1 as x from t1 where a > 0";
+ String query2 = "select b > 1 as x from tblLarger where a > 0";
runAndCheck(query2, Arrays.asList("+I[false]", "+I[true]", "+I[true]"));
+
+ String query3 = "select a > c as x from tblLarger where a > 0";
+ runAndCheck(query3, Arrays.asList("+I[false]", "+I[false]", "+I[true]"));
+
+ String query4 = "select c > d as x from tblLarger where a > 0";
+ runAndCheck(query4, Arrays.asList("+I[true]", "+I[false]", "+I[true]"));
}
@Test
void testLessThen() {
- String query1 = "select a < 2 as x from t1 where a > 0";
+ List<Row> rows =
+ Arrays.asList(Row.of(1, 1L, "2", "1"), Row.of(2, 2L, "2", "2"),
Row.of(3, 3L, "2", "1"));
+ createSimpleBoundedValuesTable("tblLess", "a int, b bigint, c string, d
string", rows);
+
+ String query1 = "select a < 2 as x from tblLess where a > 0";
runAndCheck(query1, Arrays.asList("+I[true]", "+I[false]", "+I[false]"));
- String query2 = "select b < 2 as x from t1 where a > 0";
+ String query2 = "select b < 2 as x from tblLess where a > 0";
runAndCheck(query2, Arrays.asList("+I[true]", "+I[false]", "+I[false]"));
+
+ String query3 = "select a < c as x from tblLess where a > 0";
+ runAndCheck(query3, Arrays.asList("+I[true]", "+I[false]", "+I[false]"));
+
+ String query4 = "select c < d as x from tblLess where a > 0";
+ runAndCheck(query4, Arrays.asList("+I[false]", "+I[false]", "+I[false]"));
}
@Test
void testEqual() {
- String query1 = "select a = 1 as x from t1 where a > 0";
+ List<Row> rows =
+ Arrays.asList(Row.of(1, 1L, "2", "1"), Row.of(2, 2L, "2", "2"),
Row.of(3, 3L, "2", "1"));
+ createSimpleBoundedValuesTable("tblEqual", "a int, b bigint, c string, d
string", rows);
+
+ String query1 = "select a = 1 as x from tblEqual where a > 0";
runAndCheck(query1, Arrays.asList("+I[true]", "+I[false]", "+I[false]"));
- String query2 = "select b = 1 as x from t1 where a > 0";
+ String query2 = "select b = 1 as x from tblEqual where a > 0";
runAndCheck(query2, Arrays.asList("+I[true]", "+I[false]", "+I[false]"));
+
+ String query3 = "select a, c, a = c as x from tblEqual where a > 0";
+ runAndCheck(query3, Arrays.asList("+I[1, 2, false]", "+I[2, 2, true]",
"+I[3, 2, false]"));
+
+ String query4 = "select c = d as x from tblEqual where a > 0";
+ runAndCheck(query4, Arrays.asList("+I[false]", "+I[true]", "+I[false]"));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]