Compare commits

...

4 Commits

Author SHA1 Message Date
Paul Brinkmeier
af16429d82 Also expose ConnectionError in main module 2025-08-24 21:46:07 +02:00
Paul Brinkmeier
42398e71bb Expose ConnectionError constructors 2025-08-24 21:40:12 +02:00
Paul Brinkmeier
1c32e4244e Add actual row number to row number errors 2025-08-20 22:22:21 +02:00
9e9e0204bb Add ToField Day 2025-07-28 08:57:01 +02:00
6 changed files with 53 additions and 9 deletions

View File

@ -5,7 +5,7 @@
module Database.PostgreSQL.Opium module Database.PostgreSQL.Opium
-- * Connection Management -- * Connection Management
( Connection ( Connection
, ConnectionError , ConnectionError (..)
, connect , connect
, close , close
-- * Queries -- * Queries
@ -41,7 +41,7 @@ import Database.PostgreSQL.LibPQ (Result)
import qualified Data.Text.Encoding as Encoding import qualified Data.Text.Encoding as Encoding
import qualified Database.PostgreSQL.LibPQ as LibPQ import qualified Database.PostgreSQL.LibPQ as LibPQ
import Database.PostgreSQL.Opium.Connection (Connection, ConnectionError, connect, close, withRawConnection) import Database.PostgreSQL.Opium.Connection (Connection, ConnectionError (..), connect, close, withRawConnection)
import Database.PostgreSQL.Opium.Error (Error (..), ErrorPosition (..)) import Database.PostgreSQL.Opium.Error (Error (..), ErrorPosition (..))
import Database.PostgreSQL.Opium.FromField (FromField (..), RawField (..)) import Database.PostgreSQL.Opium.FromField (FromField (..), RawField (..))
import Database.PostgreSQL.Opium.FromRow (FromRow (..), ColumnTable) import Database.PostgreSQL.Opium.FromRow (FromRow (..), ColumnTable)
@ -59,11 +59,11 @@ instance RowContainer Maybe where
extract result nRows columnTable extract result nRows columnTable
| nRows == 0 = pure Nothing | nRows == 0 = pure Nothing
| nRows == 1 = Just <$> ExceptT (fromRow result columnTable 0) | nRows == 1 = Just <$> ExceptT (fromRow result columnTable 0)
| otherwise = throwE ErrorMoreThanOneRow | otherwise = throwE $ ErrorMoreThanOneRow $ fromEnum nRows
instance RowContainer Identity where instance RowContainer Identity where
extract result nRows columnTable = do extract result nRows columnTable = do
unless (nRows == 1) $ throwE ErrorNotExactlyOneRow unless (nRows == 1) $ throwE $ ErrorNotExactlyOneRow $ fromEnum nRows
Identity <$> ExceptT (fromRow result columnTable 0) Identity <$> ExceptT (fromRow result columnTable 0)
-- The order of the type parameters is important, because it is more common to use type applications for providing the row type and row container type. -- The order of the type parameters is important, because it is more common to use type applications for providing the row type and row container type.

View File

@ -4,7 +4,7 @@
module Database.PostgreSQL.Opium.Connection module Database.PostgreSQL.Opium.Connection
( Connection ( Connection
, ConnectionError , ConnectionError (..)
, unsafeWithRawConnection , unsafeWithRawConnection
, withRawConnection , withRawConnection
, connect , connect
@ -12,6 +12,7 @@ module Database.PostgreSQL.Opium.Connection
) where ) where
import Control.Concurrent.MVar (MVar, newMVar, modifyMVar_, withMVar) import Control.Concurrent.MVar (MVar, newMVar, modifyMVar_, withMVar)
import Control.Exception (Exception)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Text (Text) import Data.Text (Text)
import Database.PostgreSQL.LibPQ (ConnStatus (..)) import Database.PostgreSQL.LibPQ (ConnStatus (..))
@ -27,6 +28,8 @@ newtype Connection = Connection
newtype ConnectionError = ConnectionError Text newtype ConnectionError = ConnectionError Text
deriving (Show) deriving (Show)
instance Exception ConnectionError
withRawConnection withRawConnection
:: HasCallStack :: HasCallStack
=> (Maybe LibPQ.Connection -> IO a) => (Maybe LibPQ.Connection -> IO a)

View File

@ -17,8 +17,8 @@ data Error
| ErrorInvalidOid Text Oid | ErrorInvalidOid Text Oid
| ErrorUnexpectedNull ErrorPosition | ErrorUnexpectedNull ErrorPosition
| ErrorInvalidField ErrorPosition Oid ByteString String | ErrorInvalidField ErrorPosition Oid ByteString String
| ErrorNotExactlyOneRow | ErrorNotExactlyOneRow Int
| ErrorMoreThanOneRow | ErrorMoreThanOneRow Int
| ErrorConnectionClosed | ErrorConnectionClosed
deriving (Eq, Show) deriving (Eq, Show)

View File

@ -7,8 +7,10 @@ module Database.PostgreSQL.Opium.ToField
import Data.Bits (Bits (..)) import Data.Bits (Bits (..))
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Int (Int32)
import Data.List (singleton) import Data.List (singleton)
import Data.Text (Text) import Data.Text (Text)
import Data.Time (Day, diffDays, fromGregorian)
import Data.Word (Word32) import Data.Word (Word32)
import Database.PostgreSQL.LibPQ (Format (..), Oid) import Database.PostgreSQL.LibPQ (Format (..), Oid)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
@ -48,3 +50,11 @@ instance ToField Float where
instance ToField Double where instance ToField Double where
toField x = Just (Oid.doublePrecision, encodeBigEndian @Word 8 $ unsafeCoerce x, Binary) toField x = Just (Oid.doublePrecision, encodeBigEndian @Word 8 $ unsafeCoerce x, Binary)
toPostgresJulian :: Day -> Integer
toPostgresJulian date = diffDays date postgresEpoch
where
postgresEpoch = fromGregorian 2000 1 1
instance ToField Day where
toField x = Just (Oid.date, encodeBigEndian @Int32 4 $ fromIntegral $ toPostgresJulian x, Binary)

View File

@ -20,7 +20,7 @@ name: opium
-- PVP summary: +-+------- breaking API changes -- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions -- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change -- | | | +--- code changes with no API change
version: 1.1.0.0 version: 1.1.1.0
-- A short (one-line) description of the package. -- A short (one-line) description of the package.
-- synopsis: -- synopsis:
@ -119,7 +119,8 @@ test-suite opium-test
SpecHook, SpecHook,
Database.PostgreSQL.OpiumSpec, Database.PostgreSQL.OpiumSpec,
Database.PostgreSQL.Opium.FromFieldSpec, Database.PostgreSQL.Opium.FromFieldSpec,
Database.PostgreSQL.Opium.FromRowSpec Database.PostgreSQL.Opium.FromRowSpec,
Database.PostgreSQL.Opium.ToFieldSpec
-- Test dependencies. -- Test dependencies.
build-depends: build-depends:

View File

@ -0,0 +1,30 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Database.PostgreSQL.Opium.ToFieldSpec (spec) where
import Data.Functor.Identity (Identity (..))
import Data.Text (Text)
import Data.Time (fromGregorian)
import GHC.Generics (Generic)
import Test.Hspec (SpecWith, describe, it, shouldBe)
import qualified Database.PostgreSQL.Opium as Opium
newtype Result = Result
{ a :: Bool
} deriving (Show, Eq, Generic)
instance Opium.FromRow Result
shouldBeTrue :: Opium.ToParamList p => Opium.Connection -> Text -> p -> IO ()
shouldBeTrue conn query params = do
result <- Opium.fetch query params conn
result `shouldBe` Right (Identity (Result True))
spec :: SpecWith Opium.Connection
spec = do
describe "ToField Day" $ do
it "Encodes Day" $ \conn -> do
shouldBeTrue conn "SELECT $1 = date '1997-09-29' AS a" (Identity $ fromGregorian 1997 9 29)
shouldBeTrue conn "SELECT $1 = date '2025-07-28' AS a" (Identity $ fromGregorian 2025 7 28)