diff --git a/src/components/diff/DataCompareDialog.vue b/src/components/diff/DataCompareDialog.vue index 192a928c6b..57f2035173 100644 --- a/src/components/diff/DataCompareDialog.vue +++ b/src/components/diff/DataCompareDialog.vue @@ -17,7 +17,7 @@ import { } from "@/lib/dataCompare"; import * as api from "@/lib/api"; import DatabaseIcon from "@/components/icons/DatabaseIcon.vue"; -import { Copy, GitCompareArrows, Loader2, Play } from "lucide-vue-next"; +import { Copy, GitCompareArrows, Loader2, Play, ArrowLeftRight } from "lucide-vue-next"; const { t } = useI18n(); const { toast } = useToast(); @@ -56,6 +56,9 @@ const syncSql = ref(""); const syncStatements = ref([]); const comparing = ref(false); const executing = ref(false); +const executedCount = ref(0); +const executeTotal = ref(0); +const syncErrors = ref<{ sql: string; error: string }[]>([]); const rowLimitOptions = [1000, 5000, 10000, 50000]; const sqlConnections = computed(() => @@ -96,6 +99,31 @@ function connectionIconType(connectionId: string) { return config?.driver_profile || config?.db_type || "mysql"; } +function swapSourceTarget() { + const tmpConnId = sourceConnectionId.value; + const tmpDb = sourceDatabase.value; + const tmpDbs = sourceDatabases.value; + const tmpSchema = sourceSchema.value; + const tmpSchemas = sourceSchemas.value; + const tmpTable = sourceTable.value; + const tmpTables = sourceTables.value; + sourceConnectionId.value = targetConnectionId.value; + sourceDatabase.value = targetDatabase.value; + sourceDatabases.value = targetDatabases.value; + sourceSchema.value = targetSchema.value; + sourceSchemas.value = targetSchemas.value; + sourceTable.value = targetTable.value; + sourceTables.value = targetTables.value; + targetConnectionId.value = tmpConnId; + targetDatabase.value = tmpDb; + targetDatabases.value = tmpDbs; + targetSchema.value = tmpSchema; + targetSchemas.value = tmpSchemas; + targetTable.value = tmpTable; + targetTables.value = tmpTables; + clearResult(); +} + async function resolveSchema(connectionId: string, database: string, preferredSchema = ""): Promise { const config = store.getConfig(connectionId); if (isSchemaAware(config?.db_type)) { @@ -305,14 +333,25 @@ async function copySql() { async function executeSql() { if (!syncSql.value.trim() || syncStatements.value.length === 0 || executing.value) return; executing.value = true; + syncErrors.value = []; + executeTotal.value = syncStatements.value.length; + executedCount.value = 0; try { - await api.executeInTransaction( - targetConnectionId.value, - targetDatabase.value, - syncStatements.value, - targetSchema.value, - ); - toast(t("dataCompare.syncSuccess"), 2000); + await store.ensureConnected(targetConnectionId.value); + for (const stmt of syncStatements.value) { + try { + await api.executeQuery(targetConnectionId.value, targetDatabase.value, stmt, targetSchema.value); + } catch (e: any) { + syncErrors.value.push({ sql: stmt, error: e?.message || String(e) }); + } + executedCount.value++; + } + const failed = syncErrors.value.length; + if (failed === 0) { + toast(t("dataCompare.syncSuccess"), 2000); + } else { + toast(t("diff.syncSummary", { success: syncStatements.value.length - failed, failed }), 5000); + } } catch (e: any) { toast(e?.message || String(e), 5000); } finally { @@ -401,7 +440,7 @@ watch(open, async (value) => {
-
+
+
+ +
+
{
+
+ +
+
+ {{ t("diff.table") }} {{ t("diff.status") }} {{ t("diff.details") }} @@ -452,6 +531,9 @@ watch(open, async (val) => { + + + {{ d.name }} @@ -531,15 +613,34 @@ watch(open, async (val) => {