Summary
DirectoryNamespace (the filesystem-backed LanceNamespace implementation in
rust/lance-namespace-impls/src/dir.rs) currently falls back to the trait's
default not_supported implementation for two DML operations:
update_table(UpdateTableRequest) -> UpdateTableResponse
delete_from_table(DeleteFromTableRequest) -> DeleteFromTableResponse
Both methods are already wired through the Java side
(DirectoryNamespace.java updateTable / deleteFromTable) and exposed by the
lance-namespace-reqwest-client model, but calling them today returns
OperationNotSupported. This issue tracks adding the Rust-side implementation
so users of dir:// namespaces can perform row-level updates and deletes
through the namespace API, on par with what Dataset::update /
Dataset::delete already provide for direct dataset access.
Motivation
- DML is a baseline capability for any catalog; without it the directory
namespace cannot back interactive workflows or downstream systems
(e.g. GooseFS / LanceDB integrations) that drive Lance via the namespace
trait.
- The underlying primitives (
UpdateBuilder, Dataset::delete) are stable
and well-tested in lance core — exposing them through the namespace layer
is a small, isolated piece of work with no schema/metadata changes.
- Closes the first two unsupported operations listed in
LANCE_UNSUPPORTED_OPS.md §1.2.
Proposed API behavior
update_table
| Field |
Source / Validation |
id |
resolved via existing namespace path resolution; missing → TableNotFound |
updates: List<List<String>> |
each inner list must be [column, expression]; non-empty, no duplicate columns, no empty column names → InvalidInput |
predicate? |
optional; if present, applied through UpdateBuilder::update_where |
Response.updated_rows |
metrics.rows_updated from UpdateBuilder::execute() |
Response.version |
new dataset version after commit |
delete_from_table
| Field |
Source / Validation |
id |
resolved as above |
predicate |
required, non-empty / non-whitespace → otherwise InvalidInput |
Response.version |
new dataset version after Dataset::delete |
Note: the namespace response model has no deleted_rows field, so the
DeleteResult.num_deleted_rows returned by lance core is intentionally
dropped at the namespace boundary.
Error mapping
| Cause |
Mapped error |
Predicate / expression parse failure (DataFusionError) |
InvalidInput |
lance_core::Error::InvalidInput from delete |
InvalidInput |
| Missing table |
TableNotFound (via existing load_dataset) |
Test plan
Add unit tests in rust/lance-namespace-impls/src/dir.rs#tests:
CI gate: cargo fmt --check, cargo clippy -D warnings,
cargo test -p lance-namespace-impls --lib dir::tests all green.
Summary
DirectoryNamespace(the filesystem-backedLanceNamespaceimplementation inrust/lance-namespace-impls/src/dir.rs) currently falls back to the trait'sdefault
not_supportedimplementation for two DML operations:update_table(UpdateTableRequest) -> UpdateTableResponsedelete_from_table(DeleteFromTableRequest) -> DeleteFromTableResponseBoth methods are already wired through the Java side
(
DirectoryNamespace.javaupdateTable/deleteFromTable) and exposed by thelance-namespace-reqwest-clientmodel, but calling them today returnsOperationNotSupported. This issue tracks adding the Rust-side implementationso users of
dir://namespaces can perform row-level updates and deletesthrough the namespace API, on par with what
Dataset::update/Dataset::deletealready provide for direct dataset access.Motivation
namespace cannot back interactive workflows or downstream systems
(e.g. GooseFS / LanceDB integrations) that drive Lance via the namespace
trait.
UpdateBuilder,Dataset::delete) are stableand well-tested in
lancecore — exposing them through the namespace layeris a small, isolated piece of work with no schema/metadata changes.
LANCE_UNSUPPORTED_OPS.md§1.2.Proposed API behavior
update_tableidTableNotFoundupdates: List<List<String>>[column, expression]; non-empty, no duplicate columns, no empty column names →InvalidInputpredicate?UpdateBuilder::update_whereupdated_rowsmetrics.rows_updatedfromUpdateBuilder::execute()versiondelete_from_tableidpredicateInvalidInputversionDataset::deleteError mapping
DataFusionError)InvalidInputlance_core::Error::InvalidInputfrom deleteInvalidInputTableNotFound(via existingload_dataset)Test plan
Add unit tests in
rust/lance-namespace-impls/src/dir.rs#tests:test_update_full_table— full-table update bumps version by 1test_update_with_predicate— only matching rows updatedtest_update_invalid_expression— surfacesInvalidInputtest_update_duplicate_columns—InvalidInputtest_delete_with_predicate— row count decreases, version + 1test_delete_empty_predicate—InvalidInputtest_delete_table_not_found—TableNotFoundCI gate:
cargo fmt --check,cargo clippy -D warnings,cargo test -p lance-namespace-impls --lib dir::testsall green.