content: /*
   * Copyright 1999-2017 Alibaba Group Holding Ltd.
   *
   * Licensed 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 com.alibaba.druid.sql.dialect.h2.parser;
  
  import com.alibaba.druid.DbType;
  import com.alibaba.druid.sql.ast.SQLName;
  import com.alibaba.druid.sql.ast.SQLStatement;
  import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
  import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;
  import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
  import com.alibaba.druid.sql.ast.statement.SQLInsertInto;
  import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
  import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;
  import com.alibaba.druid.sql.ast.statement.SQLSelect;
  import com.alibaba.druid.sql.parser.Lexer;
  import com.alibaba.druid.sql.parser.ParserException;
  import com.alibaba.druid.sql.parser.SQLParserFeature;
  import com.alibaba.druid.sql.parser.SQLStatementParser;
  import com.alibaba.druid.sql.parser.Token;
  
  import static com.alibaba.druid.sql.parser.Token.LPAREN;
  import static com.alibaba.druid.sql.parser.Token.RPAREN;
  
  public class H2StatementParser extends SQLStatementParser {
      public H2StatementParser(String sql) {
          super(new H2ExprParser(sql));
      }
  
      public H2StatementParser(String sql, SQLParserFeature... features) {
          super(new H2ExprParser(sql, features));
      }
  
      public H2StatementParser(Lexer lexer) {
          super(new H2ExprParser(lexer));
      }
  
      public H2SelectParser createSQLSelectParser() {
          return new H2SelectParser(this.exprParser, selectListCache);
      }
  
      public SQLStatement parseMerge() {
          accept(Token.MERGE);
          accept(Token.INTO);
  
          SQLReplaceStatement stmt = new SQLReplaceStatement();
          stmt.setDbType(DbType.h2);
  
          SQLName tableName = exprParser.name();
          stmt.setTableName(tableName);
  
          if (lexer.token() == Token.KEY) {
              lexer.nextToken();
              accept(Token.LPAREN);
              this.exprParser.exprList(stmt.getColumns(), stmt);
              accept(Token.RPAREN);
          }
  
          if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) {
              lexer.nextToken();
  
              parseValueClause(stmt.getValuesList(), null, 0, stmt);
          } else if (lexer.token() == Token.SELECT) {
              SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
              stmt.setQuery(queryExpr);
          } else if (lexer.token() == Token.LPAREN) {
              SQLSelect select = this.createSQLSelectParser().select();
              SQLQueryExpr queryExpr = new SQLQueryExpr(select);
              stmt.setQuery(queryExpr);
          }
  
          return stmt;
      }
  
      @Override
      protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) {
          super.parseInsert0(insertStatement, acceptSubQuery);
          parseSetStatement(insertStatement);
      }
  
      private void parseSetStatement(SQLInsertInto insertStatement) {
          if (lexer.token() == Token.SET) {
              lexer.nextToken();
              SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
              insertStatement.addValueCause(values);
  
              for (; ; ) {
                  SQLName name = this.exprParser.name();
                  insertStatement.addColumn(name);
                  if (lexer.token() == Token.EQ) {
                      lexer.nextToken();
                  } else {
                      accept(Token.COLONEQ);
                  }
                  values.addValue(this.exprParser.expr());
  
                  if (lexer.token() == Token.COMMA) {
                      lexer.nextToken();
                      continue;
                  }
                  break;
              }
          }
      }
  
      @Override
      protected void alterTableAddRestSpecific(SQLAlterTableStatement stmt) {
          if (lexer.token() == LPAREN) {
              lexer.nextToken();
              SQLAlterTableAddColumn item = parseAlterTableAddColumn();
              stmt.addItem(item);
              accept(RPAREN);
              return;
          }
          throw new ParserException("TODO " + lexer.info());
      }
  }
  