From f8fc284c54b668489903503e609e904c090f132e Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 3 Jun 2026 15:33:05 +0800 Subject: [PATCH] fix(oracle): honor sysdba agent connections --- .../connection/ConnectionDialog.vue | 14 ++++++- crates/dbx-core/src/agent_connection.rs | 41 ++++++++++++++++++- crates/dbx-core/src/connection.rs | 2 +- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/components/connection/ConnectionDialog.vue b/apps/desktop/src/components/connection/ConnectionDialog.vue index 90ba1e08a4..c35023eed5 100644 --- a/apps/desktop/src/components/connection/ConnectionDialog.vue +++ b/apps/desktop/src/components/connection/ConnectionDialog.vue @@ -103,6 +103,7 @@ const defaultForm = (): Omit => ({ proxy_password: "", ssl: false, ca_cert_path: "", + sysdba: false, oracle_connection_type: "service_name", connection_string: undefined, jdbc_driver_class: undefined, @@ -447,6 +448,7 @@ watch( proxy_password: config.proxy_password || "", ssl: config.ssl || false, ca_cert_path: config.ca_cert_path || "", + sysdba: config.sysdba || isOracleSysUser(config), oracle_connection_type: config.oracle_connection_type || "service_name", connection_string: config.connection_string, jdbc_driver_class: config.jdbc_driver_class, @@ -898,8 +900,10 @@ function connectionConfigForSubmit(id: string): ConnectionConfig { config.connection_string = normalizeMongoConnectionString(config.connection_string?.trim() || ""); } if (config.db_type !== "oracle") { + config.sysdba = undefined; config.oracle_connection_type = undefined; } else { + config.sysdba = !!config.sysdba || isOracleSysUser(config); config.oracle_connection_type = config.oracle_connection_type || "service_name"; } if (config.db_type !== "redis") { @@ -1123,6 +1127,10 @@ function parseRedisEndpoint(value: string, defaultPort: number): { host: string; return { host: endpoint, port: defaultPort }; } +function isOracleSysUser(config: Pick): boolean { + return config.db_type === "oracle" && config.username.trim().toLowerCase() === "sys"; +} + function resetTestState() { testRunId += 1; isTesting.value = false; @@ -1257,6 +1265,10 @@ watch( }, ); +watch([() => form.value.db_type, () => form.value.username], () => { + if (isOracleSysUser(form.value)) form.value.sysdba = true; +}); + watch(canUseSsh, (value) => { if (!value && configTab.value === "ssh") { configTab.value = "connection"; @@ -2247,7 +2259,7 @@ function openExternalUrl(url: string) {
diff --git a/crates/dbx-core/src/agent_connection.rs b/crates/dbx-core/src/agent_connection.rs index 0af703ac59..8bad59d820 100644 --- a/crates/dbx-core/src/agent_connection.rs +++ b/crates/dbx-core/src/agent_connection.rs @@ -5,6 +5,8 @@ use crate::models::connection::{ConnectionConfig, DatabaseType}; pub fn agent_connect_params(config: &ConnectionConfig, host: &str, port: u16, database: &str) -> serde_json::Value { let agent_database = if config.db_type == DatabaseType::MongoDb { mongo_agent_database(config, database) + } else if config.db_type == DatabaseType::Oracle { + oracle_agent_database(config, database) } else { database.to_string() }; @@ -26,12 +28,24 @@ pub fn agent_connect_params(config: &ConnectionConfig, host: &str, port: u16, da "database": agent_database, "username": config.username, "password": config.password, - "sysdba": config.sysdba, + "sysdba": oracle_uses_sysdba(config), "url_params": config.url_params.as_deref().unwrap_or(""), "connection_string": connection_string, }) } +fn oracle_uses_sysdba(config: &ConnectionConfig) -> bool { + config.sysdba || (config.db_type == DatabaseType::Oracle && config.username.trim().eq_ignore_ascii_case("sys")) +} + +fn oracle_agent_database(config: &ConnectionConfig, database: &str) -> String { + let database = database.trim(); + if database.is_empty() || !oracle_uses_sysdba(config) || database.to_uppercase().starts_with("SYSDBA:") { + return database.to_string(); + } + format!("SYSDBA:{database}") +} + fn mongo_agent_database(config: &ConnectionConfig, database: &str) -> String { if let Some(database) = non_empty_database(database) { return database.to_string(); @@ -278,6 +292,31 @@ mod tests { assert_eq!(service["connection_string"], "jdbc:oracle:thin:@//oracle.example.com:1521/ORCL"); } + #[test] + fn oracle_sys_user_connects_as_sysdba_for_agent_protocol() { + let mut cfg = config(DatabaseType::Oracle, Some("ORCLPDB1")); + cfg.username = "SYS".to_string(); + cfg.oracle_connection_type = Some("service_name".to_string()); + + let params = agent_connect_params(&cfg, "oracle.example.com", 1521, "ORCLPDB1"); + + assert_eq!(params["database"], "SYSDBA:ORCLPDB1"); + assert_eq!(params["sysdba"], true); + assert_eq!(params["connection_string"], "jdbc:oracle:thin:@//oracle.example.com:1521/ORCLPDB1"); + } + + #[test] + fn oracle_sysdba_checkbox_connects_as_sysdba_for_agent_protocol() { + let mut cfg = config(DatabaseType::Oracle, Some("ORCLPDB1")); + cfg.username = "system".to_string(); + cfg.sysdba = true; + + let params = agent_connect_params(&cfg, "oracle.example.com", 1521, "ORCLPDB1"); + + assert_eq!(params["database"], "SYSDBA:ORCLPDB1"); + assert_eq!(params["sysdba"], true); + } + #[test] fn oracle_url_preserves_custom_jdbc_descriptor_and_rewrites_host_port() { let mut cfg = config(DatabaseType::Oracle, Some("ORCL")); diff --git a/crates/dbx-core/src/connection.rs b/crates/dbx-core/src/connection.rs index 2c1ff9fc14..c1e60f4054 100644 --- a/crates/dbx-core/src/connection.rs +++ b/crates/dbx-core/src/connection.rs @@ -1183,7 +1183,7 @@ mod tests { let params = agent_connect_params(&config, "oracle.example.com", 1521, "ORCLPDB1"); - assert_eq!(params["database"], "ORCLPDB1"); + assert_eq!(params["database"], "SYSDBA:ORCLPDB1"); assert_eq!(params["sysdba"], true); assert_eq!(params["connection_string"], "jdbc:oracle:thin:@//oracle.example.com:1521/ORCLPDB1"); }