Skip to content

Commit 45ef875

Browse files
shntnuclaudegeorgestagg
authored
fix(reader): honor absolute paths in duckdb:// URIs (#347)
* fix(reader): honor absolute paths in duckdb:// URIs Closes #345. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Suggestions from code review * Tidy up comment --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: George Stagg <george.stagg@posit.co>
1 parent 39a21d4 commit 45ef875

1 file changed

Lines changed: 12 additions & 21 deletions

File tree

src/reader/connection.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,50 +27,35 @@ pub enum ConnectionInfo {
2727
/// # Supported Formats
2828
///
2929
/// - `duckdb://memory` - DuckDB in-memory database
30-
/// - `duckdb:///absolute/path/file.db` - DuckDB file (absolute path)
31-
/// - `duckdb://relative/file.db` - DuckDB file (relative path)
30+
/// - `duckdb://...` - DuckDB path
3231
/// - `postgres://...` - PostgreSQL connection string
3332
/// - `sqlite://...` - SQLite file path
34-
///
35-
/// # Examples
36-
///
37-
/// ```
38-
/// use ggsql::reader::connection::{parse_connection_string, ConnectionInfo};
39-
///
40-
/// let info = parse_connection_string("duckdb://memory").unwrap();
41-
/// assert_eq!(info, ConnectionInfo::DuckDBMemory);
42-
///
43-
/// let info = parse_connection_string("duckdb://data.db").unwrap();
44-
/// assert_eq!(info, ConnectionInfo::DuckDBFile("data.db".to_string()));
4533
/// ```
4634
pub fn parse_connection_string(uri: &str) -> Result<ConnectionInfo> {
4735
if uri == "duckdb://memory" {
4836
return Ok(ConnectionInfo::DuckDBMemory);
4937
}
5038

5139
if let Some(path) = uri.strip_prefix("duckdb://") {
52-
// Remove leading slashes for file paths
53-
let cleaned_path = path.trim_start_matches('/');
54-
if cleaned_path.is_empty() {
40+
if path.is_empty() {
5541
return Err(GgsqlError::ReaderError(
5642
"DuckDB file path cannot be empty".to_string(),
5743
));
5844
}
59-
return Ok(ConnectionInfo::DuckDBFile(cleaned_path.to_string()));
45+
return Ok(ConnectionInfo::DuckDBFile(path.to_string()));
6046
}
6147

6248
if uri.starts_with("postgres://") || uri.starts_with("postgresql://") {
6349
return Ok(ConnectionInfo::PostgreSQL(uri.to_string()));
6450
}
6551

6652
if let Some(path) = uri.strip_prefix("sqlite://") {
67-
let cleaned_path = path.trim_start_matches('/');
68-
if cleaned_path.is_empty() {
53+
if path.is_empty() {
6954
return Err(GgsqlError::ReaderError(
7055
"SQLite file path cannot be empty".to_string(),
7156
));
7257
}
73-
return Ok(ConnectionInfo::SQLite(cleaned_path.to_string()));
58+
return Ok(ConnectionInfo::SQLite(path.to_string()));
7459
}
7560

7661
if let Some(conn_str) = uri.strip_prefix("odbc://") {
@@ -107,7 +92,7 @@ mod tests {
10792
#[test]
10893
fn test_duckdb_file_absolute() {
10994
let info = parse_connection_string("duckdb:///tmp/data.db").unwrap();
110-
assert_eq!(info, ConnectionInfo::DuckDBFile("tmp/data.db".to_string()));
95+
assert_eq!(info, ConnectionInfo::DuckDBFile("/tmp/data.db".to_string()));
11196
}
11297

11398
#[test]
@@ -139,6 +124,12 @@ mod tests {
139124
assert_eq!(info, ConnectionInfo::SQLite("data.db".to_string()));
140125
}
141126

127+
#[test]
128+
fn test_sqlite_absolute() {
129+
let info = parse_connection_string("sqlite:///tmp/data.db").unwrap();
130+
assert_eq!(info, ConnectionInfo::SQLite("/tmp/data.db".to_string()));
131+
}
132+
142133
#[test]
143134
fn test_empty_duckdb_path() {
144135
let result = parse_connection_string("duckdb://");

0 commit comments

Comments
 (0)