mirror of
https://github.com/lancedb/lancedb.git
synced 2026-08-30 09:58:20 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| edf8159780 |
Generated
+350
-488
File diff suppressed because it is too large
Load Diff
+29
-29
@@ -15,39 +15,39 @@ categories = ["database-implementations"]
|
|||||||
rust-version = "1.78.0"
|
rust-version = "1.78.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
lance = { "version" = "=1.0.1", default-features = false }
|
lance = { "version" = "=2.0.0-beta.6", default-features = false, "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-core = "=1.0.1"
|
lance-core = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-datagen = "=1.0.1"
|
lance-datagen = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-file = "=1.0.1"
|
lance-file = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-io = { "version" = "=1.0.1", default-features = false }
|
lance-io = { "version" = "=2.0.0-beta.6", default-features = false, "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-index = "=1.0.1"
|
lance-index = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-linalg = "=1.0.1"
|
lance-linalg = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-namespace = "=1.0.1"
|
lance-namespace = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-namespace-impls = { "version" = "=1.0.1", default-features = false }
|
lance-namespace-impls = { "version" = "=2.0.0-beta.6", default-features = false, "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-table = "=1.0.1"
|
lance-table = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-testing = "=1.0.1"
|
lance-testing = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-datafusion = "=1.0.1"
|
lance-datafusion = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-encoding = "=1.0.1"
|
lance-encoding = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "git" = "https://github.com/lance-format/lance.git" }
|
||||||
lance-arrow = "=1.0.1"
|
lance-arrow = { "version" = "=2.0.0-beta.6", "tag" = "v2.0.0-beta.6", "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 = "56.2", optional = false }
|
arrow = { version = "57.1", optional = false }
|
||||||
arrow-array = "56.2"
|
arrow-array = "57.1"
|
||||||
arrow-data = "56.2"
|
arrow-data = "57.1"
|
||||||
arrow-ipc = "56.2"
|
arrow-ipc = "57.1"
|
||||||
arrow-ord = "56.2"
|
arrow-ord = "57.1"
|
||||||
arrow-schema = "56.2"
|
arrow-schema = "57.1"
|
||||||
arrow-select = "56.2"
|
arrow-select = "57.1"
|
||||||
arrow-cast = "56.2"
|
arrow-cast = "57.1"
|
||||||
async-trait = "0"
|
async-trait = "0"
|
||||||
datafusion = { version = "50.1", default-features = false }
|
datafusion = { version = "51.0", default-features = false }
|
||||||
datafusion-catalog = "50.1"
|
datafusion-catalog = "51.0"
|
||||||
datafusion-common = { version = "50.1", default-features = false }
|
datafusion-common = { version = "51.0", default-features = false }
|
||||||
datafusion-execution = "50.1"
|
datafusion-execution = "51.0"
|
||||||
datafusion-expr = "50.1"
|
datafusion-expr = "51.0"
|
||||||
datafusion-physical-plan = "50.1"
|
datafusion-physical-plan = "51.0"
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
half = { "version" = "2.6.0", default-features = false, features = [
|
half = { "version" = "2.7.1", default-features = false, features = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
] }
|
] }
|
||||||
futures = "0"
|
futures = "0"
|
||||||
|
|||||||
+4
-4
@@ -14,15 +14,15 @@ name = "_lancedb"
|
|||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arrow = { version = "56.2", features = ["pyarrow"] }
|
arrow = { workspace = true, features = ["pyarrow"] }
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
lancedb = { path = "../rust/lancedb", default-features = false }
|
lancedb = { path = "../rust/lancedb", default-features = false }
|
||||||
lance-core.workspace = true
|
lance-core.workspace = true
|
||||||
lance-namespace.workspace = true
|
lance-namespace.workspace = true
|
||||||
lance-io.workspace = true
|
lance-io.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
pyo3 = { version = "0.25", features = ["extension-module", "abi3-py39"] }
|
pyo3 = { version = "0.26", features = ["extension-module", "abi3-py39"] }
|
||||||
pyo3-async-runtimes = { version = "0.25", features = [
|
pyo3-async-runtimes = { version = "0.26", features = [
|
||||||
"attributes",
|
"attributes",
|
||||||
"tokio-runtime",
|
"tokio-runtime",
|
||||||
] }
|
] }
|
||||||
@@ -32,7 +32,7 @@ snafu.workspace = true
|
|||||||
tokio = { version = "1.40", features = ["sync"] }
|
tokio = { version = "1.40", features = ["sync"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
pyo3-build-config = { version = "0.25", features = [
|
pyo3-build-config = { version = "0.26", features = [
|
||||||
"extension-module",
|
"extension-module",
|
||||||
"abi3-py39",
|
"abi3-py39",
|
||||||
] }
|
] }
|
||||||
|
|||||||
+12
-5
@@ -10,8 +10,7 @@ use arrow::{
|
|||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use lancedb::arrow::SendableRecordBatchStream;
|
use lancedb::arrow::SendableRecordBatchStream;
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::PyStopAsyncIteration, pyclass, pymethods, Bound, PyAny, PyObject, PyRef, PyResult,
|
exceptions::PyStopAsyncIteration, pyclass, pymethods, Bound, Py, PyAny, PyRef, PyResult, Python,
|
||||||
Python,
|
|
||||||
};
|
};
|
||||||
use pyo3_async_runtimes::tokio::future_into_py;
|
use pyo3_async_runtimes::tokio::future_into_py;
|
||||||
|
|
||||||
@@ -36,8 +35,11 @@ impl RecordBatchStream {
|
|||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl RecordBatchStream {
|
impl RecordBatchStream {
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn schema(&self, py: Python) -> PyResult<PyObject> {
|
pub fn schema(&self, py: Python) -> PyResult<Py<PyAny>> {
|
||||||
(*self.schema).clone().into_pyarrow(py)
|
(*self.schema)
|
||||||
|
.clone()
|
||||||
|
.into_pyarrow(py)
|
||||||
|
.map(|bound| bound.unbind())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __aiter__(self_: PyRef<'_, Self>) -> PyRef<'_, Self> {
|
pub fn __aiter__(self_: PyRef<'_, Self>) -> PyRef<'_, Self> {
|
||||||
@@ -53,7 +55,12 @@ impl RecordBatchStream {
|
|||||||
.next()
|
.next()
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| PyStopAsyncIteration::new_err(""))?;
|
.ok_or_else(|| PyStopAsyncIteration::new_err(""))?;
|
||||||
Python::with_gil(|py| inner_next.infer_error()?.to_pyarrow(py))
|
Python::attach(|py| {
|
||||||
|
inner_next
|
||||||
|
.infer_error()?
|
||||||
|
.to_pyarrow(py)
|
||||||
|
.map(|bound| bound.unbind())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-19
@@ -12,7 +12,7 @@ use pyo3::{
|
|||||||
exceptions::{PyRuntimeError, PyValueError},
|
exceptions::{PyRuntimeError, PyValueError},
|
||||||
pyclass, pyfunction, pymethods,
|
pyclass, pyfunction, pymethods,
|
||||||
types::{PyDict, PyDictMethods},
|
types::{PyDict, PyDictMethods},
|
||||||
Bound, FromPyObject, Py, PyAny, PyObject, PyRef, PyResult, Python,
|
Bound, FromPyObject, Py, PyAny, PyRef, PyResult, Python,
|
||||||
};
|
};
|
||||||
use pyo3_async_runtimes::tokio::future_into_py;
|
use pyo3_async_runtimes::tokio::future_into_py;
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ impl Connection {
|
|||||||
data: Bound<'_, PyAny>,
|
data: Bound<'_, PyAny>,
|
||||||
namespace: Vec<String>,
|
namespace: Vec<String>,
|
||||||
storage_options: Option<HashMap<String, String>>,
|
storage_options: Option<HashMap<String, String>>,
|
||||||
storage_options_provider: Option<PyObject>,
|
storage_options_provider: Option<Py<PyAny>>,
|
||||||
location: Option<String>,
|
location: Option<String>,
|
||||||
) -> PyResult<Bound<'a, PyAny>> {
|
) -> PyResult<Bound<'a, PyAny>> {
|
||||||
let inner = self_.get_inner()?.clone();
|
let inner = self_.get_inner()?.clone();
|
||||||
@@ -152,7 +152,7 @@ impl Connection {
|
|||||||
schema: Bound<'_, PyAny>,
|
schema: Bound<'_, PyAny>,
|
||||||
namespace: Vec<String>,
|
namespace: Vec<String>,
|
||||||
storage_options: Option<HashMap<String, String>>,
|
storage_options: Option<HashMap<String, String>>,
|
||||||
storage_options_provider: Option<PyObject>,
|
storage_options_provider: Option<Py<PyAny>>,
|
||||||
location: Option<String>,
|
location: Option<String>,
|
||||||
) -> PyResult<Bound<'a, PyAny>> {
|
) -> PyResult<Bound<'a, PyAny>> {
|
||||||
let inner = self_.get_inner()?.clone();
|
let inner = self_.get_inner()?.clone();
|
||||||
@@ -187,7 +187,7 @@ impl Connection {
|
|||||||
name: String,
|
name: String,
|
||||||
namespace: Vec<String>,
|
namespace: Vec<String>,
|
||||||
storage_options: Option<HashMap<String, String>>,
|
storage_options: Option<HashMap<String, String>>,
|
||||||
storage_options_provider: Option<PyObject>,
|
storage_options_provider: Option<Py<PyAny>>,
|
||||||
index_cache_size: Option<u32>,
|
index_cache_size: Option<u32>,
|
||||||
location: Option<String>,
|
location: Option<String>,
|
||||||
) -> PyResult<Bound<'_, PyAny>> {
|
) -> PyResult<Bound<'_, PyAny>> {
|
||||||
@@ -304,6 +304,7 @@ 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()?;
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
||||||
@@ -325,12 +326,12 @@ impl Connection {
|
|||||||
let inner = self_.get_inner()?.clone();
|
let inner = self_.get_inner()?.clone();
|
||||||
let py = self_.py();
|
let py = self_.py();
|
||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::{create_namespace_request, CreateNamespaceRequest};
|
use lance_namespace::models::CreateNamespaceRequest;
|
||||||
let mode_enum = mode.and_then(|m| match m.to_lowercase().as_str() {
|
let mode_enum = mode.map(|m| match m.to_lowercase().as_str() {
|
||||||
"create" => Some(create_namespace_request::Mode::Create),
|
"create" => "Create".to_string(),
|
||||||
"exist_ok" => Some(create_namespace_request::Mode::ExistOk),
|
"exist_ok" => "ExistOk".to_string(),
|
||||||
"overwrite" => Some(create_namespace_request::Mode::Overwrite),
|
"overwrite" => "Overwrite".to_string(),
|
||||||
_ => None,
|
other => other.to_string(),
|
||||||
});
|
});
|
||||||
let request = CreateNamespaceRequest {
|
let request = CreateNamespaceRequest {
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
@@ -340,6 +341,7 @@ impl Connection {
|
|||||||
},
|
},
|
||||||
mode: mode_enum,
|
mode: mode_enum,
|
||||||
properties,
|
properties,
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let response = inner.create_namespace(request).await.infer_error()?;
|
let response = inner.create_namespace(request).await.infer_error()?;
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
||||||
@@ -360,16 +362,16 @@ impl Connection {
|
|||||||
let inner = self_.get_inner()?.clone();
|
let inner = self_.get_inner()?.clone();
|
||||||
let py = self_.py();
|
let py = self_.py();
|
||||||
future_into_py(py, async move {
|
future_into_py(py, async move {
|
||||||
use lance_namespace::models::{drop_namespace_request, DropNamespaceRequest};
|
use lance_namespace::models::DropNamespaceRequest;
|
||||||
let mode_enum = mode.and_then(|m| match m.to_uppercase().as_str() {
|
let mode_enum = mode.map(|m| match m.to_uppercase().as_str() {
|
||||||
"SKIP" => Some(drop_namespace_request::Mode::Skip),
|
"SKIP" => "Skip".to_string(),
|
||||||
"FAIL" => Some(drop_namespace_request::Mode::Fail),
|
"FAIL" => "Fail".to_string(),
|
||||||
_ => None,
|
other => other.to_string(),
|
||||||
});
|
});
|
||||||
let behavior_enum = behavior.and_then(|b| match b.to_uppercase().as_str() {
|
let behavior_enum = behavior.map(|b| match b.to_uppercase().as_str() {
|
||||||
"RESTRICT" => Some(drop_namespace_request::Behavior::Restrict),
|
"RESTRICT" => "Restrict".to_string(),
|
||||||
"CASCADE" => Some(drop_namespace_request::Behavior::Cascade),
|
"CASCADE" => "Cascade".to_string(),
|
||||||
_ => None,
|
other => other.to_string(),
|
||||||
});
|
});
|
||||||
let request = DropNamespaceRequest {
|
let request = DropNamespaceRequest {
|
||||||
id: if namespace.is_empty() {
|
id: if namespace.is_empty() {
|
||||||
@@ -379,6 +381,7 @@ impl Connection {
|
|||||||
},
|
},
|
||||||
mode: mode_enum,
|
mode: mode_enum,
|
||||||
behavior: behavior_enum,
|
behavior: behavior_enum,
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let response = inner.drop_namespace(request).await.infer_error()?;
|
let response = inner.drop_namespace(request).await.infer_error()?;
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
||||||
@@ -405,6 +408,7 @@ impl Connection {
|
|||||||
} 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()?;
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
||||||
@@ -434,6 +438,7 @@ 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()?;
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
Python::with_gil(|py| -> PyResult<Py<PyDict>> {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![allow(deprecated)]
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -216,7 +216,7 @@ impl<'py> IntoPyObject<'py> for PyQueryVectors {
|
|||||||
let py_objs = self
|
let py_objs = self
|
||||||
.0
|
.0
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| v.to_data().into_pyarrow(py))
|
.map(|v| v.to_data().into_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
PyList::new(py, py_objs)
|
PyList::new(py, py_objs)
|
||||||
}
|
}
|
||||||
@@ -453,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use pyo3::types::PyDict;
|
|||||||
/// Internal wrapper around a Python object implementing StorageOptionsProvider
|
/// Internal wrapper around a Python object implementing StorageOptionsProvider
|
||||||
pub struct PyStorageOptionsProvider {
|
pub struct PyStorageOptionsProvider {
|
||||||
/// The Python object implementing fetch_storage_options()
|
/// The Python object implementing fetch_storage_options()
|
||||||
inner: PyObject,
|
inner: Py<PyAny>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for PyStorageOptionsProvider {
|
impl Clone for PyStorageOptionsProvider {
|
||||||
@@ -29,7 +29,7 @@ impl Clone for PyStorageOptionsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PyStorageOptionsProvider {
|
impl PyStorageOptionsProvider {
|
||||||
pub fn new(obj: PyObject) -> PyResult<Self> {
|
pub fn new(obj: Py<PyAny>) -> PyResult<Self> {
|
||||||
Python::with_gil(|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")? {
|
||||||
@@ -143,7 +143,7 @@ impl std::fmt::Debug for PyStorageOptionsProviderWrapper {
|
|||||||
/// This is the main entry point for converting Python StorageOptionsProvider objects
|
/// This is the main entry point for converting Python StorageOptionsProvider objects
|
||||||
/// to Rust trait objects that can be used by the Lance ecosystem.
|
/// to Rust trait objects that can be used by the Lance ecosystem.
|
||||||
pub fn py_object_to_storage_options_provider(
|
pub fn py_object_to_storage_options_provider(
|
||||||
py_obj: PyObject,
|
py_obj: Py<PyAny>,
|
||||||
) -> PyResult<Arc<dyn StorageOptionsProvider>> {
|
) -> PyResult<Arc<dyn StorageOptionsProvider>> {
|
||||||
let py_provider = PyStorageOptionsProvider::new(py_obj)?;
|
let py_provider = PyStorageOptionsProvider::new(py_obj)?;
|
||||||
Ok(Arc::new(PyStorageOptionsProviderWrapper::new(py_provider)))
|
Ok(Arc::new(PyStorageOptionsProviderWrapper::new(py_provider)))
|
||||||
|
|||||||
+1
-1
@@ -287,7 +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()?;
|
||||||
Python::with_gil(|py| schema.to_pyarrow(py))
|
Python::with_gil(|py| schema.to_pyarrow(py).map(|bound| bound.unbind()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use std::sync::Arc;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use lance_namespace::{
|
use lance_namespace::{
|
||||||
models::{
|
models::{
|
||||||
CreateEmptyTableRequest, CreateNamespaceRequest, CreateNamespaceResponse,
|
CreateNamespaceRequest, CreateNamespaceResponse, DeclareTableRequest,
|
||||||
DescribeNamespaceRequest, DescribeNamespaceResponse, DescribeTableRequest,
|
DescribeNamespaceRequest, DescribeNamespaceResponse, DescribeTableRequest,
|
||||||
DropNamespaceRequest, DropNamespaceResponse, DropTableRequest, ListNamespacesRequest,
|
DropNamespaceRequest, DropNamespaceResponse, DropTableRequest, ListNamespacesRequest,
|
||||||
ListNamespacesResponse, ListTablesRequest, ListTablesResponse,
|
ListNamespacesResponse, ListTablesRequest, ListTablesResponse,
|
||||||
@@ -137,6 +137,7 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
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?;
|
||||||
@@ -154,6 +155,7 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
let describe_request = DescribeTableRequest {
|
let describe_request = DescribeTableRequest {
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
version: None,
|
version: None,
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let describe_result = self.namespace.describe_table(describe_request).await;
|
let describe_result = self.namespace.describe_table(describe_request).await;
|
||||||
@@ -171,6 +173,7 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
// Drop the existing table - must succeed
|
// Drop the existing table - must succeed
|
||||||
let drop_request = DropTableRequest {
|
let drop_request = DropTableRequest {
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
self.namespace
|
self.namespace
|
||||||
.drop_table(drop_request)
|
.drop_table(drop_request)
|
||||||
@@ -202,29 +205,24 @@ 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 create_empty_request = CreateEmptyTableRequest {
|
let declare_request = DeclareTableRequest {
|
||||||
id: Some(table_id.clone()),
|
id: Some(table_id.clone()),
|
||||||
location: None,
|
location: None,
|
||||||
properties: if self.storage_options.is_empty() {
|
vend_credentials: None,
|
||||||
None
|
..Default::default()
|
||||||
} else {
|
|
||||||
Some(self.storage_options.clone())
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_empty_response = self
|
let declare_response = self
|
||||||
.namespace
|
.namespace
|
||||||
.create_empty_table(create_empty_request)
|
.declare_table(declare_request)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::Runtime {
|
.map_err(|e| Error::Runtime {
|
||||||
message: format!("Failed to create empty table: {}", e),
|
message: format!("Failed to declare table: {}", e),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let location = create_empty_response
|
let location = declare_response.location.ok_or_else(|| Error::Runtime {
|
||||||
.location
|
message: "Table location is missing from declare_table response".to_string(),
|
||||||
.ok_or_else(|| Error::Runtime {
|
})?;
|
||||||
message: "Table location is missing from create_empty_table response".to_string(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let native_table = NativeTable::create_from_namespace(
|
let native_table = NativeTable::create_from_namespace(
|
||||||
self.namespace.clone(),
|
self.namespace.clone(),
|
||||||
@@ -281,7 +279,10 @@ impl Database for LanceNamespaceDatabase {
|
|||||||
let mut table_id = namespace.to_vec();
|
let mut table_id = namespace.to_vec();
|
||||||
table_id.push(name.to_string());
|
table_id.push(name.to_string());
|
||||||
|
|
||||||
let drop_request = DropTableRequest { id: Some(table_id) };
|
let drop_request = DropTableRequest {
|
||||||
|
id: Some(table_id),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
self.namespace
|
self.namespace
|
||||||
.drop_table(drop_request)
|
.drop_table(drop_request)
|
||||||
.await
|
.await
|
||||||
@@ -438,6 +439,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -499,6 +501,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -563,6 +566,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -647,6 +651,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -703,6 +708,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -784,6 +790,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -818,6 +825,7 @@ mod tests {
|
|||||||
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");
|
||||||
|
|||||||
@@ -1720,6 +1720,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -1746,6 +1747,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -1758,6 +1760,7 @@ mod tests {
|
|||||||
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,6 +1802,7 @@ mod tests {
|
|||||||
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");
|
||||||
@@ -1825,6 +1829,7 @@ mod tests {
|
|||||||
id: Some(namespace.clone()),
|
id: Some(namespace.clone()),
|
||||||
page_token: None,
|
page_token: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ use lance_index::DatasetIndexExt;
|
|||||||
use lance_index::IndexType;
|
use lance_index::IndexType;
|
||||||
use lance_io::object_store::LanceNamespaceStorageOptionsProvider;
|
use lance_io::object_store::LanceNamespaceStorageOptionsProvider;
|
||||||
use lance_namespace::models::{
|
use lance_namespace::models::{
|
||||||
QueryTableRequest as NsQueryTableRequest, QueryTableRequestFullTextQuery,
|
QueryTableRequest as NsQueryTableRequest, QueryTableRequestColumns,
|
||||||
QueryTableRequestVector, StringFtsQuery,
|
QueryTableRequestFullTextQuery, QueryTableRequestVector, StringFtsQuery,
|
||||||
};
|
};
|
||||||
use lance_namespace::LanceNamespace;
|
use lance_namespace::LanceNamespace;
|
||||||
use lance_table::format::Manifest;
|
use lance_table::format::Manifest;
|
||||||
@@ -1424,7 +1424,7 @@ impl Table {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let unioned = Arc::new(UnionExec::new(projected_plans));
|
let unioned = UnionExec::try_new(projected_plans).unwrap();
|
||||||
// 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(
|
||||||
unioned,
|
unioned,
|
||||||
@@ -2332,6 +2332,18 @@ impl NativeTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert selected columns into the namespace request format.
|
||||||
|
fn namespace_columns(&self, columns: &[String]) -> Option<Box<QueryTableRequestColumns>> {
|
||||||
|
if columns.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Box::new(QueryTableRequestColumns {
|
||||||
|
column_names: Some(columns.to_vec()),
|
||||||
|
column_aliases: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an AnyQuery to the namespace QueryTableRequest format.
|
/// Convert an AnyQuery to the namespace QueryTableRequest format.
|
||||||
fn convert_to_namespace_query(&self, query: &AnyQuery) -> Result<NsQueryTableRequest> {
|
fn convert_to_namespace_query(&self, query: &AnyQuery) -> Result<NsQueryTableRequest> {
|
||||||
match query {
|
match query {
|
||||||
@@ -2348,7 +2360,7 @@ impl NativeTable {
|
|||||||
// Convert select to columns list
|
// Convert select to columns list
|
||||||
let columns = match &vq.base.select {
|
let columns = match &vq.base.select {
|
||||||
Select::All => None,
|
Select::All => None,
|
||||||
Select::Columns(cols) => Some(cols.clone()),
|
Select::Columns(cols) => self.namespace_columns(cols),
|
||||||
Select::Dynamic(_) => {
|
Select::Dynamic(_) => {
|
||||||
return Err(Error::NotSupported {
|
return Err(Error::NotSupported {
|
||||||
message:
|
message:
|
||||||
@@ -2383,6 +2395,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),
|
||||||
@@ -2421,7 +2435,7 @@ impl NativeTable {
|
|||||||
|
|
||||||
let columns = match &q.select {
|
let columns = match &q.select {
|
||||||
Select::All => None,
|
Select::All => None,
|
||||||
Select::Columns(cols) => Some(cols.clone()),
|
Select::Columns(cols) => self.namespace_columns(cols),
|
||||||
Select::Dynamic(_) => {
|
Select::Dynamic(_) => {
|
||||||
return Err(Error::NotSupported {
|
return Err(Error::NotSupported {
|
||||||
message: "Dynamic columns are not supported for server-side query"
|
message: "Dynamic columns are not supported for server-side query"
|
||||||
@@ -2453,6 +2467,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,
|
||||||
@@ -5146,7 +5162,13 @@ mod tests {
|
|||||||
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!(ns_request.columns, Some(vec!["id".to_string()]));
|
let column_names = ns_request
|
||||||
|
.columns
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.column_names.as_ref())
|
||||||
|
.cloned()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(column_names, 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());
|
||||||
@@ -5187,7 +5209,13 @@ mod tests {
|
|||||||
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!(ns_request.columns, Some(vec!["id".to_string()]));
|
let column_names = ns_request
|
||||||
|
.columns
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.column_names.as_ref())
|
||||||
|
.cloned()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(column_names, 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,7 +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::Tag(_) => true, // Always checkout for tags
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_checkout {
|
if should_checkout {
|
||||||
|
|||||||
Reference in New Issue
Block a user