fix(export): surface lenient per-object failures in export completion

Closes #8184
This commit is contained in:
t8y2 committed 2026-09-05 10:04:22 +08:00
1 parent 116aced217
commit f661ff7ff3
14 files changed
+194 -9

No files matched your search

@@ -152,6 +152,17 @@ function joinExportPath(directory: string, fileName: string): string {
return `${directory.replace(/[\\/]+$/, "")}${separator}${fileName}`;
}
// Lenient exports write per-object failures into the SQL file as `-- ERROR`
// comments and still finish; completion must warn instead of reporting plain
// success (#8184).
function toastDatabaseExportCompletion(errorCount: number, errorSummary: string | null) {
if (errorCount > 0) {
toast(t("databaseExport.exportSuccessWithErrors", { count: errorCount, firstError: errorSummary ?? "" }), 8000);
return;
}
toast(t("databaseExport.exportSuccess"), 3000);
}
async function loadDatabases(connId: string) {
if (!connId) return;
loadingMeta.value = true;
@@ -370,7 +381,7 @@ async function startExport() {
finishExportTiming();
exportDone.value = true;
isExporting.value = false;
toast(t("databaseExport.exportSuccess"), 3000);
toastDatabaseExportCompletion(progress.errorCount ?? 0, progress.errorSummary ?? null);
} else if (progress.status === "Error") {
finishExportTiming();
exportError.value = progress.error;
@@ -432,6 +443,8 @@ async function startAllDatabasesExport() {
exportCancelled.value = false;
batchDatabaseIndex.value = 0;
batchRowsExported.value = 0;
let batchLenientErrorCount = 0;
let batchFirstErrorSummary: string | null = null;
const dbs = [...selectedDatabases.value];
const connectionType = store.getConfig(connectionId.value)?.db_type;
@@ -475,7 +488,7 @@ async function startAllDatabasesExport() {
const filePath = isTauriRuntime() ? joinExportPath(directoryPath, `${sanitizeFileName(item.fileStem)}.sql`) : `__web_export_${currentExportId}.sql`;
let currentDatabaseRowsExported = 0;
await runWithDatabaseBackupSnapshot(
const terminal = await runWithDatabaseBackupSnapshot(
{
connectionId: connectionId.value,
database: item.database,
@@ -530,6 +543,8 @@ async function startAllDatabasesExport() {
(terminal) => terminal.status === "Done",
);
batchLenientErrorCount += terminal.errorCount ?? 0;
batchFirstErrorSummary ??= terminal.errorSummary ?? null;
if (exportError.value || exportCancelled.value) break;
activeDatabaseExportId.value = "";
}
@@ -547,10 +562,16 @@ async function startAllDatabasesExport() {
totalRows: null,
status: "Done",
error: null,
errorCount: batchLenientErrorCount,
errorSummary: batchFirstErrorSummary,
};
exportProgress.value = finalProgress;
updateDatabaseExportTask(batchId, finalProgress);
toast(t("databaseExport.exportAllSuccess", { count: dbs.length }), 3000);
if (batchLenientErrorCount > 0) {
toast(t("databaseExport.exportAllSuccessWithErrors", { count: dbs.length, errorCount: batchLenientErrorCount, firstError: batchFirstErrorSummary ?? "" }), 8000);
} else {
toast(t("databaseExport.exportAllSuccess", { count: dbs.length }), 3000);
}
}
} catch (e: any) {
exportError.value = e?.message || String(e);
+2
View File
@@ -7560,6 +7560,8 @@ export default {
allRowsExported: "Total rows exported: {count}",
exportSuccess: "Database exported successfully",
exportAllSuccess: "{count} databases exported successfully",
exportSuccessWithErrors: "Export finished with {count} failed object(s): {firstError}… See the -- ERROR comments inside the exported file for details.",
exportAllSuccessWithErrors: "{count} databases exported, but {errorCount} object(s) failed: {firstError}… See the -- ERROR comments inside the exported files.",
allDatabasesTask: "All databases ({count})",
exportError: "Export failed: {error}",
exportCancelled: "Export cancelled",
+2
View File
@@ -7214,6 +7214,8 @@ export default withEnglishFallback({
allRowsExported: "Total de filas exportadas: {count}",
exportSuccess: "Base de datos exportada exitosamente",
exportAllSuccess: "{count} bases de datos exportadas exitosamente",
exportSuccessWithErrors: "La exportación terminó con {count} objeto(s) fallidos: {firstError}… Consulta los comentarios -- ERROR en el archivo exportado.",
exportAllSuccessWithErrors: "Se exportaron {count} bases de datos, pero {errorCount} objeto(s) fallaron: {firstError}… Consulta los comentarios -- ERROR en los archivos.",
allDatabasesTask: "Todas las bases de datos ({count})",
exportError: "Error al exportar: {error}",
exportCancelled: "Exportación cancelada",
+2
View File
@@ -7216,6 +7216,8 @@ export default withEnglishFallback({
allRowsExported: "Totale righe esportate: {count}",
exportSuccess: "Database esportato con successo",
exportAllSuccess: "{count} database esportati con successo",
exportSuccessWithErrors: "Esportazione completata con {count} oggetti non riusciti: {firstError}… Dettagli nei commenti -- ERROR nel file esportato.",
exportAllSuccessWithErrors: "Esportati {count} database, ma {errorCount} oggetti non riusciti: {firstError}… Dettagli nei commenti -- ERROR nei file.",
allDatabasesTask: "Tutti i database ({count})",
exportError: "Esportazione non riuscita: {error}",
exportCancelled: "Esportazione annullata",
+2
View File
@@ -7268,6 +7268,8 @@ export default withEnglishFallback({
allRowsExported: "累計エクスポート行数: {count}",
exportSuccess: "データベースを正常にエクスポートしました",
exportAllSuccess: "{count}個のデータベースを正常にエクスポートしました",
exportSuccessWithErrors: "エクスポートは完了しましたが、{count} 個のオブジェクトが失敗しました:{firstError}… 詳細はエクスポートファイル内の -- ERROR コメントを確認してください。",
exportAllSuccessWithErrors: "{count} 個のデータベースをエクスポートしましたが、{errorCount} 個のオブジェクトが失敗しました:{firstError}… 詳細はファイル内の -- ERROR コメントを確認してください。",
allDatabasesTask: "すべてのデータベース ({count})",
exportError: "エクスポートに失敗しました: {error}",
exportCancelled: "エクスポートがキャンセルされました",
+2
View File
@@ -6924,6 +6924,8 @@ export default withEnglishFallback({
allRowsExported: "총 내보낸 행: {count}",
exportSuccess: "데이터베이스를 성공적으로 내보냈습니다",
exportAllSuccess: "데이터베이스 {count}개를 성공적으로 내보냈습니다",
exportSuccessWithErrors: "내보내기가 완료되었지만 {count}개 객체가 실패했습니다: {firstError}… 자세한 내용은 내보낸 파일의 -- ERROR 주석을 참조하세요.",
exportAllSuccessWithErrors: "데이터베이스 {count}개를 내보냈지만 {errorCount}개 객체가 실패했습니다: {firstError}… 자세한 내용은 파일의 -- ERROR 주석을 참조하세요.",
allDatabasesTask: "모든 데이터베이스 ({count})",
exportError: "내보내기 실패: {error}",
exportCancelled: "내보내기 취소됨",
+2
View File
@@ -7218,6 +7218,8 @@ export default withEnglishFallback({
allRowsExported: "Total de linhas exportadas: {count}",
exportSuccess: "Banco de dados exportado com sucesso",
exportAllSuccess: "{count} bancos de dados exportados com sucesso",
exportSuccessWithErrors: "A exportação terminou com {count} objeto(s) com falha: {firstError}… Veja os comentários -- ERROR no arquivo exportado.",
exportAllSuccessWithErrors: "{count} bancos de dados exportados, mas {errorCount} objeto(s) falharam: {firstError}… Veja os comentários -- ERROR nos arquivos.",
allDatabasesTask: "Todos os bancos de dados ({count})",
exportError: "Falha na exportação: {error}",
exportCancelled: "Exportação cancelada",
+2
View File
@@ -7550,6 +7550,8 @@ export default withEnglishFallback({
allRowsExported: "Dışa aktarılan toplam satır: {count}",
exportSuccess: "Veritabanı başarıyla dışa aktarıldı",
exportAllSuccess: "{count} veritabanı başarıyla dışa aktarıldı",
exportSuccessWithErrors: "Dışa aktarma tamamlandı ancak {count} nesne başarısız oldu: {firstError}… Ayrıntılar için dışa aktarılan dosyadaki -- ERROR yorumlarına bakın.",
exportAllSuccessWithErrors: "{count} veritabanı dışa aktarıldı ancak {errorCount} nesne başarısız oldu: {firstError}… Ayrıntılar için dosyalardaki -- ERROR yorumlarına bakın.",
allDatabasesTask: "Tüm veritabanları ({count})",
exportError: "Dışa aktarma başarısız: {error}",
exportCancelled: "Dışa aktarma iptal edildi",
+2
View File
@@ -7541,6 +7541,8 @@ export default withEnglishFallback({
allRowsExported: "累计已导出 {count} 行",
exportSuccess: "数据库导出成功",
exportAllSuccess: "已成功导出 {count} 个数据库",
exportSuccessWithErrors: "导出完成,但有 {count} 个对象失败:{firstError}……详情见导出文件中的 -- ERROR 注释。",
exportAllSuccessWithErrors: "已导出 {count} 个数据库,但有 {errorCount} 个对象失败:{firstError}……详情见导出文件中的 -- ERROR 注释。",
allDatabasesTask: "全部数据库({count})",
exportError: "导出失败: {error}",
exportCancelled: "导出已取消",
+2
View File
@@ -6531,6 +6531,8 @@ export default withEnglishFallback({
allRowsExported: "累計已匯出 {count} 列",
exportSuccess: "資料庫匯出成功",
exportAllSuccess: "已成功匯出 {count} 個資料庫",
exportSuccessWithErrors: "匯出完成,但有 {count} 個物件失敗:{firstError}……詳情見匯出檔案中的 -- ERROR 註解。",
exportAllSuccessWithErrors: "已匯出 {count} 個資料庫,但有 {errorCount} 個物件失敗:{firstError}……詳情見匯出檔案中的 -- ERROR 註解。",
allDatabasesTask: "全部資料庫({count})",
exportError: "匯出失敗: {error}",
exportCancelled: "匯出已取消",
+4
View File
@@ -4825,6 +4825,10 @@ export interface ExportProgress {
error: string | null;
/** True while listing schema / prefetching metadata before objects are written. */
preparing?: boolean;
/** Per-object failures written into the file as `-- ERROR` comments (lenient mode). */
errorCount?: number;
/** First lenient failure, for completion warnings without opening the file. */
errorSummary?: string | null;
}
// --- Table Export ---