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

JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 4fceb75dfd8 Fix nullable AND results in tree-model CASE (#18875)
4fceb75dfd8 is described below

commit 4fceb75dfd831369488223c639ee7a8532207792
Author: Colin Lee <[email protected]>
AuthorDate: Wed Oct 21 14:44:45 2026 +0800

    Fix nullable AND results in tree-model CASE (#18875)
---
 .../iotdb/db/it/query/IoTDBCaseWhenThenIT.java     | 26 +++++++
 .../column/binary/LogicAndColumnTransformer.java   |  2 +-
 .../binary/LogicBinaryColumnTransformerTest.java   | 90 ++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBCaseWhenThenIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBCaseWhenThenIT.java
index a88b89e90b5..8a7933ffecf 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBCaseWhenThenIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBCaseWhenThenIT.java
@@ -928,4 +928,30 @@ public class IoTDBCaseWhenThenIT {
         new String[] {"0,0.0,", "1000000,11.0,", "20000000,22.0,", 
"210000000,33.0,"};
     resultSetEqualTest(sql, expectedHeader, retArray);
   }
+
+  @Test
+  public void testNullableAndInLaterCaseBranch() {
+    prepareData(
+        new String[] {
+          "CREATE TIMESERIES root.sg.case_null.s1 WITH DATATYPE=INT32, 
ENCODING=PLAIN",
+          "CREATE TIMESERIES root.sg.case_null.s2 WITH DATATYPE=INT32, 
ENCODING=PLAIN",
+          "INSERT INTO root.sg.case_null(time, s2) VALUES (1, 1)",
+          "INSERT INTO root.sg.case_null(time, s1, s2) VALUES (2, 1, 1), (3, 
0, 1), (4, 101, 1)"
+        });
+    resultSetEqualTest(
+        "SELECT CASE WHEN s1 > 100 THEN 1 WHEN s1 > 0 AND s2 > 0 THEN 2 ELSE 3 
END AS result "
+            + "FROM root.sg.case_null",
+        new String[] {TIMESTAMP_STR, "result"},
+        new String[] {"1,3.0,", "2,2.0,", "3,3.0,", "4,1.0,"});
+    resultSetEqualTest(
+        "SELECT CASE WHEN s1 > 100 THEN 1 WHEN NOT (s1 > 0 AND s2 > 0) THEN 2 
ELSE 3 END AS result "
+            + "FROM root.sg.case_null",
+        new String[] {TIMESTAMP_STR, "result"},
+        new String[] {"1,3.0,", "2,3.0,", "3,2.0,", "4,1.0,"});
+    resultSetEqualTest(
+        "SELECT CASE WHEN s1 > 100 THEN false WHEN s2 > 0 THEN (s1 > 0 AND s2 
> 0) END AS result "
+            + "FROM root.sg.case_null",
+        new String[] {TIMESTAMP_STR, "result"},
+        new String[] {"1,null,", "2,true,", "3,false,", "4,false,"});
+  }
 }
diff --git 
a/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/transformation/dag/column/binary/LogicAndColumnTransformer.java
 
b/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/transformation/dag/column/binary/LogicAndColumnTransformer.java
index 5e7197eaab8..69cf49b9644 100644
--- 
a/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/transformation/dag/column/binary/LogicAndColumnTransformer.java
+++ 
b/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/transformation/dag/column/binary/LogicAndColumnTransformer.java
@@ -77,7 +77,7 @@ public class LogicAndColumnTransformer extends 
LogicBinaryColumnTransformer {
       }
     }
 
-    initializeColumnCache(rightColumn);
+    initializeColumnCache(builder.build());
     this.leftTransformer.clearCache();
     this.rightTransformer.clearCache();
   }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/LogicBinaryColumnTransformerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/LogicBinaryColumnTransformerTest.java
index 086a143c86d..018dcefce5f 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/LogicBinaryColumnTransformerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/LogicBinaryColumnTransformerTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.transformation.dag.column.binary;
 
+import org.apache.iotdb.calc.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.calc.transformation.dag.column.binary.BinaryColumnTransformer;
 import 
org.apache.iotdb.calc.transformation.dag.column.binary.LogicAndColumnTransformer;
 import 
