This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 531c9abac8 [feature](nereids) Add ssb related expressions and PlanNode (#10227) 531c9abac8 is described below commit 531c9abac8556e061961bf2f5a686b53025395e5 Author: zhengshiJ <32082872+zhengs...@users.noreply.github.com> AuthorDate: Wed Jun 22 11:54:28 2022 +0800 [feature](nereids) Add ssb related expressions and PlanNode (#10227) Add related expressions and AggPlan and SortPlan. This PR includes the addition of the following expression types: Arithmetic/BetweenPredicate/CompoundPredicate/FunctionCall. PlanNode: LogicalAggregation/LogicalSort Add a ut to verify related expressions and node parsing --- .../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 3 +- .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 65 ++++++- .../java/org/apache/doris/catalog/FunctionSet.java | 1 - .../doris/nereids/operators/OperatorType.java | 2 + .../plans/logical/LogicalAggregation.java | 98 ++++++++++ .../operators/plans/logical/LogicalSort.java | 114 +++++++++++ .../doris/nereids/parser/LogicalPlanBuilder.java | 213 ++++++++++++++++++++- .../org/apache/doris/nereids/trees/NodeType.java | 15 ++ .../nereids/trees/analysis/FunctionParams.java | 83 ++++++++ .../trees/{NodeType.java => expressions/Add.java} | 41 ++-- .../trees/{NodeType.java => expressions/And.java} | 45 ++--- .../nereids/trees/expressions/Arithmetic.java | 134 +++++++++++++ .../trees/expressions/BetweenPredicate.java | 77 ++++++++ .../trees/expressions/ComparisonPredicate.java | 3 +- .../{FunctionCall.java => CompoundPredicate.java} | 49 ++--- .../{NodeType.java => expressions/Divide.java} | 41 ++-- .../nereids/trees/expressions/Expression.java | 1 + .../trees/expressions/ExpressionVisitor.java | 13 ++ .../nereids/trees/expressions/FunctionCall.java | 40 ++-- .../doris/nereids/trees/expressions/Literal.java | 3 +- .../trees/{NodeType.java => expressions/Mod.java} | 41 ++-- .../{NodeType.java => expressions/Multiply.java} | 40 ++-- .../trees/{NodeType.java => expressions/Or.java} | 45 ++--- .../{NodeType.java => expressions/Subtract.java} | 41 ++-- .../trees/expressions/ExpressionParserTest.java | 137 +++++++++++++ 25 files changed, 1060 insertions(+), 285 deletions(-) diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 index c07854e0cc..0958acaabf 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 @@ -103,6 +103,7 @@ AS: 'AS'; ASC: 'ASC'; AT: 'AT'; AUTHORIZATION: 'AUTHORIZATION'; +AVG: 'AVG'; BETWEEN: 'BETWEEN'; BOTH: 'BOTH'; BUCKET: 'BUCKET'; @@ -159,7 +160,6 @@ DIRECTORIES: 'DIRECTORIES'; DIRECTORY: 'DIRECTORY'; DISTINCT: 'DISTINCT'; DISTRIBUTE: 'DISTRIBUTE'; -DIV: 'DIV'; DROP: 'DROP'; ELSE: 'ELSE'; END: 'END'; @@ -316,6 +316,7 @@ STRATIFY: 'STRATIFY'; STRUCT: 'STRUCT'; SUBSTR: 'SUBSTR'; SUBSTRING: 'SUBSTRING'; +SUM: 'SUM'; SYNC: 'SYNC'; SYSTEM_TIME: 'SYSTEM_TIME'; SYSTEM_VERSION: 'SYSTEM_VERSION'; diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index edf28c1d7e..b175d9748d 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -52,8 +52,9 @@ statement : query #statementDefault ; +// -----------------Query----------------- query - : queryTerm + : queryTerm queryOrganization ; queryTerm @@ -68,7 +69,9 @@ queryPrimary querySpecification : selectClause fromClause? - whereClause? #regularQuerySpecification + whereClause? + aggClause? + havingClause? #regularQuerySpecification ; selectClause @@ -91,6 +94,30 @@ joinRelation : (joinType) JOIN right=relationPrimary joinCriteria? ; +aggClause + : GROUP BY groupByItem? + ; + +groupByItem + : expression (',' expression)* + ; + +havingClause + : HAVING booleanExpression + ; + +queryOrganization + : sortClause + ; + +sortClause + : (ORDER BY sortItem (',' sortItem)*)? + ; + +sortItem + : expression ordering = (ASC | DESC)? + ; + joinType : INNER? | CROSS @@ -128,6 +155,8 @@ multipartIdentifier : parts+=errorCapturingIdentifier (DOT parts+=errorCapturingIdentifier)* ; + +// -----------------Expression----------------- namedExpression : expression (AS? name=errorCapturingIdentifier)? ; @@ -141,12 +170,21 @@ expression ; booleanExpression - : NOT booleanExpression #not - | valueExpression #predicated + : NOT booleanExpression #logicalNot + | valueExpression predicate? #predicated + | left=booleanExpression operator=AND right=booleanExpression #logicalBinary + | left=booleanExpression operator=OR right=booleanExpression #logicalBinary + ; + +predicate + : NOT? kind=BETWEEN lower=valueExpression AND upper=valueExpression ; valueExpression : primaryExpression #valueExpressionDefault + | operator=(MINUS | PLUS) valueExpression #arithmeticUnary + | left=valueExpression operator=(ASTERISK | SLASH | PERCENT) right=valueExpression #arithmeticBinary + | left=valueExpression operator=(PLUS | MINUS) right=valueExpression #arithmeticBinary | left=valueExpression comparisonOperator right=valueExpression #comparison ; @@ -154,6 +192,7 @@ primaryExpression : constant #constantDefault | ASTERISK #star | qualifiedName DOT ASTERISK #star + | functionExpression #functioncall | LEFT_PAREN query RIGHT_PAREN #subqueryExpression | identifier #columnReference | base=primaryExpression DOT fieldName=identifier #dereference @@ -170,6 +209,10 @@ constant | STRING+ #stringLiteral ; +functionExpression + : aggFunction #aggFunctions + ; + comparisonOperator : EQ | NEQ | LT | LTE | GT | GTE | NSEQ ; @@ -178,6 +221,14 @@ booleanValue : TRUE | FALSE ; +//TODO: In the future, instead of specifying the function name, +// the function information is obtained by parsing the catalog. This method is more scalable. +aggFunction + : AVG '(' DISTINCT? expression ')' + | SUM '(' DISTINCT? expression ')' + ; + + // this rule is used for explicitly capturing wrong identifiers such as test-table, which should actually be `test-table` // replace identifier with errorCapturingIdentifier where the immediate follow symbol is not an expression, otherwise // valid expressions such as "a-b" can be recognized as an identifier @@ -234,6 +285,7 @@ ansiNonReserved | ARRAY | ASC | AT + | AVG | BETWEEN | BUCKET | BUCKETS @@ -276,7 +328,6 @@ ansiNonReserved | DIRECTORIES | DIRECTORY | DISTRIBUTE - | DIV | DROP | ESCAPED | EXCHANGE @@ -394,6 +445,7 @@ ansiNonReserved | STRUCT | SUBSTR | SUBSTRING + | SUM | SYNC | SYSTEM_TIME | SYSTEM_VERSION @@ -474,6 +526,7 @@ nonReserved | ASC | AT | AUTHORIZATION + | AVG | BETWEEN | BOTH | BUCKET @@ -529,7 +582,6 @@ nonReserved | DIRECTORY | DISTINCT | DISTRIBUTE - | DIV | DROP | ELSE | END @@ -674,6 +726,7 @@ nonReserved | STRUCT | SUBSTR | SUBSTRING + | SUM | SYNC | SYSTEM_TIME | SYSTEM_VERSION diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java index 9f8e978fe2..884a8fa452 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java @@ -1937,7 +1937,6 @@ public class FunctionSet<T> { } } - // Sum String []sumNames = {"sum", "sum_distinct"}; for (String name : sumNames) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java index 3a7554aad6..ad112935cf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java @@ -36,6 +36,8 @@ public enum OperatorType { LOGICAL_PROJECT, LOGICAL_FILTER, LOGICAL_JOIN, + LOGICAL_AGGREGATION, + LOGICAL_SORT, GROUP_PLAN, // physical plan diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java new file mode 100644 index 0000000000..eb6172420a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java @@ -0,0 +1,98 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.operators.plans.logical; + +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.operators.OperatorType; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.NamedExpression; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.Plan; + +import com.google.common.collect.ImmutableList; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * Logical Aggregation plan operator. + * + *eg:select a, sum(b), c from table group by a, c; + * groupByExpressions: Column field after group by. eg: a, c; + * outputExpressions: Column field after select. eg: a, sum(b), c; + * + * Each agg node only contains the select statement field of the same layer, + * and other agg nodes in the subquery contain. + */ +public class LogicalAggregation extends LogicalUnaryOperator { + + private final List<Expression> groupByExpressions; + private final List<? extends NamedExpression> outputExpressions; + + /** + * Desc: Constructor for LogicalAggregation. + */ + public LogicalAggregation(List<Expression> groupByExpressions, + List<? extends NamedExpression> outputExpressions) { + super(OperatorType.LOGICAL_AGGREGATION); + this.groupByExpressions = groupByExpressions; + this.outputExpressions = outputExpressions; + } + + /** + * Get GroupByAggregation list. + * + * @return all group by of this node. + */ + public List<Expression> getGroupByExpressions() { + return groupByExpressions; + } + + /** + * Get outputExpressions list. + * + * @return all agg expressions. + */ + public List<? extends NamedExpression> getoutputExpressions() { + return outputExpressions; + } + + @Override + public String toString() { + return "Aggregation (" + "outputExpressions: " + StringUtils.join(outputExpressions, ", ") + + ", groupByExpressions: " + StringUtils.join(groupByExpressions, ", ") + ")"; + } + + @Override + public List<Slot> computeOutput(Plan input) { + return outputExpressions.stream() + .map(namedExpr -> { + try { + return namedExpr.toSlot(); + } catch (UnboundException e) { + throw new IllegalStateException(e); + } + }) + .collect(ImmutableList.toImmutableList()); + } + + @Override + public List<Expression> getExpressions() { + return new ImmutableList.Builder<Expression>().addAll(groupByExpressions).addAll(outputExpressions).build(); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java new file mode 100644 index 0000000000..b1984051f7 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java @@ -0,0 +1,114 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.operators.plans.logical; + +import org.apache.doris.nereids.operators.OperatorType; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.Plan; + +import com.google.common.collect.ImmutableList; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Logical Sort plan operator. + * + * eg: select * from table order by a, b desc; + * sortItems: list of column information after order by. eg:[a, asc],[b, desc]. + * SortItems: Contains order expression information and sorting method. Default is ascending. + */ +public class LogicalSort extends LogicalUnaryOperator { + + private List<SortItems> sortItems; + + /** + * Constructor for SortItems. + */ + public LogicalSort(List<SortItems> sortItems) { + super(OperatorType.LOGICAL_SORT); + this.sortItems = Objects.requireNonNull(sortItems, "sorItems can not be null"); + } + + @Override + public String toString() { + return "Sort (" + StringUtils.join(sortItems, ", ") + ")"; + } + + @Override + public List<Slot> computeOutput(Plan input) { + return input.getOutput(); + } + + /** + * Get SortItems. + * + * @return List of SortItems. + */ + public List<SortItems> getSortItems() { + return sortItems; + } + + @Override + public List<Expression> getExpressions() { + return new ImmutableList.Builder<Expression>().addAll( + sortItems.stream().map(expr -> expr.getSort()).collect(Collectors.toList())) + .build(); + } + + /** + * SortItem. Show sort expressions and their order types. + */ + public static class SortItems { + /** + * enum of OrderDirection. + */ + public enum OrderDirection { + ASC, + DESC + } + + private final Expression sort; + private final OrderDirection orderDirection; + + public SortItems(Expression sort, OrderDirection orderDirection) { + this.sort = sort; + this.orderDirection = orderDirection; + } + + public Expression getSort() { + return sort; + } + + /** + * Get OrderDirection. + * + * @return boolean. + */ + public OrderDirection getOrderDirection() { + return orderDirection; + } + + public String toString() { + return "Expression: " + sort.sql() + " OrderDirection: " + orderDirection.toString(); + } + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index c90524f3ce..23b697ede3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -19,29 +19,38 @@ package org.apache.doris.nereids.parser; import org.apache.doris.nereids.DorisParser; +import org.apache.doris.nereids.DorisParser.AggClauseContext; +import org.apache.doris.nereids.DorisParser.AggFunctionsContext; +import org.apache.doris.nereids.DorisParser.ArithmeticBinaryContext; +import org.apache.doris.nereids.DorisParser.ArithmeticUnaryContext; import org.apache.doris.nereids.DorisParser.BooleanLiteralContext; import org.apache.doris.nereids.DorisParser.ColumnReferenceContext; import org.apache.doris.nereids.DorisParser.ComparisonContext; import org.apache.doris.nereids.DorisParser.DereferenceContext; import org.apache.doris.nereids.DorisParser.ExpressionContext; import org.apache.doris.nereids.DorisParser.FromClauseContext; +import org.apache.doris.nereids.DorisParser.GroupByItemContext; import org.apache.doris.nereids.DorisParser.IdentifierListContext; import org.apache.doris.nereids.DorisParser.IdentifierSeqContext; import org.apache.doris.nereids.DorisParser.IntegerLiteralContext; import org.apache.doris.nereids.DorisParser.JoinCriteriaContext; import org.apache.doris.nereids.DorisParser.JoinRelationContext; +import org.apache.doris.nereids.DorisParser.LogicalBinaryContext; +import org.apache.doris.nereids.DorisParser.LogicalNotContext; import org.apache.doris.nereids.DorisParser.MultipartIdentifierContext; import org.apache.doris.nereids.DorisParser.NamedExpressionContext; import org.apache.doris.nereids.DorisParser.NamedExpressionSeqContext; -import org.apache.doris.nereids.DorisParser.NotContext; import org.apache.doris.nereids.DorisParser.NullLiteralContext; +import org.apache.doris.nereids.DorisParser.PredicateContext; import org.apache.doris.nereids.DorisParser.PredicatedContext; import org.apache.doris.nereids.DorisParser.QualifiedNameContext; import org.apache.doris.nereids.DorisParser.QueryContext; +import org.apache.doris.nereids.DorisParser.QueryOrganizationContext; import org.apache.doris.nereids.DorisParser.RegularQuerySpecificationContext; import org.apache.doris.nereids.DorisParser.RelationContext; import org.apache.doris.nereids.DorisParser.SelectClauseContext; import org.apache.doris.nereids.DorisParser.SingleStatementContext; +import org.apache.doris.nereids.DorisParser.SortItemContext; import org.apache.doris.nereids.DorisParser.StarContext; import org.apache.doris.nereids.DorisParser.StringLiteralContext; import org.apache.doris.nereids.DorisParser.TableNameContext; @@ -52,20 +61,35 @@ import org.apache.doris.nereids.analyzer.UnboundRelation; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.analyzer.UnboundStar; import org.apache.doris.nereids.operators.plans.JoinType; +import org.apache.doris.nereids.operators.plans.logical.LogicalAggregation; import org.apache.doris.nereids.operators.plans.logical.LogicalFilter; import org.apache.doris.nereids.operators.plans.logical.LogicalJoin; import org.apache.doris.nereids.operators.plans.logical.LogicalProject; +import org.apache.doris.nereids.operators.plans.logical.LogicalSort; +import org.apache.doris.nereids.operators.plans.logical.LogicalSort.SortItems; +import org.apache.doris.nereids.operators.plans.logical.LogicalSort.SortItems.OrderDirection; +import org.apache.doris.nereids.trees.analysis.FunctionParams; +import org.apache.doris.nereids.trees.expressions.Add; import org.apache.doris.nereids.trees.expressions.Alias; +import org.apache.doris.nereids.trees.expressions.And; +import org.apache.doris.nereids.trees.expressions.Arithmetic; +import org.apache.doris.nereids.trees.expressions.BetweenPredicate; +import org.apache.doris.nereids.trees.expressions.Divide; import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.FunctionCall; import org.apache.doris.nereids.trees.expressions.GreaterThan; import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; import org.apache.doris.nereids.trees.expressions.LessThan; import org.apache.doris.nereids.trees.expressions.LessThanEqual; import org.apache.doris.nereids.trees.expressions.Literal; +import org.apache.doris.nereids.trees.expressions.Mod; +import org.apache.doris.nereids.trees.expressions.Multiply; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Not; import org.apache.doris.nereids.trees.expressions.NullSafeEqual; +import org.apache.doris.nereids.trees.expressions.Or; +import org.apache.doris.nereids.trees.expressions.Subtract; import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan; import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; @@ -74,11 +98,13 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan; import com.google.common.collect.Lists; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; import org.antlr.v4.runtime.tree.TerminalNode; import org.apache.commons.collections.CollectionUtils; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; @@ -132,11 +158,18 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { public LogicalPlan visitQuery(QueryContext ctx) { Supplier<LogicalPlan> f = () -> { // TODO: need to add withQueryResultClauses and withCTE - return plan(ctx.queryTerm()); + LogicalPlan query = plan(ctx.queryTerm()); + LogicalPlan queryOrganization = withQueryOrganization(ctx.queryOrganization(), query); + return queryOrganization; }; return ParserUtils.withOrigin(ctx, f); } + private LogicalPlan withQueryOrganization(QueryOrganizationContext ctx, LogicalPlan children) { + List<SortItems> sortItems = visitQueryOrganization(ctx); + return sortItems == null ? children : new LogicalUnaryPlan(new LogicalSort(sortItems), children); + } + @Override public LogicalPlan visitRegularQuerySpecification(RegularQuerySpecificationContext ctx) { Supplier<LogicalPlan> f = () -> { @@ -146,7 +179,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { ctx, ctx.selectClause(), ctx.whereClause(), - from); + from, + ctx.aggClause()); }; return ParserUtils.withOrigin(ctx, f); } @@ -162,8 +196,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { List<Expression> expressions = Lists.newArrayList(); if (ctx != null) { for (NamedExpressionContext namedExpressionContext : ctx.namedExpression()) { - NamedExpression namedExpression = typedVisit(namedExpressionContext); - expressions.add(namedExpression); + Expression expression = typedVisit(namedExpressionContext); + expressions.add(expression); } } return expressions; @@ -180,13 +214,15 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { ParserRuleContext ctx, SelectClauseContext selectClause, WhereClauseContext whereClause, - LogicalPlan relation) { + LogicalPlan relation, + AggClauseContext aggClause) { Supplier<LogicalPlan> f = () -> { // Filter(expression(ctx.booleanExpression), plan); LogicalPlan plan = visitCommonSelectQueryClausePlan( relation, visitNamedExpressionSeq(selectClause.namedExpressionSeq()), - whereClause); + whereClause, + aggClause); // TODO: process hint return plan; }; @@ -196,7 +232,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { private LogicalPlan visitCommonSelectQueryClausePlan( LogicalPlan relation, List<Expression> expressions, - WhereClauseContext whereClause) { + WhereClauseContext whereClause, + AggClauseContext aggClause) { // TODO: add lateral views // val withLateralView = lateralView.asScala.foldLeft(relation)(withGenerate) @@ -218,7 +255,14 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { withProject = withFilter; } - return withProject; + LogicalPlan withAgg; + if (aggClause != null) { + withAgg = withAggClause(namedExpressions, aggClause.groupByItem(), withFilter); + } else { + withAgg = withProject; + } + + return withAgg; } @Override @@ -278,6 +322,50 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return last; } + private LogicalPlan withAggClause(List<NamedExpression> aggExpressions, + GroupByItemContext ctx, LogicalPlan aggClause) { + List<Expression> tmpExpressions = new ArrayList<>(); + for (ExpressionContext expressionCtx : ctx.expression()) { + tmpExpressions.add(typedVisit(expressionCtx)); + } + return new LogicalUnaryPlan(new LogicalAggregation(tmpExpressions, aggExpressions), aggClause); + } + + /** + * Generate sortItems. + * + * @param ctx SortItemContext + * @return SortItems + */ + public SortItems genSortItems(SortItemContext ctx) { + OrderDirection orderDirection; + if (ctx.DESC() != null) { + orderDirection = OrderDirection.DESC; + } else { + orderDirection = OrderDirection.ASC; + } + Expression expression = typedVisit(ctx.expression()); + return new SortItems(expression, orderDirection); + } + + /** + * Create SortItems list. + * + * @param ctx QueryOrganizationContext + * @return List of SortItems + */ + public List<SortItems> visitQueryOrganization(QueryOrganizationContext ctx) { + List<SortItems> sortItems = new ArrayList<>(); + if (ctx.sortClause().ORDER() != null) { + for (SortItemContext sortItemContext : ctx.sortClause().sortItem()) { + sortItems.add(genSortItems(sortItemContext)); + } + return new ArrayList<>(sortItems); + } else { + return null; + } + } + /** * Create an aliased table reference. This is typically used in FROM clauses. */ @@ -404,11 +492,26 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { * not 1=1 */ @Override - public Expression visitNot(NotContext ctx) { + public Expression visitLogicalNot(LogicalNotContext ctx) { Expression child = expression(ctx.booleanExpression()); return new Not(child); } + @Override + public Expression visitLogicalBinary(LogicalBinaryContext ctx) { + Expression left = expression(ctx.left); + Expression right = expression(ctx.right); + + switch (ctx.operator.getType()) { + case DorisParser.AND: + return new And(left, right); + case DorisParser.OR: + return new Or(left, right); + default: + return null; + } + } + /** * Create a predicated expression. A predicated expression is a normal expression with a * predicate attached to it, for example: @@ -420,9 +523,99 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { public Expression visitPredicated(PredicatedContext ctx) { Expression e = expression(ctx.valueExpression()); // TODO: add predicate(is not null ...) + if (ctx.predicate() != null) { + return withPredicate(ctx.predicate(), e); + } return e; } + /** + * match predicate type and generate different predicates. + * + * @param ctx PredicateContext + * @param e Expression + * @return Expression + */ + public Expression withPredicate(PredicateContext ctx, Expression e) { + switch (ctx.kind.getType()) { + case DorisParser.BETWEEN: + return withBetween(ctx, e); + default: + return null; + } + } + + /** + * Generate between predicate. + * + * @param ctx PredicateContext + * @param e Expression + * @return Expression + */ + public Expression withBetween(PredicateContext ctx, Expression e) { + boolean isNotBetween = ctx.NOT() != null ? true : false; + BetweenPredicate betweenPredicate = new BetweenPredicate( + e, + expression(ctx.lower), + expression(ctx.upper) + ); + return isNotBetween ? new Not(betweenPredicate) : betweenPredicate; + } + + @Override + public Expression visitArithmeticUnary(ArithmeticUnaryContext ctx) { + Expression e = expression(ctx); + switch (ctx.operator.getType()) { + case DorisParser.PLUS: + return e; + case DorisParser.MINUS: + //TODO: Add single operator subtraction + default: + return null; + } + } + + @Override + public Expression visitArithmeticBinary(ArithmeticBinaryContext ctx) { + Expression left = expression(ctx.left); + Expression right = expression(ctx.right); + + return genArithmetic(ctx.operator, left, right); + } + + private Arithmetic genArithmetic(Token token, Expression left, Expression right) { + switch (token.getType()) { + case DorisParser.ASTERISK: + return new Multiply(left, right); + case DorisParser.SLASH: + return new Divide(left, right); + case DorisParser.PERCENT: + return new Mod(left, right); + case DorisParser.PLUS: + return new Add(left, right); + case DorisParser.MINUS: + return new Subtract(left, right); + default: + return null; + } + } + + @Override + public Expression visitAggFunctions(AggFunctionsContext ctx) { + // TODO:In the future, instead of specifying the function name, + // the function information is obtained by parsing the catalog. This method is more scalable. + String functionName = ""; + if (ctx.aggFunction().SUM() != null) { + functionName = "sum"; + } else if (ctx.aggFunction().AVG() != null) { + functionName = "avg"; + } + + return new FunctionCall(functionName, + new FunctionParams(ctx.aggFunction().DISTINCT() != null, + expression(ctx.aggFunction().expression()))); + } + @Override public Expression visitDereference(DereferenceContext ctx) { Expression e = expression(ctx.base); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java index 2ad0894766..50a1c1858b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java @@ -44,6 +44,21 @@ public enum NodeType { NOT, ALIAS, COMPOUND, + AND, + OR, + BETWEEN, + MULTIPLY, + DIVIDE, + MOD, + INT_DIVIDE, + ADD, + SUBTRACT, + BITAND, + BITOR, + BITXOR, + BITNOT, + FACTORIAL, + FUNCTIONCALL, // pattern PATTERN diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/analysis/FunctionParams.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/analysis/FunctionParams.java new file mode 100644 index 0000000000..f2f3a25ae0 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/analysis/FunctionParams.java @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.analysis; + +import org.apache.doris.nereids.trees.expressions.Expression; + +import com.google.common.collect.Lists; + +import java.util.List; +import java.util.Objects; + +/** + * Function's Params. + */ +public class FunctionParams { + private boolean isStar; + private List<Expression> expression; + private boolean isDistinct; + + /** + * Constructor for FunctionParams. + */ + public FunctionParams(boolean isDistinct, List<Expression> exprs) { + isStar = false; + this.isDistinct = isDistinct; + this.expression = exprs; + } + + public FunctionParams(boolean isDistinct, Expression expression) { + this(isDistinct, Lists.newArrayList(expression)); + } + + + // c'tor for non-star, non-distinct params + public FunctionParams(Expression exprs) { + this(false, exprs); + } + + // c'tor for <agg>(*) + private FunctionParams() { + expression = null; + isStar = true; + isDistinct = false; + } + + public List<Expression> getExpression() { + return expression; + } + + public boolean isStar() { + return isStar; + } + + public boolean isDistinct() { + return isDistinct; + } + + @Override + public int hashCode() { + int result = 31 * Boolean.hashCode(isStar) + Boolean.hashCode(isDistinct); + if (expression != null) { + for (Expression expr : expression) { + result = 31 * result + Objects.hashCode(expr); + } + } + return result; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Add.java similarity index 60% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Add.java index 2ad0894766..db20391bd4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Add.java @@ -15,37 +15,20 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Add Expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, +public class Add<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Arithmetic implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + public Add(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(ArithmeticOperator.ADD, left, right); + } - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; + @Override + public String sql() { + return left().sql() + ' ' + getArithOperator().toString() + + ' ' + right().sql(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/And.java similarity index 58% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/And.java index 2ad0894766..3da0626bad 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/And.java @@ -15,37 +15,22 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; + +import org.apache.doris.nereids.trees.NodeType; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * And predicate expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, - - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; +public class And<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends CompoundPredicate<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + /** + * Desc: Constructor for CompoundPredicate. + * + * @param left left child of comparison predicate + * @param right right child of comparison predicate + */ + public And(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(NodeType.AND, left, right); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Arithmetic.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Arithmetic.java new file mode 100644 index 0000000000..9f106ee07a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Arithmetic.java @@ -0,0 +1,134 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions; + + +import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.thrift.TExprOpcode; + +/** + * All arithmetic operator. + */ +public class Arithmetic extends Expression { + + enum OperatorPosition { + BINARY_INFIX, + UNARY_PREFIX, + UNARY_POSTFIX, + } + + /** + * All counts as expressions. + */ + @SuppressWarnings("checkstyle:RegexpSingleline") + public enum ArithmeticOperator { + MULTIPLY("*", "multiply", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.MULTIPLY), + DIVIDE("/", "divide", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.DIVIDE), + MOD("%", "mod", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.MOD), + ADD("+", "add", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.ADD), + SUBTRACT("-", "subtract", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.SUBTRACT), + //TODO: The following functions will be added later. + BITAND("&", "bitand", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.BITAND), + BITOR("|", "bitor", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.BITOR), + BITXOR("^", "bitxor", Arithmetic.OperatorPosition.BINARY_INFIX, TExprOpcode.BITXOR), + BITNOT("~", "bitnot", Arithmetic.OperatorPosition.UNARY_PREFIX, TExprOpcode.BITNOT); + + private final String description; + private final String name; + private final Arithmetic.OperatorPosition pos; + private final TExprOpcode opcode; + + ArithmeticOperator(String description, String name, Arithmetic.OperatorPosition pos, TExprOpcode opcode) { + this.description = description; + this.name = name; + this.pos = pos; + this.opcode = opcode; + } + + @Override + public String toString() { + return description; + } + + public String getName() { + return name; + } + + public Arithmetic.OperatorPosition getPos() { + return pos; + } + + public TExprOpcode getOpcode() { + return opcode; + } + + public boolean isUnary() { + return pos == Arithmetic.OperatorPosition.UNARY_PREFIX + || pos == Arithmetic.OperatorPosition.UNARY_POSTFIX; + } + + public boolean isBinary() { + return pos == Arithmetic.OperatorPosition.BINARY_INFIX; + } + } + + private final ArithmeticOperator op; + + public Arithmetic(ArithmeticOperator op, Expression... children) { + super(genNodeType(op), children); + this.op = op; + } + + public ArithmeticOperator getArithOperator() { + return op; + } + + private static NodeType genNodeType(ArithmeticOperator op) { + switch (op) { + case MULTIPLY: + return NodeType.MULTIPLY; + case DIVIDE: + return NodeType.DIVIDE; + case MOD: + return NodeType.MOD; + case ADD: + return NodeType.ADD; + case SUBTRACT: + return NodeType.SUBTRACT; + case BITAND: + return NodeType.BITAND; + case BITOR: + return NodeType.BITOR; + case BITXOR: + return NodeType.BITXOR; + case BITNOT: + return NodeType.NOT; + default: + return null; + } + } + + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitArithmetic(this, context); + } + + @Override + public String sql() { + return null; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BetweenPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BetweenPredicate.java new file mode 100644 index 0000000000..e4c875b0ef --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BetweenPredicate.java @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions; + +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.types.BooleanType; +import org.apache.doris.nereids.types.DataType; + +/** + * Between predicate expression. + */ +public class BetweenPredicate extends Expression { + + private Expression compareExpr; + private Expression lowerBound; + private Expression upperBound; + /** + * Constructor of ComparisonPredicate. + * + * @param compareExpr compare of expression + * @param lowerBound left child of between predicate + * @param upperBound right child of between predicate + */ + + public BetweenPredicate(Expression compareExpr, Expression lowerBound, + Expression upperBound) { + super(NodeType.BETWEEN, compareExpr, lowerBound, upperBound); + this.compareExpr = compareExpr; + this.lowerBound = lowerBound; + this.upperBound = upperBound; + } + + @Override + public DataType getDataType() throws UnboundException { + return BooleanType.INSTANCE; + } + + @Override + public String sql() { + return compareExpr.sql() + + " BETWEEN " + + lowerBound.sql() + " AND " + upperBound.sql(); + } + + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitBetweenPredicate(this, context); + } + + public Expression getCompareExpr() { + return compareExpr; + } + + public Expression getLowerBound() { + return lowerBound; + } + + public Expression getUpperBound() { + return upperBound; + } + +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java index eb301b4969..a0b495baf8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java @@ -48,7 +48,8 @@ public abstract class ComparisonPredicate<LEFT_CHILD_TYPE extends Expression, RI @Override public String sql() { - return toString(); + String nodeType = getType().toString(); + return left().sql() + ' ' + nodeType + ' ' + right().sql(); } public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java similarity index 50% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java index 17cc075e8f..fbb3faa50e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java @@ -17,50 +17,33 @@ package org.apache.doris.nereids.trees.expressions; -import org.apache.doris.analysis.FunctionName; -import org.apache.doris.catalog.Function; import org.apache.doris.nereids.trees.NodeType; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - /** - * Temp definition of FunctionCallExpression. + * Compound predicate expression. + * Such as &&,||,AND,OR. */ -public class FunctionCall extends Expression { - - private final FunctionName functionName; - - private final List<Expression> params; - - private final Function fn; +public class CompoundPredicate<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Expression implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { /** - * Constructor of FunctionCallExpression. + * Desc: Constructor for CompoundPredicate. + * + * @param type type of expression + * @param left left child of comparison predicate + * @param right right child of comparison predicate */ - public FunctionCall(FunctionName functionName, - Function fn, Expression... children) { - super(NodeType.EXPRESSION, children); - this.functionName = functionName; - this.params = Arrays.stream(children).collect(Collectors.toList()); - this.fn = fn; - } - - public FunctionName getFunctionName() { - return functionName; - } - - public List<Expression> getParams() { - return params; + public CompoundPredicate(NodeType type, LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(type, left, right); } - public Function getFn() { - return fn; + @Override + public String sql() { + String nodeType = getType().toString(); + return left().sql() + ' ' + nodeType + ' ' + right().sql(); } - @Override public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { - return visitor.visitFunctionCall(this, context); + return visitor.visitCompoundPredicate(this, context); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java similarity index 60% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java index 2ad0894766..e921557d09 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java @@ -15,37 +15,20 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Divide Expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, +public class Divide<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Arithmetic implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + public Divide(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(ArithmeticOperator.DIVIDE, left, right); + } - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; + @Override + public String sql() { + return left().sql() + ' ' + getArithOperator().toString() + + ' ' + right().sql(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java index 91b06bd484..53b6aea8ee 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java @@ -81,4 +81,5 @@ public abstract class Expression extends AbstractTreeNode<Expression> { } return false; } + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionVisitor.java index 7b40fb1ba3..943762537f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionVisitor.java @@ -81,6 +81,19 @@ public abstract class ExpressionVisitor<R, C> { return visit(function, context); } + public R visitBetweenPredicate(BetweenPredicate betweenPredicate, C context) { + return visit(betweenPredicate, context); + } + + public R visitCompoundPredicate(CompoundPredicate compoundPredicate, C context) { + return visit(compoundPredicate, context); + } + + public R visitArithmetic(Arithmetic arithmetic, C context) { + return visit(arithmetic, context); + } + + /* ******************************************************************************************** * Unbound expressions * ********************************************************************************************/ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java index 17cc075e8f..db797c5ef9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/FunctionCall.java @@ -18,48 +18,32 @@ package org.apache.doris.nereids.trees.expressions; import org.apache.doris.analysis.FunctionName; -import org.apache.doris.catalog.Function; import org.apache.doris.nereids.trees.NodeType; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; +import org.apache.doris.nereids.trees.analysis.FunctionParams; /** - * Temp definition of FunctionCallExpression. + * Logical FunctionCall Expression. */ public class FunctionCall extends Expression { - private final FunctionName functionName; - - private final List<Expression> params; + private FunctionName fnName; - private final Function fn; - - /** - * Constructor of FunctionCallExpression. - */ - public FunctionCall(FunctionName functionName, - Function fn, Expression... children) { - super(NodeType.EXPRESSION, children); - this.functionName = functionName; - this.params = Arrays.stream(children).collect(Collectors.toList()); - this.fn = fn; - } + private FunctionParams fnParams; - public FunctionName getFunctionName() { - return functionName; + private FunctionCall(FunctionName functionName, FunctionParams functionParams) { + super(NodeType.FUNCTIONCALL, functionParams.getExpression().toArray(new Expression[0])); + this.fnName = functionName; + this.fnParams = functionParams; } - public List<Expression> getParams() { - return params; + public FunctionCall(String functionName, Expression params) { + this(new FunctionName(functionName), new FunctionParams(false, params)); } - public Function getFn() { - return fn; + public FunctionCall(String functionName, FunctionParams functionParams) { + this(new FunctionName(functionName), functionParams); } - @Override public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { return visitor.visitFunctionCall(this, context); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Literal.java index 2152a9a3cb..912b72705e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Literal.java @@ -31,6 +31,7 @@ import java.util.Objects; /** * All data type literal expression in Nereids. + * TODO: Increase the implementation of sub expression. such as Integer. */ public class Literal extends Expression implements LeafExpression { private final DataType dataType; @@ -108,7 +109,7 @@ public class Literal extends Expression implements LeafExpression { @Override public String sql() { - return null; + return value.toString(); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Mod.java similarity index 60% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Mod.java index 2ad0894766..f5210f89fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Mod.java @@ -15,37 +15,20 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Mod Expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, +public class Mod<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Arithmetic implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + public Mod(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(ArithmeticOperator.MOD, left, right); + } - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; + @Override + public String sql() { + return left().sql() + ' ' + getArithOperator().toString() + + ' ' + right().sql(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java similarity index 59% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java index 2ad0894766..7852053dc3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java @@ -15,37 +15,21 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Multiply Expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, +public class Multiply<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Arithmetic implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, + public Multiply(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(ArithmeticOperator.MULTIPLY, left, right); + } - // pattern - PATTERN - ; + @Override + public String sql() { + return left().sql() + ' ' + getArithOperator().toString() + + ' ' + right().sql(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Or.java similarity index 58% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Or.java index 2ad0894766..eddc88126d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Or.java @@ -15,37 +15,22 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; + +import org.apache.doris.nereids.trees.NodeType; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Or predicate expression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, - - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; +public class Or<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends CompoundPredicate<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + /** + * Desc: Constructor for CompoundPredicate. + * + * @param left left child of comparison predicate + * @param right right child of comparison predicate + */ + public Or(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(NodeType.OR, left, right); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Subtract.java similarity index 59% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Subtract.java index 2ad0894766..c4944709c0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/NodeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Subtract.java @@ -15,37 +15,20 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.trees; +package org.apache.doris.nereids.trees.expressions; /** - * Types for all TreeNode in Nereids, include Plan and Expression. + * Subtract Expression. BinaryExpression. */ -public enum NodeType { - // plan - LOGICAL, - PHYSICAL, - // group plan - GROUP, +public class Subtract<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression> + extends Arithmetic implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> { + public Subtract(LEFT_CHILD_TYPE left, RIGHT_CHILD_TYPE right) { + super(ArithmeticOperator.SUBTRACT, left, right); + } - // expressions - EXPRESSION, - UNBOUND_ALIAS, - UNBOUND_SLOT, - UNBOUND_STAR, - LITERAL, - SLOT_REFERENCE, - COMPARISON_PREDICATE, - EQUAL_TO, - LESS_THAN, - GREATER_THAN, - LESS_THAN_EQUAL, - GREATER_THAN_EQUAL, - NULL_SAFE_EQUAL, - NOT, - ALIAS, - COMPOUND, - - // pattern - PATTERN - ; + @Override + public String sql() { + return left().sql() + ' ' + getArithOperator().toString() + + ' ' + right().sql(); + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java new file mode 100644 index 0000000000..987760f6bf --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java @@ -0,0 +1,137 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions; + +import org.apache.doris.nereids.parser.SqlParser; +import org.apache.doris.nereids.trees.TreeNode; + +import org.junit.Test; + +public class ExpressionParserTest { + private static final SqlParser PARSER = new SqlParser(); + + private void assertSql(String sql) throws Exception { + TreeNode treeNode = PARSER.parse(sql); + System.out.println(treeNode.toString()); + } + + private void assertExpr(String expr) { + Expression expression = PARSER.createExpression(expr); + System.out.println(expression.sql()); + } + + @Test + public void testSqlBetweenPredicate() throws Exception { + String sql = "select * from test1 where d1 between 1 and 2"; + assertSql(sql); + } + + @Test + public void testExprBetweenPredicate() { + String sql = "c BETWEEN a AND b"; + assertExpr(sql); + } + + @Test + public void testSqlAnd() throws Exception { + String sql = "select * from test1 where a > 1 and b > 1"; + TreeNode treeNode = PARSER.parse(sql); + System.out.println(treeNode); + } + + @Test + public void testExprAnd() { + String expr = "a AND b"; + assertExpr(expr); + } + + @Test + public void testExprMultiAnd() { + String expr = "a AND b AND c AND d"; + assertExpr(expr); + } + + @Test + public void testExprOr() { + String expr = "a OR b"; + assertExpr(expr); + } + + @Test + public void testExprMultiOr() { + String expr = "a OR b OR c OR d"; + assertExpr(expr); + } + + @Test + public void testExprArithmetic() { + String multiply = "1 * 2"; + assertExpr(multiply); + + String divide = "3 / 2"; + assertExpr(divide); + + String mod = "5 % 3"; + assertExpr(mod); + + String add = "3 + 3"; + assertExpr(add); + + String subtract = "3 - 2"; + assertExpr(subtract); + } + + @Test + public void testSqlFunction() throws Exception { + String sum = "select sum(a) from test1"; + assertSql(sum); + + String sumWithAs = "select sum(a) as b from test1"; + assertSql(sumWithAs); + + String sumAndAvg = "select sum(a),avg(b) from test1"; + assertSql(sumAndAvg); + } + + @Test + public void testGroupByClause() throws Exception { + + String groupBy = "select a from test group by a"; + assertSql(groupBy); + + String groupByWithFun1 = "select sum(a), b from test1 group by b"; + assertSql(groupByWithFun1); + + + String groupByWithFun2 = "select sum(a), b, c+1 from test1 group by b, c"; + assertSql(groupByWithFun2); + + String groupBySum = "select k1+k2 from test group by k1+k2"; + assertSql(groupBySum); + } + + @Test + public void testSortClause() throws Exception { + + String sort = "select a from test order by c, d"; + assertSql(sort); + + String sort1 = "select a from test order by 1"; + assertSql(sort1); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org