Skip to content

Commit 4ea03a5

Browse files
authored
fix: incorrect total row count when folding uncorrelated scalar subquery (#17014)
1 parent db973ea commit 4ea03a5

File tree

3 files changed

+44
-26
lines changed

3 files changed

+44
-26
lines changed

integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/SubqueryDataSetUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ public class SubqueryDataSetUtils {
110110
"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')",
111111
"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')",
112112
"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')",
113+
// table4
114+
"CREATE TABLE IF NOT EXISTS table4(region STRING TAG, remark STRING ATTRIBUTE, name TEXT FIELD)",
115+
"INSERT INTO table4 values(1, 'R001', 'good', 'Mary')",
116+
"INSERT INTO table4 values(2, 'R002', 'bad', 'Tom')",
113117
"FLUSH",
114118
"CLEAR ATTRIBUTE CACHE",
115119
};

integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/subquery/uncorrelated/IoTDBUncorrelatedScalarSubqueryIT.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ public void testScalarSubqueryAfterComparisonLegalityCheck() {
265265
"701: Scalar sub-query has returned multiple rows.",
266266
DATABASE_NAME);
267267

268+
tableAssertTestFail(
269+
"select s1 from table1 where time = (select time from table4)",
270+
"701: Scalar sub-query has returned multiple rows.",
271+
DATABASE_NAME);
272+
268273
// Legality check: subquery can not be parsed
269274
tableAssertTestFail(
270275
"select s1 from table1 where s1 = (select s1 from)", "mismatched input", DATABASE_NAME);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/PredicateWithUncorrelatedScalarSubqueryReconstructor.java

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ public Optional<Literal> fetchUncorrelatedSubqueryResultForPredicate(
162162
return Optional.empty();
163163
}
164164

165+
Column column = null;
166+
TSDataType dataType = null;
167+
int rowCount = 0;
165168
while (coordinator.getQueryExecution(queryId).hasNextResult()) {
166169
final Optional<TsBlock> tsBlock;
167170
try {
@@ -174,40 +177,46 @@ public Optional<Literal> fetchUncorrelatedSubqueryResultForPredicate(
174177
continue;
175178
}
176179
final Column[] columns = tsBlock.get().getValueColumns();
180+
// check column count
177181
checkArgument(columns.length == 1, "Scalar Subquery result should only have one column.");
182+
// check row count
183+
rowCount += tsBlock.get().getPositionCount();
178184
checkArgument(
179-
tsBlock.get().getPositionCount() == 1 && !tsBlock.get().getColumn(0).isNull(0),
185+
rowCount == 1 && !columns[0].isNull(0),
180186
"Scalar Subquery result should only have one row.");
187+
column = columns[0];
181188

182189
// column type
183190
DatasetHeader datasetHeader = coordinator.getQueryExecution(queryId).getDatasetHeader();
184191
List<TSDataType> dataTypes = datasetHeader.getRespDataTypes();
185192
checkArgument(dataTypes.size() == 1, "Scalar Subquery result should only have one column.");
186-
187-
switch (dataTypes.get(0)) {
188-
case INT32:
189-
case DATE:
190-
return Optional.of(new LongLiteral(Long.toString(columns[0].getInt(0))));
191-
case INT64:
192-
case TIMESTAMP:
193-
return Optional.of(new LongLiteral(Long.toString(columns[0].getLong(0))));
194-
case FLOAT:
195-
return Optional.of(new DoubleLiteral(Double.toString(columns[0].getFloat(0))));
196-
case DOUBLE:
197-
return Optional.of(new DoubleLiteral(Double.toString(columns[0].getDouble(0))));
198-
case BOOLEAN:
199-
return Optional.of(new BooleanLiteral(Boolean.toString(columns[0].getBoolean(0))));
200-
case BLOB:
201-
return Optional.of(new BinaryLiteral(columns[0].getBinary(0).toString()));
202-
case TEXT:
203-
case STRING:
204-
return Optional.of(new StringLiteral(columns[0].getBinary(0).toString()));
205-
default:
206-
throw new IllegalArgumentException(
207-
String.format(
208-
"Unsupported data type for scalar subquery result: %s",
209-
columns[0].getDataType()));
210-
}
193+
dataType = dataTypes.get(0);
194+
}
195+
checkArgument(
196+
dataType != null && column != null,
197+
"Scalar Subquery result should not get null dataType or null column.");
198+
switch (dataType) {
199+
case INT32:
200+
case DATE:
201+
return Optional.of(new LongLiteral(Long.toString(column.getInt(0))));
202+
case INT64:
203+
case TIMESTAMP:
204+
return Optional.of(new LongLiteral(Long.toString(column.getLong(0))));
205+
case FLOAT:
206+
return Optional.of(new DoubleLiteral(Double.toString(column.getFloat(0))));
207+
case DOUBLE:
208+
return Optional.of(new DoubleLiteral(Double.toString(column.getDouble(0))));
209+
case BOOLEAN:
210+
return Optional.of(new BooleanLiteral(Boolean.toString(column.getBoolean(0))));
211+
case BLOB:
212+
return Optional.of(new BinaryLiteral(column.getBinary(0).toString()));
213+
case TEXT:
214+
case STRING:
215+
return Optional.of(new StringLiteral(column.getBinary(0).toString()));
216+
default:
217+
throw new IllegalArgumentException(
218+
String.format(
219+
"Unsupported data type for scalar subquery result: %s", column.getDataType()));
211220
}
212221
} catch (final Throwable throwable) {
213222
t = throwable;

0 commit comments

Comments
 (0)