This is an automated email from the ASF dual-hosted git repository. Wei-hao-Li pushed a commit to branch fix-diff-order in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 410a52da81aefb1b2a662a6519413e083b3181d5 Author: Weihao Li <[email protected]> AuthorDate: Fri May 8 16:45:39 2026 +0800 fix Signed-off-by: Weihao Li <[email protected]> --- .../scalar/IoTDBDiffFunctionTableIT.java | 24 ++++++++++++++++++++++ .../relational/analyzer/StatementAnalyzer.java | 11 +++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionTableIT.java index 6bf1ef8db3e..36835792ff2 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionTableIT.java @@ -146,4 +146,28 @@ public class IoTDBDiffFunctionTableIT { retArray, DATABASE_NAME); } + + @Test + public void testDiffInSubQueryRespectsInnerOrderBy() { + String[] expectedHeader = new String[] {"time", "device_id", "s1", "s1_diff"}; + String[] retArray = + new String[] { + "1970-02-27T20:53:20.001Z,d1,8,3.0,", + "1970-02-27T20:53:20.000Z,d1,null,null,", + "1970-01-01T00:00:00.006Z,d1,null,null,", + "1970-01-01T00:00:00.005Z,d1,5,1.0,", + "1970-01-01T00:00:00.004Z,d1,4,2.0,", + "1970-01-01T00:00:00.003Z,d1,null,null,", + "1970-01-01T00:00:00.002Z,d1,2,1.0,", + "1970-01-01T00:00:00.001Z,d1,1,null," + }; + tableResultSetEqualTest( + "SELECT * FROM (" + + "select time, device_id, s1, diff(s1) as s1_diff " + + "from table1 where device_id='d1' ORDER by time" + + ") ORDER by time DESC", + expectedHeader, + retArray, + DATABASE_NAME); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java index 6d3326dd402..ffc39edd6de 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java @@ -281,6 +281,7 @@ import static org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Join. import static org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.PatternRecognitionRelation.RowsPerMatch.ONE; import static org.apache.iotdb.commons.schema.table.TsTable.TABLE_ALLOWED_PROPERTIES; import static org.apache.iotdb.commons.udf.builtin.relational.TableBuiltinScalarFunction.DATE_BIN; +import static org.apache.iotdb.commons.udf.builtin.relational.TableBuiltinScalarFunction.DIFF; import static org.apache.iotdb.db.queryengine.execution.warnings.StandardWarningCode.REDUNDANT_ORDER_BY; import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.AggregationAnalyzer.verifyOrderByAggregations; import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.AggregationAnalyzer.verifySourceAggregations; @@ -1188,7 +1189,8 @@ public class StatementAnalyzer { if ((sourceScope.getOuterQueryParent().isPresent() || !isTopLevel) && !node.getLimit().isPresent() && !node.getOffset().isPresent() - && !hasFillInParentScope) { + && !hasFillInParentScope + && !containsDiffFunction(outputExpressions)) { // not the root scope and ORDER BY is ineffective analysis.markRedundantOrderBy(orderBy); warningCollector.add( @@ -1301,6 +1303,13 @@ public class StatementAnalyzer { return windowFunctions; } + private boolean containsDiffFunction(List<Expression> expressions) { + return ExpressionTreeUtils.extractExpressions(expressions, FunctionCall.class).stream() + .anyMatch( + functionCall -> + functionCall.getName().getSuffix().equalsIgnoreCase(DIFF.getFunctionName())); + } + private void resolveFunctionCallAndMeasureWindows(QuerySpecification querySpecification) { ImmutableList.Builder<Expression> expressions = ImmutableList.builder();
