This is an automated email from the ASF dual-hosted git repository.

zhenchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 8b5c17e51e [CALCITE-7258] RelBuilder.filter should throw if the 
condition is not BOOLEAN
8b5c17e51e is described below

commit 8b5c17e51e0c9c3f8e3db17c8d449e67e4e2974a
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Nov 1 17:52:36 2025 +0800

    [CALCITE-7258] RelBuilder.filter should throw if the condition is not 
BOOLEAN
---
 core/src/main/java/org/apache/calcite/rel/core/Filter.java | 14 ++++++++++++++
 .../test/java/org/apache/calcite/test/RelBuilderTest.java  | 14 ++++++++++++++
 .../src/main/java/org/apache/calcite/piglet/Handler.java   |  6 +++++-
 .../java/org/apache/calcite/piglet/PigRelOpVisitor.java    |  7 ++++++-
 .../test/java/org/apache/calcite/test/PigRelExTest.java    | 11 ++++++-----
 .../src/test/java/org/apache/calcite/test/PigletTest.java  |  2 +-
 6 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/core/Filter.java 
b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
index 14b4b2fcc2..27aafd3752 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Filter.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
@@ -28,12 +28,14 @@
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexChecker;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexOver;
 import org.apache.calcite.rex.RexProgram;
 import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Litmus;
 
 import com.google.common.collect.ImmutableList;
