feat(postgres): export all schemas in one SQL file

This commit is contained in:
zipg authored and GitHub committed 2026-09-07 23:20:46 +08:00
1 parent 0bacb5effd
commit 5efbe360d9
15 files changed
+452 -38

No files matched your search

@@ -59,6 +59,7 @@ const filteredTables = computed(() => {
return tables.value.filter((name) => name.toLowerCase().includes(q));
});
const tableError = ref<string | null>(null);
const POSTGRES_ALL_SCHEMAS = "__DBX_ALL_SCHEMAS__";
// Options
const includeStructure = ref(true);
@@ -70,6 +71,7 @@ const omitAutoIncrement = ref(false);
// `AUTO_INCREMENT` stripping is a MySQL-only DDL transform (backend gates on
// db_type == mysql, which also covers MariaDB / TiDB / OceanBase-MySQL-mode).
const isMysqlFamily = computed(() => store.getConfig(connectionId.value)?.db_type === "mysql");
const isPostgresAllSchemas = computed(() => store.getConfig(connectionId.value)?.db_type === "postgres" && schema.value === POSTGRES_ALL_SCHEMAS);
// Export state
const isExporting = ref(false);
@@ -115,6 +117,7 @@ const canExport = computed(() => {
const hasContent = includeStructure.value || includeData.value || includeObjects.value;
if (!connectionId.value || !hasContent || isExporting.value) return false;
if (exportAllDatabases.value) return selectedDatabases.value.length > 0 && !loadingMeta.value;
if (isPostgresAllSchemas.value) return database.value && schemas.value.length > 0 && !loadingMeta.value;
return (
database.value &&
schema.value &&
@@ -230,6 +233,13 @@ async function loadSchemas(preferredSchema = "") {
}
async function loadTables(preferredTable = "", preferredTables: string[] = []) {
if (schema.value === POSTGRES_ALL_SCHEMAS) {
tables.value = [];
selectedTables.value = [];
loadingTables.value = false;
tableError.value = null;
return;
}
if (!connectionId.value || !database.value || !schema.value) return;
loadingTables.value = true;
tableError.value = null;
@@ -371,9 +381,9 @@ async function startExport() {
exportId: exportId.value,
connectionId: connectionId.value,
database: database.value,
schema: schema.value,
schema: isPostgresAllSchemas.value ? "" : schema.value,
filePath,
selectedTables: includeStructure.value || includeData.value ? buildSelectedTablesPayload(tables.value, selectedTables.value) : undefined,
selectedTables: !isPostgresAllSchemas.value && (includeStructure.value || includeData.value) ? buildSelectedTablesPayload(tables.value, selectedTables.value) : undefined,
includeStructure: includeStructure.value,
includeData: includeData.value,
includeObjects: includeObjects.value,
@@ -737,6 +747,7 @@ watch(schema, (value) => {
const preferredTables = pendingPrefillTables.value;
pendingPrefillTable.value = "";
pendingPrefillTables.value = [];
if (value === POSTGRES_ALL_SCHEMAS) return;
if (value) loadTables(preferredTable, preferredTables).catch((e) => toast(String(e), 5000));
});
@@ -846,12 +857,13 @@ watch(
<SelectValue :placeholder="t('diff.selectSchema')" />
</SelectTrigger>
<SelectContent position="popper" align="start">
<SelectItem v-if="store.getConfig(connectionId)?.db_type === 'postgres'" :value="POSTGRES_ALL_SCHEMAS">{{ t("databaseExport.allSchemas") }}</SelectItem>
<SelectItem v-for="s in schemas" :key="s" :value="s">{{ s }}</SelectItem>
</SelectContent>
</Select>
</div>
<div v-if="!exportAllDatabases && schema" class="space-y-2">
<div v-if="!exportAllDatabases && schema && !isPostgresAllSchemas" class="space-y-2">
<div class="flex items-center justify-between gap-2">
<Label class="text-xs">{{ t("databaseExport.tableSelection") }}</Label>
<div v-if="tables.length" class="text-[11px] text-muted-foreground">
+1
View File
@@ -7708,6 +7708,7 @@ export default {
noTables: "No tables found",
export: "Export",
exportAllDatabases: "Export All Databases",
allSchemas: "All schemas",
exporting: "Exporting...",
preparing: "Preparing export (reading tables and metadata)...",
preparingObject: "Preparing: {object}",
+1
View File
@@ -7290,6 +7290,7 @@ export default withEnglishFallback({
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})",
allSchemas: "Todos los esquemas",
exportError: "Error al exportar: {error}",
exportCancelled: "Exportación cancelada",
filterTables: "Buscar tablas...",
+1
View File
@@ -7292,6 +7292,7 @@ export default withEnglishFallback({
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})",
allSchemas: "Tutti gli schemi",
exportError: "Esportazione non riuscita: {error}",
exportCancelled: "Esportazione annullata",
runInBackground: "Esegui in background",
+1
View File
@@ -7344,6 +7344,7 @@ export default withEnglishFallback({
exportSuccessWithErrors: "エクスポートは完了しましたが、{count} 個のオブジェクトが失敗しました:{firstError}… 詳細はエクスポートファイル内の -- ERROR コメントを確認してください。",
exportAllSuccessWithErrors: "{count} 個のデータベースをエクスポートしましたが、{errorCount} 個のオブジェクトが失敗しました:{firstError}… 詳細はファイル内の -- ERROR コメントを確認してください。",
allDatabasesTask: "すべてのデータベース ({count})",
allSchemas: "すべてのスキーマ",
exportError: "エクスポートに失敗しました: {error}",
exportCancelled: "エクスポートがキャンセルされました",
},
+1
View File
@@ -7000,6 +7000,7 @@ export default withEnglishFallback({
exportSuccessWithErrors: "내보내기가 완료되었지만 {count}개 객체가 실패했습니다: {firstError}… 자세한 내용은 내보낸 파일의 -- ERROR 주석을 참조하세요.",
exportAllSuccessWithErrors: "데이터베이스 {count}개를 내보냈지만 {errorCount}개 객체가 실패했습니다: {firstError}… 자세한 내용은 파일의 -- ERROR 주석을 참조하세요.",
allDatabasesTask: "모든 데이터베이스 ({count})",
allSchemas: "모든 스키마",
exportError: "내보내기 실패: {error}",
exportCancelled: "내보내기 취소됨",
runInBackground: "백그라운드에서 실행",
+1
View File
@@ -7294,6 +7294,7 @@ export default withEnglishFallback({
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})",
allSchemas: "Todos os esquemas",
exportError: "Falha na exportação: {error}",
exportCancelled: "Exportação cancelada",
},
+1
View File
@@ -7616,6 +7616,7 @@ export default withEnglishFallback({
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})",
allSchemas: "Tüm şemalar",
exportError: "Dışa aktarma başarısız: {error}",
exportCancelled: "Dışa aktarma iptal edildi",
runInBackground: "Arka planda çalıştır",
+1
View File
@@ -7689,6 +7689,7 @@ export default withEnglishFallback({
noTables: "未找到表",
export: "导出",
exportAllDatabases: "导出全部数据库",
allSchemas: "全部 Schema",
exporting: "正在导出...",
preparing: "正在准备导出(读取表与元数据)...",
preparingObject: "正在准备: {object}",
+1
View File
@@ -6607,6 +6607,7 @@ export default withEnglishFallback({
exportSuccessWithErrors: "匯出完成,但有 {count} 個物件失敗:{firstError}……詳情見匯出檔案中的 -- ERROR 註解。",
exportAllSuccessWithErrors: "已匯出 {count} 個資料庫,但有 {errorCount} 個物件失敗:{firstError}……詳情見匯出檔案中的 -- ERROR 註解。",
allDatabasesTask: "全部資料庫({count})",
allSchemas: "全部 schema",
exportError: "匯出失敗: {error}",
exportCancelled: "匯出已取消",
runInBackground: "背景執行",
@@ -166,6 +166,17 @@ export function buildAllDatabaseExportPlan(options: AllDatabaseExportPlanInput):
displayName: schema,
}));
}
// PostgreSQL supports multiple schemas in one database. Keep the database
// as the export unit so the backend can produce one restore script for all
// schemas instead of one file per schema.
if (options.dbType === "postgres" && options.schemaAware) {
return options.databases.map((database) => ({
database,
schema: "",
fileStem: database,
displayName: database,
}));
}
return options.databases.flatMap((database) => {
const schemas = options.schemaAware ? filterExportableSchemas(options.schemasByDatabase?.[database] ?? [], options.dbType).filter((schema) => schema.trim()) : [database];
const exportSchemas = schemas.length > 0 ? schemas : [database];