From c2b60623a6699eb9260828db3f9d34edee2f07cf Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 10 Mar 2026 17:05:26 +0800 Subject: [PATCH] fix: avoid FK constraint failure when restoring provider_health during WebDAV sync Split LOCAL_ONLY_TABLES into SYNC_SKIP_TABLES (export) and SYNC_PRESERVE_TABLES (import). provider_health is skipped on export but no longer restored on import, since it has a foreign key on providers(id, app_type) that may not match the remote dataset. Health data is ephemeral and rebuilds automatically at runtime. --- src-tauri/src/database/backup.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/database/backup.rs b/src-tauri/src/database/backup.rs index 415d3649e..9438615ba 100644 --- a/src-tauri/src/database/backup.rs +++ b/src-tauri/src/database/backup.rs @@ -15,9 +15,8 @@ use tempfile::NamedTempFile; const CC_SWITCH_SQL_EXPORT_HEADER: &str = "-- CC Switch SQLite 导出"; -/// Tables that are local-only (not synced via WebDAV snapshots). -/// Schema is still exported, but data rows are skipped. -const LOCAL_ONLY_TABLES: &[&str] = &[ +/// Tables whose data rows are skipped when exporting for WebDAV sync. +const SYNC_SKIP_TABLES: &[&str] = &[ "proxy_request_logs", "stream_check_logs", "provider_health", @@ -25,6 +24,15 @@ const LOCAL_ONLY_TABLES: &[&str] = &[ "usage_daily_rollups", ]; +/// Tables whose local data is preserved (restored from local snapshot) during WebDAV import. +/// Excludes ephemeral tables like provider_health that can safely rebuild at runtime. +const SYNC_PRESERVE_TABLES: &[&str] = &[ + "proxy_request_logs", + "stream_check_logs", + "proxy_live_backup", + "usage_daily_rollups", +]; + /// A database backup entry for the UI #[derive(Debug, serde::Serialize)] #[serde(rename_all = "camelCase")] @@ -44,7 +52,7 @@ impl Database { /// Export SQL for sync (WebDAV), skipping local-only tables' data pub fn export_sql_string_for_sync(&self) -> Result { let snapshot = self.snapshot_to_memory()?; - Self::dump_sql(&snapshot, LOCAL_ONLY_TABLES) + Self::dump_sql(&snapshot, SYNC_SKIP_TABLES) } /// 导出为 SQLite 兼容的 SQL 文本 @@ -80,7 +88,7 @@ impl Database { /// Import SQL generated for sync, then restore local-only tables from the /// current device snapshot before replacing the main database. pub(crate) fn import_sql_string_for_sync(&self, sql_raw: &str) -> Result { - self.import_sql_string_inner(sql_raw, LOCAL_ONLY_TABLES) + self.import_sql_string_inner(sql_raw, SYNC_PRESERVE_TABLES) } fn import_sql_string_inner(