readDataframeBytes used to read the whole Arrow file unbounded — a
stdin / file > 1 GiB would OOM the CLI long before the backend
per-sheet ceilings kicked in. decodeArrowToSheet then materialized
every record into [][]interface{} regardless of size.
Three caps now match the backend's per-sheet hard ceilings:
- byte cap: 256 MiB (covers worst-case 200×50000 cells × ~25 B Arrow
overhead). File path pre-Stat()s before opening; both file and stdin
paths read through io.LimitReader so an oversized input is rejected
without allocating the full payload.
- column cap: 200, checked at schema-decode time before allocating any
per-column slices.
- row cap: 50000, checked during record-batch iteration so a 1M-row
Arrow file is rejected mid-stream instead of fully decoding first.
End-to-end verified against PPE — a 257 MiB file is rejected at file-
Stat with a typed validation error before any read happens.