Merge branch 'fix/11422-ob-star-rowid-pr' of https://github.com/efeire/dbx into feat/11437-ob-clob-preview

# Conflicts:
#	apps/desktop/src/lib/__tests__/sql/editableQueryHiddenKeys.spec.ts
#	apps/desktop/src/stores/__tests__/queryStore.oceanbaseRowId.spec.ts
This commit is contained in:
efeire
2026-10-10 01:41:00 +08:00
4 changed files with 42 additions and 5 deletions
@@ -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) => {
@@ -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);
@@ -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"]);
});
+7
View File
@@ -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();