mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-29 00:09:52 +00:00
fix(db): normalize default database handling
This commit is contained in:
@@ -58,10 +58,7 @@ pub fn metadata_connection_config(config: &ConnectionConfig) -> ConnectionConfig
|
||||
pub fn database_connection_config(config: &ConnectionConfig, database: Option<&str>) -> ConnectionConfig {
|
||||
let mut db_config = if database.is_some() { config.clone() } else { metadata_connection_config(config) };
|
||||
if let Some(db) = database {
|
||||
if db_config.db_type != DatabaseType::Oracle
|
||||
&& db_config.db_type != DatabaseType::Dameng
|
||||
&& db_config.db_type != DatabaseType::Gaussdb
|
||||
{
|
||||
if db_config.db_type != DatabaseType::Oracle && db_config.db_type != DatabaseType::Dameng {
|
||||
db_config.database = Some(db.to_string());
|
||||
}
|
||||
}
|
||||
@@ -90,8 +87,7 @@ impl AppState {
|
||||
return Ok(connection_id.to_string());
|
||||
}
|
||||
|
||||
let is_single_conn =
|
||||
matches!(db_type, Some(DatabaseType::Oracle) | Some(DatabaseType::Dameng) | Some(DatabaseType::Gaussdb));
|
||||
let is_single_conn = matches!(db_type, Some(DatabaseType::Oracle) | Some(DatabaseType::Dameng));
|
||||
let pool_key = if is_single_conn {
|
||||
connection_id.to_string()
|
||||
} else {
|
||||
@@ -207,7 +203,7 @@ impl AppState {
|
||||
let client = db::gaussdb_driver::connect(
|
||||
&host,
|
||||
port,
|
||||
db_config.database.as_deref().unwrap_or(""),
|
||||
db_config.effective_database().unwrap_or("postgres"),
|
||||
&db_config.username,
|
||||
&db_config.password,
|
||||
)
|
||||
@@ -272,7 +268,6 @@ impl AppState {
|
||||
c.db_type == DatabaseType::Oracle
|
||||
|| c.db_type == DatabaseType::Elasticsearch
|
||||
|| c.db_type == DatabaseType::Dameng
|
||||
|| c.db_type == DatabaseType::Gaussdb
|
||||
})
|
||||
.unwrap_or(false)
|
||||
};
|
||||
@@ -378,4 +373,24 @@ mod tests {
|
||||
|
||||
assert_eq!(scoped.database.as_deref(), Some("analytics"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gaussdb_database_connection_keeps_requested_database() {
|
||||
let mut config = mysql_config(Some("postgres"));
|
||||
config.db_type = DatabaseType::Gaussdb;
|
||||
|
||||
let scoped = database_connection_config(&config, Some("analytics"));
|
||||
|
||||
assert_eq!(scoped.database.as_deref(), Some("analytics"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oracle_database_connection_ignores_requested_database() {
|
||||
let mut config = mysql_config(Some("ORCL"));
|
||||
config.db_type = DatabaseType::Oracle;
|
||||
|
||||
let scoped = database_connection_config(&config, Some("analytics"));
|
||||
|
||||
assert_eq!(scoped.database.as_deref(), Some("ORCL"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ impl GaussdbClient {
|
||||
}
|
||||
|
||||
pub async fn connect(host: &str, port: u16, database: &str, user: &str, pass: &str) -> Result<GaussdbClient, String> {
|
||||
let database = normalize_database(database);
|
||||
let dsn = format!("host={host} port={port} user={user} password={pass} dbname={database}");
|
||||
|
||||
let result = tokio::time::timeout(std::time::Duration::from_secs(CONNECTION_TIMEOUT_SECS), async {
|
||||
@@ -41,6 +42,15 @@ pub async fn connect(host: &str, port: u16, database: &str, user: &str, pass: &s
|
||||
result.map(|client| GaussdbClient { client })
|
||||
}
|
||||
|
||||
fn normalize_database(database: &str) -> &str {
|
||||
let database = database.trim();
|
||||
if database.is_empty() {
|
||||
"postgres"
|
||||
} else {
|
||||
database
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_databases(client: &mut GaussdbClient) -> Result<Vec<DatabaseInfo>, String> {
|
||||
let rows = client
|
||||
.query_single_column("SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname")
|
||||
@@ -276,3 +286,19 @@ pub async fn execute_query(client: &mut GaussdbClient, sql: &str) -> Result<Quer
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::normalize_database;
|
||||
|
||||
#[test]
|
||||
fn normalize_database_defaults_blank_to_postgres() {
|
||||
assert_eq!(normalize_database(""), "postgres");
|
||||
assert_eq!(normalize_database(" "), "postgres");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_database_keeps_explicit_database() {
|
||||
assert_eq!(normalize_database("app"), "app");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,26 @@ pub enum DatabaseType {
|
||||
}
|
||||
|
||||
impl ConnectionConfig {
|
||||
pub fn effective_database(&self) -> Option<&str> {
|
||||
self.database
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|database| !database.is_empty())
|
||||
.or_else(|| self.default_database())
|
||||
}
|
||||
|
||||
fn default_database(&self) -> Option<&'static str> {
|
||||
match self.db_type {
|
||||
DatabaseType::Postgres => match self.driver_profile.as_deref() {
|
||||
Some("cockroachdb") => Some("defaultdb"),
|
||||
_ => Some("postgres"),
|
||||
},
|
||||
DatabaseType::Redshift => Some("dev"),
|
||||
DatabaseType::Gaussdb => Some("postgres"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn needs_bare_mysql(&self) -> bool {
|
||||
matches!(self.db_type, DatabaseType::Doris | DatabaseType::StarRocks)
|
||||
|| self
|
||||
@@ -94,12 +114,7 @@ impl ConnectionConfig {
|
||||
|
||||
pub fn redacted_connection_url_with_host(&self, host: &str, port: u16) -> String {
|
||||
let host = bracket_ipv6(host);
|
||||
let db_part = self
|
||||
.database
|
||||
.as_deref()
|
||||
.filter(|d| !d.is_empty())
|
||||
.map(|d| format!("/{}", encode_url_part(d)))
|
||||
.unwrap_or_default();
|
||||
let db_part = self.effective_database().map(|d| format!("/{}", encode_url_part(d))).unwrap_or_default();
|
||||
let params = self.normalized_url_params();
|
||||
|
||||
match self.db_type {
|
||||
@@ -148,12 +163,7 @@ impl ConnectionConfig {
|
||||
|
||||
pub fn connection_url_with_host(&self, host: &str, port: u16) -> String {
|
||||
let host = bracket_ipv6(host);
|
||||
let db_part = self
|
||||
.database
|
||||
.as_deref()
|
||||
.filter(|d| !d.is_empty())
|
||||
.map(|d| format!("/{}", encode_url_part(d)))
|
||||
.unwrap_or_default();
|
||||
let db_part = self.effective_database().map(|d| format!("/{}", encode_url_part(d))).unwrap_or_default();
|
||||
let username = encode_url_part(&self.username);
|
||||
let password = encode_url_part(&self.password);
|
||||
let params = self.normalized_url_params();
|
||||
@@ -413,6 +423,47 @@ mod tests {
|
||||
assert_eq!(config.connection_url(), "postgres://postgres:secret@10.1.2.3:2883/test?sslmode=disable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_url_defaults_to_postgres_database_when_omitted() {
|
||||
let mut config = mysql_config("root", "secret", None);
|
||||
config.db_type = DatabaseType::Postgres;
|
||||
|
||||
assert_eq!(config.connection_url(), "postgres://root:secret@10.1.2.3:2883/postgres");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_url_defaults_to_postgres_database_when_empty() {
|
||||
let mut config = mysql_config("root", "secret", Some(""));
|
||||
config.db_type = DatabaseType::Postgres;
|
||||
|
||||
assert_eq!(config.connection_url(), "postgres://root:secret@10.1.2.3:2883/postgres");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redshift_url_defaults_to_dev_database_when_empty() {
|
||||
let mut config = mysql_config("awsuser", "secret", Some(""));
|
||||
config.db_type = DatabaseType::Redshift;
|
||||
|
||||
assert_eq!(config.connection_url(), "postgres://awsuser:secret@10.1.2.3:2883/dev");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cockroachdb_url_defaults_to_defaultdb_database() {
|
||||
let mut config = mysql_config("root", "secret", None);
|
||||
config.db_type = DatabaseType::Postgres;
|
||||
config.driver_profile = Some("cockroachdb".to_string());
|
||||
|
||||
assert_eq!(config.connection_url(), "postgres://root:secret@10.1.2.3:2883/defaultdb");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gaussdb_url_defaults_to_postgres_database() {
|
||||
let mut config = mysql_config("gaussdb", "secret", None);
|
||||
config.db_type = DatabaseType::Gaussdb;
|
||||
|
||||
assert_eq!(config.connection_url(), "gaussdb://gaussdb:secret@10.1.2.3:2883/postgres");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mongodb_form_url_without_params_does_not_force_topology_or_auth() {
|
||||
let config = mongodb_config("root", "secret", Some("admin"));
|
||||
|
||||
Reference in New Issue
Block a user