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

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


The following commit(s) were added to refs/heads/ty/TableModelGrammar by this 
push:
     new cdc1fdd320f partial expression
cdc1fdd320f is described below

commit cdc1fdd320f6e67258290f05e15f100c363c7994
Author: JackieTien97 <[email protected]>
AuthorDate: Wed Feb 7 18:20:14 2024 +0800

    partial expression
---
 .../db/relational/grammar/sql/RelationalSql.g4     |    1 -
 .../iotdb/db/relational/sql/parser/AstBuilder.java | 1042 ++++++++++++++++++++
 .../iotdb/db/relational/sql/tree/AllRows.java      |   67 ++
 .../sql/tree/ArithmeticBinaryExpression.java       |  119 +++
 .../sql/tree/ArithmeticUnaryExpression.java        |  114 +++
 .../iotdb/db/relational/sql/tree/AstVisitor.java   |  404 ++++++++
 .../db/relational/sql/tree/BetweenPredicate.java   |  106 ++
 .../apache/iotdb/db/relational/sql/tree/Cast.java  |  133 +++
 .../db/relational/sql/tree/CoalesceExpression.java |   92 ++
 .../relational/sql/tree/ComparisonExpression.java  |  171 ++++
 .../db/relational/sql/tree/CurrentDatabase.java    |   70 ++
 .../iotdb/db/relational/sql/tree/CurrentUser.java  |   70 ++
 .../sql/tree/{AstVisitor.java => DataType.java}    |   14 +-
 .../{AstVisitor.java => DataTypeParameter.java}    |   15 +-
 .../relational/sql/tree/DereferenceExpression.java |  151 +++
 .../db/relational/sql/tree/DescribeTable.java      |   80 ++
 .../db/relational/sql/tree/ExistsPredicate.java    |   80 ++
 .../sql/tree/{AstVisitor.java => Expression.java}  |   17 +-
 .../db/relational/sql/tree/FieldReference.java     |   80 ++
 .../iotdb/db/relational/sql/tree/FunctionCall.java |  113 +++
 .../db/relational/sql/tree/GenericDataType.java    |   88 ++
 .../iotdb/db/relational/sql/tree/Identifier.java   |  138 +++
 .../iotdb/db/relational/sql/tree/IfExpression.java |  105 ++
 .../db/relational/sql/tree/InListExpression.java   |   83 ++
 .../iotdb/db/relational/sql/tree/InPredicate.java  |   86 ++
 .../sql/tree/{AstVisitor.java => Literal.java}     |   19 +-
 .../apache/iotdb/db/relational/sql/tree/Node.java  |    2 +-
 .../db/relational/sql/tree/NumericParameter.java   |   88 ++
 .../iotdb/db/relational/sql/tree/Property.java     |  120 +++
 .../db/relational/sql/tree/QualifiedName.java      |  139 +++
 .../db/relational/sql/tree/SetProperties.java      |  107 ++
 .../sql/tree/{AstVisitor.java => Statement.java}   |   15 +-
 .../sql/tree/{Node.java => TypeParameter.java}     |   63 +-
 .../apache/iotdb/db/relational/sql/tree/Use.java   |   81 ++
 .../relational/sql/util/ExpressionFormatter.java   |   50 +
 35 files changed, 4050 insertions(+), 73 deletions(-)

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 490ece0393e..e67a6ffe7a5 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
@@ -533,7 +533,6 @@ predicate[ParserRuleContext value]
 
 valueExpression
     : primaryExpression                                                        
         #valueExpressionDefault
-    | valueExpression AT timeZoneSpecifier                                     
         #atTimeZone
     | operator=(MINUS | PLUS) valueExpression                                  
         #arithmeticUnary
     | left=valueExpression operator=(ASTERISK | SLASH | PERCENT) 
right=valueExpression  #arithmeticBinary
     | left=valueExpression operator=(PLUS | MINUS) right=valueExpression       
         #arithmeticBinary
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
index 66654fdb83c..b40c49aded0 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.relational.sql.parser;
 
 import org.apache.iotdb.db.relational.grammar.sql.RelationalSqlBaseVisitor;
+import org.apache.iotdb.db.relational.grammar.sql.RelationalSqlParser;
 import org.apache.iotdb.db.relational.sql.tree.Node;
 import org.apache.iotdb.db.relational.sql.tree.NodeLocation;
 
@@ -41,6 +42,1047 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
     this.baseLocation = baseLocation;
   }
 
