nooneuse commented on code in PR #66307:
URL: https://github.com/apache/doris/pull/66307#discussion_r3849972555


##########
fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java:
##########
@@ -2586,154 +2651,184 @@ protected void cleanMetaObjects(boolean isReplay) {
     }
 
     private Status atomicReplaceOlapTables(Database db, boolean isReplay) {
+        Preconditions.checkState(db.isWriteLockHeldByCurrentThread(),
+                "atomic replacement must hold the database write lock");
+        Status validationStatus = prevalidateAtomicRestoreTargets(db);
+        if (!validationStatus.ok()) {
+            return validationStatus;
+        }
+        try {
+            
Env.getCurrentEnv().getConstraintManager().checkAndDropTableConstraints(
+                    getAtomicRestoreConstraintDropTargets(db), 
!isForceReplace);
+        } catch (DdlException e) {
+            return new Status(ErrCode.COMMON_ERROR,
+                    "replace table failed, reason=" + e.getMessage());
+        }
         for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
-            String originName = jobInfo.getAliasByOriginNameIfSet(tableName);
-            if (GlobalVariable.isStoredTableNamesLowerCase()) {
-                originName = originName.toLowerCase();
-            }
+            String originName = restoreTargetName(tableName);
             String aliasName = tableAliasWithAtomicRestore(originName);
 
-            if (!db.writeLockIfExist()) {
-                return Status.OK;
-            }
+            Table newTbl = db.getTableNullable(aliasName);
+            Preconditions.checkNotNull(newTbl);
+            Preconditions.checkState(newTbl.getType() == TableType.OLAP);
+            Table originTbl = db.getTableNullable(originName);
+            Preconditions.checkState(originTbl == null
+                    || originTbl.getType() == TableType.OLAP);
+            OlapTable originOlapTbl = (OlapTable) originTbl;
+
+            // replace the table.
+            OlapTable newOlapTbl = (OlapTable) newTbl;
+            newOlapTbl.writeLock();
             try {
-                Table newTbl = db.getTableNullable(aliasName);
-                if (newTbl == null) {
-                    LOG.warn("replace table from {} to {}, but the temp table 
is not found" + " isAtomicRestore: {}",
-                            aliasName, originName, isAtomicRestore);
-                    return new Status(ErrCode.COMMON_ERROR, "replace table 
failed, the temp table "
-                            + aliasName + " is not found");
-                }
-                if (newTbl.getType() != TableType.OLAP) {
-                    LOG.warn(
-                            "replace table from {} to {}, but the temp table 
is not OLAP, it type is {}"
-                                    + " isAtomicRestore: {}",
-                            aliasName, originName, newTbl.getType(), 
isAtomicRestore);
-                    return new Status(ErrCode.COMMON_ERROR, "replace table 
failed, the temp table " + aliasName
-                            + " is not OLAP table, it is " + newTbl.getType());
-                }
-
-                OlapTable originOlapTbl = null;
-                Table originTbl = db.getTableNullable(originName);
-                if (originTbl != null) {
-                    if (originTbl.getType() != TableType.OLAP) {
-                        LOG.warn(
-                                "replace table from {} to {}, but the origin 
table is not OLAP, it type is {}"
-                                        + " isAtomicRestore: {}",
-                                aliasName, originName, originTbl.getType(), 
isAtomicRestore);
-                        return new Status(ErrCode.COMMON_ERROR, "replace table 
failed, the origin table "
-                                + originName + " is not OLAP table, it is " + 
originTbl.getType());
-                    }
-                    originOlapTbl = (OlapTable) originTbl; // save the origin 
olap table, then drop it.
-                }
+                TableNameInfo originTableInfo = new TableNameInfo(
+                        InternalCatalog.INTERNAL_CATALOG_NAME, 
db.getFullName(), originName);
+                // rename new table name to origin table name and add the new 
table to database.
+                db.unregisterTable(aliasName);
+                newOlapTbl.setName(originName);
+                db.unregisterTable(originName);
+                db.registerTable(newOlapTbl);
+                
Env.getCurrentEnv().getConstraintManager().restoreTableConstraints(
+                        originTableInfo, newOlapTbl);
+                Env.getCurrentEnv().getSqlCacheManager()
+                        
.invalidateAboutTableAndFencePublication(originTableInfo);
+
+                // set the olap table state to normal immediately for querying
+                newOlapTbl.setState(OlapTableState.NORMAL);
+                LOG.info(
+                        "restore with replace table {} name to {}, and set 
state to normal, origin table={}"
+                                + " isAtomicRestore: {}",
+                        newOlapTbl.getId(), originName,
+                        originOlapTbl == null ? -1L : originOlapTbl.getId(),
+                        isAtomicRestore);
+            } finally {
+                newOlapTbl.writeUnlock();
+            }
 
-                // replace the table.
-                OlapTable newOlapTbl = (OlapTable) newTbl;
-                newOlapTbl.writeLock();
+            if (originOlapTbl != null) {
+                // The origin table is not used anymore, need to drop all its 
tablets.
+                originOlapTbl.writeLock();
                 try {
-                    // rename new table name to origin table name and add the 
new table to database.
-                    db.unregisterTable(aliasName);
-                    newOlapTbl.checkAndSetName(originName, false);
-                    db.unregisterTable(originName);
-                    db.registerTable(newOlapTbl);
-
-                    // set the olap table state to normal immediately for 
querying
-                    newOlapTbl.setState(OlapTableState.NORMAL);
-                    LOG.info(
-                            "restore with replace table {} name to {}, and set 
state to normal, origin table={}"
-                                    + " isAtomicRestore: {}",
-                            newOlapTbl.getId(), originName, originOlapTbl == 
null ? -1L : originOlapTbl.getId(),
-                            isAtomicRestore);
-                } catch (DdlException e) {
-                    LOG.warn("restore with replace table {} name from {} to 
{}, isAtomicRestore: {}",
-                            newOlapTbl.getId(), aliasName, originName, 
isAtomicRestore, e);
-                    return new Status(ErrCode.COMMON_ERROR, "replace table 
from " + aliasName + " to " + originName
-                            + " failed, reason=" + e.getMessage());
+                    LOG.info("drop the origin olap table {}. table={}" + " 
isAtomicRestore: {}",
+                            originOlapTbl.getName(), originOlapTbl.getId(), 
isAtomicRestore);
+                    Env.getCurrentEnv().onEraseOlapTable(db.getId(), 
originOlapTbl, isReplay);
                 } finally {
-                    newOlapTbl.writeUnlock();
+                    originOlapTbl.writeUnlock();
                 }
-
-                if (originOlapTbl != null) {
-                    // The origin table is not used anymore, need to drop all 
its tablets.
-                    originOlapTbl.writeLock();
-                    try {
-                        LOG.info("drop the origin olap table {}. table={}" + " 
isAtomicRestore: {}",
-                                originOlapTbl.getName(), 
originOlapTbl.getId(), isAtomicRestore);
-                        Env.getCurrentEnv().onEraseOlapTable(db.getId(), 
originOlapTbl, isReplay);
-                    } finally {
-                        originOlapTbl.writeUnlock();
-                    }
-                }
-            } finally {
-                db.writeUnlock();
             }
         }
         for (BackupJobInfo.BackupViewInfo backupViewInfo : 
jobInfo.newBackupObjects.views) {
-            String originName = 
jobInfo.getAliasByOriginNameIfSet(backupViewInfo.name);
-            if (GlobalVariable.isStoredTableNamesLowerCase()) {
-                originName = originName.toLowerCase();
-            }
+            String originName = restoreTargetName(backupViewInfo.name);
             String aliasName = tableAliasWithAtomicRestore(originName);
 
-            if (!db.writeLockIfExist()) {
-                return Status.OK;
-            }
+            Table newTbl = db.getTableNullable(aliasName);
+            Preconditions.checkNotNull(newTbl);
+            Preconditions.checkState(newTbl.getType() == TableType.VIEW);
+            Table originTbl = db.getTableNullable(originName);
+            Preconditions.checkState(originTbl == null
+                    || originTbl.getType() == TableType.VIEW);
+            View originViewTbl = (View) originTbl;
+
+            // replace the view.
+            View newViewTbl = (View) newTbl;
+            newViewTbl.writeLock();
             try {
-                Table newTbl = db.getTableNullable(aliasName);
-                if (newTbl == null) {
-                    LOG.warn("replace view from {} to {}, but the temp view is 
not found" + " isAtomicRestore: {}",
-                            aliasName, originName, isAtomicRestore);
-                    return new Status(ErrCode.COMMON_ERROR, "replace view 
failed, the temp view "
-                            + aliasName + " is not found");
-                }
-                if (newTbl.getType() != TableType.VIEW) {
-                    LOG.warn(
-                            "replace view from {} to {}, but the temp view is 
not VIEW, it type is {}"
-                                    + " isAtomicRestore: {}",
-                            aliasName, originName, newTbl.getType(), 
isAtomicRestore);
-                    return new Status(ErrCode.COMMON_ERROR, "replace view 
failed, the temp view " + aliasName
-                            + " is not OLAP, it is " + newTbl.getType());
-                }
+                // rename new view name to origin view name and add the new 
view to database.
+                db.unregisterTable(aliasName);
+                db.unregisterTable(originName);
+                newViewTbl.setName(originName);
+                db.registerTable(newViewTbl);
+
+                LOG.info(
+                        "restore with replace view {} name to {}, origin 
view={}"
+                                + " isAtomicRestore: {}",
+                        newViewTbl.getId(), originName,
+                        originViewTbl == null ? -1L : originViewTbl.getId(),
+                        isAtomicRestore);
+            } finally {
+                newViewTbl.writeUnlock();
+            }
+        }
 
