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]

Reply via email to