diff --git a/apps/desktop/src/components/editor/__tests__/useQueryEditorCompletionMetadata.spec.ts b/apps/desktop/src/components/editor/__tests__/useQueryEditorCompletionMetadata.spec.ts index d044d1ae89..70cc83cc80 100644 --- a/apps/desktop/src/components/editor/__tests__/useQueryEditorCompletionMetadata.spec.ts +++ b/apps/desktop/src/components/editor/__tests__/useQueryEditorCompletionMetadata.spec.ts @@ -60,10 +60,27 @@ describe("QueryEditor completion metadata ownership", () => { expect(store.listCompletionColumns).toHaveBeenCalledTimes(3); const sql = `SELECT s. FROM ${source} s`; const context = getSqlCompletionContext(sql, 9, { databaseType: "oceanbase-oracle" }); - expect(buildSelectStarExpansion(context, metadata.cachedColumnsByTable, "oracle", context.qualifier, "oceanbase-oracle")).toBe(`"${column}"`); + expect(buildSelectStarExpansion(context, metadata.cachedColumnsByTable, "oracle", context.qualifier, "oceanbase-oracle")).toBe(column); const items = buildSqlCompletionItems(sql, 9, { tables: [], columnsByTable: metadata.cachedColumnsByTable, databaseType: "oceanbase-oracle", currentSchema: "APP" }); expect(items.filter((item) => item.type === "column").map((item) => item.label)).toEqual([column]); - expect(items.find((item) => item.label === "s.*")?.apply).toBe(`"${column}"`); + expect(items.find((item) => item.label === "s.*")?.apply).toBe(column); + }); + + it.each([ + ["MiXeD", '"MiXeD"'], + ["With.Dot", '"With.Dot"'], + ['A"B', '"A""B"'], + ["SELECT", '"SELECT"'], + ])("preserves the exact OceanBase column identifier %s in scoped star expansion", async (column, expected) => { + const { metadata, store } = createHarness({ databaseType: "oceanbase-oracle", dialect: "oracle", schema: "APP" }); + store.listCompletionColumns.mockResolvedValue([{ name: column, table: "Alias" }]); + await metadata.ensureColumnsForTable({ name: "Alias" }, { nameQuoted: true }); + const sql = 'SELECT s. FROM "Alias" s'; + const context = getSqlCompletionContext(sql, 9, { databaseType: "oceanbase-oracle" }); + expect(buildSelectStarExpansion(context, metadata.cachedColumnsByTable, "oracle", context.qualifier, "oceanbase-oracle")).toBe(expected); + const items = buildSqlCompletionItems(sql, 9, { tables: [], columnsByTable: metadata.cachedColumnsByTable, databaseType: "oceanbase-oracle", currentSchema: "APP", quoteIdentifiers: false }); + expect(items.filter((item) => item.type === "column").map((item) => item.label)).toEqual([column]); + expect(items.find((item) => item.label === "s.*")?.apply).toBe(expected); }); it.each(["Alias", "APP.Alias", '"Alias"'])("uses the same OceanBase cache identity for diagnostics on %s", async (source) => { diff --git a/apps/desktop/src/lib/__tests__/sql/editableQueryHiddenKeys.spec.ts b/apps/desktop/src/lib/__tests__/sql/editableQueryHiddenKeys.spec.ts index 4e78dbee5f..ccca058056 100644 --- a/apps/desktop/src/lib/__tests__/sql/editableQueryHiddenKeys.spec.ts +++ b/apps/desktop/src/lib/__tests__/sql/editableQueryHiddenKeys.spec.ts @@ -7,7 +7,7 @@ describe("editable query hidden primary keys", () => { for (const [sql, expected] of [ ['SELECT * FROM "Owner"."Items" "i"', 'SELECT "i".*, ROWIDTOCHAR(ROWID) AS "__DBX_PK_1" FROM "Owner"."Items" "i"'], ['SELECT "i".* FROM "Owner"."Items" "i"', 'SELECT "i".*, ROWIDTOCHAR(ROWID) AS "__DBX_PK_1" FROM "Owner"."Items" "i"'], - ['SELECT /*+ FULL(t) */ * -- columns\nFROM APP.ITEMS t', 'SELECT /*+ FULL(t) */ t.*, ROWIDTOCHAR(ROWID) AS "__DBX_PK_1" -- columns\nFROM APP.ITEMS t'], + ["SELECT /*+ FULL(t) */ * -- columns\nFROM APP.ITEMS t", 'SELECT /*+ FULL(t) */ t.*, ROWIDTOCHAR(ROWID) AS "__DBX_PK_1" -- columns\nFROM APP.ITEMS t'], ]) { const result = buildQueryWithHiddenPrimaryKeys({ sql, databaseType, primaryKeys: ["__DBX_ROWID"], existingResultNames: ["rowid", "__DBX_PK_0"], sourceExpressions: { __DBX_ROWID: "ROWIDTOCHAR(ROWID)" } }); expect(result?.sql).toBe(expected); diff --git a/apps/desktop/src/stores/__tests__/queryStore.oceanbaseRowId.spec.ts b/apps/desktop/src/stores/__tests__/queryStore.oceanbaseRowId.spec.ts index 53ff72d19f..a01e2fb9a9 100644 --- a/apps/desktop/src/stores/__tests__/queryStore.oceanbaseRowId.spec.ts +++ b/apps/desktop/src/stores/__tests__/queryStore.oceanbaseRowId.spec.ts @@ -93,12 +93,25 @@ describe("OceanBase Oracle query ROWID preparation", () => { ])("adds a hidden identity to a safe star query: %s", async (originalSql, projection) => { const { analyzeEditableQueryEditability } = await import("@/lib/sql/sqlAnalysis"); mocks.analyze.mockImplementation(async (sql: string) => analyzeEditableQueryEditability(sql)); - mocks.executeMulti.mockResolvedValue([{ columns: ["TASKNAME", "__DBX_PK_0"], rows: [["duplicate", "ROW-A"], ["duplicate", "ROW-B"]], affected_rows: 0, execution_time_ms: 1 }]); + mocks.executeMulti.mockResolvedValue([ + { + columns: ["TASKNAME", "__DBX_PK_0"], + rows: [ + ["duplicate", "ROW-A"], + ["duplicate", "ROW-B"], + ], + affected_rows: 0, + execution_time_ms: 1, + }, + ]); const { store, id, sql } = await executedQuery(originalSql); expect(sql).toBe(`${projection}, ROWIDTOCHAR(ROWID) AS "__DBX_PK_0"${originalSql.slice(originalSql.indexOf(" from "))}`); const tab = store.tabs.find((item) => item.id === id)!; expect(tab.result?.hidden_column_indexes).toEqual([1]); - expect(tab.result?.rows).toEqual([["duplicate", "ROW-A"], ["duplicate", "ROW-B"]]); + expect(tab.result?.rows).toEqual([ + ["duplicate", "ROW-A"], + ["duplicate", "ROW-B"], + ]); await vi.waitFor(() => expect(tab.querySourceColumns).toEqual(["TASKNAME", "__DBX_ROWID"])); expect(tab.tableMeta?.primaryKeys).toEqual(["__DBX_ROWID"]); }); diff --git a/crates/dbx-web/src/routes/transfer.rs b/crates/dbx-web/src/routes/transfer.rs index 16dd46ce04..f7eb06eb54 100644 --- a/crates/dbx-web/src/routes/transfer.rs +++ b/crates/dbx-web/src/routes/transfer.rs @@ -962,6 +962,13 @@ mod tests { async fn demo_mode_transfer_does_not_write_task_history() { let (mut state, dir) = test_web_state().await; Arc::get_mut(&mut state).unwrap().demo_mode = true; + let src = sqlite_config("src", &dir.join("src.db").to_string_lossy()); + let dst = sqlite_config("dst", &dir.join("dst.db").to_string_lossy()); + std::fs::write(dir.join("src.db"), b"").unwrap(); + std::fs::write(dir.join("dst.db"), b"").unwrap(); + std::fs::write(dir.join("main.db"), b"").unwrap(); + state.app.configs.write().await.insert("src".to_string(), src); + state.app.configs.write().await.insert("dst".to_string(), dst); let req = transfer_request("src", "dst", &dir); let transfer_id = req.transfer_id.clone(); let _ = start_transfer(State(state.clone()), Json(StartTransferRequest { request: req })).await.unwrap();