394394
395395### Transactional Loading
396396
397- ` to_pgsql_transaction() ` wraps one or more loaders so each batch of rows is loaded inside a single transaction. If any
398- loader throws, the whole batch is rolled back:
397+ ` to_pgsql_transaction() ` wraps one or more loaders so every delivery happens inside a transaction: each batch of rows
398+ is loaded in its own transaction, and if any loader throws, the open transaction is rolled back:
399399
400400``` php
401401use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel;
@@ -412,7 +412,20 @@ df()
412412 ->run();
413413```
414414
415- Use ` withIsolationLevel() ` to set the transaction isolation level:
415+ Wrapped ` to_transformation() ` / ` to_branch(...)->withTransformation(...) ` steps with blocking operations (` sortBy() ` ,
416+ ` aggregate() ` , ` groupBy()->aggregate() ` , ` pivot() ` , window functions, ` collect() ` , ` join() ` - see
417+ [ transformations] ( ../core/transformations.md ) ) buffer the stream and deliver it when the pipeline closes the loader;
418+ ` to_pgsql_transaction() ` opens one final transaction around that delivery - the whole drained stream commits
419+ atomically, a failure during it rolls back. Every wrapped loader must use the same ` Client ` instance as the wrapper -
420+ a loader holding its own ` Client ` escapes the transaction.
421+
422+ Do not place ` write_with_retries() ` inside the wrapper: after a failed statement PostgreSQL aborts the whole
423+ transaction, so every retry attempt fails too. Wrap the transaction instead -
424+ ` write_with_retries(to_pgsql_transaction(...)) ` gives each attempt a fresh transaction (see
425+ [ retry] ( ../core/retry.md ) ).
426+
427+ Use ` withIsolationLevel() ` to set the transaction isolation level; it applies to every transaction the wrapper opens,
428+ including the final one:
416429
417430``` php
418431to_pgsql_transaction($client, to_pgsql_table($client, 'users'))
@@ -421,13 +434,13 @@ to_pgsql_transaction($client, to_pgsql_table($client, 'users'))
421434
422435## Loader DSL Functions Reference
423436
424- | Function | Description |
425- | ------------------------------------------------| -----------------------------------------------------|
426- | ` to_pgsql_table($client, $table) ` | Create a PostgreSQL loader for a table |
427- | ` to_pgsql_transaction($client, ...$loaders) ` | Run multiple loaders within a single transaction |
428- | ` pgsql_insert_options(...) ` | Configure insert behavior (conflicts, upsert) |
429- | ` pgsql_update_options($primaryKeys) ` | Configure update behavior (primary key columns) |
430- | ` pgsql_delete_options($primaryKeys) ` | Configure delete behavior (primary key columns) |
437+ | Function | Description |
438+ | ------------------------------------------------| ----------------------------------------------------------- |
439+ | ` to_pgsql_table($client, $table) ` | Create a PostgreSQL loader for a table |
440+ | ` to_pgsql_transaction($client, ...$loaders) ` | Run multiple loaders, every delivery inside a transaction |
441+ | ` pgsql_insert_options(...) ` | Configure insert behavior (conflicts, upsert) |
442+ | ` pgsql_update_options($primaryKeys) ` | Configure update behavior (primary key columns) |
443+ | ` pgsql_delete_options($primaryKeys) ` | Configure delete behavior (primary key columns) |
431444
432445## Schema Conversion
433446
0 commit comments