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

yiguolei pushed a commit to branch dev-1.1.2
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/dev-1.1.2 by this push:
     new b6936cc2a1 [feature](stmt) add ADMIN COPY TABLET stmt for local debug 
(#12176) (#12216)
b6936cc2a1 is described below

commit b6936cc2a13beb6c9793c2dab4bd79e41ab209e3
Author: Mingyu Chen <[email protected]>
AuthorDate: Wed Aug 31 14:07:34 2022 +0800

    [feature](stmt) add ADMIN COPY TABLET stmt for local debug (#12176) (#12216)
    
    Add a new stmt ADMIN COPY TABLET for easy copy a tablet to local env to 
reproduce problem.
    See document for more details.
---
 be/src/http/action/snapshot_action.cpp             |   6 +-
 be/src/http/action/snapshot_action.h               |   2 +-
 be/src/olap/snapshot_manager.cpp                   |  15 ++-
 be/src/olap/snapshot_manager.h                     |   3 +
 be/src/olap/tablet_meta.cpp                        |  29 +++++
 be/src/olap/tablet_meta.h                          |   1 +
 .../ADMIN-COPY-TABLET.md                           | 101 +++++++++++++++++
 .../ADMIN-COPY-TABLET.md                           | 101 +++++++++++++++++
 fe/fe-core/src/main/cup/sql_parser.cup             |   8 +-
 .../apache/doris/analysis/AdminCopyTabletStmt.java | 124 +++++++++++++++++++++
 .../java/org/apache/doris/catalog/Catalog.java     |  22 +++-
 .../apache/doris/httpv2/rest/GetDdlStmtAction.java |   2 +-
 .../doris/httpv2/rest/StmtExecutionAction.java     |   2 +-
 .../java/org/apache/doris/master/MasterImpl.java   |  10 +-
 .../java/org/apache/doris/qe/ShowExecutor.java     | 115 ++++++++++++++++++-
 .../java/org/apache/doris/task/SnapshotTask.java   |  44 ++++++--
 fe/fe-core/src/main/jflex/sql_scanner.flex         |   1 +
 .../apache/doris/catalog/CreateTableLikeTest.java  |  11 +-
 .../java/org/apache/doris/qe/ShowExecutorTest.java |   4 +-
 gensrc/thrift/AgentService.thrift                  |   1 +
 20 files changed, 565 insertions(+), 37 deletions(-)

diff --git a/be/src/http/action/snapshot_action.cpp 
b/be/src/http/action/snapshot_action.cpp
index 86336b45d9..b3bd98e498 100644
--- a/be/src/http/action/snapshot_action.cpp
+++ b/be/src/http/action/snapshot_action.cpp
@@ -78,7 +78,7 @@ void SnapshotAction::handle(HttpRequest* req) {
     VLOG_ROW << "get make snapshot tablet info: " << tablet_id << "-" << 
schema_hash;
 
     std::string snapshot_path;
-    int64_t ret = make_snapshot(tablet_id, schema_hash, &snapshot_path);
+    int64_t ret = _make_snapshot(tablet_id, schema_hash, &snapshot_path);
     if (ret != 0L) {
         std::string error_msg = std::string("make snapshot failed");
         HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR, 
error_msg);
@@ -93,8 +93,8 @@ void SnapshotAction::handle(HttpRequest* req) {
     LOG(INFO) << "deal with snapshot request finished! tablet id: " << 
tablet_id;
 }
 
-int64_t SnapshotAction::make_snapshot(int64_t tablet_id, int32_t schema_hash,
-                                      std::string* snapshot_path) {
+int64_t SnapshotAction::_make_snapshot(int64_t tablet_id, int32_t schema_hash,
+                                       std::string* snapshot_path) {
     TSnapshotRequest request;
     request.tablet_id = tablet_id;
     request.schema_hash = schema_hash;
diff --git a/be/src/http/action/snapshot_action.h 
b/be/src/http/action/snapshot_action.h
index 673d761182..1a2c5a9c09 100644
--- a/be/src/http/action/snapshot_action.h
+++ b/be/src/http/action/snapshot_action.h
@@ -38,7 +38,7 @@ public:
     void handle(HttpRequest* req) override;
 
 private:
-    int64_t make_snapshot(int64_t tablet_id, int schema_hash, std::string* 
snapshot_path);
+    int64_t _make_snapshot(int64_t tablet_id, int schema_hash, std::string* 
snapshot_path);
 }; // end class SnapshotAction
 
 } // end namespace doris
diff --git a/be/src/olap/snapshot_manager.cpp b/be/src/olap/snapshot_manager.cpp
index 0cd09e80a8..a0dbd899cf 100644
--- a/be/src/olap/snapshot_manager.cpp
+++ b/be/src/olap/snapshot_manager.cpp
@@ -285,6 +285,11 @@ std::string SnapshotManager::_get_header_full_path(const 
TabletSharedPtr& ref_ta
     return header_name_stream.str();
 }
 
+std::string SnapshotManager::_get_json_header_full_path(const TabletSharedPtr& 
ref_tablet,
+                                                        const std::string& 
schema_hash_path) const {
+    return fmt::format("{}/{}.hdr.json", schema_hash_path, 
ref_tablet->tablet_id());
+}
+
 OLAPStatus SnapshotManager::_link_index_and_data_files(
         const FilePathDesc& schema_hash_path_desc, const TabletSharedPtr& 
ref_tablet,
         const std::vector<RowsetSharedPtr>& consistent_rowsets) {
@@ -309,13 +314,13 @@ OLAPStatus SnapshotManager::_create_snapshot_files(const 
TabletSharedPtr& ref_ta
         return OLAP_ERR_INPUT_PARAMETER_ERROR;
     }
 
-    // snapshot_id_path:
-    //      /data/shard_id/tablet_id/snapshot/time_str/id.timeout/
-    string snapshot_id_path;
     int64_t timeout_s = config::snapshot_expire_time_sec;
     if (request.__isset.timeout) {
         timeout_s = request.timeout;
     }
+    // snapshot_id_path:
+    //      /data/shard_id/tablet_id/snapshot/time_str/id.timeout/
+    std::string snapshot_id_path;
     res = _calc_snapshot_id_path(ref_tablet, timeout_s, &snapshot_id_path);
     if (res != OLAP_SUCCESS) {
         LOG(WARNING) << "failed to calc snapshot_id_path, ref tablet="
@@ -329,6 +334,7 @@ OLAPStatus SnapshotManager::_create_snapshot_files(const 
TabletSharedPtr& ref_ta
     // header_path:
     //      /schema_full_path/tablet_id.hdr
     string header_path = _get_header_full_path(ref_tablet, 
schema_full_path_desc.filepath);
+    auto json_header_path = _get_json_header_full_path(ref_tablet, 
schema_full_path_desc.filepath);
     if (FileUtils::check_exist(schema_full_path_desc.filepath)) {
         VLOG_TRACE << "remove the old schema_full_path.";
         FileUtils::remove_all(schema_full_path_desc.filepath);
@@ -454,6 +460,9 @@ OLAPStatus SnapshotManager::_create_snapshot_files(const 
TabletSharedPtr& ref_ta
                       << ", schema hash:" << new_tablet_meta->schema_hash();
         } else if (snapshot_version == 
g_Types_constants.TSNAPSHOT_REQ_VERSION2) {
             res = new_tablet_meta->save(header_path);
+            if (res == OLAP_SUCCESS && request.__isset.is_copy_tablet_task && 
request.is_copy_tablet_task) {
+                res = new_tablet_meta->save_as_json(json_header_path);
+            }
         } else {
             res = OLAP_ERR_INVALID_SNAPSHOT_VERSION;
         }
diff --git a/be/src/olap/snapshot_manager.h b/be/src/olap/snapshot_manager.h
index 0efa64711b..27c70236a5 100644
--- a/be/src/olap/snapshot_manager.h
+++ b/be/src/olap/snapshot_manager.h
@@ -73,6 +73,9 @@ private:
     std::string _get_header_full_path(const TabletSharedPtr& ref_tablet,
                                       const std::string& schema_hash_path) 
const;
 
+    std::string _get_json_header_full_path(const TabletSharedPtr& ref_tablet,
+                                           const std::string& 
schema_hash_path) const;
+
     OLAPStatus _link_index_and_data_files(const FilePathDesc& header_path_desc,
                                           const TabletSharedPtr& ref_tablet,
                                           const std::vector<RowsetSharedPtr>& 
consistent_rowsets);
diff --git a/be/src/olap/tablet_meta.cpp b/be/src/olap/tablet_meta.cpp
index c4696d10c8..3283214459 100644
--- a/be/src/olap/tablet_meta.cpp
+++ b/be/src/olap/tablet_meta.cpp
@@ -20,6 +20,7 @@
 #include <boost/algorithm/string.hpp>
 #include <sstream>
 
+#include "exec/local_file_writer.h"
 #include "olap/file_helper.h"
 #include "olap/olap_common.h"
 #include "olap/olap_define.h"
@@ -293,6 +294,34 @@ std::string TabletMeta::construct_header_file_path(const 
string& schema_hash_pat
     return header_name_stream.str();
 }
 
+OLAPStatus TabletMeta::save_as_json(const string& file_path) {
+    std::string json_meta;
+    json2pb::Pb2JsonOptions json_options;
+    json_options.pretty_json = true;
+    json_options.bytes_to_base64 = true;
+    to_json(&json_meta, json_options);
+    // save to file
+    LocalFileWriter writer(file_path, 0);
+    Status st = writer.open();
+    if (!st.ok()) {
+        LOG(WARNING) << "failed to open for: " << file_path << ", err: " << 
st.get_error_msg();
+        return OLAP_ERR_IO_ERROR;
+    }
+    size_t written_len = 0;
+    st = writer.write((const uint8_t*) json_meta.data(), json_meta.length(), 
&written_len);
+    if (!st.ok()) {
+        LOG(WARNING) << "failed to write for: " << file_path << ", err: " << 
st.get_error_msg();
+        return OLAP_ERR_IO_ERROR;
+    }
+    st = writer.close();
+    if (!st.ok()) {
+        LOG(WARNING) << "failed to close writer for: " << file_path << ", err: 
" << st.get_error_msg();
+        return OLAP_ERR_IO_ERROR;
+    }
+
+    return OLAP_SUCCESS;
+}
+
 OLAPStatus TabletMeta::save(const string& file_path) {
     TabletMetaPB tablet_meta_pb;
     to_meta_pb(&tablet_meta_pb);
diff --git a/be/src/olap/tablet_meta.h b/be/src/olap/tablet_meta.h
index 5654fee29e..30c3875f03 100644
--- a/be/src/olap/tablet_meta.h
+++ b/be/src/olap/tablet_meta.h
@@ -93,6 +93,7 @@ public:
     // Previous tablet_meta is a physical file in tablet dir, which is not 
stored in rocksdb.
     OLAPStatus create_from_file(const std::string& file_path);
     OLAPStatus save(const std::string& file_path);
+    OLAPStatus save_as_json(const string& file_path);
     static OLAPStatus save(const std::string& file_path, const TabletMetaPB& 
tablet_meta_pb);
     static OLAPStatus reset_tablet_uid(const std::string& file_path);
     static std::string construct_header_file_path(const std::string& 
schema_hash_path,
diff --git 
a/docs/en/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
 
b/docs/en/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
new file mode 100644
index 0000000000..26b4631d60
--- /dev/null
+++ 
b/docs/en/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
@@ -0,0 +1,101 @@
+---
+{
+    "title": "ADMIN-COPY-TABLET"
+    "language": "en"
+}
+---
+
+<!--
+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.
+-->
+
+## ADMIN-COPY-TABLET
+
+### Name
+
+ADMIN COPY TABLET
+
+### Description
+
+This statement is used to make a snapshot for the specified tablet, mainly 
used to load the tablet locally to reproduce the problem.
+
+syntax:
+
+```sql
+ADMIN COPY TABLET tablet_id PROPERTIES("xxx");
+```
+
+Notes:
+
+This command requires ROOT privileges.
+
+PROPERTIES supports the following properties:
+
+1. backend_id: Specifies the id of the BE node where the replica is located. 
If not specified, a replica is randomly selected.
+
+2. version: Specifies the version of the snapshot. The version must be less 
than or equal to the largest version of the replica. If not specified, the 
largest version is used.
+
+3. expiration_minutes: Snapshot retention time. The default is 1 hour. It will 
automatically clean up after a timeout. Unit minutes.
+
+The results are shown below:
+
+```
+         TabletId: 10020
+        BackendId: 10003
+               Ip: 192.168.10.1
+             Path: /path/to/be/storage/snapshot/20220830101353.2.3600
+ExpirationMinutes: 60
+  CreateTableStmt: CREATE TABLE `tbl1` (
+  `k1` int(11) NULL,
+  `k2` int(11) NULL
+) ENGINE=OLAP
+DUPLICATE KEY(`k1`, `k2`)
+DISTRIBUTED BY HASH(k1) BUCKETS 1
+PROPERTIES (
+"replication_num" = "1",
+"version_info" = "2"
+);
+```
+
+* TabletId: tablet id
+* BackendId: BE node id
+* Ip: BE node ip
+* Path: The directory where the snapshot is located
+* ExpirationMinutes: snapshot expiration time
+* CreateTableStmt: The table creation statement for the table corresponding to 
the tablet. This statement is not the original table-building statement, but a 
simplified table-building statement for later loading the tablet locally.
+
+### Example
+
+1. Take a snapshot of the replica on the specified BE node
+
+    ```sql
+    ADMIN COPY TABLET 10010 PROPERTIES("backend_id" = "10001");
+    ```
+
+2. Take a snapshot of the specified version of the replica on the specified BE 
node
+
+    ```sql
+    ADMIN COPY TABLET 10010 PROPERTIES("backend_id" = "10001", "version" = 
"10");
+    ```
+
+### Keywords
+
+    ADMIN, COPY, TABLET
+
+### Best Practice
+
diff --git 
a/docs/zh-CN/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
 
b/docs/zh-CN/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
new file mode 100644
index 0000000000..1645a1c18a
--- /dev/null
+++ 
b/docs/zh-CN/docs/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET.md
@@ -0,0 +1,101 @@
+---
+{
+    "title": "ADMIN-COPY-TABLET"
+    "language": "zh-CN"
+}
+---
+
+<!--
+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.
+-->
+
+## ADMIN-COPY-TABLET
+
+### Name
+
+ADMIN COPY TABLET
+
+### Description
+
+该语句用于为指定的 tablet 制作快照,主要用于本地加载 tablet 来复现问题。
+
+语法:
+
+```sql
+ADMIN COPY TABLET tablet_id PROPERTIES("xxx");
+```
+
+说明:
+
+该命令需要 ROOT 权限。
+
+PROPERTIES 支持如下属性:
+
+1. backend_id:指定副本所在的 BE 节点的 id。如果不指定,则随机选择一个副本。
+
+2. version:指定快照的版本。该版本需小于等于副本的最大版本。如不指定,则使用最大版本。
+
+3. expiration_minutes:快照保留时长。默认为1小时。超时后会自动清理。单位分钟。
+
+结果展示如下:
+
+```
+         TabletId: 10020
+        BackendId: 10003
+               Ip: 192.168.10.1
+             Path: /path/to/be/storage/snapshot/20220830101353.2.3600
+ExpirationMinutes: 60
+  CreateTableStmt: CREATE TABLE `tbl1` (
+  `k1` int(11) NULL,
+  `k2` int(11) NULL
+) ENGINE=OLAP
+DUPLICATE KEY(`k1`, `k2`)
+DISTRIBUTED BY HASH(k1) BUCKETS 1
+PROPERTIES (
+"replication_num" = "1",
+"version_info" = "2"
+);
+```
+
+* TabletId: tablet id
+* BackendId: BE 节点 id
+* Ip: BE 节点 ip
+* Path: 快照所在目录
+* ExpirationMinutes: 快照过期时间
+* CreateTableStmt: tablet 对应的表的建表语句。该语句不是原始的建表语句,而是用于之后本地加载 tablet 的简化后的建表语句。
+
+### Example
+
+1. 对指定 BE 节点上的副本做快照
+
+    ```sql
+    ADMIN COPY TABLET 10010 PROPERTIES("backend_id" = "10001");
+    ```
+
+2. 对指定 BE 节点上的副本,做指定版本的快照
+
+    ```sql
+    ADMIN COPY TABLET 10010 PROPERTIES("backend_id" = "10001", "version" = 
"10");
+    ```
+
+### Keywords
+
+    ADMIN, COPY, TABLET
+
+### Best Practice
+
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup 
b/fe/fe-core/src/main/cup/sql_parser.cup
index 9752b9ee08..ba98bc8849 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -239,7 +239,7 @@ terminal String KW_ADD, KW_ADMIN, KW_AFTER, KW_AGGREGATE, 
KW_ALIAS, KW_ALL, KW_A
     KW_BACKEND, KW_BACKUP, KW_BETWEEN, KW_BEGIN, KW_BIGINT, KW_BINLOG, 
KW_BITMAP, KW_BITMAP_UNION, KW_BLOB, KW_BOOLEAN, KW_BROKER, KW_BACKENDS, KW_BY, 
KW_BUILTIN,
     KW_CANCEL, KW_CASE, KW_CAST, KW_CHAIN, KW_CHAR, KW_CHARSET, KW_CHECK, 
KW_CLUSTER, KW_CLUSTERS, KW_CLEAN, KW_CURRENT_TIMESTAMP,
     KW_COLLATE, KW_COLLATION, KW_COLUMN, KW_COLUMNS, KW_COMMENT, KW_COMMIT, 
KW_COMMITTED, KW_COMPACT,
-    KW_CONFIG, KW_CONNECTION, KW_CONNECTION_ID, KW_CONSISTENT, KW_CONVERT, 
KW_COUNT, KW_CREATE, KW_CREATION, KW_CROSS, KW_CUBE, KW_CURRENT, 
KW_CURRENT_USER,
+    KW_CONFIG, KW_CONNECTION, KW_CONNECTION_ID, KW_CONSISTENT, KW_CONVERT, 
KW_COPY, KW_COUNT, KW_CREATE, KW_CREATION, KW_CROSS, KW_CUBE, KW_CURRENT, 
KW_CURRENT_USER,
     KW_DATA, KW_DATABASE, KW_DATABASES, KW_DATE, KW_DATETIME, KW_DAY, 
KW_DECIMAL, KW_DECOMMISSION, KW_DEFAULT, KW_DESC, KW_DESCRIBE,
     KW_DELETE, KW_UPDATE, KW_DIAGNOSE, KW_DISTINCT, KW_DISTINCTPC, 
KW_DISTINCTPCSA, KW_DISTRIBUTED, KW_DISTRIBUTION, KW_DYNAMIC, KW_BUCKETS, 
KW_DIV, KW_DOUBLE, KW_DROP, KW_DROPP, KW_DUPLICATE,
     KW_ELSE, KW_ENABLE, KW_ENCRYPTKEY, KW_ENCRYPTKEYS, KW_END, KW_ENGINE, 
KW_ENGINES, KW_ENTER, KW_ERRORS, KW_EVENTS, KW_EXCEPT, KW_EXCLUDE,
@@ -5305,6 +5305,10 @@ admin_stmt ::=
     {:
         RESULT = new AdminShowTabletStorageFormatStmt(true);
     :}
+    | KW_ADMIN KW_COPY KW_TABLET INTEGER_LITERAL:tabletId 
opt_properties:properties
+    {:
+        RESULT = new AdminCopyTabletStmt(tabletId, properties);
+    :}
     ;
 
 truncate_stmt ::=
@@ -5470,6 +5474,8 @@ keyword ::=
     {: RESULT = id; :}
     | KW_CONVERT:id
     {: RESULT = id; :}
+    | KW_COPY:id
+    {: RESULT = id; :}
     | KW_CREATION:id
     {: RESULT = id; :}
     | KW_DATA:id
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/AdminCopyTabletStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/AdminCopyTabletStmt.java
new file mode 100644
index 0000000000..68800feb0a
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/AdminCopyTabletStmt.java
@@ -0,0 +1,124 @@
+// 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.analysis;
+
+import org.apache.doris.catalog.Catalog;
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.ShowResultSetMetaData;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+import java.util.Iterator;
+import java.util.Map;
+
+// ADMIN COPY TABLET 10110 PROPERTIES('version' = '1000', backend_id = 
'10001');
+public class AdminCopyTabletStmt extends ShowStmt {
+    public static final String PROP_VERSION = "version";
+    public static final String PROP_BACKEND_ID = "backend_id";
+    public static final String PROP_EXPIRATION = "expiration_minutes";
+    private static final long DEFAULT_EXPIRATION_MINUTES = 60;
+    public static final ImmutableList<String> TITLE_NAMES = new 
ImmutableList.Builder<String>().add("TabletId")
+            
.add("BackendId").add("Ip").add("Path").add("ExpirationMinutes").add("CreateTableStmt").build();
+
+    private long tabletId;
+    private Map<String, String> properties = Maps.newHashMap();
+    private long version = -1;
+    private long backendId = -1;
+    private long expirationMinutes = DEFAULT_EXPIRATION_MINUTES;    // default 
60min
+
+    public AdminCopyTabletStmt(long tabletId, Map<String, String> properties) {
+        this.tabletId = tabletId;
+        this.properties = properties;
+    }
+
+    public long getTabletId() {
+        return tabletId;
+    }
+
+    public long getVersion() {
+        return version;
+    }
+
+    public long getBackendId() {
+        return backendId;
+    }
+
+    public long getExpirationMinutes() {
+        return expirationMinutes;
+    }
+
+    @Override
+    public void analyze(Analyzer analyzer) throws AnalysisException {
+        if 
(!Catalog.getCurrentCatalog().getAuth().checkGlobalPriv(ConnectContext.get(), 
PrivPredicate.OPERATOR)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, 
"NODE");
+        }
+
+        if (properties == null) {
+            return;
+        }
+
+        try {
+            Iterator<Map.Entry<String, String>> iter = 
properties.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<String, String> entry = iter.next();
+                if (entry.getKey().equalsIgnoreCase(PROP_VERSION)) {
+                    version = Long.valueOf(entry.getValue());
+                    iter.remove();
+                    continue;
+                } else if (entry.getKey().equalsIgnoreCase(PROP_BACKEND_ID)) {
+                    backendId = Long.valueOf(entry.getValue());
+                    iter.remove();
+                    continue;
+                } else if (entry.getKey().equalsIgnoreCase(PROP_EXPIRATION)) {
+                    expirationMinutes = Long.valueOf(entry.getValue());
+                    expirationMinutes = Math.min(DEFAULT_EXPIRATION_MINUTES, 
expirationMinutes);
+                    iter.remove();
+                    continue;
+                }
+            }
+        } catch (NumberFormatException e) {
+            throw new AnalysisException("Invalid property: " + e.getMessage());
+        }
+
+        if (!properties.isEmpty()) {
+            throw new AnalysisException("Unknown property: " + properties);
+        }
+    }
+
+    @Override
+    public ShowResultSetMetaData getMetaData() {
+        ShowResultSetMetaData.Builder builder = 
ShowResultSetMetaData.builder();
+        for (String title : TITLE_NAMES) {
+            builder.addColumn(new Column(title, 
ScalarType.createStringType()));
+        }
+        return builder.build();
+    }
+
+    @Override
+    public RedirectStatus getRedirectStatus() {
+        return RedirectStatus.NO_FORWARD;
+    }
+}
+
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java
index bd8edc57f3..83ba31b1e3 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java
@@ -3091,7 +3091,7 @@ public class Catalog {
                     throw new DdlException("Table[" + table.getName() + "] is 
external, not support rollup copy");
                 }
 
-                Catalog.getDdlStmt(stmt, stmt.getDbName(), table, 
createTableStmt, null, null, false, false, true);
+                Catalog.getDdlStmt(stmt, stmt.getDbName(), table, 
createTableStmt, null, null, false, false, true, -1L);
                 if (createTableStmt.isEmpty()) {
                     
ErrorReport.reportDdlException(ErrorCode.ERROR_CREATE_TABLE_LIKE_EMPTY, 
"CREATE");
                 }
@@ -4113,9 +4113,9 @@ public class Catalog {
     }
 
     public static void getDdlStmt(Table table, List<String> createTableStmt, 
List<String> addPartitionStmt,
-                                  List<String> createRollupStmt, boolean 
separatePartition, boolean hidePassword) {
-        getDdlStmt(null, null, table, createTableStmt, addPartitionStmt, 
createRollupStmt,
-                separatePartition, hidePassword, false);
+            List<String> createRollupStmt, boolean separatePartition, boolean 
hidePassword, long specificVersion) {
+        getDdlStmt(null, null, table, createTableStmt, addPartitionStmt, 
createRollupStmt, separatePartition,
+                hidePassword, false, specificVersion);
     }
 
     /**
@@ -4124,8 +4124,8 @@ public class Catalog {
      * @param getDdlForLike Get schema for 'create table like' or not. when 
true, without hidden columns.
      */
     public static void getDdlStmt(DdlStmt ddlStmt, String dbName, Table table, 
List<String> createTableStmt,
-                                  List<String> addPartitionStmt, List<String> 
createRollupStmt,
-                                  boolean separatePartition, boolean 
hidePassword, boolean getDdlForLike) {
+            List<String> addPartitionStmt, List<String> createRollupStmt, 
boolean separatePartition,
+            boolean hidePassword, boolean getDdlForLike, long specificVersion) 
{
         StringBuilder sb = new StringBuilder();
 
         // 1. create table
@@ -4193,6 +4193,16 @@ public class Catalog {
             }
             sb.append(Joiner.on(", ").join(keysColumnNames)).append(")");
 
+            if (specificVersion != -1) {
+                // for copy tablet operation
+                sb.append("\nDISTRIBUTED BY 
HASH(").append(olapTable.getBaseSchema().get(0).getName())
+                        .append(") BUCKETS 1");
+                sb.append("\nPROPERTIES (\n" + "\"replication_num\" = 
\"1\",\n" + "\"version_info\" = \""
+                        + specificVersion + "\"\n" + ")");
+                createTableStmt.add(sb + ";");
+                return;
+            }
+
             if (!Strings.isNullOrEmpty(table.getComment())) {
                 sb.append("\nCOMMENT 
\"").append(table.getComment(true)).append("\"");
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/GetDdlStmtAction.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/GetDdlStmtAction.java
index ce6d93ac20..5291b7e800 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/GetDdlStmtAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/GetDdlStmtAction.java
@@ -78,7 +78,7 @@ public class GetDdlStmtAction extends RestBaseController {
 
         table.readLock();
         try {
-            Catalog.getDdlStmt(table, createTableStmt, addPartitionStmt, 
createRollupStmt, true, false /* show password */);
+            Catalog.getDdlStmt(table, createTableStmt, addPartitionStmt, 
createRollupStmt, true, false /* show password */, -1);
         } finally {
             table.readUnlock();
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
index b2ffd17935..00f8a0d317 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
@@ -177,7 +177,7 @@ public class StmtExecutionAction extends RestBaseController 
{
             List<String> createStmts = Lists.newArrayList();
             for (Table tbl : tableMap.values()) {
                 List<String> createTableStmts = Lists.newArrayList();
-                Catalog.getDdlStmt(tbl, createTableStmts, null, null, false, 
true);
+                Catalog.getDdlStmt(tbl, createTableStmts, null, null, false, 
true, -1L);
                 if (!createTableStmts.isEmpty()) {
                     createStmts.add(createTableStmts.get(0));
                 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/master/MasterImpl.java 
b/fe/fe-core/src/main/java/org/apache/doris/master/MasterImpl.java
index c1a12a840c..c799402c62 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/master/MasterImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/master/MasterImpl.java
@@ -715,10 +715,14 @@ public class MasterImpl {
 
     private void finishMakeSnapshot(AgentTask task, TFinishTaskRequest 
request) {
         SnapshotTask snapshotTask = (SnapshotTask) task;
-        if 
(Catalog.getCurrentCatalog().getBackupHandler().handleFinishedSnapshotTask(snapshotTask,
 request)) {
-            AgentTaskQueue.removeTask(task.getBackendId(), 
TTaskType.MAKE_SNAPSHOT, task.getSignature());
+        if (snapshotTask.isCopyTabletTask()) {
+            snapshotTask.setResultSnapshotPath(request.getSnapshotPath());
+            snapshotTask.countDown(task.getBackendId(), task.getTabletId());
+        } else {
+            if 
(Catalog.getCurrentCatalog().getBackupHandler().handleFinishedSnapshotTask(snapshotTask,
 request)) {
+                AgentTaskQueue.removeTask(task.getBackendId(), 
TTaskType.MAKE_SNAPSHOT, task.getSignature());
+            }
         }
-
     }
 
     private void finishUpload(AgentTask task, TFinishTaskRequest request) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
index 6ae0f4c349..8e4647d67d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.qe;
 
+import org.apache.doris.analysis.AdminCopyTabletStmt;
 import org.apache.doris.analysis.AdminDiagnoseTabletStmt;
 import org.apache.doris.analysis.AdminShowConfigStmt;
 import org.apache.doris.analysis.AdminShowReplicaDistributionStmt;
@@ -125,6 +126,7 @@ import org.apache.doris.common.DdlException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.MarkedCountDownLatch;
 import org.apache.doris.common.MetaNotFoundException;
 import org.apache.doris.common.PatternMatcher;
 import org.apache.doris.common.proc.BackendsProcDir;
@@ -161,18 +163,22 @@ import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.system.Backend;
 import org.apache.doris.system.Diagnoser;
 import org.apache.doris.system.SystemInfoService;
+import org.apache.doris.task.AgentBatchTask;
 import org.apache.doris.task.AgentClient;
+import org.apache.doris.task.AgentTaskExecutor;
+import org.apache.doris.task.AgentTaskQueue;
+import org.apache.doris.task.SnapshotTask;
 import org.apache.doris.thrift.TCheckStorageFormatResult;
+import org.apache.doris.thrift.TTaskType;
 import org.apache.doris.thrift.TUnit;
 import org.apache.doris.transaction.GlobalTransactionMgr;
+import org.apache.doris.transaction.TransactionStatus;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-
 import org.apache.commons.lang3.tuple.Triple;
-import org.apache.doris.transaction.TransactionStatus;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -188,6 +194,7 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 // Execute one show statement.
@@ -344,6 +351,8 @@ public class ShowExecutor {
             handleAdminDiagnoseTablet();
         } else if (stmt instanceof ShowCreateMaterializedViewStmt) {
             handleShowCreateMaterializedView();
+        } else if (stmt instanceof AdminCopyTabletStmt) {
+            handleCopyTablet();
         } else {
             handleEmtpy();
         }
@@ -807,7 +816,7 @@ public class ShowExecutor {
         table.readLock();
         try {
             List<String> createTableStmt = Lists.newArrayList();
-            Catalog.getDdlStmt(table, createTableStmt, null, null, false, true 
/* hide password */);
+            Catalog.getDdlStmt(table, createTableStmt, null, null, false, true 
/* hide password */, -1L);
             if (createTableStmt.isEmpty()) {
                 resultSet = new ShowResultSet(showStmt.getMetaData(), rows);
                 return;
@@ -917,7 +926,7 @@ public class ShowExecutor {
             view.readLock();
             try {
                 List<String> createViewStmt = Lists.newArrayList();
-                Catalog.getDdlStmt(view, createViewStmt, null, null, false, 
true /* hide password */);
+                Catalog.getDdlStmt(view, createViewStmt, null, null, false, 
true /* hide password */, -1L);
                 if (!createViewStmt.isEmpty()) {
                     rows.add(Lists.newArrayList(view.getName(), 
createViewStmt.get(0)));
                 }
@@ -2206,4 +2215,102 @@ public class ShowExecutor {
         resultSet = new ShowResultSet(showStmt.getMetaData(), resultRowSet);
     }
 
+    private void handleCopyTablet() throws AnalysisException {
+        AdminCopyTabletStmt copyStmt = (AdminCopyTabletStmt) stmt;
+        long tabletId = copyStmt.getTabletId();
+        long version = copyStmt.getVersion();
+        long backendId = copyStmt.getBackendId();
+
+        TabletInvertedIndex invertedIndex = Catalog.getCurrentInvertedIndex();
+        TabletMeta tabletMeta = invertedIndex.getTabletMeta(tabletId);
+        if (tabletMeta == null) {
+            throw new AnalysisException("Unknown tablet: " + tabletId);
+        }
+
+        // 1. find replica
+        Replica replica = null;
+        if (backendId != -1) {
+            replica = invertedIndex.getReplica(tabletId, backendId);
+        } else {
+            List<Replica> replicas = 
invertedIndex.getReplicasByTabletId(tabletId);
+            if (!replicas.isEmpty()) {
+                replica = replicas.get(0);
+            }
+        }
+        if (replica == null) {
+            throw new AnalysisException("Replica not found on backend: " + 
backendId);
+        }
+        backendId = replica.getBackendId();
+        Backend be = Catalog.getCurrentSystemInfo().getBackend(backendId);
+        if (be == null || !be.isAlive()) {
+            throw new AnalysisException("Unavailable backend: " + backendId);
+        }
+
+        // 2. find version
+        if (version != -1 && replica.getVersion() < version) {
+            throw new AnalysisException("Version is larger than replica max 
version: " + replica.getVersion());
+        }
+        version = version == -1 ? replica.getVersion() : version;
+
+        // 3. get create table stmt
+        Database db = 
Catalog.getCurrentCatalog().getDbOrAnalysisException(tabletMeta.getDbId());
+        OlapTable tbl = (OlapTable) 
db.getTableNullable(tabletMeta.getTableId());
+        if (tbl == null) {
+            throw new AnalysisException("Failed to find table: " + 
tabletMeta.getTableId());
+        }
+
+        List<String> createTableStmt = Lists.newArrayList();
+        tbl.readLock();
+        try {
+            Catalog.getDdlStmt(tbl, createTableStmt, null, null, false, true 
/* hide password */, version);
+        } finally {
+            tbl.readUnlock();
+        }
+
+        // 4. create snapshot task
+        SnapshotTask task = new SnapshotTask(null, backendId, tabletId, -1, 
tabletMeta.getDbId(),
+                tabletMeta.getTableId(), tabletMeta.getPartitionId(), 
tabletMeta.getIndexId(), tabletId, version, tabletMeta.getOldSchemaHash(),
+                copyStmt.getExpirationMinutes() * 60 * 1000, false);
+        task.setIsCopyTabletTask(true);
+        MarkedCountDownLatch<Long, Long> countDownLatch = new 
MarkedCountDownLatch<Long, Long>(1);
+        countDownLatch.addMark(backendId, tabletId);
+        task.setCountDownLatch(countDownLatch);
+
+        // 5. send task and wait
+        AgentBatchTask batchTask = new AgentBatchTask();
+        batchTask.addTask(task);
+        try {
+            AgentTaskQueue.addBatchTask(batchTask);
+            AgentTaskExecutor.submit(batchTask);
+
+            boolean ok = false;
+            try {
+                ok = countDownLatch.await(10, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                LOG.warn("InterruptedException: ", e);
+                ok = false;
+            }
+
+            if (!ok) {
+                throw new AnalysisException(
+                        "Failed to make snapshot for tablet " + tabletId + " 
on backend: " + backendId);
+            }
+
+            // send result
+            List<List<String>> resultRowSet = Lists.newArrayList();
+            List<String> row = Lists.newArrayList();
+            row.add(String.valueOf(tabletId));
+            row.add(String.valueOf(backendId));
+            row.add(be.getHost());
+            row.add(task.getResultSnapshotPath());
+            row.add(String.valueOf(copyStmt.getExpirationMinutes()));
+            row.add(createTableStmt.get(0));
+            resultRowSet.add(row);
+
+            ShowResultSetMetaData showMetaData = copyStmt.getMetaData();
+            resultSet = new ShowResultSet(showMetaData, resultRowSet);
+        } finally {
+            AgentTaskQueue.removeBatchTask(batchTask, TTaskType.MAKE_SNAPSHOT);
+        }
+    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/task/SnapshotTask.java 
b/fe/fe-core/src/main/java/org/apache/doris/task/SnapshotTask.java
index 7da6a5afea..71b3570f28 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/task/SnapshotTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/task/SnapshotTask.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.task;
 
+import org.apache.doris.common.MarkedCountDownLatch;
 import org.apache.doris.thrift.TResourceInfo;
 import org.apache.doris.thrift.TSnapshotRequest;
 import org.apache.doris.thrift.TTaskType;
@@ -24,18 +25,22 @@ import org.apache.doris.thrift.TypesConstants;
 
 public class SnapshotTask extends AgentTask {
     private long jobId;
-
     private long version;
-
     private int schemaHash;
-
     private long timeoutMs;
-
     private boolean isRestoreTask;
 
-    public SnapshotTask(TResourceInfo resourceInfo, long backendId, long 
signature, long jobId,
-            long dbId, long tableId, long partitionId, long indexId, long 
tabletId,
-            long version, int schemaHash, long timeoutMs, boolean 
isRestoreTask) {
+    // Set to true if this task for AdminCopyTablet.
+    // Otherwise, it is for Backup/Restore operation.
+    private boolean isCopyTabletTask = false;
+    private MarkedCountDownLatch<Long, Long> countDownLatch;
+    // Only for copy tablet task.
+    // Save the snapshot path.
+    private String resultSnapshotPath;
+
+    public SnapshotTask(TResourceInfo resourceInfo, long backendId, long 
signature, long jobId, long dbId, long tableId,
+            long partitionId, long indexId, long tabletId, long version, int 
schemaHash, long timeoutMs,
+            boolean isRestoreTask) {
         super(resourceInfo, backendId, TTaskType.MAKE_SNAPSHOT, dbId, tableId, 
partitionId, indexId, tabletId,
                 signature);
 
@@ -49,6 +54,22 @@ public class SnapshotTask extends AgentTask {
         this.isRestoreTask = isRestoreTask;
     }
 
+    public void setIsCopyTabletTask(boolean value) {
+        this.isCopyTabletTask = value;
+    }
+
+    public boolean isCopyTabletTask() {
+        return isCopyTabletTask;
+    }
+
+    public void setCountDownLatch(MarkedCountDownLatch<Long, Long> 
countDownLatch) {
+        this.countDownLatch = countDownLatch;
+    }
+
+    public void countDown(long backendId, long tabletId) {
+        this.countDownLatch.markedCountDown(backendId, tabletId);
+    }
+
     public long getJobId() {
         return jobId;
     }
@@ -69,12 +90,21 @@ public class SnapshotTask extends AgentTask {
         return isRestoreTask;
     }
 
+    public void setResultSnapshotPath(String resultSnapshotPath) {
+        this.resultSnapshotPath = resultSnapshotPath;
+    }
+
+    public String getResultSnapshotPath() {
+        return resultSnapshotPath;
+    }
+
     public TSnapshotRequest toThrift() {
         TSnapshotRequest request = new TSnapshotRequest(tabletId, schemaHash);
         request.setVersion(version);
         request.setListFiles(true);
         
request.setPreferredSnapshotVersion(TypesConstants.TPREFER_SNAPSHOT_REQ_VERSION);
         request.setTimeout(timeoutMs / 1000);
+        request.setIsCopyTabletTask(isCopyTabletTask);
         return request;
     }
 }
diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex 
b/fe/fe-core/src/main/jflex/sql_scanner.flex
index faaf4fdfe5..edabe681e6 100644
--- a/fe/fe-core/src/main/jflex/sql_scanner.flex
+++ b/fe/fe-core/src/main/jflex/sql_scanner.flex
@@ -143,6 +143,7 @@ import org.apache.doris.qe.SqlModeHelper;
         keywordMap.put("connection_id", new 
Integer(SqlParserSymbols.KW_CONNECTION_ID));
         keywordMap.put("consistent", new 
Integer(SqlParserSymbols.KW_CONSISTENT));
         keywordMap.put("convert", new Integer(SqlParserSymbols.KW_CONVERT));
+        keywordMap.put("copy", new Integer(SqlParserSymbols.KW_COPY));
         keywordMap.put("count", new Integer(SqlParserSymbols.KW_COUNT));
         keywordMap.put("create", new Integer(SqlParserSymbols.KW_CREATE));
         keywordMap.put("creation", new Integer(SqlParserSymbols.KW_CREATION));
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
index bda5ea67bd..8d90c0a08a 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
@@ -25,13 +25,12 @@ import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.utframe.UtFrameUtils;
 
+import com.google.common.collect.Lists;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.google.common.collect.Lists;
-
 import java.io.File;
 import java.util.List;
 import java.util.UUID;
@@ -80,11 +79,13 @@ public class CreateTableLikeTest {
     private static void checkTableEqual(Table newTable, Table existedTable, 
int rollupSize) {
         List<String> newCreateTableStmt = Lists.newArrayList();
         List<String> newAddRollupStmt = Lists.newArrayList();
-        Catalog.getDdlStmt(newTable, newCreateTableStmt, null, 
newAddRollupStmt, false, true /* hide password */);
+        Catalog.getDdlStmt(newTable, newCreateTableStmt, null, 
newAddRollupStmt, false, true /* hide password */, -1L);
         List<String> existedTableStmt = Lists.newArrayList();
         List<String> existedAddRollupStmt = Lists.newArrayList();
-        Catalog.getDdlStmt(existedTable, existedTableStmt, null, 
existedAddRollupStmt, false, true /* hide password */);
-        
Assert.assertEquals(newCreateTableStmt.get(0).replace(newTable.getName(), 
existedTable.getName()), existedTableStmt.get(0));
+        Catalog.getDdlStmt(existedTable, existedTableStmt, null, 
existedAddRollupStmt, false, true /* hide password */,
+                -1L);
+        
Assert.assertEquals(newCreateTableStmt.get(0).replace(newTable.getName(), 
existedTable.getName()),
+                existedTableStmt.get(0));
         checkTableRollup(existedAddRollupStmt, newAddRollupStmt, 
newTable.getName(), existedTable.getName(), rollupSize);
     }
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/ShowExecutorTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/ShowExecutorTest.java
index a6aa8b8084..fd46949d35 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/ShowExecutorTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/ShowExecutorTest.java
@@ -200,10 +200,10 @@ public class ShowExecutorTest {
                 minTimes = 0;
                 result = catalog;
 
-                Catalog.getDdlStmt((Table) any, (List) any, (List) any, (List) 
any, anyBoolean, anyBoolean);
+                Catalog.getDdlStmt((Table) any, (List) any, (List) any, (List) 
any, anyBoolean, anyBoolean, anyLong);
                 minTimes = 0;
 
-                Catalog.getDdlStmt((Table) any, (List) any, null, null, 
anyBoolean, anyBoolean);
+                Catalog.getDdlStmt((Table) any, (List) any, null, null, 
anyBoolean, anyBoolean, anyLong);
                 minTimes = 0;
             }
         };
diff --git a/gensrc/thrift/AgentService.thrift 
b/gensrc/thrift/AgentService.thrift
index 62855abfe1..6301cef6ca 100644
--- a/gensrc/thrift/AgentService.thrift
+++ b/gensrc/thrift/AgentService.thrift
@@ -250,6 +250,7 @@ struct TSnapshotRequest {
     // Deprecated since version 0.13
     8: optional bool allow_incremental_clone
     9: optional i32 preferred_snapshot_version = 
Types.TPREFER_SNAPSHOT_REQ_VERSION
+    10: optional bool is_copy_tablet_task
 }
 
 struct TReleaseSnapshotRequest {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to