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

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 699159698e [enhancement](planner) support update from syntax (#17639)
699159698e is described below

commit 699159698efe13920a183cfbcc563649ea543cbb
Author: morrySnow <101034200+morrys...@users.noreply.github.com>
AuthorDate: Tue Mar 14 19:26:30 2023 +0800

    [enhancement](planner) support update from syntax (#17639)
    
    support update from syntax
    
    note: enable_concurrent_update is not supported now
    
    ```
    UPDATE <target_table>
      SET <col_name> = <value> [ , <col_name> = <value> , ... ]
      [ FROM <additional_tables> ]
      [ WHERE <condition> ]
    ```
    
    for example:
    t1
    ```
    +----+----+----+-----+------------+
    | id | c1 | c2 | c3  | c4         |
    +----+----+----+-----+------------+
    | 3  | 3  | 3  | 3.0 | 2000-01-03 |
    | 2  | 2  | 2  | 2.0 | 2000-01-02 |
    | 1  | 1  | 1  | 1.0 | 2000-01-01 |
    +----+----+----+-----+------------+
    ```
    
    t2
    ```
    +----+----+----+------+------------+
    | id | c1 | c2 | c3   | c4         |
    +----+----+----+------+------------+
    | 4  | 4  | 4  |  4.0 | 2000-01-04 |
    | 2  | 20 | 20 | 20.0 | 2000-01-20 |
    | 5  | 5  | 5  |  5.0 | 2000-01-05 |
    | 1  | 10 | 10 | 10.0 | 2000-01-10 |
    | 3  | 30 | 30 | 30.0 | 2000-01-30 |
    +----+----+----+------+------------+
    ```
    
    t3
    ```
    +----+
    | id |
    +----+
    | 1  |
    | 5  |
    | 4  |
    +----+
    ```
    
    do update
    ```sql
     update t1 set t1.c1 = t2.c1, t1.c3 = t2.c3 * 100 from t2 inner join t3 on 
t2.id = t3.id where t1.id = t2.id;
    ```
    
    the result
    ```
    +----+----+----+--------+------------+
    | id | c1 | c2 | c3     | c4         |
    +----+----+----+--------+------------+
    | 3  | 3  | 3  |    3.0 | 2000-01-03 |
    | 2  | 2  | 2  |    2.0 | 2000-01-02 |
    | 1  | 10 | 1  | 1000.0 | 2000-01-01 |
    +----+----+----+--------+------------+
    ```
---
 .../Manipulation/UPDATE.md                         | 125 +++++++++--
 .../Manipulation/UPDATE.md                         | 123 +++++++++--
 fe/fe-core/src/main/cup/sql_parser.cup             |  47 +++-
 .../java/org/apache/doris/analysis/UpdateStmt.java | 174 +++++++--------
 .../main/java/org/apache/doris/catalog/Env.java    |   7 -
 .../apache/doris/load/update/UpdateManager.java    |  89 --------
 .../apache/doris/load/update/UpdatePlanner.java    | 192 -----------------
 .../doris/load/update/UpdateStmtExecutor.java      | 238 ---------------------
 .../main/java/org/apache/doris/qe/DdlExecutor.java |   3 -
 .../java/org/apache/doris/qe/SessionVariable.java  |  13 ++
 .../java/org/apache/doris/qe/StmtExecutor.java     |  16 ++
 .../doris/load/update/UpdateManagerTest.java       |  66 ------
 .../doris/load/update/UpdateStmtExecutorTest.java  | 101 ---------
 .../java/org/apache/doris/planner/PlannerTest.java |   8 -
 .../apache/doris/planner/UpdatePlannerTest.java    | 185 ----------------
 regression-test/data/update/test_update_unique.out |   5 +
 .../suites/update/test_update_unique.groovy        |  64 ++++--
 17 files changed, 436 insertions(+), 1020 deletions(-)

diff --git 
a/docs/en/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
 
b/docs/en/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
index 5605f62d13..1ec248c653 100644
--- 
a/docs/en/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
+++ 
b/docs/en/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
@@ -32,33 +32,63 @@ UPDATE
 
 ### Description
 
-This statement is used to update the data (the update statement currently only 
supports the Unique Key model).
+This statement is used to update the data. The UPDATE statement currently only 
supports the UNIQUE KEY model.
+
+#### Syntax
 
 ```sql
-UPDATE table_name
+UPDATE target_table
     SET assignment_list
-    WHERE expression
+    WHERE condition
 
-value:
-    {expr | DEFAULT}
+assignment_list:
+    assignment [, assignment] ...
 
 assignment:
     col_name = value
 
-assignment_list:
-    assignment [, assignment] ...
-````
+value:
+    {expr | DEFAULT}
+```
+
+<version since="dev">
+
+UPDATE_FROM
+
+</version>
+
+```sql
+UPDATE target_table
+    SET assignment_list
+    [ FROM additional_tables]
+    WHERE condition
+```
 
- Parameters
+#### Required Parameters
 
-+ table_name: The target table of the data to be updated. Can be of the form 
'db_name.table_name'
++ target_table: The target table of the data to be updated. Can be of the form 
'db_name.table_name'
 + assignment_list: The target column to be updated, in the format 'col_name = 
value, col_name = value'
-+ where expression: the condition that is expected to be updated, an 
expression that returns true or false can be
++ where condition: the condition that is expected to be updated, an expression 
that returns true or false can be
 
- Note
+#### Optional Parameters
 
-The current UPDATE statement only supports row updates on the Unique model, 
and there may be data conflicts caused by concurrent updates.
-At present, Doris does not deal with such problems, and users need to avoid 
such problems from the business side.
+<version since="dev">
+
+UPDATE_FROM
+
+</version>
+
++ FROM additional_tables: Specifies one or more tables to use for selecting 
rows to update or for setting new values. Note that if you want use target 
table here, you should give it a alias explicitly.
+
+#### Note
+
+<version since="dev">
+
+UPDATE_FROM
+
+</version>
+
+The current UPDATE statement only supports row updates on the Unique model.
 
 ### Example
 
@@ -68,13 +98,76 @@ The `test` table is a unique model table, which contains 
four columns: k1, k2, v
 
 ```sql
 UPDATE test SET v1 = 1 WHERE k1=1 and k2=2;
-````
+```
 
 2. Increment the v1 column of the k1=1 column in the 'test' table by 1
 
 ```sql
 UPDATE test SET v1 = v1+1 WHERE k1=1;
-````
+```
+
+<version since="dev">
+
+UPDATE_FROM
+
+</version>
+
+3. use the result of `t2` join `t3` to update `t1`
+
+```sql
+-- create t1, t2, t3 tables
+CREATE TABLE t1
+  (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE)
+UNIQUE KEY (id)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1', "function_column.sequence_col" = "c4");
+
+CREATE TABLE t2
+  (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1');
+
+CREATE TABLE t3
+  (id INT)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1');
+
+-- insert data
+INSERT INTO t1 VALUES
+  (1, 1, '1', 1.0, '2000-01-01'),
+  (2, 2, '2', 2.0, '2000-01-02'),
+  (3, 3, '3', 3.0, '2000-01-03');
+
+INSERT INTO t2 VALUES
+  (1, 10, '10', 10.0, '2000-01-10'),
+  (2, 20, '20', 20.0, '2000-01-20'),
+  (3, 30, '30', 30.0, '2000-01-30'),
+  (4, 4, '4', 4.0, '2000-01-04'),
+  (5, 5, '5', 5.0, '2000-01-05');
+
+INSERT INTO t3 VALUES
+  (1),
+  (4),
+  (5);
+
+-- update t1
+UPDATE t1
+  SET t1.c1 = t2.c1, t1.c3 = t2.c3 * 100
+  FROM t2 INNER JOIN t3 ON t2.id = t3.id
+  WHERE t1.id = t2.id;
+```
+
+the expect result is only update the row where id = 1 in table t1
+
+```
++----+----+----+--------+------------+
+| id | c1 | c2 | c3     | c4         |
++----+----+----+--------+------------+
+| 1  | 10 | 1  | 1000.0 | 2000-01-01 |
+| 2  | 2  | 2  |    2.0 | 2000-01-02 |
+| 3  | 3  | 3  |    3.0 | 2000-01-03 |
++----+----+----+--------+------------+
+```
 
 ### Keywords
 
diff --git 
a/docs/zh-CN/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
 
b/docs/zh-CN/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
index 21160d424d..72164fba71 100644
--- 
a/docs/zh-CN/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
+++ 
b/docs/zh-CN/docs/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/UPDATE.md
@@ -32,33 +32,64 @@ UPDATE
 
 ### Description
 
-该语句是为进行对数据进行更新的操作,( update 语句目前仅支持  Unique Key 模型)。
+该语句是为进行对数据进行更新的操作,UPDATE 语句目前仅支持 UNIQUE KEY 模型。
+
+#### Syntax
 
 ```sql
-UPDATE table_name
+UPDATE target_table
     SET assignment_list
-    WHERE expression
+    WHERE condition
 
-value:
-    {expr | DEFAULT}
+assignment_list:
+    assignment [, assignment] ...
 
 assignment:
     col_name = value
 
-assignment_list:
-    assignment [, assignment] ...
+value:
+    {expr | DEFAULT}
 ```
 
- Parameters
+<version since="dev">
+
+UPDATE_FROM
 
-+ table_name: 待更新数据的目标表。可以是 'db_name.table_name' 形式
+</version>
+
+```sql
+UPDATE target_table
+    SET assignment_list
+    [ FROM additional_tables]
+    WHERE condition
+```
+
+
+#### Required Parameters
+
++ target_table: 待更新数据的目标表。可以是 'db_name.table_name' 形式
 + assignment_list: 待更新的目标列,形如 'col_name = value, col_name = value' 格式
-+ where expression: 期望更新的条件,一个返回 true 或者 false 的表达式即可
++ WHERE condition: 期望更新的条件,一个返回 true 或者 false 的表达式即可
+
+#### Optional Parameters
+
+<version since="dev">
 
- Note
+UPDATE_FROM
 
-当前 UPDATE 语句仅支持在 Unique 模型上的行更新,存在并发更新导致的数据冲突可能。
-目前 Doris 并不处理这类问题,需要用户从业务侧规避这类问题。
+</version>
+
++ FROM additional_tables: 
指定一个或多个表,用于选中更新的行,或者获取更新的值。注意,如需要在此列表中再次使用目标表,需要为其显式指定别名。
+
+#### Note
+
+<version since="dev">
+
+UPDATE_FROM
+
+</version>
+
+当前 UPDATE 语句仅支持在 Unique 模型上的行更新。
 
 ### Example
 
@@ -76,9 +107,69 @@ UPDATE test SET v1 = 1 WHERE k1=1 and k2=2;
 UPDATE test SET v1 = v1+1 WHERE k1=1;
 ```
 
-### Keywords
+<version since="dev">
 
-    UPDATE
+UPDATE_FROM
 
-### Best Practice
+</version>
 
+3. 使用`t2`和`t3`表连接的结果,更新`t1`
+
+```sql
+-- 创建t1, t2, t3三张表
+CREATE TABLE t1
+  (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE)
+UNIQUE KEY (id)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1', "function_column.sequence_col" = "c4");
+
+CREATE TABLE t2
+  (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1');
+
+CREATE TABLE t3
+  (id INT)
+DISTRIBUTED BY HASH (id)
+PROPERTIES('replication_num'='1');
+
+-- 插入数据
+INSERT INTO t1 VALUES
+  (1, 1, '1', 1.0, '2000-01-01', '2000-01-01'),
+  (2, 2, '2', 2.0, '2000-01-02', '2000-01-02'),
+  (3, 3, '3', 3.0, '2000-01-03', '2000-01-03');
+
+INSERT INTO t2 VALUES
+  (1, 10, '10', 10.0, '2000-01-10'),
+  (2, 20, '20', 20.0, '2000-01-20'),
+  (3, 30, '30', 30.0, '2000-01-30'),
+  (4, 4, '4', 4.0, '2000-01-04'),
+  (5, 5, '5', 5.0, '2000-01-05');
+
+INSERT INTO t3 VALUES
+  (1),
+  (4),
+  (5);
+
+-- 更新 t1
+UPDATE t1
+  SET t1.c1 = t2.c1, t1.c3 = t2.c3 * 100
+  FROM t2 INNER JOIN t3 ON t2.id = t3.id
+  WHERE t1.id = t2.id;
+```
+
+预期结果为,更新了`t1`表`id`为`1`的列
+
+```
++----+----+----+--------+------------+
+| id | c1 | c2 | c3     | c4         |
++----+----+----+--------+------------+
+| 1  | 10 | 1  | 1000.0 | 2000-01-01 |
+| 2  | 2  | 2  |    2.0 | 2000-01-02 |
+| 3  | 3  | 3  |    3.0 | 2000-01-03 |
++----+----+----+--------+------------+
+```
+
+### Keywords
+
+    UPDATE
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup 
b/fe/fe-core/src/main/cup/sql_parser.cup
index ca10463d88..fb05c5af66 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -685,6 +685,9 @@ nonterminal InsertStmt insert_stmt;
 nonterminal InsertTarget insert_target;
 nonterminal InsertSource insert_source;
 nonterminal UpdateStmt update_stmt;
+nonterminal List<BinaryPredicate> set_clause;
+nonterminal List<BinaryPredicate> assignment_list;
+nonterminal BinaryPredicate assignment;
 
 nonterminal BackupStmt backup_stmt;
 nonterminal AbstractBackupTableRefClause opt_backup_table_ref_list;
@@ -751,6 +754,7 @@ nonterminal FunctionCallExpr column_slice;
 nonterminal ArrayList<TableRef> table_ref_list, base_table_ref_list;
 nonterminal ArrayList<LateralViewRef> opt_lateral_view_ref_list, 
lateral_view_ref_list;
 nonterminal FromClause from_clause;
+nonterminal FromClause opt_from_clause;
 nonterminal TableRef table_ref;
 nonterminal TableRef base_table_ref;
 nonterminal LateralViewRef lateral_view_ref;
@@ -4445,9 +4449,48 @@ insert_source ::=
 
 // update stmt
 update_stmt ::=
-    KW_UPDATE table_name:tbl KW_SET expr_list:setExprs where_clause:whereClause
+    KW_UPDATE table_name:tbl set_clause:setClause opt_from_clause:fromClause 
where_clause:whereClause
     {:
-        RESULT = new UpdateStmt(tbl, setExprs, whereClause);
+        RESULT = new UpdateStmt(tbl, setClause, fromClause, whereClause);
+    :}
+    ;
+
+opt_from_clause ::=
+    /* empty */
+    {:
+        RESULT = null;
+    :}
+    | from_clause:fromClause
+    {:
+        RESULT = fromClause;
+    :}
+    ;
+
+set_clause ::=
+    KW_SET assignment_list:list
+    {:
+        RESULT = list;
+    :}
+    ;
+
+assignment_list ::=
+    assignment:a
+    {:
+      List<BinaryPredicate> list = new ArrayList<>();
+      list.add(a);
+      RESULT = list;
+    :}
+    | assignment_list:list COMMA assignment:a
+    {:
+      list.add(a);
+      RESULT = list;
+    :}
+    ;
+
+assignment ::=
+    column_ref:columnRef EQUAL expr:value
+    {:
+        RESULT = new BinaryPredicate(BinaryPredicate.Operator.EQ, columnRef, 
value);
     :}
     ;
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/UpdateStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/UpdateStmt.java
index 979fd06730..7251a7e76d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/UpdateStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/UpdateStmt.java
@@ -17,12 +17,12 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.KeysType;
 import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.catalog.Table;
-import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
@@ -30,88 +30,116 @@ import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
-import org.apache.doris.rewrite.ExprRewriter;
+import org.apache.doris.qe.SessionVariable;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
 /**
- * UPDATE is a DML statement that modifies rows in a table.
+ * UPDATE is a DML statement that modifies rows in a unique key olap table.
  * The current update syntax only supports updating the filtered data of a 
single table.
- *
+ * <p>
  * UPDATE table_reference
  *     SET assignment_list
+ *     [from_clause]
  *     [WHERE where_condition]
- *
- * value:
- *     {expr}
- *
- * assignment:
- *     col_name = value
- *
+ * <p>
  * assignment_list:
  *     assignment [, assignment] ...
+ * <p>
+ * assignment:
+ *     col_name = value
+ * <p>
+ * value:
+ *     {expr}
  */
 public class UpdateStmt extends DdlStmt {
 
-    private TableName tableName;
-    private List<Expr> setExprs;
-    private Expr whereExpr;
-
-    // After analyzed
+    private final TableName tableName;
+    private final List<BinaryPredicate> setExprs;
+    private final Expr whereExpr;
+    private final FromClause fromClause;
+    private InsertStmt insertStmt;
     private Table targetTable;
-    private TupleDescriptor srcTupleDesc;
+    List<SelectListItem> selectListItems = Lists.newArrayList();
+    List<String> cols = Lists.newArrayList();
 
-    public UpdateStmt(TableName tableName, List<Expr> setExprs, Expr 
whereExpr) {
+    public UpdateStmt(TableName tableName, List<BinaryPredicate> setExprs, 
FromClause fromClause, Expr whereExpr) {
         this.tableName = tableName;
         this.setExprs = setExprs;
+        this.fromClause = fromClause;
         this.whereExpr = whereExpr;
-    }
-
-    public TableName getTableName() {
-        return tableName;
-    }
-
-    public List<Expr> getSetExprs() {
-        return setExprs;
-    }
-
-    public Expr getWhereExpr() {
-        return whereExpr;
-    }
 
-    public Table getTargetTable() {
-        return targetTable;
     }
 
-    public TupleDescriptor getSrcTupleDesc() {
-        return srcTupleDesc;
+    public InsertStmt getInsertStmt() {
+        return insertStmt;
     }
 
     @Override
     public void analyze(Analyzer analyzer) throws UserException {
         super.analyze(analyzer);
+        if (ConnectContext.get() != null && 
ConnectContext.get().getSessionVariable().isInDebugMode()) {
+            throw new AnalysisException("Update is forbidden since current 
session is in debug mode."
+                    + " Please check the following session variables: "
+                    + String.join(", ", SessionVariable.DEBUG_VARIABLES));
+        }
         analyzeTargetTable(analyzer);
         analyzeSetExprs(analyzer);
-        analyzeWhereExpr(analyzer);
+        constructInsertStmt();
+    }
+
+    private void constructInsertStmt() {
+        // not use origin from clause, because we need to mod it, and this 
action will affect toSql().
+        FromClause fromUsedInInsert;
+        TableRef tableRef = new TableRef(tableName, null);
+        if (fromClause == null) {
+            fromUsedInInsert = new FromClause(Lists.newArrayList(tableRef));
+        } else {
+            fromUsedInInsert = fromClause.clone();
+            fromUsedInInsert.getTableRefs().add(0, tableRef);
+        }
+        SelectStmt selectStmt = new SelectStmt(
+                // select list
+                new SelectList(selectListItems, false),
+                // from clause
+                fromUsedInInsert,
+                // where expr
+                whereExpr,
+                // group by
+                null,
+                // having
+                null,
+                // order by
+                null,
+                // limit
+                LimitElement.NO_LIMIT
+        );
+
+        insertStmt = new InsertStmt(
+                new InsertTarget(tableName, null),
+                null,
+                cols,
+                new InsertSource(selectStmt),
+                null);
     }
 
     private void analyzeTargetTable(Analyzer analyzer) throws 
AnalysisException {
-        // step1: analyze table name
+        // step1: analyze table name and origin table alias
         tableName.analyze(analyzer);
         // disallow external catalog
         Util.prohibitExternalCatalog(tableName.getCtl(), 
this.getClass().getSimpleName());
-
-        // check priv
+        // check load privilege, select privilege will check when analyze 
insert stmt
         if (!Env.getCurrentEnv().getAccessManager()
                 .checkTblPriv(ConnectContext.get(), tableName.getDb(), 
tableName.getTbl(), PrivPredicate.LOAD)) {
             
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, 
"LOAD");
         }
 
-        // step2: resolve table name with catalog, only unique olap table 
could be update
+        // step2: resolve table name with catalog, only unique olap table 
could be updated
         String dbName = tableName.getDb();
         String targetTableName = tableName.getTbl();
         Preconditions.checkNotNull(dbName);
@@ -120,12 +148,12 @@ public class UpdateStmt extends DdlStmt {
         targetTable = database.getTableOrAnalysisException(tableName.getTbl());
         if (targetTable.getType() != Table.TableType.OLAP
                 || ((OlapTable) targetTable).getKeysType() != 
KeysType.UNIQUE_KEYS) {
-            throw new AnalysisException("Only unique olap table could be 
updated.");
+            throw new AnalysisException("Only unique table could be updated.");
         }
-        // step3: register tuple desc
+        // register table to ensure we could analyze column name on the left 
side of set exprs.
         targetTable.readLock();
         try {
-            srcTupleDesc = analyzer.registerOlapTable(targetTable, tableName, 
null);
+            analyzer.registerOlapTable(targetTable, tableName, null);
         } finally {
             targetTable.readUnlock();
         }
@@ -134,14 +162,9 @@ public class UpdateStmt extends DdlStmt {
     private void analyzeSetExprs(Analyzer analyzer) throws AnalysisException {
         // step1: analyze set exprs
         Set<String> columnMappingNames = new 
TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-        // the column expr only support binary predicate which's child(0) must 
be a SloRef.
+        // the column expr only support binary predicate which child(0) must 
be a SloRef.
         // the duplicate column name of SloRef is forbidden.
-        for (Expr setExpr : setExprs) {
-            if (!(setExpr instanceof BinaryPredicate)) {
-                throw new AnalysisException("Set function expr only support eq 
binary predicate. "
-                        + "Expr: " + setExpr.toSql());
-            }
-            BinaryPredicate predicate = (BinaryPredicate) setExpr;
+        for (BinaryPredicate predicate : setExprs) {
             if (predicate.getOp() != BinaryPredicate.Operator.EQ) {
                 throw new AnalysisException("Set function expr only support eq 
binary predicate. "
                         + "The predicate operator error, op: " + 
predicate.getOp());
@@ -149,7 +172,7 @@ public class UpdateStmt extends DdlStmt {
             Expr lhs = predicate.getChild(0);
             if (!(lhs instanceof SlotRef)) {
                 throw new AnalysisException("Set function expr only support eq 
binary predicate "
-                        + "which's child(0) must be a column name. "
+                        + "which child(0) must be a column name. "
                         + "The child(0) expr error. expr: " + lhs.toSql());
             }
             String column = ((SlotRef) lhs).getColumnName();
@@ -159,8 +182,7 @@ public class UpdateStmt extends DdlStmt {
         }
         // step2: resolve target columns with catalog,
         //        only value columns which belong to target table could be 
updated.
-        for (Expr setExpr : setExprs) {
-            Preconditions.checkState(setExpr instanceof BinaryPredicate);
+        for (BinaryPredicate setExpr : setExprs) {
             // check target column
             // 1. columns must belong to target table
             // 2. only value columns could be updated
@@ -170,41 +192,22 @@ public class UpdateStmt extends DdlStmt {
             }
             lhs.analyze(analyzer);
             if (((SlotRef) lhs).getColumn().isKey()) {
-                throw new AnalysisException("Only value columns of unique 
table could be updated.");
+                throw new AnalysisException("Only value columns of unique 
table could be updated");
             }
-            // check set expr of target column
-            Expr rhs = setExpr.getChild(1);
-            checkLargeIntOverflow(rhs);
-            rhs.analyze(analyzer);
-            if (lhs.getType() != rhs.getType()) {
-                setExpr.setChild(1, rhs.checkTypeCompatibility(lhs.getType()));
-            }
-        }
-    }
-
-    /*
-   The overflow detection of LargeInt needs to be verified again here.
-   The reason is: the first overflow detection(in constructor) cannot filter 
2^127.
-   Therefore, a second verification is required here.
-    */
-    private void checkLargeIntOverflow(Expr expr) throws AnalysisException {
-        if (expr instanceof LargeIntLiteral) {
-            expr.analyzeImpl(analyzer);
         }
-    }
 
-    private void analyzeWhereExpr(Analyzer analyzer) throws AnalysisException {
-        if (whereExpr == null) {
-            throw new AnalysisException("Where clause is required");
-        }
-        whereExpr.analyze(analyzer);
-        whereExpr = analyzer.getExprRewriter().rewrite(whereExpr, analyzer, 
ExprRewriter.ClauseType.WHERE_CLAUSE);
-        whereExpr.reset();
-        whereExpr.analyze(analyzer);
-        if (!whereExpr.getType().equals(Type.BOOLEAN)) {
-            throw new AnalysisException("Where clause is not a valid statement 
return bool");
+        // step3: generate select list and insert column name list in insert 
stmt
+        for (Column column : targetTable.getColumns()) {
+            Expr expr = new SlotRef(tableName, column.getName());
+            for (BinaryPredicate setExpr : setExprs) {
+                Expr lhs = setExpr.getChild(0);
+                if (((SlotRef) lhs).getColumn().equals(column)) {
+                    expr = setExpr.getChild(1);
+                }
+            }
+            selectListItems.add(new SelectListItem(expr, null));
+            cols.add(column.getName());
         }
-        analyzer.registerConjunct(whereExpr, srcTupleDesc.getId());
     }
 
     @Override
@@ -215,6 +218,9 @@ public class UpdateStmt extends DdlStmt {
         for (Expr setExpr : setExprs) {
             sb.append(setExpr.toSql()).append(", ");
         }
+        if (fromClause != null) {
+            sb.append("\n").append(fromClause.toSql());
+        }
         sb.append("\n");
         if (whereExpr != null) {
             sb.append("  ").append("WHERE ").append(whereExpr.toSql());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index 43b5a26d52..5190f8106d 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -162,7 +162,6 @@ import 
org.apache.doris.load.routineload.RoutineLoadScheduler;
 import org.apache.doris.load.routineload.RoutineLoadTaskScheduler;
 import org.apache.doris.load.sync.SyncChecker;
 import org.apache.doris.load.sync.SyncJobManager;
-import org.apache.doris.load.update.UpdateManager;
 import org.apache.doris.master.Checkpoint;
 import org.apache.doris.master.MetaHelper;
 import org.apache.doris.master.PartitionInMemoryInfoCollector;
@@ -318,7 +317,6 @@ public class Env {
     private ConsistencyChecker consistencyChecker;
     private BackupHandler backupHandler;
     private PublishVersionDaemon publishVersionDaemon;
-    private UpdateManager updateManager;
     private DeleteHandler deleteHandler;
     private DbUsedDataQuotaInfoCollector dbUsedDataQuotaInfoCollector;
     private PartitionInMemoryInfoCollector partitionInMemoryInfoCollector;
@@ -554,7 +552,6 @@ public class Env {
         this.backupHandler = new BackupHandler(this);
         this.metaDir = Config.meta_dir;
         this.publishVersionDaemon = new PublishVersionDaemon();
-        this.updateManager = new UpdateManager();
         this.deleteHandler = new DeleteHandler();
         this.dbUsedDataQuotaInfoCollector = new DbUsedDataQuotaInfoCollector();
         this.partitionInMemoryInfoCollector = new 
PartitionInMemoryInfoCollector();
@@ -3478,10 +3475,6 @@ public class Env {
         return this.backupHandler;
     }
 
-    public UpdateManager getUpdateManager() {
-        return updateManager;
-    }
-
     public DeleteHandler getDeleteHandler() {
         return this.deleteHandler;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateManager.java 
b/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateManager.java
deleted file mode 100644
index 697709fd4c..0000000000
--- a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateManager.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.load.update;
-
-import org.apache.doris.analysis.UpdateStmt;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.Config;
-import org.apache.doris.common.DdlException;
-import org.apache.doris.common.UserException;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-public class UpdateManager {
-    private final boolean enableConcurrentUpdate = 
Config.enable_concurrent_update;
-    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
-    private Map<Long, List<UpdateStmtExecutor>> tableIdToCurrentUpdate = 
Maps.newConcurrentMap();
-
-    private void writeLock() {
-        rwLock.writeLock().lock();
-    }
-
-    private void writeUnlock() {
-        rwLock.writeLock().unlock();
-    }
-
-    public void handleUpdate(UpdateStmt updateStmt) throws UserException {
-        UpdateStmtExecutor updateStmtExecutor = addUpdateExecutor(updateStmt);
-        try {
-            updateStmtExecutor.execute();
-        } finally {
-            removeUpdateExecutor(updateStmtExecutor);
-        }
-    }
-
-    private UpdateStmtExecutor addUpdateExecutor(UpdateStmt updateStmt) throws 
AnalysisException, DdlException {
-        writeLock();
-        try {
-            List<UpdateStmtExecutor> currentUpdateList
-                    = 
tableIdToCurrentUpdate.get(updateStmt.getTargetTable().getId());
-            if (!enableConcurrentUpdate && currentUpdateList != null && 
currentUpdateList.size() > 0) {
-                throw new DdlException("There is an update operation in 
progress for the current table. "
-                        + "Please try again later, or set 
enable_concurrent_update in fe.conf to true");
-            }
-            UpdateStmtExecutor updateStmtExecutor = 
UpdateStmtExecutor.fromUpdateStmt(updateStmt);
-            if (currentUpdateList == null) {
-                currentUpdateList = Lists.newArrayList();
-                
tableIdToCurrentUpdate.put(updateStmtExecutor.getTargetTableId(), 
currentUpdateList);
-            }
-            currentUpdateList.add(updateStmtExecutor);
-            return updateStmtExecutor;
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    private void removeUpdateExecutor(UpdateStmtExecutor updateStmtExecutor) {
-        writeLock();
-        try {
-            List<UpdateStmtExecutor> currentUpdateList
-                    = 
tableIdToCurrentUpdate.get(updateStmtExecutor.getTargetTableId());
-            if (currentUpdateList == null) {
-                return;
-            }
-            currentUpdateList.remove(updateStmtExecutor);
-        } finally {
-            writeUnlock();
-        }
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java 
b/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java
deleted file mode 100644
index d116477bcc..0000000000
--- a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java
+++ /dev/null
@@ -1,192 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.load.update;
-
-import org.apache.doris.alter.SchemaChangeHandler;
-import org.apache.doris.analysis.Analyzer;
-import org.apache.doris.analysis.BinaryPredicate;
-import org.apache.doris.analysis.DescriptorTable;
-import org.apache.doris.analysis.Expr;
-import org.apache.doris.analysis.NullLiteral;
-import org.apache.doris.analysis.SlotDescriptor;
-import org.apache.doris.analysis.SlotRef;
-import org.apache.doris.analysis.TupleDescriptor;
-import org.apache.doris.catalog.Column;
-import org.apache.doris.catalog.OlapTable;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.IdGenerator;
-import org.apache.doris.common.UserException;
-import org.apache.doris.common.util.VectorizedUtil;
-import org.apache.doris.planner.DataPartition;
-import org.apache.doris.planner.OlapScanNode;
-import org.apache.doris.planner.OlapTableSink;
-import org.apache.doris.planner.OriginalPlanner;
-import org.apache.doris.planner.PlanFragment;
-import org.apache.doris.planner.PlanFragmentId;
-import org.apache.doris.planner.PlanNodeId;
-import org.apache.doris.planner.ScanNode;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import java.util.List;
-import java.util.Map;
-
-
-public class UpdatePlanner extends OriginalPlanner {
-
-    private final IdGenerator<PlanNodeId> nodeIdGenerator = 
PlanNodeId.createGenerator();
-    private final IdGenerator<PlanFragmentId> fragmentIdGenerator =
-            PlanFragmentId.createGenerator();
-
-    private long targetDBId;
-    private OlapTable targetTable;
-    private List<Expr> setExprs;
-    private TupleDescriptor srcTupleDesc;
-    private Analyzer analyzer;
-
-    private List<ScanNode> scanNodeList = Lists.newArrayList();
-
-    public UpdatePlanner(long dbId, OlapTable targetTable, List<Expr> setExprs,
-                         TupleDescriptor srcTupleDesc, Analyzer analyzer) {
-        super(analyzer);
-        this.targetDBId = dbId;
-        this.targetTable = targetTable;
-        this.setExprs = setExprs;
-        this.srcTupleDesc = srcTupleDesc;
-        this.analyzer = analyzer;
-    }
-
-    @Override
-    public List<ScanNode> getScanNodes() {
-        return scanNodeList;
-    }
-
-    public void plan(long txnId) throws UserException {
-        // 1. gen scan node
-        OlapScanNode olapScanNode = new 
OlapScanNode(nodeIdGenerator.getNextId(), srcTupleDesc, "OlapScanNode");
-        /* BEGIN: Temporary code, this part of the code needs to be refactored 
*/
-        olapScanNode.closePreAggregation("This an update operation");
-        olapScanNode.useBaseIndexId();
-        /* END */
-        olapScanNode.init(analyzer);
-        olapScanNode.finalize(analyzer);
-        if (VectorizedUtil.isVectorized()) {
-            olapScanNode.convertToVectorized();
-        }
-        scanNodeList.add(olapScanNode);
-        // 2. gen olap table sink
-        OlapTableSink olapTableSink = new OlapTableSink(targetTable, 
computeTargetTupleDesc(), null, false);
-        olapTableSink.init(analyzer.getContext().queryId(), txnId, targetDBId,
-                analyzer.getContext().getSessionVariable().queryTimeoutS,
-                
analyzer.getContext().getSessionVariable().sendBatchParallelism, false);
-        olapTableSink.complete();
-        // 3. gen plan fragment
-        PlanFragment planFragment = new 
PlanFragment(fragmentIdGenerator.getNextId(), olapScanNode,
-                DataPartition.RANDOM);
-        planFragment.setSink(olapTableSink);
-        planFragment.setOutputExprs(computeOutputExprs());
-        planFragment.finalize(null);
-        fragments.add(planFragment);
-    }
-
-    private TupleDescriptor computeTargetTupleDesc() {
-        DescriptorTable descTable = analyzer.getDescTbl();
-        TupleDescriptor targetTupleDesc = descTable.createTupleDescriptor();
-        for (Column col : targetTable.getFullSchema()) {
-            SlotDescriptor slotDesc = 
descTable.addSlotDescriptor(targetTupleDesc);
-            slotDesc.setIsMaterialized(true);
-            slotDesc.setType(col.getType());
-            slotDesc.setColumn(col);
-            slotDesc.setIsNullable(col.isAllowNull());
-        }
-        targetTupleDesc.computeStatAndMemLayout();
-        return targetTupleDesc;
-    }
-
-    /**
-     * There are three Rules of output exprs:
-     * RuleA: columns that need to be updated,
-     * use the right child of a set expr
-     *     base column: (k1, v1)
-     *     update stmt: set v1=1
-     *     output expr: k1, 1(use 1 as output expr)
-     * RuleB: columns that do not need to be updated,
-     * just add the original value of column -> slot ref
-     *     base column: (k1, v1)
-     *     update stmt: set v1 = 1
-     *     output expr: k1(use k1 slot ref as output expr), 1
-     * RuleC: the output columns is being added by the schema change job,
-     * need to add default value expr in output expr
-     *     base column: (k1, v1)
-     *     schema change job: add v2 column
-     *     full column: (k1, v1, v2)
-     *     output expr: k1, v1, default_value(v2)
-     */
-    private List<Expr> computeOutputExprs() throws AnalysisException {
-        Map<String, Expr> columnNameToSetExpr = Maps.newHashMap();
-        for (Expr setExpr : setExprs) {
-            Preconditions.checkState(setExpr instanceof BinaryPredicate);
-            Preconditions.checkState(setExpr.getChild(0) instanceof SlotRef);
-            SlotRef slotRef = (SlotRef) setExpr.getChild(0);
-            // pay attention to case ignore of column name
-            columnNameToSetExpr.put(slotRef.getColumnName().toLowerCase(), 
setExpr.getChild(1));
-        }
-        Map<String, SlotDescriptor> columnNameToSrcSlotDesc = 
Maps.newHashMap();
-        for (SlotDescriptor srcSlotDesc : srcTupleDesc.getSlots()) {
-            // pay attention to case ignore of column name
-            
columnNameToSrcSlotDesc.put(srcSlotDesc.getColumn().getName().toLowerCase(), 
srcSlotDesc);
-        }
-
-        // compute output expr
-        List<Expr> outputExprs = Lists.newArrayList();
-        for (int i = 0; i < targetTable.getFullSchema().size(); i++) {
-            Column column = targetTable.getFullSchema().get(i);
-            // pay attention to case ignore of column name
-            String originColumnName = 
(column.getName().startsWith(SchemaChangeHandler.SHADOW_NAME_PREFIX)
-                    ? 
column.getName().substring(SchemaChangeHandler.SHADOW_NAME_PREFIX.length()) : 
column.getName())
-                    .toLowerCase();
-            Expr setExpr = columnNameToSetExpr.get(originColumnName);
-            SlotDescriptor srcSlotDesc = 
columnNameToSrcSlotDesc.get(originColumnName);
-            if (setExpr != null) {
-                // RuleA
-                outputExprs.add(setExpr);
-            } else if (srcSlotDesc != null) {
-                // RuleB
-                SlotRef slotRef = new SlotRef(srcSlotDesc);
-                outputExprs.add(slotRef);
-            } else {
-                // RuleC
-                Expr defaultExpr;
-                if (column.getDefaultValue() != null) {
-                    defaultExpr = column.getDefaultValueExpr();
-                } else {
-                    if (column.isAllowNull()) {
-                        defaultExpr = NullLiteral.create(column.getType());
-                    } else {
-                        throw new AnalysisException("column has no source 
field, column=" + column.getName());
-                    }
-                }
-                defaultExpr.analyze(analyzer);
-                outputExprs.add(defaultExpr);
-            }
-        }
-        return outputExprs;
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateStmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateStmtExecutor.java
deleted file mode 100644
index f7148f9b15..0000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdateStmtExecutor.java
+++ /dev/null
@@ -1,238 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.load.update;
-
-import org.apache.doris.analysis.Analyzer;
-import org.apache.doris.analysis.Expr;
-import org.apache.doris.analysis.UpdateStmt;
-import org.apache.doris.catalog.Database;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.catalog.OlapTable;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.DdlException;
-import org.apache.doris.common.DuplicatedRequestException;
-import org.apache.doris.common.ErrorCode;
-import org.apache.doris.common.ErrorReport;
-import org.apache.doris.common.LabelAlreadyUsedException;
-import org.apache.doris.common.MetaNotFoundException;
-import org.apache.doris.common.QuotaExceedException;
-import org.apache.doris.common.UserException;
-import org.apache.doris.common.util.DebugUtil;
-import org.apache.doris.common.util.TimeUtils;
-import org.apache.doris.common.util.VectorizedUtil;
-import org.apache.doris.qe.Coordinator;
-import org.apache.doris.qe.QeProcessorImpl;
-import org.apache.doris.service.FrontendOptions;
-import org.apache.doris.task.LoadEtlTask;
-import org.apache.doris.thrift.TQueryType;
-import org.apache.doris.thrift.TUniqueId;
-import org.apache.doris.transaction.BeginTransactionException;
-import org.apache.doris.transaction.GlobalTransactionMgr;
-import org.apache.doris.transaction.TabletCommitInfo;
-import org.apache.doris.transaction.TransactionState.LoadJobSourceType;
-import org.apache.doris.transaction.TransactionState.TxnCoordinator;
-import org.apache.doris.transaction.TransactionState.TxnSourceType;
-import org.apache.doris.transaction.TransactionStatus;
-
-import com.google.common.collect.Lists;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.util.List;
-
-public class UpdateStmtExecutor {
-    private static final Logger LOG = 
LogManager.getLogger(UpdateStmtExecutor.class);
-
-    private OlapTable targetTable;
-    private Expr whereExpr;
-    private List<Expr> setExprs;
-    private long dbId;
-    private TUniqueId queryId;
-    private int timeoutSecond;
-    private Analyzer analyzer;
-    private UpdatePlanner updatePlanner;
-
-    private String label;
-    private long txnId;
-    private Coordinator coordinator;
-    private long effectRows;
-
-
-    public long getTargetTableId() {
-        return targetTable.getId();
-    }
-
-    public void execute() throws UserException {
-        // 0. empty set
-        // A where clause with a constant equal to false will not execute the 
update directly
-        // Example: update xxx set v1=0 where 1=2
-        if (analyzer.hasEmptyResultSet()) {
-            QeProcessorImpl.INSTANCE.unregisterQuery(queryId);
-            analyzer.getContext().getState().setOk();
-            return;
-        }
-
-        // 1. begin txn
-        beginTxn();
-
-        // 2. plan
-        targetTable.readLock();
-        try {
-            updatePlanner.plan(txnId);
-        } catch (Throwable e) {
-            LOG.warn("failed to plan update stmt, query id:{}", 
DebugUtil.printId(queryId), e);
-            Env.getCurrentGlobalTransactionMgr().abortTransaction(dbId, txnId, 
e.getMessage());
-            QeProcessorImpl.INSTANCE.unregisterQuery(queryId);
-            throw new DdlException("failed to plan update stmt, query id: "
-                    + DebugUtil.printId(queryId) + ", err: " + e.getMessage());
-        } finally {
-            targetTable.readUnlock();
-        }
-
-        // 3. execute plan
-        try {
-            executePlan();
-        } catch (DdlException e) {
-            LOG.warn("failed to execute update stmt, query id:{}", 
DebugUtil.printId(queryId), e);
-            Env.getCurrentGlobalTransactionMgr().abortTransaction(dbId, txnId, 
e.getMessage());
-            throw e;
-        } catch (Throwable e) {
-            LOG.warn("failed to execute update stmt, query id:{}", 
DebugUtil.printId(queryId), e);
-            Env.getCurrentGlobalTransactionMgr().abortTransaction(dbId, txnId, 
e.getMessage());
-            throw new DdlException("failed to execute update stmt, query id: "
-                    + DebugUtil.printId(queryId) + ", err: " + e.getMessage());
-        } finally {
-            QeProcessorImpl.INSTANCE.unregisterQuery(queryId);
-        }
-
-        // 4. commit and publish
-        commitAndPublishTxn();
-    }
-
-    private void beginTxn() throws LabelAlreadyUsedException, 
AnalysisException, BeginTransactionException,
-            DuplicatedRequestException, QuotaExceedException, 
MetaNotFoundException {
-        LOG.info("begin transaction for update stmt, query id:{}", 
DebugUtil.printId(queryId));
-        label = "update_" + DebugUtil.printId(queryId);
-        txnId = Env.getCurrentGlobalTransactionMgr()
-                .beginTransaction(dbId, 
Lists.newArrayList(targetTable.getId()), label,
-                        new TxnCoordinator(TxnSourceType.FE, 
FrontendOptions.getLocalHostAddress()),
-                        LoadJobSourceType.INSERT_STREAMING, timeoutSecond);
-    }
-
-    // TODO(ML): Abstract the logic of executing the coordinater and retrying.
-    //           It makes stmt such as insert, load, update and export can be 
reused
-    private void executePlan() throws Exception {
-        LOG.info("begin execute update stmt, query id:{}", 
DebugUtil.printId(queryId));
-        coordinator = new Coordinator(Env.getCurrentEnv().getNextId(), 
queryId, analyzer.getDescTbl(),
-                updatePlanner.getFragments(), updatePlanner.getScanNodes(), 
TimeUtils.DEFAULT_TIME_ZONE, false);
-        coordinator.setQueryType(TQueryType.LOAD);
-        coordinator.setExecVecEngine(VectorizedUtil.isVectorized());
-        coordinator.setExecPipEngine(VectorizedUtil.isPipeline());
-        QeProcessorImpl.INSTANCE.registerQuery(queryId, coordinator);
-        analyzer.getContext().getExecutor().setCoord(coordinator);
-
-        // execute
-        coordinator.setTimeout(timeoutSecond);
-        coordinator.exec();
-        if (coordinator.join(timeoutSecond)) {
-            if (!coordinator.isDone()) {
-                coordinator.cancel();
-                ErrorReport.reportDdlException(ErrorCode.ERR_EXECUTE_TIMEOUT);
-            }
-            if (!coordinator.getExecStatus().ok()) {
-                String errMsg = "update failed: " + 
coordinator.getExecStatus().getErrorMsg();
-                LOG.warn(errMsg);
-                throw new DdlException(errMsg);
-            }
-            LOG.info("finish to execute update stmt, query id:{}", 
DebugUtil.printId(queryId));
-        } else {
-            String errMsg = "coordinator could not finished before update 
timeout: "
-                    + coordinator.getExecStatus().getErrorMsg();
-            LOG.warn(errMsg);
-            throw new DdlException(errMsg);
-        }
-
-        // counter
-        if (coordinator.getLoadCounters().get(LoadEtlTask.DPP_NORMAL_ALL) != 
null) {
-            effectRows = 
Long.valueOf(coordinator.getLoadCounters().get(LoadEtlTask.DPP_NORMAL_ALL));
-            if 
(Long.valueOf(coordinator.getLoadCounters().get(LoadEtlTask.DPP_ABNORMAL_ALL)) 
!= 0) {
-                throw new DdlException("update failed, some rows did not take 
effect");
-            }
-        }
-    }
-
-    private void commitAndPublishTxn() throws UserException {
-        GlobalTransactionMgr globalTransactionMgr = 
Env.getCurrentGlobalTransactionMgr();
-        TransactionStatus txnStatus;
-        boolean isPublished;
-        try {
-            LOG.info("commit and publish transaction for update stmt, query 
id: {}", DebugUtil.printId(queryId));
-            isPublished = globalTransactionMgr.commitAndPublishTransaction(
-                    Env.getCurrentInternalCatalog().getDbOrMetaException(dbId),
-                    Lists.newArrayList(targetTable), txnId, 
TabletCommitInfo.fromThrift(coordinator.getCommitInfos()),
-                    
analyzer.getContext().getSessionVariable().getInsertVisibleTimeoutMs());
-        } catch (Throwable e) {
-            // situation2.1: publish error, throw exception
-            String errMsg = "failed to commit and publish transaction for 
update stmt, query id:"
-                    + DebugUtil.printId(queryId);
-            LOG.warn(errMsg, e);
-            globalTransactionMgr.abortTransaction(dbId, txnId, e.getMessage());
-            throw new DdlException(errMsg, e);
-        }
-        String errMsg = null;
-        if (isPublished) {
-            // situation2.2: publish successful
-            txnStatus = TransactionStatus.VISIBLE;
-        } else {
-            // situation2.3: be published later
-            txnStatus = TransactionStatus.COMMITTED;
-            errMsg = "transaction will be published later, data will be 
visible later";
-            LOG.warn("transaction will be published later, query id: {}", 
DebugUtil.printId(queryId));
-        }
-
-        // set context
-        StringBuilder sb = new StringBuilder();
-        sb.append("{'label':'").append(label).append("', 
'status':'").append(txnStatus.name()).append("'");
-        sb.append(", 'txnId':'").append(txnId).append("'");
-        sb.append(", 
'queryId':'").append(DebugUtil.printId(queryId)).append("'");
-        if (errMsg != null) {
-            sb.append(", 'err':'").append(errMsg).append("'");
-        }
-        sb.append("}");
-        analyzer.getContext().getState().setOk(effectRows, 0, sb.toString());
-    }
-
-    public static UpdateStmtExecutor fromUpdateStmt(UpdateStmt updateStmt) 
throws AnalysisException {
-        UpdateStmtExecutor updateStmtExecutor = new UpdateStmtExecutor();
-        updateStmtExecutor.targetTable = (OlapTable) 
updateStmt.getTargetTable();
-        updateStmtExecutor.whereExpr = updateStmt.getWhereExpr();
-        updateStmtExecutor.setExprs = updateStmt.getSetExprs();
-        Database database = Env.getCurrentInternalCatalog()
-                .getDbOrAnalysisException(updateStmt.getTableName().getDb());
-        updateStmtExecutor.dbId = database.getId();
-        updateStmtExecutor.analyzer = updateStmt.getAnalyzer();
-        updateStmtExecutor.queryId = 
updateStmtExecutor.analyzer.getContext().queryId();
-        updateStmtExecutor.timeoutSecond = 
updateStmtExecutor.analyzer.getContext()
-                .getExecTimeout();
-        updateStmtExecutor.updatePlanner = new 
UpdatePlanner(updateStmtExecutor.dbId, updateStmtExecutor.targetTable,
-                updateStmt.getSetExprs(), updateStmt.getSrcTupleDesc(),
-                updateStmt.getAnalyzer());
-        return updateStmtExecutor;
-    }
-
-}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java
index 4d0e873643..e4df13fb05 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java
@@ -110,7 +110,6 @@ import org.apache.doris.analysis.StopSyncJobStmt;
 import org.apache.doris.analysis.SyncStmt;
 import org.apache.doris.analysis.TruncateTableStmt;
 import org.apache.doris.analysis.UninstallPluginStmt;
-import org.apache.doris.analysis.UpdateStmt;
 import org.apache.doris.catalog.EncryptKeyHelper;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.common.DdlException;
@@ -182,8 +181,6 @@ public class DdlExecutor {
             
env.getRoutineLoadManager().stopRoutineLoadJob((StopRoutineLoadStmt) ddlStmt);
         } else if (ddlStmt instanceof AlterRoutineLoadStmt) {
             
env.getRoutineLoadManager().alterRoutineLoadJob((AlterRoutineLoadStmt) ddlStmt);
-        } else if (ddlStmt instanceof UpdateStmt) {
-            env.getUpdateManager().handleUpdate((UpdateStmt) ddlStmt);
         } else if (ddlStmt instanceof DeleteStmt) {
             env.getDeleteHandler().process((DeleteStmt) ddlStmt);
         } else if (ddlStmt instanceof CreateUserStmt) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 8dfd08a05e..1b52bc4574 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -30,6 +30,7 @@ import org.apache.doris.thrift.TRuntimeFilterType;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import org.apache.logging.log4j.LogManager;
@@ -290,6 +291,14 @@ public class SessionVariable implements Serializable, 
Writable {
 
     public static final String DRY_RUN_QUERY = "dry_run_query";
 
+    public static final List<String> DEBUG_VARIABLES = ImmutableList.of(
+            SKIP_DELETE_PREDICATE,
+            SKIP_DELETE_BITMAP,
+            SKIP_DELETE_SIGN,
+            SKIP_STORAGE_ENGINE_MERGE,
+            SHOW_HIDDEN_COLUMNS
+    );
+
     // session origin value
     public Map<Field, String> sessionOriginValue = new HashMap<Field, 
String>();
     // check stmt is or not [select /*+ SET_VAR(...)*/ ...]
@@ -858,6 +867,10 @@ public class SessionVariable implements Serializable, 
Writable {
 
     private Set<Class<? extends Event>> parsedNereidsEventMode = 
EventSwitchParser.parse(Lists.newArrayList("all"));
 
+    public boolean isInDebugMode() {
+        return showHiddenColumns || skipDeleteBitmap || skipDeletePredicate || 
skipDeleteSign || skipStorageEngineMerge;
+    }
+
     public void setEnableNereidsTrace(boolean enableNereidsTrace) {
         this.enableNereidsTrace = enableNereidsTrace;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 97532558e9..c5e9f8caf2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -59,6 +59,7 @@ import org.apache.doris.analysis.TransactionRollbackStmt;
 import org.apache.doris.analysis.TransactionStmt;
 import org.apache.doris.analysis.UnlockTablesStmt;
 import org.apache.doris.analysis.UnsupportedStmt;
+import org.apache.doris.analysis.UpdateStmt;
 import org.apache.doris.analysis.UseStmt;
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Database;
@@ -605,6 +606,8 @@ public class StmtExecutor implements ProfileWriter {
                 }
             } else if (parsedStmt instanceof LoadStmt) {
                 handleLoadStmt();
+            } else if (parsedStmt instanceof UpdateStmt) {
+                handleUpdateStmt();
             } else if (parsedStmt instanceof DdlStmt) {
                 handleDdlStmt();
             } else if (parsedStmt instanceof ShowStmt) {
@@ -1925,6 +1928,19 @@ public class StmtExecutor implements ProfileWriter {
         }
     }
 
+    private void handleUpdateStmt() {
+        try {
+            UpdateStmt updateStmt = (UpdateStmt) parsedStmt;
+            parsedStmt = updateStmt.getInsertStmt();
+            execute();
+            if (MysqlStateType.ERR.equals(context.getState().getStateType())) {
+                LOG.warn("update data error, stmt={}", parsedStmt.toSql());
+            }
+        } catch (Exception e) {
+            LOG.warn("update data error, stmt={}", parsedStmt.toSql(), e);
+        }
+    }
+
     private void handleDdlStmt() {
         try {
             DdlExecutor.execute(context.getEnv(), (DdlStmt) parsedStmt);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateManagerTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateManagerTest.java
deleted file mode 100644
index 5d48093ad4..0000000000
--- 
a/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateManagerTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.load.update;
-
-import org.apache.doris.analysis.UpdateStmt;
-import org.apache.doris.common.Config;
-import org.apache.doris.common.DdlException;
-import org.apache.doris.common.jmockit.Deencapsulation;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import mockit.Expectations;
-import mockit.Injectable;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.Map;
-
-public class UpdateManagerTest {
-
-    @Test
-    public void testDisableConcurrentUpdate(@Injectable UpdateStmt updateStmt,
-                                            @Injectable UpdateStmtExecutor 
updateStmtExecutor) {
-        Config.enable_concurrent_update = false;
-        Map<Long, List<UpdateStmtExecutor>> tableIdToCurrentUpdate = 
Maps.newConcurrentMap();
-        List<UpdateStmtExecutor> currentUpdate = Lists.newArrayList();
-        currentUpdate.add(updateStmtExecutor);
-        tableIdToCurrentUpdate.put(new Long(1), currentUpdate);
-        UpdateManager updateManager = new UpdateManager();
-        Assert.assertFalse(Deencapsulation.getField(updateManager, 
"enableConcurrentUpdate"));
-        Deencapsulation.setField(updateManager, "tableIdToCurrentUpdate", 
tableIdToCurrentUpdate);
-        new Expectations() {
-            {
-                updateStmt.getTargetTable().getId();
-                result = 1;
-            }
-        };
-
-        try {
-            Deencapsulation.invoke(updateManager, "addUpdateExecutor", 
updateStmt);
-            Assert.fail();
-        } catch (Exception e) {
-            if (e instanceof DdlException) {
-                System.out.println(e.getMessage());
-            } else {
-                throw e;
-            }
-        }
-    }
-}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateStmtExecutorTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateStmtExecutorTest.java
deleted file mode 100644
index 2fe3b13e20..0000000000
--- 
a/fe/fe-core/src/test/java/org/apache/doris/load/update/UpdateStmtExecutorTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.load.update;
-
-import org.apache.doris.analysis.Analyzer;
-import org.apache.doris.analysis.BinaryPredicate;
-import org.apache.doris.analysis.Expr;
-import org.apache.doris.analysis.IntLiteral;
-import org.apache.doris.analysis.SlotRef;
-import org.apache.doris.analysis.TableName;
-import org.apache.doris.analysis.UpdateStmt;
-import org.apache.doris.catalog.Database;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.catalog.OlapTable;
-import org.apache.doris.cluster.Cluster;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.jmockit.Deencapsulation;
-import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.qe.Coordinator;
-import org.apache.doris.thrift.TUniqueId;
-import org.apache.doris.transaction.GlobalTransactionMgr;
-
-import com.google.common.collect.Lists;
-import mockit.Expectations;
-import mockit.Injectable;
-import mockit.Mocked;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class UpdateStmtExecutorTest {
-
-    @Test
-    public void testCommitAndPublishTxn(@Injectable Analyzer analyzer,
-                                        @Injectable Coordinator coordinator,
-                                        @Mocked GlobalTransactionMgr 
globalTransactionMgr) {
-        Cluster testCluster = new Cluster("test_cluster", 0);
-        Database testDb = new Database(1, "test_db");
-        testDb.setClusterName("test_cluster");
-        Env.getCurrentEnv().addCluster(testCluster);
-        Env.getCurrentEnv().unprotectCreateDb(testDb);
-        UpdateStmtExecutor updateStmtExecutor = new UpdateStmtExecutor();
-        Deencapsulation.setField(updateStmtExecutor, "dbId", 1);
-        Deencapsulation.setField(updateStmtExecutor, "effectRows", 0);
-        Deencapsulation.setField(updateStmtExecutor, "analyzer", analyzer);
-        Deencapsulation.setField(updateStmtExecutor, "coordinator", 
coordinator);
-        Deencapsulation.invoke(updateStmtExecutor, "commitAndPublishTxn");
-    }
-
-    @Test
-    public void testFromUpdateStmt(@Injectable OlapTable olapTable,
-                                   @Mocked Env env,
-                                   @Injectable Database db,
-                                   @Injectable Analyzer analyzer) throws 
AnalysisException {
-        TableName tableName = new 
TableName(InternalCatalog.INTERNAL_CATALOG_NAME, "db", "test");
-        List<Expr> setExprs = Lists.newArrayList();
-        SlotRef slotRef = new SlotRef(tableName, "v1");
-        IntLiteral intLiteral = new IntLiteral(1);
-        BinaryPredicate binaryPredicate = new 
BinaryPredicate(BinaryPredicate.Operator.EQ,
-                slotRef, intLiteral);
-        setExprs.add(binaryPredicate);
-        SlotRef keySlotRef = new SlotRef(tableName, "k1");
-        Expr whereExpr = new BinaryPredicate(BinaryPredicate.Operator.EQ, 
keySlotRef, intLiteral);
-        UpdateStmt updateStmt = new UpdateStmt(tableName, setExprs, whereExpr);
-        Deencapsulation.setField(updateStmt, "targetTable", olapTable);
-        Deencapsulation.setField(updateStmt, "analyzer", analyzer);
-        new Expectations() {
-            {
-                db.getId();
-                result = 1;
-                analyzer.getContext().queryId();
-                result = new TUniqueId(1, 2);
-                analyzer.getContext().getExecTimeout();
-                result = 1000;
-                olapTable.getId();
-                result = 2;
-            }
-        };
-        UpdateStmtExecutor executor = 
UpdateStmtExecutor.fromUpdateStmt(updateStmt);
-        Assert.assertEquals(new Long(2), new 
Long(executor.getTargetTableId()));
-        Assert.assertEquals(whereExpr, Deencapsulation.getField(executor, 
"whereExpr"));
-        Assert.assertEquals(setExprs, Deencapsulation.getField(executor, 
"setExprs"));
-        Assert.assertEquals(new Long(1), Deencapsulation.getField(executor, 
"dbId"));
-    }
-}
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
index 04302e1c62..730aab5674 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
@@ -494,16 +494,8 @@ public class PlannerTest extends TestWithFeService {
         Assertions.assertEquals(MysqlStateType.ERR, state.getStateType());
         Assertions.assertTrue(state.getErrorMessage()
                 .contains("you need (at least one of) the LOAD privilege(s) 
for this operation"));
-
         // set to admin user
         connectContext.setCurrentUserIdentity(UserIdentity.ADMIN);
-        stmtExecutor = new StmtExecutor(connectContext, qSQL);
-        stmtExecutor.execute();
-        state = connectContext.getState();
-        // still error because we can not do real update in unit test.
-        // just check if it pass the priv check.
-        Assertions.assertEquals(MysqlStateType.ERR, state.getStateType());
-        Assertions.assertTrue(state.getErrorMessage().contains("failed to 
execute update stmt"));
     }
 
     @Test
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/UpdatePlannerTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/UpdatePlannerTest.java
deleted file mode 100644
index 253ce82930..0000000000
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/UpdatePlannerTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.planner;
-
-import org.apache.doris.alter.SchemaChangeHandler;
-import org.apache.doris.analysis.Analyzer;
-import org.apache.doris.analysis.BinaryPredicate;
-import org.apache.doris.analysis.Expr;
-import org.apache.doris.analysis.IntLiteral;
-import org.apache.doris.analysis.SlotDescriptor;
-import org.apache.doris.analysis.SlotId;
-import org.apache.doris.analysis.SlotRef;
-import org.apache.doris.analysis.TableName;
-import org.apache.doris.analysis.TupleDescriptor;
-import org.apache.doris.analysis.TupleId;
-import org.apache.doris.catalog.Column;
-import org.apache.doris.catalog.OlapTable;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.IdGenerator;
-import org.apache.doris.common.jmockit.Deencapsulation;
-import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.load.update.UpdatePlanner;
-
-import com.google.common.collect.Lists;
-import mockit.Expectations;
-import mockit.Injectable;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class UpdatePlannerTest {
-
-    private final IdGenerator<TupleId> tupleIdGenerator = 
TupleId.createGenerator();
-    private final IdGenerator<SlotId> slotIdGenerator = 
SlotId.createGenerator();
-
-    /**
-     * Full columns: k1, k2 v1, shadow_column
-     * Shadow column: SHADOW_NAME_PRFIX + v1
-     * Set expr: v1=1
-     * Expect output exprs: k1, k2, 1, 1
-     */
-    @Test
-    public void testComputeOutputExprsWithShadowColumnAndSetExpr(@Injectable 
OlapTable targetTable,
-                                                                 @Injectable 
Column k1,
-                                                                 @Injectable 
Column k2,
-                                                                 @Injectable 
Column v1,
-                                                                 @Injectable 
Column shadowV1,
-                                                                 @Injectable 
Analyzer analyzer) {
-        List<Expr> setExprs = Lists.newArrayList();
-        TableName tableName = new 
TableName(InternalCatalog.INTERNAL_CATALOG_NAME, null, "test");
-        SlotRef slotRef = new SlotRef(tableName, "V1");
-        IntLiteral intLiteral = new IntLiteral(1);
-        BinaryPredicate binaryPredicate = new 
BinaryPredicate(BinaryPredicate.Operator.EQ,
-                slotRef, intLiteral);
-        setExprs.add(binaryPredicate);
-        TupleDescriptor srcTupleDesc = new 
TupleDescriptor(tupleIdGenerator.getNextId());
-        SlotDescriptor k1SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        k1SlotDesc.setColumn(k1);
-        srcTupleDesc.addSlot(k1SlotDesc);
-        SlotDescriptor k2SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        k2SlotDesc.setColumn(k2);
-        srcTupleDesc.addSlot(k2SlotDesc);
-        SlotDescriptor v1SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        v1SlotDesc.setColumn(v1);
-        srcTupleDesc.addSlot(v1SlotDesc);
-        List<Column> fullSchema = Lists.newArrayList();
-        fullSchema.add(k1);
-        fullSchema.add(k2);
-        fullSchema.add(v1);
-        fullSchema.add(shadowV1);
-
-        new Expectations() {
-            {
-                targetTable.getFullSchema();
-                result = fullSchema;
-                k1.getName();
-                result = "k1";
-                k2.getName();
-                result = "k2";
-                v1.getName();
-                result = "v1";
-                shadowV1.getName();
-                result = SchemaChangeHandler.SHADOW_NAME_PREFIX + "v1";
-            }
-        };
-
-        UpdatePlanner updatePlanner = new UpdatePlanner(1, targetTable, 
setExprs, srcTupleDesc, analyzer);
-        List<Expr> outputExpr = Deencapsulation.invoke(updatePlanner, 
"computeOutputExprs");
-        Assert.assertEquals(4, outputExpr.size());
-        Expr outputExpr1 = outputExpr.get(0);
-        Assert.assertTrue(outputExpr1 instanceof SlotRef);
-        Assert.assertEquals(((SlotRef) 
outputExpr1).getDesc().getColumn().getName(), "k1");
-        Expr outputExpr2 = outputExpr.get(1);
-        Assert.assertTrue(outputExpr2 instanceof SlotRef);
-        Assert.assertEquals(((SlotRef) 
outputExpr2).getDesc().getColumn().getName(), "k2");
-        Expr outputExpr3 = outputExpr.get(2);
-        Assert.assertTrue(outputExpr3 instanceof IntLiteral);
-        Assert.assertEquals(((IntLiteral) outputExpr3).getValue(), 1);
-        Expr outputExpr4 = outputExpr.get(3);
-        Assert.assertTrue(outputExpr4 instanceof IntLiteral);
-        Assert.assertEquals(((IntLiteral) outputExpr4).getValue(), 1);
-    }
-
-    @Test
-    public void testNewColumnBySchemaChange(@Injectable OlapTable targetTable,
-                                            @Injectable Column k1,
-                                            @Injectable Column k2,
-                                            @Injectable Column v1,
-                                            @Injectable Column newV2,
-                                            @Injectable Analyzer analyzer) 
throws AnalysisException {
-        List<Expr> setExprs = Lists.newArrayList();
-        TableName tableName = new 
TableName(InternalCatalog.INTERNAL_CATALOG_NAME, null, "test");
-        SlotRef slotRef = new SlotRef(tableName, "V1");
-        IntLiteral intLiteral = new IntLiteral(1);
-        BinaryPredicate binaryPredicate = new 
BinaryPredicate(BinaryPredicate.Operator.EQ,
-                slotRef, intLiteral);
-        setExprs.add(binaryPredicate);
-        TupleDescriptor srcTupleDesc = new 
TupleDescriptor(tupleIdGenerator.getNextId());
-        SlotDescriptor k1SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        k1SlotDesc.setColumn(k1);
-        srcTupleDesc.addSlot(k1SlotDesc);
-        SlotDescriptor k2SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        k2SlotDesc.setColumn(k2);
-        srcTupleDesc.addSlot(k2SlotDesc);
-        SlotDescriptor v1SlotDesc = new 
SlotDescriptor(slotIdGenerator.getNextId(), srcTupleDesc);
-        v1SlotDesc.setColumn(v1);
-        srcTupleDesc.addSlot(v1SlotDesc);
-        List<Column> fullSchema = Lists.newArrayList();
-        fullSchema.add(k1);
-        fullSchema.add(k2);
-        fullSchema.add(v1);
-        fullSchema.add(newV2);
-
-        new Expectations() {
-            {
-                targetTable.getFullSchema();
-                result = fullSchema;
-                k1.getName();
-                result = "k1";
-                k2.getName();
-                result = "k2";
-                v1.getName();
-                result = "v1";
-                newV2.getName();
-                result = "v2";
-                newV2.getDefaultValue();
-                result = "1";
-                newV2.getDefaultValueExpr();
-                result = new IntLiteral(1);
-            }
-        };
-
-        UpdatePlanner updatePlanner = new UpdatePlanner(1, targetTable, 
setExprs, srcTupleDesc, analyzer);
-        List<Expr> outputExpr = Deencapsulation.invoke(updatePlanner, 
"computeOutputExprs");
-        Assert.assertEquals(4, outputExpr.size());
-        Expr outputExpr1 = outputExpr.get(0);
-        Assert.assertTrue(outputExpr1 instanceof SlotRef);
-        Assert.assertEquals(((SlotRef) 
outputExpr1).getDesc().getColumn().getName(), "k1");
-        Expr outputExpr2 = outputExpr.get(1);
-        Assert.assertTrue(outputExpr2 instanceof SlotRef);
-        Assert.assertEquals(((SlotRef) 
outputExpr2).getDesc().getColumn().getName(), "k2");
-        Expr outputExpr3 = outputExpr.get(2);
-        Assert.assertTrue(outputExpr3 instanceof IntLiteral);
-        Assert.assertEquals(((IntLiteral) outputExpr3).getValue(), 1);
-        Expr outputExpr4 = outputExpr.get(3);
-        Assert.assertTrue(outputExpr4 instanceof IntLiteral);
-        Assert.assertEquals(((IntLiteral) outputExpr4).getValue(), 1);
-    }
-}
diff --git a/regression-test/data/update/test_update_unique.out 
b/regression-test/data/update/test_update_unique.out
index 98f001495e..3d8737af02 100644
--- a/regression-test/data/update/test_update_unique.out
+++ b/regression-test/data/update/test_update_unique.out
@@ -13,3 +13,8 @@ value1        INT     Yes     false   \N      REPLACE
 value2 INT     Yes     false   \N      REPLACE
 date_value     DATE    Yes     false   \N      REPLACE
 
+-- !complex_update --
+1      10      1       1000.0  2000-01-01
+2      2       2       2.0     2000-01-02
+3      3       3       3.0     2000-01-03
+
diff --git a/regression-test/suites/update/test_update_unique.groovy 
b/regression-test/suites/update/test_update_unique.groovy
index 21d2d26b13..6acff99f39 100644
--- a/regression-test/suites/update/test_update_unique.groovy
+++ b/regression-test/suites/update/test_update_unique.groovy
@@ -16,10 +16,12 @@
 // under the License.
 
 suite("test_update_unique", "p0") {
-    def tbName = "test_update_unique"
-    sql "DROP TABLE IF EXISTS ${tbName}"
+    def tbName1 = "test_update_unique_1"
+    def tbName2 = "test_update_unique_2"
+    def tbName3 = "test_update_unique_3"
+    sql "DROP TABLE IF EXISTS ${tbName1}"
     sql """
-            CREATE TABLE IF NOT EXISTS ${tbName} (
+            CREATE TABLE IF NOT EXISTS ${tbName1} (
                 k int,
                 value1 int,
                 value2 int,
@@ -28,14 +30,50 @@ suite("test_update_unique", "p0") {
             UNIQUE KEY(k)
             DISTRIBUTED BY HASH(k) BUCKETS 5 properties("replication_num" = 
"1");
         """
-    sql "insert into ${tbName} values(1, 1, 1, '2000-01-01');"
-    sql "insert into ${tbName} values(2, 1, 1, '2000-01-01');"
-    sql "UPDATE ${tbName} SET value1 = 2 WHERE k=1;"
-    sql "UPDATE ${tbName} SET value1 = value1+1 WHERE k=2;"
-    sql "UPDATE ${tbName} SET date_value = '1999-01-01' WHERE k in (1,2);"
-    qt_select_uniq_table "select * from ${tbName} order by k"
-    sql "UPDATE ${tbName} SET date_value = '1998-01-01' WHERE k is null or k 
is not null;"
-    qt_select_uniq_table "select * from ${tbName} order by k"
-    qt_desc_uniq_table "desc ${tbName}"
-    sql "DROP TABLE ${tbName}"
+    sql "insert into ${tbName1} values(1, 1, 1, '2000-01-01');"
+    sql "insert into ${tbName1} values(2, 1, 1, '2000-01-01');"
+    sql "UPDATE ${tbName1} SET value1 = 2 WHERE k=1;"
+    sql "UPDATE ${tbName1} SET value1 = value1+1 WHERE k=2;"
+    sql "UPDATE ${tbName1} SET date_value = '1999-01-01' WHERE k in (1,2);"
+    qt_select_uniq_table "select * from ${tbName1} order by k"
+    sql "UPDATE ${tbName1} SET date_value = '1998-01-01' WHERE k is null or k 
is not null;"
+    qt_select_uniq_table "select * from ${tbName1} order by k"
+    qt_desc_uniq_table "desc ${tbName1}"
+    sql "DROP TABLE ${tbName1}"
+
+    sql "DROP TABLE IF EXISTS ${tbName1}"
+    sql "DROP TABLE IF EXISTS ${tbName2}"
+    sql "DROP TABLE IF EXISTS ${tbName3}"
+
+    // test complex update syntax
+    sql """
+        create table ${tbName1} (id int, c1 bigint, c2 string, c3 double, c4 
date) unique key (id) distributed by hash(id) properties('replication_num'='1');
+    """
+    sql """
+        create table ${tbName2} (id int, c1 bigint, c2 string, c3 double, c4 
date) unique key (id) distributed by hash(id) properties('replication_num'='1');
+    """
+    sql """
+        create table ${tbName3} (id int) distributed by hash (id) 
properties('replication_num'='1');
+    """
+    sql """
+        insert into ${tbName1} values(1, 1, '1', 1.0, '2000-01-01'),(2, 2, 
'2', 2.0, '2000-01-02'),(3, 3, '3', 3.0, '2000-01-03');
+    """
+    sql """
+        insert into ${tbName2} values(1, 10, '10', 10.0, '2000-01-10'),(2, 20, 
'20', 20.0, '2000-01-20'),(3, 30, '30', 30.0, '2000-01-30'),(4, 4, '4', 4.0, 
'2000-01-04'),(5, 5, '5', 5.0, '2000-01-05');
+    """
+    sql """
+        insert into ${tbName3} values(1), (4), (5);
+    """
+
+    sql """
+        update ${tbName1} set ${tbName1}.c1 = ${tbName2}.c1, ${tbName1}.c3 = 
${tbName2}.c3 * 100 from ${tbName2} inner join ${tbName3} on ${tbName2}.id = 
${tbName3}.id where ${tbName1}.id = ${tbName2}.id;
+    """
+
+    qt_complex_update """
+        select * from ${tbName1} order by id;
+    """
+
+    sql "DROP TABLE IF EXISTS ${tbName1}"
+    sql "DROP TABLE IF EXISTS ${tbName2}"
+    sql "DROP TABLE IF EXISTS ${tbName3}"
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to