pg-entity 0.0.5.1 → 0.0.6.0
raw patch · 6 files changed
+52/−130 lines, 6 filesdep −colouristadep ~bytestringdep ~resource-pooldep ~template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: colourista
Dependency ranges changed: bytestring, resource-pool, template-haskell, time
API changes (from Hackage documentation)
- Database.PostgreSQL.Entity.DBT: Delete :: QueryNature
- Database.PostgreSQL.Entity.DBT: Insert :: QueryNature
- Database.PostgreSQL.Entity.DBT: Select :: QueryNature
- Database.PostgreSQL.Entity.DBT: Update :: QueryNature
- Database.PostgreSQL.Entity.DBT: data QueryNature
- Database.PostgreSQL.Entity.DBT: instance GHC.Classes.Eq Database.PostgreSQL.Entity.DBT.QueryNature
- Database.PostgreSQL.Entity.DBT: instance GHC.Internal.Show.Show Database.PostgreSQL.Entity.DBT.QueryNature
+ Database.PostgreSQL.Entity.DBT: data DBT (m :: Type -> Type) a
- Database.PostgreSQL.Entity.DBT: execute :: forall params (m :: Type -> Type). (ToRow params, MonadIO m) => QueryNature -> Query -> params -> DBT m Int64
+ Database.PostgreSQL.Entity.DBT: execute :: forall params (m :: Type -> Type). (HasCallStack, ToRow params, MonadIO m) => Query -> params -> DBT m Int64
- Database.PostgreSQL.Entity.DBT: executeMany :: forall params (m :: Type -> Type). (ToRow params, MonadIO m) => QueryNature -> Query -> [params] -> DBT m Int64
+ Database.PostgreSQL.Entity.DBT: executeMany :: forall params (m :: Type -> Type). (HasCallStack, ToRow params, MonadIO m) => Query -> [params] -> DBT m Int64
- Database.PostgreSQL.Entity.DBT: mkPool :: ConnectInfo -> Int -> NominalDiffTime -> Int -> IO (Pool Connection)
+ Database.PostgreSQL.Entity.DBT: mkPool :: HasCallStack => ConnectInfo -> Int -> NominalDiffTime -> Int -> IO (Pool Connection)
- Database.PostgreSQL.Entity.DBT: query :: forall params result (m :: Type -> Type). (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Vector result)
+ Database.PostgreSQL.Entity.DBT: query :: forall params result (m :: Type -> Type). (HasCallStack, ToRow params, FromRow result, MonadIO m) => Query -> params -> DBT m (Vector result)
- Database.PostgreSQL.Entity.DBT: queryOne :: forall params result (m :: Type -> Type). (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Maybe result)
+ Database.PostgreSQL.Entity.DBT: queryOne :: forall params result (m :: Type -> Type). (HasCallStack, ToRow params, FromRow result, MonadIO m) => Query -> params -> DBT m (Maybe result)
- Database.PostgreSQL.Entity.DBT: queryOne_ :: forall result (m :: Type -> Type). (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Maybe result)
+ Database.PostgreSQL.Entity.DBT: queryOne_ :: forall result (m :: Type -> Type). (HasCallStack, FromRow result, MonadIO m) => Query -> DBT m (Maybe result)
- Database.PostgreSQL.Entity.DBT: query_ :: forall result (m :: Type -> Type). (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Vector result)
+ Database.PostgreSQL.Entity.DBT: query_ :: forall result (m :: Type -> Type). (HasCallStack, FromRow result, MonadIO m) => Query -> DBT m (Vector result)
- Database.PostgreSQL.Entity.DBT: withPool :: MonadIO m => Pool Connection -> DBT IO a -> m a
+ Database.PostgreSQL.Entity.DBT: withPool :: (HasCallStack, MonadIO m) => Pool Connection -> DBT IO a -> m a
Files
- CHANGELOG.md +4/−0
- docs/src/Tutorial.hs +0/−1
- pg-entity.cabal +3/−15
- src/Database/PostgreSQL/Entity.hs +17/−15
- src/Database/PostgreSQL/Entity/DBT.hs +26/−97
- test/EntitySpec.hs +2/−2
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for Entity +## 0.0.6.0 -- 2025-05-20++* The `prod` flag is removed, end of the experiment. End-users should be in charge of logging the queries.+ ## 0.0.5.1 -- 2025-04-23 * Update dependencies
docs/src/Tutorial.hs view
@@ -25,7 +25,6 @@ import Database.PostgreSQL.Simple import Database.PostgreSQL.Simple.FromField import Database.PostgreSQL.Simple.ToField-import Database.PostgreSQL.Transact (DBT) import GHC.Generics import Control.Monad.IO.Class (MonadIO (..))
pg-entity.cabal view
@@ -5,7 +5,7 @@ A PostgreSQL layer to safely expand your SQL queries with a lightweight eDSL. Read the tutorial at https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html -version: 0.0.5.1+version: 0.0.6.0 homepage: https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html @@ -15,7 +15,7 @@ category: Database license: MIT build-type: Simple-tested-with: GHC ==9.2.8 || ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.1+tested-with: GHC ==9.2.8 || ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.2 extra-source-files: CHANGELOG.md LICENSE.md@@ -34,13 +34,6 @@ ./docs/book/fonts/*.woff2 ./docs/book/searchindex.json -flag prod- description:- This flag enables features for production usage, like disabling logs-- default: False- manual: True- flag book description: Enable the generation of the book default: False@@ -103,8 +96,6 @@ hs-source-dirs: src build-depends: , base >=4.12 && <5.0- , bytestring ^>=0.12- , colourista ^>=0.1 , parsec ^>=3.1 , pg-transact ^>=0.3 , postgresql-simple ^>=0.7@@ -113,11 +104,8 @@ , text ^>=2.1 , text-display ^>=1.0 , text-manipulate ^>=0.3- , time ^>=1.14+ , time >=1.12 && <1.16 , vector ^>=0.13-- if flag(prod)- cpp-options: -DPROD executable book import: common-extensions
src/Database/PostgreSQL/Entity.hs view
@@ -22,6 +22,8 @@ -- * High-level API -- $highlevel+ + -- ** Selection , selectById , selectOneByField , selectManyByField@@ -93,7 +95,7 @@ import Database.PostgreSQL.Transact (DBT) import Data.Text (Text)-import Database.PostgreSQL.Entity.DBT (QueryNature (..), execute, executeMany, query, queryOne, queryOne_, query_)+import Database.PostgreSQL.Entity.DBT (execute, executeMany, query, queryOne, queryOne_, query_) import Database.PostgreSQL.Entity.Internal import Database.PostgreSQL.Entity.Types @@ -174,7 +176,7 @@ => Field -> value -> DBT m (Maybe e)-selectOneByField f value = queryOne Select (_selectWhere @e [f]) value+selectOneByField f value = queryOne (_selectWhere @e [f]) value {-| Select potentially many entities by a provided field. @@ -186,7 +188,7 @@ => Field -> value -> DBT m (Vector e)-selectManyByField f value = query Select (_selectWhere @e [f]) value+selectManyByField f value = query (_selectWhere @e [f]) value {-| Select statement with a non-null condition @@ -199,7 +201,7 @@ . (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)-selectWhereNotNull fs = query_ Select (_selectWhereNotNull @e fs)+selectWhereNotNull fs = query_ (_selectWhereNotNull @e fs) {-| Select statement with a null condition @@ -212,7 +214,7 @@ . (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)-selectWhereNull fs = query_ Select (_selectWhereNull @e fs)+selectWhereNull fs = query_ (_selectWhereNull @e fs) {-| Select statement when for an entity where the field is one of the options passed @@ -224,7 +226,7 @@ => Field -> Vector Text -> DBT m (Maybe e)-selectOneWhereIn f values = queryOne_ Select (_selectWhereIn @e f values)+selectOneWhereIn f values = queryOne_ (_selectWhereIn @e f values) {-| Perform a INNER JOIN between two entities @@ -234,7 +236,7 @@ :: forall e1 e2 m . (Entity e1, Entity e2, FromRow e1, MonadIO m) => DBT m (Vector e1)-joinSelectById = query_ Select (_joinSelect @e1 @e2)+joinSelectById = query_ (_joinSelect @e1 @e2) {-| Perform a @INNER JOIN ON field1 WHERE field2 = value@ between two entities @@ -251,7 +253,7 @@ -- ^ The value of the where clause -> DBT m (Vector e1) joinSelectOneByField pivot whereClause value =- query Select (_joinSelectOneByField @e1 @e2 pivot whereClause) (Only value)+ query (_joinSelectOneByField @e1 @e2 pivot whereClause) (Only value) -- @@ -264,7 +266,7 @@ . (Entity e, FromRow e, MonadIO m) => Vector (Field, SortKeyword) -> DBT m (Vector e)-selectOrderBy sortSpec = query_ Select (_select @e <> _orderByMany sortSpec)+selectOrderBy sortSpec = query_ (_select @e <> _orderByMany sortSpec) {-| Insert an entity. @@ -275,7 +277,7 @@ . (Entity e, ToRow values, MonadIO m) => values -> DBT m ()-insert fs = void $ execute Insert (_insert @e) fs+insert fs = void $ execute (_insert @e) fs {-| Insert an entity with a "ON CONFLICT DO UPDATE" clause on the primary key as the conflict target @@ -289,7 +291,7 @@ -> Vector Field -- ^ Fields to replace in case of conflict -> DBT m ()-upsert entity fieldsToReplace = void $ execute Insert (_insert @e <> _onConflictDoUpdate conflictTarget fieldsToReplace) entity+upsert entity fieldsToReplace = void $ execute (_insert @e <> _onConflictDoUpdate conflictTarget fieldsToReplace) entity where conflictTarget = V.singleton $ primaryKey @e @@ -302,7 +304,7 @@ . (Entity e, ToRow values, MonadIO m) => [values] -> DBT m ()-insertMany values = void $ executeMany Insert (_insert @e) values+insertMany values = void $ executeMany (_insert @e) values {-| Update an entity. @@ -319,7 +321,7 @@ . (Entity e, ToRow newValue, MonadIO m) => newValue -> DBT m ()-update fs = void $ execute Update (_update @e) (UpdateRow fs)+update fs = void $ execute (_update @e) (UpdateRow fs) {-| Update rows of an entity matching the given value @@ -341,7 +343,7 @@ -> v2 -- ^ New values of those fields -> DBT m Int64-updateFieldsBy fs (f, oldValue) newValue = execute Update (_updateFieldsBy @e fs f) (toRow newValue ++ toRow (Only oldValue))+updateFieldsBy fs (f, oldValue) newValue = execute (_updateFieldsBy @e fs f) (toRow newValue ++ toRow (Only oldValue)) {-| Delete an entity according to its primary key. @@ -368,7 +370,7 @@ => Vector Field -> values -> DBT m ()-deleteByField fs values = void $ execute Delete (_deleteWhere @e fs) values+deleteByField fs values = void $ execute (_deleteWhere @e fs) values -- * SQL combinators API
src/Database/PostgreSQL/Entity/DBT.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wno-redundant-constraints #-} {-| Module : Database.PostgreSQL.Entity.DBT@@ -11,7 +12,8 @@ The 'Database.PostgreSQL.Transact.DBT' plumbing module to handle database queries and pools -} module Database.PostgreSQL.Entity.DBT- ( mkPool+ ( PGT.DBT+ , mkPool , withPool , execute , executeMany@@ -19,32 +21,19 @@ , query_ , queryOne , queryOne_- , QueryNature (..) ) where -#ifdef PROD-#else-import Colourista (cyan, red, yellow, formatWith)-import Data.ByteString (ByteString)-import qualified Database.PostgreSQL.Simple as Simple-import System.IO (stdout)-import qualified Data.ByteString.Char8 as BS-#endif import Control.Monad.IO.Class-#if MIN_VERSION_resource_pool(0,3,0)-#else-import Control.Monad.Trans.Control-#endif import Data.Int import Data.Maybe (listToMaybe) import Data.Pool (Pool, createPool, withResource) import Data.Time (NominalDiffTime) import Data.Vector (Vector)-import qualified Data.Vector as V- import Database.PostgreSQL.Simple as PG (ConnectInfo, Connection, FromRow, Query, ToRow, close, connect)+import GHC.Stack+import qualified Data.Vector as V import qualified Database.PostgreSQL.Transact as PGT {-| Create a Pool Connection with the appropriate parameters@@ -52,7 +41,8 @@ @since 0.0.1.0 -} mkPool- :: ConnectInfo -- Database access information+ :: HasCallStack+ => ConnectInfo -- Database access information -> Int -- Number of sub-pools -> NominalDiffTime -- Allowed timeout -> Int -- Number of connections@@ -78,26 +68,19 @@ @since 0.0.1.0 -}-#if MIN_VERSION_resource_pool(0,3,0)-withPool :: (MonadIO m) => Pool Connection -> PGT.DBT IO a -> m a+withPool :: (HasCallStack, MonadIO m) => Pool Connection -> PGT.DBT IO a -> m a withPool pool action = liftIO $ withResource pool (\conn -> PGT.runDBTSerializable action conn)-#else-withPool :: (MonadBaseControl IO m) => Pool Connection -> PGT.DBT m a -> m a-withPool pool action = withResource pool (\conn -> PGT.runDBTSerializable action conn)-#endif {-| Query wrapper that returns a 'Vector' of results @since 0.0.1.0 -} query- :: (ToRow params, FromRow result, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, ToRow params, FromRow result, MonadIO m)+ => Query -> params -> PGT.DBT m (Vector result)-query queryNature q params = do- logQueryFormat queryNature q params+query q params = do V.fromList <$> PGT.query q params {-| Query wrapper that returns a 'Vector' of results and does not take an argument@@ -105,12 +88,10 @@ @since 0.0.1.0 -} query_- :: (FromRow result, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, FromRow result, MonadIO m)+ => Query -> PGT.DBT m (Vector result)-query_ queryNature q = do- logQueryFormat queryNature q ()+query_ q = do V.fromList <$> PGT.query_ q {-| Query wrapper that returns one result.@@ -118,13 +99,11 @@ @since 0.0.1.0 -} queryOne- :: (ToRow params, FromRow result, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, ToRow params, FromRow result, MonadIO m)+ => Query -> params -> PGT.DBT m (Maybe result)-queryOne queryNature q params = do- logQueryFormat queryNature q params+queryOne q params = do listToMaybe <$> PGT.query q params --@@ -134,12 +113,10 @@ @since 0.0.2.0 -} queryOne_- :: (FromRow result, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, FromRow result, MonadIO m)+ => Query -> PGT.DBT m (Maybe result)-queryOne_ queryNature q = do- logQueryFormat queryNature q ()+queryOne_ q = do listToMaybe <$> PGT.query_ q {-| Query wrapper for SQL statements which do not return.@@ -147,13 +124,11 @@ @since 0.0.1.0 -} execute- :: (ToRow params, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, ToRow params, MonadIO m)+ => Query -> params -> PGT.DBT m Int64-execute queryNature q params = do- logQueryFormat queryNature q params+execute q params = do PGT.execute q params {-| Query wrapper for SQL statements that operate on multiple rows which do not return.@@ -161,55 +136,9 @@ @since 0.0.2.0 -} executeMany- :: (ToRow params, MonadIO m)- => QueryNature- -> Query+ :: (HasCallStack, ToRow params, MonadIO m)+ => Query -> [params] -> PGT.DBT m Int64-executeMany queryNature q params = do- logQueryFormatMany queryNature q params+executeMany q params = do PGT.executeMany q params--#ifndef PROD-displayColoured :: (MonadIO m) => ByteString -> ByteString -> PGT.DBT m ()-displayColoured colour text = liftIO $ BS.hPutStrLn stdout (formatWith [colour] text)-#endif--#ifdef PROD-logQueryFormat :: (Monad m) => QueryNature -> Query -> params -> PGT.DBT m ()-logQueryFormat _ _ _ = pure ()-#else-logQueryFormat :: (ToRow params, MonadIO m)- => QueryNature -> Query -> params -> PGT.DBT m ()-logQueryFormat queryNature q params = do- msg <- PGT.formatQuery q params- case queryNature of- Select -> displayColoured cyan msg- Update -> displayColoured yellow msg- Insert -> displayColoured yellow msg- Delete -> displayColoured red msg-#endif--#ifdef PROD-logQueryFormatMany :: (Monad m) => QueryNature -> Query -> [params] -> PGT.DBT m ()-logQueryFormatMany _ _ _ = pure ()-#else-logQueryFormatMany :: (ToRow params, MonadIO m) => QueryNature -> Query -> [params] -> PGT.DBT m ()-logQueryFormatMany queryNature q params = do- msg <- formatMany q params- case queryNature of- Select -> displayColoured cyan msg- Update -> displayColoured yellow msg- Insert -> displayColoured yellow msg- Delete -> displayColoured red msg--formatMany :: (ToRow q, MonadIO m) => Query -> [q] -> PGT.DBT m ByteString-formatMany q xs = PGT.getConnection >>= \conn -> liftIO $ Simple.formatMany conn q xs-#endif--{-| This sum type is given to the 'query', 'queryOne' and 'execute' functions to help- with logging.-- @since 0.0.1.0--}-data QueryNature = Select | Insert | Update | Delete deriving (Eq, Show)
test/EntitySpec.hs view
@@ -35,7 +35,7 @@ , _joinSelectWithFields , _where )-import Database.PostgreSQL.Entity.DBT (QueryNature (..), query)+import Database.PostgreSQL.Entity.DBT (query) import Database.PostgreSQL.Simple (Only (Only)) import Database.PostgreSQL.Transact (DBT) @@ -133,7 +133,7 @@ let q = _joinSelectWithFields @BlogPost @Author [[field| title |]] [[field| name |]] <> _where [[field| name |]]- result <- liftDB (query Select q (Only ("Hansi Kürsch" :: Text)) :: MonadIO m => DBT m (Vector (Text, Text)))+ result <- liftDB (query q (Only ("Hansi Kürsch" :: Text)) :: MonadIO m => DBT m (Vector (Text, Text))) let actualMap = Map.fromList $ Vector.toList result let expectedMap = Map.fromList [("The Script for my requiem", "Hansi Kürsch"), ("Mordred's Song", "Hansi Kürsch")] U.assertEqual