-                View originViewTbl = null;
-                Table originTbl = db.getTableNullable(originName);
-                if (originTbl != null) {
-                    if (originTbl.getType() != TableType.VIEW) {
-                        LOG.warn(
-                                "replace view from {} to {}, but the origin 
view is not VIEW, it type is {}"
-                                        + " isAtomicRestore: {}",
-                                aliasName, originName, originTbl.getType(), 
isAtomicRestore);
-                        return new Status(ErrCode.COMMON_ERROR, "replace view 
failed, the origin view "
-                                + originName + " is not VIEW, it is " + 
originTbl.getType());
-                    }
-                    originViewTbl = (View) originTbl; // save the origin view, 
then drop it.
-                }
+        return Status.OK;
+    }
 
-                // replace the view.
-                View newViewTbl = (View) newTbl;
-                newViewTbl.writeLock();
-                try {
-                    // rename new view name to origin view name and add the 
new view to database.
-                    db.unregisterTable(aliasName);
-                    db.unregisterTable(originName);
-                    newViewTbl.setName(originName);
-                    db.registerTable(newViewTbl);
-
-                    LOG.info(
-                            "restore with replace view {} name to {}, origin 
view={}"
-                                    + " isAtomicRestore: {}",
-                            newViewTbl.getId(), originName,
-                            originViewTbl == null ? -1L : 
originViewTbl.getId(),
-                            isAtomicRestore);
-                } finally {
-                    newViewTbl.writeUnlock();
+    private Status prevalidateAtomicRestoreTargets(Database db) {
+        for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
+            String originName = restoreTargetName(tableName);
+            String aliasName = tableAliasWithAtomicRestore(originName);
+            Table newTable = db.getTableNullable(aliasName);
+            if (newTable == null) {
+                return new Status(ErrCode.COMMON_ERROR,
+                        "replace table failed, the temp table " + aliasName + 
" is not found");
+            }
+            if (newTable.getType() != TableType.OLAP) {
+                return new Status(ErrCode.COMMON_ERROR, "replace table failed, 
the temp table "
+                        + aliasName + " is not OLAP table, it is " + 
newTable.getType());
+            }
+            try {
+                ((OlapTable) newTable).checkAndSetName(originName, true);
+            } catch (DdlException e) {
+                return new Status(ErrCode.COMMON_ERROR, "replace table failed, 
the temp table "
+                        + aliasName + " cannot be renamed to " + originName
+                        + ", reason=" + e.getMessage());
+            }
+            Table originTable = db.getTableNullable(originName);
+            if (originTable != null && originTable.getType() != 
TableType.OLAP) {
+                return new Status(ErrCode.COMMON_ERROR, "replace table failed, 
the origin table "
+                        + originName + " is not OLAP table, it is " + 
originTable.getType());
+            }
+        }
+        for (BackupJobInfo.BackupViewInfo backupViewInfo : 
jobInfo.newBackupObjects.views) {
+            String originName = restoreTargetName(backupViewInfo.name);
+            String aliasName = tableAliasWithAtomicRestore(originName);
+            Table newView = db.getTableNullable(aliasName);
+            if (newView == null) {
+                return new Status(ErrCode.COMMON_ERROR,
+                        "replace view failed, the temp view " + aliasName + " 
is not found");
+            }
+            if (newView.getType() != TableType.VIEW) {
+                return new Status(ErrCode.COMMON_ERROR, "replace view failed, 
the temp view "
+                        + aliasName + " is not VIEW, it is " + 
newView.getType());
+            }
+            Table originView = db.getTableNullable(originName);
+            if (originView != null && originView.getType() != TableType.VIEW) {
+                return new Status(ErrCode.COMMON_ERROR, "replace view failed, 
the origin view "
+                        + originName + " is not VIEW, it is " + 
originView.getType());
+            }
+        }
+        return Status.OK;
+    }
+
+    private List<TableNameInfo> getAtomicRestoreConstraintDropTargets(Database 
db) {
+        Set<String> tableNames = Sets.newLinkedHashSet();
+        for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
+            String originName = restoreTargetName(tableName);
+            tableNames.add(originName);
+            tableNames.add(tableAliasWithAtomicRestore(originName));
+        }
+        for (BackupJobInfo.BackupViewInfo view : 
jobInfo.newBackupObjects.views) {
+            String originName = restoreTargetName(view.name);
+            tableNames.add(originName);
+            tableNames.add(tableAliasWithAtomicRestore(originName));
+        }
+        if (isCleanTables) {

Review Comment:
   alright. 



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/MetastoreEventSyncDriver.java:
##########
@@ -276,6 +293,8 @@ private void applyOne(PluginDrivenExternalCatalog catalog, 
Connector connector,
             case UNREGISTER_TABLE:
                 catalogMgr.unregisterExternalTableFromEvent(
                         before.localDbName, before.localTableName, 
catalogName);
+                
Env.getCurrentEnv().getConstraintManager().dropTableConstraints(

Review Comment:
   alright. And I found a catalog-level drop/rename issue, also fixed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to