Detach materialized SQL rows from transaction lifetime

This commit is contained in:
sergeych committed 2026-04-17 20:38:40 +03:00
1 parent 07cb5a519c
commit 49fc700233
10 files changed
+119 -41

No files matched your search

+4 -4
View File
@@ -61,10 +61,10 @@ Notes:
rather than silently degrading to some other visible type.
- `ResultSet` should stay iterable, but also expose `isEmpty()` for cheap
emptiness checks where possible and `size()` as a separate operation.
- `ResultSet` and all `SqlRow` instances obtained from it are valid only while
the owning transaction is active. After transaction end, any further row or
result-set access should fail with `SqlUsageException`, even if the provider
had buffered data internally.
- `ResultSet` is valid only while the owning transaction is active.
- Materialized `SqlRow` values should be detached snapshots, so
`transaction { tx.select(...).toList() }` is a valid pattern and the rows
remain usable after transaction end.
- Portable SQL parameter values should match the row conversion set: `null`,
`Bool`, `Int`, `Double`, `Decimal`, `String`, `Buffer`,
`Date`, `DateTime`, and `Instant`.
+4 -4
View File
@@ -42,11 +42,11 @@ class SqlRow(
- iteration to the end or canceled iteration should close the underlying
resources automatically
- using the result set after its transaction ends is invalid
- rows obtained from the result set are also invalid after the owning
transaction ends, even if the implementation had already buffered them
- rows obtained from the result set stay usable after the owning
transaction ends once they have been materialized
If user code wants row data to survive independently, it should copy the
values it needs into ordinary Lyng objects while the transaction is active.
Calling [toList] while the transaction is active is the normal way to
detach rows for use after the transaction block returns.
*/
interface ResultSet : Iterable<SqlRow> {
/*
+2 -2
View File
@@ -96,8 +96,8 @@ row-id behavior are all connection-local.
The provider may stream rows or buffer them, but it must preserve the core
contract:
- result sets are valid only while the owning transaction is active
- rows obtained from a result set are also invalid after the owning
transaction ends, even if they were already buffered
- rows obtained from a result set should stay usable after the owning
transaction ends once they were materialized, e.g. with `toList()`
- iteration closes underlying resources when finished or canceled
- `isEmpty()` should be cheap where possible
- `size()` may consume or buffer the full result