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

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

commit 6e045ebb2673fb9c58f15ba102335e592dc775b0
Author: Beyyes <[email protected]>
AuthorDate: Thu Feb 6 16:48:55 2025 +0800

    add time duration parser
---
 .../plan/relational/analyzer/Analysis.java         |  7 +++++
 .../relational/analyzer/StatementAnalyzer.java     |  5 ++++
 .../plan/relational/sql/ast/AsofJoinOn.java        | 16 ++++-------
 .../plan/relational/sql/ast/JoinOn.java            |  2 +-
 .../plan/relational/sql/parser/AstBuilder.java     | 32 +++++++++++++++++++++-
 .../db/relational/grammar/sql/RelationalSql.g4     | 25 ++++-------------
 6 files changed, 54 insertions(+), 33 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
index 1f3873067b4..dc2d47b72cc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
@@ -49,6 +49,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Join;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Offset;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.OrderBy;
@@ -146,6 +147,8 @@ public class Analysis implements IAnalysis {
   private final Map<NodeRef<Node>, SubqueryAnalysis> subQueries = new 
LinkedHashMap<>();
   private final Map<NodeRef<Expression>, PredicateCoercions> 
predicateCoercions =
       new LinkedHashMap<>();
+  // TODO null firstly
+  private final Map<NodeRef<Join>, List<LongLiteral>> asofJoinTolerances = new 
LinkedHashMap<>();
 
   private final Map<NodeRef<Table>, TableEntry> tables = new LinkedHashMap<>();
 
@@ -544,6 +547,10 @@ public class Analysis implements IAnalysis {
     joins.put(NodeRef.of(node), criteria);
   }
 
+  public void setAsofJoinCriteria(Join node, List<LongLiteral> tolerance) {
+    asofJoinTolerances.put(NodeRef.of(node), tolerance);
+  }
+
   public Expression getJoinCriteria(Join join) {
     return joins.get(NodeRef.of(join));
   }
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 65ae1c14835..ed0b0a9c76b 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
@@ -51,6 +51,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AllColumns;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AllRows;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterPipe;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AsofJoinOn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
@@ -2072,6 +2073,7 @@ public class StatementAnalyzer {
       } else if (node.getType() == Join.Type.CROSS || node.getType() == 
Join.Type.IMPLICIT) {
         return output;
       }
+
       if (criteria instanceof JoinOn) {
         Expression expression = ((JoinOn) criteria).getExpression();
         verifyNoAggregateWindowOrGroupingFunctions(expression, "JOIN clause");
@@ -2104,6 +2106,9 @@ public class StatementAnalyzer {
 
         analysis.recordSubqueries(node, expressionAnalysis);
         analysis.setJoinCriteria(node, expression);
+        if (criteria instanceof AsofJoinOn) {
+          analysis.setAsofJoinCriteria(node, ((AsofJoinOn) 
criteria).getToleranceValue());
+        }
       } else {
         throw new UnsupportedOperationException(
             "Unsupported join criteria: " + criteria.getClass().getName());
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AsofJoinOn.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AsofJoinOn.java
index 45d69bd2467..ef2d0d2d77b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AsofJoinOn.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AsofJoinOn.java
@@ -26,22 +26,16 @@ import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
-public class AsofJoinOn extends JoinCriteria {
+public class AsofJoinOn extends JoinOn {
 
-  private final Expression expression;
+  private final List<LongLiteral> toleranceValue;
 
-  private final long toleranceValue;
-
-  public AsofJoinOn(final Expression expression, final long toleranceValue) {
-    this.expression = expression;
+  public AsofJoinOn(final Expression expression, final List<LongLiteral> 
toleranceValue) {
+    super(expression);
     this.toleranceValue = toleranceValue;
   }
 
-  public Expression getExpression() {
-    return this.expression;
-  }
-
-  public long getToleranceValue() {
+  public List<LongLiteral> getToleranceValue() {
     return this.toleranceValue;
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/JoinOn.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/JoinOn.java
index 16f8fb95fe3..83c102b9d37 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/JoinOn.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/JoinOn.java
@@ -29,7 +29,7 @@ import static java.util.Objects.requireNonNull;
 
 public class JoinOn extends JoinCriteria {
 
-  private final Expression expression;
+  protected final Expression expression;
 
   public JoinOn(Expression expression) {
     this.expression = requireNonNull(expression, "expression is null");
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index b6ac6013f21..daa9205aece 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -2043,7 +2043,37 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
       right = (Relation) visit(ctx.rightRelation);
       if (ctx.joinCriteria().ON() != null) {
         if (ctx.ASOF() != null) {
-          criteria = new AsofJoinOn((Expression) 
visit(ctx.joinCriteria().booleanExpression()), 0);
+          List<LongLiteral> tolerance = new ArrayList<>(2);
+          if (ctx.toleranceParameter() != null) {
+            if (ctx.toleranceParameter().toleranceValue().timeDuration() != 
null) {
+              TimeDuration timeDuration =
+                  DateTimeUtils.constructTimeDuration(
+                      
ctx.toleranceParameter().toleranceValue().timeDuration().getText());
+
+              if (timeDuration.monthDuration != 0 && 
timeDuration.nonMonthDuration != 0) {
+                throw new SemanticException(
+                    "Simultaneous setting of monthly and non-monthly intervals 
is not supported.");
+              }
+
+              LongLiteral monthDuration =
+                  new LongLiteral(
+                      
getLocation(ctx.toleranceParameter().toleranceValue().timeDuration()),
+                      String.valueOf(timeDuration.monthDuration));
+              LongLiteral nonMonthDuration =
+                  new LongLiteral(
+                      
getLocation(ctx.toleranceParameter().toleranceValue().timeDuration()),
+                      String.valueOf(timeDuration.nonMonthDuration));
+              tolerance.add(monthDuration);
+              tolerance.add(nonMonthDuration);
+            } else {
+              throw new SemanticException("Only support time duration");
+            }
+          } else {
+            tolerance.add(new LongLiteral("0"));
+            tolerance.add(new LongLiteral("0"));
+          }
+          criteria =
+              new AsofJoinOn((Expression) 
visit(ctx.joinCriteria().booleanExpression()), tolerance);
           return new Join(getLocation(ctx), Join.Type.INNER, left, right, 
criteria);
         } else {
           criteria = new JoinOn((Expression) 
visit(ctx.joinCriteria().booleanExpression()));
diff --git 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index be419e983d5..be9aa0e5fca 100644
--- 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++ 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -824,7 +824,7 @@ relation
       ( CROSS JOIN right=aliasedRelation
       | joinType JOIN rightRelation=relation joinCriteria
       | NATURAL joinType JOIN right=aliasedRelation
-      | ASOF (toleranceParameter)? JOIN rightRelation=relation joinCriteria
+      | ASOF toleranceParameter? JOIN rightRelation=relation joinCriteria
       )                                                     #joinRelation
     | aliasedRelation                                       #relationDefault
     ;
@@ -846,28 +846,12 @@ aliasedRelation
     ;
 
 toleranceParameter
-    : '(' 'tolerance' timeUnit ')'
+    : '(' TOLERANCE toleranceValue ')'
     ;
 
 toleranceValue
-    : numericLiteral_
-    | timeInterval
-    ;
-
-timeInterval
-    : numericLiteral_ timeUnit
-    ;
-
-timeUnit
-    : 's'       // seconds
-    | 'ms'      // milliseconds
-    | 'm'       // minutes
-    | 'h'       // hours
-    | 'd'       // days
-    ;
-
-numericLiteral_
-    : DIGIT+ ('.' DIGIT+)?  // Supports integers and floats
+    : timeDuration
+    | INTEGER_VALUE
     ;
 
 columnAliases
@@ -1439,6 +1423,7 @@ TIMESERIES: 'TIMESERIES';
 TIMESLOTID: 'TIMESLOTID';
 TIMESTAMP: 'TIMESTAMP';
 TO: 'TO';
+TOLERANCE: 'TOLERANCE';
 TOPIC: 'TOPIC';
 TOPICS: 'TOPICS';
 TRAILING: 'TRAILING';

Reply via email to