mirror of
https://github.com/lancedb/lancedb.git
synced 2026-08-18 20:18:37 +00:00
0f8f2a42e3447e43b5eeea34e119acbfd69e31d6
2700 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0f8f2a42e3 |
feat(client): Table.load_columns() REST client for LOAD COLUMNS
Geneva Table.load_columns() parity on the REST-only client. Fills existing
columns from an external Parquet/Lance/IPC source by primary-key join.
- BaseTable::load_columns default (NotSupported) + public Table::load_columns,
taking a LoadColumnsRequest (source uris/format/storage_options, target/source
key, (target, source?) column mappings, on_missing, worker/batch/commit knobs).
- Remote impl POSTs to /v1/table/{id}/load_columns with the matching body;
mock test asserts the request shape.
- PyO3 binding + Python remote Table.load_columns(source, pk, columns, *,
source_format, source_pk, on_missing, ...) accepting a column list or
{target: source} dict.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
c43dbe45f8 |
feat(view): full=True force-rebuild on refresh_materialized_view
View.refresh(full=True) (sync + async) now works -- it previously raised NotImplementedError. Thread the flag through the client: RefreshMaterialized- ViewRequest.full -> the REST body (RemoteRefreshMaterializedViewRequest.full); pyo3 refresh_materialized_view(full=...); Connection.refresh_materialized_view( name, full=) sync + async. A full refresh forces a recompute-and-replace and preserves the view's indexes (reindexed by the distributed indexer). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
339d2bee3f |
feat(view): materialized views are first-class indexable + searchable
Add View.create_index / create_scalar_index / create_fts_index / search as pass-throughs to open_table(name). A materialized view is a real Lance dataset; these let it be indexed and searched like any other table, closing the parity gap with Geneva (whose create_materialized_view returns a first-class Table). The server-side create_index handler records indexes declared on a view so they survive a full refresh (which overwrites the dataset, dropping its indices); that re-apply is wired in the sophon engine. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
cef840463a |
feat(refresh): priority as a per-refresh knob; fix batch_size on RemoteTable
Thread priority (Kueue tier) through refresh_column at every layer (Python sync+async + RemoteTable -> pyo3 -> Rust client trait/public/remote -> REST body), mirroring num_workers/batch_size. The function keeps its priority as a default; the per-refresh value overrides. Also adds the previously-missed batch_size to RemoteTable.refresh_column (the REST sync path). cargo check (lancedb --features remote --tests, lancedb-python) + ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
78884d2755 |
feat(refresh): batch_size is a per-refresh knob (refresh_column), not a function-only option
batch_size / num_workers / max_workers are invocation concerns (how to schedule THIS refresh), so expose batch_size on refresh_column through every layer (Python sync+async -> pyo3 -> Rust client -> the REST RefreshColumnRequest.batch_size, which the handler already forwards into the backfill). num_workers/max_workers were already invocation- placed; batch_size was the gap. The function may still carry a default; the refresh override wins (extends the batch_size_override model). Both crates cargo-check clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a80d3ab082 |
feat(udf): computed columns as expressions -- add_columns(computed={col: fn("input")})
A computed column is an expression over a registered function applied to input
columns, not a UDF coupled to a column. fn("data") already returned the expression
string "fn(data)"; make it a ColumnExpr (a str subclass) that also carries the
function's return type, so add_columns(computed={"vec": embed("data")}) declares the
column with no hand-written type. _normalize_computed handles the new form (and tuple
keys for STRUCT fan-out) and keeps the legacy {col: (sql_type, expression)} tuple.
add_computed_column is deprecated (delegates, with a DeprecationWarning). The function
stays decoupled from columns -- register once, apply anywhere.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
87679116a6 |
feat(mv): partition_by option on create_materialized_view / create_view
Thread an optional partition_by through the client: CreateMaterializedViewRequest -> REST body -> pyo3 binding -> Python create_materialized_view/create_view kwarg (sync + async). The server partitions the view's table function by the named source column -- by IVF index clusters if the column is indexed (image-dedup), else by distinct value. Unifies Geneva's partition_by + partition_by_indexed_column into one knob. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4463a23535 |
feat: async UDF client ergonomics (AsyncConnection/AsyncTable + AsyncView/AsyncJobHandle)
Mirrors the sync ergonomics on the async surface: AsyncConnection create_function(udf, replace=)/create_view/job; AsyncTable.add_computed_column; AsyncView + AsyncJobHandle (await + asyncio.sleep; shared submission-prefix matcher with the sync JobHandle). Decorator + REST routes are shared/already validated; this is the async wrapper layer. Exported from the package root. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
df911fd657 |
fix: JobHandle resolves the manifest job id from the submission id
db.job(id) gets the submission id the refresh/backfill endpoints return, but list_jobs / cancel report the agent's manifest id (<table>-<type>-<first 8 of submission id>). JobHandle now matches that (exact id or submission prefix) so wait()/progress() truly track, and cancel() cancels by the resolved canonical id instead of the unusable submission uuid. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
24cb147383 |
feat: fold UDF authoring into lancedb (udf module + connection/table ergonomics)
Brings the @udf/@table_udf decorator + type inference into lancedb as lancedb.udf (Apache-2.0), and adds the ergonomic glue to the existing connection/table so there's no separate object model: - create_function() accepts a Udf (and a replace= flag) - Table.add_computed_column(column, udf) - create_view(name, source, select, ...) -> View (assembles the SELECT) - Connection.job(job_id) -> JobHandle - View / JobHandle are thin references over a connection Exports udf/table_udf/Udf/JobHandle/View from the package root. The operations stay the existing remote-only methods (enterprise/cloud); the decorator works locally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3d07922170 |
feat: explain_refresh_materialized_view over REST (EXPLAIN REFRESH SDK)
Database trait gains explain_refresh_materialized_view (default NotSupported)
returning an MvRefreshPlan; RemoteDatabase POSTs
/v1/materialized_view/{name}/explain_refresh; Connection method; pyo3
MvRefreshPlan pyclass + binding; sync+async python wrappers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
f38d890190 |
feat: cancel_job over REST (Database::cancel_job + remote impl + pyo3 + python)
Exposes the existing server-side CANCEL JOB (CoordinatorCatalog::cancel_job)
as a REST-backed SDK method: Database trait default NotSupported,
RemoteDatabase POSTs /v1/job/{id}/cancel, pyo3 binding, sync+async python
wrappers. Best-effort: a missing job returns false, not an error. Mock-HTTP
unit test in test_derived_compute_routes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
220724e7a1 |
feat: computed columns as a param on add_columns
Per the interface design: computed columns are parameters on the
existing add_columns operation, not a separate method.
- BaseTable::add_computed_columns((name, sql_type) pairs + a f(args)
expression) -- default NotSupported; RemoteTable posts 'computed'
entries to the existing /v1/table/{id}/add_columns route.
- python add_columns gains computed= on LanceTable, RemoteTable, and
AsyncTable: tbl.add_columns(computed={'doubled': ('FLOAT',
'double_it(val)')}); grouped by expression so struct-returning
functions' columns land adjacently.
|
||
|
|
eeffbeffb5 |
feat: SDK surface for functions, materialized views, jobs, refresh_column
Adds the derived-compute interface to the SDK:
- Database trait: create/list/drop_function, create/refresh/alter/
drop/list_materialized_view, list_jobs -- default implementations
return Error::NotSupported (NotImplementedError in python), so
existing Database impls are unaffected; local single-node
implementations are planned. BaseTable gains refresh_column with
the same default.
- RemoteDatabase/RemoteTable implement them against the server REST
routes (/v1/function/*, /v1/materialized_view/*, /v1/job/list,
/v1/table/{id}/refresh_column), with mock-HTTP unit tests.
- Connection/Table public methods, pyo3 bindings (FunctionInfo,
MaterializedViewInfo, JobInfo pyclasses), and python wrappers:
sync on the DBConnection base (shared by local and remote
connections), async on AsyncConnection; refresh_column on
LanceTable, RemoteTable, and AsyncTable.
|
||
|
|
6416840c33 | test: update python expectations for lance 9.1 | ||
|
|
b030361d86 | test: relax hash split distribution assertions | ||
|
|
325cab394b | chore: update lance dependency to v9.1.0-beta.2 | ||
|
|
bc8674ab22 |
chore!: update lance dependency to v9.0.0-rc.1 (#3673)
BREAKING CHANGE: splits generated by the permutation data loader will not be the same, due to a change in hash function. Updates the Lance dependencies and Java lance-core to [v9.0.0-rc.1](https://github.com/lance-format/lance/releases/tag/v9.0.0-rc.1). Includes the required DataFusion 54 and Lance file-reader compatibility updates. --------- Co-authored-by: Will Jones <willjones127@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
37032151d3 |
feat: support distributed analyze plan metrics in clients (#3675)
Adds client-side support for analyze_plan distributed metrics modes across Rust, Python, and TypeScript clients. Defaults to aggregate for backward compatibility and sends the remote distributed_metrics parameter only when a non-default mode is requested. |
||
|
|
00c4a7b843 |
chore: consolidate skills into one (#3672)
Consolidating skills so we have only one `lancedb` skill, making it
easier to install and work with, vs. installing and using different
skills for "lancedb-column-metadata", "lancedb-branch-ops", etc.
Also deleted lancedb-connect, because the new monoskill uses the
python/TS APIs so it doesn't need extra handholding to connect to the
REST API.
## does it work?
Test 1: do some column metadata operations with 1. no skills, 2. our
previous baseline lancedb skill, 3. the baseline lancedb skill with the
lancedb-column-metadata skill folded in:
```
┌───────────────────────────┬──────────────────────┬────────────────────┬───────────────────────┐
│ eval │ no-skill │ lancedb (original) │ lancedb2-incl-columns │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ 2-add-all-metadata-types │ 2.5/5 · 116s · $0.44 │ 0/5 · 154s · $0.60 │ 5/5 · 58s · $0.26 │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ 3-delete-one-metadata-key │ 4/4 · 67s · $0.23 │ 4/4 · 100s · $0.45 │ 4/4 · 45s · $0.20 │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ TOTAL (per rep avg) │ 6.5/9 · 183s · $0.66 │ 4/9 · 254s · $1.05 │ 9/9 · 103s · $0.46 │
└───────────────────────────┴──────────────────────┴────────────────────┴───────────────────────┘
```
without column-metadata-specific content, it failed because it wrote
keys like `description` instead of `lancedb:description`. That's pretty
undiscoverable without the skill.
Test 2: do some simple branch operations with 1. no skills, 2. our
previous baseline lancedb skill, 3. the combined skill (in this PR):
```
┌───────────────────────────┬────────────────────┬────────────────────┬────────────────────────────────┐
│ eval │ no-skill │ lancedb (original) │ lancedb3-incl-columns-branches │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 5-create-branch │ 2/2 · 64s · $0.30 │ 2/2 · 57s · $0.34 │ 2/2 · 38s · $0.22 │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 6-delete-branch │ 2/2 · 38s · $0.21 │ 2/2 · 44s · $0.27 │ 2/2 · 40s · $0.22 │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 7-switch-branch-and-write │ 1/2 · 96s · $0.49 │ 1/2 · 106s · $0.58 │ 2/2 · 66s · $0.40 │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ TOTAL (per rep avg) │ 5/6 · 199s · $1.00 │ 5/6 · 207s · $1.20 │ 6/6 · 143s · $0.83 │
└───────────────────────────┴────────────────────┴────────────────────┴────────────────────────────────┘
```
Test 3: run everything, with the lancedb (original) skill,
lancedb(original) + all the separate skills, and
lancedb3-incl-columns-branches
```
┌────────────────────────────────┬──────────────────────┬────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
│ eval │ lancedb (original) │ lancedb3-incl-columns-branches │ all-separate (lancedb + connect + column-metadata + branch-ops) │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 1-pick-column-for-image-search │ 2/2 · 141s · $0.67 │ 2/2 · 128s · $0.43 │ 1/2 · 257s · $0.81 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 2-add-all-metadata-types │ 5/5 · 93s · $0.52 │ 5/5 · 54s · $0.30 │ 5/5 · 40s · $0.24 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 3-delete-one-metadata-key │ 4/4 · 84s · $0.44 │ 4/4 · 36s · $0.24 │ 4/4 · 28s · $0.20 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 4-build-index │ 3/3 · 275s · $0.52 │ 3/3 · 84s · $0.39 │ 3/3 · 68s · $0.50 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 5-create-branch │ 2/2 · 39s · $0.31 │ 2/2 · 41s · $0.20 │ 2/2 · 15s · $0.17 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 6-delete-branch │ 2/2 · 59s · $0.25 │ 2/2 · 69s · $0.29 │ 2/2 · 26s · $0.17 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 7-switch-branch-and-write │ 1/2 · 84s · $0.46 │ 2/2 · 62s · $0.40 │ 2/2 · 27s · $0.23 │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ TOTAL │ 19/20 · 774s · $3.17 │ 20/20 · 474s · $2.24 │ 19/20 · 462s · $2.32 │
└────────────────────────────────┴──────────────────────┴────────────────────────────────┴─────────────────────────────────────────────────────────────────┘
```
("lancedb3-incl-columns-branches" is the combined skill in this PR,
all-separate is using the four separate skills.)
For overall performance, it helps to have the specialized skills for
metadata and branching; doesn't really matter whether they're separate
skills or all together. Also doesn't matter much whether it's REST or
Python. So let's merge these skills to make it easier for users.
|
||
|
|
1773fb2239 |
chore: update lance dependency to v9.0.0-beta.24 (#3667)
Updates the Rust workspace Lance dependencies and Java lance-core dependency to v9.0.0-beta.24. Lance tag: https://github.com/lance-format/lance/releases/tag/v9.0.0-beta.24 |
||
|
|
8a4eaaa8b9 | Bump version: 0.32.0-beta.1 → 0.32.0-beta.2 | ||
|
|
3fd322a93a | Bump version: 0.35.0-beta.1 → 0.35.0-beta.2 python-v0.35.0-beta.2 | ||
|
|
d8f0982ee8 |
chore: update lance dependency to v9.0.0-beta.23 (#3665)
Updates the Rust workspace Lance dependencies and Java lance-core from v9.0.0-beta.19 to v9.0.0-beta.23. No compatibility fixes were required; strict workspace Clippy and Rust formatting pass. Lance tag: https://github.com/lance-format/lance/releases/tag/v9.0.0-beta.23 --------- Co-authored-by: Jack Ye <yezhaoqin@gmail.com> |
||
|
|
7276c34c51 |
chore(deps): bump the rust-minor-patch group across 1 directory with 6 updates (#3658)
Bumps the rust-minor-patch group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [regex](https://github.com/rust-lang/regex) | `1.12.4` | `1.13.0` | | [bytes](https://github.com/tokio-rs/bytes) | `1.12.0` | `1.12.1` | | [uuid](https://github.com/uuid-rs/uuid) | `1.23.4` | `1.23.5` | | [http-body](https://github.com/hyperium/http-body) | `1.0.1` | `1.1.0` | | [napi](https://github.com/napi-rs/napi-rs) | `3.10.3` | `3.10.5` | | [napi-derive](https://github.com/napi-rs/napi-rs) | `3.5.9` | `3.5.10` | Updates `regex` from 1.12.4 to 1.13.0 <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rust-lang/regex/blob/master/CHANGELOG.md">regex's changelog</a>.</em></p> <blockquote> <h1>1.13.0 (2026-07-09)</h1> <p>This release includes a new API, a <code>regex!</code> macro, for lazy compilation of a regex from a string literal. If you use regexes a lot, it's likely you've already written one exactly like it. The new macro can be used like this:</p> <pre lang="rust"><code>use regex::regex; <p>fn is_match(line: &str) -> bool {<br /> // The regex will be compiled approximately once and reused automatically.<br /> // This avoids the footgun of using <code>Regex::new</code> here, which would<br /> // guarantee that it would be compiled every time this routine is called.<br /> // This would likely make this routine much slower than it needs to be.<br /> regex!(r"bar|baz").is_match(line)<br /> }</p> <p>let hay = "<br /> path/to/foo:54:Blue Harvest<br /> path/to/bar:90:Something, Something, Something, Dark Side<br /> path/to/baz:3:It's a Trap!<br /> ";</p> <p>let matches = hay.lines().filter(|line| is_match(line)).count();<br /> assert_eq!(matches, 2);<br /> </code></pre></p> <p>Improvements:</p> <ul> <li><a href="https://redirect.github.com/rust-lang/regex/issues/709">#709</a>: Add a new <code>regex!</code> macro for efficient and automatic reuse of a compiled regex.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rust-lang/regex/commit/926af2e68eca3ce089815790541cf50759ba2c59"><code>926af2e</code></a> 1.13.0</li> <li><a href="https://github.com/rust-lang/regex/commit/7d941a93561430cd259bb9ceb84cc66f33ae7be8"><code>7d941a9</code></a> regex-automata-0.4.15</li> <li><a href="https://github.com/rust-lang/regex/commit/e358341229ebd5feb9a78d8cc85b459c3c7b6600"><code>e358341</code></a> api: add <code>regex!</code> macro for lazy compilation</li> <li><a href="https://github.com/rust-lang/regex/commit/c42033379c8760105ef90287f319de73d1572242"><code>c420333</code></a> automata: disable miri on a couple doc tests</li> <li><a href="https://github.com/rust-lang/regex/commit/b9d2cf724f89754ea879b6c223d2292c4d3e2dd3"><code>b9d2cf7</code></a> github: add FUNDING link</li> <li><a href="https://github.com/rust-lang/regex/commit/0858006b1460ba781deda54b8d2b01b3f9f949f7"><code>0858006</code></a> docs: add AI policy for contributors</li> <li><a href="https://github.com/rust-lang/regex/commit/468fc64ecd6493caaca40dbe8319c31c5c08a83d"><code>468fc64</code></a> automata: reject dense DFA start states that are match states</li> <li>See full diff in <a href="https://github.com/rust-lang/regex/compare/1.12.4...1.13.0">compare view</a></li> </ul> </details> <br /> Updates `bytes` from 1.12.0 to 1.12.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tokio-rs/bytes/releases">bytes's releases</a>.</em></p> <blockquote> <h2>Bytes v1.12.1</h2> <h1>1.12.1 (July 8th, 2026)</h1> <h3>Fixed</h3> <ul> <li>Properly handle when <code>Box::new</code> panics (<a href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's changelog</a>.</em></p> <blockquote> <h1>1.12.1 (July 8th, 2026)</h1> <h3>Fixed</h3> <ul> <li>Properly handle when <code>Box::new</code> panics (<a href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tokio-rs/bytes/commit/76c0fbb54ed4336caf9d2311658a2f4a5627c21d"><code>76c0fbb</code></a> Release bytes v1.12.1 (<a href="https://redirect.github.com/tokio-rs/bytes/issues/838">#838</a>)</li> <li><a href="https://github.com/tokio-rs/bytes/commit/924c82bf0053cb13a0fb5165925d564622b2092f"><code>924c82b</code></a> Handle unwinding from Box::new (<a href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li> <li>See full diff in <a href="https://github.com/tokio-rs/bytes/compare/v1.12.0...v1.12.1">compare view</a></li> </ul> </details> <br /> Updates `uuid` from 1.23.4 to 1.23.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/uuid-rs/uuid/releases">uuid's releases</a>.</em></p> <blockquote> <h2>v1.23.5</h2> <h2>What's Changed</h2> <ul> <li>doc: Fix broken link by <a href="https://github.com/frostyplanet"><code>@frostyplanet</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/891">uuid-rs/uuid#891</a></li> <li>perf: Optimize UUID hex parsing and formatting by <a href="https://github.com/geeknoid"><code>@geeknoid</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/894">uuid-rs/uuid#894</a></li> <li>Prepare for 1.23.5 release by <a href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/895">uuid-rs/uuid#895</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/geeknoid"><code>@geeknoid</code></a> made their first contribution in <a href="https://redirect.github.com/uuid-rs/uuid/pull/894">uuid-rs/uuid#894</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/uuid-rs/uuid/compare/v1.23.4...v1.23.5">https://github.com/uuid-rs/uuid/compare/v1.23.4...v1.23.5</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/uuid-rs/uuid/commit/5dc6b3d1a995e6244a386740588c8d094ca30690"><code>5dc6b3d</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/895">#895</a> from uuid-rs/cargo/v1.23.5</li> <li><a href="https://github.com/uuid-rs/uuid/commit/5a7dfe50e2a2cf41a9d4330e00971e891bcb990f"><code>5a7dfe5</code></a> prepare for 1.23.5 release</li> <li><a href="https://github.com/uuid-rs/uuid/commit/9b4bfc8fe359e24638eccf6c6be424c25ad6ba8c"><code>9b4bfc8</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/894">#894</a> from geeknoid/main</li> <li><a href="https://github.com/uuid-rs/uuid/commit/5acc5a550ef1ccec951f1d2618b33e1171a88b9e"><code>5acc5a5</code></a> perf: Optimize UUID hex parsing and formatting</li> <li><a href="https://github.com/uuid-rs/uuid/commit/1e5d8679542d2bb15412a86839006dc01f680a51"><code>1e5d867</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/891">#891</a> from frostyplanet/doc</li> <li><a href="https://github.com/uuid-rs/uuid/commit/49310f04afd83b7d7667c1e6d7f26f93f46cedda"><code>49310f0</code></a> doc: Fix broken link</li> <li>See full diff in <a href="https://github.com/uuid-rs/uuid/compare/v1.23.4...v1.23.5">compare view</a></li> </ul> </details> <br /> Updates `http-body` from 1.0.1 to 1.1.0 <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/hyperium/http-body/commit/3396328602f7b147ae7b13f022c2b94dff9434e3"><code>3396328</code></a> http-body v1.1.0</li> <li><a href="https://github.com/hyperium/http-body/commit/2fb78de9c875c364b7eb1a1a117acc3b83ffb13a"><code>2fb78de</code></a> chore: bump license year (<a href="https://redirect.github.com/hyperium/http-body/issues/170">#170</a>)</li> <li><a href="https://github.com/hyperium/http-body/commit/b16554b604e598466f6ae5a2689d637230d56d3e"><code>b16554b</code></a> chore(ci): bump checkout to v7</li> <li><a href="https://github.com/hyperium/http-body/commit/c0c53caee7b5192e83cd2bcd273f66419b8acedc"><code>c0c53ca</code></a> chore(ci): use msrv aware update for msrv job</li> <li><a href="https://github.com/hyperium/http-body/commit/5ed15d2c3d10592c82c4bab30c2cda060831bc47"><code>5ed15d2</code></a> tests: fix clippy::double_parens</li> <li><a href="https://github.com/hyperium/http-body/commit/c8cb37f9ce2f8723b25e1ef1a9f6cb63ef1f9c54"><code>c8cb37f</code></a> Derive <code>Copy</code> trait to <code>SizeHint</code> struct (<a href="https://redirect.github.com/hyperium/http-body/issues/164">#164</a>)</li> <li><a href="https://github.com/hyperium/http-body/commit/915d6d5cbb5406b09f1d95978096094a1d35d5bf"><code>915d6d5</code></a> feat(util): add <code>InspectErr</code>, <code>InspectFrame</code> combinators (<a href="https://redirect.github.com/hyperium/http-body/issues/161">#161</a>)</li> <li><a href="https://github.com/hyperium/http-body/commit/0fc0a9415cff00df921c2e8b5b6bbcb9e1a34263"><code>0fc0a94</code></a> docs: fix broken intradoc links (<a href="https://redirect.github.com/hyperium/http-body/issues/162">#162</a>)</li> <li><a href="https://github.com/hyperium/http-body/commit/5a849d49dc8ddba3382cead6d0368264fae5d827"><code>5a849d4</code></a> chore: add FUNDING.yml</li> <li><a href="https://github.com/hyperium/http-body/commit/1a91851246be2ed913d6ace3f5cc18acf0d1d332"><code>1a91851</code></a> feat: impl <code>Add</code> for <code>SizeHint</code>'s (<a href="https://redirect.github.com/hyperium/http-body/issues/156">#156</a>)</li> <li>Additional commits viewable in <a href="https://github.com/hyperium/http-body/compare/v1.0.1...v1.1.0">compare view</a></li> </ul> </details> <br /> Updates `napi` from 3.10.3 to 3.10.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/napi-rs/napi-rs/releases">napi's releases</a>.</em></p> <blockquote> <h2>napi-v3.10.5</h2> <h3>Fixed</h3> <ul> <li><em>(napi)</em> release FunctionRef off the JS thread via the custom-GC TSFN (<a href="https://redirect.github.com/napi-rs/napi-rs/pull/3394">#3394</a>)</li> </ul> <h2>napi-v3.10.4</h2> <h3>Fixed</h3> <ul> <li><em>(cli)</em> align build and project configuration (<a href="https://redirect.github.com/napi-rs/napi-rs/pull/3387">#3387</a>)</li> </ul> <h3>Other</h3> <ul> <li><em>(readme)</em> point sponsors image at napi.rs/sponsors.svg (<a href="https://redirect.github.com/napi-rs/napi-rs/pull/3379">#3379</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/napi-rs/napi-rs/commit/970988341eb7f859d2df6da1fb7b12f404a2123e"><code>9709883</code></a> chore(napi): release v3.10.5 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3395">#3395</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/c931c97a82ad9da42e86c141ce92cbe322930585"><code>c931c97</code></a> fix(napi): release FunctionRef off the JS thread via the custom-GC TSFN (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3394">#3394</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/3812aa748caeb1fdb72d773564827a23307b81d8"><code>3812aa7</code></a> chore: release (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3380">#3380</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/ce5677944b8e66e44396b435dcb154122b2b8732"><code>ce56779</code></a> chore(release): publish</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/b9825c713ff4f871a47c8be897db9859508f4bd5"><code>b9825c7</code></a> fix(derive): defer receiver borrow until argument conversion (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3392">#3392</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/aa49714ed8a5619d65407ceb4ad9e79a1ee5b332"><code>aa49714</code></a> fix(cli): align build and project configuration (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3387">#3387</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/68cbb8d63a73d4c740c4c1c9b61b82c88e13f8b7"><code>68cbb8d</code></a> chore(deps): update yarn to v4.17.1 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3385">#3385</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/3069f442c30ce3d02e218a29a865ae89d3f50847"><code>3069f44</code></a> fix(sys): fall back to libnode.dll for symbol loading on MSVC targets (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3384">#3384</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/b0157131dc4086debffd321db318eb2c6c905401"><code>b015713</code></a> fix(cli): validate cross-compilation flags upfront and document them accurate...</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/81a35ce09c67765cdfdc06b909318e10d1345193"><code>81a35ce</code></a> chore(deps): update dependency oxc-parser to ^0.139.0 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3382">#3382</a>)</li> <li>Additional commits viewable in <a href="https://github.com/napi-rs/napi-rs/compare/napi-v3.10.3...napi-v3.10.5">compare view</a></li> </ul> </details> <br /> Updates `napi-derive` from 3.5.9 to 3.5.10 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/napi-rs/napi-rs/releases">napi-derive's releases</a>.</em></p> <blockquote> <h2>napi-derive-v3.5.10</h2> <h3>Other</h3> <ul> <li>updated the following local packages: napi-derive-backend</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/napi-rs/napi-rs/commit/3812aa748caeb1fdb72d773564827a23307b81d8"><code>3812aa7</code></a> chore: release (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3380">#3380</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/ce5677944b8e66e44396b435dcb154122b2b8732"><code>ce56779</code></a> chore(release): publish</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/b9825c713ff4f871a47c8be897db9859508f4bd5"><code>b9825c7</code></a> fix(derive): defer receiver borrow until argument conversion (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3392">#3392</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/aa49714ed8a5619d65407ceb4ad9e79a1ee5b332"><code>aa49714</code></a> fix(cli): align build and project configuration (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3387">#3387</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/68cbb8d63a73d4c740c4c1c9b61b82c88e13f8b7"><code>68cbb8d</code></a> chore(deps): update yarn to v4.17.1 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3385">#3385</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/3069f442c30ce3d02e218a29a865ae89d3f50847"><code>3069f44</code></a> fix(sys): fall back to libnode.dll for symbol loading on MSVC targets (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3384">#3384</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/b0157131dc4086debffd321db318eb2c6c905401"><code>b015713</code></a> fix(cli): validate cross-compilation flags upfront and document them accurate...</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/81a35ce09c67765cdfdc06b909318e10d1345193"><code>81a35ce</code></a> chore(deps): update dependency oxc-parser to ^0.139.0 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3382">#3382</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/4bff1272b0c045117c74f541afe9d7b47852181e"><code>4bff127</code></a> docs(readme): point sponsors image at napi.rs/sponsors.svg (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3379">#3379</a>)</li> <li><a href="https://github.com/napi-rs/napi-rs/commit/1ac467e06e71f78b983630926c7908894d08e496"><code>1ac467e</code></a> chore(napi): release v3.10.3 (<a href="https://redirect.github.com/napi-rs/napi-rs/issues/3376">#3376</a>)</li> <li>Additional commits viewable in <a href="https://github.com/napi-rs/napi-rs/compare/napi-derive-v3.5.9...napi-derive-v3.5.10">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
1918d1a3b6 |
fix(rust): skip embedding functions for empty batches (#3646)
Fixes #3174 Also fixes #3645 Empty record batches now append correctly typed empty embedding arrays without invoking embedding providers. This avoids OpenAI requests with an invalid empty input while preserving source-column validation and the non-empty execution paths. As a small cleanup, the single- and multi-embedding code paths now share a single upfront lookup of their source columns ("input_columns") instead of each path looking them up independently. Also moves `lance-testing` from regular dependencies to dev-dependencies where it belongs. Tests run: - `cargo fmt --all -- --check` - `cargo test --quiet -p lancedb --lib empty_batch_skips_embedding_functions` - `cargo test --quiet -p lancedb --lib empty_batch_still_validates_source_column` - `cargo test --quiet -p lancedb --lib test_create_empty_table_with_embeddings` - `cargo check --quiet -p lancedb --features remote --tests --examples` - `cargo clippy --quiet -p lancedb --features remote --tests --examples` - `cargo test --quiet -p lancedb --lib` - `cargo test --quiet --features remote --tests` |
||
|
|
3b626efa47 |
fix(python): fill bad vector values element-wise (#3613)
## Summary Fix `on_bad_vectors="fill"` so it replaces only invalid or missing vector values instead of replacing the entire vector row. Fixes #3026. ## Reasoning The old Python sanitizer detected whether a vector row was bad at row granularity. For `fill`, it then used that row-level flag to replace the whole vector with `[fill_value] * dim`. That meant an input like `[1.0, NaN, 3.0]` became `[0.0, 0.0, 0.0]`, even though the documented and more useful behavior is to preserve valid values and fill only the bad element. I checked whether this should be a Rust-side fix so TypeScript users would benefit too. Today, Rust core exposes `NaNVectorBehavior::{Error, Keep}` for rejecting or keeping NaN vectors, while the Python `on_bad_vectors` API (`error`, `drop`, `fill`, `null`) is implemented in the Python ingestion sanitizer before data reaches Rust. TypeScript does not expose the Python `on_bad_vectors="fill"` behavior today. Moving this exact behavior to Rust would be a broader cross-language API change, so this PR keeps the fix scoped to the currently affected Python API. ## What changed - Added a small helper that fills bad vector rows by preserving valid elements, replacing NaN elements with `fill_value`, truncating vectors longer than the expected dimension, and padding short vectors with `fill_value`. - Kept the existing fast path unchanged: the helper only runs after bad vectors are detected and `on_bad_vectors="fill"` is selected. - Updated sanitizer and table tests to assert element-wise NaN replacement and short-vector padding for both `create_table` and `add`. ## Validation - `uv run ruff format .` - `uv run ruff check .` - `cd python && uv run --no-sync pytest python/tests/test_util.py::test_handle_bad_vectors_jagged python/tests/test_util.py::test_handle_bad_vectors_nan python/tests/test_table.py::test_create_with_nans python/tests/test_table.py::test_add_with_nans -vv` Targeted pytest result: `10 passed`. ## Why this fix is Python-side (and not Rust) The problematic behavior lives in Python’s `on_bad_vectors` sanitizer, before data is handed off to Rust. Rust currently only exposes `NaNVectorBehavior::{Error, Keep}` for add operations, while Python has the richer `on_bad_vectors={"error","drop","fill","null"}` API. TypeScript does not currently expose the Python-style fill behavior, so moving this exact fix into Rust would require designing a broader cross-language bad-vector handling API. This PR keeps the change scoped to the existing affected surface: Python’s `on_bad_vectors="fill"` path. This way, Python users immediately benefit. |
||
|
|
137eac9b50 |
docs: add LanceDB agent skill for portable pipelines (#3662)
## What the new agent skill covers We want to help users _easily_ write LanceDB pipelines to bring their data in from other places, no matter whether they use LanceDB OSS or Enterprise. The `lancedb` set of skills contains guidance for agents on the following: - Distinguishes local and remote table capabilities. - Promotes bounded reads using `select()` and `limit()`. - Prevents accidental full-table materialization. - Documents correct Python sync/async scan APIs. - Recommends validated Python schemas and batched ingestion. - Provides indexing, query-tuning, diagnostics, and maintenance guidance. - Documents the Enterprise table-name cache issue: avoid immediately reusing a dropped or overwritten table name; write to a fresh name and rename after propagation. - Adds Python and TypeScript API, pattern, and performance references. - Adds a heuristic scanner for potentially unsafe Python and TypeScript materialization patterns. This change only adds agent documentation and tooling: no LanceDB runtime code, Rust code, SDK APIs, dependencies, or CI configuration are modified. ## Context The LanceDB agent skill was accidentally pushed directly to `main` in `8ea78e3fbcb26718112ab4ddec55a91804b869d3`, bypassing the normal review workflow. That commit was reverted on `main` by `c12a6dce` so the protected branch is back to its prior content. |
||
|
|
06b53c97d6 |
feat: add table FTS query tokenization (#3659)
## Summary - add table-level FTS query tokenization returning token text and position - use the native index tokenizer for local tables and remote index metadata for remote tables - expose sync and async Python table wrappers with focused coverage |
||
|
|
711e05619b |
perf: skip Dataset::index_statistics() for all index types (#3346)
`Dataset::index_statistics()` loads index files and does meaningful CPU work to serialize low-level info. Most fields `NativeTable::index_stats()` needs are available from manifest metadata via `Dataset::describe_indices()`, which is much cheaper. `NativeTable::index_stats()` now: - Calls `describe_indices()` filtered by name; returns `Ok(None)` if no match. - Parses `distance_type` from `description.details()` JSON (the `VectorIndexDetails` proto stored in the manifest by recent Lance versions). - Falls back to `index_statistics()` only for vector indices where `details()` returns no `distance_type` — this handles older Lance datasets that didn't write `VectorIndexDetails`. - `Unknown` index types (e.g. Lance's internal `FragReuseIndex`) are explicitly filtered out of `list_indices` rather than erroring. ## Test plan - [x] `test_create_scalar_index` — asserts `index_type`, `distance_type`, and `num_unindexed_rows > 0` after adding rows post-index - [x] `test_create_fm_index`, `test_create_bitmap_index`, `test_create_label_list_index` — added `index_stats` assertions - [x] IvfPq, IvfHnswPq, IvfHnswSq, IvfHnswFlat tests assert `distance_type == Some(L2)` - [x] `test_list_indices_skip_frag_reuse` — FragReuseIndex is filtered by the Unknown guard in `list_indices` --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
afc0e5f497 | chore: upgrade spin dependency in lock file to avoid yanked version (#3663) | ||
|
|
c12a6dce9f |
Revert "add LanceDB agent skill for portable pipelines"
This reverts commit
|
||
|
|
8ea78e3fbc | add LanceDB agent skill for portable pipelines | ||
|
|
40238d240a |
fix(python): preserve phrase semantics in sync queries (#3654)
## Summary - serialize sync phrase queries consistently for execution and query plans - restore the documented no-argument hybrid `phrase_query()` behavior - keep reranker input as the original user text without mutating the builder Fixes #3653. ## Testing - `python/.venv/bin/python -m pytest <8 focused test nodes> -q` (`8 passed`) - `python/.venv/bin/python -m ruff format --check python/python/lancedb/query.py python/python/tests/test_fts.py python/python/tests/test_hybrid_query.py` - `python/.venv/bin/python -m ruff check .` - `git diff --check origin/main...HEAD` The complete hybrid module and the real native FTS phrase test were not completed in the current PyO3 runtime environment: both stalled in the native `lancedb.connect()` fixture and were interrupted without an assertion failure. |
||
|
|
60428e1a32 |
chore(deps): bump rand from 0.9.4 to 0.10.1 (#3648)
Bumps [rand](https://github.com/rust-random/rand) from 0.9.4 to 0.10.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rust-random/rand/blob/master/CHANGELOG.md">rand's changelog</a>.</em></p> <blockquote> <h2>[0.10.1] — 2026-02-11</h2> <p>This release includes a fix for a soundness bug; see <a href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>.</p> <h3>Changes</h3> <ul> <li>Document panic behavior of <code>make_rng</code> and add <code>#[track_caller]</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1761">#1761</a>)</li> <li>Deprecate feature <code>log</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>)</li> </ul> <p><a href="https://redirect.github.com/rust-random/rand/issues/1761">#1761</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1761">rust-random/rand#1761</a> <a href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1763">rust-random/rand#1763</a></p> <h2>[0.10.0] - 2026-02-08</h2> <h3>Changes</h3> <ul> <li>The dependency on <code>rand_chacha</code> has been replaced with a dependency on <code>chacha20</code>. This changes the implementation behind <code>StdRng</code>, but the output remains the same. There may be some API breakage when using the ChaCha-types directly as these are now the ones in <code>chacha20</code> instead of <code>rand_chacha</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1642">#1642</a>).</li> <li>Rename fns <code>IndexedRandom::choose_multiple</code> -> <code>sample</code>, <code>choose_multiple_array</code> -> <code>sample_array</code>, <code>choose_multiple_weighted</code> -> <code>sample_weighted</code>, struct <code>SliceChooseIter</code> -> <code>IndexedSamples</code> and fns <code>IteratorRandom::choose_multiple</code> -> <code>sample</code>, <code>choose_multiple_fill</code> -> <code>sample_fill</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1632">#1632</a>)</li> <li>Use Edition 2024 and MSRV 1.85 (<a href="https://redirect.github.com/rust-random/rand/issues/1653">#1653</a>)</li> <li>Let <code>Fill</code> be implemented for element types, not sliceable types (<a href="https://redirect.github.com/rust-random/rand/issues/1652">#1652</a>)</li> <li>Fix <code>OsError::raw_os_error</code> on UEFI targets by returning <code>Option<usize></code> (<a href="https://redirect.github.com/rust-random/rand/issues/1665">#1665</a>)</li> <li>Replace fn <code>TryRngCore::read_adapter(..) -> RngReadAdapter</code> with simpler struct <code>RngReader</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1669">#1669</a>)</li> <li>Remove fns <code>SeedableRng::from_os_rng</code>, <code>try_from_os_rng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1674">#1674</a>)</li> <li>Remove <code>Clone</code> support for <code>StdRng</code>, <code>ReseedingRng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1677">#1677</a>)</li> <li>Use <code>postcard</code> instead of <code>bincode</code> to test the serde feature (<a href="https://redirect.github.com/rust-random/rand/issues/1693">#1693</a>)</li> <li>Avoid excessive allocation in <code>IteratorRandom::sample</code> when <code>amount</code> is much larger than iterator size (<a href="https://redirect.github.com/rust-random/rand/issues/1695">#1695</a>)</li> <li>Rename <code>os_rng</code> -> <code>sys_rng</code>, <code>OsRng</code> -> <code>SysRng</code>, <code>OsError</code> -> <code>SysError</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1697">#1697</a>)</li> <li>Rename <code>Rng</code> -> <code>RngExt</code> as upstream <code>rand_core</code> has renamed <code>RngCore</code> -> <code>Rng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1717">#1717</a>)</li> </ul> <h3>Additions</h3> <ul> <li>Add fns <code>IndexedRandom::choose_iter</code>, <code>choose_weighted_iter</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1632">#1632</a>)</li> <li>Pub export <code>Xoshiro128PlusPlus</code>, <code>Xoshiro256PlusPlus</code> prngs (<a href="https://redirect.github.com/rust-random/rand/issues/1649">#1649</a>)</li> <li>Pub export <code>ChaCha8Rng</code>, <code>ChaCha12Rng</code>, <code>ChaCha20Rng</code> behind <code>chacha</code> feature (<a href="https://redirect.github.com/rust-random/rand/issues/1659">#1659</a>)</li> <li>Fn <code>rand::make_rng() -> R where R: SeedableRng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1734">#1734</a>)</li> </ul> <h3>Removals</h3> <ul> <li>Removed <code>ReseedingRng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1722">#1722</a>)</li> <li>Removed unused feature "nightly" (<a href="https://redirect.github.com/rust-random/rand/issues/1732">#1732</a>)</li> <li>Removed feature <code>small_rng</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1732">#1732</a>)</li> </ul> <p><a href="https://redirect.github.com/rust-random/rand/issues/1632">#1632</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1632">rust-random/rand#1632</a> <a href="https://redirect.github.com/rust-random/rand/issues/1642">#1642</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1642">rust-random/rand#1642</a> <a href="https://redirect.github.com/rust-random/rand/issues/1649">#1649</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1649">rust-random/rand#1649</a> <a href="https://redirect.github.com/rust-random/rand/issues/1652">#1652</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1652">rust-random/rand#1652</a> <a href="https://redirect.github.com/rust-random/rand/issues/1653">#1653</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1653">rust-random/rand#1653</a> <a href="https://redirect.github.com/rust-random/rand/issues/1659">#1659</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1659">rust-random/rand#1659</a> <a href="https://redirect.github.com/rust-random/rand/issues/1665">#1665</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1665">rust-random/rand#1665</a> <a href="https://redirect.github.com/rust-random/rand/issues/1669">#1669</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1669">rust-random/rand#1669</a> <a href="https://redirect.github.com/rust-random/rand/issues/1674">#1674</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1674">rust-random/rand#1674</a> <a href="https://redirect.github.com/rust-random/rand/issues/1677">#1677</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1677">rust-random/rand#1677</a> <a href="https://redirect.github.com/rust-random/rand/issues/1693">#1693</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1693">rust-random/rand#1693</a> <a href="https://redirect.github.com/rust-random/rand/issues/1695">#1695</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1695">rust-random/rand#1695</a> <a href="https://redirect.github.com/rust-random/rand/issues/1697">#1697</a>: <a href="https://redirect.github.com/rust-random/rand/pull/1697">rust-random/rand#1697</a></p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rust-random/rand/commit/27ff4cb7ced3122a1f677fc248c1a07e59ddc8cd"><code>27ff4cb</code></a> Prepare v0.10.1: deprecate feature <code>log</code> (<a href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/98d06386dc4e1d1c89a91f4e483d571921c29ecf"><code>98d0638</code></a> make_rng: document panic and add #[track_caller] (<a href="https://redirect.github.com/rust-random/rand/issues/1761">#1761</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/54e5eaaa7ac11af3aa60b5ccc486182189e6f9ef"><code>54e5eaa</code></a> Fix doc error (<a href="https://redirect.github.com/rust-random/rand/issues/1758">#1758</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/1ce4c080186730595a8d464591d17aac22a42252"><code>1ce4c08</code></a> Bump itoa from 1.0.17 to 1.0.18 in the all-deps group (<a href="https://redirect.github.com/rust-random/rand/issues/1756">#1756</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/ccb734b9c22891a19f11be125c2f09a43809b08e"><code>ccb734b</code></a> docs: fix typo in doc comment (<a href="https://redirect.github.com/rust-random/rand/issues/1754">#1754</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/357eb7de9c9c80184449e8b515c821e48cf4df74"><code>357eb7d</code></a> Bump libc from 0.2.182 to 0.2.183 in the all-deps group (<a href="https://redirect.github.com/rust-random/rand/issues/1753">#1753</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/5e77fe5d61b886988cae67b6d8fb09e405845c63"><code>5e77fe5</code></a> Fix trait references in documentation (<a href="https://redirect.github.com/rust-random/rand/issues/1752">#1752</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/da891850ab2b38f4322ec140ae29d305dfb162c3"><code>da89185</code></a> Bump the all-deps group with 3 updates (<a href="https://redirect.github.com/rust-random/rand/issues/1751">#1751</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/50516ff45c3675d9c2d247e70bc8db691ed8366d"><code>50516ff</code></a> Bump the all-deps group with 2 updates (<a href="https://redirect.github.com/rust-random/rand/issues/1749">#1749</a>)</li> <li><a href="https://github.com/rust-random/rand/commit/fd71de97fdc7050b9a2d8384f5f8afce7d991ca3"><code>fd71de9</code></a> Bump the all-deps group with 2 updates (<a href="https://redirect.github.com/rust-random/rand/issues/1747">#1747</a>)</li> <li>Additional commits viewable in <a href="https://github.com/rust-random/rand/compare/0.9.4...0.10.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
5b982f2f05 |
feat(python): added support for WatsonxReranker component (#3642)
## Summary Adds `WatsonxReranker` to the Python bindings, integrating the [IBM watsonx.ai text rerank API](https://cloud.ibm.com/docs/apis/watsonx-ai#text-rerank) via the `ibm_watsonx_ai` SDK (`pip install ibm-watsonx-ai`). ## Parameters | Parameter | Default | Description | |---|---|---| | `model_name` | `"cross-encoder/ms-marco-minilm-l-12-v2"` | Rerank model ID | | `column` | `"text"` | Table column used as document input | | `top_n` | `None` | Return only the top-n results | | `return_score` | `"relevance"` | `"relevance"` or `"all"` | | `api_key` | `None` | Falls back to `WATSONX_API_KEY` env var | | `project_id` | `None` | Falls back to `WATSONX_PROJECT_ID` env var — mutually exclusive with `space_id` | | `space_id` | `None` | Falls back to `WATSONX_SPACE_ID` env var — mutually exclusive with `project_id` | | `url` | `None` | Defaults to `https://us-south.ml.cloud.ibm.com` | | `truncate_input_tokens` | `None` | Token truncation limit | ## Usage ```python from lancedb.rerankers import WatsonxReranker # credentials from environment variables reranker = WatsonxReranker() # or passed explicitly reranker = WatsonxReranker( api_key="<key>", project_id="<project-id>", # or space_id="<space-id>" top_n=5, ) ``` ## Testing Integration test added in `test_rerankers.py`, skipped unless `WATSONX_API_KEY` and one of `WATSONX_PROJECT_ID` / `WATSONX_SPACE_ID` are set. |
||
|
|
cde48fad95 |
ci: remove CODEOWNERS file (#3655)
The CODEOWNERS file added in #3312 automatically requests reviewers on every PR — the `*` default owner routes all changes to two reviewers. This is mostly noise for contributors, and we prefer a single requested reviewer per PR. Remove the file. Reverts #3312. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1f2068b9fe |
fix(python): gemini batching, user agent and variable dims (#3618)
Carrying over from #2915, this patch introduces: * Single-API call batching support for Gemini embeddings (up to 100 at a time, the API limit) * A versioned user agent header for Gemini API calls * Support for [variable embedding dimension size](https://ai.google.dev/gemini-api/docs/embeddings#control-embedding-size) (Gemini is MRL trained) |
||
|
|
7527890607 |
fix(python): preserve zero distance bounds in hybrid search (#3652)
## Summary - preserve explicit `0.0` distance bounds in synchronous hybrid search - distinguish omitted `None` endpoints from zero-valued endpoints when configuring the vector child query - add a public end-to-end regression test for a zero upper bound ## Testing - `cd python && uv run --extra tests pytest python/tests/test_hybrid_query.py -q` - `uv run --project python ruff format --check python/python/lancedb/query.py python/python/tests/test_hybrid_query.py` - `uv run --project python ruff check .` Fixes #3651 |
||
|
|
a548e59d49 |
feat(python): blob v2 fetch API (#3578)
Python bindings for blob v2 read on **local** tables. Rust read APIs landed in #3562. This PR wires `fetch_blob_files`, `fetch_blobs`, v2 query/`to_pandas(blob_mode="bytes")`, and hidden `_rowid` metadata so `fetch_*` works from query hits without exposing `_rowid` in the column list. **Cloud:** `RemoteTable.fetch_blobs` / `fetch_blob_files` raise `NotImplementedError` until Phalanx ships the server route (separate track; not blocking local merge). ### Primary path: lazy file handles ```python table = db.create_table("videos", schema=pa.schema([ pa.field("id", pa.int64()), lancedb.blob("video"), ])) table.add([{"id": 1, "video": open("clip.mp4", "rb").read()}]) hits = table.search().select(["id", "video"]).to_arrow() handle = table.fetch_blob_files("video", hits)[0] # seek + partial read — PyAV / decoders can use the handle handle.seek(frame_offset) chunk = handle.read_range(0, 65536) ``` `BlobFile` exposes `seek`, `read`, `read_range`, `read_up_to`, and works with `BufferedReader`. ### When you want full bytes ```python blobs = table.fetch_blobs("video", hits) # eager materialize, null-aligned df = table.to_pandas(blob_mode="bytes") # descriptors → bytes in pandas ``` ### `_rowid` (join key, not user `id`) Fetch needs Lance row ids. For v2 blob queries we auto-inject `_rowid`, stash it in Arrow schema metadata on `to_arrow()`, and drop the visible column unless you pass `.with_row_id(True)`. v1 legacy blobs (`lance-encoding:blob`) unchanged; fetch on v1 raises the migration error. ## Test plan - [x] `./scripts/test-blob.sh python` (105 passed in worktree) - [x] `fetch_blob_files` lazy read, seek, partial read, null alignment, cross-fragment dups - [x] hybrid query → `fetch_blobs` / `fetch_blob_files` - [ ] Will re-review after seek/`BlobFile` commit (`d77ab1a6`) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
104fc5a08e | Bump version: 0.32.0-beta.0 → 0.32.0-beta.1 | ||
|
|
715be580d0 | Bump version: 0.35.0-beta.0 → 0.35.0-beta.1 python-v0.35.0-beta.1 | ||
|
|
0d9c87a079 |
ci(nodejs): move Windows builds to larger runner and use ThinLTO (#3634)
The `build - aarch64-pc-windows-msvc` node build job (and, marginally, the x86_64 one) had started hitting `rustc-LLVM ERROR: out of memory` while linking the `lancedb-nodejs` cdylib — most recently surfaced by #3526, which adds the goosefs backend (and its tonic/prost gRPC subtree) to the default node binary. The peak-memory step is the fat-LTO codegen (`lto=fat`, `codegen-units=1` from `.cargo/config.toml`), which merges the whole crate graph into a single LLVM module and runs single-threaded. It therefore neither parallelizes across cores nor fits in the 16 GB of the standard `windows-latest` runner as the dependency graph grows. This PR: - Moves both `*-pc-windows-msvc` node build jobs to `windows-2025-8x-x64` (more memory + cores). - Overrides the release profile to ThinLTO for just these jobs, via `CARGO_PROFILE_RELEASE_LTO=thin` / `CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16` in `pre_build`. ThinLTO parallelizes the cross-module optimization across the runner's cores and keeps peak memory well under the limit. Scoped so Python wheels and Rust release builds keep fat LTO. The larger runner alone would clear the OOM but waste the added cores on the single-threaded fat-LTO tail; ThinLTO is what makes the extra cores actually reduce wall-clock and gives durable memory headroom for future dependency growth. Tradeoff: ThinLTO can leave a small runtime-perf gap vs fat LTO for the node native binary, but it recovers most of it and is a common release configuration. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8e364e6812 | Bump version: 0.31.0-beta.6 → 0.32.0-beta.0 | ||
|
|
32a2776446 | Bump version: 0.34.0-beta.6 → 0.35.0-beta.0 python-v0.35.0-beta.0 | ||
|
|
285add40dd |
feat: expose Lance metrics via OpenTelemetry in Python and Node (#3609)
Bridges Lance's internal `metrics`-crate instrumentation (object store request counts, bytes, latency, errors, and throttles) into OpenTelemetry, in both the Python and Node bindings, with a shared adapter in the Rust core. This is the LanceDB counterpart to lance-format/lance#7537. ## Rust core (`rust/lancedb`) Two new, **off-by-default** features: - `metrics` — re-exports the [`metrics`](https://docs.rs/metrics) crate as `lancedb::metrics` and turns on Lance's object-store instrumentation. Install any `metrics`-compatible recorder to collect them. - `metrics-otel` — adds `lancedb::metrics_otel`, a pull-based adapter that installs a process-global recorder aggregating into lock-free cumulative storage and exposes a snapshot/catalog API (`register_metrics_recorder`, `metrics_catalog`, `snapshot_metrics`, `MetricPoint`/`MetricValue`/`MetricKind`/`MetricDescription`). Both bindings build on this. ## Python `lancedb.otel.instrument_lancedb_metrics()` registers each metric as an OpenTelemetry observable instrument on the given (or global) `MeterProvider`. Available via the `otel` extra (`pip install lancedb[otel]`), which pulls in only `opentelemetry-api` — the application supplies and configures the SDK. ## Node `instrumentLanceDbMetrics()` provides the equivalent wiring against `@opentelemetry/api`. This is the only public entry point; the underlying recorder/catalog/snapshot functions stay internal. Because OpenTelemetry has no asynchronous histogram instrument, histograms are exported Prometheus-style as `<name>_bucket` (with an `le` attribute), `<name>_count`, and `<name>_sum`. Only `_sum` carries the histogram's unit; `_bucket` and `_count` observe cumulative counts and are unitless. The adapter is enabled by default in the Python and Node builds, and off by default in the Rust crate. ## Notes - Requires Lance ≥ `v9.0.0-beta.19`, which ships the object-store metrics APIs (upstream lance-format/lance#7537, now merged). `main` is already on beta.19, so this is a single feature commit with no dependency bump. - Tests: 8 Rust unit tests, 3 Python tests, 2 Node tests, all covering the end-to-end object-store-metrics → OpenTelemetry path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
22bf091de1 |
fix: avoid manifest writes for read-only directory namespace opens (#3635)
Bumps Lance to v9.0.0-beta.19, which includes lance-format/lance#7687 for side-effect-free DirectoryNamespace read paths. This fixes root-level read-only table opens that previously could trigger `__manifest` creation through directory namespace construction, including Hugging Face bucket reads with read-only tokens. A LanceDB regression test now covers root listing operations without creating `__manifest`. Fixes #3633. |
||
|
|
ff81428a9c |
fix(python): flatten_columns raises when flatten=False (#3629)
### Summary
`flatten_columns` raises `ValueError` when called with `flatten=False`,
even though `False` should mean "do not flatten". This is reachable from
the public API — `Query.to_pandas(flatten=...)` and
`to_batches(flatten=...)` type their `flatten` param as
`Optional[Union[int, bool]]` and pass it straight to `flatten_columns`.
### Cause
`bool` is a subclass of `int`, so `isinstance(False, int)` is `True`.
`flatten=False` skips the `flatten is True` check, falls into the
integer branch, and `False <= 0` evaluates to `True`, raising:
```
ValueError: Please specify a positive integer for flatten or the boolean value `True`
```
### Reproduction
```python
import lancedb
db = lancedb.connect("/tmp/db")
t = db.create_table("t", data=[{"id": 1, "vector": [0.1, 0.2]}])
t.search([0.1, 0.2]).to_pandas(flatten=False) # -> ValueError
```
### Fix
Guard the integer branch with `not isinstance(flatten, bool)` so that
`flatten=False` (and `None`) mean "do not flatten". Behavior is
otherwise unchanged:
- `flatten=True` → flatten all nested levels
- positive `int` → flatten to that depth
- non-positive `int` (e.g. `0`) → still rejected with `ValueError`
Added a regression test in `tests/test_util.py` covering `None`,
`False`, `True`, a positive depth, and `0`.
|
||
|
|
75c5c83f12 |
fix(python): resolve Ollama embedding serialization error in create_table (#3583)
This PR fixes a serialization error when using Ollama embeddings in `create_table`. The use of `@cached_property` for the Ollama client was causing issues during serialization/pickling, which is required by certain LanceDB operations (like when using multiprocessing or certain storage backends). Switching to a standard `@property` ensures the client is instantiated when needed without being stored in a way that breaks serialization. Verified with the following script: ```python import lancedb from lancedb.embeddings import get_registry import pickle registry = get_registry().get(\"ollama\") model = registry(name=\"llama3\") # This would fail before the fix pickled = pickle.dumps(model) unpickled = pickle.loads(pickled) ``` Fixes #2629 (or similar serialization issues reported). --------- Co-authored-by: Unmilan Mukherjee <Missing-Identity@users.noreply.github.com> |
||
|
|
291e9e37be |
feat: add Tencent COS and GooseFS object store support via new feature flags (#3526)
## Summary Closes #3525 This PR wires up two new optional object-store backends at the LanceDB layer, exposing capabilities that already exist upstream in `lance` / `lance-io`: | Backend | Cargo feature | Default in Rust crate | Default in Python wheel | Default in Node binding | | --- | --- | --- | --- | --- | | **Tencent COS** | `cos` | ❌ off | ✅ on | ❌ off | | **GooseFS** | `goosefs` | ❌ off | ✅ on | ✅ on | Both backends are additive and do not affect existing users who don't opt in. ## Motivation - **Tencent COS** is the dominant object storage in the China region. Tencent Cloud users currently need an S3-compatible proxy or a private fork to use LanceDB against COS buckets. - **GooseFS** is Tencent Cloud's distributed cache acceleration layer that sits in front of COS/S3, a common pattern for vector search / AI training where the same hot dataset is read repeatedly. - This brings COS / GooseFS to feature parity with the existing first-class backends (`aws`, `gcs`, `azure`, `oss`, `huggingface`). See the linked issue #3525 for the full discussion. ## Changes ### `rust/lancedb/Cargo.toml` Add two new optional features that pull through the corresponding upstream feature flags: ```toml cos = ["lance/tencent", "lance-io/tencent"] goosefs = [ "lance/goosefs", "lance-io/goosefs", "lance-namespace-impls/dir-goosefs", ] ``` ### `python/Cargo.toml` Enable both `cos` and `goosefs` by default for the Python wheels, so `pip install lancedb` works against COS / GooseFS out of the box (consistent with how `aws` / `gcs` / `azure` / `oss` are bundled today): ```diff -default = ["remote", "lancedb/aws", "lancedb/gcs", "lancedb/azure", "lancedb/dynamodb", "lancedb/oss", "lancedb/huggingface"] +default = ["remote", "lancedb/aws", "lancedb/gcs", "lancedb/azure", "lancedb/dynamodb", "lancedb/oss", "lancedb/huggingface", "lancedb/cos", "lancedb/goosefs"] ``` ### `nodejs/Cargo.toml` Enable `goosefs` by default for the Node binding (COS kept opt-in to limit the default native binary size; can be revisited based on demand): ```diff -default = ["remote", "lancedb/aws", "lancedb/gcs", "lancedb/azure", "lancedb/dynamodb", "lancedb/oss", "lancedb/huggingface"] +default = ["remote", "lancedb/aws", "lancedb/gcs", "lancedb/azure", "lancedb/dynamodb", "lancedb/oss", "lancedb/huggingface", "lancedb/goosefs"] ``` ### `Cargo.lock` Regenerated to reflect the transitive dependencies brought in by the new upstream features. No manual edits. ## Example Usage ### Rust ```toml # Cargo.toml lancedb = { version = "0.30", features = ["cos", "goosefs"] } ``` ```rust // Tencent COS let db = lancedb::connect("cos://my-bucket/my-db").execute().await?; // GooseFS let db = lancedb::connect("goosefs://my-namespace/my-db").execute().await?; ``` ### Python ```python import lancedb db = lancedb.connect( "cos://my-bucket/my-db", storage_options={ "secret_id": "...", "secret_key": "...", "region": "ap-guangzhou", }, ) ``` ## Backwards Compatibility - All new features are **opt-in** at the Rust crate level (`default = []` for `lancedb` itself is unchanged). - The Python wheel gains both backends by default, increasing wheel size slightly but matching the existing pattern of bundling all major cloud backends. - Node binding only adds `goosefs` to defaults; existing users see no behavior change. ## Testing - `cargo check --all-features` ✅ - `cargo check -p lancedb --features cos` ✅ - `cargo check -p lancedb --features goosefs` ✅ - End-to-end COS / GooseFS smoke tests require Tencent Cloud credentials and are intentionally not added to CI in this PR (same approach used for `s3-test`). Happy to add a gated test feature in a follow-up if reviewers prefer. ## Checklist - [x] Added `cos` and `goosefs` features to `rust/lancedb/Cargo.toml` - [x] Updated `python/Cargo.toml` default features - [x] Updated `nodejs/Cargo.toml` default features - [x] Regenerated `Cargo.lock` - [x] Verified build with `--all-features` - [ ] Documentation update (can be done in a follow-up PR once API stabilizes) ## Related - Issue: #3525 - Upstream support: [`lance/tencent`](https://github.com/lance-format/lance), [`lance/goosefs`](https://github.com/lance-format/lance) |