fix(sqlserver): keep hidden-key sorting editable across pages
This commit is contained in:
1 parent
961d9683b9
commit
e5287f50b4
3 files changed
+44
-4
No files matched your search
@@ -569,6 +569,22 @@ describe("queryStore hidden primary key editing", () => {
|
|||||||
expect(tab.resultSortedSql).toBe("SELECT name, `id` AS `__DBX_PK_0` FROM users ORDER BY name ASC");
|
expect(tab.resultSortedSql).toBe("SELECT name, `id` AS `__DBX_PK_0` FROM users ORDER BY name ASC");
|
||||||
await vi.waitFor(() => expect(tab.querySourceColumns).toEqual(["name", "id"]));
|
await vi.waitFor(() => expect(tab.querySourceColumns).toEqual(["name", "id"]));
|
||||||
expect(tab.queryAnalysis).toBeDefined();
|
expect(tab.queryAnalysis).toBeDefined();
|
||||||
|
|
||||||
|
await store.executeTabSql(tabId, "SELECT name FROM users", {
|
||||||
|
resultBaseSql: "SELECT name FROM users",
|
||||||
|
resultSortedSql: tab.resultSortedSql,
|
||||||
|
querySort: {
|
||||||
|
resultColumns: ["name"],
|
||||||
|
columnIndex: 0,
|
||||||
|
column: "name",
|
||||||
|
direction: "asc",
|
||||||
|
},
|
||||||
|
pagination: { offset: 100, limit: 100 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await vi.waitFor(() => expect(tab.querySourceColumns).toEqual(["name", "id"]));
|
||||||
|
expect(tab.queryEditabilityReason).toBeUndefined();
|
||||||
|
expect(tab.result?.hidden_column_indexes).toEqual([1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("clears result sorting when the editor SQL is executed again", async () => {
|
it("clears result sorting when the editor SQL is executed again", async () => {
|
||||||
|
|||||||
@@ -3817,7 +3817,10 @@ export const useQueryStore = defineStore("query", () => {
|
|||||||
if (tab.mode === "query") {
|
if (tab.mode === "query") {
|
||||||
const prepared = await prepareEditableQueryExecution(tab, sqlToExecute, conn, effectiveDbType, executionDatabase, traceId, elapsed);
|
const prepared = await prepareEditableQueryExecution(tab, sqlToExecute, conn, effectiveDbType, executionDatabase, traceId, elapsed);
|
||||||
sqlToExecute = prepared.sql;
|
sqlToExecute = prepared.sql;
|
||||||
queryMetadataSql = prepared.metadataSql;
|
// Database sorting executes a generated wrapper around the user's query.
|
||||||
|
// Keep editability metadata anchored to the original query so the wrapper
|
||||||
|
// does not turn an otherwise editable result into a complex read-only one.
|
||||||
|
queryMetadataSql = options?.resultSortedSql && !options?.querySort ? queryBaseSql : prepared.metadataSql;
|
||||||
hiddenPrimaryKeys = prepared.hiddenPrimaryKeys;
|
hiddenPrimaryKeys = prepared.hiddenPrimaryKeys;
|
||||||
if (options?.querySort) {
|
if (options?.querySort) {
|
||||||
const sorted = await api.buildSortedQuerySql({
|
const sorted = await api.buildSortedQuerySql({
|
||||||
|
|||||||
+24
-3
@@ -1934,12 +1934,14 @@ test("keeps joined query read-only when multiple source tables are writable cand
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses dbo as SQL Server metadata schema when query omits schema", async () => {
|
test("uses dbo as SQL Server metadata schema and keeps sorted query results editable", async () => {
|
||||||
const restoreStorage = installMemoryStorage();
|
const restoreStorage = installMemoryStorage();
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
const connectionStore = useConnectionStore();
|
const connectionStore = useConnectionStore();
|
||||||
const store = useQueryStore();
|
const store = useQueryStore();
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
|
const baseSql = "select id, name from users";
|
||||||
|
const analyzedSql: string[] = [];
|
||||||
const columnRequests: Array<{ schema: string | null; table: string | null }> = [];
|
const columnRequests: Array<{ schema: string | null; table: string | null }> = [];
|
||||||
|
|
||||||
connectionStore.addEphemeralConnection(sqlServerConn("sqlserver-1"));
|
connectionStore.addEphemeralConnection(sqlServerConn("sqlserver-1"));
|
||||||
@@ -1961,7 +1963,13 @@ test("uses dbo as SQL Server metadata schema when query omits schema", async ()
|
|||||||
}
|
}
|
||||||
if (url === "/api/query/analyze-editability") {
|
if (url === "/api/query/analyze-editability") {
|
||||||
const body = JSON.parse(String(init?.body ?? "{}"));
|
const body = JSON.parse(String(init?.body ?? "{}"));
|
||||||
assert.equal(body.sql, "select id, name from users");
|
analyzedSql.push(body.sql);
|
||||||
|
if (body.sql !== baseSql) {
|
||||||
|
return new Response(JSON.stringify({ editable: false, reason: "complex-source" }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
editable: true,
|
editable: true,
|
||||||
@@ -2020,14 +2028,27 @@ test("uses dbo as SQL Server metadata schema when query omits schema", async ()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const tabId = store.createTab("sqlserver-1", "app", "Query 1", "query");
|
const tabId = store.createTab("sqlserver-1", "app", "Query 1", "query");
|
||||||
await store.executeTabSql(tabId, "select id, name from users");
|
await store.executeTabSql(tabId, baseSql);
|
||||||
|
|
||||||
const tab = store.tabs.find((item) => item.id === tabId);
|
const tab = store.tabs.find((item) => item.id === tabId);
|
||||||
await waitFor(() => columnRequests.length > 0 && tab?.tableMeta?.tableName === "users");
|
await waitFor(() => columnRequests.length > 0 && tab?.tableMeta?.tableName === "users");
|
||||||
|
assert.deepEqual(analyzedSql, [baseSql]);
|
||||||
assert.deepEqual(columnRequests, [{ schema: "dbo", table: "users" }]);
|
assert.deepEqual(columnRequests, [{ schema: "dbo", table: "users" }]);
|
||||||
assert.equal(tab?.tableMeta?.schema, "dbo");
|
assert.equal(tab?.tableMeta?.schema, "dbo");
|
||||||
assert.equal(tab?.tableMeta?.columns[0]?.comment, "编号");
|
assert.equal(tab?.tableMeta?.columns[0]?.comment, "编号");
|
||||||
assert.equal(tab?.tableMeta?.columns[1]?.comment, "姓名");
|
assert.equal(tab?.tableMeta?.columns[1]?.comment, "姓名");
|
||||||
|
|
||||||
|
const sortedSql = "SELECT * FROM (select id, name from users) t([ID], [NAME]) ORDER BY [NAME] ASC;";
|
||||||
|
await store.executeTabSql(tabId, sortedSql, {
|
||||||
|
resultBaseSql: baseSql,
|
||||||
|
resultSortedSql: sortedSql,
|
||||||
|
preserveResultDuringExecution: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => analyzedSql.length === 2);
|
||||||
|
assert.deepEqual(analyzedSql, [baseSql, baseSql]);
|
||||||
|
assert.equal(tab?.queryEditabilityReason, undefined);
|
||||||
|
assert.equal(tab?.queryAnalysis?.tableName, "users");
|
||||||
} finally {
|
} finally {
|
||||||
globalThis.fetch = originalFetch;
|
globalThis.fetch = originalFetch;
|
||||||
restoreStorage();
|
restoreStorage();
|
||||||
|
|||||||
Reference in new issue
Block a user