You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add missing row streaming and notice response release notes (#197)
The old release-notes bot created separate files for PR #117 (notice
response) and PR #127 (row streaming) but never consolidated them into
next-release.md. Row streaming was also missing from the CHANGELOG
entirely.
- Merge `.release-notes/add-row-streaming.md` content into
`next-release.md` (between COPY OUT and SSLPreferred, matching PR order)
- Merge `.release-notes/notice-response.md` content into
`next-release.md` (between COPY IN and bytea, matching PR order)
- Add missing `Add row streaming support (#127)` entry to CHANGELOG
- Delete the now-consolidated separate release note files
Copy file name to clipboardExpand all lines: .release-notes/next-release.md
+39Lines changed: 39 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -428,6 +428,21 @@ actor BulkLoader is (SessionStatusNotify & ResultReceiver & CopyInReceiver)
428
428
429
429
Data format depends on the COPY command — the default is tab-delimited text with newline row terminators. The pull-based design provides bounded memory usage: only one chunk is in flight at a time.
430
430
431
+
## Add notice response message support
432
+
433
+
PostgreSQL sends NoticeResponse messages for non-fatal informational feedback — for example, "table does not exist, skipping" when you run `DROP TABLE IF EXISTS` on a nonexistent table, or `RAISE NOTICE` output from PL/pgSQL functions. Previously, the driver silently discarded these messages.
434
+
435
+
A new `pg_notice` callback on `SessionStatusNotify` delivers notices as `NoticeResponseMessage` values with the full set of PostgreSQL notice fields (severity, code, message, detail, hint, etc.):
436
+
437
+
```pony
438
+
actor MyNotify is SessionStatusNotify
439
+
be pg_notice(session: Session, notice: NoticeResponseMessage) =>
The callback has a default no-op implementation, so existing code is unaffected.
445
+
431
446
## Add bytea type conversion
432
447
433
448
PostgreSQL `bytea` columns are now automatically decoded from hex format into `Bytea`, a wrapper around `Array[U8] val`. Previously, bytea values were returned as raw hex strings (e.g., `\x48656c6c6f`). They are now decoded into `Bytea` values whose `.data` field contains the raw bytes.
@@ -494,6 +509,30 @@ actor Exporter is (SessionStatusNotify & ResultReceiver & CopyOutReceiver)
494
509
495
510
Data format depends on the COPY command — the default is tab-delimited text with newline row terminators. Data chunks do not necessarily align with row boundaries; the receiver should buffer chunks if row-level processing is needed.
496
511
512
+
## Add row streaming support
513
+
514
+
Row streaming delivers query results in fixed-size batches instead of buffering all rows before delivery. This enables pull-based paged result consumption with bounded memory, ideal for large result sets.
515
+
516
+
A new `StreamingResultReceiver` interface provides three callbacks: `pg_stream_batch` delivers each batch of rows, `pg_stream_complete` signals all rows have been delivered, and `pg_stream_failed` reports errors. Three new `Session` methods control the flow:
517
+
518
+
```pony
519
+
// Start streaming with a window size of 100 rows per batch
520
+
session.stream(
521
+
PreparedQuery("SELECT * FROM big_table",
522
+
recover val Array[FieldDataTypes] end),
523
+
100, my_receiver)
524
+
525
+
// In the receiver:
526
+
be pg_stream_batch(session: Session, rows: Rows) =>
527
+
// Process this batch
528
+
session.fetch_more() // Pull the next batch
529
+
530
+
be pg_stream_complete(session: Session) =>
531
+
// All rows delivered
532
+
```
533
+
534
+
Call `session.close_stream()` to end streaming early. Only `PreparedQuery` and `NamedPreparedQuery` are supported — streaming uses the extended query protocol's `Execute(max_rows)` + `PortalSuspended` mechanism.
535
+
497
536
## Add SSLPreferred mode
498
537
499
538
`SSLPreferred` is a new SSL mode equivalent to PostgreSQL's `sslmode=prefer`. It attempts SSL negotiation when connecting and falls back to plaintext if the server refuses. A TLS handshake failure (server accepts but handshake fails) is a hard failure — the connection is not retried as plaintext.
0 commit comments