packages feed

pqi-conformance 0.1.2.1 → 0.1.2.2

raw patch · 3 files changed

+30/−3 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+# 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.
pqi-conformance.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: pqi-conformance-version: 0.1.2.1+version: 0.1.2.2 category: Database, PostgreSQL, Testing synopsis: Differential conformance tests for pqi adapters description:
src/library/Pqi/Conformance/Reference.hs view
@@ -9,6 +9,8 @@ where  import qualified Database.PostgreSQL.LibPQ as LibPQ+import qualified GHC.Exts+import qualified GHC.IO import qualified Pqi import Pqi.Conformance.Prelude @@ -119,8 +121,8 @@       Pqi.resultErrorMessage = LibPQ.resultErrorMessage r,       Pqi.resultErrorField = \field -> LibPQ.resultErrorField r (toFieldCode field),       Pqi.unsafeFreeResult = LibPQ.unsafeFreeResult r,-      Pqi.ntuples = fromRow <$> LibPQ.ntuples r,-      Pqi.nfields = fromColumn <$> LibPQ.nfields r,+      Pqi.ntuples = strictly r (fromRow <$> LibPQ.ntuples r),+      Pqi.nfields = strictly r (fromColumn <$> LibPQ.nfields r),       Pqi.fname = \column -> LibPQ.fname r (toColumn column),       Pqi.fnumber = \name -> fmap fromColumn <$> LibPQ.fnumber r name,       Pqi.ftable = \column -> fromOid <$> LibPQ.ftable r (toColumn column),@@ -138,6 +140,25 @@       Pqi.cmdStatus = LibPQ.cmdStatus r,       Pqi.cmdTuples = LibPQ.cmdTuples r     }++-- | Read a number out of a result handle, forcing it while the handle is still+-- guaranteed to be alive.+--+-- @postgresql-libpq@ imports @PQntuples@ and @PQnfields@ as /pure/ functions+-- and defines the wrappers as @withResult res (return . toRow . c_PQntuples)@,+-- so the C call escapes 'Foreign.ForeignPtr.withForeignPtr' as an unevaluated+-- thunk over the raw @PGresult@ pointer. Should the handle become unreachable+-- before that thunk is forced, its @PQclear@ finalizer has already freed the+-- memory and the number read is garbage — which made the reference disagree+-- with a correct candidate whenever a collection happened to land in the+-- window. Every other accessor is imported in 'IO' and is unaffected.+strictly :: LibPQ.Result -> IO Int32 -> IO Int32+strictly r io = do+  !n <- io+  touch r+  pure n+  where+    touch x = GHC.IO.IO \s -> case GHC.Exts.touch# x s of s' -> (# s', () #)  -- | Build a 'Pqi.Cancel' whose field closes over the given -- @postgresql-libpq@ cancellation handle.