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

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

commit b9c3e1c6c99c2379a268e64690f5f8e1abe2ee0a
Author: JackieTien97 <[email protected]>
AuthorDate: Thu May 15 15:10:43 2025 +0800

    Make input defaultly order by timecol asc
---
 .../relational/analyzer/StatementAnalyzer.java     | 94 +++++++++++++++++++++-
 .../function/tvf/ForecastTableFunction.java        |  2 +-
 .../sql/ast/TableFunctionTableArgument.java        |  6 +-
 3 files changed, 97 insertions(+), 5 deletions(-)

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 df9fa7052e4..ef93fe1f5d8 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
@@ -38,6 +38,8 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.tablefunction.Ar
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.tablefunction.ArgumentsAnalysis;
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.tablefunction.TableArgumentAnalysis;
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.tablefunction.TableFunctionInvocationAnalysis;
+import 
org.apache.iotdb.db.queryengine.plan.relational.function.TableBuiltinTableFunction;
+import 
org.apache.iotdb.db.queryengine.plan.relational.function.tvf.ForecastTableFunction;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
@@ -157,6 +159,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SortItem;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StartPipe;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StopPipe;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SubqueryExpression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table;
@@ -4056,7 +4059,8 @@ public class StatementAnalyzer {
 
     @Override
     public Scope visitTableFunctionInvocation(TableFunctionInvocation node, 
Optional<Scope> scope) {
-      TableFunction function = 
metadata.getTableFunction(node.getName().toString());
+      String functionName = node.getName().toString();
+      TableFunction function = metadata.getTableFunction(functionName);
       Node errorLocation = node;
       if (!node.getArguments().isEmpty()) {
         errorLocation = node.getArguments().get(0);
@@ -4064,7 +4068,11 @@ public class StatementAnalyzer {
 
       ArgumentsAnalysis argumentsAnalysis =
           analyzeArguments(
-              function.getArgumentsSpecifications(), node.getArguments(), 
scope, errorLocation);
+              function.getArgumentsSpecifications(),
+              node.getArguments(),
+              scope,
+              errorLocation,
+              functionName);
 
       TableFunctionAnalysis functionAnalysis;
       try {
@@ -4210,7 +4218,8 @@ public class StatementAnalyzer {
         List<ParameterSpecification> parameterSpecifications,
         List<TableFunctionArgument> arguments,
         Optional<Scope> scope,
-        Node errorLocation) {
+        Node errorLocation,
+        String functionName) {
       if (parameterSpecifications.size() < arguments.size()) {
         throw new SemanticException(
             String.format(
@@ -4246,6 +4255,11 @@ public class StatementAnalyzer {
                 "Duplicate argument specification for name: " + 
parameterSpecification.getName());
           }
         }
+
+        // append order by time asc for built-in forecast tvf if user doesn't 
specify order by
+        // clause
+        tryUpdateOrderByForForecastByName(functionName, arguments, 
argumentSpecificationsByName);
+
         Set<String> uniqueArgumentNames = new HashSet<>();
         Set<String> specifiedArgumentNames =
             ImmutableSet.copyOf(argumentSpecificationsByName.keySet());
@@ -4277,6 +4291,9 @@ public class StatementAnalyzer {
               analyzeDefault(parameterSpecification, errorLocation));
         }
       } else {
+        // append order by time asc for built-in forecast tvf if user doesn't 
specify order by
+        // clause
+        tryUpdateOrderByForForecastByPosition(functionName, arguments, 
parameterSpecifications);
         for (int i = 0; i < arguments.size(); i++) {
           TableFunctionArgument argument = arguments.get(i);
           ParameterSpecification parameterSpecification = 
parameterSpecifications.get(i);
@@ -4296,6 +4313,77 @@ public class StatementAnalyzer {
       return new ArgumentsAnalysis(passedArguments.buildOrThrow(), 
tableArgumentAnalyses.build());
     }
 
+    // append order by time asc for built-in forecast tvf if user doesn't 
specify order by clause
+    private void tryUpdateOrderByForForecastByName(
+        String functionName,
+        List<TableFunctionArgument> arguments,
+        Map<String, ParameterSpecification> argumentSpecificationsByName) {
+      if 
(TableBuiltinTableFunction.FORECAST.getFunctionName().equalsIgnoreCase(functionName))
 {
+        String timeColumn =
+            (String)
+                argumentSpecificationsByName
+                    .get(ForecastTableFunction.TIMECOL_PARAMETER_NAME)
+                    .getDefaultValue()
+                    .get();
+        for (TableFunctionArgument argument : arguments) {
+          if (ForecastTableFunction.TIMECOL_PARAMETER_NAME.equalsIgnoreCase(
+              argument.getName().get().getValue())) {
+            if (argument.getValue() instanceof StringLiteral) {
+              timeColumn = ((StringLiteral) argument.getValue()).getValue();
+            }
+          }
+        }
+        tryUpdateOrderByForForecast(arguments, timeColumn);
+      }
+    }
+
+    // append order by time asc for built-in forecast tvf if user doesn't 
specify order by clause
+    private void tryUpdateOrderByForForecastByPosition(
+        String functionName,
+        List<TableFunctionArgument> arguments,
+        List<ParameterSpecification> parameterSpecifications) {
+      if 
(TableBuiltinTableFunction.FORECAST.getFunctionName().equalsIgnoreCase(functionName))
 {
+        int position = -1;
+        String timeColumn = null;
+        for (int i = 0, size = parameterSpecifications.size(); i < size; i++) {
+          if (ForecastTableFunction.TIMECOL_PARAMETER_NAME.equalsIgnoreCase(
+              parameterSpecifications.get(i).getName())) {
+            position = i;
+            timeColumn = (String) 
parameterSpecifications.get(i).getDefaultValue().get();
+            break;
+          }
+        }
+        if (position == -1) {
+          throw new IllegalStateException(
+              "ForecastTableFunction must contain 
ForecastTableFunction.TIMECOL_PARAMETER_NAME");
+        }
+        if (position < arguments.size()
+            && arguments.get(position).getValue() instanceof StringLiteral) {
+          timeColumn = ((StringLiteral) 
arguments.get(position).getValue()).getValue();
+        }
+        tryUpdateOrderByForForecast(arguments, timeColumn);
+      }
+    }
+
+    // append order by time asc for built-in forecast tvf if user doesn't 
specify order by clause
+    private void tryUpdateOrderByForForecast(
+        List<TableFunctionArgument> arguments, String timeColumn) {
+      for (TableFunctionArgument argument : arguments) {
+        if (argument.getValue() instanceof TableFunctionTableArgument) {
+          TableFunctionTableArgument input = (TableFunctionTableArgument) 
argument.getValue();
+          if (!input.getOrderBy().isPresent()) {
+            input.updateOrderBy(
+                new OrderBy(
+                    Collections.singletonList(
+                        new SortItem(
+                            new Identifier(null, timeColumn),
+                            SortItem.Ordering.ASCENDING,
+                            SortItem.NullOrdering.FIRST))));
+          }
+        }
+      }
+    }
+
     private ArgumentAnalysis analyzeArgument(
         ParameterSpecification parameterSpecification,
         TableFunctionArgument argument,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/tvf/ForecastTableFunction.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/tvf/ForecastTableFunction.java
index 9086e6f5edd..a04cb1c3ad3 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/tvf/ForecastTableFunction.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/tvf/ForecastTableFunction.java
@@ -166,7 +166,7 @@ public class ForecastTableFunction implements TableFunction 
{
   private static final long DEFAULT_OUTPUT_START_TIME = Long.MIN_VALUE;
   private static final String OUTPUT_INTERVAL = "OUTPUT_INTERVAL";
   private static final long DEFAULT_OUTPUT_INTERVAL = 0L;
-  private static final String TIMECOL_PARAMETER_NAME = "TIMECOL";
+  public static final String TIMECOL_PARAMETER_NAME = "TIMECOL";
   private static final String DEFAULT_TIME_COL = "time";
   private static final String KEEP_INPUT_PARAMETER_NAME = "KEEP_INPUT";
   private static final Boolean DEFAULT_KEEP_INPUT = Boolean.FALSE;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/TableFunctionTableArgument.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/TableFunctionTableArgument.java
index 8c0addef1d8..c6f1ee88d0c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/TableFunctionTableArgument.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/TableFunctionTableArgument.java
@@ -32,7 +32,7 @@ import static 
org.apache.iotdb.db.queryengine.plan.relational.sql.util.Expressio
 public class TableFunctionTableArgument extends Node {
   private final Relation table;
   private final Optional<List<Expression>> partitionBy; // it is allowed to 
partition by empty list
-  private final Optional<OrderBy> orderBy;
+  private Optional<OrderBy> orderBy;
 
   public TableFunctionTableArgument(
       NodeLocation location,
@@ -57,6 +57,10 @@ public class TableFunctionTableArgument extends Node {
     return orderBy;
   }
 
+  public void updateOrderBy(OrderBy orderBy) {
+    this.orderBy = Optional.of(orderBy);
+  }
+
   @Override
   public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
     return visitor.visitTableArgument(this, context);

Reply via email to