Skip to content

Lazy rows - #2666

Open
norberttech wants to merge 17 commits into
1.xfrom
lazy-rows
Open

norberttech wants to merge 17 commits into
1.xfrom
lazy-rows

Conversation

@norberttech

Copy link
Copy Markdown
Member

Resolves: #xxx

Change Log


Added

  • flow-php/etl - columnar Rows batch built by a configurable column Backend (PhpBackend, RustBackend, AdaptiveBackend)
  • flow-php/etl - FileReadLoop / FileBatches and FileWriteFrame / FileSinks shared by every file format
  • flow-php/etl - Rows::select(), Rows::concat(), RowsJoin and ColumnBuilder::appendPhysicals()
  • flow-php/flow-php-ext - native Arrow column backend, CSV, JSON and Parquet read and write as native columns
  • flow-php/arrow-ext - new Parquet core exchanging batches with flow_php through the Arrow C Data Interface
  • flow-php/etl-adapter-http - withBatchSize() on from_static_http_requests()
  • flow-php/etl - Column Backend documentation page and new playground examples

Fixed

  • flow-php/etl - group-by keys stay stable when a batch lacks a nullable key column
  • flow-php/etl - date and datetime keys at the same instant join and group together
  • flow-php/etl - matchTo() reports the first bad row
  • flow-php/etl - html and xml elements keep their parent through a column
  • flow-php/etl-adapter-excel - html, html_element and xml_element cells are written instead of empty
  • flow-php/etl-adapter-seal - html values no longer leak internal bytes
  • flow-php/parquet - DELTA_BINARY_PACKED, unsigned integers and INT96 follow the spec
  • flow-php/filesystem - Path::uri() of a local file keeps the root slash
  • flow-php/etl - to_branch() runs in the WASM playground

Changed

  • flow-php/etl - Row removed, every reader, writer, function and processor works on columns
  • flow-php/etl - the configured backend builds every batch, function result, join, sort, group-by and cache read
  • flow-php/etl - Rows::empty(), matchTo(), project(), concat() and ResultColumn take a Backend
  • flow-php/etl - FloeSerializer and the caches take the serializer and backend explicitly
  • flow-php/etl - file plumbing moved to Extractor\File and Loader\File, column internals to Column\Physical and Column\Layout
  • flow-php/etl - Floe writes one BATCH frame per batch
  • flow-php/etl - a mismatched flow_php or arrow extension build is refused with a clear message
  • flow-php/etl-adapter-csv - header names, absent cells and blank leading rows follow one rule shared with Excel and Google Sheet
  • flow-php/etl-adapter-json - from_json_lines() / to_json_lines() return JsonExtractor / JsonLoader, *JSONEncoder renamed *JsonEncoder
  • flow-php/etl-adapter-excel - CellStyler receives the written cell
  • flow-php/etl-adapter-doctrine - markup is bound as rendered text
  • flow-php/etl-adapter-postgresql - InsertQueryBuilder::build() takes columns, markup is bound as rendered text
  • flow-php/parquet - ParquetEngine follows the Php / Rust / Adaptive pattern, arrow-ext owns Parquet

Removed

  • flow-php/etl - row(), InferredBatch, DataFrame::getEach(), RowsBuffer, RowEquality, DeclaredColumns and eleven Rows helpers
  • flow-php/etl-adapter-json - JsonLinesExtractor and JsonLinesLoader
  • flow-php/etl-adapter-xml - XMLReaderExtractor and XMLLoader::write()
  • flow-php/arrow-ext - RandomAccessFile and OutputStream
  • flow-php/parquet - ArrowParquetEngine, the arrow() factories and Option::BYTE_ARRAY_TO_STRING

Deprecated

Security

