feat(execution): multi-database SQL execution with scoped targets

This commit is contained in:
miracle authored and GitHub committed 2026-08-09 14:24:10 +08:00
1 parent 328a2aa107
commit 71ccb3d97d
46 files changed
+4421 -182

No files matched your search

@@ -1,7 +1,7 @@
import { ref } from "vue";
import { useConnectionStore } from "@/stores/connectionStore";
import { filterDatabaseNamesForConnection, filterSchemaNamesForConnection } from "@/lib/database/visibleDatabases";
import { isDorisFamilyCatalogCapable } from "@/lib/database/databaseFeatureSupport";
import { isDorisFamilyCatalogCapable, supportsQueryTargetDatabaseListing } from "@/lib/database/databaseFeatureSupport";
import { usesTreeSchemaMode } from "@/lib/database/databaseCapabilities";
import { isInternalDorisCatalog } from "@/lib/database/databaseFeatureSupport";
import type { CatalogInfo, ConnectionConfig } from "@/types/database";
@@ -78,43 +78,54 @@ export function useDatabaseOptions() {
const loadingCatalogOptions = ref<Record<string, boolean>>({});
const catalogDatabaseOptions = ref<Record<string, string[]>>({});
const loadingCatalogDatabaseOptions = ref<Record<string, boolean>>({});
const databaseRequests = new Map<string, Promise<void>>();
const catalogRequests = new Map<string, Promise<CatalogInfo[]>>();
const catalogDatabaseRequests = new Map<string, Promise<string[]>>();
async function loadDatabaseOptions(connectionId: string, catalog?: string) {
async function loadDatabaseOptions(connectionId: string, catalog?: string): Promise<void> {
const connection = connectionStore.getConfig(connectionId);
if (!connection || loadingDatabaseOptions.value[connectionId]) return;
if (!connection) return;
loadingDatabaseOptions.value[connectionId] = true;
try {
await connectionStore.ensureConnected(connectionId);
if (connection.db_type === "redis") {
const dbs = await api.redisListDatabases(connectionId);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => String(db.db)),
connection,
);
} else if (connection.db_type === "mongodb") {
databaseOptions.value[connectionId] = filterDatabaseNamesForConnection(await api.mongoListDatabases(connectionId), connection);
} else if (connection.db_type === "dameng") {
// 达梦的"数据库"概念对应 schema,使用 listSchemas 获取 schema 列表
databaseOptions.value[connectionId] = await fetchNamespaceOptionsForConnection(connectionId, connection);
} else if (catalog && isDorisFamilyCatalogCapable(connection?.db_type, connection?.driver_profile)) {
const dbs = await api.listDorisCatalogDatabases(connectionId, catalog);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => db.name),
connection,
);
} else {
const dbs = await api.listDatabases(connectionId);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => db.name),
connection,
);
const requestKey = `${connectionId}:${catalog ?? ""}`;
const pending = databaseRequests.get(requestKey);
if (pending) return pending;
const request = (async () => {
loadingDatabaseOptions.value[connectionId] = true;
try {
await connectionStore.ensureConnected(connectionId);
if (connection.db_type === "redis") {
const dbs = await api.redisListDatabases(connectionId);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => String(db.db)),
connection,
);
} else if (connection.db_type === "mongodb") {
databaseOptions.value[connectionId] = filterDatabaseNamesForConnection(await api.mongoListDatabases(connectionId), connection);
} else if (connection.db_type === "dameng") {
databaseOptions.value[connectionId] = await fetchNamespaceOptionsForConnection(connectionId, connection);
} else if (supportsQueryTargetDatabaseListing(connection.db_type)) {
databaseOptions.value[connectionId] = filterDatabaseNamesForConnection(await api.documentListDatabases(connectionId), connection);
} else if (catalog && isDorisFamilyCatalogCapable(connection?.db_type, connection?.driver_profile)) {
const dbs = await api.listDorisCatalogDatabases(connectionId, catalog);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => db.name),
connection,
);
} else {
const dbs = await api.listDatabases(connectionId);
databaseOptions.value[connectionId] = databaseOptionsForConnection(
dbs.map((db) => db.name),
connection,
);
}
} finally {
loadingDatabaseOptions.value[connectionId] = false;
databaseRequests.delete(requestKey);
}
} finally {
loadingDatabaseOptions.value[connectionId] = false;
}
})();
databaseRequests.set(requestKey, request);
return request;
}
async function loadCatalogOptions(connectionId: string): Promise<CatalogInfo[]> {