feat(postgres): export all schemas in one SQL file
This commit is contained in:
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">
|
||||
|
||||
@@ -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}",
|
||||
|
||||
@@ -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...",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -7344,6 +7344,7 @@ export default withEnglishFallback({
|
||||
exportSuccessWithErrors: "エクスポートは完了しましたが、{count} 個のオブジェクトが失敗しました:{firstError}… 詳細はエクスポートファイル内の -- ERROR コメントを確認してください。",
|
||||
exportAllSuccessWithErrors: "{count} 個のデータベースをエクスポートしましたが、{errorCount} 個のオブジェクトが失敗しました:{firstError}… 詳細はファイル内の -- ERROR コメントを確認してください。",
|
||||
allDatabasesTask: "すべてのデータベース ({count})",
|
||||
allSchemas: "すべてのスキーマ",
|
||||
exportError: "エクスポートに失敗しました: {error}",
|
||||
exportCancelled: "エクスポートがキャンセルされました",
|
||||
},
|
||||
|
||||
@@ -7000,6 +7000,7 @@ export default withEnglishFallback({
|
||||
exportSuccessWithErrors: "내보내기가 완료되었지만 {count}개 객체가 실패했습니다: {firstError}… 자세한 내용은 내보낸 파일의 -- ERROR 주석을 참조하세요.",
|
||||
exportAllSuccessWithErrors: "데이터베이스 {count}개를 내보냈지만 {errorCount}개 객체가 실패했습니다: {firstError}… 자세한 내용은 파일의 -- ERROR 주석을 참조하세요.",
|
||||
allDatabasesTask: "모든 데이터베이스 ({count})",
|
||||
allSchemas: "모든 스키마",
|
||||
exportError: "내보내기 실패: {error}",
|
||||
exportCancelled: "내보내기 취소됨",
|
||||
runInBackground: "백그라운드에서 실행",
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -7689,6 +7689,7 @@ export default withEnglishFallback({
|
||||
noTables: "未找到表",
|
||||
export: "导出",
|
||||
exportAllDatabases: "导出全部数据库",
|
||||
allSchemas: "全部 Schema",
|
||||
exporting: "正在导出...",
|
||||
preparing: "正在准备导出(读取表与元数据)...",
|
||||
preparingObject: "正在准备: {object}",
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in new issue
Block a user