fix(explain): preserve backend error details

This commit is contained in:
t8y2 committed 2026-07-18 00:11:21 +08:00
1 parent c40683431b
commit fa64952c08
5 files changed
+160 -14

No files matched your search

@@ -0,0 +1,41 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
invoke: vi.fn(),
}));
vi.mock("@tauri-apps/api/core", () => ({
invoke: mocks.invoke,
}));
vi.mock("@tauri-apps/api/event", () => ({
listen: vi.fn(),
}));
describe("getExplainInfo backend error propagation", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.unstubAllGlobals();
});
it("preserves Tauri command errors", async () => {
const error = new Error("ORA-01031: insufficient privileges");
mocks.invoke.mockRejectedValue(error);
const { getExplainInfo } = await import("@/lib/backend/tauri");
await expect(getExplainInfo("oracle-1", "ORCL", "APP", "SELECT * FROM DUAL", "explain")).rejects.toBe(error);
});
it("preserves HTTP response errors", async () => {
vi.stubGlobal(
"fetch",
vi.fn().mockResolvedValue({
ok: false,
text: vi.fn().mockResolvedValue("Agent error: PLAN_TABLE is not accessible"),
}),
);
const { getExplainInfo } = await import("@/lib/backend/http");
await expect(getExplainInfo("oracle-1", "ORCL", "APP", "SELECT * FROM DUAL", "explain")).rejects.toThrow("Agent error: PLAN_TABLE is not accessible");
});
});
+2 -6
View File
@@ -810,12 +810,8 @@ export async function buildCreateUserSql(username: string, password: string, tab
}
export async function getExplainInfo(connectionId: string, database: string | undefined, schema: string | undefined, sql: string, mode: string): Promise<string | undefined> {
try {
const result = await post<string>("/api/query/get-explain-info", { connectionId, database, schema, sql, mode });
return result;
} catch {
return undefined;
}
// Match the Tauri path: transport and Agent failures must remain distinguishable from an empty plan.
return post<string>("/api/query/get-explain-info", { connectionId, database, schema, sql, mode });
}
export async function buildDroppedFilePreviewSql(options: DroppedFilePreviewSqlOptions): Promise<string | undefined> {
+2 -7
View File
@@ -901,13 +901,8 @@ export async function buildCreateUserSql(username: string, password: string, tab
}
export async function getExplainInfo(connectionId: string, database: string | undefined, schema: string | undefined, sql: string, mode: string): Promise<string | undefined> {
try {
const result = await invoke<string>("get_explain_info", { connectionId, database, schema, sql, mode });
return result;
} catch (e: any) {
console.error("[getExplainInfo] invoke failed:", e?.message || e);
return undefined;
}
// Preserve Agent/driver errors so the explain view can show the actionable cause.
return invoke<string>("get_explain_info", { connectionId, database, schema, sql, mode });
}
export async function buildDroppedFilePreviewSql(options: DroppedFilePreviewSqlOptions): Promise<string | undefined> {