- Rows holds a Schema plus one Column per definition; Row is a (Rows, index) view
- Rows::of(Schema, Row ...) and Rows::fromColumns() replace the constructor, trusted() and conformed()
- new Column / ColumnBuilder / Backend contracts with a PHP backend, Config::backend() replaces hydrator()
- FloeEngine, NativeFloeEncoder, adaptive/native hydrators and extension gates removed
- core consumers ported to column operations (gather, slice, project, withColumns)
- a date is midnight at UTC; join collisions suggest a prefix for every join shape
- array_to_row(s) refuse keys the schema does not declare
- extractors project declared columns through DeclaredColumns
- every row() call moves to a declared schema
- docs, upgrading entry, completers and playground phar updated
- remove Hydrator, TypedRowValues, Row\Encoder and Row\RowsBuffer; add Rows\RowsBuffer
- extractors build through RowsBuilder with the context backend, encoders take Rows
- split adapter encoders into decoders and encoders
- Floe takes a Backend instead of a hydrator
- parquet reads column chunks via readColumns() / ParquetFile::columns()
- Parquet and Floe refuse withSchema(), the footer is the schema
- columnar BATCH frame (FrameEncoder/FrameDecoder, BufferLayout), codec per buffer
- row format removed: PhpFloeEncoder, Encoding/Decoding, ROW frames
- read batches are frame-sized, batchSize an upper bound; bucket reads coalesce
- NOT NULL refusal moves to Rows::fromColumns, nested nulls refused on decode
- oversized batches split in halves on OffsetOverflow/FrameTooLarge
- Rows serialize as a BATCH frame; golden fixtures and docs regenerated
- DefaultBackend, NativeColumn, NativeColumnBuilder over Arrow arrays
- flow-batch-frame crate for column buffers and BATCH bodies
- CSV reads straight into native columns via nextColumns()
- Backend gains adopt() and allocatedBytes(); pipelines build with the configured backend
- RawRowValues, row hydrator and ROW-frame encoder removed
- untagged builds report the next minor as -dev; Composer conflict on older extensions
- ScalarFunction evaluates a whole batch into one Column
- sort, join, group-by, window, constraints and aggregates on columns
- uuid/json/date-time values compare by value; one sort order
- spilling steps stop at a process-wide memory limit
- group-by and window stay in memory under the limit
- BucketingProcessor and BucketingStrategy removed
- Rust Parquet core: row groups straight into native columns, offset/limit reads only the row groups needed
- from_parquet()/to_parquet() use flow_php when loaded and no engine is given
- Rows cast to the writer schema once, in the loader, for every engine
- Flow float written as Parquet DOUBLE; invalid UTF-8 refused on write
- PHP engine: nested columns read page by page, DELTA_BINARY_PACKED follows the spec, RLE booleans in v2 pages, required structs with null children
…-ext deprecated

- ParquetEngine::openForRead() returns a ParquetFileReader, replaces readColumns()
- flow_php lib surface: footer read and decoded once in Rust, PHP engine values and write acceptance
- column chunks fetched once per row group instead of per page header
- PhpParquetEngine reads unsigned ints and INT96 exactly, refuses values it wrote wrongly
- from_parquet opens each file once and reads ENUM columns
- TextValues: one per-type text rule for CSV, JSON, XML and Text
- CSV / JSON: one sink per adapter, encoder contracts with PHP and native implementations
- flow_php: native CSV and JSON writers
- Parquet: writeColumns() on the PHP, native and arrow writers
- XML: column-wise encoding, XMLValueNodes
- FloatType casts NAN, INF and -INF
- flow_php casts nested values in one walk into the arrow builders
- container casts stop re-validating, identity physicals for plain nested types, bulk column builders
- XML node documents are UTF-8 and read as text, string cast without re-parsing
- date / numeric-string / xml_element cast fixes, NAN and INF handled without PHP coercion
- just benchmark runs again, comparators registered through a PHPUnit extension
…column

- element bytes carry the owner document, the element path and its markup
- older element bytes still read
- element columns compare by the element markup
…columns

- from_json() / from_json_lines() read natively with flow_php through JsonSourceOpener
- strict JSON on the native lane: malformed input refused with file and record
- batch assembly shared by the CSV and JSON readers, one-value append shared with NativeColumnBuilder
- a scalar JSON record throws RuntimeException instead of TypeError
…hrough the Arrow C Data Interface

- Parquet core and lib surface moved from flow_php into arrow-ext, old Reader/Writer removed
- ArrowParquetEngine runs on arrow-ext again, deprecation undone
- flow_php ETL reader/writer exchange batches with arrow-ext via C Data, imports counted in allocatedBytes()
- native ETL lane needs both extensions, flow_php alone uses the PHP engine
- lib writer on typed arrow-rs builders, rows checked whole before appending
- extensions register the package interfaces; Rust classes implement them
- Adaptive classes are the only extension_loaded() pick per contract
- CSV, JSON and Parquet open sources move into Rust, iterating as Generators
- openers, Default*, Native* and Arrow* classes removed
- ext-php-rs 0.16 in both extensions, rustfmt at width 120
- tools updated, rust-toolchain action repinned
- one file read loop and one write frame for every file format, per-read state out of extractors and loaders
- the configured backend reaches every batch: extractor batches adopted at the read boundary, Rows::concat/matchTo/project, functions, joins, caches, Floe
- no hidden default backend: Floe readers, merger, serializer, Config and caches take it explicitly
- one record decoder for CSV, Excel and Google Sheet; one JSON extractor and loader
- file plumbing moved to Extractor\File, Extractor\Memory and Loader\File; Column\Php split into Physical and Layout
- dead API removed: Rows::merge and ten other Rows methods, Column::builder, RowsBuffer, XMLReaderExtractor
…yground

