Skip to content

Commit 764dcd7

Browse files
authored
[fix](restore) Fix view signature #41120 (#41149)
cherry pick from #41120
1 parent 36c9046 commit 764dcd7

File tree

5 files changed

+194
-9
lines changed

5 files changed

+194
-9
lines changed

fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -751,16 +751,23 @@ private void checkAndPrepareMeta() {
751751
if (localTbl != null) {
752752
Preconditions.checkState(localTbl.getType() == TableType.VIEW);
753753
View localView = (View) localTbl;
754-
if (!localView.getSignature(BackupHandler.SIGNATURE_VERSION)
755-
.equals(remoteView.getSignature(BackupHandler.SIGNATURE_VERSION))) {
756-
status = new Status(ErrCode.COMMON_ERROR, "View "
757-
+ jobInfo.getAliasByOriginNameIfSet(backupViewName)
758-
+ " already exist but with different schema");
759-
return;
754+
String localViewSignature = localView.getSignature(BackupHandler.SIGNATURE_VERSION);
755+
// keep compatible with old version, compare the signature without reset view def
756+
if (!localViewSignature.equals(remoteView.getSignature(BackupHandler.SIGNATURE_VERSION))) {
757+
// reset view def to dest db name and compare signature again
758+
String srcDbName = jobInfo.dbName;
759+
remoteView.resetViewDefForRestore(srcDbName, db.getName());
760+
if (!localViewSignature.equals(remoteView.getSignature(BackupHandler.SIGNATURE_VERSION))) {
761+
status = new Status(ErrCode.COMMON_ERROR, "View "
762+
+ jobInfo.getAliasByOriginNameIfSet(backupViewName)
763+
+ " already exist but with different schema");
764+
return;
765+
}
760766
}
761767
} else {
762768
String srcDbName = jobInfo.dbName;
763-
remoteView.resetIdsForRestore(env, srcDbName, db.getFullName());
769+
remoteView.resetViewDefForRestore(srcDbName, db.getName());
770+
remoteView.resetIdsForRestore(env);
764771
restoredTbls.add(remoteView);
765772
}
766773
}

fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public Status resetIdsForRestore(Env env, Database db, ReplicaAllocation restore
591591
baseIndexId = newIdxId;
592592
}
593593
MaterializedIndexMeta indexMeta = origIdxIdToMeta.get(entry.getKey());
594-
indexMeta.resetIndexIdForRestore(newIdxId, srcDbName, db.getFullName());
594+
indexMeta.resetIndexIdForRestore(newIdxId, srcDbName, db.getName());
595595
indexIdToMeta.put(newIdxId, indexMeta);
596596
indexNameToId.put(entry.getValue(), newIdxId);
597597
}

fe/fe-core/src/main/java/org/apache/doris/catalog/View.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,11 @@ public View clone() {
247247
return copied;
248248
}
249249

