# v1.0.15.0
## Non-breaking
- Added a `connectdb` spec covering a conninfo that gives an unresolvable `host` together with a `hostaddr` that is reachable (a loopback proxy in front of the container). `libpq` connects to the `hostaddr` and never resolves the `host`, and still reports the name from `host`. Both the `keyword=value` form and the URI form (`?hostaddr=`) are covered. Found `pqi-native` never reads `hostaddr`: it resolves `host` through DNS regardless, so the connection fails, and the key is passed on in the startup packet as if it were a server setting. Found via `pqi-native` issue #11.
# v1.0.14.0
## Non-breaking
- Extended the lost-connection scenario (`getResult`, `exec` and `execParams`) to observe the rest of the connection state that a caller reads after the loss: `transactionStatus`, `pipelineStatus`, `isBusy` and whether `socket` is still there. Found `pqi-native` diverging in two of them in every cell: `transactionStatus` stayed `TransIdle` (or whatever the last `ReadyForQuery` said) where `libpq`'s `PQtransactionStatus` reports `PQTRANS_UNKNOWN` for any connection that is not `CONNECTION_OK`, and `socket` returned the number of the closed descriptor (`Just (-1)`) where `PQsocket` returns `-1` once `pqDropConnection` has closed it, i.e. `Nothing`. `pipelineStatus` and `isBusy` agree: `libpq` leaves the pipeline status as it was and `PQisBusy` is `False` once the asynchronous status is back at idle. Only whether the socket is present is compared, not its number, which differs between adapters.
# v1.0.13.0
## Non-breaking
- Added `getResult`, `exec` and `execParams` specs covering a connection that is lost while it is idle and is then used: `sendQuery` (a multi-statement text), `sendQueryParams`, `sendPrepare`, `sendQueryPrepared` (a statement prepared before the loss) and a two-command pipeline run through `getResult` until the sync, plus `exec` and `execParams`, each against three ways of dying - a silent close (FIN with no protocol message), a server-announced termination (`pg_terminate_backend` from a second connection) and a reset (RST). The handle is then used once more and finished. Every call of the victim runs under `try` and a 5 s `timeout`, so that a throw or a hang is recorded in the compared transcript as `THREW …` or `TIMED OUT` instead of aborting the run, and the transcript is compared line by line. The connection goes through an in-process TCP proxy (`Pqi.Conformance.Fixture.ConnectionLoss`) that keeps the client side open and drained once the database side is gone, and the scenario waits for the victim's own socket to have noticed the death before the victim's next command. A direct connection cannot be killed deterministically: the dead server answers the victim's write with a reset that races with reading the `FATAL`/EOF (38 EOF to 2 `Connection reset by peer` in 40 attempts of one cell), and a victim that writes before an RST has been processed by its kernel takes a different path than one that writes after. Found `pqi-native` 1.0.1.12 diverging from `libpq` in every cell. Where the connection is closed or terminated, `getResult` throws `pqi-native: connection closed by server: end of file` where `libpq` returns a `FatalError` result; `status` stays `ConnectionOk` where `libpq` reports `ConnectionBad` (for a termination `libpq` is `ConnectionOk` after the server's `FATAL` and only goes bad on the second `getResult`, which `pqi-native` never reaches); `errorMessage` is empty where `libpq` carries its "server closed the connection unexpectedly" text (after a termination, appended to the `FATAL` text); and the handle accepts a further `sendQuery` (`True`) where `libpq` answers `False` with "no connection to the server", then throws again on `getResult`. After a reset the send already fails (`False`, and for a pipeline the sends after the first) where `libpq` defers a write failure and reports the loss from the following `getResult`. `exec` and `execParams` no longer throw, but their `FatalError` result carries a `DiagMessagePrimary` error field where `libpq`'s made-up result has no error fields at all, after a termination `errorMessage` lacks the preceding `FATAL` text, and after the loss `errorMessage` keeps the "server closed the connection" text where `libpq` reports "no connection to the server". Found via `hasql` issue #341.
# v1.0.12.0
## Non-breaking
- Added a `sendQueryParams` spec covering pipeline flow control: a burst of pipelined commands larger than the socket buffers along the path can absorb, submitted before a single result is read, with each command producing output of its own. The sender must keep draining the socket while it still has bytes to write, like libpq's `pqSendSome` (which absorbs incoming data via `pqReadData` and waits for read-or-write readiness on an incomplete send). Found `pqi-native`'s `Transport.send` was a bare blocking `sendAll` that never reads while sending, so once the unread results fill the server's output path the server stops reading the client's commands and both sides block forever. Surfaced as hasql's `manyLargeResultsViaPipeline` benchmark hanging from `pqi-native` 1.0.1.4 onward, exposed by the Unix-socket default host (whose 8KB buffers saturate on a ~10KB burst that TCP's 128KB ones absorbed); the spec scales the burst to force the same saturation over the suite's TCP container link. Because the failure is a hang rather than a wrong value, the scenario runs under a deadline and the bounded outcome is compared, so the deadlocked candidate fails as a deadline miss instead of stalling the suite.
# v1.0.11.0
## Non-breaking
- Added `connectionNeedsPassword` and `connectionUsedPassword` specs covering trust auth with a `password=` field present in the conninfo (expected `False` for both, since the server never actually challenged for one) and a SCRAM-auth container both with and without a password supplied. Found `pqi-native`'s implementations tracked the conninfo `password=` field instead of libpq's `password_needed` auth-exchange state (`connectionNeedsPassword` was hardcoded `False`; `connectionUsedPassword` was `True` whenever a password string was merely present, trust auth or not).
# v1.0.10.0
## Non-breaking
- Added a `sendQuery` spec covering a connection whose write side is already gone at send time, distinct from `Exec.ConnectionLostMidQuery` (the connection dies while a result is in flight, so the *read* side fails). The connection's own socket is shut down on the write side directly (`shutdown(fd, SHUT_WR)`) rather than via a peer-initiated reset - a peer reset was tried first and found unreliable to force a failing write with: a single write issued a full second after the peer had already reset the connection was still silently accepted into the local kernel send buffer on this platform. Found `pqi-native`'s `sendAsync` - the function every one of `Pqi.sendQuery`/`sendQueryParams`/`sendPrepare`/`sendQueryPrepared`/`sendDescribePrepared`/`sendDescribePortal` is built on - let an escaped `IOException` from the send blow straight through it uncaught, instead of the `False` libpq's `PQsendQuery` always returns for a fatal send. This is the entry point `hasql`'s `Session` machinery actually exercises for every ordinary (non-pipelined) statement, so the raw exception used to escape as far as `Hasql.Connection.use`, misclassified as an async interruption instead of a send failure.
# v1.0.9.0
## Non-breaking
- Added a `connectdb` spec covering a host name that DNS cannot resolve, asserting `errorMessage` exactly against the reference. Found `pqi-native`'s failure message is the raw `Show`n `getAddrInfo` exception, worded unrelatedly to libpq's own (locale-translated) sentence for the same failure, so a downstream classifier that pattern-matches libpq's wording reacts inconsistently between the two adapters. Found via `hasql` issue #329.
- Added a `connectdb` spec covering a handshake-time connection reset (`ECONNRESET`, forced via `SO_LINGER` 0) as distinct from a clean EOF. Found `pqi-native`'s `handshakeFailureMessage` only special-cases EOF with libpq-matching wording ("server closed the connection unexpectedly") and falls back to the raw `Show`n `IOException` (e.g. `Network.Socket.recvBuf: resource vanished (Connection reset by peer)`) for any other handshake-time I/O error, even though libpq itself reports a hard reset with the very same EOF wording. Found via `hasql` issue #329.
- Added an `exec` spec covering a connection reset while a query response is in flight, after a valid handshake. Found none of `pqi-native`'s query functions (`exec`, `execParams`, `prepare`, `execPrepared`, `describePrepared`, `describePortal`) wrap their read loop in any exception handler at all, so a connection lost mid-query escapes as a raw, uncaught `IOException` instead of any classified failure - unlike libpq, which returns a `FatalError` result with its own "server closed the connection unexpectedly" message and never throws. Found via `hasql` issue #329.
# v1.0.8.0
## Non-breaking
- Added a `connectdb` spec covering a Unix-socket directory that doesn't exist, asserting `errorMessage` exactly against the reference. Found `pqi-native`'s failure message is the raw `Show`n `IOException`, which happens to contain `"could not connect to server"` - one of `Hasql.Connection`'s networking (transient) patterns - while libpq's message for the identical `ENOENT` doesn't, so the two adapters drive `Hasql.Connection.acquire` to opposite classifications of the same failure. Found via `hasql` issue #329.
# v1.0.7.0
## Non-breaking
- Added a `connectdb` spec covering a `postgresql://` URI whose host segment is a percent-encoded Unix-socket directory, checked via the parsed host rather than the failure message. Found `pqi-native`'s URI parser never runs the host segment through percent-decoding, unlike every sibling component.
# v1.0.6.0
## Non-breaking
- Added a `pipelineSync` spec covering a pipelined command whose result gets misattributed to a later, unrelated command after a prior pipeline aborted on a server error: a named-statement prepare discarded by the server after an earlier command in the same pipeline fails, followed by a plain `SELECT` in the next pipeline on the same connection, which must come back `TuplesOk` rather than short-circuiting as `CommandOk`. `pqi-native` 1.0.1.5 fails it, 1.0.1.6 fixes it. Found via `pqi-native` issue #9.
- Added a `connectdb` spec covering a mid-handshake server rejection: a listener that accepts the connection, writes the first three bytes of an `E`rrorResponse frame, then closes before the frame completes - mirroring how a server sheds load with e.g. "sorry, too many clients already". A sound adapter reports `ConnectionBad` with a classified error message, the same way it reports any other rejected handshake, instead of letting the underlying I/O exception escape `connectdb`.
Unlike most operation specs, this one drives a raw listener rather than the shared PostgreSQL container: the failure is about how an adapter reacts to a truncated read, which a real server only triggers racily (e.g. under `max_connections` pressure). A hand-rolled listener reproduces the exact byte pattern deterministically. Adds a new `network` dependency.
The spec asserts full equality on both `status` and `errorMessage`, not just `status`: an adapter that swaps in a made-up message instead of reproducing libpq's actual wording would otherwise slip through unnoticed. Getting that message comparison to hold required two adjustments once real libpq's behavior was checked against: the conninfo passes `sslmode=disable`, since libpq negotiates SSL before the startup packet by default and the candidate adapters under test never do, so without it the two sides would be reacting to the truncated bytes at different points in the protocol; and the listener's host is given as a literal IP (`127.0.0.1`) rather than a name, since libpq only parenthesizes a resolved IP in its failure message when it differs from the given host string, which a literal IP never does. Both attempts now also share one listener/port, since the failure message embeds the port number and two independently-bound ephemeral listeners would otherwise never produce an equal message even when every other detail matches.
`pqi-native` throws an uncaught `IOException` out of `connectdb` here, since only the initial TCP connect was wrapped in an exception handler, not the handshake read that follows it. Found via [`pqi-native` issue #8](https://github.com/nikita-volkov/pqi-native/issues/8), itself found while investigating `hasql` issue #329.
# v1.0.5.0
## Non-breaking
- Added `sendQueryParams` specs covering a parameter list longer than 65535: `libpq` rejects it locally, without writing anything to the socket, both standalone and in the middle of a pipeline where the commands surrounding it must still get dispatched and drained without desync. `pqi-native` 1.0.1.3 fails both, encoding the parameter count as a wrapping 16-bit field instead of validating it, which corrupted the `Bind` message and desynchronized the connection; 1.0.1.4 fixes it. Found via `hasql` issue #326.
# v1.0.4.0
## Non-breaking
- Added a `pipelineSync` spec covering an async interruption landing while the sync's `ReadyForQuery` is the only thing left outstanding. An adapter that defers the interrupt across the wait for a frame, rather than across only the instructions that move the frame into its buffer, has delivery pinned to the instant the frame arrives - the one moment at which it holds a fully-read message it has not yet accounted for. Dropping that particular message costs the caller the connection rather than a result: the adapter still has a sync outstanding, so the next `getResult` goes back to the socket for a message the backend has already sent and will not send again.
Unlike the existing interruption spec, which sweeps a timer across the window, this one constructs it. A flush request separates the command's results from the sync's `ReadyForQuery`, and a `DEFERRABLE INITIALLY DEFERRED` trigger - fired by the backend's handling of `Sync` itself - holds that `ReadyForQuery` back for half a second, so the interrupt lands with 450ms of margin either side.
`pqi-native` 1.0.1.2 fails it, 1.0.1.3 passes it. Found via a hang in `hasql`'s `Integration.Sharing.Connection.Use.PipelineAbortedInterruptionCleanup`
# v1.0.3.0
## Non-breaking
- Added a `pipelineSync` spec covering resilience to an asynchronous interruption around a pipeline abort. Found the native adapter can leave a connection permanently unusable instead of failing outright, since none of its transport/connection code is exception-safe
# v1.0.2.1
## Fixes
- Fix a flaky test
# v1.0.2.0
## Non-breaking
- Added a differential spec for `sendQueryParams` in pipeline mode, catching that the native adapter charges its own `ParseComplete` against a pending `sendPrepare` and so emits a spurious leading `CommandOk`, shifting every later result
# v1.0.1.0
## Non-breaking
- Picked up `pqi` 1.1.0.0, which renamed `Notify`'s fields to `notifyRelname`/`notifyBePid`/`notifyExtra` to match `postgresql-libpq`
# v1.0.0.1
Doc corrections.
# v1.0.0.0
## Non-breaking
- Differential spec for the new `resStatus` field of `Pqi.Adapter`
# v0.1.2.2
## Fixes
- Fixed the reference adapter's `ntuples` and `nfields` intermittently returning garbage, which made the differential suite fail correct candidates. `postgresql-libpq` imports `PQntuples` and `PQnfields` as pure functions and lets the resulting thunk escape `withForeignPtr`, so if the result handle got collected before the count was forced, the number was read from memory that `PQclear` had already freed. Both counts are now forced while the handle is still alive.
# v0.1.2.1
- Fixed the publishing.
# v0.1.2.0
- Added another test.
# v0.1.1.1
- Fixed the docs.
# v0.1.1.0
## Non-breaking
- Added differential coverage for extra conninfo params (e.g. `application_name`) supplied at connect time, closing the gap where only `SET`-based updates were covered
# v0.1.0.1
## Fixes
- Removed remaining `OverloadedRecordDot` usages from the source, since that extension (along with `DuplicateRecordFields` and `NoFieldSelectors`) was dropped from the default extensions to support GHC 8.10
# v0.1.0.0
## Breaking
- Migrated to record-of-functions API structure
## Non-breaking
- Added parity specification for pipeline sync operations
- Added UnescapeBytea to the conformance test battery