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';