250-
public void resetIdsForRestore(Env env, String srcDbName, String dbName) {
250+
public void resetIdsForRestore(Env env) {
251251
id = env.getNextId();
252+
}
252253

254+
public void resetViewDefForRestore(String srcDbName, String dbName) {
253255
// the source db name is not setted in old BackupMeta, keep compatible with the old one.
254256
if (srcDbName != null) {
255257
inlineViewDef = inlineViewDef.replaceAll(srcDbName, dbName);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
-- This file is automatically generated. You should know what you did if you want to edit this
2+
-- !sql --
3+
1 1
4+
2 2
5+
3 3
6+
4 4
7+
5 5
8+
6 6
9+
7 7
10+
8 8
11+
9 9
12+
10 10
13+
14+
-- !sql --
15+
6 6
16+
7 7
17+
8 8
18+
9 9
19+
10 10
20+
21+
-- !sql --
22+
1 1
23+
2 2
24+
3 3
25+
4 4
26+
5 5
27+
6 6
28+
7 7
29+
8 8
30+
9 9
31+
10 10
32+
33+
-- !sql --
34+
6 6
35+
7 7
36+
8 8
37+
9 9
38+
10 10
39+
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_backup_restore_with_view", "backup_restore") {
19+
String suiteName = "backup_restore_with_view"
20+
String dbName = "${suiteName}_db"
21+
String dbName1 = "${suiteName}_db_1"
22+
String repoName = "repo_" + UUID.randomUUID().toString().replace("-", "")
23+
String snapshotName = "${suiteName}_snapshot"
24+
String tableName = "${suiteName}_table"
25+
String viewName = "${suiteName}_view"
26+
27+
def syncer = getSyncer()
28+
syncer.createS3Repository(repoName)
29+
sql "CREATE DATABASE IF NOT EXISTS ${dbName}"
30+
sql "CREATE DATABASE IF NOT EXISTS ${dbName1}"
31+
32+
int numRows = 10;
33+
sql "DROP TABLE IF EXISTS ${dbName}.${tableName} FORCE"
34+
sql "DROP VIEW IF EXISTS ${dbName}.${viewName}"
35+
sql """
36+
CREATE TABLE ${dbName}.${tableName} (
37+
`id` LARGEINT NOT NULL,
38+
`count` LARGEINT SUM DEFAULT "0"
39+
)
40+
AGGREGATE KEY(`id`)
41+
DISTRIBUTED BY HASH(`id`) BUCKETS 2
42+
PROPERTIES
43+
(
44+
"replication_num" = "1"
45+
)
46+
"""
47+
List<String> values = []
48+
for (int j = 1; j <= numRows; ++j) {
49+
values.add("(${j}, ${j})")
50+
}
51+
sql "INSERT INTO ${dbName}.${tableName} VALUES ${values.join(",")}"
52+
53+
sql """CREATE VIEW ${dbName}.${viewName} (id, count)
54+
AS
55+
SELECT * FROM ${dbName}.${tableName} WHERE count > 5
56+
"""
57+
58+
qt_sql "SELECT * FROM ${dbName}.${tableName} ORDER BY id ASC"
59+
qt_sql "SELECT * FROM ${dbName}.${viewName} ORDER BY id ASC"
60+
61+
sql """
62+
BACKUP SNAPSHOT ${dbName}.${snapshotName}
63+
TO `${repoName}`
64+
"""
65+
66+
syncer.waitSnapshotFinish(dbName)
67+
68+
def snapshot = syncer.getSnapshotTimestamp(repoName, snapshotName)
69+
assertTrue(snapshot != null)
70+
71+
sql "DROP TABLE IF EXISTS ${dbName1}.${tableName} FORCE"
72+
sql "DROP VIEW IF EXISTS ${dbName1}.${viewName}"
73+
74+
sql """
75+
RESTORE SNAPSHOT ${dbName1}.${snapshotName}
76+
FROM `${repoName}`
77+
PROPERTIES
78+
(
79+
"backup_timestamp" = "${snapshot}",
80+
"reserve_replica" = "true"
81+
)
82+
"""
83+
84+
syncer.waitAllRestoreFinish(dbName1)
85+
86+
qt_sql "SELECT * FROM ${dbName1}.${tableName} ORDER BY id ASC"
87+
qt_sql "SELECT * FROM ${dbName1}.${viewName} ORDER BY id ASC"
88+
def show_view_result = sql_return_maparray "SHOW VIEW FROM ${tableName} FROM ${dbName1}"
89+
logger.info("show view result: ${show_view_result}")
90+
assertTrue(show_view_result.size() == 1);
91+
def show_view = show_view_result[0]['Create View']
92+
assertTrue(show_view.contains("${dbName1}"))
93+
assertTrue(show_view.contains("${tableName}"))
94+
95+
// restore to db, test the view signature.
96+
sql """
97+
RESTORE SNAPSHOT ${dbName}.${snapshotName}
98+
FROM `${repoName}`
99+
PROPERTIES
100+
(
101+
"backup_timestamp" = "${snapshot}",
102+
"reserve_replica" = "true"
103+
)
104+
"""
105+
106+
syncer.waitAllRestoreFinish(dbName)
107+
def restore_result = sql_return_maparray """ SHOW RESTORE FROM ${dbName} WHERE Label ="${snapshotName}" """
108+
restore_result.last()
109+
logger.info("show restore result: ${restore_result}")
110+
assertTrue(restore_result.last().State == "FINISHED")
111+
112+
// restore to db1, test the view signature.
113+
sql """
114+
RESTORE SNAPSHOT ${dbName1}.${snapshotName}
115+
FROM `${repoName}`
116+
PROPERTIES
117+
(
118+
"backup_timestamp" = "${snapshot}",
119+
"reserve_replica" = "true"
120+
)
121+
"""
122+
123+
syncer.waitAllRestoreFinish(dbName1)
124+
restore_result = sql_return_maparray """ SHOW RESTORE FROM ${dbName1} WHERE Label ="${snapshotName}" """
125+
restore_result.last()
126+
logger.info("show restore result: ${restore_result}")
127+
assertTrue(restore_result.last().State == "FINISHED")
128+
129+
sql "DROP TABLE ${dbName}.${tableName} FORCE"
130+
sql "DROP VIEW ${dbName}.${viewName}"
131+
sql "DROP DATABASE ${dbName} FORCE"
132+
sql "DROP TABLE ${dbName1}.${tableName} FORCE"
133+
sql "DROP VIEW ${dbName1}.${viewName}"
134+
sql "DROP DATABASE ${dbName1} FORCE"
135+
sql "DROP REPOSITORY `${repoName}`"
136+
}
137+

0 commit comments

Comments
 (0)