fix(sql-file): list Dameng schemas for execution target
This commit is contained in:
1 parent
28a5b22e7e
commit
e3d5dbda2a
3 files changed
+99
-7
No files matched your search
@@ -15,9 +15,9 @@ import { useToast } from "@/composables/useToast";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { useProductionSafetyStore } from "@/stores/productionSafetyStore";
|
||||
import { productionContextForDatabase } from "@/lib/database/productionSafety";
|
||||
import { databaseOptionsForConnection } from "@/composables/useDatabaseOptions";
|
||||
import { fetchSqlFileTargetOptions } from "@/composables/useDatabaseOptions";
|
||||
import { requiresSqlFileTargetDatabaseSelection } from "@/lib/connection/connectionLevelDatabaseBootstrap";
|
||||
import { cancelSqlFileExecution, executeSqlFile, listenSqlFileProgress, listDatabases, previewSqlFile, type SqlFilePreview, type SqlFileProgress, type SqlFileStatus } from "@/lib/backend/api";
|
||||
import { cancelSqlFileExecution, executeSqlFile, listenSqlFileProgress, previewSqlFile, type SqlFilePreview, type SqlFileProgress, type SqlFileStatus } from "@/lib/backend/api";
|
||||
import { useExportTracker } from "@/composables/useExportTracker";
|
||||
import { Check, CheckSquare, FileCode, FolderOpen, Loader2, Play, Square, X } from "@lucide/vue";
|
||||
|
||||
@@ -188,10 +188,9 @@ async function loadDatabasesForConnection(id: string) {
|
||||
loadingDatabases.value = true;
|
||||
try {
|
||||
await store.ensureConnected(id);
|
||||
const names = databaseOptionsForConnection(
|
||||
(await listDatabases(id)).map((db) => db.name),
|
||||
store.getConfig(id),
|
||||
);
|
||||
const connection = store.getConfig(id);
|
||||
if (!connection) return;
|
||||
const names = await fetchSqlFileTargetOptions(id, connection);
|
||||
if (token !== databaseLoadToken) return;
|
||||
databaseOptions.value = names;
|
||||
database.value = chooseDatabase(names, id);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { fetchSqlFileTargetOptions } from "@/composables/useDatabaseOptions";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
listDatabases: vi.fn(),
|
||||
listSchemas: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/backend/api", () => ({
|
||||
listDatabases: mocks.listDatabases,
|
||||
listSchemas: mocks.listSchemas,
|
||||
}));
|
||||
|
||||
vi.mock("@/stores/connectionStore", () => ({
|
||||
useConnectionStore: vi.fn(),
|
||||
}));
|
||||
|
||||
describe("fetchSqlFileTargetOptions", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("uses Dameng schemas so independent schemas remain selectable", async () => {
|
||||
mocks.listSchemas.mockResolvedValue(["APP_USER", "REPORTING", "SYS"]);
|
||||
|
||||
const options = await fetchSqlFileTargetOptions("connection-1", {
|
||||
db_type: "dameng",
|
||||
database: "APP_USER",
|
||||
visible_databases: ["APP_USER", "REPORTING"],
|
||||
});
|
||||
|
||||
expect(options).toEqual(["APP_USER", "REPORTING"]);
|
||||
expect(mocks.listSchemas).toHaveBeenCalledWith("connection-1", "APP_USER", true);
|
||||
expect(mocks.listDatabases).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("honors the configured Dameng schema filter before the legacy database filter", async () => {
|
||||
mocks.listSchemas.mockResolvedValue(["APP_USER", "REPORTING", "ARCHIVE"]);
|
||||
|
||||
const options = await fetchSqlFileTargetOptions("connection-1", {
|
||||
db_type: "dameng",
|
||||
database: "APP_USER",
|
||||
visible_databases: ["APP_USER", "REPORTING"],
|
||||
visible_schemas: { APP_USER: ["ARCHIVE"] },
|
||||
});
|
||||
|
||||
expect(options).toEqual(["ARCHIVE"]);
|
||||
});
|
||||
|
||||
it("preserves listDatabases and visible database filtering for other databases", async () => {
|
||||
mocks.listDatabases.mockResolvedValue([{ name: "app" }, { name: "analytics" }, { name: "postgres" }]);
|
||||
|
||||
const options = await fetchSqlFileTargetOptions("connection-2", {
|
||||
db_type: "postgres",
|
||||
database: "app",
|
||||
visible_databases: ["analytics"],
|
||||
});
|
||||
|
||||
expect(options).toEqual(["analytics"]);
|
||||
expect(mocks.listDatabases).toHaveBeenCalledWith("connection-2");
|
||||
expect(mocks.listSchemas).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("propagates metadata loading errors", async () => {
|
||||
const error = new Error("schema metadata failed");
|
||||
mocks.listSchemas.mockRejectedValue(error);
|
||||
|
||||
await expect(
|
||||
fetchSqlFileTargetOptions("connection-1", {
|
||||
db_type: "dameng",
|
||||
database: "APP_USER",
|
||||
}),
|
||||
).rejects.toBe(error);
|
||||
});
|
||||
});
|
||||
@@ -1,16 +1,34 @@
|
||||
import { ref } from "vue";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { filterDatabaseNamesForConnection } from "@/lib/database/visibleDatabases";
|
||||
import { filterDatabaseNamesForConnection, filterSchemaNamesForConnection } from "@/lib/database/visibleDatabases";
|
||||
import { usesTreeSchemaMode } from "@/lib/database/databaseCapabilities";
|
||||
import type { ConnectionConfig } from "@/types/database";
|
||||
import * as api from "@/lib/backend/api";
|
||||
|
||||
type SqlFileTargetConnection = Pick<ConnectionConfig, "database" | "db_type" | "driver_profile" | "visible_databases" | "visible_schemas">;
|
||||
|
||||
export function databaseOptionsForConnection(databaseNames: string[], connection: Pick<ConnectionConfig, "db_type" | "visible_databases"> | undefined): string[] {
|
||||
const names = filterDatabaseNamesForConnection(databaseNames, connection);
|
||||
if (names.length === 0 && usesTreeSchemaMode(connection?.db_type)) return [""];
|
||||
return names;
|
||||
}
|
||||
|
||||
export async function fetchSqlFileTargetOptions(connectionId: string, connection: SqlFileTargetConnection): Promise<string[]> {
|
||||
if (connection.db_type === "dameng") {
|
||||
const database = connection.database || "";
|
||||
// Dameng users and schemas are not interchangeable: independent schemas
|
||||
// appear in listSchemas but not in the user-backed listDatabases result.
|
||||
const schemas = await api.listSchemas(connectionId, database, true);
|
||||
return filterSchemaNamesForConnection(schemas, connection, database);
|
||||
}
|
||||
|
||||
const databases = await api.listDatabases(connectionId);
|
||||
return databaseOptionsForConnection(
|
||||
databases.map((database) => database.name),
|
||||
connection,
|
||||
);
|
||||
}
|
||||
|
||||
export function useDatabaseOptions() {
|
||||
const connectionStore = useConnectionStore();
|
||||
|
||||
|
||||
Reference in new issue
Block a user