From d082c2d2ac538170a560703f35bc8b51759d7169 Mon Sep 17 00:00:00 2001 From: LanceDB Robot Date: Sun, 5 Apr 2026 10:49:51 +0800 Subject: [PATCH] chore: update lance dependency to v5.0.0-beta.5 (#3237) ## Summary - update Rust Lance workspace dependencies to `v5.0.0-beta.5` using `ci/set_lance_version.py` - update Java `lance-core` dependency property to `5.0.0-beta.5` - refresh Cargo lockfile to the new Lance tag ## Verification - `cargo clippy --workspace --tests --all-features -- -D warnings` - `cargo fmt --all` ## Upstream Tag - https://github.com/lance-format/lance/releases/tag/v5.0.0-beta.5 --------- Co-authored-by: Jack Ye --- Cargo.lock | 64 +++++++++++++------------- Cargo.toml | 28 +++++------ java/pom.xml | 2 +- python/pyproject.toml | 4 +- python/python/lancedb/_lancedb.pyi | 3 ++ python/python/lancedb/db.py | 55 ++++++++++++++++++++++ python/python/lancedb/namespace.py | 27 +++++++++++ python/python/lancedb/remote/db.py | 14 ++++++ python/python/tests/test_db.py | 57 +++++++++++++++++++++++ python/src/connection.rs | 19 ++++++++ rust/lancedb/src/connection.rs | 10 ++++ rust/lancedb/src/database.rs | 9 ++++ rust/lancedb/src/database/listing.rs | 9 ++++ rust/lancedb/src/database/namespace.rs | 10 ++++ rust/lancedb/src/remote/db.rs | 26 +++++++++++ 15 files changed, 288 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54e25c4f8..e2cf80fa0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3072,8 +3072,8 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "fsst" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-array", "rand 0.9.2", @@ -4134,8 +4134,8 @@ dependencies = [ [[package]] name = "lance" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-arith", @@ -4201,8 +4201,8 @@ dependencies = [ [[package]] name = "lance-arrow" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-array", "arrow-buffer", @@ -4222,8 +4222,8 @@ dependencies = [ [[package]] name = "lance-bitpacking" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrayref", "paste", @@ -4232,8 +4232,8 @@ dependencies = [ [[package]] name = "lance-core" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-array", "arrow-buffer", @@ -4270,8 +4270,8 @@ dependencies = [ [[package]] name = "lance-datafusion" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-array", @@ -4301,8 +4301,8 @@ dependencies = [ [[package]] name = "lance-datagen" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-array", @@ -4320,8 +4320,8 @@ dependencies = [ [[package]] name = "lance-encoding" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-arith", "arrow-array", @@ -4358,8 +4358,8 @@ dependencies = [ [[package]] name = "lance-file" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-arith", "arrow-array", @@ -4391,8 +4391,8 @@ dependencies = [ [[package]] name = "lance-index" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-arith", @@ -4456,8 +4456,8 @@ dependencies = [ [[package]] name = "lance-io" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-arith", @@ -4501,8 +4501,8 @@ dependencies = [ [[package]] name = "lance-linalg" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-array", "arrow-buffer", @@ -4518,8 +4518,8 @@ dependencies = [ [[package]] name = "lance-namespace" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "async-trait", @@ -4532,8 +4532,8 @@ dependencies = [ [[package]] name = "lance-namespace-impls" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-ipc", @@ -4578,8 +4578,8 @@ dependencies = [ [[package]] name = "lance-table" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow", "arrow-array", @@ -4618,8 +4618,8 @@ dependencies = [ [[package]] name = "lance-testing" -version = "5.0.0-beta.4" -source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.4#d9068e76a301df9e21d7282419f24f61a11375ac" +version = "5.0.0-beta.5" +source = "git+https://github.com/lance-format/lance.git?tag=v5.0.0-beta.5#d630106da5a238b3adfb8c5dea3b3921f3519945" dependencies = [ "arrow-array", "arrow-schema", diff --git a/Cargo.toml b/Cargo.toml index feef1066d..9bb9ab8a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,20 +15,20 @@ categories = ["database-implementations"] rust-version = "1.91.0" [workspace.dependencies] -lance = { "version" = "=5.0.0-beta.4", default-features = false, "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-core = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-datagen = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-file = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-io = { "version" = "=5.0.0-beta.4", default-features = false, "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-index = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-linalg = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-namespace = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-namespace-impls = { "version" = "=5.0.0-beta.4", default-features = false, "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-table = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-testing = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-datafusion = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-encoding = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } -lance-arrow = { "version" = "=5.0.0-beta.4", "tag" = "v5.0.0-beta.4", "git" = "https://github.com/lance-format/lance.git" } +lance = { "version" = "=5.0.0-beta.5", default-features = false, "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-core = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-datagen = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-file = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-io = { "version" = "=5.0.0-beta.5", default-features = false, "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-index = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-linalg = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-namespace = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-namespace-impls = { "version" = "=5.0.0-beta.5", default-features = false, "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-table = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-testing = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-datafusion = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-encoding = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } +lance-arrow = { "version" = "=5.0.0-beta.5", "tag" = "v5.0.0-beta.5", "git" = "https://github.com/lance-format/lance.git" } ahash = "0.8" # Note that this one does not include pyarrow arrow = { version = "57.2", optional = false } diff --git a/java/pom.xml b/java/pom.xml index 69d728acc..9aef9d792 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -28,7 +28,7 @@ UTF-8 15.0.0 - 5.0.0-beta.4 + 5.0.0-beta.5 false 2.30.0 1.7 diff --git a/python/pyproject.toml b/python/pyproject.toml index 1f3de8b5d..98dfad32c 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -45,7 +45,7 @@ repository = "https://github.com/lancedb/lancedb" [project.optional-dependencies] pylance = [ - "pylance>=5.0.0b3", + "pylance>=5.0.0b5", ] tests = [ "aiohttp>=3.9.0", @@ -59,7 +59,7 @@ tests = [ "polars>=0.19, <=1.3.0", "tantivy>=0.20.0", "pyarrow-stubs>=16.0", - "pylance>=5.0.0b3", + "pylance>=5.0.0b5", "requests>=2.31.0", "datafusion>=52,<53", ] diff --git a/python/python/lancedb/_lancedb.pyi b/python/python/lancedb/_lancedb.pyi index 6a8b51d16..76c08041b 100644 --- a/python/python/lancedb/_lancedb.pyi +++ b/python/python/lancedb/_lancedb.pyi @@ -151,6 +151,9 @@ class Connection(object): async def drop_all_tables( self, namespace_path: Optional[List[str]] = None ) -> None: ... + async def namespace_client_config( + self, + ) -> Dict[str, Any]: ... class Table: def name(self) -> str: ... diff --git a/python/python/lancedb/db.py b/python/python/lancedb/db.py index bfe7f8d70..869f1481f 100644 --- a/python/python/lancedb/db.py +++ b/python/python/lancedb/db.py @@ -23,11 +23,13 @@ from lancedb.embeddings.registry import EmbeddingFunctionRegistry from lancedb.common import data_to_reader, sanitize_uri, validate_schema from lancedb.background_loop import LOOP from lance_namespace import ( + LanceNamespace, ListNamespacesResponse, CreateNamespaceResponse, DropNamespaceResponse, DescribeNamespaceResponse, ListTablesResponse, + connect as namespace_connect, ) from . import __version__ @@ -507,6 +509,26 @@ class DBConnection(EnforceOverrides): def uri(self) -> str: return self._uri + def namespace_client(self) -> LanceNamespace: + """Get the equivalent namespace client for this connection. + + For native storage connections, this returns a DirectoryNamespace + pointing to the same root with the same storage options. + + For namespace connections, this returns the backing namespace client. + + For enterprise (remote) connections, this returns a RestNamespace + with the same URI and authentication headers. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + raise NotImplementedError( + "namespace_client is not supported for this connection type" + ) + class LanceDBConnection(DBConnection): """ @@ -1044,6 +1066,20 @@ class LanceDBConnection(DBConnection): ) ) + @override + def namespace_client(self) -> LanceNamespace: + """Get the equivalent namespace client for this connection. + + Returns a DirectoryNamespace pointing to the same root with the + same storage options. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + return LOOP.run(self._conn.namespace_client()) + @deprecation.deprecated( deprecated_in="0.15.1", removed_in="0.17", @@ -1716,6 +1752,25 @@ class AsyncConnection(object): namespace_path = [] await self._inner.drop_all_tables(namespace_path=namespace_path) + async def namespace_client(self) -> LanceNamespace: + """Get the equivalent namespace client for this connection. + + For native storage connections, this returns a DirectoryNamespace + pointing to the same root with the same storage options. + + For namespace connections, this returns the backing namespace client. + + For enterprise (remote) connections, this returns a RestNamespace + with the same URI and authentication headers. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + config = await self._inner.namespace_client_config() + return namespace_connect(config["impl"], config["properties"]) + @deprecation.deprecated( deprecated_in="0.15.1", removed_in="0.17", diff --git a/python/python/lancedb/namespace.py b/python/python/lancedb/namespace.py index a400b2817..55df0c82b 100644 --- a/python/python/lancedb/namespace.py +++ b/python/python/lancedb/namespace.py @@ -890,6 +890,20 @@ class LanceNamespaceDBConnection(DBConnection): pushdown_operations=self._pushdown_operations, ) + @override + def namespace_client(self) -> LanceNamespace: + """Get the namespace client for this connection. + + For namespace connections, this returns the backing namespace client + that was provided during construction. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + return self._namespace_client + class AsyncLanceNamespaceDBConnection: """ @@ -1387,6 +1401,19 @@ class AsyncLanceNamespaceDBConnection: page_token=response.page_token, ) + async def namespace_client(self) -> LanceNamespace: + """Get the namespace client for this connection. + + For namespace connections, this returns the backing namespace client + that was provided during construction. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + return self._namespace_client + def connect_namespace( namespace_client_impl: str, diff --git a/python/python/lancedb/remote/db.py b/python/python/lancedb/remote/db.py index 0afe469b9..e110cdac1 100644 --- a/python/python/lancedb/remote/db.py +++ b/python/python/lancedb/remote/db.py @@ -24,6 +24,7 @@ from ..common import DATA from ..db import DBConnection, LOOP from ..embeddings import EmbeddingFunctionConfig from lance_namespace import ( + LanceNamespace, CreateNamespaceResponse, DescribeNamespaceResponse, DropNamespaceResponse, @@ -570,6 +571,19 @@ class RemoteDBConnection(DBConnection): ) ) + @override + def namespace_client(self) -> LanceNamespace: + """Get the equivalent namespace client for this connection. + + Returns a RestNamespace with the same URI and authentication headers. + + Returns + ------- + LanceNamespace + The namespace client for this connection. + """ + return LOOP.run(self._conn.namespace_client()) + async def close(self): """Close the connection to the database.""" self._conn.close() diff --git a/python/python/tests/test_db.py b/python/python/tests/test_db.py index 5ad72f8ed..ebb42b61e 100644 --- a/python/python/tests/test_db.py +++ b/python/python/tests/test_db.py @@ -3,6 +3,7 @@ import re +import sys from datetime import timedelta import os @@ -1048,3 +1049,59 @@ def test_clone_table_deep_clone_fails(tmp_path): source_uri = os.path.join(tmp_path, "source.lance") with pytest.raises(Exception, match="Deep clone is not yet implemented"): db.clone_table("cloned", source_uri, is_shallow=False) + + +@pytest.mark.skipif(sys.platform == "win32", reason="Namespace client issues") +def test_namespace_client_native_storage(tmp_path): + """Test namespace_client() returns DirectoryNamespace for native storage.""" + from lance.namespace import DirectoryNamespace + + db = lancedb.connect(tmp_path) + ns_client = db.namespace_client() + + assert isinstance(ns_client, DirectoryNamespace) + assert str(tmp_path) in ns_client.namespace_id() + + +@pytest.mark.skipif(sys.platform == "win32", reason="Namespace client issues") +def test_namespace_client_with_storage_options(tmp_path): + """Test namespace_client() preserves storage options.""" + from lance.namespace import DirectoryNamespace + + storage_options = {"timeout": "10s"} + db = lancedb.connect(tmp_path, storage_options=storage_options) + ns_client = db.namespace_client() + + assert isinstance(ns_client, DirectoryNamespace) + + +@pytest.mark.skipif(sys.platform == "win32", reason="Namespace client issues") +def test_namespace_client_operations(tmp_path): + """Test that namespace_client() returns a functional namespace client.""" + db = lancedb.connect(tmp_path) + ns_client = db.namespace_client() + + # Create a table through the main db connection + data = [{"id": 1, "text": "hello", "vector": [1.0, 2.0]}] + db.create_table("test_table", data=data) + + # Verify the namespace client can see the table + from lance_namespace import ListTablesRequest + + # id=[] means root namespace + response = ns_client.list_tables(ListTablesRequest(id=[])) + # Tables can be strings or objects with name attribute + table_names = [t.name if hasattr(t, "name") else t for t in response.tables] + assert "test_table" in table_names + + +@pytest.mark.skipif(sys.platform == "win32", reason="Namespace client issues") +def test_namespace_client_namespace_connection(tmp_path): + """Test namespace_client() returns the backing client for namespace connections.""" + from lance.namespace import DirectoryNamespace + + db = lancedb.connect_namespace("dir", {"root": str(tmp_path)}) + ns_client = db.namespace_client() + + assert isinstance(ns_client, DirectoryNamespace) + assert str(tmp_path) in ns_client.namespace_id() diff --git a/python/src/connection.rs b/python/src/connection.rs index 1e0bdee21..1db4e7344 100644 --- a/python/src/connection.rs +++ b/python/src/connection.rs @@ -474,6 +474,25 @@ impl Connection { }) }) } + + /// Get the configuration for constructing an equivalent namespace client. + /// Returns a dict with: + /// - "impl": "dir" for DirectoryNamespace, "rest" for RestNamespace + /// - "properties": configuration properties for the namespace + #[pyo3(signature = ())] + pub fn namespace_client_config(self_: PyRef<'_, Self>) -> PyResult> { + let inner = self_.get_inner()?.clone(); + let py = self_.py(); + future_into_py(py, async move { + let (impl_type, properties) = inner.namespace_client_config().await.infer_error()?; + Python::attach(|py| -> PyResult> { + let dict = PyDict::new(py); + dict.set_item("impl", impl_type)?; + dict.set_item("properties", properties)?; + Ok(dict.unbind()) + }) + }) + } } #[pyfunction] diff --git a/rust/lancedb/src/connection.rs b/rust/lancedb/src/connection.rs index 169246baf..e89dea37e 100644 --- a/rust/lancedb/src/connection.rs +++ b/rust/lancedb/src/connection.rs @@ -541,6 +541,16 @@ impl Connection { self.internal.namespace_client().await } + /// Get the configuration for constructing an equivalent namespace client. + /// Returns (impl_type, properties) where: + /// - impl_type: "dir" for DirectoryNamespace, "rest" for RestNamespace + /// - properties: configuration properties for the namespace + pub async fn namespace_client_config( + &self, + ) -> Result<(String, std::collections::HashMap)> { + self.internal.namespace_client_config().await + } + /// List tables with pagination support pub async fn list_tables(&self, request: ListTablesRequest) -> Result { self.internal.list_tables(request).await diff --git a/rust/lancedb/src/database.rs b/rust/lancedb/src/database.rs index 1fee2f295..787221909 100644 --- a/rust/lancedb/src/database.rs +++ b/rust/lancedb/src/database.rs @@ -265,4 +265,13 @@ pub trait Database: /// For ListingDatabase, it is the equivalent DirectoryNamespace. /// For RemoteDatabase, it is the equivalent RestNamespace. async fn namespace_client(&self) -> Result>; + + /// Get the configuration for constructing an equivalent namespace client. + /// Returns (impl_type, properties) where: + /// - impl_type: "dir" for DirectoryNamespace, "rest" for RestNamespace + /// - properties: configuration properties for the namespace + /// + /// This is useful for Python bindings where we want to return a Python + /// namespace object rather than a Rust trait object. + async fn namespace_client_config(&self) -> Result<(String, HashMap)>; } diff --git a/rust/lancedb/src/database/listing.rs b/rust/lancedb/src/database/listing.rs index 9c19fbee4..09b902f4d 100644 --- a/rust/lancedb/src/database/listing.rs +++ b/rust/lancedb/src/database/listing.rs @@ -1099,6 +1099,15 @@ impl Database for ListingDatabase { })?; Ok(Arc::new(namespace) as Arc) } + + async fn namespace_client_config(&self) -> Result<(String, HashMap)> { + let mut properties = HashMap::new(); + properties.insert("root".to_string(), self.uri.clone()); + for (key, value) in &self.storage_options { + properties.insert(format!("storage.{}", key), value.clone()); + } + Ok(("dir".to_string(), properties)) + } } #[cfg(test)] diff --git a/rust/lancedb/src/database/namespace.rs b/rust/lancedb/src/database/namespace.rs index 2e381aaea..03bc434e6 100644 --- a/rust/lancedb/src/database/namespace.rs +++ b/rust/lancedb/src/database/namespace.rs @@ -45,6 +45,10 @@ pub struct LanceNamespaceDatabase { uri: String, // Operations to push down to the namespace server pushdown_operations: HashSet, + // Namespace implementation type (e.g., "dir", "rest") + ns_impl: String, + // Namespace properties used to construct the namespace client + ns_properties: HashMap, } impl LanceNamespaceDatabase { @@ -74,6 +78,8 @@ impl LanceNamespaceDatabase { session, uri: format!("namespace://{}", ns_impl), pushdown_operations, + ns_impl: ns_impl.to_string(), + ns_properties, }) } } @@ -345,6 +351,10 @@ impl Database for LanceNamespaceDatabase { async fn namespace_client(&self) -> Result> { Ok(self.namespace.clone()) } + + async fn namespace_client_config(&self) -> Result<(String, HashMap)> { + Ok((self.ns_impl.clone(), self.ns_properties.clone())) + } } #[cfg(test)] diff --git a/rust/lancedb/src/remote/db.rs b/rust/lancedb/src/remote/db.rs index 553ce5599..be50b6859 100644 --- a/rust/lancedb/src/remote/db.rs +++ b/rust/lancedb/src/remote/db.rs @@ -777,6 +777,32 @@ impl Database for RemoteDatabase { let namespace = builder.build(); Ok(Arc::new(namespace) as Arc) } + + async fn namespace_client_config(&self) -> Result<(String, HashMap)> { + let mut properties = HashMap::new(); + properties.insert("uri".to_string(), self.client.host().to_string()); + properties.insert("delimiter".to_string(), self.client.id_delimiter.clone()); + for (key, value) in &self.namespace_headers { + properties.insert(format!("header.{}", key), value.clone()); + } + // Add TLS configuration if present + if let Some(tls_config) = &self.tls_config { + if let Some(cert_file) = &tls_config.cert_file { + properties.insert("tls.cert_file".to_string(), cert_file.clone()); + } + if let Some(key_file) = &tls_config.key_file { + properties.insert("tls.key_file".to_string(), key_file.clone()); + } + if let Some(ssl_ca_cert) = &tls_config.ssl_ca_cert { + properties.insert("tls.ssl_ca_cert".to_string(), ssl_ca_cert.clone()); + } + properties.insert( + "tls.assert_hostname".to_string(), + tls_config.assert_hostname.to_string(), + ); + } + Ok(("rest".to_string(), properties)) + } } /// RemoteOptions contains a subset of StorageOptions that are compatible with Remote LanceDB connections