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.builder.impl;
  
  import com.alibaba.druid.DbType;
  import com.alibaba.druid.sql.SQLUtils;
  import com.alibaba.druid.sql.ast.SQLExpr;
  import com.alibaba.druid.sql.ast.SQLStatement;
  import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
  import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
  import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
  import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
  import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
  import com.alibaba.druid.sql.builder.SQLUpdateBuilder;
  import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
  import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
  import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement;
  import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
  
  import java.util.List;
  import java.util.Map;
  
  public class SQLUpdateBuilderImpl extends SQLBuilderImpl implements SQLUpdateBuilder {
      private SQLUpdateStatement stmt;
      private DbType dbType;
  
      public SQLUpdateBuilderImpl(DbType dbType) {
          this.dbType = dbType;
      }
  
      public SQLUpdateBuilderImpl(String sql, DbType dbType) {
          List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
  
          if (stmtList.isEmpty()) {
              throw new IllegalArgumentException("not support empty-statement :" + sql);
          }
  
          if (stmtList.size() > 1) {
              throw new IllegalArgumentException("not support multi-statement :" + sql);
          }
  
          SQLUpdateStatement stmt = (SQLUpdateStatement) stmtList.get(0);
          this.stmt = stmt;
          this.dbType = dbType;
      }
  
      public SQLUpdateBuilderImpl(SQLUpdateStatement stmt, DbType dbType) {
          this.stmt = stmt;
          this.dbType = dbType;
      }
  
      @Override
      public SQLUpdateBuilderImpl limit(int rowCount) {
          throw new UnsupportedOperationException();
      }
  
      @Override
      public SQLUpdateBuilderImpl limit(int rowCount, int offset) {
          throw new UnsupportedOperationException();
      }
  
      @Override
      public SQLUpdateBuilderImpl from(String table) {
          return from(table, null);
      }
  
      @Override
      public SQLUpdateBuilderImpl from(String table, String alias) {
          SQLUpdateStatement update = getSQLUpdateStatement();
          SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);
          update.setTableSource(from);
          return this;
      }
  
      @Override
      public SQLUpdateBuilderImpl where(String expr) {
          SQLUpdateStatement update = getSQLUpdateStatement();
  
          SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
          update.setWhere(exprObj);
  
          return this;
      }
  
      @Override
      public SQLUpdateBuilderImpl whereAnd(String expr) {
          SQLUpdateStatement update = getSQLUpdateStatement();
  
          SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
          SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, update.getWhere());
          update.setWhere(newCondition);
  
          return this;
      }
  
      @Override
      public SQLUpdateBuilderImpl whereOr(String expr) {
          SQLUpdateStatement update = getSQLUpdateStatement();
  
          SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
          SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, update.getWhere());
          update.setWhere(newCondition);
  
          return this;
      }
  
      public SQLUpdateBuilderImpl set(String... items) {
          SQLUpdateStatement update = getSQLUpdateStatement();
          for (String item : items) {
              SQLUpdateSetItem updateSetItem = SQLUtils.toUpdateSetItem(item, dbType);
              update.addItem(updateSetItem);
          }
  
          return this;
      }
  
      public SQLUpdateBuilderImpl setValue(Map<String, Object> values) {
          for (Map.Entry<String, Object> entry : values.entrySet()) {
              setValue(entry.getKey(), entry.getValue());
          }
  
          return this;
      }
  
      public SQLUpdateBuilderImpl setValue(String column, Object value) {
          SQLUpdateStatement update = getSQLUpdateStatement();
  
          SQLExpr columnExpr = SQLUtils.toSQLExpr(column, dbType);
          SQLExpr valueExpr = toSQLExpr(value, dbType);
  
          SQLUpdateSetItem item = new SQLUpdateSetItem();
          item.setColumn(columnExpr);
          item.setValue(valueExpr);
          update.addItem(item);
  
          return this;
      }
  
      public SQLUpdateStatement getSQLUpdateStatement() {
          if (stmt == null) {
              stmt = createSQLUpdateStatement();
          }
          return stmt;
      }
  
      public SQLUpdateStatement createSQLUpdateStatement() {
          switch (dbType) {
              case mysql:
              case mariadb:
              case tidb:
              case polardbx:
                  return new MySqlUpdateStatement();
              case oracle:
                  return new OracleUpdateStatement();
              case postgresql:
              case greenplum:
              case edb:
                  return new PGUpdateStatement();
              case sqlserver:
                  return new SQLServerUpdateStatement();
              default:
                  return new SQLUpdateStatement();
          }
      }
  
      public String toString() {
          return SQLUtils.toSQLString(stmt, dbType);
      }
  }
  