diff --git a/rust/lancedb/src/database/listing.rs b/rust/lancedb/src/database/listing.rs index 454498d54..4fea6767c 100644 --- a/rust/lancedb/src/database/listing.rs +++ b/rust/lancedb/src/database/listing.rs @@ -1376,6 +1376,68 @@ mod tests { assert!(!tempdir.path().join("__manifest").exists()); } + /// Regression test for https://github.com/lancedb/lancedb/issues/1600. + /// + /// Opening a table used to create a separate object-store client instead of + /// reusing the one that successfully connected to the database. Repeating + /// credential discovery made S3 table opens intermittent, especially in AWS + /// Lambda, and the failed open was reported as `TableNotFound`. + #[tokio::test] + async fn test_open_table_reuses_connection_object_store() { + let tempdir = tempdir().unwrap(); + let uri = tempdir.path().to_str().unwrap(); + let registry = Arc::new(lance_io::object_store::ObjectStoreRegistry::default()); + let session = Arc::new(lance::session::Session::new(16, 16, registry.clone())); + + let request = ConnectRequest { + uri: uri.to_string(), + #[cfg(feature = "remote")] + client_config: Default::default(), + options: Default::default(), + namespace_client_properties: Default::default(), + manifest_enabled: false, + read_consistency_interval: None, + session: Some(session), + }; + let db = ListingDatabase::connect_with_options(&request) + .await + .unwrap(); + + let schema = Arc::new(Schema::new(vec![Field::new("id", DataType::Int32, false)])); + db.create_table(CreateTableRequest { + name: "test".to_string(), + namespace_path: vec![], + data: Box::new(RecordBatch::new_empty(schema)) as Box, + mode: CreateTableMode::Create, + write_options: Default::default(), + location: None, + namespace_client: None, + }) + .await + .unwrap(); + + let before_open = registry.stats(); + for _ in 0..3 { + let table = db + .open_table(OpenTableRequest { + name: "test".to_string(), + namespace_path: vec![], + index_cache_size: None, + lance_read_params: None, + location: None, + namespace_client: None, + managed_versioning: None, + }) + .await + .unwrap(); + assert_eq!(table.count_rows(None).await.unwrap(), 0); + } + + let after_open = registry.stats(); + assert_eq!(after_open.misses, before_open.misses); + assert!(after_open.hits >= before_open.hits + 3); + } + #[tokio::test] async fn test_clone_table_basic() { let (_tempdir, db) = setup_database().await;