fix: 修复 SQL Server 列注释显示
This commit is contained in:
6 files changed
+186
-35
No files matched your search
@@ -47,6 +47,15 @@ function oracleConn(id: string): ConnectionConfig {
|
||||
};
|
||||
}
|
||||
|
||||
function sqlServerConn(id: string): ConnectionConfig {
|
||||
return {
|
||||
...conn(id),
|
||||
db_type: "sqlserver",
|
||||
port: 1433,
|
||||
username: "sa",
|
||||
};
|
||||
}
|
||||
|
||||
function withConnectionHealthMock(handler: typeof fetch): typeof fetch {
|
||||
return async (input, init) => {
|
||||
if (String(input) === "/api/connection/check-health") {
|
||||
@@ -826,6 +835,106 @@ test("normalizes unquoted Oracle query identifiers before loading editable metad
|
||||
}
|
||||
});
|
||||
|
||||
test("uses dbo as SQL Server metadata schema when query omits schema", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
const connectionStore = useConnectionStore();
|
||||
const store = useQueryStore();
|
||||
const originalFetch = globalThis.fetch;
|
||||
const columnRequests: Array<{ schema: string | null; table: string | null }> = [];
|
||||
|
||||
connectionStore.addEphemeralConnection(sqlServerConn("sqlserver-1"));
|
||||
|
||||
globalThis.fetch = withConnectionHealthMock(async (input, init) => {
|
||||
const url = String(input);
|
||||
if (url === "/api/query/execute-multi") {
|
||||
return new Response(
|
||||
JSON.stringify([
|
||||
{
|
||||
columns: ["ID", "NAME"],
|
||||
rows: [[1, "Ada"]],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 1,
|
||||
},
|
||||
]),
|
||||
{ status: 200, headers: { "Content-Type": "application/json" } },
|
||||
);
|
||||
}
|
||||
if (url === "/api/query/analyze-editability") {
|
||||
const body = JSON.parse(String(init?.body ?? "{}"));
|
||||
assert.equal(body.sql, "select id, name from users");
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
editable: true,
|
||||
analysis: {
|
||||
schema: undefined,
|
||||
schemaQuoted: false,
|
||||
tableName: "users",
|
||||
tableNameQuoted: false,
|
||||
tableAlias: undefined,
|
||||
selectStar: false,
|
||||
columns: [
|
||||
{ sourceName: "id", sourceNameQuoted: false, resultName: "ID", expression: "id" },
|
||||
{ sourceName: "name", sourceNameQuoted: false, resultName: "NAME", expression: "name" },
|
||||
],
|
||||
},
|
||||
}),
|
||||
{ status: 200, headers: { "Content-Type": "application/json" } },
|
||||
);
|
||||
}
|
||||
if (url.startsWith("/api/schema/columns?")) {
|
||||
const params = new URL(url, "http://localhost").searchParams;
|
||||
columnRequests.push({ schema: params.get("schema"), table: params.get("table") });
|
||||
return new Response(
|
||||
JSON.stringify([
|
||||
{
|
||||
name: "ID",
|
||||
data_type: "int",
|
||||
is_nullable: false,
|
||||
column_default: null,
|
||||
is_primary_key: true,
|
||||
extra: null,
|
||||
comment: "编号",
|
||||
},
|
||||
{
|
||||
name: "NAME",
|
||||
data_type: "nvarchar(100)",
|
||||
is_nullable: true,
|
||||
column_default: null,
|
||||
is_primary_key: false,
|
||||
extra: null,
|
||||
comment: "姓名",
|
||||
},
|
||||
]),
|
||||
{ status: 200, headers: { "Content-Type": "application/json" } },
|
||||
);
|
||||
}
|
||||
if (url === "/api/query/prepare-pagination-plan") {
|
||||
const body = JSON.parse(String(init?.body ?? "{}"));
|
||||
return new Response(JSON.stringify({ sqlToExecute: body.options.sql, useAgentResultSession: false }), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
return new Response("unexpected request", { status: 500 });
|
||||
});
|
||||
|
||||
try {
|
||||
const tabId = store.createTab("sqlserver-1", "app", "Query 1", "query");
|
||||
await store.executeTabSql(tabId, "select id, name from users");
|
||||
|
||||
const tab = store.tabs.find((item) => item.id === tabId);
|
||||
await waitFor(() => columnRequests.length > 0 && tab?.tableMeta?.tableName === "users");
|
||||
assert.deepEqual(columnRequests, [{ schema: "dbo", table: "users" }]);
|
||||
assert.equal(tab?.tableMeta?.schema, "dbo");
|
||||
assert.equal(tab?.tableMeta?.columns[0]?.comment, "编号");
|
||||
assert.equal(tab?.tableMeta?.columns[1]?.comment, "姓名");
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
restoreStorage();
|
||||
}
|
||||
});
|
||||
|
||||
test("evicting cached tab results releases multi-result payloads and sessions", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
@@ -2500,14 +2609,14 @@ test("query results keep readable table source labels with active database conte
|
||||
{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 },
|
||||
{ columns: ["id"], rows: [[2]], affected_rows: 0, execution_time_ms: 1 },
|
||||
]
|
||||
: currentSql === "select * from public.users"
|
||||
? [{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 }]
|
||||
: currentSql === "select u.id from users u join orders o on o.user_id = u.id"
|
||||
: currentSql === "select * from public.users"
|
||||
? [{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 }]
|
||||
: [
|
||||
{ columns: [], rows: [], affected_rows: 1, execution_time_ms: 1 },
|
||||
{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 },
|
||||
];
|
||||
: currentSql === "select u.id from users u join orders o on o.user_id = u.id"
|
||||
? [{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 }]
|
||||
: [
|
||||
{ columns: [], rows: [], affected_rows: 1, execution_time_ms: 1 },
|
||||
{ columns: ["id"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 },
|
||||
];
|
||||
return new Response(JSON.stringify(results), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
}
|
||||
if (url === "/api/query/analyze-editability") {
|
||||
@@ -2522,15 +2631,21 @@ test("query results keep readable table source labels with active database conte
|
||||
try {
|
||||
await store.executeTabSql(tabId, "select * from users; select * from orders");
|
||||
let tab = store.tabs.find((item) => item.id === tabId);
|
||||
assert.deepEqual(tab?.results?.map((result) => result.sourceLabel), ["db.users", "db.orders"]);
|
||||
assert.deepEqual(tab?.results?.map((result) => result.sourceStatement), ["select * from users", "select * from orders"]);
|
||||
|
||||
await store.executeTabSql(
|
||||
defaultDatabaseTabId,
|
||||
"SELECT *\nFROM apis AS ap\nLIMIT 10;\n\nSELECT *\nFROM menus AS mn\nLIMIT 10;",
|
||||
assert.deepEqual(
|
||||
tab?.results?.map((result) => result.sourceLabel),
|
||||
["db.users", "db.orders"],
|
||||
);
|
||||
assert.deepEqual(
|
||||
tab?.results?.map((result) => result.sourceStatement),
|
||||
["select * from users", "select * from orders"],
|
||||
);
|
||||
|
||||
await store.executeTabSql(defaultDatabaseTabId, "SELECT *\nFROM apis AS ap\nLIMIT 10;\n\nSELECT *\nFROM menus AS mn\nLIMIT 10;");
|
||||
tab = store.tabs.find((item) => item.id === defaultDatabaseTabId);
|
||||
assert.deepEqual(tab?.results?.map((result) => result.sourceLabel), ["aaa.apis", "aaa.menus"]);
|
||||
assert.deepEqual(
|
||||
tab?.results?.map((result) => result.sourceLabel),
|
||||
["aaa.apis", "aaa.menus"],
|
||||
);
|
||||
|
||||
await store.executeTabSql(tabId, "select * from public.users");
|
||||
tab = store.tabs.find((item) => item.id === tabId);
|
||||
|
||||
Reference in new issue
Block a user