mirror of
https://github.com/lancedb/lancedb.git
synced 2026-09-11 15:52:17 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7b29dfabb |
Generated
+34
-34
@@ -3072,8 +3072,8 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsst"
|
name = "fsst"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"rand 0.9.2",
|
"rand 0.9.2",
|
||||||
@@ -4404,8 +4404,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance"
|
name = "lance"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-arith",
|
"arrow-arith",
|
||||||
@@ -4470,8 +4470,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-arrow"
|
name = "lance-arrow"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-buffer",
|
"arrow-buffer",
|
||||||
@@ -4490,8 +4490,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-bitpacking"
|
name = "lance-bitpacking"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"paste",
|
"paste",
|
||||||
@@ -4500,8 +4500,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-core"
|
name = "lance-core"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-buffer",
|
"arrow-buffer",
|
||||||
@@ -4538,8 +4538,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-datafusion"
|
name = "lance-datafusion"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4569,8 +4569,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-datagen"
|
name = "lance-datagen"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4588,8 +4588,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-encoding"
|
name = "lance-encoding"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-arith",
|
"arrow-arith",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4626,8 +4626,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-file"
|
name = "lance-file"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-arith",
|
"arrow-arith",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4659,8 +4659,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-geo"
|
name = "lance-geo"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"datafusion",
|
"datafusion",
|
||||||
"geo-traits",
|
"geo-traits",
|
||||||
@@ -4674,8 +4674,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-index"
|
name = "lance-index"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-arith",
|
"arrow-arith",
|
||||||
@@ -4742,8 +4742,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-io"
|
name = "lance-io"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-arith",
|
"arrow-arith",
|
||||||
@@ -4783,8 +4783,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-linalg"
|
name = "lance-linalg"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-buffer",
|
"arrow-buffer",
|
||||||
@@ -4800,8 +4800,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-namespace"
|
name = "lance-namespace"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -4813,8 +4813,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-namespace-impls"
|
name = "lance-namespace-impls"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-ipc",
|
"arrow-ipc",
|
||||||
@@ -4857,8 +4857,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-table"
|
name = "lance-table"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4897,8 +4897,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lance-testing"
|
name = "lance-testing"
|
||||||
version = "2.0.0-beta.8"
|
version = "2.0.0-beta.9"
|
||||||
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.8#5bffcfc3f9716fd6eb069579eb5027ed9c69feb7"
|
source = "git+https://github.com/lance-format/lance.git?tag=v2.0.0-beta.9#768bf30973ad28c892bfbae98d87bdf9a2139139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-schema",
|
"arrow-schema",
|
||||||
|
|||||||
+16
-16
@@ -15,20 +15,20 @@ categories = ["database-implementations"]
|
|||||||
rust-version = "1.78.0"
|
rust-version = "1.78.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
lance = { "version" = "=2.0.0-beta.8", default-features = false, "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance = { "version" = "=2.0.0-beta.9", default-features = false, "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-core = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-core = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-datagen = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-datagen = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-file = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-file = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-io = { "version" = "=2.0.0-beta.8", default-features = false, "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-io = { "version" = "=2.0.0-beta.9", default-features = false, "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-index = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-index = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-linalg = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-linalg = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-namespace = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-namespace = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-namespace-impls = { "version" = "=2.0.0-beta.8", default-features = false, "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-namespace-impls = { "version" = "=2.0.0-beta.9", default-features = false, "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-table = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-table = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-testing = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-testing = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-datafusion = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-datafusion = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-encoding = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-encoding = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-arrow = { "version" = "=2.0.0-beta.8", "tag" = "v2.0.0-beta.8", "git" = "https://github.com/lance-format/lance.git" }
|
lance-arrow = { "version" = "=2.0.0-beta.9", "tag" = "v2.0.0-beta.9", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
ahash = "0.8"
|
ahash = "0.8"
|
||||||
# Note that this one does not include pyarrow
|
# Note that this one does not include pyarrow
|
||||||
arrow = { version = "57.2", optional = false }
|
arrow = { version = "57.2", optional = false }
|
||||||
@@ -47,7 +47,7 @@ datafusion-execution = "51.0"
|
|||||||
datafusion-expr = "51.0"
|
datafusion-expr = "51.0"
|
||||||
datafusion-physical-plan = "51.0"
|
datafusion-physical-plan = "51.0"
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
half = { "version" = "2.7.1", default-features = false, features = [
|
half = { "version" = "2.6.0", default-features = false, features = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
] }
|
] }
|
||||||
futures = "0"
|
futures = "0"
|
||||||
@@ -59,7 +59,7 @@ rand = "0.9"
|
|||||||
snafu = "0.8"
|
snafu = "0.8"
|
||||||
url = "2"
|
url = "2"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
regex = "1.12"
|
regex = "1.10"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
semver = "1.0.25"
|
semver = "1.0.25"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[tool.bumpversion]
|
[tool.bumpversion]
|
||||||
current_version = "0.27.0-beta.0"
|
current_version = "0.26.1"
|
||||||
parse = """(?x)
|
parse = """(?x)
|
||||||
(?P<major>0|[1-9]\\d*)\\.
|
(?P<major>0|[1-9]\\d*)\\.
|
||||||
(?P<minor>0|[1-9]\\d*)\\.
|
(?P<minor>0|[1-9]\\d*)\\.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lancedb-python"
|
name = "lancedb-python"
|
||||||
version = "0.27.0-beta.0"
|
version = "0.26.1"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
description = "Python bindings for LanceDB"
|
description = "Python bindings for LanceDB"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ class Table:
|
|||||||
cleanup_since_ms: Optional[int] = None,
|
cleanup_since_ms: Optional[int] = None,
|
||||||
delete_unverified: Optional[bool] = None,
|
delete_unverified: Optional[bool] = None,
|
||||||
) -> OptimizeStats: ...
|
) -> OptimizeStats: ...
|
||||||
async def uri(self) -> str: ...
|
|
||||||
@property
|
@property
|
||||||
def tags(self) -> Tags: ...
|
def tags(self) -> Tags: ...
|
||||||
def query(self) -> Query: ...
|
def query(self) -> Query: ...
|
||||||
|
|||||||
@@ -961,27 +961,22 @@ class LanceQueryBuilder(ABC):
|
|||||||
>>> query = [100, 100]
|
>>> query = [100, 100]
|
||||||
>>> plan = table.search(query).analyze_plan()
|
>>> plan = table.search(query).analyze_plan()
|
||||||
>>> print(plan) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
>>> print(plan) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
||||||
AnalyzeExec verbose=true, elapsed=..., metrics=...
|
AnalyzeExec verbose=true, metrics=[], cumulative_cpu=...
|
||||||
TracedExec, elapsed=..., metrics=...
|
TracedExec, metrics=[], cumulative_cpu=...
|
||||||
ProjectionExec: elapsed=..., expr=[...],
|
ProjectionExec: expr=[...], metrics=[...], cumulative_cpu=...
|
||||||
metrics=[output_rows=..., elapsed_compute=..., output_bytes=...]
|
GlobalLimitExec: skip=0, fetch=10, metrics=[...], cumulative_cpu=...
|
||||||
GlobalLimitExec: elapsed=..., skip=0, fetch=10,
|
FilterExec: _distance@2 IS NOT NULL,
|
||||||
metrics=[output_rows=..., elapsed_compute=..., output_bytes=...]
|
metrics=[output_rows=..., elapsed_compute=...], cumulative_cpu=...
|
||||||
FilterExec: elapsed=..., _distance@2 IS NOT NULL, metrics=[...]
|
SortExec: TopK(fetch=10), expr=[...],
|
||||||
SortExec: elapsed=..., TopK(fetch=10), expr=[...],
|
|
||||||
preserve_partitioning=[...],
|
preserve_partitioning=[...],
|
||||||
metrics=[output_rows=..., elapsed_compute=...,
|
metrics=[output_rows=..., elapsed_compute=..., row_replacements=...],
|
||||||
output_bytes=..., row_replacements=...]
|
cumulative_cpu=...
|
||||||
KNNVectorDistance: elapsed=..., metric=l2,
|
KNNVectorDistance: metric=l2,
|
||||||
metrics=[output_rows=..., elapsed_compute=...,
|
metrics=[output_rows=..., elapsed_compute=..., output_batches=...],
|
||||||
output_bytes=..., output_batches=...]
|
cumulative_cpu=...
|
||||||
LanceRead: elapsed=..., uri=..., projection=[vector],
|
LanceRead: uri=..., projection=[vector], ...
|
||||||
num_fragments=..., range_before=None, range_after=None,
|
metrics=[output_rows=..., elapsed_compute=...,
|
||||||
row_id=true, row_addr=false,
|
bytes_read=..., iops=..., requests=...], cumulative_cpu=...
|
||||||
full_filter=--, refine_filter=--,
|
|
||||||
metrics=[output_rows=..., elapsed_compute=..., output_bytes=...,
|
|
||||||
fragments_scanned=..., ranges_scanned=1, rows_scanned=1,
|
|
||||||
bytes_read=..., iops=..., requests=..., task_wait_time=...]
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|||||||
@@ -655,14 +655,6 @@ class RemoteTable(Table):
|
|||||||
def stats(self):
|
def stats(self):
|
||||||
return LOOP.run(self._table.stats())
|
return LOOP.run(self._table.stats())
|
||||||
|
|
||||||
@property
|
|
||||||
def uri(self) -> str:
|
|
||||||
"""The table URI (storage location).
|
|
||||||
|
|
||||||
For remote tables, this fetches the location from the server via describe.
|
|
||||||
"""
|
|
||||||
return LOOP.run(self._table.uri())
|
|
||||||
|
|
||||||
def take_offsets(self, offsets: list[int]) -> LanceTakeQueryBuilder:
|
def take_offsets(self, offsets: list[int]) -> LanceTakeQueryBuilder:
|
||||||
return LanceTakeQueryBuilder(self._table.take_offsets(offsets))
|
return LanceTakeQueryBuilder(self._table.take_offsets(offsets))
|
||||||
|
|
||||||
|
|||||||
@@ -2218,10 +2218,6 @@ class LanceTable(Table):
|
|||||||
def stats(self) -> TableStatistics:
|
def stats(self) -> TableStatistics:
|
||||||
return LOOP.run(self._table.stats())
|
return LOOP.run(self._table.stats())
|
||||||
|
|
||||||
@property
|
|
||||||
def uri(self) -> str:
|
|
||||||
return LOOP.run(self._table.uri())
|
|
||||||
|
|
||||||
def create_scalar_index(
|
def create_scalar_index(
|
||||||
self,
|
self,
|
||||||
column: str,
|
column: str,
|
||||||
@@ -3610,20 +3606,6 @@ class AsyncTable:
|
|||||||
"""
|
"""
|
||||||
return await self._inner.stats()
|
return await self._inner.stats()
|
||||||
|
|
||||||
async def uri(self) -> str:
|
|
||||||
"""
|
|
||||||
Get the table URI (storage location).
|
|
||||||
|
|
||||||
For remote tables, this fetches the location from the server via describe.
|
|
||||||
For local tables, this returns the dataset URI.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
The full storage location of the table (e.g., S3/GCS path).
|
|
||||||
"""
|
|
||||||
return await self._inner.uri()
|
|
||||||
|
|
||||||
async def add(
|
async def add(
|
||||||
self,
|
self,
|
||||||
data: DATA,
|
data: DATA,
|
||||||
|
|||||||
@@ -1967,9 +1967,3 @@ def test_add_table_with_empty_embeddings(tmp_path):
|
|||||||
on_bad_vectors="drop",
|
on_bad_vectors="drop",
|
||||||
)
|
)
|
||||||
assert table.count_rows() == 1
|
assert table.count_rows() == 1
|
||||||
|
|
||||||
|
|
||||||
def test_table_uri(tmp_path):
|
|
||||||
db = lancedb.connect(tmp_path)
|
|
||||||
table = db.create_table("my_table", data=[{"x": 0}])
|
|
||||||
assert table.uri == str(tmp_path / "my_table.lance")
|
|
||||||
|
|||||||
+6
-6
@@ -55,12 +55,12 @@ impl RecordBatchStream {
|
|||||||
.next()
|
.next()
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| PyStopAsyncIteration::new_err(""))?;
|
.ok_or_else(|| PyStopAsyncIteration::new_err(""))?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
inner_next
|
||||||
let bound = inner_next.infer_error()?.to_pyarrow(py)?;
|
.infer_error()?
|
||||||
Ok(bound.unbind())
|
.to_pyarrow(py)
|
||||||
})?;
|
.map(|obj| obj.unbind())
|
||||||
Ok(py_obj)
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -297,6 +297,8 @@ impl Connection {
|
|||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::ListNamespacesRequest;
|
use lance_namespace::models::ListNamespacesRequest;
|
||||||
let request = ListNamespacesRequest {
|
let request = ListNamespacesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -304,11 +306,9 @@ impl Connection {
|
|||||||
},
|
},
|
||||||
page_token,
|
page_token,
|
||||||
limit: limit.map(|l| l as i32),
|
limit: limit.map(|l| l as i32),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let response = inner.list_namespaces(request).await.infer_error()?;
|
let response = inner.list_namespaces(request).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| -> PyResult<Py<PyDict>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("namespaces", response.namespaces)?;
|
dict.set_item("namespaces", response.namespaces)?;
|
||||||
dict.set_item("page_token", response.page_token)?;
|
dict.set_item("page_token", response.page_token)?;
|
||||||
@@ -328,25 +328,25 @@ impl Connection {
|
|||||||
let py = self_.py();
|
let py = self_.py();
|
||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::CreateNamespaceRequest;
|
use lance_namespace::models::CreateNamespaceRequest;
|
||||||
let mode_enum = mode.and_then(|m| match m.to_lowercase().as_str() {
|
let mode_value = mode.and_then(|m| match m.to_lowercase().as_str() {
|
||||||
"create" => Some("Create".to_string()),
|
"create" => Some("Create".to_string()),
|
||||||
"exist_ok" => Some("ExistOk".to_string()),
|
"exist_ok" => Some("ExistOk".to_string()),
|
||||||
"overwrite" => Some("Overwrite".to_string()),
|
"overwrite" => Some("Overwrite".to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let request = CreateNamespaceRequest {
|
let request = CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(namespace)
|
Some(namespace)
|
||||||
},
|
},
|
||||||
mode: mode_enum,
|
mode: mode_value,
|
||||||
properties,
|
properties,
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let response = inner.create_namespace(request).await.infer_error()?;
|
let response = inner.create_namespace(request).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| -> PyResult<Py<PyDict>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("properties", response.properties)?;
|
dict.set_item("properties", response.properties)?;
|
||||||
Ok(dict.unbind())
|
Ok(dict.unbind())
|
||||||
@@ -365,29 +365,29 @@ impl Connection {
|
|||||||
let py = self_.py();
|
let py = self_.py();
|
||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::DropNamespaceRequest;
|
use lance_namespace::models::DropNamespaceRequest;
|
||||||
let mode_enum = mode.and_then(|m| match m.to_uppercase().as_str() {
|
let mode_value = mode.and_then(|m| match m.to_uppercase().as_str() {
|
||||||
"SKIP" => Some("Skip".to_string()),
|
"SKIP" => Some("Skip".to_string()),
|
||||||
"FAIL" => Some("Fail".to_string()),
|
"FAIL" => Some("Fail".to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let behavior_enum = behavior.and_then(|b| match b.to_uppercase().as_str() {
|
let behavior_value = behavior.and_then(|b| match b.to_uppercase().as_str() {
|
||||||
"RESTRICT" => Some("Restrict".to_string()),
|
"RESTRICT" => Some("Restrict".to_string()),
|
||||||
"CASCADE" => Some("Cascade".to_string()),
|
"CASCADE" => Some("Cascade".to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let request = DropNamespaceRequest {
|
let request = DropNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(namespace)
|
Some(namespace)
|
||||||
},
|
},
|
||||||
mode: mode_enum,
|
mode: mode_value,
|
||||||
behavior: behavior_enum,
|
behavior: behavior_value,
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let response = inner.drop_namespace(request).await.infer_error()?;
|
let response = inner.drop_namespace(request).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| -> PyResult<Py<PyDict>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("properties", response.properties)?;
|
dict.set_item("properties", response.properties)?;
|
||||||
dict.set_item("transaction_id", response.transaction_id)?;
|
dict.set_item("transaction_id", response.transaction_id)?;
|
||||||
@@ -406,16 +406,16 @@ impl Connection {
|
|||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::DescribeNamespaceRequest;
|
use lance_namespace::models::DescribeNamespaceRequest;
|
||||||
let request = DescribeNamespaceRequest {
|
let request = DescribeNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(namespace)
|
Some(namespace)
|
||||||
},
|
},
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let response = inner.describe_namespace(request).await.infer_error()?;
|
let response = inner.describe_namespace(request).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| -> PyResult<Py<PyDict>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("properties", response.properties)?;
|
dict.set_item("properties", response.properties)?;
|
||||||
Ok(dict.unbind())
|
Ok(dict.unbind())
|
||||||
@@ -435,6 +435,8 @@ impl Connection {
|
|||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::ListTablesRequest;
|
use lance_namespace::models::ListTablesRequest;
|
||||||
let request = ListTablesRequest {
|
let request = ListTablesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -442,11 +444,9 @@ impl Connection {
|
|||||||
},
|
},
|
||||||
page_token,
|
page_token,
|
||||||
limit: limit.map(|l| l as i32),
|
limit: limit.map(|l| l as i32),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let response = inner.list_tables(request).await.infer_error()?;
|
let response = inner.list_tables(request).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| -> PyResult<Py<PyDict>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("tables", response.tables)?;
|
dict.set_item("tables", response.tables)?;
|
||||||
dict.set_item("page_token", response.page_token)?;
|
dict.set_item("page_token", response.page_token)?;
|
||||||
|
|||||||
+47
-54
@@ -40,34 +40,31 @@ impl<T> PythonErrorExt<T> for std::result::Result<T, LanceError> {
|
|||||||
request_id,
|
request_id,
|
||||||
source,
|
source,
|
||||||
status_code,
|
status_code,
|
||||||
} => {
|
} => Python::attach(|py| {
|
||||||
#[allow(deprecated)]
|
let message = err.to_string();
|
||||||
Python::with_gil(|py| {
|
let http_err_cls = py
|
||||||
let message = err.to_string();
|
.import(intern!(py, "lancedb.remote.errors"))?
|
||||||
let http_err_cls = py
|
.getattr(intern!(py, "HttpError"))?;
|
||||||
.import(intern!(py, "lancedb.remote.errors"))?
|
let err = http_err_cls.call1((
|
||||||
.getattr(intern!(py, "HttpError"))?;
|
message,
|
||||||
let err = http_err_cls.call1((
|
request_id,
|
||||||
message,
|
status_code.map(|s| s.as_u16()),
|
||||||
|
))?;
|
||||||
|
|
||||||
|
if let Some(cause) = source.source() {
|
||||||
|
// The HTTP error already includes the first cause. But
|
||||||
|
// we can add the rest of the chain if there is any more.
|
||||||
|
let cause_err = http_from_rust_error(
|
||||||
|
py,
|
||||||
|
cause,
|
||||||
request_id,
|
request_id,
|
||||||
status_code.map(|s| s.as_u16()),
|
status_code.map(|s| s.as_u16()),
|
||||||
))?;
|
)?;
|
||||||
|
err.setattr(intern!(py, "__cause__"), cause_err)?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(cause) = source.source() {
|
Err(PyErr::from_value(err))
|
||||||
// The HTTP error already includes the first cause. But
|
}),
|
||||||
// we can add the rest of the chain if there is any more.
|
|
||||||
let cause_err = http_from_rust_error(
|
|
||||||
py,
|
|
||||||
cause,
|
|
||||||
request_id,
|
|
||||||
status_code.map(|s| s.as_u16()),
|
|
||||||
)?;
|
|
||||||
err.setattr(intern!(py, "__cause__"), cause_err)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(PyErr::from_value(err))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
LanceError::Retry {
|
LanceError::Retry {
|
||||||
request_id,
|
request_id,
|
||||||
request_failures,
|
request_failures,
|
||||||
@@ -78,37 +75,33 @@ impl<T> PythonErrorExt<T> for std::result::Result<T, LanceError> {
|
|||||||
max_read_failures,
|
max_read_failures,
|
||||||
source,
|
source,
|
||||||
status_code,
|
status_code,
|
||||||
} =>
|
} => Python::attach(|py| {
|
||||||
{
|
let cause_err = http_from_rust_error(
|
||||||
#[allow(deprecated)]
|
py,
|
||||||
Python::with_gil(|py| {
|
source.as_ref(),
|
||||||
let cause_err = http_from_rust_error(
|
request_id,
|
||||||
py,
|
status_code.map(|s| s.as_u16()),
|
||||||
source.as_ref(),
|
)?;
|
||||||
request_id,
|
|
||||||
status_code.map(|s| s.as_u16()),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let message = err.to_string();
|
let message = err.to_string();
|
||||||
let retry_error_cls = py
|
let retry_error_cls = py
|
||||||
.import(intern!(py, "lancedb.remote.errors"))?
|
.import(intern!(py, "lancedb.remote.errors"))?
|
||||||
.getattr("RetryError")?;
|
.getattr("RetryError")?;
|
||||||
let err = retry_error_cls.call1((
|
let err = retry_error_cls.call1((
|
||||||
message,
|
message,
|
||||||
request_id,
|
request_id,
|
||||||
*request_failures,
|
*request_failures,
|
||||||
*connect_failures,
|
*connect_failures,
|
||||||
*read_failures,
|
*read_failures,
|
||||||
*max_request_failures,
|
*max_request_failures,
|
||||||
*max_connect_failures,
|
*max_connect_failures,
|
||||||
*max_read_failures,
|
*max_read_failures,
|
||||||
status_code.map(|s| s.as_u16()),
|
status_code.map(|s| s.as_u16()),
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
err.setattr(intern!(py, "__cause__"), cause_err)?;
|
err.setattr(intern!(py, "__cause__"), cause_err)?;
|
||||||
Err(PyErr::from_value(err))
|
Err(PyErr::from_value(err))
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
_ => self.runtime_error(),
|
_ => self.runtime_error(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ pub struct PyHeaderProvider {
|
|||||||
|
|
||||||
impl Clone for PyHeaderProvider {
|
impl Clone for PyHeaderProvider {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| Self {
|
||||||
Python::with_gil(|py| Self {
|
|
||||||
provider: self.provider.clone_ref(py),
|
provider: self.provider.clone_ref(py),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -26,8 +25,7 @@ impl PyHeaderProvider {
|
|||||||
|
|
||||||
/// Get headers from the Python provider (internal implementation)
|
/// Get headers from the Python provider (internal implementation)
|
||||||
fn get_headers_internal(&self) -> Result<HashMap<String, String>, String> {
|
fn get_headers_internal(&self) -> Result<HashMap<String, String>, String> {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
// Call the get_headers method
|
// Call the get_headers method
|
||||||
let result = self.provider.call_method0(py, "get_headers");
|
let result = self.provider.call_method0(py, "get_headers");
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use pyo3::{
|
|||||||
exceptions::PyRuntimeError,
|
exceptions::PyRuntimeError,
|
||||||
pyclass, pymethods,
|
pyclass, pymethods,
|
||||||
types::{PyAnyMethods, PyDict, PyDictMethods, PyType},
|
types::{PyAnyMethods, PyDict, PyDictMethods, PyType},
|
||||||
Bound, Py, PyAny, PyRef, PyRefMut, PyResult, Python,
|
Bound, PyAny, PyRef, PyRefMut, PyResult, Python,
|
||||||
};
|
};
|
||||||
use pyo3_async_runtimes::tokio::future_into_py;
|
use pyo3_async_runtimes::tokio::future_into_py;
|
||||||
|
|
||||||
@@ -281,12 +281,7 @@ impl PyPermutationReader {
|
|||||||
let reader = slf.reader.clone();
|
let reader = slf.reader.clone();
|
||||||
future_into_py(slf.py(), async move {
|
future_into_py(slf.py(), async move {
|
||||||
let schema = reader.output_schema(selection).await.infer_error()?;
|
let schema = reader.output_schema(selection).await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.as_ref().to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-25
@@ -29,7 +29,6 @@ use pyo3::types::PyList;
|
|||||||
use pyo3::types::{PyDict, PyString};
|
use pyo3::types::{PyDict, PyString};
|
||||||
use pyo3::Bound;
|
use pyo3::Bound;
|
||||||
use pyo3::IntoPyObject;
|
use pyo3::IntoPyObject;
|
||||||
use pyo3::Py;
|
|
||||||
use pyo3::PyAny;
|
use pyo3::PyAny;
|
||||||
use pyo3::PyRef;
|
use pyo3::PyRef;
|
||||||
use pyo3::PyResult;
|
use pyo3::PyResult;
|
||||||
@@ -454,12 +453,7 @@ impl Query {
|
|||||||
let inner = self_.inner.clone();
|
let inner = self_.inner.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let schema = inner.output_schema().await.infer_error()?;
|
let schema = inner.output_schema().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,12 +532,7 @@ impl TakeQuery {
|
|||||||
let inner = self_.inner.clone();
|
let inner = self_.inner.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let schema = inner.output_schema().await.infer_error()?;
|
let schema = inner.output_schema().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,12 +627,7 @@ impl FTSQuery {
|
|||||||
let inner = self_.inner.clone();
|
let inner = self_.inner.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let schema = inner.output_schema().await.infer_error()?;
|
let schema = inner.output_schema().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,12 +806,7 @@ impl VectorQuery {
|
|||||||
let inner = self_.inner.clone();
|
let inner = self_.inner.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let schema = inner.output_schema().await.infer_error()?;
|
let schema = inner.output_schema().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ pub struct PyStorageOptionsProvider {
|
|||||||
|
|
||||||
impl Clone for PyStorageOptionsProvider {
|
impl Clone for PyStorageOptionsProvider {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| Self {
|
||||||
Python::with_gil(|py| Self {
|
|
||||||
inner: self.inner.clone_ref(py),
|
inner: self.inner.clone_ref(py),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -31,17 +30,14 @@ impl Clone for PyStorageOptionsProvider {
|
|||||||
|
|
||||||
impl PyStorageOptionsProvider {
|
impl PyStorageOptionsProvider {
|
||||||
pub fn new(obj: Py<PyAny>) -> PyResult<Self> {
|
pub fn new(obj: Py<PyAny>) -> PyResult<Self> {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
// Verify the object has a fetch_storage_options method
|
// Verify the object has a fetch_storage_options method
|
||||||
if !obj.bind(py).hasattr("fetch_storage_options")? {
|
if !obj.bind(py).hasattr("fetch_storage_options")? {
|
||||||
return Err(pyo3::exceptions::PyTypeError::new_err(
|
return Err(pyo3::exceptions::PyTypeError::new_err(
|
||||||
"StorageOptionsProvider must implement fetch_storage_options() method",
|
"StorageOptionsProvider must implement fetch_storage_options() method",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self { inner: obj })
|
||||||
inner: obj.clone_ref(py),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,8 +60,7 @@ impl StorageOptionsProvider for PyStorageOptionsProviderWrapper {
|
|||||||
let py_provider = self.py_provider.clone();
|
let py_provider = self.py_provider.clone();
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
// Call the Python fetch_storage_options method
|
// Call the Python fetch_storage_options method
|
||||||
let result = py_provider
|
let result = py_provider
|
||||||
.inner
|
.inner
|
||||||
@@ -124,8 +119,7 @@ impl StorageOptionsProvider for PyStorageOptionsProviderWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn provider_id(&self) -> String {
|
fn provider_id(&self) -> String {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
// Call provider_id() method on the Python object
|
// Call provider_id() method on the Python object
|
||||||
let obj = self.py_provider.inner.bind(py);
|
let obj = self.py_provider.inner.bind(py);
|
||||||
obj.call_method0("provider_id")
|
obj.call_method0("provider_id")
|
||||||
|
|||||||
+6
-20
@@ -21,7 +21,7 @@ use pyo3::{
|
|||||||
exceptions::{PyKeyError, PyRuntimeError, PyValueError},
|
exceptions::{PyKeyError, PyRuntimeError, PyValueError},
|
||||||
pyclass, pymethods,
|
pyclass, pymethods,
|
||||||
types::{IntoPyDict, PyAnyMethods, PyDict, PyDictMethods},
|
types::{IntoPyDict, PyAnyMethods, PyDict, PyDictMethods},
|
||||||
Bound, FromPyObject, Py, PyAny, PyRef, PyResult, Python,
|
Bound, FromPyObject, PyAny, PyRef, PyResult, Python,
|
||||||
};
|
};
|
||||||
use pyo3_async_runtimes::tokio::future_into_py;
|
use pyo3_async_runtimes::tokio::future_into_py;
|
||||||
|
|
||||||
@@ -287,12 +287,7 @@ impl Table {
|
|||||||
let inner = self_.inner_ref()?.clone();
|
let inner = self_.inner_ref()?.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let schema = inner.schema().await.infer_error()?;
|
let schema = inner.schema().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| schema.to_pyarrow(py).map(|obj| obj.unbind()))
|
||||||
let py_obj: Py<PyAny> = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
|
||||||
let bound = schema.to_pyarrow(py)?;
|
|
||||||
Ok(bound.unbind())
|
|
||||||
})?;
|
|
||||||
Ok(py_obj)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,8 +437,7 @@ impl Table {
|
|||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let stats = inner.index_stats(&index_name).await.infer_error()?;
|
let stats = inner.index_stats(&index_name).await.infer_error()?;
|
||||||
if let Some(stats) = stats {
|
if let Some(stats) = stats {
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("num_indexed_rows", stats.num_indexed_rows)?;
|
dict.set_item("num_indexed_rows", stats.num_indexed_rows)?;
|
||||||
dict.set_item("num_unindexed_rows", stats.num_unindexed_rows)?;
|
dict.set_item("num_unindexed_rows", stats.num_unindexed_rows)?;
|
||||||
@@ -473,8 +467,7 @@ impl Table {
|
|||||||
let inner = self_.inner_ref()?.clone();
|
let inner = self_.inner_ref()?.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let stats = inner.stats().await.infer_error()?;
|
let stats = inner.stats().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("total_bytes", stats.total_bytes)?;
|
dict.set_item("total_bytes", stats.total_bytes)?;
|
||||||
dict.set_item("num_rows", stats.num_rows)?;
|
dict.set_item("num_rows", stats.num_rows)?;
|
||||||
@@ -504,11 +497,6 @@ impl Table {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uri(self_: PyRef<'_, Self>) -> PyResult<Bound<'_, PyAny>> {
|
|
||||||
let inner = self_.inner_ref()?.clone();
|
|
||||||
future_into_py(self_.py(), async move { inner.uri().await.infer_error() })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
None => format!("ClosedTable({})", self.name),
|
None => format!("ClosedTable({})", self.name),
|
||||||
@@ -528,8 +516,7 @@ impl Table {
|
|||||||
let inner = self_.inner_ref()?.clone();
|
let inner = self_.inner_ref()?.clone();
|
||||||
future_into_py(self_.py(), async move {
|
future_into_py(self_.py(), async move {
|
||||||
let versions = inner.list_versions().await.infer_error()?;
|
let versions = inner.list_versions().await.infer_error()?;
|
||||||
#[allow(deprecated)]
|
let versions_as_dict = Python::attach(|py| {
|
||||||
let versions_as_dict = Python::with_gil(|py| {
|
|
||||||
versions
|
versions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
@@ -880,8 +867,7 @@ impl Tags {
|
|||||||
let tags = inner.tags().await.infer_error()?;
|
let tags = inner.tags().await.infer_error()?;
|
||||||
let res = tags.list().await.infer_error()?;
|
let res = tags.list().await.infer_error()?;
|
||||||
|
|
||||||
#[allow(deprecated)]
|
Python::attach(|py| {
|
||||||
Python::with_gil(|py| {
|
|
||||||
let py_dict = PyDict::new(py);
|
let py_dict = PyDict::new(py);
|
||||||
for (key, contents) in res {
|
for (key, contents) in res {
|
||||||
let value_dict = PyDict::new(py);
|
let value_dict = PyDict::new(py);
|
||||||
|
|||||||
@@ -463,20 +463,9 @@ impl ListingDatabase {
|
|||||||
validate_table_name(name)?;
|
validate_table_name(name)?;
|
||||||
|
|
||||||
let mut uri = self.uri.clone();
|
let mut uri = self.uri.clone();
|
||||||
// If the URI does not end with a path separator, add one
|
// If the URI does not end with a slash, add one
|
||||||
// Use forward slash for URIs (http://, s3://, gs://, file://, etc.)
|
if !uri.ends_with('/') {
|
||||||
// Use platform-specific separator for local paths without scheme
|
uri.push('/');
|
||||||
let has_scheme = uri.contains("://");
|
|
||||||
let ends_with_separator = uri.ends_with('/') || uri.ends_with('\\');
|
|
||||||
|
|
||||||
if !ends_with_separator {
|
|
||||||
if has_scheme {
|
|
||||||
// URIs always use forward slash
|
|
||||||
uri.push('/');
|
|
||||||
} else {
|
|
||||||
// Local path without scheme - use platform separator
|
|
||||||
uri.push(std::path::MAIN_SEPARATOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Append the table name with the lance file extension
|
// Append the table name with the lance file extension
|
||||||
uri.push_str(&format!("{}.{}", name, LANCE_FILE_EXTENSION));
|
uri.push_str(&format!("{}.{}", name, LANCE_FILE_EXTENSION));
|
||||||
@@ -1082,7 +1071,6 @@ mod tests {
|
|||||||
use crate::table::{Table, TableDefinition};
|
use crate::table::{Table, TableDefinition};
|
||||||
use arrow_array::{Int32Array, RecordBatch, StringArray};
|
use arrow_array::{Int32Array, RecordBatch, StringArray};
|
||||||
use arrow_schema::{DataType, Field, Schema};
|
use arrow_schema::{DataType, Field, Schema};
|
||||||
use std::path::PathBuf;
|
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
async fn setup_database() -> (tempfile::TempDir, ListingDatabase) {
|
async fn setup_database() -> (tempfile::TempDir, ListingDatabase) {
|
||||||
@@ -2058,19 +2046,6 @@ mod tests {
|
|||||||
assert_eq!(db_options.new_table_config.enable_stable_row_ids, None);
|
assert_eq!(db_options.new_table_config.enable_stable_row_ids, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_table_uri() {
|
|
||||||
let (_tempdir, db) = setup_database().await;
|
|
||||||
|
|
||||||
let mut pb = PathBuf::new();
|
|
||||||
pb.push(db.uri.clone());
|
|
||||||
pb.push("test.lance");
|
|
||||||
|
|
||||||
let expected = pb.to_str().unwrap();
|
|
||||||
let uri = db.table_uri("test").ok().unwrap();
|
|
||||||
assert_eq!(uri, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_namespace_client() {
|
async fn test_namespace_client() {
|
||||||
let (_tempdir, db) = setup_database().await;
|
let (_tempdir, db) = setup_database().await;
|
||||||
|
|||||||
@@ -134,10 +134,11 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
|
|
||||||
async fn table_names(&self, request: TableNamesRequest) -> Result<Vec<String>> {
|
async fn table_names(&self, request: TableNamesRequest) -> Result<Vec<String>> {
|
||||||
let ns_request = ListTablesRequest {
|
let ns_request = ListTablesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(request.namespace),
|
id: Some(request.namespace),
|
||||||
page_token: request.start_after,
|
page_token: request.start_after,
|
||||||
limit: request.limit.map(|l| l as i32),
|
limit: request.limit.map(|l| l as i32),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = self.namespace.list_tables(ns_request).await?;
|
let response = self.namespace.list_tables(ns_request).await?;
|
||||||
@@ -153,9 +154,13 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
let mut table_id = request.namespace.clone();
|
let mut table_id = request.namespace.clone();
|
||||||
table_id.push(request.name.clone());
|
table_id.push(request.name.clone());
|
||||||
let describe_request = DescribeTableRequest {
|
let describe_request = DescribeTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
version: None,
|
version: None,
|
||||||
..Default::default()
|
with_table_uri: None,
|
||||||
|
load_detailed_metadata: None,
|
||||||
|
vend_credentials: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let describe_result = self.namespace.describe_table(describe_request).await;
|
let describe_result = self.namespace.describe_table(describe_request).await;
|
||||||
@@ -172,8 +177,9 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
if describe_result.is_ok() {
|
if describe_result.is_ok() {
|
||||||
// Drop the existing table - must succeed
|
// Drop the existing table - must succeed
|
||||||
let drop_request = DropTableRequest {
|
let drop_request = DropTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
self.namespace
|
self.namespace
|
||||||
.drop_table(drop_request)
|
.drop_table(drop_request)
|
||||||
@@ -206,10 +212,15 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
table_id.push(request.name.clone());
|
table_id.push(request.name.clone());
|
||||||
|
|
||||||
let create_empty_request = DeclareTableRequest {
|
let create_empty_request = DeclareTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
location: None,
|
location: None,
|
||||||
vend_credentials: None,
|
vend_credentials: if self.storage_options.is_empty() {
|
||||||
..Default::default()
|
None
|
||||||
|
} else {
|
||||||
|
Some(true)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_empty_response = self
|
let create_empty_response = self
|
||||||
@@ -282,8 +293,9 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
table_id.push(name.to_string());
|
table_id.push(name.to_string());
|
||||||
|
|
||||||
let drop_request = DropTableRequest {
|
let drop_request = DropTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(table_id),
|
id: Some(table_id),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
self.namespace
|
self.namespace
|
||||||
.drop_table(drop_request)
|
.drop_table(drop_request)
|
||||||
@@ -438,10 +450,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -500,10 +513,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -565,10 +579,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -650,10 +665,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -707,10 +723,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -789,10 +806,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -824,10 +842,11 @@ mod tests {
|
|||||||
|
|
||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(vec!["test_ns".into()]),
|
id: Some(vec!["test_ns".into()]),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
|
|||||||
@@ -54,8 +54,6 @@
|
|||||||
//! You can also use [`ConnectOptions`] to configure the connection to the database.
|
//! You can also use [`ConnectOptions`] to configure the connection to the database.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(feature = "aws")]
|
|
||||||
//! # {
|
|
||||||
//! use object_store::aws::AwsCredential;
|
//! use object_store::aws::AwsCredential;
|
||||||
//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
|
//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
//! let db = lancedb::connect("data/sample-lancedb")
|
//! let db = lancedb::connect("data/sample-lancedb")
|
||||||
@@ -68,7 +66,6 @@
|
|||||||
//! .await
|
//! .await
|
||||||
//! .unwrap();
|
//! .unwrap();
|
||||||
//! # });
|
//! # });
|
||||||
//! # }
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! LanceDB uses [arrow-rs](https://github.com/apache/arrow-rs) to define schema, data types and array itself.
|
//! LanceDB uses [arrow-rs](https://github.com/apache/arrow-rs) to define schema, data types and array itself.
|
||||||
|
|||||||
@@ -1717,10 +1717,11 @@ mod tests {
|
|||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
let namespace = vec!["test_ns".to_string()];
|
let namespace = vec!["test_ns".to_string()];
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -1744,10 +1745,11 @@ mod tests {
|
|||||||
// List tables in the child namespace
|
// List tables in the child namespace
|
||||||
let list_response = conn
|
let list_response = conn
|
||||||
.list_tables(ListTablesRequest {
|
.list_tables(ListTablesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
page_token: None,
|
page_token: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to list tables");
|
.expect("Failed to list tables");
|
||||||
@@ -1757,10 +1759,11 @@ mod tests {
|
|||||||
let namespace_client = conn.namespace_client().await.unwrap();
|
let namespace_client = conn.namespace_client().await.unwrap();
|
||||||
let list_response = namespace_client
|
let list_response = namespace_client
|
||||||
.list_tables(ListTablesRequest {
|
.list_tables(ListTablesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
page_token: None,
|
page_token: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1799,10 +1802,11 @@ mod tests {
|
|||||||
// Create a child namespace first
|
// Create a child namespace first
|
||||||
let namespace = vec!["multi_table_ns".to_string()];
|
let namespace = vec!["multi_table_ns".to_string()];
|
||||||
conn.create_namespace(CreateNamespaceRequest {
|
conn.create_namespace(CreateNamespaceRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
mode: None,
|
mode: None,
|
||||||
properties: None,
|
properties: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create namespace");
|
.expect("Failed to create namespace");
|
||||||
@@ -1826,10 +1830,11 @@ mod tests {
|
|||||||
// List tables in the child namespace
|
// List tables in the child namespace
|
||||||
let list_response = conn
|
let list_response = conn
|
||||||
.list_tables(ListTablesRequest {
|
.list_tables(ListTablesRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
page_token: None,
|
page_token: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -204,7 +204,6 @@ pub struct RemoteTable<S: HttpSend = Sender> {
|
|||||||
server_version: ServerVersion,
|
server_version: ServerVersion,
|
||||||
|
|
||||||
version: RwLock<Option<u64>>,
|
version: RwLock<Option<u64>>,
|
||||||
location: RwLock<Option<String>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: HttpSend> RemoteTable<S> {
|
impl<S: HttpSend> RemoteTable<S> {
|
||||||
@@ -222,7 +221,6 @@ impl<S: HttpSend> RemoteTable<S> {
|
|||||||
identifier,
|
identifier,
|
||||||
server_version,
|
server_version,
|
||||||
version: RwLock::new(None),
|
version: RwLock::new(None),
|
||||||
location: RwLock::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,7 +639,6 @@ impl<S: HttpSend> RemoteTable<S> {
|
|||||||
struct TableDescription {
|
struct TableDescription {
|
||||||
version: u64,
|
version: u64,
|
||||||
schema: JsonSchema,
|
schema: JsonSchema,
|
||||||
location: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: HttpSend> std::fmt::Display for RemoteTable<S> {
|
impl<S: HttpSend> std::fmt::Display for RemoteTable<S> {
|
||||||
@@ -670,7 +667,6 @@ mod test_utils {
|
|||||||
identifier: name,
|
identifier: name,
|
||||||
server_version: version.map(ServerVersion).unwrap_or_default(),
|
server_version: version.map(ServerVersion).unwrap_or_default(),
|
||||||
version: RwLock::new(None),
|
version: RwLock::new(None),
|
||||||
location: RwLock::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1465,28 +1461,8 @@ impl<S: HttpSend> BaseTable for RemoteTable<S> {
|
|||||||
message: "table_definition is not supported on LanceDB cloud.".into(),
|
message: "table_definition is not supported on LanceDB cloud.".into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
async fn uri(&self) -> Result<String> {
|
fn dataset_uri(&self) -> &str {
|
||||||
// Check if we already have the location cached
|
"NOT_SUPPORTED"
|
||||||
{
|
|
||||||
let location = self.location.read().await;
|
|
||||||
if let Some(ref loc) = *location {
|
|
||||||
return Ok(loc.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch from server via describe
|
|
||||||
let description = self.describe().await?;
|
|
||||||
let location = description.location.ok_or_else(|| Error::NotSupported {
|
|
||||||
message: "Table URI not supported by the server".into(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Cache the location for future use
|
|
||||||
{
|
|
||||||
let mut cached_location = self.location.write().await;
|
|
||||||
*cached_location = Some(location.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(location)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn storage_options(&self) -> Option<HashMap<String, String>> {
|
async fn storage_options(&self) -> Option<HashMap<String, String>> {
|
||||||
@@ -3356,69 +3332,4 @@ mod tests {
|
|||||||
let result = table.drop_columns(&["old_col1", "old_col2"]).await.unwrap();
|
let result = table.drop_columns(&["old_col1", "old_col2"]).await.unwrap();
|
||||||
assert_eq!(result.version, 5);
|
assert_eq!(result.version, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_uri() {
|
|
||||||
let table = Table::new_with_handler("my_table", |request| {
|
|
||||||
assert_eq!(request.method(), "POST");
|
|
||||||
assert_eq!(request.url().path(), "/v1/table/my_table/describe/");
|
|
||||||
|
|
||||||
http::Response::builder()
|
|
||||||
.status(200)
|
|
||||||
.body(r#"{"version": 1, "schema": {"fields": []}, "location": "s3://bucket/path/to/table"}"#)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
let uri = table.uri().await.unwrap();
|
|
||||||
assert_eq!(uri, "s3://bucket/path/to/table");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_uri_missing_location() {
|
|
||||||
let table = Table::new_with_handler("my_table", |request| {
|
|
||||||
assert_eq!(request.method(), "POST");
|
|
||||||
assert_eq!(request.url().path(), "/v1/table/my_table/describe/");
|
|
||||||
|
|
||||||
// Server returns response without location field
|
|
||||||
http::Response::builder()
|
|
||||||
.status(200)
|
|
||||||
.body(r#"{"version": 1, "schema": {"fields": []}}"#)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = table.uri().await;
|
|
||||||
assert!(result.is_err());
|
|
||||||
assert!(matches!(&result, Err(Error::NotSupported { .. })));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_uri_caching() {
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
let call_count = Arc::new(AtomicUsize::new(0));
|
|
||||||
let call_count_clone = call_count.clone();
|
|
||||||
|
|
||||||
let table = Table::new_with_handler("my_table", move |request| {
|
|
||||||
assert_eq!(request.url().path(), "/v1/table/my_table/describe/");
|
|
||||||
call_count_clone.fetch_add(1, Ordering::SeqCst);
|
|
||||||
|
|
||||||
http::Response::builder()
|
|
||||||
.status(200)
|
|
||||||
.body(
|
|
||||||
r#"{"version": 1, "schema": {"fields": []}, "location": "gs://bucket/table"}"#,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
// First call should fetch from server
|
|
||||||
let uri1 = table.uri().await.unwrap();
|
|
||||||
assert_eq!(uri1, "gs://bucket/table");
|
|
||||||
assert_eq!(call_count.load(Ordering::SeqCst), 1);
|
|
||||||
|
|
||||||
// Second call should use cached value
|
|
||||||
let uri2 = table.uri().await.unwrap();
|
|
||||||
assert_eq!(uri2, "gs://bucket/table");
|
|
||||||
assert_eq!(call_count.load(Ordering::SeqCst), 1); // Still 1, no new call
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-26
@@ -608,8 +608,8 @@ pub trait BaseTable: std::fmt::Display + std::fmt::Debug + Send + Sync {
|
|||||||
async fn list_versions(&self) -> Result<Vec<Version>>;
|
async fn list_versions(&self) -> Result<Vec<Version>>;
|
||||||
/// Get the table definition.
|
/// Get the table definition.
|
||||||
async fn table_definition(&self) -> Result<TableDefinition>;
|
async fn table_definition(&self) -> Result<TableDefinition>;
|
||||||
/// Get the table URI (storage location)
|
/// Get the table URI
|
||||||
async fn uri(&self) -> Result<String>;
|
fn dataset_uri(&self) -> &str;
|
||||||
/// Get the storage options used when opening this table, if any.
|
/// Get the storage options used when opening this table, if any.
|
||||||
async fn storage_options(&self) -> Option<HashMap<String, String>>;
|
async fn storage_options(&self) -> Option<HashMap<String, String>>;
|
||||||
/// Poll until the columns are fully indexed. Will return Error::Timeout if the columns
|
/// Poll until the columns are fully indexed. Will return Error::Timeout if the columns
|
||||||
@@ -1317,12 +1317,11 @@ impl Table {
|
|||||||
self.inner.list_indices().await
|
self.inner.list_indices().await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the table URI (storage location)
|
/// Get the underlying dataset URI
|
||||||
///
|
///
|
||||||
/// Returns the full storage location of the table (e.g., S3/GCS path).
|
/// Warning: This is an internal API and the return value is subject to change.
|
||||||
/// For remote tables, this fetches the location from the server via describe.
|
pub fn dataset_uri(&self) -> &str {
|
||||||
pub async fn uri(&self) -> Result<String> {
|
self.inner.dataset_uri()
|
||||||
self.inner.uri().await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the storage options used when opening this table, if any.
|
/// Get the storage options used when opening this table, if any.
|
||||||
@@ -1426,7 +1425,7 @@ impl Table {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let unioned = UnionExec::try_new(projected_plans).map_err(|e| Error::Runtime {
|
let unioned = UnionExec::try_new(projected_plans).map_err(|e| Error::Runtime {
|
||||||
message: format!("Failed to build union plan: {e}"),
|
message: format!("Failed to union query plans: {}", e),
|
||||||
})?;
|
})?;
|
||||||
// We require 1 partition in the final output
|
// We require 1 partition in the final output
|
||||||
let repartitioned = RepartitionExec::try_new(
|
let repartitioned = RepartitionExec::try_new(
|
||||||
@@ -2349,7 +2348,7 @@ impl NativeTable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Convert select to columns list
|
// Convert select to columns list
|
||||||
let columns: Option<Box<QueryTableRequestColumns>> = match &vq.base.select {
|
let columns = match &vq.base.select {
|
||||||
Select::All => None,
|
Select::All => None,
|
||||||
Select::Columns(cols) => Some(Box::new(QueryTableRequestColumns {
|
Select::Columns(cols) => Some(Box::new(QueryTableRequestColumns {
|
||||||
column_names: Some(cols.clone()),
|
column_names: Some(cols.clone()),
|
||||||
@@ -2389,6 +2388,8 @@ impl NativeTable {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Ok(NsQueryTableRequest {
|
Ok(NsQueryTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: None, // Will be set in namespace_query
|
id: None, // Will be set in namespace_query
|
||||||
k: vq.base.limit.unwrap_or(10) as i32,
|
k: vq.base.limit.unwrap_or(10) as i32,
|
||||||
vector: Box::new(vector),
|
vector: Box::new(vector),
|
||||||
@@ -2408,7 +2409,6 @@ impl NativeTable {
|
|||||||
bypass_vector_index: Some(!vq.use_index),
|
bypass_vector_index: Some(!vq.use_index),
|
||||||
full_text_query,
|
full_text_query,
|
||||||
version: None,
|
version: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
AnyQuery::Query(q) => {
|
AnyQuery::Query(q) => {
|
||||||
@@ -2426,7 +2426,7 @@ impl NativeTable {
|
|||||||
.map(|f| self.filter_to_sql(f))
|
.map(|f| self.filter_to_sql(f))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let columns: Option<Box<QueryTableRequestColumns>> = match &q.select {
|
let columns = match &q.select {
|
||||||
Select::All => None,
|
Select::All => None,
|
||||||
Select::Columns(cols) => Some(Box::new(QueryTableRequestColumns {
|
Select::Columns(cols) => Some(Box::new(QueryTableRequestColumns {
|
||||||
column_names: Some(cols.clone()),
|
column_names: Some(cols.clone()),
|
||||||
@@ -2463,6 +2463,8 @@ impl NativeTable {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Ok(NsQueryTableRequest {
|
Ok(NsQueryTableRequest {
|
||||||
|
identity: None,
|
||||||
|
context: None,
|
||||||
id: None, // Will be set by caller
|
id: None, // Will be set by caller
|
||||||
vector,
|
vector,
|
||||||
k: q.limit.unwrap_or(10) as i32,
|
k: q.limit.unwrap_or(10) as i32,
|
||||||
@@ -2482,7 +2484,6 @@ impl NativeTable {
|
|||||||
fast_search: None,
|
fast_search: None,
|
||||||
lower_bound: None,
|
lower_bound: None,
|
||||||
upper_bound: None,
|
upper_bound: None,
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3235,8 +3236,8 @@ impl BaseTable for NativeTable {
|
|||||||
Ok(results.into_iter().flatten().collect())
|
Ok(results.into_iter().flatten().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn uri(&self) -> Result<String> {
|
fn dataset_uri(&self) -> &str {
|
||||||
Ok(self.uri.clone())
|
self.uri.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn storage_options(&self) -> Option<HashMap<String, String>> {
|
async fn storage_options(&self) -> Option<HashMap<String, String>> {
|
||||||
@@ -5154,15 +5155,16 @@ mod tests {
|
|||||||
let any_query = AnyQuery::VectorQuery(vq);
|
let any_query = AnyQuery::VectorQuery(vq);
|
||||||
let ns_request = table.convert_to_namespace_query(&any_query).unwrap();
|
let ns_request = table.convert_to_namespace_query(&any_query).unwrap();
|
||||||
|
|
||||||
let column_names = ns_request
|
|
||||||
.columns
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|cols| cols.column_names.clone());
|
|
||||||
|
|
||||||
assert_eq!(ns_request.k, 10);
|
assert_eq!(ns_request.k, 10);
|
||||||
assert_eq!(ns_request.offset, Some(5));
|
assert_eq!(ns_request.offset, Some(5));
|
||||||
assert_eq!(ns_request.filter, Some("id > 0".to_string()));
|
assert_eq!(ns_request.filter, Some("id > 0".to_string()));
|
||||||
assert_eq!(column_names, Some(vec!["id".to_string()]));
|
assert_eq!(
|
||||||
|
ns_request
|
||||||
|
.columns
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|columns| columns.column_names.clone()),
|
||||||
|
Some(vec!["id".to_string()])
|
||||||
|
);
|
||||||
assert_eq!(ns_request.vector_column, Some("vector".to_string()));
|
assert_eq!(ns_request.vector_column, Some("vector".to_string()));
|
||||||
assert_eq!(ns_request.distance_type, Some("l2".to_string()));
|
assert_eq!(ns_request.distance_type, Some("l2".to_string()));
|
||||||
assert!(ns_request.vector.single_vector.is_some());
|
assert!(ns_request.vector.single_vector.is_some());
|
||||||
@@ -5199,16 +5201,17 @@ mod tests {
|
|||||||
let any_query = AnyQuery::Query(q);
|
let any_query = AnyQuery::Query(q);
|
||||||
let ns_request = table.convert_to_namespace_query(&any_query).unwrap();
|
let ns_request = table.convert_to_namespace_query(&any_query).unwrap();
|
||||||
|
|
||||||
let column_names = ns_request
|
|
||||||
.columns
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|cols| cols.column_names.clone());
|
|
||||||
|
|
||||||
// Plain queries should pass an empty vector
|
// Plain queries should pass an empty vector
|
||||||
assert_eq!(ns_request.k, 20);
|
assert_eq!(ns_request.k, 20);
|
||||||
assert_eq!(ns_request.offset, Some(5));
|
assert_eq!(ns_request.offset, Some(5));
|
||||||
assert_eq!(ns_request.filter, Some("id > 5".to_string()));
|
assert_eq!(ns_request.filter, Some("id > 5".to_string()));
|
||||||
assert_eq!(column_names, Some(vec!["id".to_string()]));
|
assert_eq!(
|
||||||
|
ns_request
|
||||||
|
.columns
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|columns| columns.column_names.clone()),
|
||||||
|
Some(vec!["id".to_string()])
|
||||||
|
);
|
||||||
assert_eq!(ns_request.with_row_id, Some(true));
|
assert_eq!(ns_request.with_row_id, Some(true));
|
||||||
assert_eq!(ns_request.bypass_vector_index, Some(true));
|
assert_eq!(ns_request.bypass_vector_index, Some(true));
|
||||||
assert!(ns_request.vector_column.is_none()); // No vector column for plain queries
|
assert!(ns_request.vector_column.is_none()); // No vector column for plain queries
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ impl DatasetRef {
|
|||||||
let should_checkout = match &target_ref {
|
let should_checkout = match &target_ref {
|
||||||
refs::Ref::Version(_, Some(target_ver)) => version != target_ver,
|
refs::Ref::Version(_, Some(target_ver)) => version != target_ver,
|
||||||
refs::Ref::Version(_, None) => true, // No specific version, always checkout
|
refs::Ref::Version(_, None) => true, // No specific version, always checkout
|
||||||
|
refs::Ref::Tag(_) => true, // Always checkout for tags
|
||||||
refs::Ref::VersionNumber(target_ver) => version != target_ver,
|
refs::Ref::VersionNumber(target_ver) => version != target_ver,
|
||||||
refs::Ref::Tag(_) => true, // Always checkout for tags
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_checkout {
|
if should_checkout {
|
||||||
|
|||||||
Reference in New Issue
Block a user