fix(completion): resolve Oracle current schema for JDBC star expansion

This commit is contained in:
Melody Ruch
2026-09-05 09:04:57 +08:00
committed by GitHub
parent 4cc6d0959d
commit aeab0f8b03
2 changed files with 54 additions and 4 deletions
@@ -60,6 +60,19 @@ function oracleConnection(): ConnectionConfig {
} as ConnectionConfig;
}
function jdbcOracleConnection(): ConnectionConfig {
return {
...postgresConnection(),
id: "jdbc-oracle-1",
name: "Oracle via JDBC",
db_type: "jdbc",
port: 1521,
username: "APP",
database: "ORCL",
connection_string: "jdbc:oracle:thin:@127.0.0.1:1521/ORCL",
} as ConnectionConfig;
}
function oceanBaseOracleConnection(): ConnectionConfig {
return {
...oracleConnection(),
@@ -613,6 +626,36 @@ describe("connectionStore completion assistant", () => {
expect(store.lookupLocalCompletionColumns("oracle-1", "ORCL", "ORDERS")).toEqual([]);
});
it("lets a JDBC connection to Oracle resolve CURRENT_SCHEMA for unqualified column completion, same as the native Oracle driver", async () => {
const completionAssistantSearch = vi.fn().mockResolvedValue({
candidates: [],
incomplete: false,
fallback_used: false,
});
const getColumns = vi.fn().mockResolvedValue([{ name: "REPORT_ID", data_type: "NUMBER", is_nullable: false, column_default: null, is_primary_key: true, extra: null, comment: null }]);
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
vi.doMock("@/lib/backend/api", () => ({
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
completionAssistantSearch,
getColumns,
}));
const { useConnectionStore } = await import("@/stores/connectionStore");
const store = useConnectionStore();
store.connections = [jdbcOracleConnection()];
store.connectedIds.add("jdbc-oracle-1");
// No schema is selected (undefined) — before the fix this fell through
// both the Oracle current-schema completion path and the schema-required
// guard, silently returning [] without ever calling getColumns.
const columns = await store.listCompletionColumns("jdbc-oracle-1", "ORCL", "ORDERS", undefined, { clientSessionId: "tab-a", version: 0 });
expect(completionAssistantSearch).not.toHaveBeenCalled();
expect(getColumns).toHaveBeenCalledWith("jdbc-oracle-1", "ORCL", "", "ORDERS", undefined, "tab-a");
expect(columns).toEqual([expect.objectContaining({ name: "REPORT_ID", table: "ORDERS", schema: undefined, dataType: "NUMBER" })]);
});
it("uses the Dameng login schema for unqualified column completion", async () => {
const completionAssistantSearch = vi.fn().mockRejectedValue(new Error("assistant unavailable"));
const getColumns = vi.fn().mockResolvedValue([{ name: "ID", data_type: "BIGINT", is_nullable: false, column_default: null, is_primary_key: true, extra: null, comment: null }]);
+11 -4
View File
@@ -8094,12 +8094,19 @@ export const useConnectionStore = defineStore("connection", () => {
async function listCompletionColumns(connectionId: string, database: string, table: string, schema?: string, context?: { clientSessionId?: string; version?: number; tableQuoted?: boolean; schemaQuoted?: boolean }, catalog?: string): Promise<SqlCompletionColumn[]> {
const config = getConfig(connectionId);
const oracleIdentifier = config?.db_type === "oracle" || config?.db_type === "oceanbase-oracle";
const uppercaseUnquotedIdentifier = oracleIdentifier || config?.db_type === "saphana";
// Use the effective database type (e.g. a JDBC connection whose URL is
// `jdbc:oracle:...` resolves to "oracle") rather than the raw db_type.
// Otherwise a JDBC-Oracle connection with no schema selected falls
// through neither the Oracle current-schema completion path nor the
// schema-required early return below finds a schema, and every star
// expansion silently returns no columns.
const effectiveDbType = effectiveDatabaseTypeForConnection(config);
const oracleIdentifier = effectiveDbType === "oracle" || effectiveDbType === "oceanbase-oracle";
const uppercaseUnquotedIdentifier = oracleIdentifier || effectiveDbType === "saphana";
const completionTable = uppercaseUnquotedIdentifier && context?.tableQuoted === false ? table.toUpperCase() : table;
const rawCompletionSchema = schema?.trim() || (config?.db_type === "dameng" ? config.username?.trim() || undefined : undefined);
const rawCompletionSchema = schema?.trim() || (effectiveDbType === "dameng" ? config?.username?.trim() || undefined : undefined);
const completionSchema = uppercaseUnquotedIdentifier && rawCompletionSchema && context?.schemaQuoted === false ? rawCompletionSchema.toUpperCase() : rawCompletionSchema;
const usesCurrentSchema = usesOracleCurrentSchemaCompletion(config?.db_type, completionSchema);
const usesCurrentSchema = usesOracleCurrentSchemaCompletion(effectiveDbType, completionSchema);
if (isSchemaAwareDatabase(connectionId) && !connectionUsesDatabaseObjectTreeMode(config) && !completionSchema && !usesCurrentSchema) {
return [];
}