@@ -146,6 +148,18 @@ public final boolean containsOver() {
     if (RexUtil.isNullabilityCast(getCluster().getTypeFactory(), condition)) {
       return litmus.fail("Cast for just nullability not allowed");
     }
+
+    final RelDataType conditionType = condition.getType();
+    if (!conditionType.isNullable() && conditionType.getSqlTypeName() != 
SqlTypeName.BOOLEAN) {
+      return litmus.fail("Filter condition must have type BOOLEAN, got " + 
conditionType);
+    }
+    if (conditionType.isNullable()
+        && conditionType.getSqlTypeName() != SqlTypeName.BOOLEAN
+        && conditionType.getSqlTypeName() != SqlTypeName.NULL) {
+      return litmus.fail("Filter condition must have type BOOLEAN or NULL, got 
"
+          + conditionType);
+    }
+
     final RexChecker checker =
         new RexChecker(getInput().getRowType(), context, litmus);
     condition.accept(checker);
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java 
b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index f1dc0baac9..b54e08e26d 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -5969,6 +5969,20 @@ private static RelNode 
buildCorrelateWithJoin(JoinRelType type, RelBuilder build
     }
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7258";>[CALCITE-7258]
+   * RelBuilder.filter should throw if the condition is not BOOLEAN</a>. */
+  @Test void testFilterWithNonBooleanLiteralCondition() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    try {
+      builder.scan("EMP")
+          .filter(builder.literal("foo"))
+          .build();
+    } catch (Error e) {
+      assertTrue(e.getMessage().contains("Filter condition must have type 
BOOLEAN"));
+    }
+  }
+
   /** Operand to a user-defined function. */
   private interface Arg {
     String name();
diff --git a/piglet/src/main/java/org/apache/calcite/piglet/Handler.java 
b/piglet/src/main/java/org/apache/calcite/piglet/Handler.java
index 04646b5661..d8acf8432a 100644
--- a/piglet/src/main/java/org/apache/calcite/piglet/Handler.java
+++ b/piglet/src/main/java/org/apache/calcite/piglet/Handler.java
@@ -107,7 +107,11 @@ public Handler handle(Ast.Node node) {
       builder.clear();
       input = map.get(filter.source.value);
       builder.push(input);
-      final RexNode rexNode = toRex(filter.condition);
+      RexNode rexNode = toRex(filter.condition);
+      if (rexNode.getType().getSqlTypeName() != SqlTypeName.BOOLEAN) {
+        RelDataType boolType = 
builder.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN);
+        rexNode = builder.getRexBuilder().makeCast(boolType, rexNode);
+      }
       builder.filter(rexNode);
       register(filter.target.value);
       return this;
diff --git 
a/piglet/src/main/java/org/apache/calcite/piglet/PigRelOpVisitor.java 
b/piglet/src/main/java/org/apache/calcite/piglet/PigRelOpVisitor.java
index 62bf4f0bea..e1c90e25cc 100644
--- a/piglet/src/main/java/org/apache/calcite/piglet/PigRelOpVisitor.java
+++ b/piglet/src/main/java/org/apache/calcite/piglet/PigRelOpVisitor.java
@@ -29,6 +29,7 @@
 import org.apache.calcite.rex.RexWindowBounds;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Pair;
@@ -169,7 +170,11 @@ List<RelNode> translate() throws FrontendException {
   }
 
   @Override public void visit(LOFilter filter) throws FrontendException {
-    final RexNode relExFilter = PigRelExVisitor.translatePigEx(builder, 
filter.getFilterPlan());
+    RexNode relExFilter = PigRelExVisitor.translatePigEx(builder, 
filter.getFilterPlan());
+    if (relExFilter.getType().getSqlTypeName() != SqlTypeName.BOOLEAN) {
+      RelDataType boolType = 
builder.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN);
+      relExFilter = builder.getRexBuilder().makeCast(boolType, relExFilter);
+    }
     builder.filter(relExFilter);
     builder.register(filter);
   }
diff --git a/piglet/src/test/java/org/apache/calcite/test/PigRelExTest.java 
b/piglet/src/test/java/org/apache/calcite/test/PigRelExTest.java
index 5d56694c04..aff0759796 100644
--- a/piglet/src/test/java/org/apache/calcite/test/PigRelExTest.java
+++ b/piglet/src/test/java/org/apache/calcite/test/PigRelExTest.java
@@ -173,15 +173,16 @@ public void testMatch() {
   }
 
   @Test void testTupleDereference() {
-    checkTranslation("k2.k21", inTree("[$11.k21]"));
-    checkTranslation("k2.(k21, k22)", inTree("[ROW($11.k21, $11.k22)]"));
+    checkTranslation("k2.k21", inTree("[<>($11.k21, 0)]"));
+    checkTranslation("k2.(k21, k22)", inTree("[CAST(ROW($11.k21, 
$11.k22)):BOOLEAN NOT NULL]"));
     checkTranslation("k2.k22.(k221,k222)",
-        inTree("[ROW($11.k22.k221, $11.k22.k222)]"));
+        inTree("[CAST(ROW($11.k22.k221, $11.k22.k222)):BOOLEAN NOT NULL]"));
   }
 
   @Test void testBagDereference() {
-    checkTranslation("l2.l22", inTree("[MULTISET_PROJECTION($13, 1)]"));
-    checkTranslation("l2.(l21, l22)", inTree("[MULTISET_PROJECTION($13, 0, 
1)]"));
+    checkTranslation("l2.l22", inTree("[CAST(MULTISET_PROJECTION($13, 
1)):BOOLEAN NOT NULL]"));
+    checkTranslation("l2.(l21, l22)",
+        inTree("[CAST(MULTISET_PROJECTION($13, 0, 1)):BOOLEAN NOT NULL]"));
   }
 
   @Test void testMapLookup() {
diff --git a/piglet/src/test/java/org/apache/calcite/test/PigletTest.java 
b/piglet/src/test/java/org/apache/calcite/test/PigletTest.java
index 5586b7fb27..3eddf31c8a 100644
--- a/piglet/src/test/java/org/apache/calcite/test/PigletTest.java
+++ b/piglet/src/test/java/org/apache/calcite/test/PigletTest.java
@@ -172,7 +172,7 @@ private static Fluent pig(String pig) {
   @Test void testFilter() throws ParseException {
     final String s = "A = LOAD 'DEPT';\n"
         + "B = FILTER A BY DEPTNO;";
-    final String expected = "LogicalFilter(condition=[$0])\n"
+    final String expected = "LogicalFilter(condition=[<>($0, 0)])\n"
         + "  LogicalTableScan(table=[[scott, DEPT]])\n";
     pig(s).explainContains(expected);
   }

Reply via email to