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

jackietien 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 4ea03a5c448 fix: incorrect total row count when folding uncorrelated 
scalar subquery (#17014)
4ea03a5c448 is described below

commit 4ea03a5c448b4709df7d7d036018135cc31d0f26
Author: shizy <[email protected]>
AuthorDate: Mon Jan 12 20:44:28 2026 +0800

    fix: incorrect total row count when folding uncorrelated scalar subquery 
(#17014)
---
 .../recent/subquery/SubqueryDataSetUtils.java      |  4 ++
 .../IoTDBUncorrelatedScalarSubqueryIT.java         |  5 ++
 ...ithUncorrelatedScalarSubqueryReconstructor.java | 61 +++++++++++++---------
 3 files changed, 44 insertions(+), 26 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/SubqueryDataSetUtils.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/SubqueryDataSetUtils.java
index 0e6e2124f32..e9ea6344bca 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/SubqueryDataSetUtils.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/SubqueryDataSetUtils.java
@@ -110,6 +110,10 @@ public class SubqueryDataSetUtils {
         "INSERT INTO table3(time,device_id,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) 
values 
(2024-09-24T06:14:30.000+00:00,'d01',40,40,40.0,40.0,false,'shanghai_huangpu_red_A_d01_40','shanghai_huangpu_red_A_d01_40',X'cafebabe40',2024-09-24T06:14:00.000+00:00,'2024-09-24')",
         "INSERT INTO table3(time,device_id,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) 
values 
(2024-09-24T06:13:30.000+00:00,'d_null',30,30,30.0,30.0,true,'shanghai_huangpu_red_A_d01_30','shanghai_huangpu_red_A_d01_30',X'cafebabe30',2024-09-24T06:13:00.000+00:00,'2024-09-23')",
         "INSERT INTO table3(time,device_id,s2,s3,s4,s5,s6,s7,s8,s9,s10) values 
(2024-09-24T06:14:30.000+00:00,'d_null',40,40.0,40.0,false,'shanghai_huangpu_red_A_d01_40','shanghai_huangpu_red_A_d01_40',X'cafebabe40',2024-09-24T06:14:00.000+00:00,'2024-09-24')",
+        // table4
+        "CREATE TABLE IF NOT EXISTS table4(region STRING TAG, remark STRING 
ATTRIBUTE, name TEXT FIELD)",
+        "INSERT INTO table4 values(1, 'R001', 'good', 'Mary')",
+        "INSERT INTO table4 values(2, 'R002', 'bad', 'Tom')",
         "FLUSH",
         "CLEAR ATTRIBUTE CACHE",
       };
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/uncorrelated/IoTDBUncorrelatedScalarSubqueryIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/uncorrelated/IoTDBUncorrelatedScalarSubqueryIT.java
index d2bce2e0d4a..f6a2cdff48b 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/uncorrelated/IoTDBUncorrelatedScalarSubqueryIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/uncorrelated/IoTDBUncorrelatedScalarSubqueryIT.java
@@ -265,6 +265,11 @@ public class IoTDBUncorrelatedScalarSubqueryIT {
         "701: Scalar sub-query has returned multiple rows.",
         DATABASE_NAME);
 
+    tableAssertTestFail(
+        "select s1 from table1 where time = (select time from table4)",
+        "701: Scalar sub-query has returned multiple rows.",
+        DATABASE_NAME);
+
     // Legality check: subquery can not be parsed
     tableAssertTestFail(
         "select s1 from table1 where s1 = (select s1 from)", "mismatched 
input", DATABASE_NAME);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java
index bce197c2681..cf6772fa1c2 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java
@@ -162,6 +162,9 @@ public class 
PredicateWithUncorrelatedScalarSubqueryReconstructor {
         return Optional.empty();
       }
 
+      Column column = null;
+      TSDataType dataType = null;
+      int rowCount = 0;
       while (coordinator.getQueryExecution(queryId).hasNextResult()) {
         final Optional<TsBlock> tsBlock;
         try {
@@ -174,40 +177,46 @@ public class 
PredicateWithUncorrelatedScalarSubqueryReconstructor {
           continue;
         }
         final Column[] columns = tsBlock.get().getValueColumns();
+        // check column count
         checkArgument(columns.length == 1, "Scalar Subquery result should only 
have one column.");
+        // check row count
+        rowCount += tsBlock.get().getPositionCount();
         checkArgument(
-            tsBlock.get().getPositionCount() == 1 && 
!tsBlock.get().getColumn(0).isNull(0),
+            rowCount == 1 && !columns[0].isNull(0),
             "Scalar Subquery result should only have one row.");
+        column = columns[0];
 
         // column type
         DatasetHeader datasetHeader = 
coordinator.getQueryExecution(queryId).getDatasetHeader();
         List<TSDataType> dataTypes = datasetHeader.getRespDataTypes();
         checkArgument(dataTypes.size() == 1, "Scalar Subquery result should 
only have one column.");
-
-        switch (dataTypes.get(0)) {
-          case INT32:
-          case DATE:
-            return Optional.of(new 
LongLiteral(Long.toString(columns[0].getInt(0))));
-          case INT64:
-          case TIMESTAMP:
-            return Optional.of(new 
LongLiteral(Long.toString(columns[0].getLong(0))));
-          case FLOAT:
-            return Optional.of(new 
DoubleLiteral(Double.toString(columns[0].getFloat(0))));
-          case DOUBLE:
-            return Optional.of(new 
DoubleLiteral(Double.toString(columns[0].getDouble(0))));
-          case BOOLEAN:
-            return Optional.of(new 
BooleanLiteral(Boolean.toString(columns[0].getBoolean(0))));
-          case BLOB:
-            return Optional.of(new 
BinaryLiteral(columns[0].getBinary(0).toString()));
-          case TEXT:
-          case STRING:
-            return Optional.of(new 
StringLiteral(columns[0].getBinary(0).toString()));
-          default:
-            throw new IllegalArgumentException(
-                String.format(
-                    "Unsupported data type for scalar subquery result: %s",
-                    columns[0].getDataType()));
-        }
+        dataType = dataTypes.get(0);
+      }
+      checkArgument(
+          dataType != null && column != null,
+          "Scalar Subquery result should not get null dataType or null 
column.");
+      switch (dataType) {
+        case INT32:
+        case DATE:
+          return Optional.of(new LongLiteral(Long.toString(column.getInt(0))));
+        case INT64:
+        case TIMESTAMP:
+          return Optional.of(new 
LongLiteral(Long.toString(column.getLong(0))));
+        case FLOAT:
+          return Optional.of(new 
DoubleLiteral(Double.toString(column.getFloat(0))));
+        case DOUBLE:
+          return Optional.of(new 
DoubleLiteral(Double.toString(column.getDouble(0))));
+        case BOOLEAN:
+          return Optional.of(new 
BooleanLiteral(Boolean.toString(column.getBoolean(0))));
+        case BLOB:
+          return Optional.of(new 
BinaryLiteral(column.getBinary(0).toString()));
+        case TEXT:
+        case STRING:
+          return Optional.of(new 
StringLiteral(column.getBinary(0).toString()));
+        default:
+          throw new IllegalArgumentException(
+              String.format(
+                  "Unsupported data type for scalar subquery result: %s", 
column.getDataType()));
       }
     } catch (final Throwable throwable) {
       t = throwable;

Reply via email to