/*
 * 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.mpp.plan.parser;

import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.cluster.NodeStatus;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.PathUtils;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.exception.sql.SQLParserException;
import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.mpp.common.filter.BasicFunctionFilter;
import org.apache.iotdb.db.mpp.common.filter.QueryFilter;
import org.apache.iotdb.db.mpp.plan.analyze.ExpressionAnalyzer;
import org.apache.iotdb.db.mpp.plan.constant.StatementType;
import org.apache.iotdb.db.mpp.plan.expression.Expression;
import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
import org.apache.iotdb.db.mpp.plan.expression.binary.AdditionExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.CompareBinaryExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.DivisionExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.EqualToExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterThanExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LessEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LogicOrExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.ModuloExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.MultiplicationExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.NonEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.SubtractionExpression;
import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand;
import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
import org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand;
import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
import org.apache.iotdb.db.mpp.plan.expression.ternary.BetweenExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.InExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.IsNullExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.LikeExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.LogicNotExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.NegationExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.RegularExpression;
import org.apache.iotdb.db.mpp.plan.statement.Statement;
import org.apache.iotdb.db.mpp.plan.statement.component.FillComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.FillPolicy;
import org.apache.iotdb.db.mpp.plan.statement.component.FromComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByLevelComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByTimeComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.HavingCondition;
import org.apache.iotdb.db.mpp.plan.statement.component.OrderByComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.Ordering;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultSetFormat;
import org.apache.iotdb.db.mpp.plan.statement.component.SelectComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.SortItem;
import org.apache.iotdb.db.mpp.plan.statement.component.SortKey;
import org.apache.iotdb.db.mpp.plan.statement.component.WhereCondition;
import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
import org.apache.iotdb.db.mpp.plan.statement.crud.InsertStatement;
import org.apache.iotdb.db.mpp.plan.statement.crud.LoadTsFileStatement;
import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
import org.apache.iotdb.db.mpp.plan.statement.literal.BooleanLiteral;
import org.apache.iotdb.db.mpp.plan.statement.literal.DoubleLiteral;
import org.apache.iotdb.db.mpp.plan.statement.literal.Literal;
import org.apache.iotdb.db.mpp.plan.statement.literal.LongLiteral;
import org.apache.iotdb.db.mpp.plan.statement.literal.StringLiteral;
import org.apache.iotdb.db.mpp.plan.statement.metadata.AlterTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountDevicesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateFunctionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTriggerStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.DeleteStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.DeleteTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.DropFunctionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.DropTriggerStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.SetStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.SetTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildPathsStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowClusterStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowConfigNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDataNodesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowFunctionsStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowRegionStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTriggersStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.UnSetTTLStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ActivateTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.SetSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowPathSetTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ClearCacheStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.FlushStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.LoadConfigurationStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.MergeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.SetSystemStatusStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.CreatePipeSinkStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.CreatePipeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.DropPipeSinkStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.DropPipeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.ShowPipeSinkStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.ShowPipeSinkTypeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.ShowPipeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.StartPipeStatement;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.StopPipeStatement;
import org.apache.iotdb.db.qp.constant.SQLConstant;
import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ConstantContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountDevicesContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountNodesContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountStorageGroupContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountTimeseriesContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CreateFunctionContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.DropFunctionContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ExpressionContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ShowFunctionsContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.UriContext;
import org.apache.iotdb.db.qp.sql.IoTDBSqlParserBaseVisitor;
import org.apache.iotdb.db.qp.utils.DatetimeUtils;
import org.apache.iotdb.trigger.api.enums.TriggerEvent;
import org.apache.iotdb.trigger.api.enums.TriggerType;
import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.utils.Pair;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;

/** Parse AST to Statement. */
public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {

  private static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig();

  private static final String DELETE_RANGE_ERROR_MSG =
      "For delete statement, where clause can only contain atomic expressions like : "
          + "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'";
  private static final String DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG =
      "For delete statement, where clause can only contain time expressions, "
          + "value filter is not currently supported.";

  /** For create-cq clause and select-into clause, used to match "{x}", where x is an integer. */
  private static final Pattern leveledPathNodePattern = Pattern.compile("\\$\\{\\w+}");

  // TODO: add comment
  private ZoneId zoneId;

  public void setZoneId(ZoneId zoneId) {
    this.zoneId = zoneId;
  }

  /** Top Level Description */
  @Override
  public Statement visitSingleStatement(IoTDBSqlParser.SingleStatementContext ctx) {
    Statement statement = visit(ctx.statement());
    if (ctx.DEBUG() != null) {
      statement.setDebug(true);
    }
    return statement;
  }

  /** Data Definition Language (DDL) */

  // Create Timeseries ========================================================================
  @Override
  public Statement visitCreateNonAlignedTimeseries(
      IoTDBSqlParser.CreateNonAlignedTimeseriesContext ctx) {
    CreateTimeSeriesStatement createTimeSeriesStatement = new CreateTimeSeriesStatement();
    createTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
    if (ctx.attributeClauses() != null) {
      parseAttributeClauses(ctx.attributeClauses(), createTimeSeriesStatement);
    }
    return createTimeSeriesStatement;
  }

  @Override
  public Statement visitCreateAlignedTimeseries(IoTDBSqlParser.CreateAlignedTimeseriesContext ctx) {
    CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement =
        new CreateAlignedTimeSeriesStatement();
    createAlignedTimeSeriesStatement.setDevicePath(parseFullPath(ctx.fullPath()));
    parseAlignedMeasurements(ctx.alignedMeasurements(), createAlignedTimeSeriesStatement);
    return createAlignedTimeSeriesStatement;
  }

  public void parseAlignedMeasurements(
      IoTDBSqlParser.AlignedMeasurementsContext ctx,
      CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement) {
    for (int i = 0; i < ctx.nodeNameWithoutWildcard().size(); i++) {
      createAlignedTimeSeriesStatement.addMeasurement(
          parseNodeNameWithoutWildCard(ctx.nodeNameWithoutWildcard(i)));
      parseAttributeClauses(ctx.attributeClauses(i), createAlignedTimeSeriesStatement);
    }
  }

  public void parseAttributeClauses(
      IoTDBSqlParser.AttributeClausesContext ctx,
      CreateTimeSeriesStatement createTimeSeriesStatement) {
    if (ctx.aliasNodeName() != null) {
      createTimeSeriesStatement.setAlias(parseNodeName(ctx.aliasNodeName().nodeName()));
    }

    Map<String, String> props = new HashMap<>();
    if (ctx.dataType != null) {
      if (ctx.attributeKey() != null) {
        if (!parseAttributeKey(ctx.attributeKey())
            .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
          throw new SQLParserException("expecting datatype");
        }
      }
      props.put(
          IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase(),
          parseAttributeValue(ctx.dataType).toLowerCase());
    }
    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
    if (ctx.attributePair(0) != null) {
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
        props.put(
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
      }
    }

    createTimeSeriesStatement.setProps(props);
    checkPropsInCreateTimeSeries(createTimeSeriesStatement);

    if (ctx.tagClause() != null) {
      parseTagClause(ctx.tagClause(), createTimeSeriesStatement);
    }
    if (ctx.attributeClause() != null) {
      parseAttributeClause(ctx.attributeClause(), createTimeSeriesStatement);
    }
  }

  /** check and set datatype, encoding, compressor */
  private void checkPropsInCreateTimeSeries(CreateTimeSeriesStatement createTimeSeriesStatement) {
    Map<String, String> props = createTimeSeriesStatement.getProps();
    if (props != null
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase())) {
      String datatypeString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase()).toUpperCase();
      try {
        createTimeSeriesStatement.setDataType(TSDataType.valueOf(datatypeString));
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("Unsupported datatype: %s", datatypeString));
      }
    }
    if (createTimeSeriesStatement.getDataType() == null) {
      throw new SemanticException("datatype must be declared");
    }

    final IoTDBDescriptor ioTDBDescriptor = IoTDBDescriptor.getInstance();
    createTimeSeriesStatement.setEncoding(
        ioTDBDescriptor.getDefaultEncodingByType(createTimeSeriesStatement.getDataType()));
    if (props != null
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
      String encodingString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
      try {
        createTimeSeriesStatement.setEncoding(TSEncoding.valueOf(encodingString));
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("Unsupported encoding: %s", encodingString));
      }
    }

    createTimeSeriesStatement.setCompressor(
        TSFileDescriptor.getInstance().getConfig().getCompressor());
    if (props != null
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
      String compressionString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
      try {
        createTimeSeriesStatement.setCompressor(CompressionType.valueOf(compressionString));
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(
            String.format("Unsupported compression: %s", compressionString));
      }
    } else if (props != null
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
      String compressorString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
      try {
        createTimeSeriesStatement.setCompressor(CompressionType.valueOf(compressorString));
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("Unsupported compression: %s", compressorString));
      }
    }
    createTimeSeriesStatement.setProps(props);
  }

  public void parseAttributeClauses(
      IoTDBSqlParser.AttributeClausesContext ctx,
      CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement) {
    if (ctx.aliasNodeName() != null) {
      createAlignedTimeSeriesStatement.addAliasList(parseNodeName(ctx.aliasNodeName().nodeName()));
    } else {
      createAlignedTimeSeriesStatement.addAliasList(null);
    }

    TSDataType dataType = null;
    if (ctx.dataType != null) {
      if (ctx.attributeKey() != null) {
        if (!parseAttributeKey(ctx.attributeKey())
            .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
          throw new SQLParserException("expecting datatype");
        }
      }
      String dataTypeString = ctx.dataType.getText().toUpperCase();
      try {
        dataType = TSDataType.valueOf(dataTypeString);
        createAlignedTimeSeriesStatement.addDataType(dataType);
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported datatype: %s", dataTypeString));
      }
    }

    Map<String, String> props = new HashMap<>();
    if (ctx.attributePair() != null) {
      for (int i = 0; i < ctx.attributePair().size(); i++) {
        props.put(
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
      }
    }

    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
      String encodingString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
      try {
        encoding = TSEncoding.valueOf(encodingString);
        createAlignedTimeSeriesStatement.addEncoding(encoding);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported encoding: %s", encodingString));
      }
    } else {
      createAlignedTimeSeriesStatement.addEncoding(encoding);
    }

    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
      String compressorString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
      try {
        compressor = CompressionType.valueOf(compressorString);
        createAlignedTimeSeriesStatement.addCompressor(compressor);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported compressor: %s", compressorString));
      }
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
      String compressionString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
      try {
        compressor = CompressionType.valueOf(compressionString);
        createAlignedTimeSeriesStatement.addCompressor(compressor);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(
            String.format("unsupported compression: %s", compressionString));
      }
    } else {
      createAlignedTimeSeriesStatement.addCompressor(compressor);
    }

    if (props.size() > 0) {
      throw new SQLParserException("create aligned timeseries: property is not supported yet.");
    }

    if (ctx.tagClause() != null) {
      parseTagClause(ctx.tagClause(), createAlignedTimeSeriesStatement);
    } else {
      createAlignedTimeSeriesStatement.addTagsList(null);
    }

    if (ctx.attributeClause() != null) {
      parseAttributeClause(ctx.attributeClause(), createAlignedTimeSeriesStatement);
    } else {
      createAlignedTimeSeriesStatement.addAttributesList(null);
    }
  }

  // Tag & Property & Attribute

  public void parseTagClause(IoTDBSqlParser.TagClauseContext ctx, Statement statement) {
    Map<String, String> tags = extractMap(ctx.attributePair(), ctx.attributePair(0));
    if (statement instanceof CreateTimeSeriesStatement) {
      ((CreateTimeSeriesStatement) statement).setTags(tags);
    } else if (statement instanceof CreateAlignedTimeSeriesStatement) {
      ((CreateAlignedTimeSeriesStatement) statement).addTagsList(tags);
    } else if (statement instanceof AlterTimeSeriesStatement) {
      ((AlterTimeSeriesStatement) statement).setTagsMap(tags);
    }
  }

  public void parseAttributeClause(IoTDBSqlParser.AttributeClauseContext ctx, Statement statement) {
    Map<String, String> attributes = extractMap(ctx.attributePair(), ctx.attributePair(0));
    if (statement instanceof CreateTimeSeriesStatement) {
      ((CreateTimeSeriesStatement) statement).setAttributes(attributes);
    } else if (statement instanceof CreateAlignedTimeSeriesStatement) {
      ((CreateAlignedTimeSeriesStatement) statement).addAttributesList(attributes);
    } else if (statement instanceof AlterTimeSeriesStatement) {
      ((AlterTimeSeriesStatement) statement).setAttributesMap(attributes);
    }
  }

  // Alter Timeseries ========================================================================

  @Override
  public Statement visitAlterTimeseries(IoTDBSqlParser.AlterTimeseriesContext ctx) {
    AlterTimeSeriesStatement alterTimeSeriesStatement = new AlterTimeSeriesStatement();
    alterTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
    parseAlterClause(ctx.alterClause(), alterTimeSeriesStatement);
    return alterTimeSeriesStatement;
  }

  private void parseAlterClause(
      IoTDBSqlParser.AlterClauseContext ctx, AlterTimeSeriesStatement alterTimeSeriesStatement) {
    Map<String, String> alterMap = new HashMap<>();
    // rename
    if (ctx.RENAME() != null) {
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.RENAME);
      alterMap.put(parseAttributeKey(ctx.beforeName), parseAttributeKey(ctx.currentName));
    } else if (ctx.SET() != null) {
      // set
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.SET);
      setMap(ctx, alterMap);
    } else if (ctx.DROP() != null) {
      // drop
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.DROP);
      for (int i = 0; i < ctx.attributeKey().size(); i++) {
        alterMap.put(parseAttributeKey(ctx.attributeKey().get(i)), null);
      }
    } else if (ctx.TAGS() != null) {
      // add tag
      alterTimeSeriesStatement.setAlterType((AlterTimeSeriesStatement.AlterType.ADD_TAGS));
      setMap(ctx, alterMap);
    } else if (ctx.ATTRIBUTES() != null) {
      // add attribute
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.ADD_ATTRIBUTES);
      setMap(ctx, alterMap);
    } else {
      // upsert
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.UPSERT);
      if (ctx.aliasClause() != null) {
        parseAliasClause(ctx.aliasClause(), alterTimeSeriesStatement);
      }
      if (ctx.tagClause() != null) {
        parseTagClause(ctx.tagClause(), alterTimeSeriesStatement);
      }
      if (ctx.attributeClause() != null) {
        parseAttributeClause(ctx.attributeClause(), alterTimeSeriesStatement);
      }
    }
    alterTimeSeriesStatement.setAlterMap(alterMap);
  }

  public void parseAliasClause(
      IoTDBSqlParser.AliasClauseContext ctx, AlterTimeSeriesStatement alterTimeSeriesStatement) {
    if (alterTimeSeriesStatement != null && ctx.ALIAS() != null) {
      alterTimeSeriesStatement.setAlias(parseAlias(ctx.alias()));
    }
  }

  // Delete Timeseries ======================================================================

  @Override
  public Statement visitDeleteTimeseries(IoTDBSqlParser.DeleteTimeseriesContext ctx) {
    DeleteTimeSeriesStatement deleteTimeSeriesStatement = new DeleteTimeSeriesStatement();
    List<PartialPath> partialPaths = new ArrayList<>();
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
      partialPaths.add(parsePrefixPath(prefixPathContext));
    }
    deleteTimeSeriesStatement.setPathPatternList(partialPaths);
    return deleteTimeSeriesStatement;
  }

  // Show Timeseries ========================================================================

  @Override
  public Statement visitShowTimeseries(IoTDBSqlParser.ShowTimeseriesContext ctx) {
    boolean orderByHeat = ctx.LATEST() != null;
    ShowTimeSeriesStatement showTimeSeriesStatement;
    if (ctx.prefixPath() != null) {
      showTimeSeriesStatement =
          new ShowTimeSeriesStatement(parsePrefixPath(ctx.prefixPath()), orderByHeat);
    } else {
      showTimeSeriesStatement =
          new ShowTimeSeriesStatement(
              new PartialPath(SQLConstant.getSingleRootArray()), orderByHeat);
    }
    if (ctx.tagWhereClause() != null) {
      parseTagWhereClause(ctx.tagWhereClause(), showTimeSeriesStatement);
    }
    if (ctx.limitClause() != null) {
      parseLimitClause(ctx.limitClause(), showTimeSeriesStatement);
    }
    return showTimeSeriesStatement;
  }

  private void parseTagWhereClause(IoTDBSqlParser.TagWhereClauseContext ctx, Statement statement) {
    IoTDBSqlParser.AttributeValueContext attributeValueContext;
    String key;
    String value;
    boolean isContains;
    if (ctx.containsExpression() != null) {
      isContains = true;
      attributeValueContext = ctx.containsExpression().attributeValue();
      key = parseAttributeKey(ctx.containsExpression().attributeKey());
    } else {
      isContains = false;
      attributeValueContext = ctx.attributePair().attributeValue();
      key = parseAttributeKey(ctx.attributePair().attributeKey());
    }
    value = parseAttributeValue(attributeValueContext);
    if (statement instanceof ShowTimeSeriesStatement) {
      ((ShowTimeSeriesStatement) statement).setContains(isContains);
      ((ShowTimeSeriesStatement) statement).setKey(key);
      ((ShowTimeSeriesStatement) statement).setValue(value);
    } else if (statement instanceof CountTimeSeriesStatement) {
      ((CountTimeSeriesStatement) statement).setContains(isContains);
      ((CountTimeSeriesStatement) statement).setKey(key);
      ((CountTimeSeriesStatement) statement).setValue(value);
    } else if (statement instanceof CountLevelTimeSeriesStatement) {
      ((CountLevelTimeSeriesStatement) statement).setContains(isContains);
      ((CountLevelTimeSeriesStatement) statement).setKey(key);
      ((CountLevelTimeSeriesStatement) statement).setValue(value);
    }
  }

  // Show Storage Group

  @Override
  public Statement visitShowStorageGroup(IoTDBSqlParser.ShowStorageGroupContext ctx) {
    if (ctx.prefixPath() != null) {
      return new ShowStorageGroupStatement(parsePrefixPath(ctx.prefixPath()));
    } else {
      return new ShowStorageGroupStatement(new PartialPath(SQLConstant.getSingleRootArray()));
    }
  }

  // Show Devices ========================================================================

  @Override
  public Statement visitShowDevices(IoTDBSqlParser.ShowDevicesContext ctx) {
    ShowDevicesStatement showDevicesStatement;
    if (ctx.prefixPath() != null) {
      showDevicesStatement = new ShowDevicesStatement(parsePrefixPath(ctx.prefixPath()));
    } else {
      showDevicesStatement =
          new ShowDevicesStatement(new PartialPath(SQLConstant.getSingleRootArray()));
    }
    if (ctx.limitClause() != null) {
      parseLimitClause(ctx.limitClause(), showDevicesStatement);
    }
    // show devices wtih storage group
    if (ctx.WITH() != null) {
      showDevicesStatement.setSgCol(true);
    }
    return showDevicesStatement;
  }

  // Count Devices ========================================================================

  @Override
  public Statement visitCountDevices(CountDevicesContext ctx) {
    PartialPath path;
    if (ctx.prefixPath() != null) {
      path = parsePrefixPath(ctx.prefixPath());
    } else {
      path = new PartialPath(SQLConstant.getSingleRootArray());
    }
    return new CountDevicesStatement(path);
  }

  // Count TimeSeries ========================================================================
  @Override
  public Statement visitCountTimeseries(CountTimeseriesContext ctx) {
    Statement statement;
    PartialPath path;
    if (ctx.prefixPath() != null) {
      path = parsePrefixPath(ctx.prefixPath());
    } else {
      path = new PartialPath(SQLConstant.getSingleRootArray());
    }
    if (ctx.INTEGER_LITERAL() != null) {
      int level = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
      statement = new CountLevelTimeSeriesStatement(path, level);
    } else {
      statement = new CountTimeSeriesStatement(path);
    }
    if (ctx.tagWhereClause() != null) {
      parseTagWhereClause(ctx.tagWhereClause(), statement);
    }
    return statement;
  }

  // Count Nodes ========================================================================
  @Override
  public Statement visitCountNodes(CountNodesContext ctx) {
    PartialPath path;
    if (ctx.prefixPath() != null) {
      path = parsePrefixPath(ctx.prefixPath());
    } else {
      path = new PartialPath(SQLConstant.getSingleRootArray());
    }
    int level = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
    return new CountNodesStatement(path, level);
  }

  // Count StorageGroup ========================================================================
  @Override
  public Statement visitCountStorageGroup(CountStorageGroupContext ctx) {
    PartialPath path;
    if (ctx.prefixPath() != null) {
      path = parsePrefixPath(ctx.prefixPath());
    } else {
      path = new PartialPath(SQLConstant.getSingleRootArray());
    }
    return new CountStorageGroupStatement(path);
  }

  // Show version
  @Override
  public Statement visitShowVersion(IoTDBSqlParser.ShowVersionContext ctx) {
    return new ShowVersionStatement();
  }

  // Create Function
  @Override
  public Statement visitCreateFunction(CreateFunctionContext ctx) {
    return new CreateFunctionStatement(
        parseIdentifier(ctx.udfName.getText()),
        parseStringLiteral(ctx.className.getText()),
        parseUris(ctx.uri()));
  }

  private List<URI> parseUris(List<UriContext> uriContexts) {
    List<URI> uris = new ArrayList<>();
    if (uriContexts != null) {
      for (UriContext uriContext : uriContexts) {
        final String uriString = uriContext.getText();
        try {
          uris.add(new URI(parseStringLiteral(uriString)));
        } catch (URISyntaxException e) {
          throw new SemanticException(String.format("'%s' is not a legal URI.", uriString));
        }
      }
    }
    return uris;
  }

  // Drop Function
  @Override
  public Statement visitDropFunction(DropFunctionContext ctx) {
    return new DropFunctionStatement(parseIdentifier(ctx.udfName.getText()));
  }

  // Show Functions
  @Override
  public Statement visitShowFunctions(ShowFunctionsContext ctx) {
    return new ShowFunctionsStatement();
  }

  // Create Trigger =====================================================================
  @Override
  public Statement visitCreateTrigger(IoTDBSqlParser.CreateTriggerContext ctx) {
    if (ctx.triggerEventClause().DELETE() != null) {
      throw new SemanticException("Trigger does not support DELETE as TRIGGER_EVENT for now.");
    }
    if (ctx.triggerType() == null) {
      throw new SemanticException("Please specify trigger type: STATELESS or STATEFUL.");
    }
    if (ctx.jarLocation() == null) {
      throw new SemanticException("Please specify the location of jar.");
    }
    // parse jarPath
    String jarPath;
    boolean usingURI;
    if (ctx.jarLocation().FILE() != null) {
      usingURI = false;
      jarPath = parseFilePath(ctx.jarLocation().fileName.getText());
    } else {
      usingURI = true;
      jarPath = parseFilePath(ctx.jarLocation().uri().getText());
    }
    Map<String, String> attributes = new HashMap<>();
    if (ctx.triggerAttributeClause() != null) {
      for (IoTDBSqlParser.TriggerAttributeContext triggerAttributeContext :
          ctx.triggerAttributeClause().triggerAttribute()) {
        attributes.put(
            parseAttributeKey(triggerAttributeContext.key),
            parseAttributeValue(triggerAttributeContext.value));
      }
    }
    return new CreateTriggerStatement(
        parseIdentifier(ctx.triggerName.getText()),
        parseStringLiteral(ctx.className.getText()),
        jarPath,
        usingURI,
        ctx.triggerEventClause().BEFORE() != null
            ? TriggerEvent.BEFORE_INSERT
            : TriggerEvent.AFTER_INSERT,
        ctx.triggerType().STATELESS() != null ? TriggerType.STATELESS : TriggerType.STATEFUL,
        parsePrefixPath(ctx.prefixPath()),
        attributes);
  }

  @Override
  public Statement visitDropTrigger(IoTDBSqlParser.DropTriggerContext ctx) {
    return new DropTriggerStatement(parseIdentifier(ctx.triggerName.getText()));
  }

  @Override
  public Statement visitShowTriggers(IoTDBSqlParser.ShowTriggersContext ctx) {
    return new ShowTriggersStatement();
  }

  // Show Child Paths =====================================================================
  @Override
  public Statement visitShowChildPaths(IoTDBSqlParser.ShowChildPathsContext ctx) {
    if (ctx.prefixPath() != null) {
      return new ShowChildPathsStatement(parsePrefixPath(ctx.prefixPath()));
    } else {
      return new ShowChildPathsStatement(new PartialPath(SQLConstant.getSingleRootArray()));
    }
  }

  // Show Child Nodes =====================================================================
  @Override
  public Statement visitShowChildNodes(IoTDBSqlParser.ShowChildNodesContext ctx) {
    if (ctx.prefixPath() != null) {
      return new ShowChildNodesStatement(parsePrefixPath(ctx.prefixPath()));
    } else {
      return new ShowChildNodesStatement(new PartialPath(SQLConstant.getSingleRootArray()));
    }
  }

  /** Data Manipulation Language (DML) */

  // Select Statement ========================================================================

  private QueryStatement queryStatement;

  @Override
  public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext ctx) {
    if (ctx.intoClause() != null) {
      throw new SemanticException(
          "The SELECT-INTO statement is not supported in the current version.");
    }

    // initialize query statement
    queryStatement = new QueryStatement();

    // parser select, from
    parseSelectClause(ctx.selectClause());
    parseFromClause(ctx.fromClause());

    // parse where clause
    if (ctx.whereClause() != null) {
      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
      queryStatement.setWhereCondition(whereCondition);
    }

    // parser special clause
    if (ctx.specialClause() != null) {
      queryStatement = (QueryStatement) visit(ctx.specialClause());
    }
    return queryStatement;
  }

  // Select Clause

  public void parseSelectClause(IoTDBSqlParser.SelectClauseContext ctx) {
    SelectComponent selectComponent = new SelectComponent(zoneId);

    // parse LAST
    if (ctx.LAST() != null) {
      selectComponent.setHasLast(true);
    }

    // parse resultColumn
    Map<String, Expression> aliasToColumnMap = new HashMap<>();
    for (IoTDBSqlParser.ResultColumnContext resultColumnContext : ctx.resultColumn()) {
      ResultColumn resultColumn = parseResultColumn(resultColumnContext);
      if (resultColumn.hasAlias()) {
        String alias = resultColumn.getAlias();
        if (aliasToColumnMap.containsKey(alias)) {
          throw new SemanticException("duplicate alias in select clause");
        }
        aliasToColumnMap.put(alias, resultColumn.getExpression());
      }
      selectComponent.addResultColumn(resultColumn);
    }
    selectComponent.setAliasToColumnMap(aliasToColumnMap);

    // set selectComponent
    queryStatement.setSelectComponent(selectComponent);
  }

  private ResultColumn parseResultColumn(IoTDBSqlParser.ResultColumnContext resultColumnContext) {
    Expression expression = parseExpression(resultColumnContext.expression(), false);
    if (expression.isConstantOperand()) {
      throw new SemanticException("Constant operand is not allowed: " + expression);
    }
    String alias = null;
    if (resultColumnContext.AS() != null) {
      alias = parseAlias(resultColumnContext.alias());
    }
    ResultColumn.ColumnType columnType =
        ExpressionAnalyzer.identifyOutputColumnType(expression, true);
    return new ResultColumn(expression, alias, columnType);
  }

  // From Clause

  public void parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
    FromComponent fromComponent = new FromComponent();
    List<IoTDBSqlParser.PrefixPathContext> prefixFromPaths = ctx.prefixPath();
    for (IoTDBSqlParser.PrefixPathContext prefixFromPath : prefixFromPaths) {
      PartialPath path = parsePrefixPath(prefixFromPath);
      fromComponent.addPrefixPath(path);
    }
    queryStatement.setFromComponent(fromComponent);
  }

  // Where Clause

  public WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext ctx) {
    Expression predicate =
        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == null);
    return new WhereCondition(predicate);
  }

  // Group By Time Clause

  @Override
  public Statement visitGroupByTimeStatement(IoTDBSqlParser.GroupByTimeStatementContext ctx) {
    // parse group by time clause
    parseGroupByTimeClause(ctx.groupByTimeClause());

    // parse order by time
    if (ctx.orderByClause() != null) {
      parseOrderByClause(ctx.orderByClause());
    }

    // parse Having
    if (ctx.havingClause() != null) {
      parseHavingClause(ctx.havingClause());
    }

    // parse limit & offset
    if (ctx.specialLimit() != null) {
      return visit(ctx.specialLimit());
    }

    return queryStatement;
  }

  @Override
  public Statement visitGroupByFillStatement(IoTDBSqlParser.GroupByFillStatementContext ctx) {
    // parse group by time clause & fill clause
    parseGroupByTimeClause(ctx.groupByFillClause());

    // parse order by time
    if (ctx.orderByClause() != null) {
      parseOrderByClause(ctx.orderByClause());
    }

    // parse Having
    if (ctx.havingClause() != null) {
      parseHavingClause(ctx.havingClause());
    }

    // parse limit & offset
    if (ctx.specialLimit() != null) {
      return visit(ctx.specialLimit());
    }
    return queryStatement;
  }

  private void parseGroupByTimeClause(IoTDBSqlParser.GroupByTimeClauseContext ctx) {
    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();

    // parse time range
    parseTimeRange(ctx.timeRange(), groupByTimeComponent);
    groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);

    // parse time interval
    groupByTimeComponent.setInterval(
        parseTimeIntervalOrSlidingStep(
            ctx.DURATION_LITERAL(0).getText(), true, groupByTimeComponent));
    if (groupByTimeComponent.getInterval() <= 0) {
      throw new SemanticException(
          "The second parameter time interval should be a positive integer.");
    }

    // parse sliding step
    if (ctx.DURATION_LITERAL().size() == 2) {
      groupByTimeComponent.setSlidingStep(
          parseTimeIntervalOrSlidingStep(
              ctx.DURATION_LITERAL(1).getText(), false, groupByTimeComponent));
    } else {
      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
      groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
    }

    // parse GroupByLevel clause
    if (ctx.LEVEL() != null && ctx.INTEGER_LITERAL() != null) {
      GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
      int[] levels = new int[ctx.INTEGER_LITERAL().size()];
      for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
        levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
      }
      groupByLevelComponent.setLevels(levels);
      queryStatement.setGroupByLevelComponent(groupByLevelComponent);
    }

    // parse fill clause
    if (ctx.fillClause() != null) {
      parseFillClause(ctx.fillClause());
    }

    // set groupByTimeComponent
    queryStatement.setGroupByTimeComponent(groupByTimeComponent);
  }

  private void parseGroupByTimeClause(IoTDBSqlParser.GroupByFillClauseContext ctx) {
    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();

    // parse time range
    parseTimeRange(ctx.timeRange(), groupByTimeComponent);
    groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);

    // parse time interval
    groupByTimeComponent.setInterval(
        parseTimeIntervalOrSlidingStep(
            ctx.DURATION_LITERAL(0).getText(), true, groupByTimeComponent));
    if (groupByTimeComponent.getInterval() <= 0) {
      throw new SemanticException(
          "The second parameter time interval should be a positive integer.");
    }

    // parse sliding step
    if (ctx.DURATION_LITERAL().size() == 2) {
      groupByTimeComponent.setSlidingStep(
          parseTimeIntervalOrSlidingStep(
              ctx.DURATION_LITERAL(1).getText(), false, groupByTimeComponent));
    } else {
      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
      groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
    }

    // parse fill clause
    if (ctx.fillClause() != null) {
      parseFillClause(ctx.fillClause());
    }

    // set groupByTimeComponent
    queryStatement.setGroupByTimeComponent(groupByTimeComponent);
  }

  /** parse time range (startTime and endTime) in group by query. */
  private void parseTimeRange(
      IoTDBSqlParser.TimeRangeContext timeRange, GroupByTimeComponent groupByClauseComponent) {
    long currentTime = DatetimeUtils.currentTime();
    long startTime = parseTimeValue(timeRange.timeValue(0), currentTime);
    long endTime = parseTimeValue(timeRange.timeValue(1), currentTime);
    groupByClauseComponent.setStartTime(startTime);
    groupByClauseComponent.setEndTime(endTime);
    if (startTime >= endTime) {
      throw new SemanticException("Start time should be smaller than endTime in GroupBy");
    }
  }

  /**
   * parse time interval or sliding step in group by query.
   *
   * @param duration represent duration string like: 12d8m9ns, 1y1d, etc.
   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
   */
  private long parseTimeIntervalOrSlidingStep(
      String duration, boolean isParsingTimeInterval, GroupByTimeComponent groupByTimeComponent) {
    if (duration.toLowerCase().contains("mo")) {
      if (isParsingTimeInterval) {
        groupByTimeComponent.setIntervalByMonth(true);
      } else {
        groupByTimeComponent.setSlidingStepByMonth(true);
      }
    }
    return DatetimeUtils.convertDurationStrToLong(duration);
  }

  // Group By Level Clause
  @Override
  public Statement visitGroupByLevelStatement(IoTDBSqlParser.GroupByLevelStatementContext ctx) {
    // parse GroupByLevel clause
    parseGroupByLevelClause(ctx.groupByLevelClause());

    // parse order by time
    if (ctx.orderByClause() != null) {
      parseOrderByClause(ctx.orderByClause());
    }

    // parse Having
    if (ctx.havingClause() != null) {
      parseHavingClause(ctx.havingClause());
    }

    // parse limit & offset
    if (ctx.specialLimit() != null) {
      return visit(ctx.specialLimit());
    }
    return queryStatement;
  }

  public void parseGroupByLevelClause(IoTDBSqlParser.GroupByLevelClauseContext ctx) {
    GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
    int[] levels = new int[ctx.INTEGER_LITERAL().size()];
    for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
      levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
    }
    groupByLevelComponent.setLevels(levels);

    // parse fill clause
    if (ctx.fillClause() != null) {
      parseFillClause(ctx.fillClause());
    }

    queryStatement.setGroupByLevelComponent(groupByLevelComponent);
  }

  // HAVING Clause
  public void parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
    Expression predicate =
        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == null);
    queryStatement.setHavingCondition(new HavingCondition(predicate));
  }

  // Fill Clause
  @Override
  public Statement visitFillStatement(IoTDBSqlParser.FillStatementContext ctx) {
    // parse fill
    parseFillClause(ctx.fillClause());

    // parse order by time
    if (ctx.orderByClause() != null) {
      parseOrderByClause(ctx.orderByClause());
    }

    // parse limit & offset
    if (ctx.specialLimit() != null) {
      return visit(ctx.specialLimit());
    }
    return queryStatement;
  }

  public void parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
    FillComponent fillComponent = new FillComponent();
    if (ctx.linearClause() != null) {
      if (ctx.linearClause().DURATION_LITERAL().size() > 0) {
        throw new SemanticException("The specified fill time range is not supported.");
      }
      fillComponent.setFillPolicy(FillPolicy.LINEAR);
    } else if (ctx.previousClause() != null) {
      if (ctx.previousClause().DURATION_LITERAL() != null) {
        throw new SemanticException("The specified fill time range is not supported.");
      }
      fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
    } else if (ctx.specificValueClause() != null) {
      fillComponent.setFillPolicy(FillPolicy.VALUE);
      if (ctx.specificValueClause().constant() != null) {
        Literal fillValue = parseLiteral(ctx.specificValueClause().constant());
        fillComponent.setFillValue(fillValue);
      } else {
        throw new SemanticException("fill value cannot be null");
      }
    } else if (ctx.previousUntilLastClause() != null) {
      throw new SemanticException("PREVIOUSUNTILLAST fill is not supported yet.");
    } else if (ctx.oldTypeClause() != null) {
      throw new SemanticException("The specified fill datatype is not supported.");
    }
    queryStatement.setFillComponent(fillComponent);
  }

  private Literal parseLiteral(ConstantContext constantContext) {
    String text = constantContext.getText();
    if (constantContext.BOOLEAN_LITERAL() != null) {
      return new BooleanLiteral(text);
    } else if (constantContext.STRING_LITERAL() != null) {
      return new StringLiteral(parseStringLiteral(text));
    } else if (constantContext.INTEGER_LITERAL() != null) {
      return new LongLiteral(text);
    } else if (constantContext.realLiteral() != null) {
      return new DoubleLiteral(text);
    } else if (constantContext.dateExpression() != null) {
      return new LongLiteral(parseDateExpression(constantContext.dateExpression()));
    } else {
      throw new SQLParserException("Unsupported constant operand: " + text);
    }
  }

  // Other Clauses
  @Override
  public Statement visitSpecialLimitStatement(IoTDBSqlParser.SpecialLimitStatementContext ctx) {
    return visit(ctx.specialLimit());
  }

  @Override
  public Statement visitLimitStatement(IoTDBSqlParser.LimitStatementContext ctx) {
    // parse LIMIT
    parseLimitClause(ctx.limitClause(), queryStatement);

    // parse SLIMIT
    if (ctx.slimitClause() != null) {
      parseSlimitClause(ctx.slimitClause());
    }

    // parse ALIGN BY DEVICE or DISABLE ALIGN
    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
      parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
    }
    return queryStatement;
  }

  // parse LIMIT & OFFSET
  private void parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx, Statement statement) {
    int limit;
    try {
      limit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
    } catch (NumberFormatException e) {
      throw new SemanticException("Out of range. LIMIT <N>: N should be Int32.");
    }
    if (limit <= 0) {
      throw new SemanticException("LIMIT <N>: N should be greater than 0.");
    }
    if (statement instanceof ShowTimeSeriesStatement) {
      ((ShowTimeSeriesStatement) statement).setLimit(limit);
    } else if (statement instanceof ShowDevicesStatement) {
      ((ShowDevicesStatement) statement).setLimit(limit);
    } else {
      queryStatement.setRowLimit(limit);
    }

    // parse OFFSET
    if (ctx.offsetClause() != null) {
      parseOffsetClause(ctx.offsetClause(), statement);
    }
  }

  // parse OFFSET
  private void parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx, Statement statement) {
    int offset;
    try {
      offset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
    } catch (NumberFormatException e) {
      throw new SemanticException(
          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32.");
    }
    if (offset < 0) {
      throw new SemanticException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
    }
    if (statement instanceof ShowTimeSeriesStatement) {
      ((ShowTimeSeriesStatement) statement).setOffset(offset);
    } else if (statement instanceof ShowDevicesStatement) {
      ((ShowDevicesStatement) statement).setOffset(offset);
    } else {
      queryStatement.setRowOffset(offset);
    }
  }

  @Override
  public Statement visitSlimitStatement(IoTDBSqlParser.SlimitStatementContext ctx) {
    // parse SLIMIT
    parseSlimitClause(ctx.slimitClause());

    // parse LIMIT
    if (ctx.limitClause() != null) {
      parseLimitClause(ctx.limitClause(), queryStatement);
    }

    // parse ALIGN BY DEVICE or DISABLE ALIGN
    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
      parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
    }
    return queryStatement;
  }

  // parse SLIMIT & SOFFSET
  private void parseSlimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
    int slimit;
    try {
      slimit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
    } catch (NumberFormatException e) {
      throw new SemanticException("Out of range. SLIMIT <SN>: SN should be Int32.");
    }
    if (slimit <= 0) {
      throw new SemanticException("SLIMIT <SN>: SN should be greater than 0.");
    }
    queryStatement.setSeriesLimit(slimit);

    // parse SOFFSET
    if (ctx.soffsetClause() != null) {
      parseSoffsetClause(ctx.soffsetClause());
    }
  }

  // parse SOFFSET
  public void parseSoffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
    int soffset;
    try {
      soffset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
    } catch (NumberFormatException e) {
      throw new SemanticException(
          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
    }
    if (soffset < 0) {
      throw new SemanticException("SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
    }
    queryStatement.setSeriesOffset(soffset);
  }

  // WITHOUT NULL Clause

  @Override
  public Statement visitWithoutNullStatement(IoTDBSqlParser.WithoutNullStatementContext ctx) {
    // parse WITHOUT NULL
    parseWithoutNullClause(ctx.withoutNullClause());

    // parse LIMIT & OFFSET
    if (ctx.limitClause() != null) {
      parseLimitClause(ctx.limitClause(), queryStatement);
    }

    // parse SLIMIT & SOFFSET
    if (ctx.slimitClause() != null) {
      parseSlimitClause(ctx.slimitClause());
    }

    // parse ALIGN BY DEVICE or DISABLE ALIGN
    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
      parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
    }
    return queryStatement;
  }

  // parse WITHOUT NULL
  private void parseWithoutNullClause(IoTDBSqlParser.WithoutNullClauseContext ctx) {
    throw new SemanticException("WITHOUT NULL clause is not supported yet.");
  }

  // ORDER BY TIME Clause

  @Override
  public Statement visitOrderByTimeStatement(IoTDBSqlParser.OrderByTimeStatementContext ctx) {
    // parse ORDER BY TIME
    parseOrderByClause(ctx.orderByClause());

    // parse others
    if (ctx.specialLimit() != null) {
      return visit(ctx.specialLimit());
    }
    return queryStatement;
  }

  // parse ORDER BY TIME
  private void parseOrderByClause(IoTDBSqlParser.OrderByClauseContext ctx) {
    OrderByComponent orderByComponent = new OrderByComponent();
    Set<SortKey> sortKeySet = new HashSet<>();
    for (IoTDBSqlParser.OrderByAttributeClauseContext orderByAttributeClauseContext :
        ctx.orderByAttributeClause()) {
      SortItem sortItem = parseOrderByAttributeClause(orderByAttributeClauseContext);

      SortKey sortKey = sortItem.getSortKey();
      if (sortKeySet.contains(sortKey)) {
        throw new SemanticException(String.format("ORDER BY: duplicate sort key '%s'", sortKey));
      } else {
        sortKeySet.add(sortKey);
        orderByComponent.addSortItem(sortItem);
      }
    }
    queryStatement.setOrderByComponent(orderByComponent);
  }

  private SortItem parseOrderByAttributeClause(IoTDBSqlParser.OrderByAttributeClauseContext ctx) {
    return new SortItem(
        SortKey.valueOf(ctx.sortKey().getText().toUpperCase()),
        ctx.DESC() != null ? Ordering.DESC : Ordering.ASC);
  }

  // ResultSetFormat Clause

  @Override
  public Statement visitAlignByDeviceClauseOrDisableAlignStatement(
      IoTDBSqlParser.AlignByDeviceClauseOrDisableAlignStatementContext ctx) {
    parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
    return queryStatement;
  }

  private void parseAlignByDeviceClauseOrDisableAlign(
      IoTDBSqlParser.AlignByDeviceClauseOrDisableAlignContext ctx) {
    if (ctx.alignByDeviceClause() != null) {
      queryStatement.setResultSetFormat(ResultSetFormat.ALIGN_BY_DEVICE);
    } else {
      queryStatement.setResultSetFormat(ResultSetFormat.DISABLE_ALIGN);
    }
  }

  // Insert Statement ========================================================================

  @Override
  public Statement visitInsertStatement(IoTDBSqlParser.InsertStatementContext ctx) {
    InsertStatement insertStatement = new InsertStatement();
    insertStatement.setDevice(parsePrefixPath(ctx.prefixPath()));
    boolean isTimeDefault = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, isTimeDefault);
    insertStatement.setAligned(ctx.ALIGNED() != null);
    return insertStatement;
  }

  private boolean parseInsertColumnSpec(
      IoTDBSqlParser.InsertColumnsSpecContext ctx, InsertStatement insertStatement) {
    List<String> measurementList = new ArrayList<>();
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext measurementName :
        ctx.nodeNameWithoutWildcard()) {
      measurementList.add(parseNodeNameWithoutWildCard(measurementName));
    }
    insertStatement.setMeasurementList(measurementList.toArray(new String[0]));
    return (ctx.TIME() == null && ctx.TIMESTAMP() == null);
  }

  private void parseInsertValuesSpec(
      IoTDBSqlParser.InsertValuesSpecContext ctx,
      InsertStatement insertStatement,
      boolean isTimeDefault) {
    List<IoTDBSqlParser.InsertMultiValueContext> insertMultiValues = ctx.insertMultiValue();
    List<String[]> valuesList = new ArrayList<>();
    long[] timeArray = new long[insertMultiValues.size()];
    for (int i = 0; i < insertMultiValues.size(); i++) {
      // parse timestamp
      long timestamp;
      List<String> valueList = new ArrayList<>();

      if (insertMultiValues.get(i).timeValue() != null) {
        if (isTimeDefault) {
          if (insertMultiValues.size() != 1) {
            throw new SemanticException("need timestamps when insert multi rows");
          }
          valueList.add(insertMultiValues.get(i).timeValue().getText());
          timestamp = DatetimeUtils.currentTime();
        } else {
          timestamp =
              parseTimeValue(insertMultiValues.get(i).timeValue(), DatetimeUtils.currentTime());
        }
      } else {
        if (!isTimeDefault) {
          throw new SemanticException(
              "the measurementList's size is not consistent with the valueList's size");
        }
        if (insertMultiValues.size() != 1) {
          throw new SemanticException("need timestamps when insert multi rows");
        }
        timestamp = parseDateFormat(SQLConstant.NOW_FUNC);
      }
      timeArray[i] = timestamp;

      // parse values
      List<IoTDBSqlParser.MeasurementValueContext> values =
          insertMultiValues.get(i).measurementValue();
      for (IoTDBSqlParser.MeasurementValueContext value : values) {
        for (IoTDBSqlParser.ConstantContext constant : value.constant()) {
          if (constant.STRING_LITERAL() != null) {
            valueList.add(parseStringLiteralInInsertValue(constant.getText()));
          } else {
            valueList.add(constant.getText());
          }
        }
      }
      valuesList.add(valueList.toArray(new String[0]));
    }
    insertStatement.setTimes(timeArray);
    insertStatement.setValuesList(valuesList);
  }

  // Load File

  @Override
  public Statement visitLoadFile(IoTDBSqlParser.LoadFileContext ctx) {
    LoadTsFileStatement loadTsFileStatement =
        new LoadTsFileStatement(parseStringLiteral(ctx.fileName.getText()));
    if (ctx.loadFilesClause() != null) {
      parseLoadFiles(loadTsFileStatement, ctx.loadFilesClause());
    }
    return loadTsFileStatement;
  }

  /**
   * used for parsing load tsfile, context will be one of "SCHEMA, LEVEL, METADATA", and maybe
   * followed by a recursion property statement
   *
   * @param loadTsFileStatement the result statement, setting by clause context
   * @param ctx context of property statement
   */
  private void parseLoadFiles(
      LoadTsFileStatement loadTsFileStatement, IoTDBSqlParser.LoadFilesClauseContext ctx) {
    if (ctx.AUTOREGISTER() != null) {
      loadTsFileStatement.setAutoCreateSchema(
          Boolean.parseBoolean(ctx.BOOLEAN_LITERAL().getText()));
    } else if (ctx.SGLEVEL() != null) {
      loadTsFileStatement.setSgLevel(Integer.parseInt(ctx.INTEGER_LITERAL().getText()));
    } else if (ctx.VERIFY() != null) {
      loadTsFileStatement.setVerifySchema(Boolean.parseBoolean(ctx.BOOLEAN_LITERAL().getText()));
    } else {
      throw new SQLParserException(
          String.format(
              "load tsfile format %s error, please input AUTOREGISTER | SGLEVEL | VERIFY.",
              ctx.getText()));
    }
    if (ctx.loadFilesClause() != null) {
      parseLoadFiles(loadTsFileStatement, ctx.loadFilesClause());
    }
  }

  /** Common Parsers */

  // IoTDB Objects ========================================================================

  private PartialPath parseFullPath(IoTDBSqlParser.FullPathContext ctx) {
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
        ctx.nodeNameWithoutWildcard();
    String[] path = new String[nodeNamesWithoutStar.size() + 1];
    int i = 0;
    if (ctx.ROOT() != null) {
      path[0] = ctx.ROOT().getText();
    }
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext nodeNameWithoutStar : nodeNamesWithoutStar) {
      i++;
      path[i] = parseNodeNameWithoutWildCard(nodeNameWithoutStar);
    }
    return new PartialPath(path);
  }

  /** path of expression in withoutNull clause can start with root. */
  private PartialPath parseFullPathInExpression(
      IoTDBSqlParser.FullPathInExpressionContext ctx, boolean inWithoutNull)
      throws SQLParserException {
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
    int size = nodeNames.size();
    if (ctx.ROOT() != null) {
      if (!inWithoutNull) {
        throw new SQLParserException("Path can not start with root in select clause.");
      }
      size++;
    }
    String[] path = new String[size];
    if (ctx.ROOT() != null) {
      path[0] = ctx.ROOT().getText();
      for (int i = 0; i < nodeNames.size(); i++) {
        path[i + 1] = parseNodeName(nodeNames.get(i));
      }
    } else {
      for (int i = 0; i < nodeNames.size(); i++) {
        path[i] = parseNodeName(nodeNames.get(i));
      }
    }
    return new PartialPath(path);
  }

  private PartialPath parsePrefixPath(IoTDBSqlParser.PrefixPathContext ctx) {
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
    String[] path = new String[nodeNames.size() + 1];
    path[0] = ctx.ROOT().getText();
    for (int i = 0; i < nodeNames.size(); i++) {
      path[i + 1] = parseNodeName(nodeNames.get(i));
    }
    return new PartialPath(path);
  }

  private PartialPath parseSuffixPath(IoTDBSqlParser.SuffixPathContext ctx) {
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
    String[] path = new String[nodeNames.size()];
    for (int i = 0; i < nodeNames.size(); i++) {
      path[i] = parseNodeName(nodeNames.get(i));
    }
    return new PartialPath(path);
  }

  private PartialPath convertConstantToPath(String src) throws IllegalPathException {
    return new PartialPath(src);
  }

  private String parseNodeName(IoTDBSqlParser.NodeNameContext ctx) {
    return parseNodeString(ctx.getText());
  }

  private String parseNodeNameWithoutWildCard(IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
    return parseNodeString(ctx.getText());
  }

  private String parseNodeString(String nodeName) {
    if (nodeName.equals(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)
        || nodeName.equals(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
      return nodeName;
    }
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
      String unWrapped = nodeName.substring(1, nodeName.length() - 1);
      if (PathUtils.isRealNumber(unWrapped)
          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(unWrapped).matches()) {
        return nodeName;
      }
      return unWrapped;
    }
    checkNodeName(nodeName);
    return nodeName;
  }

  private void checkNodeName(String src) {
    // node name could start with * and end with *
    if (!TsFileConstant.NODE_NAME_PATTERN.matcher(src).matches()) {
      throw new SQLParserException(
          String.format(
              "%s is illegal, unquoted node name can only consist of digits, characters and underscore, or start or end with wildcard",
              src));
    }
  }

  private void checkIdentifier(String src) {
    if (!TsFileConstant.IDENTIFIER_PATTERN.matcher(src).matches()) {
      throw new SQLParserException(
          String.format(
              "%s is illegal, unquoted identifier can only consist of digits, characters and underscore",
              src));
    }
  }

  // Literals ========================================================================

  public long parseDateFormat(String timestampStr) throws SQLParserException {
    if (timestampStr == null || "".equals(timestampStr.trim())) {
      throw new SemanticException("input timestamp cannot be empty");
    }
    if (timestampStr.equalsIgnoreCase(SQLConstant.NOW_FUNC)) {
      return DatetimeUtils.currentTime();
    }
    try {
      return DatetimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
    } catch (Exception e) {
      throw new SQLParserException(
          String.format(
              "Input time format %s error. "
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
                  + "refer to user document for more info.",
              timestampStr));
    }
  }

  public long parseDateFormat(String timestampStr, long currentTime) throws SQLParserException {
    if (timestampStr == null || "".equals(timestampStr.trim())) {
      throw new SemanticException("input timestamp cannot be empty");
    }
    if (timestampStr.equalsIgnoreCase(SQLConstant.NOW_FUNC)) {
      return currentTime;
    }
    try {
      return DatetimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
    } catch (Exception e) {
      throw new SQLParserException(
          String.format(
              "Input time format %s error. "
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
                  + "refer to user document for more info.",
              timestampStr));
    }
  }

  private String parseStringLiteral(String src) {
    if (2 <= src.length()) {
      // do not unescape string
      String unWrappedString = src.substring(1, src.length() - 1);
      if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
        // replace "" with "
        String replaced = unWrappedString.replace("\"\"", "\"");
        return replaced.length() == 0 ? "" : replaced;
      }
      if ((src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'')) {
        // replace '' with '
        String replaced = unWrappedString.replace("''", "'");
        return replaced.length() == 0 ? "" : replaced;
      }
    }
    return src;
  }

  private String parseStringLiteralInInsertValue(String src) {
    if (2 <= src.length()) {
      if ((src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"')
          || (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'')) {
        return "'" + parseStringLiteral(src) + "'";
      }
    }
    return src;
  }

  private String parseIdentifier(String src) {
    if (src.startsWith(TsFileConstant.BACK_QUOTE_STRING)
        && src.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
      return src.substring(1, src.length() - 1)
          .replace(TsFileConstant.DOUBLE_BACK_QUOTE_STRING, TsFileConstant.BACK_QUOTE_STRING);
    }
    checkIdentifier(src);
    return src;
  }

  /** function for parsing Alias. */
  private String parseAlias(IoTDBSqlParser.AliasContext ctx) {
    String alias;
    if (ctx.constant() != null) {
      alias = parseStringLiteral(ctx.constant().getText());
    } else {
      alias = parseIdentifier(ctx.identifier().getText());
    }
    return alias;
  }

  /** Data Control Language (DCL) */

  // Create User

  @Override
  public Statement visitCreateUser(IoTDBSqlParser.CreateUserContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.CREATE_USER);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    authorStatement.setPassWord(parseStringLiteral(ctx.password.getText()));
    return authorStatement;
  }

  // Create Role

  @Override
  public Statement visitCreateRole(IoTDBSqlParser.CreateRoleContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.CREATE_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    return authorStatement;
  }

  // Alter Password

  @Override
  public Statement visitAlterUser(IoTDBSqlParser.AlterUserContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.UPDATE_USER);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    authorStatement.setNewPassword(parseStringLiteral(ctx.password.getText()));
    return authorStatement;
  }

  // Grant User Privileges

  @Override
  public Statement visitGrantUser(IoTDBSqlParser.GrantUserContext ctx) {
    String[] privileges = parsePrivilege(ctx.privileges());
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream()
            .map(this::parsePrefixPath)
            .distinct()
            .collect(Collectors.toList());
    checkGrantRevokePrivileges(privileges, nodeNameList);

    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.GRANT_USER);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    authorStatement.setPrivilegeList(privileges);
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  // Grant Role Privileges

  @Override
  public Statement visitGrantRole(IoTDBSqlParser.GrantRoleContext ctx) {
    String[] privileges = parsePrivilege(ctx.privileges());
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream()
            .map(this::parsePrefixPath)
            .distinct()
            .collect(Collectors.toList());
    checkGrantRevokePrivileges(privileges, nodeNameList);

    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.GRANT_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    authorStatement.setPrivilegeList(privileges);
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  // Grant User Role

  @Override
  public Statement visitGrantRoleToUser(IoTDBSqlParser.GrantRoleToUserContext ctx) {
    AuthorStatement authorStatement =
        new AuthorStatement(AuthorOperator.AuthorType.GRANT_USER_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    return authorStatement;
  }

  // Revoke User Privileges

  @Override
  public Statement visitRevokeUser(IoTDBSqlParser.RevokeUserContext ctx) {
    String[] privileges = parsePrivilege(ctx.privileges());
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream()
            .map(this::parsePrefixPath)
            .distinct()
            .collect(Collectors.toList());
    checkGrantRevokePrivileges(privileges, nodeNameList);

    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.REVOKE_USER);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    authorStatement.setPrivilegeList(privileges);
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  // Revoke Role Privileges

  @Override
  public Statement visitRevokeRole(IoTDBSqlParser.RevokeRoleContext ctx) {
    String[] privileges = parsePrivilege(ctx.privileges());
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream()
            .map(this::parsePrefixPath)
            .distinct()
            .collect(Collectors.toList());
    checkGrantRevokePrivileges(privileges, nodeNameList);

    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.REVOKE_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    authorStatement.setPrivilegeList(privileges);
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  private void checkGrantRevokePrivileges(String[] privileges, List<PartialPath> nodeNameList) {
    if (nodeNameList.isEmpty()) {
      nodeNameList.addAll(Collections.singletonList(new PartialPath(ALL_RESULT_NODES)));
      return;
    }
    boolean pathRelevant = true;
    String errorPrivilegeName = "";
    for (String privilege : privileges) {
      if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
        pathRelevant = false;
        errorPrivilegeName = privilege.toUpperCase();
        break;
      }
    }
    if (!(pathRelevant
        || (nodeNameList.size() == 1
            && nodeNameList.contains(new PartialPath(ALL_RESULT_NODES))))) {
      throw new SQLParserException(
          String.format(
              "path independent privilege: [%s] can only be set on path: root.**",
              errorPrivilegeName));
    }
  }

  // Revoke Role From User

  @Override
  public Statement visitRevokeRoleFromUser(IoTDBSqlParser.RevokeRoleFromUserContext ctx) {
    AuthorStatement authorStatement =
        new AuthorStatement(AuthorOperator.AuthorType.REVOKE_USER_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    return authorStatement;
  }

  // Drop User

  @Override
  public Statement visitDropUser(IoTDBSqlParser.DropUserContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.DROP_USER);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    return authorStatement;
  }

  // Drop Role

  @Override
  public Statement visitDropRole(IoTDBSqlParser.DropRoleContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.DROP_ROLE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    return authorStatement;
  }

  // List Users

  @Override
  public Statement visitListUser(IoTDBSqlParser.ListUserContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.LIST_USER);
    if (ctx.roleName != null) {
      authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    }
    return authorStatement;
  }

  // List Roles

  @Override
  public Statement visitListRole(IoTDBSqlParser.ListRoleContext ctx) {
    AuthorStatement authorStatement = new AuthorStatement(AuthorOperator.AuthorType.LIST_ROLE);
    if (ctx.userName != null) {
      authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    }
    return authorStatement;
  }

  // List Privileges

  @Override
  public Statement visitListPrivilegesUser(IoTDBSqlParser.ListPrivilegesUserContext ctx) {
    AuthorStatement authorStatement =
        new AuthorStatement(AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  // List Privileges of Roles On Specific Path

  @Override
  public Statement visitListPrivilegesRole(IoTDBSqlParser.ListPrivilegesRoleContext ctx) {
    AuthorStatement authorStatement =
        new AuthorStatement(AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
    List<PartialPath> nodeNameList =
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
    authorStatement.setNodeNameList(nodeNameList);
    return authorStatement;
  }

  private String[] parsePrivilege(IoTDBSqlParser.PrivilegesContext ctx) {
    List<IoTDBSqlParser.PrivilegeValueContext> privilegeList = ctx.privilegeValue();
    List<String> privileges = new ArrayList<>();
    for (IoTDBSqlParser.PrivilegeValueContext privilegeValue : privilegeList) {
      privileges.add(privilegeValue.getText());
    }
    return privileges.toArray(new String[0]);
  }

  // Create Storage Group

  @Override
  public Statement visitSetStorageGroup(IoTDBSqlParser.SetStorageGroupContext ctx) {
    SetStorageGroupStatement setStorageGroupStatement = new SetStorageGroupStatement();
    PartialPath path = parsePrefixPath(ctx.prefixPath());
    setStorageGroupStatement.setStorageGroupPath(path);
    if (ctx.storageGroupAttributesClause() != null) {
      parseStorageGroupAttributesClause(
          setStorageGroupStatement, ctx.storageGroupAttributesClause());
    }
    return setStorageGroupStatement;
  }

  @Override
  public Statement visitCreateStorageGroup(IoTDBSqlParser.CreateStorageGroupContext ctx) {
    SetStorageGroupStatement setStorageGroupStatement = new SetStorageGroupStatement();
    PartialPath path = parsePrefixPath(ctx.prefixPath());
    setStorageGroupStatement.setStorageGroupPath(path);
    if (ctx.storageGroupAttributesClause() != null) {
      parseStorageGroupAttributesClause(
          setStorageGroupStatement, ctx.storageGroupAttributesClause());
    }
    return setStorageGroupStatement;
  }

  private void parseStorageGroupAttributesClause(
      SetStorageGroupStatement setStorageGroupStatement,
      IoTDBSqlParser.StorageGroupAttributesClauseContext ctx) {
    if (ctx.storageGroupAttributeClause().size() != 0) {
      throw new RuntimeException(
          "Currently not support set ttl, schemaReplication factor, dataReplication factor, time partition interval to specific storage group.");
    }
    for (IoTDBSqlParser.StorageGroupAttributeClauseContext attribute :
        ctx.storageGroupAttributeClause()) {
      if (attribute.TTL() != null) {
        long ttl = Long.parseLong(attribute.INTEGER_LITERAL().getText());
        setStorageGroupStatement.setTtl(ttl);
      } else if (attribute.SCHEMA_REPLICATION_FACTOR() != null) {
        int schemaReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
        setStorageGroupStatement.setSchemaReplicationFactor(schemaReplicationFactor);
      } else if (attribute.DATA_REPLICATION_FACTOR() != null) {
        int dataReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
        setStorageGroupStatement.setDataReplicationFactor(dataReplicationFactor);
      } else if (attribute.TIME_PARTITION_INTERVAL() != null) {
        long timePartitionInterval = Long.parseLong(attribute.INTEGER_LITERAL().getText());
        setStorageGroupStatement.setTimePartitionInterval(timePartitionInterval);
      }
    }
  }

  @Override
  public Statement visitSetTTL(IoTDBSqlParser.SetTTLContext ctx) {
    SetTTLStatement setTTLStatement = new SetTTLStatement();
    PartialPath path = parsePrefixPath(ctx.prefixPath());
    long ttl = Long.parseLong(ctx.INTEGER_LITERAL().getText());
    setTTLStatement.setStorageGroupPath(path);
    setTTLStatement.setTTL(ttl);
    return setTTLStatement;
  }

  @Override
  public Statement visitUnsetTTL(IoTDBSqlParser.UnsetTTLContext ctx) {
    UnSetTTLStatement unSetTTLStatement = new UnSetTTLStatement();
    PartialPath partialPath = parsePrefixPath(ctx.prefixPath());
    unSetTTLStatement.setStorageGroupPath(partialPath);
    return unSetTTLStatement;
  }

  @Override
  public Statement visitShowTTL(IoTDBSqlParser.ShowTTLContext ctx) {
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
      PartialPath partialPath = parsePrefixPath(prefixPathContext);
      showTTLStatement.addPathPatterns(partialPath);
    }
    return showTTLStatement;
  }

  @Override
  public Statement visitShowAllTTL(IoTDBSqlParser.ShowAllTTLContext ctx) {
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
    showTTLStatement.setAll(true);
    return showTTLStatement;
  }

  @Override
  public Statement visitShowCluster(IoTDBSqlParser.ShowClusterContext ctx) {
    ShowClusterStatement showClusterStatement = new ShowClusterStatement();
    return showClusterStatement;
  }

  @Override
  public Statement visitDeleteStorageGroup(IoTDBSqlParser.DeleteStorageGroupContext ctx) {
    DeleteStorageGroupStatement deleteStorageGroupStatement = new DeleteStorageGroupStatement();
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
    List<String> paths = new ArrayList<>();
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
    }
    deleteStorageGroupStatement.setPrefixPath(paths);
    return deleteStorageGroupStatement;
  }

  // Explain ========================================================================
  @Override
  public Statement visitExplain(IoTDBSqlParser.ExplainContext ctx) {
    QueryStatement queryStatement = (QueryStatement) visitSelectStatement(ctx.selectStatement());
    return new ExplainStatement(queryStatement);
  }

  @Override
  public Statement visitDeleteStatement(IoTDBSqlParser.DeleteStatementContext ctx) {
    DeleteDataStatement statement = new DeleteDataStatement();
    List<IoTDBSqlParser.PrefixPathContext> prefixPaths = ctx.prefixPath();
    List<PartialPath> pathList = new ArrayList<>();
    for (IoTDBSqlParser.PrefixPathContext prefixPath : prefixPaths) {
      pathList.add(parsePrefixPath(prefixPath));
    }
    statement.setPathList(pathList);
    if (ctx.whereClause() != null) {
      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
      TimeRange timeRange = parseDeleteTimeRange(whereCondition.getPredicate());
      statement.setTimeRange(timeRange);
    } else {
      statement.setTimeRange(new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE));
    }
    return statement;
  }

  private TimeRange parseDeleteTimeRange(Expression predicate) {
    if (predicate instanceof LogicAndExpression) {
      TimeRange leftTimeRange =
          parseDeleteTimeRange(((LogicAndExpression) predicate).getLeftExpression());
      TimeRange rightTimeRange =
          parseDeleteTimeRange(((LogicAndExpression) predicate).getRightExpression());
      return new TimeRange(
          Math.max(leftTimeRange.getMin(), rightTimeRange.getMin()),
          Math.min(leftTimeRange.getMax(), rightTimeRange.getMax()));
    } else if (predicate instanceof CompareBinaryExpression) {
      if (((CompareBinaryExpression) predicate).getLeftExpression() instanceof TimestampOperand) {
        return parseTimeRange(
            predicate.getExpressionType(),
            ((CompareBinaryExpression) predicate).getLeftExpression(),
            ((CompareBinaryExpression) predicate).getRightExpression());
      } else {
        return parseTimeRange(
            predicate.getExpressionType(),
            ((CompareBinaryExpression) predicate).getRightExpression(),
            ((CompareBinaryExpression) predicate).getLeftExpression());
      }
    } else {
      throw new SemanticException(DELETE_RANGE_ERROR_MSG);
    }
  }

  private TimeRange parseTimeRange(
      ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
    if (!(timeExpression instanceof TimestampOperand)
        || !(valueExpression instanceof ConstantOperand)) {
      throw new SemanticException(DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG);
    }

    if (((ConstantOperand) valueExpression).getDataType() != TSDataType.INT64) {
      throw new SemanticException("The datatype of timestamp should be LONG.");
    }

    long time = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
    switch (expressionType) {
      case LESS_THAN:
        return new TimeRange(Long.MIN_VALUE, time - 1);
      case LESS_EQUAL:
        return new TimeRange(Long.MIN_VALUE, time);
      case GREATER_THAN:
        return new TimeRange(time + 1, Long.MAX_VALUE);
      case GREATER_EQUAL:
        return new TimeRange(time, Long.MAX_VALUE);
      case EQUAL_TO:
        return new TimeRange(time, time);
      default:
        throw new SemanticException(DELETE_RANGE_ERROR_MSG);
    }
  }

  /** function for parsing file path used by LOAD statement. */
  public String parseFilePath(String src) {
    return src.substring(1, src.length() - 1);
  }

  // Expression & Predicate ========================================================================

  private Expression parseExpression(
      IoTDBSqlParser.ExpressionContext context, boolean inWithoutNull) {
    if (context.unaryInBracket != null) {
      return parseExpression(context.unaryInBracket, inWithoutNull);
    }

    if (context.expressionAfterUnaryOperator != null) {
      if (context.MINUS() != null) {
        return new NegationExpression(
            parseExpression(context.expressionAfterUnaryOperator, inWithoutNull));
      }
      if (context.OPERATOR_NOT() != null) {
        return new LogicNotExpression(
            parseExpression(context.expressionAfterUnaryOperator, inWithoutNull));
      }
      return parseExpression(context.expressionAfterUnaryOperator, inWithoutNull);
    }

    if (context.leftExpression != null && context.rightExpression != null) {
      Expression leftExpression = parseExpression(context.leftExpression, inWithoutNull);
      Expression rightExpression = parseExpression(context.rightExpression, inWithoutNull);
      if (context.STAR() != null) {
        return new MultiplicationExpression(leftExpression, rightExpression);
      }
      if (context.DIV() != null) {
        return new DivisionExpression(leftExpression, rightExpression);
      }
      if (context.MOD() != null) {
        return new ModuloExpression(leftExpression, rightExpression);
      }
      if (context.PLUS() != null) {
        return new AdditionExpression(leftExpression, rightExpression);
      }
      if (context.MINUS() != null) {
        return new SubtractionExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_GT() != null) {
        return new GreaterThanExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_GTE() != null) {
        return new GreaterEqualExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_LT() != null) {
        return new LessThanExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_LTE() != null) {
        return new LessEqualExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_DEQ() != null || context.OPERATOR_SEQ() != null) {
        return new EqualToExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_NEQ() != null) {
        return new NonEqualExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_AND() != null) {
        return new LogicAndExpression(leftExpression, rightExpression);
      }
      if (context.OPERATOR_OR() != null) {
        return new LogicOrExpression(leftExpression, rightExpression);
      }
      throw new UnsupportedOperationException();
    }

    if (context.unaryBeforeRegularOrLikeExpression != null) {
      if (context.REGEXP() != null) {
        return parseRegularExpression(context, inWithoutNull);
      }
      if (context.LIKE() != null) {
        return parseLikeExpression(context, inWithoutNull);
      }
      throw new UnsupportedOperationException();
    }

    if (context.unaryBeforeIsNullExpression != null) {
      return parseIsNullExpression(context, inWithoutNull);
    }

    if (context.firstExpression != null
        && context.secondExpression != null
        && context.thirdExpression != null) {
      Expression firstExpression = parseExpression(context.firstExpression, inWithoutNull);
      Expression secondExpression = parseExpression(context.secondExpression, inWithoutNull);
      Expression thirdExpression = parseExpression(context.thirdExpression, inWithoutNull);

      if (context.OPERATOR_BETWEEN() != null) {
        return new BetweenExpression(
            firstExpression, secondExpression, thirdExpression, context.OPERATOR_NOT() != null);
      }
      throw new UnsupportedOperationException();
    }

    if (context.unaryBeforeInExpression != null) {
      return parseInExpression(context, inWithoutNull);
    }

    if (context.functionName() != null) {
      return parseFunctionExpression(context, inWithoutNull);
    }

    if (context.fullPathInExpression() != null) {
      return new TimeSeriesOperand(
          parseFullPathInExpression(context.fullPathInExpression(), inWithoutNull));
    }

    if (context.time != null) {
      return new TimestampOperand();
    }

    if (context.constant() != null && !context.constant().isEmpty()) {
      return parseConstantOperand(context.constant(0));
    }

    throw new UnsupportedOperationException();
  }

  private Expression parseFunctionExpression(
      IoTDBSqlParser.ExpressionContext functionClause, boolean inWithoutNull) {
    FunctionExpression functionExpression =
        new FunctionExpression(parseIdentifier(functionClause.functionName().getText()));

    // expressions
    boolean hasNonPureConstantSubExpression = false;
    for (IoTDBSqlParser.ExpressionContext expression : functionClause.expression()) {
      Expression subexpression = parseExpression(expression, inWithoutNull);
      if (!subexpression.isConstantOperand()) {
        hasNonPureConstantSubExpression = true;
      }
      if (subexpression instanceof EqualToExpression
          && ((EqualToExpression) subexpression).getLeftExpression().isConstantOperand()
          && ((EqualToExpression) subexpression).getRightExpression().isConstantOperand()) {
        // parse attribute
        functionExpression.addAttribute(
            ((ConstantOperand) ((EqualToExpression) subexpression).getLeftExpression())
                .getValueString(),
            ((ConstantOperand) ((EqualToExpression) subexpression).getRightExpression())
                .getValueString());
      } else {
        functionExpression.addExpression(subexpression);
      }
    }

    // It is not allowed to have function expressions like F(1, 1.0). There should be at least one
    // non-pure-constant sub-expression, otherwise the timestamp of the row cannot be inferred.
    if (!hasNonPureConstantSubExpression) {
      throw new SemanticException(
          "Invalid function expression, all the arguments are constant operands: "
              + functionClause.getText());
    }
    return functionExpression;
  }

  private Expression parseRegularExpression(ExpressionContext context, boolean inWithoutNull) {
    return new RegularExpression(
        parseExpression(context.unaryBeforeRegularOrLikeExpression, inWithoutNull),
        parseStringLiteral(context.STRING_LITERAL().getText()));
  }

  private Expression parseLikeExpression(ExpressionContext context, boolean inWithoutNull) {
    return new LikeExpression(
        parseExpression(context.unaryBeforeRegularOrLikeExpression, inWithoutNull),
        parseStringLiteral(context.STRING_LITERAL().getText()));
  }

  private Expression parseIsNullExpression(ExpressionContext context, boolean inWithoutNull) {
    return new IsNullExpression(
        parseExpression(context.unaryBeforeIsNullExpression, inWithoutNull),
        context.OPERATOR_NOT() != null);
  }

  private Expression parseInExpression(ExpressionContext context, boolean inWithoutNull) {
    Expression childExpression = parseExpression(context.unaryBeforeInExpression, inWithoutNull);
    LinkedHashSet<String> values = new LinkedHashSet<>();
    for (ConstantContext constantContext : context.constant()) {
      values.add(parseConstant(constantContext));
    }
    return new InExpression(childExpression, context.OPERATOR_NOT() != null, values);
  }

  private String parseConstant(ConstantContext constantContext) {
    String text = constantContext.getText();
    if (constantContext.BOOLEAN_LITERAL() != null
        || constantContext.INTEGER_LITERAL() != null
        || constantContext.realLiteral() != null) {
      return text;
    } else if (constantContext.STRING_LITERAL() != null) {
      return parseStringLiteral(text);
    } else if (constantContext.dateExpression() != null) {
      return String.valueOf(parseDateExpression(constantContext.dateExpression()));
    } else {
      throw new IllegalArgumentException("Unsupported constant operand: " + text);
    }
  }

  private Expression parseConstantOperand(ConstantContext constantContext) {
    String text = constantContext.getText();
    if (constantContext.BOOLEAN_LITERAL() != null) {
      return new ConstantOperand(TSDataType.BOOLEAN, text);
    } else if (constantContext.STRING_LITERAL() != null) {
      return new ConstantOperand(TSDataType.TEXT, parseStringLiteral(text));
    } else if (constantContext.INTEGER_LITERAL() != null) {
      return new ConstantOperand(TSDataType.INT64, text);
    } else if (constantContext.realLiteral() != null) {
      return parseRealLiteral(text);
    } else if (constantContext.dateExpression() != null) {
      return new ConstantOperand(
          TSDataType.INT64, String.valueOf(parseDateExpression(constantContext.dateExpression())));
    } else {
      throw new SQLParserException("Unsupported constant operand: " + text);
    }
  }

  private Expression parseRealLiteral(String value) {
    // 3.33 is float by default
    return new ConstantOperand(
        CONFIG.getFloatingStringInferType().equals(TSDataType.DOUBLE)
            ? TSDataType.DOUBLE
            : TSDataType.FLOAT,
        value);
  }

  /**
   * parse time expression, which is addition and subtraction expression of duration time, now() or
   * DataTimeFormat time.
   *
   * <p>eg. now() + 1d - 2h
   */
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx) {
    long time;
    time = parseDateFormat(ctx.getChild(0).getText());
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
      if ("+".equals(ctx.getChild(i).getText())) {
        time += DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
      } else {
        time -= DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
      }
    }
    return time;
  }

  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx, long currentTime) {
    long time;
    time = parseDateFormat(ctx.getChild(0).getText(), currentTime);
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
      if ("+".equals(ctx.getChild(i).getText())) {
        time += DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
      } else {
        time -= DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
      }
    }
    return time;
  }

  private long parseTimeValue(IoTDBSqlParser.TimeValueContext ctx, long currentTime) {
    if (ctx.INTEGER_LITERAL() != null) {
      try {
        if (ctx.MINUS() != null) {
          return -Long.parseLong(ctx.INTEGER_LITERAL().getText());
        }
        return Long.parseLong(ctx.INTEGER_LITERAL().getText());
      } catch (NumberFormatException e) {
        throw new SQLParserException(
            String.format("Can not parse %s to long value", ctx.INTEGER_LITERAL().getText()));
      }
    } else if (ctx.dateExpression() != null) {
      return parseDateExpression(ctx.dateExpression(), currentTime);
    } else {
      return parseDateFormat(ctx.datetimeLiteral().getText(), currentTime);
    }
  }

  /** Utils */
  private void setMap(IoTDBSqlParser.AlterClauseContext ctx, Map<String, String> alterMap) {
    List<IoTDBSqlParser.AttributePairContext> tagsList = ctx.attributePair();
    if (ctx.attributePair(0) != null) {
      for (IoTDBSqlParser.AttributePairContext attributePair : tagsList) {
        String value;
        value = parseAttributeValue(attributePair.attributeValue());
        alterMap.put(parseAttributeKey(attributePair.attributeKey()), value);
      }
    }
  }

  private Map<String, String> extractMap(
      List<IoTDBSqlParser.AttributePairContext> attributePair2,
      IoTDBSqlParser.AttributePairContext attributePair3) {
    Map<String, String> tags = new HashMap<>(attributePair2.size());
    if (attributePair3 != null) {
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePair2) {
        tags.put(
            parseAttributeKey(attributePair.attributeKey()),
            parseAttributeValue(attributePair.attributeValue()));
      }
    }
    return tags;
  }

  private String parseAttributeKey(IoTDBSqlParser.AttributeKeyContext ctx) {
    if (ctx.constant() != null) {
      return parseStringLiteral(ctx.getText());
    }
    return parseIdentifier(ctx.getText());
  }

  private String parseAttributeValue(IoTDBSqlParser.AttributeValueContext ctx) {
    if (ctx.constant() != null) {
      return parseStringLiteral(ctx.getText());
    }
    return parseIdentifier(ctx.getText());
  }

  private Pair<Long, Long> calcOperatorInterval(QueryFilter queryFilter) {

    if (queryFilter.getSinglePath() != null
        && !IoTDBConstant.TIME.equals(queryFilter.getSinglePath().getMeasurement())) {
      throw new SemanticException(DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG);
    }

    long time = Long.parseLong(((BasicFunctionFilter) queryFilter).getValue());
    switch (queryFilter.getFilterType()) {
      case LESSTHAN:
        return new Pair<>(Long.MIN_VALUE, time - 1);
      case LESSTHANOREQUALTO:
        return new Pair<>(Long.MIN_VALUE, time);
      case GREATERTHAN:
        return new Pair<>(time + 1, Long.MAX_VALUE);
      case GREATERTHANOREQUALTO:
        return new Pair<>(time, Long.MAX_VALUE);
      case EQUAL:
        return new Pair<>(time, time);
      default:
        throw new SemanticException(DELETE_RANGE_ERROR_MSG);
    }
  }

  // Merge
  @Override
  public Statement visitMerge(IoTDBSqlParser.MergeContext ctx) {
    MergeStatement mergeStatement = new MergeStatement(StatementType.MERGE);
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException("MERGE ON CLUSTER is not supported in standalone mode");
    }
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
    return mergeStatement;
  }

  @Override
  public Statement visitFullMerge(IoTDBSqlParser.FullMergeContext ctx) {
    MergeStatement mergeStatement = new MergeStatement(StatementType.FULL_MERGE);
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException("FULL MERGE ON CLUSTER is not supported in standalone mode");
    }
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
    return mergeStatement;
  }

  // Flush

  @Override
  public Statement visitFlush(IoTDBSqlParser.FlushContext ctx) {
    FlushStatement flushStatement = new FlushStatement(StatementType.FLUSH);
    List<PartialPath> storageGroups = null;
    if (ctx.BOOLEAN_LITERAL() != null) {
      flushStatement.setSeq(Boolean.parseBoolean(ctx.BOOLEAN_LITERAL().getText()));
    }
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException("FLUSH ON CLUSTER is not supported in standalone mode");
    }
    flushStatement.setOnCluster(ctx.LOCAL() == null);
    if (ctx.prefixPath(0) != null) {
      storageGroups = new ArrayList<>();
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
        storageGroups.add(parsePrefixPath(prefixPathContext));
      }
    }
    flushStatement.setStorageGroups(storageGroups);
    return flushStatement;
  }

  // Clear Cache

  @Override
  public Statement visitClearCache(IoTDBSqlParser.ClearCacheContext ctx) {
    ClearCacheStatement clearCacheStatement = new ClearCacheStatement(StatementType.CLEAR_CACHE);
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException("CLEAR CACHE ON CLUSTER is not supported in standalone mode");
    }
    clearCacheStatement.setOnCluster(ctx.LOCAL() == null);
    return clearCacheStatement;
  }

  // Load Configuration

  @Override
  public Statement visitLoadConfiguration(IoTDBSqlParser.LoadConfigurationContext ctx) {
    LoadConfigurationStatement loadConfigurationStatement =
        new LoadConfigurationStatement(StatementType.LOAD_CONFIGURATION);
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException(
          "LOAD CONFIGURATION ON CLUSTER is not supported in standalone mode");
    }
    loadConfigurationStatement.setOnCluster(ctx.LOCAL() == null);
    return loadConfigurationStatement;
  }

  // Set System Status

  @Override
  public Statement visitSetSystemStatus(IoTDBSqlParser.SetSystemStatusContext ctx) {
    SetSystemStatusStatement setSystemStatusStatement = new SetSystemStatusStatement();
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
      throw new SemanticException(
          "SET SYSTEM STATUS ON CLUSTER is not supported in standalone mode");
    }
    setSystemStatusStatement.setOnCluster(ctx.LOCAL() == null);
    if (ctx.RUNNING() != null) {
      setSystemStatusStatement.setStatus(NodeStatus.Running);
    } else if (ctx.READONLY() != null) {
      setSystemStatusStatement.setStatus(NodeStatus.ReadOnly);
    } else {
      throw new RuntimeException("Unknown system status in set system command.");
    }
    return setSystemStatusStatement;
  }

  // show region

  @Override
  public Statement visitShowRegion(IoTDBSqlParser.ShowRegionContext ctx) {
    ShowRegionStatement showRegionStatement = new ShowRegionStatement();
    // TODO: Maybe add a show partition region in the future
    if (ctx.DATA() != null) {
      showRegionStatement.setRegionType(TConsensusGroupType.DataRegion);
    } else if (ctx.SCHEMA() != null) {
      showRegionStatement.setRegionType(TConsensusGroupType.SchemaRegion);
    } else {
      showRegionStatement.setRegionType(null);
    }

    if (ctx.OF() != null) {
      List<PartialPath> storageGroups = null;
      if (ctx.prefixPath(0) != null) {
        storageGroups = new ArrayList<>();
        for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
          storageGroups.add(parsePrefixPath(prefixPathContext));
        }
      }
      showRegionStatement.setStorageGroups(storageGroups);
    } else {
      showRegionStatement.setStorageGroups(null);
    }
    return showRegionStatement;
  }

  // show datanodes

  @Override
  public Statement visitShowDataNodes(IoTDBSqlParser.ShowDataNodesContext ctx) {
    return new ShowDataNodesStatement();
  }

  // show confignodes

  @Override
  public Statement visitShowConfigNodes(IoTDBSqlParser.ShowConfigNodesContext ctx) {
    return new ShowConfigNodesStatement();
  }

  // schema template

  @Override
  public Statement visitCreateSchemaTemplate(IoTDBSqlParser.CreateSchemaTemplateContext ctx) {
    String name = parseIdentifier(parseIdentifier(ctx.templateName.getText()));
    List<List<String>> measurementsList = new ArrayList<List<String>>();
    List<List<TSDataType>> dataTypesList = new ArrayList<List<TSDataType>>();
    List<List<TSEncoding>> encodingsList = new ArrayList<List<TSEncoding>>();
    List<List<CompressionType>> compressorsList = new ArrayList<List<CompressionType>>();

    if (ctx.ALIGNED() != null) {
      // aligned
      List<String> measurements = new ArrayList<>();
      List<TSDataType> dataTypes = new ArrayList<>();
      List<TSEncoding> encodings = new ArrayList<>();
      List<CompressionType> compressors = new ArrayList<>();
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
          ctx.templateMeasurementClause()) {
        measurements.add(
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
        parseAttributeClause(
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
      }
      measurementsList.add(measurements);
      dataTypesList.add(dataTypes);
      encodingsList.add(encodings);
      compressorsList.add(compressors);
    } else {
      // non-aligned
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
          ctx.templateMeasurementClause()) {
        List<String> measurements = new ArrayList<>();
        List<TSDataType> dataTypes = new ArrayList<>();
        List<TSEncoding> encodings = new ArrayList<>();
        List<CompressionType> compressors = new ArrayList<>();
        measurements.add(
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
        parseAttributeClause(
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
        measurementsList.add(measurements);
        dataTypesList.add(dataTypes);
        encodingsList.add(encodings);
        compressorsList.add(compressors);
      }
    }

    return new CreateSchemaTemplateStatement(
        name, measurementsList, dataTypesList, encodingsList, compressorsList);
  }

  void parseAttributeClause(
      IoTDBSqlParser.AttributeClausesContext ctx,
      List<TSDataType> dataTypes,
      List<TSEncoding> encodings,
      List<CompressionType> compressors) {
    if (ctx.aliasNodeName() != null) {
      throw new SQLParserException("schema template: alias is not supported yet.");
    }

    TSDataType dataType = null;
    if (ctx.dataType != null) {
      if (ctx.attributeKey() != null) {
        if (!parseAttributeKey(ctx.attributeKey())
            .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
          throw new SQLParserException("expecting datatype");
        }
      }
      String dataTypeString = ctx.dataType.getText().toUpperCase();
      try {
        dataType = TSDataType.valueOf(dataTypeString);
        dataTypes.add(dataType);
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported datatype: %s", dataTypeString));
      }
    }

    Map<String, String> props = new HashMap<>();
    if (ctx.attributePair() != null) {
      for (int i = 0; i < ctx.attributePair().size(); i++) {
        props.put(
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
      }
    }

    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
      String encodingString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
      try {
        encoding = TSEncoding.valueOf(encodingString);
        encodings.add(encoding);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported encoding: %s", encodingString));
      }
    } else {
      encodings.add(encoding);
    }

    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
      String compressorString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
      try {
        compressor = CompressionType.valueOf(compressorString);
        compressors.add(compressor);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(String.format("unsupported compressor: %s", compressorString));
      }
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
      String compressionString =
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
      try {
        compressor = CompressionType.valueOf(compressionString);
        compressors.add(compressor);
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
      } catch (Exception e) {
        throw new SemanticException(
            String.format("unsupported compression: %s", compressionString));
      }
    } else {
      compressors.add(compressor);
    }

    if (props.size() > 0) {
      throw new SQLParserException("schema template: property is not supported yet.");
    }

    if (ctx.tagClause() != null) {
      throw new SQLParserException("schema template: tag is not supported yet.");
    }

    if (ctx.attributeClause() != null) {
      throw new SQLParserException("schema template: attribute is not supported yet.");
    }
  }

  @Override
  public Statement visitShowSchemaTemplates(IoTDBSqlParser.ShowSchemaTemplatesContext ctx) {
    return new ShowSchemaTemplateStatement();
  }

  @Override
  public Statement visitShowNodesInSchemaTemplate(
      IoTDBSqlParser.ShowNodesInSchemaTemplateContext ctx) {
    String templateName = parseIdentifier(ctx.templateName.getText());
    return new ShowNodesInSchemaTemplateStatement(templateName);
  }

  @Override
  public Statement visitSetSchemaTemplate(IoTDBSqlParser.SetSchemaTemplateContext ctx) {
    String templateName = parseIdentifier(ctx.templateName.getText());
    return new SetSchemaTemplateStatement(templateName, parsePrefixPath(ctx.prefixPath()));
  }

  @Override
  public Statement visitShowPathsSetSchemaTemplate(
      IoTDBSqlParser.ShowPathsSetSchemaTemplateContext ctx) {
    String templateName = parseIdentifier(ctx.templateName.getText());
    return new ShowPathSetTemplateStatement(templateName);
  }

  @Override
  public Statement visitCreateTimeseriesOfSchemaTemplate(
      IoTDBSqlParser.CreateTimeseriesOfSchemaTemplateContext ctx) {
    ActivateTemplateStatement statement = new ActivateTemplateStatement();
    statement.setPath(parsePrefixPath(ctx.prefixPath()));
    return statement;
  }

  @Override
  public Statement visitShowPathsUsingSchemaTemplate(
      IoTDBSqlParser.ShowPathsUsingSchemaTemplateContext ctx) {
    return new ShowPathsUsingTemplateStatement(parseIdentifier(ctx.templateName.getText()));
  }

  public Map<String, String> parseSyncAttributeClauses(
      IoTDBSqlParser.SyncAttributeClausesContext ctx) {

    Map<String, String> attributes = new HashMap<>();

    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
    if (ctx.attributePair(0) != null) {
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
        attributes.put(
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
      }
    }

    return attributes;
  }

  private PartialPath parsePathFromExpression(Expression expression) {
    if (expression instanceof TimeSeriesOperand) {
      return ((TimeSeriesOperand) expression).getPath();
    } else if (expression instanceof TimestampOperand) {
      return SQLConstant.TIME_PATH;
    } else {
      throw new IllegalArgumentException(
          "Unsupported expression type: " + expression.getExpressionType());
    }
  }

  private void parseSelectStatementForPipe(
      IoTDBSqlParser.SelectStatementContext ctx, CreatePipeStatement statement)
      throws SQLParserException {
    if (ctx.TRACING() != null || ctx.intoClause() != null || ctx.specialClause() != null) {
      throw new SQLParserException("Not support for this sql in pipe.");
    }

    // parse select
    IoTDBSqlParser.SelectClauseContext selectCtx = ctx.selectClause();
    if (selectCtx.LAST() != null || selectCtx.resultColumn().size() != 1) {
      throw new SQLParserException("Not support for this sql in pipe.");
    }
    IoTDBSqlParser.ResultColumnContext resultColumnCtx = selectCtx.resultColumn(0);
    if (resultColumnCtx.AS() != null
        || !IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD.equals(
            resultColumnCtx.expression().getText())) {
      throw new SQLParserException("Not support for this sql in pipe.");
    }

    // parse from
    IoTDBSqlParser.FromClauseContext fromCtx = ctx.fromClause();
    if (fromCtx.prefixPath().size() != 1
        || !IoTDBConstant.PATH_ROOT.equals(fromCtx.prefixPath(0).getText())) {
      throw new SQLParserException("Not support for this sql in pipe.");
    }

    // parse where
    IoTDBSqlParser.WhereClauseContext whereCtx = ctx.whereClause();
    if (whereCtx != null) {
      Expression predicate =
          parseExpression(whereCtx.expression(), whereCtx.expression().OPERATOR_NOT() == null);
      if (!((predicate instanceof GreaterThanExpression)
          || (predicate instanceof GreaterEqualExpression))) {
        throw new SQLParserException("Not support for this sql in pipe.");
      }
      Expression left = ((BinaryExpression) predicate).getLeftExpression();
      Expression right = ((BinaryExpression) predicate).getRightExpression();

      if (!SQLConstant.isReservedPath(parsePathFromExpression(left))) {
        throw new SQLParserException("Not support for this sql in pipe.");
      }
      if (!(right instanceof ConstantOperand)) {
        throw new SQLParserException("Not support for this sql in pipe.");
      }
      if (((ConstantOperand) right).getDataType() != TSDataType.INT64) {
        throw new SQLParserException("Not support for this sql in pipe.");
      }
      long startTime = Long.parseLong(((ConstantOperand) right).getValueString());
      statement.setStartTime(startTime);
    }
  }

  // PIPE

  @Override
  public Statement visitShowPipe(IoTDBSqlParser.ShowPipeContext ctx) {
    ShowPipeStatement showPipeStatement = new ShowPipeStatement();
    if (ctx.pipeName != null) {
      showPipeStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
    }
    return showPipeStatement;
  }

  @Override
  public Statement visitCreatePipe(IoTDBSqlParser.CreatePipeContext ctx) throws SQLParserException {

    CreatePipeStatement createPipeStatement = new CreatePipeStatement(StatementType.CREATE_PIPE);

    if (ctx.pipeName != null && ctx.pipeSinkName != null) {
      createPipeStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
      createPipeStatement.setPipeSinkName(parseIdentifier(ctx.pipeSinkName.getText()));
    } else {
      throw new SQLParserException(
          "Not support for this sql in CREATEPIPE, please enter pipename or pipesinkname.");
    }
    if (ctx.selectStatement() != null) {
      parseSelectStatementForPipe(ctx.selectStatement(), createPipeStatement);
    }
    if (ctx.syncAttributeClauses() != null) {
      createPipeStatement.setPipeAttributes(parseSyncAttributeClauses(ctx.syncAttributeClauses()));
    } else {
      createPipeStatement.setPipeAttributes(new HashMap<>());
    }
    return createPipeStatement;
  }

  @Override
  public Statement visitStartPipe(IoTDBSqlParser.StartPipeContext ctx) {
    StartPipeStatement startPipeStatement = new StartPipeStatement(StatementType.START_PIPE);

    if (ctx.pipeName != null) {
      startPipeStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
    } else {
      throw new SQLParserException("Not support for this sql in STARTPIPE, please enter pipename.");
    }
    return startPipeStatement;
  }

  @Override
  public Statement visitStopPipe(IoTDBSqlParser.StopPipeContext ctx) {
    StopPipeStatement stopPipeStatement = new StopPipeStatement(StatementType.STOP_PIPE);

    if (ctx.pipeName != null) {
      stopPipeStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
    } else {
      throw new SQLParserException("Not support for this sql in STOPPIPE, please enter pipename.");
    }
    return stopPipeStatement;
  }

  @Override
  public Statement visitDropPipe(IoTDBSqlParser.DropPipeContext ctx) {

    DropPipeStatement dropPipeStatement = new DropPipeStatement(StatementType.DROP_PIPE);

    if (ctx.pipeName != null) {
      dropPipeStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
    } else {
      throw new SQLParserException("Not support for this sql in DROPPIPE, please enter pipename.");
    }
    return dropPipeStatement;
  }

  // pipeSink

  @Override
  public Statement visitShowPipeSink(IoTDBSqlParser.ShowPipeSinkContext ctx) {
    ShowPipeSinkStatement showPipeSinkStatement = new ShowPipeSinkStatement();
    if (ctx.pipeSinkName != null) {
      showPipeSinkStatement.setPipeSinkName(parseIdentifier(ctx.pipeSinkName.getText()));
    }
    return showPipeSinkStatement;
  }

  @Override
  public Statement visitShowPipeSinkType(IoTDBSqlParser.ShowPipeSinkTypeContext ctx) {
    ShowPipeSinkTypeStatement showPipeSinkTypeStatement = new ShowPipeSinkTypeStatement();
    return showPipeSinkTypeStatement;
  }

  @Override
  public Statement visitCreatePipeSink(IoTDBSqlParser.CreatePipeSinkContext ctx) {

    CreatePipeSinkStatement createPipeSinkStatement =
        new CreatePipeSinkStatement(StatementType.CREATE_PIPESINK);

    if (ctx.pipeSinkName != null) {
      createPipeSinkStatement.setPipeSinkName(parseIdentifier(ctx.pipeSinkName.getText()));
    } else {
      throw new SQLParserException(
          "Not support for this sql in CREATEPIPESINK, please enter pipesinkname.");
    }
    if (ctx.pipeSinkType != null) {
      createPipeSinkStatement.setPipeSinkType(parseIdentifier(ctx.pipeSinkType.getText()));
    } else {
      throw new SQLParserException(
          "Not support for this sql in CREATEPIPESINK, please enter pipesinktype.");
    }
    if (ctx.syncAttributeClauses() != null) {
      createPipeSinkStatement.setAttributes(parseSyncAttributeClauses(ctx.syncAttributeClauses()));
    } else {
      createPipeSinkStatement.setAttributes(new HashMap<>());
    }

    return createPipeSinkStatement;
  }

  @Override
  public Statement visitDropPipeSink(IoTDBSqlParser.DropPipeSinkContext ctx) {

    DropPipeSinkStatement dropPipeSinkStatement =
        new DropPipeSinkStatement(StatementType.DROP_PIPESINK);

    if (ctx.pipeSinkName != null) {
      dropPipeSinkStatement.setPipeSinkName(parseIdentifier(ctx.pipeSinkName.getText()));
    } else {
      throw new SQLParserException(
          "Not support for this sql in DROPPIPESINK, please enter pipesinkname.");
    }
    return dropPipeSinkStatement;
  }
}
