fix: support remote tables in storage root

This commit is contained in:
Gatefixer
2026-08-06 06:17:33 +00:00
parent 7357d63e87
commit 72ac16ba76
4 changed files with 50 additions and 7 deletions
+31
View File
@@ -656,6 +656,7 @@ pub struct ConnectRequest {
/// - `/path/to/database` - local database on file system.
/// - `s3://bucket/path/to/database` or `gs://bucket/path/to/database` - database on cloud object store
/// - `db://dbname` - LanceDB Cloud
/// - `db://` with a host override - remote tables in the storage root
pub uri: String,
#[cfg(feature = "remote")]
@@ -768,6 +769,8 @@ impl ConnectBuilder {
///
/// This option is only used when connecting to LanceDB Cloud (db:// URIs)
/// and will be ignored for other URIs.
/// Use the URI `db://` together with a host override to connect to remote
/// tables stored directly in the storage root.
///
/// # Arguments
///
@@ -1354,6 +1357,34 @@ mod tests {
}
}
#[cfg(feature = "remote")]
#[tokio::test]
async fn test_connect_remote_storage_root() {
let conn = ConnectBuilder::new("db://")
.region("us-east-1")
.api_key("my-api-key")
.host_override("https://example.com")
.execute()
.await
.unwrap();
let (impl_name, properties) = conn.namespace_client_config().await.unwrap();
assert_eq!(impl_name, "rest");
assert_eq!(properties["uri"], "https://example.com");
assert_eq!(properties["header.x-lancedb-database"], "");
let result = ConnectBuilder::new("db://")
.region("us-east-1")
.api_key("my-api-key")
.execute()
.await;
assert!(matches!(
result,
Err(Error::InvalidInput { message })
if message.contains("A host override is required")
));
}
#[cfg(feature = "remote")]
#[tokio::test]
async fn test_connect_rejects_header_provider_with_oauth_config() {
+1
View File
@@ -54,6 +54,7 @@
//! - `/path/to/database` - local database on file system.
//! - `s3://bucket/path/to/database` or `gs://bucket/path/to/database` - database on cloud object store
//! - `db://dbname` - Lance Cloud
//! - `db://` with a host override - remote tables in the storage root
//!
//! You can also use [`ConnectBuilder`] to configure the connection to the database.
//!
+11 -7
View File
@@ -349,18 +349,22 @@ pub struct ParsedDbUrl {
/// Parse a database URL and extract the database name and optional prefix.
///
/// Expected format: `db://db_name` or `db://db_name/prefix`
/// Expected format: `db://db_name`, `db://db_name/prefix`, or `db://` when
/// connecting to the storage root through a host override.
pub fn parse_db_url(db_url: &str) -> Result<ParsedDbUrl> {
let parsed_url = url::Url::parse(db_url).map_err(|err| Error::InvalidInput {
message: format!("db_url is not a valid URL. '{db_url}'. Error: {err}"),
})?;
debug_assert_eq!(parsed_url.scheme(), "db");
if !parsed_url.has_host() {
return Err(Error::InvalidInput {
message: format!("Invalid database URL (missing host) '{}'", db_url),
});
}
let db_name = parsed_url.host_str().unwrap().to_string();
let db_name = match parsed_url.host_str() {
Some(db_name) => db_name.to_string(),
None if matches!(parsed_url.path(), "" | "/") => String::new(),
None => {
return Err(Error::InvalidInput {
message: format!("Invalid database URL (missing host) '{}'", db_url),
});
}
};
let db_prefix = {
let prefix = parsed_url.path().trim_start_matches('/');
if prefix.is_empty() {
+7
View File
@@ -272,6 +272,13 @@ impl RemoteDatabase {
read_consistency_interval: Option<std::time::Duration>,
) -> Result<Self> {
let parsed = super::client::parse_db_url(uri)?;
if parsed.db_name.is_empty() && host_override.is_none() {
return Err(Error::InvalidInput {
message:
"A host override is required when connecting to the storage root with 'db://'"
.to_string(),
});
}
let header_map = RestfulLanceDbClient::<Sender>::default_headers(
api_key,
region,