diff --git a/apps/desktop/src/components/transfer/DataTransferDialog.vue b/apps/desktop/src/components/transfer/DataTransferDialog.vue index f015c1211..e765ba008 100644 --- a/apps/desktop/src/components/transfer/DataTransferDialog.vue +++ b/apps/desktop/src/components/transfer/DataTransferDialog.vue @@ -32,6 +32,7 @@ const sqlConnections = computed(() => store.connections.filter((c) => supportsTr const sourceConnectionId = ref(""); const sourceDatabase = ref(""); const sourceDatabases = ref([]); +const sourceSchemas = ref([]); const sourceSchema = ref(""); const sourceTables = ref([]); const selectedTables = ref>(new Set()); @@ -42,6 +43,7 @@ const loadingTables = ref(false); const targetConnectionId = ref(""); const targetDatabase = ref(""); const targetDatabases = ref([]); +const targetSchemas = ref([]); const targetSchema = ref(""); // Options @@ -112,6 +114,34 @@ async function loadDatabases(connectionId: string, target: "source" | "target") } } +async function loadSchemas(connectionId: string, database: string, side: "source" | "target", preferredSchema = "") { + if (!connectionId || !database) return; + try { + const schemas = await api.listSchemas(connectionId, database); + const selected = + preferredSchema && schemas.includes(preferredSchema) + ? preferredSchema + : schemas.includes("public") + ? "public" + : (schemas[0] ?? ""); + if (side === "source") { + sourceSchemas.value = schemas; + sourceSchema.value = selected; + } else { + targetSchemas.value = schemas; + targetSchema.value = selected; + } + } catch { + if (side === "source") { + sourceSchemas.value = []; + sourceSchema.value = ""; + } else { + targetSchemas.value = []; + targetSchema.value = ""; + } + } +} + async function loadTables() { if (!sourceConnectionId.value || !sourceDatabase.value) { sourceTables.value = []; @@ -121,13 +151,8 @@ async function loadTables() { try { const config = store.getConfig(sourceConnectionId.value); const needsSchema = isSchemaAware(config?.db_type); - if (needsSchema) { - const schemas = await api.listSchemas(sourceConnectionId.value, sourceDatabase.value); - sourceSchema.value = schemas.includes("public") ? "public" : (schemas[0] ?? ""); - } else { - sourceSchema.value = sourceDatabase.value; - } - const tables = await api.listTables(sourceConnectionId.value, sourceDatabase.value, sourceSchema.value); + const schema = needsSchema && sourceSchema.value ? sourceSchema.value : sourceDatabase.value; + const tables = await api.listTables(sourceConnectionId.value, sourceDatabase.value, schema); sourceTables.value = tables .filter((t) => t.table_type === "TABLE" || t.table_type === "BASE TABLE") .map((t) => t.name); @@ -152,13 +177,37 @@ watch(sourceConnectionId, (id) => { loadDatabases(id, "source"); }); -watch(sourceDatabase, () => loadTables()); +watch(sourceDatabase, async (db) => { + if (db) { + const config = store.getConfig(sourceConnectionId.value); + if (isSchemaAware(config?.db_type)) { + await loadSchemas(sourceConnectionId.value, db, "source"); + } else { + sourceSchema.value = db; + } + } +}); + +watch(sourceSchema, () => loadTables()); watch(targetConnectionId, (id) => { targetDatabase.value = ""; + targetSchemas.value = []; + targetSchema.value = ""; loadDatabases(id, "target"); }); +watch(targetDatabase, async (db) => { + if (db) { + const config = store.getConfig(targetConnectionId.value); + if (isSchemaAware(config?.db_type)) { + await loadSchemas(targetConnectionId.value, db, "target"); + } else { + targetSchema.value = db; + } + } +}); + watch( open, async (val) => { @@ -181,6 +230,7 @@ function resetState() { sourceConnectionId.value = ""; sourceDatabase.value = ""; sourceDatabases.value = []; + sourceSchemas.value = []; sourceSchema.value = ""; sourceTables.value = []; selectedTables.value.clear(); @@ -188,6 +238,7 @@ function resetState() { targetConnectionId.value = ""; targetDatabase.value = ""; targetDatabases.value = []; + targetSchemas.value = []; targetSchema.value = ""; createTable.value = true; transferMode.value = "append"; @@ -209,21 +260,8 @@ async function startTransfer() { transferId.value = uuid(); - // Auto-detect target schema - const targetConfig = store.getConfig(targetConnectionId.value); - const targetNeedsSchema = isSchemaAware(targetConfig?.db_type); - const sourceConfig = store.getConfig(sourceConnectionId.value); - const sourceNeedsSchema = isSchemaAware(sourceConfig?.db_type); - if (targetNeedsSchema && !targetSchema.value) { - try { - const schemas = await api.listSchemas(targetConnectionId.value, targetDatabase.value); - targetSchema.value = schemas.includes("public") ? "public" : (schemas[0] ?? ""); - } catch { - /* use empty */ - } - } - const effectiveSourceSchema = sourceNeedsSchema ? sourceSchema.value : sourceDatabase.value; - const effectiveTargetSchema = targetNeedsSchema ? targetSchema.value : targetDatabase.value; + const effectiveSourceSchema = sourceSchema.value || sourceDatabase.value; + const effectiveTargetSchema = targetSchema.value || targetDatabase.value; const request: api.TransferRequest = { transferId: transferId.value, @@ -340,6 +378,18 @@ const totalTransferred = computed(() => + +
+ + +
@@ -382,6 +432,18 @@ const totalTransferred = computed(() => + +
+ + +
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 20e190707..a95422a7d 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -1195,8 +1195,10 @@ export default { target: "Target", sourceConnection: "Source Connection", sourceDatabase: "Source Database", + sourceSchema: "Source Schema", targetConnection: "Target Connection", targetDatabase: "Target Database", + targetSchema: "Target Schema", tables: "Tables", selectAll: "Select All", deselectAll: "Deselect All", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index 6adab3a5e..091d5d7c6 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -1171,8 +1171,10 @@ export default { target: "目标", sourceConnection: "源连接", sourceDatabase: "源数据库", + sourceSchema: "源 Schema", targetConnection: "目标连接", targetDatabase: "目标数据库", + targetSchema: "目标 Schema", tables: "表", selectAll: "全选", deselectAll: "取消全选",