+  @Override
+  public Node visitSingleStatement(RelationalSqlParser.SingleStatementContext 
ctx) {
+    return visit(ctx.statement());
+  }
+
+  @Override
+  public Node 
visitUseDatabaseStatement(RelationalSqlParser.UseDatabaseStatementContext ctx) {
+    return super.visitUseDatabaseStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowDatabasesStatement(RelationalSqlParser.ShowDatabasesStatementContext 
ctx) {
+    return super.visitShowDatabasesStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitCreateDbStatement(RelationalSqlParser.CreateDbStatementContext ctx) {
+    return super.visitCreateDbStatement(ctx);
+  }
+
+  @Override
+  public Node visitDropDbStatement(RelationalSqlParser.DropDbStatementContext 
ctx) {
+    return super.visitDropDbStatement(ctx);
+  }
+
+  @Override
+  public Node visitCharsetDesc(RelationalSqlParser.CharsetDescContext ctx) {
+    return super.visitCharsetDesc(ctx);
+  }
+
+  @Override
+  public Node 
visitCreateTableStatement(RelationalSqlParser.CreateTableStatementContext ctx) {
+    return super.visitCreateTableStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitColumnDefinition(RelationalSqlParser.ColumnDefinitionContext ctx) {
+    return super.visitColumnDefinition(ctx);
+  }
+
+  @Override
+  public Node visitColumnCategory(RelationalSqlParser.ColumnCategoryContext 
ctx) {
+    return super.visitColumnCategory(ctx);
+  }
+
+  @Override
+  public Node visitCharsetName(RelationalSqlParser.CharsetNameContext ctx) {
+    return super.visitCharsetName(ctx);
+  }
+
+  @Override
+  public Node 
visitDropTableStatement(RelationalSqlParser.DropTableStatementContext ctx) {
+    return super.visitDropTableStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowTableStatement(RelationalSqlParser.ShowTableStatementContext ctx) {
+    return super.visitShowTableStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitDescTableStatement(RelationalSqlParser.DescTableStatementContext ctx) {
+    return super.visitDescTableStatement(ctx);
+  }
+
+  @Override
+  public Node visitRenameTable(RelationalSqlParser.RenameTableContext ctx) {
+    return super.visitRenameTable(ctx);
+  }
+
+  @Override
+  public Node visitAddColumn(RelationalSqlParser.AddColumnContext ctx) {
+    return super.visitAddColumn(ctx);
+  }
+
+  @Override
+  public Node visitRenameColumn(RelationalSqlParser.RenameColumnContext ctx) {
+    return super.visitRenameColumn(ctx);
+  }
+
+  @Override
+  public Node visitDropColumn(RelationalSqlParser.DropColumnContext ctx) {
+    return super.visitDropColumn(ctx);
+  }
+
+  @Override
+  public Node 
visitSetTableProperties(RelationalSqlParser.SetTablePropertiesContext ctx) {
+    return super.visitSetTableProperties(ctx);
+  }
+
+  @Override
+  public Node 
visitCreateIndexStatement(RelationalSqlParser.CreateIndexStatementContext ctx) {
+    return super.visitCreateIndexStatement(ctx);
+  }
+
+  @Override
+  public Node visitIdentifierList(RelationalSqlParser.IdentifierListContext 
ctx) {
+    return super.visitIdentifierList(ctx);
+  }
+
+  @Override
+  public Node 
visitDropIndexStatement(RelationalSqlParser.DropIndexStatementContext ctx) {
+    return super.visitDropIndexStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowIndexStatement(RelationalSqlParser.ShowIndexStatementContext ctx) {
+    return super.visitShowIndexStatement(ctx);
+  }
+
+  @Override
+  public Node visitInsertStatement(RelationalSqlParser.InsertStatementContext 
ctx) {
+    return super.visitInsertStatement(ctx);
+  }
+
+  @Override
+  public Node visitDeleteStatement(RelationalSqlParser.DeleteStatementContext 
ctx) {
+    return super.visitDeleteStatement(ctx);
+  }
+
+  @Override
+  public Node visitUpdateStatement(RelationalSqlParser.UpdateStatementContext 
ctx) {
+    return super.visitUpdateStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitCreateFunctionStatement(RelationalSqlParser.CreateFunctionStatementContext 
ctx) {
+    return super.visitCreateFunctionStatement(ctx);
+  }
+
+  @Override
+  public Node visitUriClause(RelationalSqlParser.UriClauseContext ctx) {
+    return super.visitUriClause(ctx);
+  }
+
+  @Override
+  public Node 
visitDropFunctionStatement(RelationalSqlParser.DropFunctionStatementContext 
ctx) {
+    return super.visitDropFunctionStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowFunctionsStatement(RelationalSqlParser.ShowFunctionsStatementContext 
ctx) {
+    return super.visitShowFunctionsStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitLoadTsFileStatement(RelationalSqlParser.LoadTsFileStatementContext ctx) {
+    return super.visitLoadTsFileStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowDevicesStatement(RelationalSqlParser.ShowDevicesStatementContext ctx) {
+    return super.visitShowDevicesStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitCountDevicesStatement(RelationalSqlParser.CountDevicesStatementContext 
ctx) {
+    return super.visitCountDevicesStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowClusterStatement(RelationalSqlParser.ShowClusterStatementContext ctx) {
+    return super.visitShowClusterStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowRegionsStatement(RelationalSqlParser.ShowRegionsStatementContext ctx) {
+    return super.visitShowRegionsStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowDataNodesStatement(RelationalSqlParser.ShowDataNodesStatementContext 
ctx) {
+    return super.visitShowDataNodesStatement(ctx);
+  }
+
+  @Override
+  public Node visitShowConfigNodesStatement(
+      RelationalSqlParser.ShowConfigNodesStatementContext ctx) {
+    return super.visitShowConfigNodesStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowClusterIdStatement(RelationalSqlParser.ShowClusterIdStatementContext 
ctx) {
+    return super.visitShowClusterIdStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowRegionIdStatement(RelationalSqlParser.ShowRegionIdStatementContext 
ctx) {
+    return super.visitShowRegionIdStatement(ctx);
+  }
+
+  @Override
+  public Node visitShowTimeSlotListStatement(
+      RelationalSqlParser.ShowTimeSlotListStatementContext ctx) {
+    return super.visitShowTimeSlotListStatement(ctx);
+  }
+
+  @Override
+  public Node visitCountTimeSlotListStatement(
+      RelationalSqlParser.CountTimeSlotListStatementContext ctx) {
+    return super.visitCountTimeSlotListStatement(ctx);
+  }
+
+  @Override
+  public Node visitShowSeriesSlotListStatement(
+      RelationalSqlParser.ShowSeriesSlotListStatementContext ctx) {
+    return super.visitShowSeriesSlotListStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitMigrateRegionStatement(RelationalSqlParser.MigrateRegionStatementContext 
ctx) {
+    return super.visitMigrateRegionStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowVariablesStatement(RelationalSqlParser.ShowVariablesStatementContext 
ctx) {
+    return super.visitShowVariablesStatement(ctx);
+  }
+
+  @Override
+  public Node visitFlushStatement(RelationalSqlParser.FlushStatementContext 
ctx) {
+    return super.visitFlushStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitClearCacheStatement(RelationalSqlParser.ClearCacheStatementContext ctx) {
+    return super.visitClearCacheStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitRepairDataStatement(RelationalSqlParser.RepairDataStatementContext ctx) {
+    return super.visitRepairDataStatement(ctx);
+  }
+
+  @Override
+  public Node visitSetSystemStatusStatement(
+      RelationalSqlParser.SetSystemStatusStatementContext ctx) {
+    return super.visitSetSystemStatusStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowVersionStatement(RelationalSqlParser.ShowVersionStatementContext ctx) {
+    return super.visitShowVersionStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitShowQueriesStatement(RelationalSqlParser.ShowQueriesStatementContext ctx) {
+    return super.visitShowQueriesStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitKillQueryStatement(RelationalSqlParser.KillQueryStatementContext ctx) {
+    return super.visitKillQueryStatement(ctx);
+  }
+
+  @Override
+  public Node visitLoadConfigurationStatement(
+      RelationalSqlParser.LoadConfigurationStatementContext ctx) {
+    return super.visitLoadConfigurationStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitLocalOrClusterMode(RelationalSqlParser.LocalOrClusterModeContext ctx) {
+    return super.visitLocalOrClusterMode(ctx);
+  }
+
+  @Override
+  public Node 
visitStatementDefault(RelationalSqlParser.StatementDefaultContext ctx) {
+    return super.visitStatementDefault(ctx);
+  }
+
+  @Override
+  public Node visitExplain(RelationalSqlParser.ExplainContext ctx) {
+    return super.visitExplain(ctx);
+  }
+
+  @Override
+  public Node visitExplainAnalyze(RelationalSqlParser.ExplainAnalyzeContext 
ctx) {
+    return super.visitExplainAnalyze(ctx);
+  }
+
+  @Override
+  public Node visitQuery(RelationalSqlParser.QueryContext ctx) {
+    return super.visitQuery(ctx);
+  }
+
+  @Override
+  public Node visitWith(RelationalSqlParser.WithContext ctx) {
+    return super.visitWith(ctx);
+  }
+
+  @Override
+  public Node visitProperties(RelationalSqlParser.PropertiesContext ctx) {
+    return super.visitProperties(ctx);
+  }
+
+  @Override
+  public Node 
visitPropertyAssignments(RelationalSqlParser.PropertyAssignmentsContext ctx) {
+    return super.visitPropertyAssignments(ctx);
+  }
+
+  @Override
+  public Node visitProperty(RelationalSqlParser.PropertyContext ctx) {
+    return super.visitProperty(ctx);
+  }
+
+  @Override
+  public Node 
visitDefaultPropertyValue(RelationalSqlParser.DefaultPropertyValueContext ctx) {
+    return super.visitDefaultPropertyValue(ctx);
+  }
+
+  @Override
+  public Node 
visitNonDefaultPropertyValue(RelationalSqlParser.NonDefaultPropertyValueContext 
ctx) {
+    return super.visitNonDefaultPropertyValue(ctx);
+  }
+
+  @Override
+  public Node visitQueryNoWith(RelationalSqlParser.QueryNoWithContext ctx) {
+    return super.visitQueryNoWith(ctx);
+  }
+
+  @Override
+  public Node visitLimitRowCount(RelationalSqlParser.LimitRowCountContext ctx) 
{
+    return super.visitLimitRowCount(ctx);
+  }
+
+  @Override
+  public Node visitRowCount(RelationalSqlParser.RowCountContext ctx) {
+    return super.visitRowCount(ctx);
+  }
+
+  @Override
+  public Node 
visitQueryTermDefault(RelationalSqlParser.QueryTermDefaultContext ctx) {
+    return super.visitQueryTermDefault(ctx);
+  }
+
+  @Override
+  public Node visitSetOperation(RelationalSqlParser.SetOperationContext ctx) {
+    return super.visitSetOperation(ctx);
+  }
+
+  @Override
+  public Node 
visitQueryPrimaryDefault(RelationalSqlParser.QueryPrimaryDefaultContext ctx) {
+    return super.visitQueryPrimaryDefault(ctx);
+  }
+
+  @Override
+  public Node visitTable(RelationalSqlParser.TableContext ctx) {
+    return super.visitTable(ctx);
+  }
+
+  @Override
+  public Node visitInlineTable(RelationalSqlParser.InlineTableContext ctx) {
+    return super.visitInlineTable(ctx);
+  }
+
+  @Override
+  public Node visitSubquery(RelationalSqlParser.SubqueryContext ctx) {
+    return super.visitSubquery(ctx);
+  }
+
+  @Override
+  public Node visitSortItem(RelationalSqlParser.SortItemContext ctx) {
+    return super.visitSortItem(ctx);
+  }
+
+  @Override
+  public Node 
visitQuerySpecification(RelationalSqlParser.QuerySpecificationContext ctx) {
+    return super.visitQuerySpecification(ctx);
+  }
+
+  @Override
+  public Node visitGroupBy(RelationalSqlParser.GroupByContext ctx) {
+    return super.visitGroupBy(ctx);
+  }
+
+  @Override
+  public Node visitTimenGrouping(RelationalSqlParser.TimenGroupingContext ctx) 
{
+    return super.visitTimenGrouping(ctx);
+  }
+
+  @Override
+  public Node 
visitVariationGrouping(RelationalSqlParser.VariationGroupingContext ctx) {
+    return super.visitVariationGrouping(ctx);
+  }
+
+  @Override
+  public Node 
visitConditionGrouping(RelationalSqlParser.ConditionGroupingContext ctx) {
+    return super.visitConditionGrouping(ctx);
+  }
+
+  @Override
+  public Node visitSessionGrouping(RelationalSqlParser.SessionGroupingContext 
ctx) {
+    return super.visitSessionGrouping(ctx);
+  }
+
+  @Override
+  public Node visitCountGrouping(RelationalSqlParser.CountGroupingContext ctx) 
{
+    return super.visitCountGrouping(ctx);
+  }
+
+  @Override
+  public Node 
visitSingleGroupingSet(RelationalSqlParser.SingleGroupingSetContext ctx) {
+    return super.visitSingleGroupingSet(ctx);
+  }
+
+  @Override
+  public Node visitRollup(RelationalSqlParser.RollupContext ctx) {
+    return super.visitRollup(ctx);
+  }
+
+  @Override
+  public Node visitCube(RelationalSqlParser.CubeContext ctx) {
+    return super.visitCube(ctx);
+  }
+
+  @Override
+  public Node 
visitMultipleGroupingSets(RelationalSqlParser.MultipleGroupingSetsContext ctx) {
+    return super.visitMultipleGroupingSets(ctx);
+  }
+
+  @Override
+  public Node 
visitLeftClosedRightOpen(RelationalSqlParser.LeftClosedRightOpenContext ctx) {
+    return super.visitLeftClosedRightOpen(ctx);
+  }
+
+  @Override
+  public Node 
visitLeftOpenRightClosed(RelationalSqlParser.LeftOpenRightClosedContext ctx) {
+    return super.visitLeftOpenRightClosed(ctx);
+  }
+
+  @Override
+  public Node visitTimeValue(RelationalSqlParser.TimeValueContext ctx) {
+    return super.visitTimeValue(ctx);
+  }
+
+  @Override
+  public Node visitDateExpression(RelationalSqlParser.DateExpressionContext 
ctx) {
+    return super.visitDateExpression(ctx);
+  }
+
+  @Override
+  public Node visitDatetimeLiteral(RelationalSqlParser.DatetimeLiteralContext 
ctx) {
+    return super.visitDatetimeLiteral(ctx);
+  }
+
+  @Override
+  public Node visitKeepExpression(RelationalSqlParser.KeepExpressionContext 
ctx) {
+    return super.visitKeepExpression(ctx);
+  }
+
+  @Override
+  public Node visitGroupingSet(RelationalSqlParser.GroupingSetContext ctx) {
+    return super.visitGroupingSet(ctx);
+  }
+
+  @Override
+  public Node visitNamedQuery(RelationalSqlParser.NamedQueryContext ctx) {
+    return super.visitNamedQuery(ctx);
+  }
+
+  @Override
+  public Node visitSetQuantifier(RelationalSqlParser.SetQuantifierContext ctx) 
{
+    return super.visitSetQuantifier(ctx);
+  }
+
+  @Override
+  public Node visitSelectSingle(RelationalSqlParser.SelectSingleContext ctx) {
+    return super.visitSelectSingle(ctx);
+  }
+
+  @Override
+  public Node visitSelectAll(RelationalSqlParser.SelectAllContext ctx) {
+    return super.visitSelectAll(ctx);
+  }
+
+  @Override
+  public Node visitRelationDefault(RelationalSqlParser.RelationDefaultContext 
ctx) {
+    return super.visitRelationDefault(ctx);
+  }
+
+  @Override
+  public Node visitJoinRelation(RelationalSqlParser.JoinRelationContext ctx) {
+    return super.visitJoinRelation(ctx);
+  }
+
+  @Override
+  public Node visitJoinType(RelationalSqlParser.JoinTypeContext ctx) {
+    return super.visitJoinType(ctx);
+  }
+
+  @Override
+  public Node visitJoinCriteria(RelationalSqlParser.JoinCriteriaContext ctx) {
+    return super.visitJoinCriteria(ctx);
+  }
+
+  @Override
+  public Node visitAliasedRelation(RelationalSqlParser.AliasedRelationContext 
ctx) {
+    return super.visitAliasedRelation(ctx);
+  }
+
+  @Override
+  public Node visitColumnAliases(RelationalSqlParser.ColumnAliasesContext ctx) 
{
+    return super.visitColumnAliases(ctx);
+  }
+
+  @Override
+  public Node visitTableName(RelationalSqlParser.TableNameContext ctx) {
+    return super.visitTableName(ctx);
+  }
+
+  @Override
+  public Node 
visitSubqueryRelation(RelationalSqlParser.SubqueryRelationContext ctx) {
+    return super.visitSubqueryRelation(ctx);
+  }
+
+  @Override
+  public Node 
visitParenthesizedRelation(RelationalSqlParser.ParenthesizedRelationContext 
ctx) {
+    return super.visitParenthesizedRelation(ctx);
+  }
+
+  @Override
+  public Node visitExpression(RelationalSqlParser.ExpressionContext ctx) {
+    return super.visitExpression(ctx);
+  }
+
+  @Override
+  public Node visitLogicalNot(RelationalSqlParser.LogicalNotContext ctx) {
+    return super.visitLogicalNot(ctx);
+  }
+
+  @Override
+  public Node visitPredicated(RelationalSqlParser.PredicatedContext ctx) {
+    return super.visitPredicated(ctx);
+  }
+
+  @Override
+  public Node visitOr(RelationalSqlParser.OrContext ctx) {
+    return super.visitOr(ctx);
+  }
+
+  @Override
+  public Node visitAnd(RelationalSqlParser.AndContext ctx) {
+    return super.visitAnd(ctx);
+  }
+
+  @Override
+  public Node visitComparison(RelationalSqlParser.ComparisonContext ctx) {
+    return super.visitComparison(ctx);
+  }
+
+  @Override
+  public Node 
visitQuantifiedComparison(RelationalSqlParser.QuantifiedComparisonContext ctx) {
+    return super.visitQuantifiedComparison(ctx);
+  }
+
+  @Override
+  public Node visitBetween(RelationalSqlParser.BetweenContext ctx) {
+    return super.visitBetween(ctx);
+  }
+
+  @Override
+  public Node visitInList(RelationalSqlParser.InListContext ctx) {
+    return super.visitInList(ctx);
+  }
+
+  @Override
+  public Node visitInSubquery(RelationalSqlParser.InSubqueryContext ctx) {
+    return super.visitInSubquery(ctx);
+  }
+
+  @Override
+  public Node visitLike(RelationalSqlParser.LikeContext ctx) {
+    return super.visitLike(ctx);
+  }
+
+  @Override
+  public Node visitNullPredicate(RelationalSqlParser.NullPredicateContext ctx) 
{
+    return super.visitNullPredicate(ctx);
+  }
+
+  @Override
+  public Node visitDistinctFrom(RelationalSqlParser.DistinctFromContext ctx) {
+    return super.visitDistinctFrom(ctx);
+  }
+
+  @Override
+  public Node 
visitValueExpressionDefault(RelationalSqlParser.ValueExpressionDefaultContext 
ctx) {
+    return super.visitValueExpressionDefault(ctx);
+  }
+
+  @Override
+  public Node visitConcatenation(RelationalSqlParser.ConcatenationContext ctx) 
{
+    return super.visitConcatenation(ctx);
+  }
+
+  @Override
+  public Node 
visitArithmeticBinary(RelationalSqlParser.ArithmeticBinaryContext ctx) {
+    return super.visitArithmeticBinary(ctx);
+  }
+
+  @Override
+  public Node visitArithmeticUnary(RelationalSqlParser.ArithmeticUnaryContext 
ctx) {
+    return super.visitArithmeticUnary(ctx);
+  }
+
+  @Override
+  public Node visitAtTimeZone(RelationalSqlParser.AtTimeZoneContext ctx) {
+    return super.visitAtTimeZone(ctx);
+  }
+
+  @Override
+  public Node visitDereference(RelationalSqlParser.DereferenceContext ctx) {
+    return super.visitDereference(ctx);
+  }
+
+  @Override
+  public Node visitSimpleCase(RelationalSqlParser.SimpleCaseContext ctx) {
+    return super.visitSimpleCase(ctx);
+  }
+
+  @Override
+  public Node visitColumnReference(RelationalSqlParser.ColumnReferenceContext 
ctx) {
+    return super.visitColumnReference(ctx);
+  }
+
+  @Override
+  public Node 
visitSpecialDateTimeFunction(RelationalSqlParser.SpecialDateTimeFunctionContext 
ctx) {
+    return super.visitSpecialDateTimeFunction(ctx);
+  }
+
+  @Override
+  public Node 
visitSubqueryExpression(RelationalSqlParser.SubqueryExpressionContext ctx) {
+    return super.visitSubqueryExpression(ctx);
+  }
+
+  @Override
+  public Node visitCurrentDatabase(RelationalSqlParser.CurrentDatabaseContext 
ctx) {
+    return super.visitCurrentDatabase(ctx);
+  }
+
+  @Override
+  public Node visitSubstring(RelationalSqlParser.SubstringContext ctx) {
+    return super.visitSubstring(ctx);
+  }
+
+  @Override
+  public Node visitLiteral(RelationalSqlParser.LiteralContext ctx) {
+    return super.visitLiteral(ctx);
+  }
+
+  @Override
+  public Node visitCast(RelationalSqlParser.CastContext ctx) {
+    return super.visitCast(ctx);
+  }
+
+  @Override
+  public Node visitCurrentUser(RelationalSqlParser.CurrentUserContext ctx) {
+    return super.visitCurrentUser(ctx);
+  }
+
+  @Override
+  public Node 
visitParenthesizedExpression(RelationalSqlParser.ParenthesizedExpressionContext 
ctx) {
+    return super.visitParenthesizedExpression(ctx);
+  }
+
+  @Override
+  public Node visitTrim(RelationalSqlParser.TrimContext ctx) {
+    return super.visitTrim(ctx);
+  }
+
+  @Override
+  public Node visitFunctionCall(RelationalSqlParser.FunctionCallContext ctx) {
+    return super.visitFunctionCall(ctx);
+  }
+
+  @Override
+  public Node visitExists(RelationalSqlParser.ExistsContext ctx) {
+    return super.visitExists(ctx);
+  }
+
+  @Override
+  public Node visitSearchedCase(RelationalSqlParser.SearchedCaseContext ctx) {
+    return super.visitSearchedCase(ctx);
+  }
+
+  @Override
+  public Node visitNullLiteral(RelationalSqlParser.NullLiteralContext ctx) {
+    return super.visitNullLiteral(ctx);
+  }
+
+  @Override
+  public Node visitNumericLiteral(RelationalSqlParser.NumericLiteralContext 
ctx) {
+    return super.visitNumericLiteral(ctx);
+  }
+
+  @Override
+  public Node visitBooleanLiteral(RelationalSqlParser.BooleanLiteralContext 
ctx) {
+    return super.visitBooleanLiteral(ctx);
+  }
+
+  @Override
+  public Node visitStringLiteral(RelationalSqlParser.StringLiteralContext ctx) 
{
+    return super.visitStringLiteral(ctx);
+  }
+
+  @Override
+  public Node visitBinaryLiteral(RelationalSqlParser.BinaryLiteralContext ctx) 
{
+    return super.visitBinaryLiteral(ctx);
+  }
+
+  @Override
+  public Node visitParameter(RelationalSqlParser.ParameterContext ctx) {
+    return super.visitParameter(ctx);
+  }
+
+  @Override
+  public Node 
visitTrimsSpecification(RelationalSqlParser.TrimsSpecificationContext ctx) {
+    return super.visitTrimsSpecification(ctx);
+  }
+
+  @Override
+  public Node 
visitBasicStringLiteral(RelationalSqlParser.BasicStringLiteralContext ctx) {
+    return super.visitBasicStringLiteral(ctx);
+  }
+
+  @Override
+  public Node 
visitUnicodeStringLiteral(RelationalSqlParser.UnicodeStringLiteralContext ctx) {
+    return super.visitUnicodeStringLiteral(ctx);
+  }
+
+  @Override
+  public Node 
visitIdentifierOrString(RelationalSqlParser.IdentifierOrStringContext ctx) {
+    return super.visitIdentifierOrString(ctx);
+  }
+
+  @Override
+  public Node 
visitTimeZoneInterval(RelationalSqlParser.TimeZoneIntervalContext ctx) {
+    return super.visitTimeZoneInterval(ctx);
+  }
+
+  @Override
+  public Node visitTimeZoneString(RelationalSqlParser.TimeZoneStringContext 
ctx) {
+    return super.visitTimeZoneString(ctx);
+  }
+
+  @Override
+  public Node 
visitComparisonOperator(RelationalSqlParser.ComparisonOperatorContext ctx) {
+    return super.visitComparisonOperator(ctx);
+  }
+
+  @Override
+  public Node 
visitComparisonQuantifier(RelationalSqlParser.ComparisonQuantifierContext ctx) {
+    return super.visitComparisonQuantifier(ctx);
+  }
+
+  @Override
+  public Node visitBooleanValue(RelationalSqlParser.BooleanValueContext ctx) {
+    return super.visitBooleanValue(ctx);
+  }
+
+  @Override
+  public Node visitInterval(RelationalSqlParser.IntervalContext ctx) {
+    return super.visitInterval(ctx);
+  }
+
+  @Override
+  public Node visitIntervalField(RelationalSqlParser.IntervalFieldContext ctx) 
{
+    return super.visitIntervalField(ctx);
+  }
+
+  @Override
+  public Node visitTimeDuration(RelationalSqlParser.TimeDurationContext ctx) {
+    return super.visitTimeDuration(ctx);
+  }
+
+  @Override
+  public Node visitGenericType(RelationalSqlParser.GenericTypeContext ctx) {
+    return super.visitGenericType(ctx);
+  }
+
+  @Override
+  public Node visitTypeParameter(RelationalSqlParser.TypeParameterContext ctx) 
{
+    return super.visitTypeParameter(ctx);
+  }
+
+  @Override
+  public Node visitWhenClause(RelationalSqlParser.WhenClauseContext ctx) {
+    return super.visitWhenClause(ctx);
+  }
+
+  @Override
+  public Node 
visitQuantifiedPrimary(RelationalSqlParser.QuantifiedPrimaryContext ctx) {
+    return super.visitQuantifiedPrimary(ctx);
+  }
+
+  @Override
+  public Node 
visitPatternConcatenation(RelationalSqlParser.PatternConcatenationContext ctx) {
+    return super.visitPatternConcatenation(ctx);
+  }
+
+  @Override
+  public Node 
visitPatternAlternation(RelationalSqlParser.PatternAlternationContext ctx) {
+    return super.visitPatternAlternation(ctx);
+  }
+
+  @Override
+  public Node visitPatternVariable(RelationalSqlParser.PatternVariableContext 
ctx) {
+    return super.visitPatternVariable(ctx);
+  }
+
+  @Override
+  public Node visitEmptyPattern(RelationalSqlParser.EmptyPatternContext ctx) {
+    return super.visitEmptyPattern(ctx);
+  }
+
+  @Override
+  public Node 
visitPatternPermutation(RelationalSqlParser.PatternPermutationContext ctx) {
+    return super.visitPatternPermutation(ctx);
+  }
+
+  @Override
+  public Node visitGroupedPattern(RelationalSqlParser.GroupedPatternContext 
ctx) {
+    return super.visitGroupedPattern(ctx);
+  }
+
+  @Override
+  public Node 
visitPartitionStartAnchor(RelationalSqlParser.PartitionStartAnchorContext ctx) {
+    return super.visitPartitionStartAnchor(ctx);
+  }
+
+  @Override
+  public Node 
visitPartitionEndAnchor(RelationalSqlParser.PartitionEndAnchorContext ctx) {
+    return super.visitPartitionEndAnchor(ctx);
+  }
+
+  @Override
+  public Node visitExcludedPattern(RelationalSqlParser.ExcludedPatternContext 
ctx) {
+    return super.visitExcludedPattern(ctx);
+  }
+
+  @Override
+  public Node 
visitZeroOrMoreQuantifier(RelationalSqlParser.ZeroOrMoreQuantifierContext ctx) {
+    return super.visitZeroOrMoreQuantifier(ctx);
+  }
+
+  @Override
+  public Node 
visitOneOrMoreQuantifier(RelationalSqlParser.OneOrMoreQuantifierContext ctx) {
+    return super.visitOneOrMoreQuantifier(ctx);
+  }
+
+  @Override
+  public Node 
visitZeroOrOneQuantifier(RelationalSqlParser.ZeroOrOneQuantifierContext ctx) {
+    return super.visitZeroOrOneQuantifier(ctx);
+  }
+
+  @Override
+  public Node visitRangeQuantifier(RelationalSqlParser.RangeQuantifierContext 
ctx) {
+    return super.visitRangeQuantifier(ctx);
+  }
+
+  @Override
+  public Node 
visitUpdateAssignment(RelationalSqlParser.UpdateAssignmentContext ctx) {
+    return super.visitUpdateAssignment(ctx);
+  }
+
+  @Override
+  public Node visitReturnStatement(RelationalSqlParser.ReturnStatementContext 
ctx) {
+    return super.visitReturnStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitAssignmentStatement(RelationalSqlParser.AssignmentStatementContext ctx) {
+    return super.visitAssignmentStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitSimpleCaseStatement(RelationalSqlParser.SimpleCaseStatementContext ctx) {
+    return super.visitSimpleCaseStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitSearchedCaseStatement(RelationalSqlParser.SearchedCaseStatementContext 
ctx) {
+    return super.visitSearchedCaseStatement(ctx);
+  }
+
+  @Override
+  public Node visitIfStatement(RelationalSqlParser.IfStatementContext ctx) {
+    return super.visitIfStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitIterateStatement(RelationalSqlParser.IterateStatementContext ctx) {
+    return super.visitIterateStatement(ctx);
+  }
+
+  @Override
+  public Node visitLeaveStatement(RelationalSqlParser.LeaveStatementContext 
ctx) {
+    return super.visitLeaveStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitCompoundStatement(RelationalSqlParser.CompoundStatementContext ctx) {
+    return super.visitCompoundStatement(ctx);
+  }
+
+  @Override
+  public Node visitLoopStatement(RelationalSqlParser.LoopStatementContext ctx) 
{
+    return super.visitLoopStatement(ctx);
+  }
+
+  @Override
+  public Node visitWhileStatement(RelationalSqlParser.WhileStatementContext 
ctx) {
+    return super.visitWhileStatement(ctx);
+  }
+
+  @Override
+  public Node visitRepeatStatement(RelationalSqlParser.RepeatStatementContext 
ctx) {
+    return super.visitRepeatStatement(ctx);
+  }
+
+  @Override
+  public Node 
visitCaseStatementWhenClause(RelationalSqlParser.CaseStatementWhenClauseContext 
ctx) {
+    return super.visitCaseStatementWhenClause(ctx);
+  }
+
+  @Override
+  public Node visitElseIfClause(RelationalSqlParser.ElseIfClauseContext ctx) {
+    return super.visitElseIfClause(ctx);
+  }
+
+  @Override
+  public Node visitElseClause(RelationalSqlParser.ElseClauseContext ctx) {
+    return super.visitElseClause(ctx);
+  }
+
+  @Override
+  public Node 
visitVariableDeclaration(RelationalSqlParser.VariableDeclarationContext ctx) {
+    return super.visitVariableDeclaration(ctx);
+  }
+
+  @Override
+  public Node 
visitSqlStatementList(RelationalSqlParser.SqlStatementListContext ctx) {
+    return super.visitSqlStatementList(ctx);
+  }
+
+  @Override
+  public Node visitPrivilege(RelationalSqlParser.PrivilegeContext ctx) {
+    return super.visitPrivilege(ctx);
+  }
+
+  @Override
+  public Node visitQualifiedName(RelationalSqlParser.QualifiedNameContext ctx) 
{
+    return super.visitQualifiedName(ctx);
+  }
+
+  @Override
+  public Node 
visitSpecifiedPrincipal(RelationalSqlParser.SpecifiedPrincipalContext ctx) {
+    return super.visitSpecifiedPrincipal(ctx);
+  }
+
+  @Override
+  public Node 
visitCurrentUserGrantor(RelationalSqlParser.CurrentUserGrantorContext ctx) {
+    return super.visitCurrentUserGrantor(ctx);
+  }
+
+  @Override
+  public Node 
visitCurrentRoleGrantor(RelationalSqlParser.CurrentRoleGrantorContext ctx) {
+    return super.visitCurrentRoleGrantor(ctx);
+  }
+
+  @Override
+  public Node 
visitUnspecifiedPrincipal(RelationalSqlParser.UnspecifiedPrincipalContext ctx) {
+    return super.visitUnspecifiedPrincipal(ctx);
+  }
+
+  @Override
+  public Node visitUserPrincipal(RelationalSqlParser.UserPrincipalContext ctx) 
{
+    return super.visitUserPrincipal(ctx);
+  }
+
+  @Override
+  public Node visitRolePrincipal(RelationalSqlParser.RolePrincipalContext ctx) 
{
+    return super.visitRolePrincipal(ctx);
+  }
+
+  @Override
+  public Node visitRoles(RelationalSqlParser.RolesContext ctx) {
+    return super.visitRoles(ctx);
+  }
+
+  @Override
+  public Node 
visitUnquotedIdentifier(RelationalSqlParser.UnquotedIdentifierContext ctx) {
+    return super.visitUnquotedIdentifier(ctx);
+  }
+
+  @Override
+  public Node 
visitQuotedIdentifier(RelationalSqlParser.QuotedIdentifierContext ctx) {
+    return super.visitQuotedIdentifier(ctx);
+  }
+
+  @Override
+  public Node 
visitBackQuotedIdentifier(RelationalSqlParser.BackQuotedIdentifierContext ctx) {
+    return super.visitBackQuotedIdentifier(ctx);
+  }
+
+  @Override
+  public Node visitDigitIdentifier(RelationalSqlParser.DigitIdentifierContext 
ctx) {
+    return super.visitDigitIdentifier(ctx);
+  }
+
+  @Override
+  public Node visitDecimalLiteral(RelationalSqlParser.DecimalLiteralContext 
ctx) {
+    return super.visitDecimalLiteral(ctx);
+  }
+
+  @Override
+  public Node visitDoubleLiteral(RelationalSqlParser.DoubleLiteralContext ctx) 
{
+    return super.visitDoubleLiteral(ctx);
+  }
+
+  @Override
+  public Node visitIntegerLiteral(RelationalSqlParser.IntegerLiteralContext 
ctx) {
+    return super.visitIntegerLiteral(ctx);
+  }
+
+  @Override
+  public Node visitIdentifierUser(RelationalSqlParser.IdentifierUserContext 
ctx) {
+    return super.visitIdentifierUser(ctx);
+  }
+
+  @Override
+  public Node visitStringUser(RelationalSqlParser.StringUserContext ctx) {
+    return super.visitStringUser(ctx);
+  }
+
+  @Override
+  public Node visitNonReserved(RelationalSqlParser.NonReservedContext ctx) {
+    return super.visitNonReserved(ctx);
+  }
+
   private NodeLocation getLocation(TerminalNode terminalNode) {
     requireNonNull(terminalNode, "terminalNode is null");
     return getLocation(terminalNode.getSymbol());
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AllRows.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AllRows.java
new file mode 100644
index 00000000000..d2940551401
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AllRows.java
@@ -0,0 +1,67 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public final class AllRows extends Expression {
+
+  public AllRows() {
+    super(null);
+  }
+
+  public AllRows(@Nonnull NodeLocation location) {
+    super(requireNonNull(location, "location is null"));
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitAllRows(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    return (o != null) && (getClass() == o.getClass());
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode();
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticBinaryExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticBinaryExpression.java
new file mode 100644
index 00000000000..9bcfeedbc8c
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticBinaryExpression.java
@@ -0,0 +1,119 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class ArithmeticBinaryExpression extends Expression {
+
+  public enum Operator {
+    ADD("+"),
+    SUBTRACT("-"),
+    MULTIPLY("*"),
+    DIVIDE("/"),
+    MODULUS("%");
+    private final String value;
+
+    Operator(String value) {
+      this.value = value;
+    }
+
+    public String getValue() {
+      return value;
+    }
+  }
+
+  private final Operator operator;
+  private final Expression left;
+  private final Expression right;
+
+  public ArithmeticBinaryExpression(Operator operator, Expression left, 
Expression right) {
+    super(null);
+    this.operator = operator;
+    this.left = left;
+    this.right = right;
+  }
+
+  public ArithmeticBinaryExpression(
+      @Nonnull NodeLocation location, Operator operator, Expression left, 
Expression right) {
+    super(requireNonNull(location, "location is null"));
+    this.operator = operator;
+    this.left = left;
+    this.right = right;
+  }
+
+  public Operator getOperator() {
+    return operator;
+  }
+
+  public Expression getLeft() {
+    return left;
+  }
+
+  public Expression getRight() {
+    return right;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitArithmeticBinary(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(left, right);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    ArithmeticBinaryExpression that = (ArithmeticBinaryExpression) o;
+    return (operator == that.operator)
+        && Objects.equals(left, that.left)
+        && Objects.equals(right, that.right);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(operator, left, right);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    return operator == ((ArithmeticBinaryExpression) other).operator;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticUnaryExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticUnaryExpression.java
new file mode 100644
index 00000000000..364acc94a33
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ArithmeticUnaryExpression.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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class ArithmeticUnaryExpression extends Expression {
+
+  public enum Sign {
+    PLUS,
+    MINUS
+  }
+
+  private final Expression value;
+  private final Sign sign;
+
+  private ArithmeticUnaryExpression(NodeLocation location, Sign sign, 
Expression value) {
+    super(location);
+    requireNonNull(value, "value is null");
+    requireNonNull(sign, "sign is null");
+
+    this.value = value;
+    this.sign = sign;
+  }
+
+  public static ArithmeticUnaryExpression positive(
+      @Nonnull NodeLocation location, Expression value) {
+    return new ArithmeticUnaryExpression(
+        requireNonNull(location, "location is null"), Sign.PLUS, value);
+  }
+
+  public static ArithmeticUnaryExpression negative(
+      @Nonnull NodeLocation location, Expression value) {
+    return new ArithmeticUnaryExpression(
+        requireNonNull(location, "location is null"), Sign.MINUS, value);
+  }
+
+  public static ArithmeticUnaryExpression positive(Expression value) {
+    return new ArithmeticUnaryExpression(null, Sign.PLUS, value);
+  }
+
+  public static ArithmeticUnaryExpression negative(Expression value) {
+    return new ArithmeticUnaryExpression(null, Sign.MINUS, value);
+  }
+
+  public Expression getValue() {
+    return value;
+  }
+
+  public Sign getSign() {
+    return sign;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitArithmeticUnary(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(value);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    ArithmeticUnaryExpression that = (ArithmeticUnaryExpression) o;
+    return Objects.equals(value, that.value) && (sign == that.sign);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(value, sign);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    return sign == ((ArithmeticUnaryExpression) other).sign;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
index b8e0c07973a..607c3a1a93b 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
@@ -34,4 +34,408 @@ public abstract class AstVisitor<R, C> {
   protected R visitNode(Node node, C context) {
     return null;
   }
+
+  protected R visitExpression(Expression node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitCurrentTime(CurrentTime node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitArithmeticBinary(ArithmeticBinaryExpression node, C 
context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitBetweenPredicate(BetweenPredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitCoalesceExpression(CoalesceExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitComparisonExpression(ComparisonExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitLiteral(Literal node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitDoubleLiteral(DoubleLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitDecimalLiteral(DecimalLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitStatement(Statement node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitQuery(Query node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitExplain(Explain node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitExplainAnalyze(ExplainAnalyze node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitShowFunctions(ShowFunctions node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitUse(Use node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitGenericLiteral(GenericLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitWith(With node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitWithQuery(WithQuery node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitSelect(Select node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitRelation(Relation node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitQueryBody(QueryBody node, C context) {
+    return visitRelation(node, context);
+  }
+
+  protected R visitOrderBy(OrderBy node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitOffset(Offset node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitLimit(Limit node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitAllRows(AllRows node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitQuerySpecification(QuerySpecification node, C context) {
+    return visitQueryBody(node, context);
+  }
+
+  protected R visitSetOperation(SetOperation node, C context) {
+    return visitQueryBody(node, context);
+  }
+
+  protected R visitUnion(Union node, C context) {
+    return visitSetOperation(node, context);
+  }
+
+  protected R visitIntersect(Intersect node, C context) {
+    return visitSetOperation(node, context);
+  }
+
+  protected R visitExcept(Except node, C context) {
+    return visitSetOperation(node, context);
+  }
+
+  protected R visitWhenClause(WhenClause node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitInPredicate(InPredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitFunctionCall(FunctionCall node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitSimpleCaseExpression(SimpleCaseExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitSearchedCaseExpression(SearchedCaseExpression node, C 
context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitStringLiteral(StringLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitBinaryLiteral(BinaryLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitBooleanLiteral(BooleanLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitInListExpression(InListExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitIdentifier(Identifier node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitDereferenceExpression(DereferenceExpression node, C 
context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitTrim(Trim node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitNullIfExpression(NullIfExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitIfExpression(IfExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitNullLiteral(NullLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitArithmeticUnary(ArithmeticUnaryExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitNotExpression(NotExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitSelectItem(SelectItem node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitSingleColumn(SingleColumn node, C context) {
+    return visitSelectItem(node, context);
+  }
+
+  protected R visitAllColumns(AllColumns node, C context) {
+    return visitSelectItem(node, context);
+  }
+
+  protected R visitLikePredicate(LikePredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitIsNotNullPredicate(IsNotNullPredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitIsNullPredicate(IsNullPredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitLongLiteral(LongLiteral node, C context) {
+    return visitLiteral(node, context);
+  }
+
+  protected R visitParameter(Parameter node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitLogicalExpression(LogicalExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitSubqueryExpression(SubqueryExpression node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitSortItem(SortItem node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitTable(Table node, C context) {
+    return visitQueryBody(node, context);
+  }
+
+  protected R visitValues(Values node, C context) {
+    return visitQueryBody(node, context);
+  }
+
+  protected R visitTableSubquery(TableSubquery node, C context) {
+    return visitQueryBody(node, context);
+  }
+
+  protected R visitAliasedRelation(AliasedRelation node, C context) {
+    return visitRelation(node, context);
+  }
+
+  protected R visitSampledRelation(SampledRelation node, C context) {
+    return visitRelation(node, context);
+  }
+
+  protected R visitJoin(Join node, C context) {
+    return visitRelation(node, context);
+  }
+
+  protected R visitExists(ExistsPredicate node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitCast(Cast node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitFieldReference(FieldReference node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitColumnDefinition(ColumnDefinition node, C context) {
+    return visitTableElement(node, context);
+  }
+
+  protected R visitCreateDB(CreateDB node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitDropDB(DropDB node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitShowDB(ShowDB node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitCreateTable(CreateTable node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitProperty(Property node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitDropTable(DropTable node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitShowTables(ShowTables node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitRenameTable(RenameTable node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitDescribeTable(DescribeTable node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitSetProperties(SetProperties node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitRenameColumn(RenameColumn node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitDropColumn(DropColumn node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitAddColumn(AddColumn node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitInsert(Insert node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitDelete(Delete node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitUpdate(Update node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitUpdateAssignment(UpdateAssignment node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitGroupBy(GroupBy node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitGroupingElement(GroupingElement node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitGroupingSets(GroupingSets node, C context) {
+    return visitGroupingElement(node, context);
+  }
+
+  protected R visitSimpleGroupBy(SimpleGroupBy node, C context) {
+    return visitGroupingElement(node, context);
+  }
+
+  protected R visitSymbolReference(SymbolReference node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R 
visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, C 
context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitCurrentDatabase(CurrentDatabase node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitCurrentUser(CurrentUser node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitDataType(DataType node, C context) {
+    return visitExpression(node, context);
+  }
+
+  protected R visitGenericDataType(GenericDataType node, C context) {
+    return visitDataType(node, context);
+  }
+
+  protected R visitDataTypeParameter(DataTypeParameter node, C context) {
+    return visitNode(node, context);
+  }
+
+  protected R visitNumericTypeParameter(NumericParameter node, C context) {
+    return visitDataTypeParameter(node, context);
+  }
+
+  protected R visitTypeParameter(TypeParameter node, C context) {
+    return visitDataTypeParameter(node, context);
+  }
+
+  protected R visitCreateFunction(ShowFunctions node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitCreateFunction(CreateFunction node, C context) {
+    return visitStatement(node, context);
+  }
+
+  protected R visitDropFunction(DropFunction node, C context) {
+    return visitStatement(node, context);
+  }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BetweenPredicate.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BetweenPredicate.java
new file mode 100644
index 00000000000..47905caf4b0
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BetweenPredicate.java
@@ -0,0 +1,106 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public final class BetweenPredicate extends Expression {
+
+  private final Expression value;
+  private final Expression min;
+  private final Expression max;
+
+  public BetweenPredicate(Expression value, Expression min, Expression max) {
+    super(null);
+    requireNonNull(value, "value is null");
+    requireNonNull(min, "min is null");
+    requireNonNull(max, "max is null");
+
+    this.value = value;
+    this.min = min;
+    this.max = max;
+  }
+
+  public BetweenPredicate(
+      @Nonnull NodeLocation location, Expression value, Expression min, 
Expression max) {
+    super(requireNonNull(location, "location is null"));
+    requireNonNull(value, "value is null");
+    requireNonNull(min, "min is null");
+    requireNonNull(max, "max is null");
+
+    this.value = value;
+    this.min = min;
+    this.max = max;
+  }
+
+  public Expression getValue() {
+    return value;
+  }
+
+  public Expression getMin() {
+    return min;
+  }
+
+  public Expression getMax() {
+    return max;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitBetweenPredicate(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(value, min, max);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    BetweenPredicate that = (BetweenPredicate) o;
+    return Objects.equals(value, that.value)
+        && Objects.equals(min, that.min)
+        && Objects.equals(max, that.max);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(value, min, max);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Cast.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Cast.java
new file mode 100644
index 00000000000..c108f8e74ba
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Cast.java
@@ -0,0 +1,133 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public final class Cast extends Expression {
+  private final Expression expression;
+  private final DataType type;
+  private final boolean safe;
+  private final boolean typeOnly;
+
+  public Cast(Expression expression, DataType type) {
+    this(expression, type, false, false);
+  }
+
+  public Cast(Expression expression, DataType type, boolean safe) {
+    this(expression, type, safe, false);
+  }
+
+  public Cast(Expression expression, DataType type, boolean safe, boolean 
typeOnly) {
+    super(null);
+    requireNonNull(expression, "expression is null");
+
+    this.expression = expression;
+    this.type = type;
+    this.safe = safe;
+    this.typeOnly = typeOnly;
+  }
+
+  public Cast(@Nonnull NodeLocation location, Expression expression, DataType 
type) {
+    this(requireNonNull(location, "location is null"), expression, type, 
false, false);
+  }
+
+  public Cast(@Nonnull NodeLocation location, Expression expression, DataType 
type, boolean safe) {
+    this(requireNonNull(location, "location is null"), expression, type, safe, 
false);
+  }
+
+  private Cast(
+      @Nonnull NodeLocation location,
+      Expression expression,
+      DataType type,
+      boolean safe,
+      boolean typeOnly) {
+    super(location);
+    requireNonNull(expression, "expression is null");
+
+    this.expression = expression;
+    this.type = type;
+    this.safe = safe;
+    this.typeOnly = typeOnly;
+  }
+
+  public Expression getExpression() {
+    return expression;
+  }
+
+  public DataType getType() {
+    return type;
+  }
+
+  public boolean isSafe() {
+    return safe;
+  }
+
+  public boolean isTypeOnly() {
+    return typeOnly;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitCast(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(expression, type);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Cast cast = (Cast) o;
+    return safe == cast.safe
+        && typeOnly == cast.typeOnly
+        && expression.equals(cast.expression)
+        && type.equals(cast.type);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(expression, type, safe, typeOnly);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    Cast otherCast = (Cast) other;
+    return safe == otherCast.safe && typeOnly == otherCast.typeOnly;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CoalesceExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CoalesceExpression.java
new file mode 100644
index 00000000000..dcb02312c1f
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CoalesceExpression.java
@@ -0,0 +1,92 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public final class CoalesceExpression extends Expression {
+
+  private final List<Expression> operands;
+
+  public CoalesceExpression(Expression first, Expression second, Expression... 
additional) {
+    this(ImmutableList.<Expression>builder().add(first, 
second).add(additional).build());
+  }
+
+  public CoalesceExpression(List<Expression> operands) {
+    super(null);
+    requireNonNull(operands, "operands is null");
+    checkArgument(operands.size() >= 2, "must have at least two operands");
+
+    this.operands = ImmutableList.copyOf(operands);
+  }
+
+  public CoalesceExpression(@Nonnull NodeLocation location, List<Expression> 
operands) {
+    super(requireNonNull(location, "location is null"));
+    requireNonNull(operands, "operands is null");
+    checkArgument(operands.size() >= 2, "must have at least two operands");
+
+    this.operands = ImmutableList.copyOf(operands);
+  }
+
+  public List<Expression> getOperands() {
+    return operands;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitCoalesceExpression(this, context);
+  }
+
+  @Override
+  public List<? extends Node> getChildren() {
+    return operands;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CoalesceExpression that = (CoalesceExpression) o;
+    return Objects.equals(operands, that.operands);
+  }
+
+  @Override
+  public int hashCode() {
+    return operands.hashCode();
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ComparisonExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ComparisonExpression.java
new file mode 100644
index 00000000000..f5a264ed786
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ComparisonExpression.java
@@ -0,0 +1,171 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class ComparisonExpression extends Expression {
+
+  public enum Operator {
+    EQUAL("="),
+    NOT_EQUAL("<>"),
+    LESS_THAN("<"),
+    LESS_THAN_OR_EQUAL("<="),
+    GREATER_THAN(">"),
+    GREATER_THAN_OR_EQUAL(">="),
+    IS_DISTINCT_FROM("IS DISTINCT FROM");
+
+    private final String value;
+
+    Operator(String value) {
+      this.value = value;
+    }
+
+    public String getValue() {
+      return value;
+    }
+
+    public Operator flip() {
+      switch (this) {
+        case EQUAL:
+          return EQUAL;
+        case NOT_EQUAL:
+          return NOT_EQUAL;
+        case LESS_THAN:
+          return GREATER_THAN;
+        case LESS_THAN_OR_EQUAL:
+          return GREATER_THAN_OR_EQUAL;
+        case GREATER_THAN:
+          return LESS_THAN;
+        case GREATER_THAN_OR_EQUAL:
+          return LESS_THAN_OR_EQUAL;
+        case IS_DISTINCT_FROM:
+          return IS_DISTINCT_FROM;
+      }
+      throw new IllegalArgumentException("Unsupported comparison: " + this);
+    }
+
+    public Operator negate() {
+      switch (this) {
+        case EQUAL:
+          return NOT_EQUAL;
+        case NOT_EQUAL:
+          return EQUAL;
+        case LESS_THAN:
+          return GREATER_THAN_OR_EQUAL;
+        case LESS_THAN_OR_EQUAL:
+          return GREATER_THAN;
+        case GREATER_THAN:
+          return LESS_THAN_OR_EQUAL;
+        case GREATER_THAN_OR_EQUAL:
+          return LESS_THAN;
+        case IS_DISTINCT_FROM:
+          // Cannot negate
+          break;
+      }
+      throw new IllegalArgumentException("Unsupported comparison: " + this);
+    }
+  }
+
+  private final Operator operator;
+  private final Expression left;
+  private final Expression right;
+
+  public ComparisonExpression(Operator operator, Expression left, Expression 
right) {
+    super(null);
+    requireNonNull(operator, "operator is null");
+    requireNonNull(left, "left is null");
+    requireNonNull(right, "right is null");
+
+    this.operator = operator;
+    this.left = left;
+    this.right = right;
+  }
+
+  public ComparisonExpression(
+      @Nonnull NodeLocation location, Operator operator, Expression left, 
Expression right) {
+    super(requireNonNull(location, "location is null"));
+    requireNonNull(operator, "operator is null");
+    requireNonNull(left, "left is null");
+    requireNonNull(right, "right is null");
+
+    this.operator = operator;
+    this.left = left;
+    this.right = right;
+  }
+
+  public Operator getOperator() {
+    return operator;
+  }
+
+  public Expression getLeft() {
+    return left;
+  }
+
+  public Expression getRight() {
+    return right;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitComparisonExpression(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(left, right);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    ComparisonExpression that = (ComparisonExpression) o;
+    return (operator == that.operator)
+        && Objects.equals(left, that.left)
+        && Objects.equals(right, that.right);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(operator, left, right);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    return operator == ((ComparisonExpression) other).operator;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentDatabase.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentDatabase.java
new file mode 100644
index 00000000000..3c05932316a
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentDatabase.java
@@ -0,0 +1,70 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public class CurrentDatabase extends Expression {
+
+  public CurrentDatabase() {
+    super(null);
+  }
+
+  public CurrentDatabase(@Nonnull NodeLocation location) {
+    super(requireNonNull(location, "location is null"));
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitCurrentDatabase(this, context);
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || (getClass() != obj.getClass())) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentUser.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentUser.java
new file mode 100644
index 00000000000..f995296c2f8
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/CurrentUser.java
@@ -0,0 +1,70 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public class CurrentUser extends Expression {
+
+  public CurrentUser() {
+    super(null);
+  }
+
+  public CurrentUser(@Nonnull NodeLocation location) {
+    super(requireNonNull(location, "location is null"));
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitCurrentUser(this, context);
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || (getClass() != obj.getClass())) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataType.java
similarity index 76%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataType.java
index b8e0c07973a..53726ace8b3 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataType.java
@@ -21,17 +21,9 @@ package org.apache.iotdb.db.relational.sql.tree;
 
 import javax.annotation.Nullable;
 
-public abstract class AstVisitor<R, C> {
+public abstract class DataType extends Expression {
 
-  public R process(Node node) {
-    return process(node, null);
-  }
-
-  public R process(Node node, @Nullable C context) {
-    return node.accept(this, context);
-  }
-
-  protected R visitNode(Node node, C context) {
-    return null;
+  DataType(@Nullable NodeLocation location) {
+    super(location);
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataTypeParameter.java
similarity index 76%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataTypeParameter.java
index b8e0c07973a..427d38c3677 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DataTypeParameter.java
@@ -21,17 +21,14 @@ package org.apache.iotdb.db.relational.sql.tree;
 
 import javax.annotation.Nullable;
 
-public abstract class AstVisitor<R, C> {
+public abstract class DataTypeParameter extends Node {
 
-  public R process(Node node) {
-    return process(node, null);
+  protected DataTypeParameter(@Nullable NodeLocation location) {
+    super(location);
   }
 
-  public R process(Node node, @Nullable C context) {
-    return node.accept(this, context);
-  }
-
-  protected R visitNode(Node node, C context) {
-    return null;
+  @Override
+  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitDataTypeParameter(this, context);
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DereferenceExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DereferenceExpression.java
new file mode 100644
index 00000000000..76723933de5
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DereferenceExpression.java
@@ -0,0 +1,151 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.util.Objects.requireNonNull;
+
+public class DereferenceExpression extends Expression {
+
+  private final Expression base;
+  @Nullable private final Identifier field;
+
+  public DereferenceExpression(Expression base, Identifier field) {
+    super(null);
+    this.base = requireNonNull(base, "base is null");
+    this.field = requireNonNull(field, "field is null");
+  }
+
+  public DereferenceExpression(NodeLocation location, Expression base, 
Identifier field) {
+    super(requireNonNull(location, "location is null"));
+    this.base = requireNonNull(base, "base is null");
+    this.field = requireNonNull(field, "field is null");
+  }
+
+  public DereferenceExpression(Identifier field) {
+    super(null);
+    this.base = null;
+    this.field = requireNonNull(field, "field is null");
+  }
+
+  public DereferenceExpression(NodeLocation location, Identifier field) {
+    super(requireNonNull(location, "location is null"));
+    this.base = null;
+    this.field = requireNonNull(field, "field is null");
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitDereferenceExpression(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    ImmutableList.Builder<Node> children = ImmutableList.builder();
+    children.add(base);
+    if (field != null) {
+      children.add(field);
+    }
+    return children.build();
+  }
+
+  public Expression getBase() {
+    return base;
+  }
+
+  public Optional<Identifier> getField() {
+    return Optional.ofNullable(field);
+  }
+
+  /**
+   * If this DereferenceExpression looks like a QualifiedName, return 
QualifiedName. Otherwise
+   * return null
+   */
+  public static QualifiedName getQualifiedName(DereferenceExpression 
expression) {
+    if (expression.field == null) {
+      return null;
+    }
+
+    Identifier field = expression.field;
+
+    List<Identifier> parts = null;
+    if (expression.base instanceof Identifier) {
+      parts = ImmutableList.of((Identifier) expression.base, field);
+    } else if (expression.base instanceof DereferenceExpression) {
+      QualifiedName baseQualifiedName = 
getQualifiedName((DereferenceExpression) expression.base);
+      if (baseQualifiedName != null) {
+        ImmutableList.Builder<Identifier> builder = ImmutableList.builder();
+        builder.addAll(baseQualifiedName.getOriginalParts());
+        builder.add(field);
+        parts = builder.build();
+      }
+    }
+
+    return parts == null ? null : QualifiedName.of(parts);
+  }
+
+  public static Expression from(QualifiedName name) {
+    Expression result = null;
+
+    for (String part : name.getParts()) {
+      if (result == null) {
+        result = new Identifier(part);
+      } else {
+        result = new DereferenceExpression(result, new Identifier(part));
+      }
+    }
+
+    return result;
+  }
+
+  public static boolean isQualifiedAllFieldsReference(Expression expression) {
+    return expression instanceof DereferenceExpression
+        && ((DereferenceExpression) expression).field == null;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    DereferenceExpression that = (DereferenceExpression) o;
+    return Objects.equals(base, that.base) && Objects.equals(field, 
that.field);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(base, field);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DescribeTable.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DescribeTable.java
new file mode 100644
index 00000000000..f1d8c206b55
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DescribeTable.java
@@ -0,0 +1,80 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class DescribeTable extends Statement {
+  private final QualifiedName table;
+
+  public DescribeTable(QualifiedName table) {
+    super(null);
+    this.table = requireNonNull(table, "table is null");
+  }
+
+  public DescribeTable(@Nonnull NodeLocation location, QualifiedName table) {
+    super(requireNonNull(location, "location is null"));
+    this.table = requireNonNull(table, "table is null");
+  }
+
+  public QualifiedName getTable() {
+    return table;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitDescribeTable(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    DescribeTable that = (DescribeTable) o;
+    return Objects.equals(table, that.table);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(table);
+  }
+
+  @Override
+  public String toString() {
+    return toStringHelper(this).add("table", table).toString();
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ExistsPredicate.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ExistsPredicate.java
new file mode 100644
index 00000000000..e23d13e2354
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/ExistsPredicate.java
@@ -0,0 +1,80 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class ExistsPredicate extends Expression {
+  private final Expression subquery;
+
+  public ExistsPredicate(Expression subquery) {
+    super(null);
+    this.subquery = requireNonNull(subquery, "subquery is null");
+  }
+
+  public ExistsPredicate(@Nonnull NodeLocation location, Expression subquery) {
+    super(requireNonNull(location, "location is null"));
+    this.subquery = requireNonNull(subquery, "subquery is null");
+  }
+
+  public Expression getSubquery() {
+    return subquery;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitExists(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(subquery);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    ExistsPredicate that = (ExistsPredicate) o;
+    return Objects.equals(subquery, that.subquery);
+  }
+
+  @Override
+  public int hashCode() {
+    return subquery.hashCode();
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
similarity index 66%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
index b8e0c07973a..2e401eaf4cd 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
@@ -21,17 +21,20 @@ package org.apache.iotdb.db.relational.sql.tree;
 
 import javax.annotation.Nullable;
 
-public abstract class AstVisitor<R, C> {
+public abstract class Expression extends Node {
 
-  public R process(Node node) {
-    return process(node, null);
+  protected Expression(@Nullable NodeLocation location) {
+    super(location);
   }
 
-  public R process(Node node, @Nullable C context) {
-    return node.accept(this, context);
+  /** Accessible for {@link AstVisitor}, use {@link AstVisitor#process(Node, 
Object)} instead. */
+  @Override
+  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitExpression(this, context);
   }
 
-  protected R visitNode(Node node, C context) {
-    return null;
+  @Override
+  public final String toString() {
+    return ExpressionFormatter.formatExpression(this);
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FieldReference.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FieldReference.java
new file mode 100644
index 00000000000..ff2d7d0c2b0
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FieldReference.java
@@ -0,0 +1,80 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class FieldReference extends Expression {
+
+  private final int fieldIndex;
+
+  public FieldReference(int fieldIndex) {
+    super(null);
+    checkArgument(fieldIndex >= 0, "fieldIndex must be >= 0");
+
+    this.fieldIndex = fieldIndex;
+  }
+
+  public int getFieldIndex() {
+    return fieldIndex;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitFieldReference(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    FieldReference that = (FieldReference) o;
+
+    return fieldIndex == that.fieldIndex;
+  }
+
+  @Override
+  public int hashCode() {
+    return fieldIndex;
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    return fieldIndex == ((FieldReference) other).fieldIndex;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FunctionCall.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FunctionCall.java
new file mode 100644
index 00000000000..8e2b4acf355
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/FunctionCall.java
@@ -0,0 +1,113 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class FunctionCall extends Expression {
+  private final QualifiedName name;
+  private final boolean distinct;
+  private final List<Expression> arguments;
+
+  public FunctionCall(QualifiedName name, List<Expression> arguments) {
+    super(null);
+    this.name = requireNonNull(name, "name is null");
+    this.distinct = false;
+    this.arguments = requireNonNull(arguments, "arguments is null");
+  }
+
+  public FunctionCall(QualifiedName name, boolean distinct, List<Expression> 
arguments) {
+    super(null);
+    this.name = requireNonNull(name, "name is null");
+    this.distinct = distinct;
+    this.arguments = requireNonNull(arguments, "arguments is null");
+  }
+
+  public FunctionCall(NodeLocation location, QualifiedName name, 
List<Expression> arguments) {
+    this(location, name, false, arguments);
+  }
+
+  public FunctionCall(
+      NodeLocation location, QualifiedName name, boolean distinct, 
List<Expression> arguments) {
+    super(requireNonNull(location, "location is null"));
+    this.name = requireNonNull(name, "name is null");
+    this.distinct = distinct;
+    this.arguments = requireNonNull(arguments, "arguments is null");
+  }
+
+  public QualifiedName getName() {
+    return name;
+  }
+
+  public boolean isDistinct() {
+    return distinct;
+  }
+
+  public List<Expression> getArguments() {
+    return arguments;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitFunctionCall(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+    nodes.addAll(arguments);
+    return nodes.build();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || (getClass() != obj.getClass())) {
+      return false;
+    }
+    FunctionCall o = (FunctionCall) obj;
+    return Objects.equals(name, o.name)
+        && Objects.equals(distinct, o.distinct)
+        && Objects.equals(arguments, o.arguments);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(name, distinct, arguments);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    FunctionCall otherFunction = (FunctionCall) other;
+
+    return name.equals(otherFunction.name) && distinct == 
otherFunction.distinct;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericDataType.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericDataType.java
new file mode 100644
index 00000000000..99059ba7c5f
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericDataType.java
@@ -0,0 +1,88 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public final class GenericDataType extends DataType {
+
+  private final Identifier name;
+  private final List<DataTypeParameter> arguments;
+
+  public GenericDataType(Identifier name, List<DataTypeParameter> arguments) {
+    super(null);
+    this.name = requireNonNull(name, "name is null");
+    this.arguments = requireNonNull(arguments, "arguments is null");
+  }
+
+  public GenericDataType(
+      @Nonnull NodeLocation location, Identifier name, List<DataTypeParameter> 
arguments) {
+    super(requireNonNull(location, "location is null"));
+    this.name = requireNonNull(name, "name is null");
+    this.arguments = requireNonNull(arguments, "arguments is null");
+  }
+
+  public Identifier getName() {
+    return name;
+  }
+
+  public List<DataTypeParameter> getArguments() {
+    return arguments;
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.<Node>builder().add(name).addAll(arguments).build();
+  }
+
+  @Override
+  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitGenericDataType(this, context);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    GenericDataType that = (GenericDataType) o;
+    return name.equals(that.name) && arguments.equals(that.arguments);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(name, arguments);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Identifier.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Identifier.java
new file mode 100644
index 00000000000..caac01cc149
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Identifier.java
@@ -0,0 +1,138 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verify;
+import static java.util.Locale.ENGLISH;
+import static java.util.Objects.requireNonNull;
+
+public class Identifier extends Expression {
+
+  private static final CharMatcher FIRST_CHAR_DISALLOWED_MATCHER =
+      CharMatcher.inRange('0', '9').precomputed();
+
+  private static final CharMatcher ALLOWED_CHARS_MATCHER =
+      CharMatcher.inRange('a', 'z')
+          .or(CharMatcher.inRange('A', 'Z'))
+          .or(CharMatcher.is('_'))
+          .or(CharMatcher.inRange('0', '9'))
+          .precomputed();
+
+  private final String value;
+  private final boolean delimited;
+
+  public Identifier(NodeLocation location, String value, boolean delimited) {
+    super(requireNonNull(location, "location is null"));
+    this.value = requireNonNull(value, "value is null");
+    this.delimited = delimited;
+
+    checkArgument(!value.isEmpty(), "value is empty");
+    checkArgument(
+        delimited || isValidIdentifier(value), "value contains illegal 
characters: %s", value);
+  }
+
+  public Identifier(String value, boolean delimited) {
+    super(null);
+    this.value = requireNonNull(value, "value is null");
+    this.delimited = delimited;
+
+    checkArgument(!value.isEmpty(), "value is empty");
+    checkArgument(
+        delimited || isValidIdentifier(value), "value contains illegal 
characters: %s", value);
+  }
+
+  public Identifier(String value) {
+    this(value, !isValidIdentifier(value));
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public boolean isDelimited() {
+    return delimited;
+  }
+
+  public String getCanonicalValue() {
+    if (isDelimited()) {
+      return value;
+    }
+
+    return value.toUpperCase(ENGLISH);
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitIdentifier(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    Identifier that = (Identifier) o;
+    return Objects.equals(value, that.value);
+  }
+
+  @Override
+  public int hashCode() {
+    return value.hashCode();
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    Identifier that = (Identifier) other;
+    return Objects.equals(value, that.value) && delimited == that.delimited;
+  }
+
+  private static boolean isValidIdentifier(String value) {
+    verify(!Strings.isNullOrEmpty(value), "Identifier cannot be empty or 
null");
+
+    if (FIRST_CHAR_DISALLOWED_MATCHER.matches(value.charAt(0))) {
+      return false;
+    }
+
+    // We've already checked that first char does not contain digits,
+    // so to avoid copying we are checking whole string.
+    return ALLOWED_CHARS_MATCHER.matchesAllOf(value);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IfExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IfExpression.java
new file mode 100644
index 00000000000..097c89ee42b
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IfExpression.java
@@ -0,0 +1,105 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.util.Objects.requireNonNull;
+
+/** IF(v1,v2[,v3]): CASE WHEN v1 THEN v2 [ELSE v3] END */
+public class IfExpression extends Expression {
+  private final Expression condition;
+  private final Expression trueValue;
+  @Nullable private final Expression falseValue;
+
+  public IfExpression(Expression condition, Expression trueValue, @Nullable 
Expression falseValue) {
+    super(null);
+    this.condition = requireNonNull(condition, "condition is null");
+    this.trueValue = requireNonNull(trueValue, "trueValue is null");
+    this.falseValue = falseValue;
+  }
+
+  public IfExpression(
+      NodeLocation location,
+      Expression condition,
+      Expression trueValue,
+      @Nullable Expression falseValue) {
+    super(requireNonNull(location, "location is null"));
+    this.condition = requireNonNull(condition, "condition is null");
+    this.trueValue = requireNonNull(trueValue, "trueValue is null");
+    this.falseValue = falseValue;
+  }
+
+  public Expression getCondition() {
+    return condition;
+  }
+
+  public Expression getTrueValue() {
+    return trueValue;
+  }
+
+  public Optional<Expression> getFalseValue() {
+    return Optional.ofNullable(falseValue);
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitIfExpression(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+    if (falseValue != null) {
+      nodes.add(falseValue);
+    }
+    return nodes.add(condition).add(trueValue).build();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || (getClass() != obj.getClass())) {
+      return false;
+    }
+    IfExpression o = (IfExpression) obj;
+    return Objects.equals(condition, o.condition)
+        && Objects.equals(trueValue, o.trueValue)
+        && Objects.equals(falseValue, o.falseValue);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(condition, trueValue, falseValue);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InListExpression.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InListExpression.java
new file mode 100644
index 00000000000..f8d263aa7e3
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InListExpression.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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class InListExpression extends Expression {
+  private final List<Expression> values;
+
+  public InListExpression(List<Expression> values) {
+    super(null);
+    requireNonNull(values, "values is null");
+    checkArgument(!values.isEmpty(), "values cannot be empty");
+    this.values = ImmutableList.copyOf(values);
+  }
+
+  public InListExpression(NodeLocation location, List<Expression> values) {
+    super(requireNonNull(location, "location is null"));
+    requireNonNull(values, "values is null");
+    checkArgument(!values.isEmpty(), "values cannot be empty");
+    this.values = ImmutableList.copyOf(values);
+  }
+
+  public List<Expression> getValues() {
+    return values;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitInListExpression(this, context);
+  }
+
+  @Override
+  public List<? extends Node> getChildren() {
+    return values;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    InListExpression that = (InListExpression) o;
+    return Objects.equals(values, that.values);
+  }
+
+  @Override
+  public int hashCode() {
+    return values.hashCode();
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InPredicate.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InPredicate.java
new file mode 100644
index 00000000000..b5233b9500d
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/InPredicate.java
@@ -0,0 +1,86 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class InPredicate extends Expression {
+
+  private final Expression value;
+  private final Expression valueList;
+
+  public InPredicate(Expression value, Expression valueList) {
+    super(null);
+    this.value = requireNonNull(value, "value is null");
+    this.valueList = requireNonNull(valueList, "valueList is null");
+  }
+
+  public InPredicate(NodeLocation location, Expression value, Expression 
valueList) {
+    super(requireNonNull(location, "location is null"));
+    this.value = requireNonNull(value, "value is null");
+    this.valueList = requireNonNull(valueList, "valueList is null");
+  }
+
+  public Expression getValue() {
+    return value;
+  }
+
+  public Expression getValueList() {
+    return valueList;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitInPredicate(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of(value, valueList);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    InPredicate that = (InPredicate) o;
+    return Objects.equals(value, that.value) && Objects.equals(valueList, 
that.valueList);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(value, valueList);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
similarity index 69%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
index b8e0c07973a..b61b0bbb9cd 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
@@ -19,19 +19,24 @@
 
 package org.apache.iotdb.db.relational.sql.tree;
 
+import com.google.common.collect.ImmutableList;
+
 import javax.annotation.Nullable;
 
-public abstract class AstVisitor<R, C> {
+import java.util.List;
 
-  public R process(Node node) {
-    return process(node, null);
+public abstract class Literal extends Expression {
+  protected Literal(@Nullable NodeLocation location) {
+    super(location);
   }
 
-  public R process(Node node, @Nullable C context) {
-    return node.accept(this, context);
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitLiteral(this, context);
   }
 
-  protected R visitNode(Node node, C context) {
-    return null;
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
index 0c3ec9b8e32..96797b308f3 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
@@ -41,7 +41,7 @@ public abstract class Node {
     return Optional.ofNullable(location);
   }
 
-  public abstract List<Node> getChildren();
+  public abstract List<? extends Node> getChildren();
 
   // Force subclasses to have a proper equals and hashcode implementation
   @Override
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NumericParameter.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NumericParameter.java
new file mode 100644
index 00000000000..7d2c5e1e657
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NumericParameter.java
@@ -0,0 +1,88 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class NumericParameter extends DataTypeParameter {
+  private final String value;
+
+  public NumericParameter(String value) {
+    super(null);
+    this.value = requireNonNull(value, "value is null");
+  }
+
+  public NumericParameter(@Nonnull NodeLocation location, String value) {
+    super(requireNonNull(location, "location is null"));
+    this.value = requireNonNull(value, "value is null");
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  @Override
+  public String toString() {
+    return value;
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitNumericTypeParameter(this, context);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    NumericParameter that = (NumericParameter) o;
+    return value.equals(that.value);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(value);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    if (!sameClass(this, other)) {
+      return false;
+    }
+
+    return Objects.equals(value, ((NumericParameter) other).value);
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Property.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Property.java
new file mode 100644
index 00000000000..653fab420dd
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Property.java
@@ -0,0 +1,120 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+public class Property extends Node {
+  private final Identifier name;
+
+  @Nullable private final Expression value; // null iff the value is set to 
DEFAULT
+
+  /** Constructs an instance representing a property whose value is set to 
DEFAULT */
+  public Property(@Nonnull Identifier name) {
+    super(null);
+    this.name = requireNonNull(name, "name is null");
+    this.value = null;
+  }
+
+  /** Constructs an instance representing a property whose value is set to 
DEFAULT */
+  public Property(@Nonnull NodeLocation location, @Nonnull Identifier name) {
+    super(requireNonNull(location, "location is null"));
+    this.name = requireNonNull(name, "name is null");
+    this.value = null;
+  }
+
+  public Property(@Nonnull Identifier name, @Nonnull Expression value) {
+    super(null);
+    this.name = requireNonNull(name, "name is null");
+    this.value = requireNonNull(value, "value is null");
+  }
+
+  public Property(
+      @Nonnull NodeLocation location, @Nonnull Identifier name, @Nullable 
Expression value) {
+    super(requireNonNull(location, "location is null"));
+    this.name = requireNonNull(name, "name is null");
+    this.value = requireNonNull(value, "value is null");
+  }
+
+  public Identifier getName() {
+    return name;
+  }
+
+  public boolean isSetToDefault() {
+    return value == null;
+  }
+
+  /**
+   * Returns the non-default value of the property. This method should be 
called only if the
+   * property is not set to DEFAULT.
+   */
+  public Expression getNonDefaultValue() {
+    checkState(
+        !isSetToDefault(),
+        "Cannot get non-default value of property %s since its value is set to 
DEFAULT",
+        name);
+    return value;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitProperty(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return isSetToDefault() ? ImmutableList.of(name) : ImmutableList.of(name, 
getNonDefaultValue());
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null || getClass() != obj.getClass()) {
+      return false;
+    }
+    Property other = (Property) obj;
+    return Objects.equals(name, other.name) && Objects.equals(value, 
other.value);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(name, value);
+  }
+
+  @Override
+  public String toString() {
+    return toStringHelper(this)
+        .add("name", name)
+        .add("value", isSetToDefault() ? "DEFAULT" : getNonDefaultValue())
+        .toString();
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QualifiedName.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QualifiedName.java
new file mode 100644
index 00000000000..4b62f96b85f
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QualifiedName.java
@@ -0,0 +1,139 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.Iterables.isEmpty;
+import static java.util.Locale.ENGLISH;
+import static java.util.Objects.requireNonNull;
+
+public class QualifiedName {
+
+  private final List<Identifier> originalParts;
+  private final List<String> parts;
+
+  // Following fields are not part of the equals/hashCode methods as
+  // they are exist solely to speed-up certain method calls.
+  private final String name;
+
+  @Nullable private final QualifiedName prefix;
+  private final String suffix;
+
+  public static QualifiedName of(String first, String... rest) {
+    requireNonNull(first, "first is null");
+    return of(Lists.asList(first, 
rest).stream().map(Identifier::new).collect(toImmutableList()));
+  }
+
+  public static QualifiedName of(String name) {
+    requireNonNull(name, "name is null");
+    return of(ImmutableList.of(new Identifier(name)));
+  }
+
+  public static QualifiedName of(Iterable<Identifier> originalParts) {
+    requireNonNull(originalParts, "originalParts is null");
+    checkArgument(!isEmpty(originalParts), "originalParts is empty");
+
+    return new QualifiedName(ImmutableList.copyOf(originalParts));
+  }
+
+  private QualifiedName(List<Identifier> originalParts) {
+    this.originalParts = originalParts;
+    // Iteration instead of stream for performance reasons
+    ImmutableList.Builder<String> partsBuilder =
+        ImmutableList.builderWithExpectedSize(originalParts.size());
+    for (Identifier identifier : originalParts) {
+      partsBuilder.add(mapIdentifier(identifier));
+    }
+    this.parts = partsBuilder.build();
+    this.name = String.join(".", parts);
+
+    if (originalParts.size() == 1) {
+      this.prefix = null;
+      this.suffix = mapIdentifier(originalParts.get(0));
+    } else {
+      List<Identifier> subList = originalParts.subList(0, originalParts.size() 
- 1);
+      this.prefix = new QualifiedName(subList);
+      this.suffix = mapIdentifier(originalParts.get(originalParts.size() - 1));
+    }
+  }
+
+  private static String mapIdentifier(Identifier identifier) {
+    return identifier.getValue().toLowerCase(ENGLISH);
+  }
+
+  public List<String> getParts() {
+    return parts;
+  }
+
+  public List<Identifier> getOriginalParts() {
+    return originalParts;
+  }
+
+  /**
+   * For an identifier of the form "a.b.c.d", returns "a.b.c" For an 
identifier of the form "a",
+   * returns absent
+   */
+  public Optional<QualifiedName> getPrefix() {
+    return Optional.ofNullable(this.prefix);
+  }
+
+  public boolean hasSuffix(QualifiedName suffix) {
+    if (parts.size() < suffix.getParts().size()) {
+      return false;
+    }
+
+    int start = parts.size() - suffix.getParts().size();
+    return parts.subList(start, parts.size()).equals(suffix.getParts());
+  }
+
+  public String getSuffix() {
+    return this.suffix;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    return parts.equals(((QualifiedName) o).parts);
+  }
+
+  @Override
+  public int hashCode() {
+    return parts.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SetProperties.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SetProperties.java
new file mode 100644
index 00000000000..f6e9227cd4a
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SetProperties.java
@@ -0,0 +1,107 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class SetProperties extends Statement {
+
+  public enum Type {
+    TABLE,
+    MATERIALIZED_VIEW
+  }
+
+  private final Type type;
+  private final QualifiedName name;
+  private final List<Property> properties;
+
+  public SetProperties(Type type, QualifiedName name, List<Property> 
properties) {
+    super(null);
+    this.type = requireNonNull(type, "type is null");
+    this.name = requireNonNull(name, "name is null");
+    this.properties = ImmutableList.copyOf(requireNonNull(properties, 
"properties is null"));
+  }
+
+  public SetProperties(
+      @Nonnull NodeLocation location, Type type, QualifiedName name, 
List<Property> properties) {
+    super(requireNonNull(location, "location is null"));
+    this.type = requireNonNull(type, "type is null");
+    this.name = requireNonNull(name, "name is null");
+    this.properties = ImmutableList.copyOf(requireNonNull(properties, 
"properties is null"));
+  }
+
+  public Type getType() {
+    return type;
+  }
+
+  public QualifiedName getName() {
+    return name;
+  }
+
+  public List<Property> getProperties() {
+    return properties;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitSetProperties(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(type, name, properties);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || (getClass() != obj.getClass())) {
+      return false;
+    }
+    SetProperties o = (SetProperties) obj;
+    return type == o.type
+        && Objects.equals(name, o.name)
+        && Objects.equals(properties, o.properties);
+  }
+
+  @Override
+  public String toString() {
+    return toStringHelper(this)
+        .add("type", type)
+        .add("name", name)
+        .add("properties", properties)
+        .toString();
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Statement.java
similarity index 77%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Statement.java
index b8e0c07973a..39fa39ba136 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Statement.java
@@ -21,17 +21,14 @@ package org.apache.iotdb.db.relational.sql.tree;
 
 import javax.annotation.Nullable;
 
-public abstract class AstVisitor<R, C> {
+public abstract class Statement extends Node {
 
-  public R process(Node node) {
-    return process(node, null);
+  protected Statement(@Nullable NodeLocation location) {
+    super(location);
   }
 
-  public R process(Node node, @Nullable C context) {
-    return node.accept(this, context);
-  }
-
-  protected R visitNode(Node node, C context) {
-    return null;
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitStatement(this, context);
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/TypeParameter.java
similarity index 51%
copy from 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
copy to 
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/TypeParameter.java
index 0c3ec9b8e32..4970cc479a8 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/TypeParameter.java
@@ -19,53 +19,60 @@
 
 package org.apache.iotdb.db.relational.sql.tree;
 
-import javax.annotation.Nullable;
+import com.google.common.collect.ImmutableList;
 
 import java.util.List;
-import java.util.Optional;
+import java.util.Objects;
 
-public abstract class Node {
+import static java.util.Objects.requireNonNull;
 
-  @Nullable private final NodeLocation location;
+public class TypeParameter extends DataTypeParameter {
 
-  protected Node(@Nullable NodeLocation location) {
-    this.location = location;
-  }
+  private final DataType type;
 
-  /** Accessible for {@link AstVisitor}, use {@link AstVisitor#process(Node, 
Object)} instead. */
-  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
-    return visitor.visitNode(this, context);
+  public TypeParameter(DataType type) {
+    super(null);
+    this.type = requireNonNull(type, "type is null");
   }
 
-  public Optional<NodeLocation> getLocation() {
-    return Optional.ofNullable(location);
+  public DataType getValue() {
+    return type;
   }
 
-  public abstract List<Node> getChildren();
-
-  // Force subclasses to have a proper equals and hashcode implementation
   @Override
-  public abstract int hashCode();
+  public String toString() {
+    return type.toString();
+  }
 
   @Override
-  public abstract boolean equals(Object obj);
+  public List<Node> getChildren() {
+    return ImmutableList.of(type);
+  }
 
   @Override
-  public abstract String toString();
-
-  /**
-   * Compare with another node by considering internal state excluding any 
Node returned by
-   * getChildren()
-   */
-  public boolean shallowEquals(Node other) {
-    throw new UnsupportedOperationException("not yet implemented: " + 
getClass().getName());
+  protected <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitTypeParameter(this, context);
   }
 
-  static boolean sameClass(Node left, Node right) {
-    if (left == right) {
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
       return true;
     }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    TypeParameter that = (TypeParameter) o;
+    return type.equals(that.type);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(type);
+  }
 
-    return left.getClass() == right.getClass();
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
   }
 }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Use.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Use.java
new file mode 100644
index 00000000000..d94ce5c9f70
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Use.java
@@ -0,0 +1,81 @@
+/*
+ * 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.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import javax.annotation.Nonnull;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public final class Use extends Statement {
+
+  private final Identifier db;
+
+  public Use(@Nonnull Identifier db) {
+    super(null);
+    this.db = requireNonNull(db, "db is null");
+  }
+
+  public Use(@Nonnull NodeLocation location, @Nonnull Identifier db) {
+    super(requireNonNull(location, "location is null"));
+    this.db = requireNonNull(db, "db is null");
+  }
+
+  public Identifier getDatabase() {
+    return db;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitUse(this, context);
+  }
+
+  @Override
+  public List<Node> getChildren() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Use use = (Use) o;
+    return Objects.equals(db, use.db);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(db);
+  }
+
+  @Override
+  public String toString() {
+    return toStringHelper(this).toString();
+  }
+}
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
new file mode 100644
index 00000000000..de9ac00e13c
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.iotdb.db.relational.sql.util;
+
+import org.apache.iotdb.db.relational.sql.tree.AstVisitor;
+import org.apache.iotdb.db.relational.sql.tree.Expression;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+import static java.util.Objects.requireNonNull;
+
+public final class ExpressionFormatter {
+
+  private ExpressionFormatter() {}
+
+  public static String formatExpression(Expression expression) {
+    return new Formatter(Optional.empty(), 
Optional.empty()).process(expression, null);
+  }
+
+  public static class Formatter extends AstVisitor<String, Void> {
+    private final Optional<Function<Literal, String>> literalFormatter;
+    private final Optional<Function<SymbolReference, String>> 
symbolReferenceFormatter;
+
+    public Formatter(
+        Optional<Function<Literal, String>> literalFormatter,
+        Optional<Function<SymbolReference, String>> symbolReferenceFormatter) {
+      this.literalFormatter = requireNonNull(literalFormatter, 
"literalFormatter is null");
+      this.symbolReferenceFormatter =
+          requireNonNull(symbolReferenceFormatter, "symbolReferenceFormatter 
is null");
+    }
+  }
+}


Reply via email to