From e977e886c36d304c44aa4bf4dc7c4d6b71386769 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Tue, 25 Aug 2026 05:05:55 +0000 Subject: [PATCH] fix(query): skip metadata for constant projections Closes #7111 --- .../queryStore.hiddenPrimaryKey.spec.ts | 36 +++++++++++++++++++ apps/desktop/src/stores/queryStore.ts | 10 ++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts b/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts index 108ee312d9..563293adbc 100644 --- a/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts +++ b/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts @@ -387,6 +387,42 @@ describe("queryStore hidden primary key editing", () => { expect(tab.tableMeta?.schema).toBe("reporting"); }); + it("executes a constant projection without waiting for Oracle table metadata", async () => { + getConnectionConfig.mockReturnValue({ id: "oracle-1", name: "Oracle", db_type: "oracle", database: "ORCL", query_timeout_secs: 30 }); + getColumns.mockResolvedValue([{ name: "DUMMY", data_type: "VARCHAR2(1)", is_nullable: true, column_default: null, is_primary_key: false, extra: null }]); + listIndexes.mockResolvedValue([]); + listTables.mockReturnValue(new Promise(() => undefined)); + analyzeEditableQueryEditability.mockResolvedValue({ + editable: true, + analysis: { + schema: undefined, + tableName: "DUAL", + selectStar: false, + columns: [{ resultName: "1", expression: "1" }], + }, + }); + const result = [{ columns: ["1"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 }]; + const executionGate = deferred(); + executeMulti.mockReturnValue(executionGate.promise); + + const { useQueryStore } = await import("@/stores/queryStore"); + const store = useQueryStore(); + const tabId = store.createTab("oracle-1", "ORCL", "Query"); + store.setAutoCommit(tabId, true); + const sql = "SELECT 1 FROM DUAL"; + + const execution = store.executeTabSql(tabId, sql); + await vi.waitFor(() => expect(executeMulti).toHaveBeenCalled(), { timeout: 250 }); + + expect(executeMulti).toHaveBeenCalledWith("oracle-1", "ORCL", sql, undefined, expect.any(String), expect.objectContaining({ timeoutSecs: 30 })); + expect(getColumns).not.toHaveBeenCalled(); + expect(listIndexes).not.toHaveBeenCalled(); + expect(listTables).not.toHaveBeenCalled(); + + executionGate.resolve(result); + await execution; + }); + it("uses a hidden Oracle ROWID to keep keyless base-table query results editable", async () => { getConnectionConfig.mockReturnValue({ id: "oracle-1", name: "Oracle", db_type: "oracle", database: "ORCL", query_timeout_secs: 30 }); getColumns.mockResolvedValue([ diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index 6bcbed5468..a931486e13 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -3958,11 +3958,15 @@ export const useQueryStore = defineStore("query", () => { const analysis = editability.analysis; const sources = editableQuerySources(analysis); if (sources.length !== 1 || analysis.distinct) return unchanged; + const source = sources[0]!; + const wholeSourceProjected = projectsAllColumnsForSource(analysis, source.key); + const hasDirectSourceProjection = analysis.columns.some((column) => Boolean(column.sourceName) && (!column.sourceKey || column.sourceKey === source.key)); + if (!wholeSourceProjected && !hasDirectSourceProjection) return unchanged; // Whole-source projections already include declared primary keys. Only // Oracle needs preflight metadata here to add ROWID for a keyless table. - if (databaseType !== "oracle" && projectsAllColumnsForSource(analysis, sources[0]!.key)) return unchanged; + if (databaseType !== "oracle" && wholeSourceProjected) return unchanged; - const target = resolveEditableSourceMetadataTarget(tab, analysis, sources[0]!, conn, databaseType, executionDatabase); + const target = resolveEditableSourceMetadataTarget(tab, analysis, source, conn, databaseType, executionDatabase); const cached = getCachedTableMetadata(target.request); let loaded = cached ? loadedEditableSourceFromMetadata(target, cached.metadata) : undefined; if (!cached && databaseType === "oracle") { @@ -3981,7 +3985,7 @@ export const useQueryStore = defineStore("query", () => { loaded = loadedEditableSourceFromMetadata(target, (await fullMetadataPromise).metadata); } - loaded ??= await loadEditableQuerySource(tab, analysis, sources[0]!, conn, databaseType, executionDatabase, traceId, elapsed); + loaded ??= await loadEditableQuerySource(tab, analysis, source, conn, databaseType, executionDatabase, traceId, elapsed); if (loaded.tableMeta.columns.length === 0) return unchanged; if (loaded.tableMeta.tableType?.toUpperCase().includes("VIEW")) return unchanged; const columnPrimaryKeys = loaded.tableMeta.columns.filter((column) => column.is_primary_key).map((column) => column.name);