mirror of
https://github.com/lancedb/lancedb.git
synced 2026-08-31 18:48:25 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f9ff474c9 |
@@ -656,7 +656,6 @@ 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")]
|
||||
@@ -769,8 +768,6 @@ 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
|
||||
///
|
||||
@@ -1357,34 +1354,6 @@ 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() {
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
//! - `/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.
|
||||
//!
|
||||
|
||||
@@ -349,22 +349,18 @@ pub struct ParsedDbUrl {
|
||||
|
||||
/// Parse a database URL and extract the database name and optional prefix.
|
||||
///
|
||||
/// Expected format: `db://db_name`, `db://db_name/prefix`, or `db://` when
|
||||
/// connecting to the storage root through a host override.
|
||||
/// Expected format: `db://db_name` or `db://db_name/prefix`
|
||||
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");
|
||||
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),
|
||||
});
|
||||
}
|
||||
};
|
||||
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_prefix = {
|
||||
let prefix = parsed_url.path().trim_start_matches('/');
|
||||
if prefix.is_empty() {
|
||||
|
||||
@@ -272,13 +272,6 @@ 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,
|
||||
|
||||
@@ -304,6 +304,68 @@ mod tests {
|
||||
assert_eq!(all_values, expected);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parallel_compaction_reserves_fragment_ids_once() {
|
||||
let conn = connect("memory://").execute().await.unwrap();
|
||||
let schema = Arc::new(Schema::new(vec![Field::new("i", DataType::Int32, false)]));
|
||||
let batch =
|
||||
RecordBatch::try_new(schema, vec![Arc::new(Int32Array::from_iter_values(0..10))])
|
||||
.unwrap();
|
||||
|
||||
let table = conn
|
||||
.create_table("test_parallel_compaction", batch.clone())
|
||||
.execute()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create 64 fragments. With a 20-row target, compaction plans 32 tasks,
|
||||
// which is more than the commit retry limit that used to be exhausted
|
||||
// when each parallel task reserved fragment IDs independently.
|
||||
for _ in 1..64 {
|
||||
table.add(batch.clone()).execute().await.unwrap();
|
||||
}
|
||||
|
||||
// Legacy row IDs require fragment IDs before an index can be remapped.
|
||||
assert!(
|
||||
!table
|
||||
.as_native()
|
||||
.unwrap()
|
||||
.manifest()
|
||||
.await
|
||||
.unwrap()
|
||||
.uses_stable_row_ids()
|
||||
);
|
||||
table
|
||||
.create_index(&["i"], Index::BTree(BTreeIndexBuilder::default()))
|
||||
.execute()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let version_before = table.version().await.unwrap();
|
||||
let stats = table
|
||||
.optimize(OptimizeAction::Compact {
|
||||
options: CompactionOptions {
|
||||
target_rows_per_fragment: 20,
|
||||
num_threads: Some(64),
|
||||
..Default::default()
|
||||
},
|
||||
remap_options: None,
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.compaction
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(stats.fragments_removed, 64);
|
||||
assert_eq!(stats.fragments_added, 32);
|
||||
assert_eq!(table.count_rows(None).await.unwrap(), 640);
|
||||
assert_eq!(
|
||||
table.version().await.unwrap(),
|
||||
version_before + 2,
|
||||
"parallel compaction should use one fragment reservation commit and one rewrite commit"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_optimize_prune_versions() {
|
||||
let conn = connect("memory://").execute().await.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user