org.apache.iotdb.calc.transformation.dag.column.binary.LogicOrColumnTransformer;
@@ -37,6 +38,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Arrays;
+import java.util.function.BiFunction;
 
 public class LogicBinaryColumnTransformerTest {
 
@@ -44,6 +46,14 @@ public class LogicBinaryColumnTransformerTest {
 
   private static final int POSITION_COUNT = 4;
 
+  private static final Boolean[] AND_EXPECTED = {
+    null, false, null, false, false, false, null, false, true
+  };
+
+  private static final Boolean[] OR_EXPECTED = {
+    null, null, true, null, false, true, true, true, true
+  };
+
   private static final boolean[] leftInput = new boolean[] {true, false, true, 
false};
 
   private static final boolean[] rightInput = new boolean[] {true, false, 
true, false};
@@ -113,4 +123,84 @@ public class LogicBinaryColumnTransformerTest {
 
     }
   }
+
+  @Test
+  public void testLogicAndWithNullsAndSelection() {
+    assertSelected(
+        (left, right) -> new LogicAndColumnTransformer(returnType, left, 
right),
+        AND_EXPECTED,
+        false);
+  }
+
+  @Test
+  public void testLogicAndWithNullsAndPartialSelection() {
+    assertSelected(
+        (left, right) -> new LogicAndColumnTransformer(returnType, left, 
right),
+        AND_EXPECTED,
+        true);
+  }
+
+  @Test
+  public void testLogicOrWithNullsAndSelection() {
+    assertSelected(
+        (left, right) -> new LogicOrColumnTransformer(returnType, left, 
right), OR_EXPECTED, false);
+  }
+
+  @Test
+  public void testLogicOrWithNullsAndPartialSelection() {
+    assertSelected(
+        (left, right) -> new LogicOrColumnTransformer(returnType, left, 
right), OR_EXPECTED, true);
+  }
+
+  private void assertSelected(
+      BiFunction<ColumnTransformer, ColumnTransformer, 
BinaryColumnTransformer> transformerFactory,
+      Boolean[] expected,
+      boolean partial) {
+    Boolean[] values = {null, false, true};
+    TsBlockBuilder builder =
+        new TsBlockBuilder(9, Arrays.asList(TSDataType.BOOLEAN, 
TSDataType.BOOLEAN));
+    for (Boolean left : values) {
+      for (Boolean right : values) {
+        builder.getTimeColumnBuilder().writeLong(0);
+        if (left == null) {
+          builder.getColumnBuilder(0).appendNull();
+        } else {
+          builder.getColumnBuilder(0).writeBoolean(left);
+        }
+        if (right == null) {
+          builder.getColumnBuilder(1).appendNull();
+        } else {
+          builder.getColumnBuilder(1).writeBoolean(right);
+        }
+        builder.declarePosition();
+      }
+    }
+    TsBlock block = builder.build();
+    IdentityColumnTransformer left = new IdentityColumnTransformer(returnType, 
0);
+    IdentityColumnTransformer right = new 
IdentityColumnTransformer(returnType, 1);
+    left.addReferenceCount();
+    right.addReferenceCount();
+    left.initFromTsBlock(block);
+    right.initFromTsBlock(block);
+    BinaryColumnTransformer transformer = transformerFactory.apply(left, 
right);
+    transformer.addReferenceCount();
+    boolean[] selection = new boolean[9];
+    for (int i = 0; i < selection.length; i++) {
+      // Keep the right-FALSE rows (1 and 7) selected while excluding some 
left-FALSE rows.
+      selection[i] = !partial || (i != 3 && i != 5);
+    }
+    boolean[] selected = selection.clone();
+    transformer.evaluateWithSelection(selection);
+    Assert.assertArrayEquals(selected, selection);
+    Column result = transformer.getColumn();
+    Assert.assertEquals(expected.length, result.getPositionCount());
+    for (int i = 0; i < expected.length; i++) {
+      if (!selected[i] || expected[i] == null) {
+        Assert.assertTrue(result.isNull(i));
+      } else {
+        Assert.assertFalse(result.isNull(i));
+        Assert.assertEquals(expected[i], result.getBoolean(i));
+      }
+    }
+  }
 }

Reply via email to