From 102518ebda39513aa0bf337be96706df5ad558a0 Mon Sep 17 00:00:00 2001 From: "lancedb-gatefixer[bot]" <313497061+lancedb-gatefixer[bot]@users.noreply.github.com> Date: Fri, 23 Oct 2026 01:09:16 +0800 Subject: [PATCH] fix(python): preserve nested fields in filtered scans (#3816) ## Summary - add a Python regression for filtered scans over deeply nested list/struct values - verify the public query path returns every nested sibling field without an Arrow schema mismatch ## Root cause Older Lance scanner code split filter projections into partial nested arrays and did not recursively merge List children, so a sibling field could be omitted from the returned array while remaining in the declared schema. That merge was fixed upstream in lance-format/lance#4838, and the Lance revision currently pinned by LanceDB contains that fix. This test makes the repair durable at the LanceDB Python API boundary. ## Validation - cd python && uv run --extra tests pytest python/tests/test_query.py::test_filter_preserves_deeply_nested_struct_fields -q - cd python && uv run --extra tests pytest python/tests/test_query.py -q - uv run --project python --extra tests --extra dev ruff check . - uv run --project python --extra tests --extra dev ruff format --check python/python/tests/test_query.py Fixes #2217 Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com> --- python/python/tests/test_query.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/python/python/tests/test_query.py b/python/python/tests/test_query.py index c8d0ad159..58ea7deb5 100644 --- a/python/python/tests/test_query.py +++ b/python/python/tests/test_query.py @@ -833,6 +833,28 @@ def test_with_row_id(table: lancedb.table.Table): assert rs["_rowid"].to_pylist() == [0, 1] +def test_filter_preserves_deeply_nested_struct_fields(tmp_db): + # Regression test for https://github.com/lancedb/lancedb/issues/2217. + data = [ + { + "item": "test", + "sub_obj": { + "second_sub_obj": [ + { + "third_sub_obj": {"int_val": 1}, + "str_val": "test", + } + ] + }, + } + ] + table = tmp_db.create_table("deeply_nested_struct", data=data) + + result = table.search().where("item = 'test'").limit(1).to_arrow() + + assert result.to_pylist() == data + + def test_blob_v2_query_omits_auto_row_id(tmp_db): table = _create_blob_v2_query_table(tmp_db, "test_blob_v2_omits_auto_rowid")