fix(oracle): refresh table hover metadata from local index
Closes #8056
This commit is contained in:
4 files changed
+109
-10
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { getSqlCompletionContext } from "@/lib/sql/sqlCompletion";
|
||||
import type { ConnectionConfig } from "@/types/database";
|
||||
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
||||
|
||||
function installLocalStorage() {
|
||||
const data = new Map<string, string>();
|
||||
@@ -471,6 +471,85 @@ describe("connectionStore completion assistant", () => {
|
||||
expect(store.lookupLocalCompletionTables("oracle-1", "ORCL", "", 20, "scott")).toEqual(tables);
|
||||
});
|
||||
|
||||
it("reconciles a non-empty filtered cache with a table added to the sidebar tree", async () => {
|
||||
const completionAssistantSearch = vi.fn().mockResolvedValue({
|
||||
candidates: [{ name: "REPORT_0001", kind: "table", schema: "APP" }],
|
||||
incomplete: false,
|
||||
fallback_used: false,
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
|
||||
completionAssistantSearch,
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.connections = [oracleConnection()];
|
||||
store.connectedIds.add("oracle-1");
|
||||
|
||||
const first = await store.listCompletionTables("oracle-1", "ORCL", "REPORT", 200, "APP");
|
||||
const assistantCallsBeforeSidebarLoad = completionAssistantSearch.mock.calls.length;
|
||||
store.treeNodes = [
|
||||
{
|
||||
id: "oracle-1:ORCL:APP:tables",
|
||||
label: "Tables",
|
||||
type: "group-tables",
|
||||
connectionId: "oracle-1",
|
||||
database: "ORCL",
|
||||
schema: "APP",
|
||||
children: [
|
||||
{ id: "report-0001", label: "REPORT_0001", type: "table", connectionId: "oracle-1", database: "ORCL", schema: "APP" },
|
||||
{ id: "report-1001", label: "REPORT_1001", type: "table", connectionId: "oracle-1", database: "ORCL", schema: "APP" },
|
||||
{ id: "other-schema", label: "REPORT_1001", type: "table", connectionId: "oracle-1", database: "ORCL", schema: "OTHER" },
|
||||
],
|
||||
},
|
||||
] as TreeNode[];
|
||||
|
||||
const merged = await store.listCompletionTables("oracle-1", "ORCL", "REPORT", 200, "APP");
|
||||
|
||||
expect(first).toEqual([expect.objectContaining({ name: "REPORT_0001", schema: "APP" })]);
|
||||
expect(merged.map((table) => table.name)).toEqual(["REPORT_0001", "REPORT_1001"]);
|
||||
expect(merged.every((table) => table.schema === "APP")).toBe(true);
|
||||
expect(completionAssistantSearch).toHaveBeenCalledTimes(assistantCallsBeforeSidebarLoad);
|
||||
});
|
||||
|
||||
it("reconciles an empty filtered cache after the sidebar loads a late table", async () => {
|
||||
const completionAssistantSearch = vi.fn().mockResolvedValue({ candidates: [], incomplete: false, fallback_used: false });
|
||||
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
|
||||
completionAssistantSearch,
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.connections = [oracleConnection()];
|
||||
store.connectedIds.add("oracle-1");
|
||||
|
||||
const first = await store.listCompletionTables("oracle-1", "ORCL", "REPORT_1001", 200, "APP");
|
||||
const assistantCallsBeforeSidebarLoad = completionAssistantSearch.mock.calls.length;
|
||||
store.treeNodes = [
|
||||
{
|
||||
id: "oracle-1:ORCL:APP:tables",
|
||||
label: "Tables",
|
||||
type: "group-tables",
|
||||
connectionId: "oracle-1",
|
||||
database: "ORCL",
|
||||
schema: "APP",
|
||||
children: [{ id: "report-1001", label: "REPORT_1001", type: "table", connectionId: "oracle-1", database: "ORCL", schema: "APP" }],
|
||||
},
|
||||
] as TreeNode[];
|
||||
|
||||
const merged = await store.listCompletionTables("oracle-1", "ORCL", "REPORT_1001", 200, "APP");
|
||||
|
||||
expect(first).toEqual([]);
|
||||
expect(merged).toEqual([expect.objectContaining({ name: "REPORT_1001", schema: "APP", type: "table" })]);
|
||||
expect(completionAssistantSearch).toHaveBeenCalledTimes(assistantCallsBeforeSidebarLoad);
|
||||
});
|
||||
|
||||
it("maps global Oracle tables with safe qualification and schema priority", async () => {
|
||||
const completionAssistantSearch = vi.fn().mockResolvedValue({
|
||||
candidates: [
|
||||
|
||||
@@ -7711,7 +7711,13 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
// case-insensitive because tableMatchScore normalizes internally.
|
||||
const relaxedFilter = relaxedCompletionTableFilter(trimmedFilter);
|
||||
const cacheKey = `${connectionId}:${database}:${catalog ?? ""}:${trimmedFilter}:${limit ?? ""}:${schema ?? ""}:${globalSearch ? "global" : "scoped"}:${currentSchema ?? ""}`;
|
||||
if (completionTablesCache.value[cacheKey]) {
|
||||
const cachedTables = completionTablesCache.value[cacheKey];
|
||||
if (cachedTables) {
|
||||
const localTables = lookupLocalCompletionTables(connectionId, database, trimmedFilter, limit, schema, catalog);
|
||||
if (localTables.length === 0) return cachedTables;
|
||||
const mergedTables = dedupeCompletionTables([...localTables, ...cachedTables]);
|
||||
completionTablesCache.value[cacheKey] = limit ? mergedTables.slice(0, limit) : mergedTables;
|
||||
indexCompletionTables(connectionId, database, schema, completionTablesCache.value[cacheKey], catalog);
|
||||
return completionTablesCache.value[cacheKey];
|
||||
}
|
||||
const requestRevision = completionCacheRevision(connectionId, database);
|
||||
|
||||
Reference in new issue
Block a user