fix(node): support nested blobs with blobMode 'bytes' (#4610)

Closes #4609.

`blobMode: "bytes"` only resolved top-level blob columns, so a blob
nested in a struct came back as its descriptor. Now struct projections
that contain blob columns are resolved too: the bytes are fetched per
blob column and the struct is rebuilt with `LargeBinary` leaves,
preserving struct validity so a null struct stays null. Sibling fields
pass through untouched, aliases work for both `info.image AS image` and
`info AS details`, and blobs nested in lists still keep their
descriptors.

Tested with `npx tsc`, `biome check`, and the full `table.test.ts` suite
(580 tests, including new regressions for select-all, struct selection,
aliases, null structs, null and empty blobs, sibling fields, empty
results, and single-row batches). Not run against remote tables.
This commit is contained in:
Ishita Singh
2026-10-23 03:24:56 +08:00
committed by GitHub
parent a6011dcd95
commit e5873d9763
4 changed files with 258 additions and 33 deletions
@@ -20,12 +20,13 @@ How to return blob v2 columns. Applies to `toArrow()` and `toArray()`.
- `"descriptions"` (default): each blob is a descriptor. Read the bytes
with [Table.fetchBlobs](../classes/Table.md#fetchblobs) or [Table.fetchBlobFiles](../classes/Table.md#fetchblobfiles).
- `"bytes"`: each top-level blob column holds the blob bytes as
`LargeBinary`. The query also reads `_rowid` to fetch the bytes, and
leaves it out of the result unless [QueryBase.withRowId](../classes/QueryBase.md#withrowid) was
called. All the bytes are held in memory.
- `"bytes"`: each blob column holds the blob bytes as `LargeBinary`,
including blobs nested in structs. The query also reads `_rowid` to
fetch the bytes, and leaves it out of the result unless
[QueryBase.withRowId](../classes/QueryBase.md#withrowid) was called. All the bytes are held in
memory.
Blobs nested in a struct or a list keep their descriptors.
Blobs nested in a list keep their descriptors.
The rows and the bytes come from the same table version. If the table
changes while the query runs, the query runs again, up to three times.