- flow_php and arrow-ext declare an ABI; a mismatched build is refused instead of failing on a missing class
- local Path::uri() keeps the root slash (file:///...)
- Parquet Option::BYTE_ARRAY_TO_STRING removed
- WASM: ucontext shim over Emscripten fibers, so sinks running in a Fiber (to_branch()) work; undefined symbols now fail the link
- published examples aligned with the columnar API; examples for the column backend, forEach() and CSV header/absent cells
- docs updated for lazy-rows, new column-backend page
… its deprecated schema API

- doctrine/dbal raised to ^4.5, dependencies updated
- tables built through TableEditor instead of deprecated Table::addPrimaryKeyConstraint/addIndex/addUniqueIndex
- Column::getType() replaced by getTypeName()
@norberttech norberttech added this to the 0.45.0 milestone Oct 3, 2026
@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 13.18182% with 382 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.24%. Comparing base (e125c41) to head (82c4600).

Additional details and impacted files
@@             Coverage Diff              @@
##                1.x    #2666      +/-   ##
============================================
- Coverage     88.66%   86.24%   -2.43%     
- Complexity        0     5340    +5340     
============================================
  Files          2044     2203     +159     
  Lines         78135    91198   +13063     
============================================
+ Hits          69276    78650    +9374     
- Misses         8859    12548    +3689     
Components Coverage Δ
etl 94.91% <ø> (-0.45%) ⬇️
cli 87.62% <ø> (ø)
lib-array-dot 96.52% <ø> (ø)
lib-azure-sdk 64.44% <ø> (ø)
lib-doctrine-dbal-bulk 90.93% <ø> (-3.32%) ⬇️
lib-filesystem 86.64% <ø> (-0.98%) ⬇️
lib-types 89.78% <ø> (-4.65%) ⬇️
lib-parquet 64.79% <ø> (-6.59%) ⬇️
lib-parquet-viewer 69.66% <ø> (-12.60%) ⬇️
lib-snappy 90.30% <ø> (ø)
lib-dremel 0.00% <ø> (ø)
lib-postgresql 89.34% <ø> (ø)
lib-telemetry 86.64% <ø> (ø)
bridge-filesystem-async-aws 92.76% <ø> (ø)
bridge-filesystem-azure 90.34% <ø> (ø)
bridge-filesystem-sftp 91.02% <ø> (ø)
bridge-monolog-http 96.84% <ø> (ø)
bridge-monolog-telemetry 94.79% <ø> (ø)
bridge-openapi-specification 91.45% <ø> (ø)
symfony-http-foundation 75.81% <ø> (ø)
bridge-psr18-telemetry 100.00% <ø> (ø)
bridge-psr3-telemetry 98.95% <ø> (ø)
bridge-psr7-telemetry 100.00% <ø> (ø)
bridge-telemetry-otlp 90.11% <ø> (ø)
bridge-symfony-http-foundation-telemetry 92.85% <ø> (ø)
bridge-symfony-filesystem-bundle 91.85% <ø> (ø)
bridge-symfony-filesystem-cache 98.18% <ø> (ø)
bridge-symfony-postgresql-bundle 93.62% <ø> (ø)
bridge-symfony-postgresql-cache 94.41% <ø> (ø)
bridge-symfony-postgresql-messenger 98.80% <ø> (ø)
bridge-symfony-postgresql-session 93.65% <ø> (ø)
bridge-symfony-telemetry-bundle 90.72% <ø> (ø)
adapter-chartjs 61.96% <0.00%> (-18.54%) ⬇️
adapter-csv 69.63% <22.64%> (-25.83%) ⬇️
adapter-doctrine 88.11% <0.00%> (-5.10%) ⬇️
adapter-google-sheet 76.05% <ø> (-23.27%) ⬇️
adapter-http 70.67% <ø> (-17.47%) ⬇️
adapter-json 65.37% <ø> (-25.60%) ⬇️
adapter-logger 44.44% <ø> (ø)
adapter-parquet 80.35% <ø> (-15.73%) ⬇️
adapter-text 62.06% <ø> (-33.39%) ⬇️
adapter-xml 51.76% <ø> (-37.10%) ⬇️
adapter-avro 7.14% <0.00%> (ø)
adapter-excel 80.76% <4.00%> (-15.16%) ⬇️
adapter-postgresql 81.37% <ø> (-14.43%) ⬇️
adapter-seal 72.24% <ø> (-11.65%) ⬇️
bridge-phpunit-postgresql 75.30% <ø> (ø)
bridge-phpunit-telemetry 87.36% <ø> (ø)
bridge-phpstan-types 0.00% <ø> (ø)
bridge-postgresql-valinor 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant