servant-db-postgresql 0.2.0.0 → 0.2.0.1
raw patch · 4 files changed
+187/−196 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +6/−1
- servant-db-postgresql.cabal +2/−2
- src/Servant/DB/PostgreSQL.hs +59/−62
- src/Servant/DB/PostgreSQL/HasDB.hs +120/−131
CHANGELOG.md view
@@ -1,7 +1,12 @@+0.2.0.1+=======++* Fix haddocks for code blocks.+ 0.2.0.0 ======= -* Split `Arg` to `ArgNamed` and `ArgPos`. +* Split `Arg` to `ArgNamed` and `ArgPos`. 0.1.0.0 =======
servant-db-postgresql.cabal view
@@ -1,10 +1,10 @@ name: servant-db-postgresql-version: 0.2.0.0+version: 0.2.0.1 synopsis: Derive a postgres client to database API specified by servant-db -- description: license: BSD3 license-file: LICENSE-homepage: +homepage: author: Anton Gushcha maintainer: ncrashed@gmail.com category: Database
src/Servant/DB/PostgreSQL.hs view
@@ -12,89 +12,86 @@ * Define your instances of `MonadLogger` and `HasPostgres` for your app monad:-@-newtype PostgresM a = PostgresM { runPostgresM :: PgMonadT (LoggingT IO) a }- deriving (Functor, HasPostgres, MonadLogger, Monad, Applicative, MonadBase IO)-@ -* Define type level API:-@-type UserId = Int--data RegisterUser = RegisterUser {- userRegName :: String-, userRegPassword :: String-, userRegRegTime :: Day-} deriving (Eq)--deriveToRow ''RegisterUser--data User = User {- userId :: UserId-, userName :: String-, userPassword :: String-, userRegTime :: Day-} deriving (Eq)+> newtype PostgresM a = PostgresM { runPostgresM :: PgMonadT (LoggingT IO) a }+> deriving (Functor, HasPostgres, MonadLogger, Monad, Applicative, MonadBase IO) -deriveFromRow ''User-deriveToRow ''User+* Define type level API: -type UserAPI =- ArgNamed "u" (Composite RegisterUser)- :> Procedure "postUser" (Only Int)- :<|> ArgPos Int- :> Procedure "getUser" (Maybe User)- :<|> ArgPos Int- :> Procedure "deleteUser" ()- :<|> Procedure "getUsers" [User]-@+> type UserId = Int+>+> data RegisterUser = RegisterUser {+> userRegName :: String+> , userRegPassword :: String+> , userRegRegTime :: Day+> } deriving (Eq)+>+> deriveToRow ''RegisterUser+>+> data User = User {+> userId :: UserId+> , userName :: String+> , userPassword :: String+> , userRegTime :: Day+> } deriving (Eq)+>+> deriveFromRow ''User+> deriveToRow ''User+>+> type UserAPI =+> ArgNamed "u" (Composite RegisterUser)+> :> Procedure "postUser" (Only Int)+> :<|> ArgPos Int+> :> Procedure "getUser" (Maybe User)+> :<|> ArgPos Int+> :> Procedure "deleteUser" ()+> :<|> Procedure "getUsers" [User] * Derive client functions from the API: -@-postUser :: Composite RegisterUser -> PostgresM (Only Int)-getUser :: Int -> PostgresM (Maybe User)-deleteUser :: Int -> PostgresM ()-getUsers :: PostgresM [User]-( postUser- :<|> getUser- :<|> deleteUser- :<|> getUsers) = deriveDB (Proxy :: Proxy UserAPI) (Proxy :: Proxy PostgresM)-@+> postUser :: Composite RegisterUser -> PostgresM (Only Int)+> getUser :: Int -> PostgresM (Maybe User)+> deleteUser :: Int -> PostgresM ()+> getUsers :: PostgresM [User]+> ( postUser+> :<|> getUser+> :<|> deleteUser+> :<|> getUsers) = deriveDB (Proxy :: Proxy UserAPI) (Proxy :: Proxy PostgresM) = Features * Call functions in schema with `:>` operator:-@-type API = "test" :> ArgPos Int :> Procedure "square" (Only Int)-@++> type API = "test" :> ArgPos Int :> Procedure "square" (Only Int)+ That will call function `test.square(int)`. * Composite types are defined with `Composite a` wrapper:-@-type API = ArgNamed "u" (Composite UserCreate) :> Procedure "postUser" (Only Int)-@ +> type API = ArgNamed "u" (Composite UserCreate) :> Procedure "postUser" (Only Int)+ * Support for arrays:-@-type API = ArgPos (PGArray Int) :> Procedure "mleast" (Maybe (Only Int))-@ +> type API = ArgPos (PGArray Int) :> Procedure "mleast" (Maybe (Only Int))+ * Support for variadic arguments:-@-type API = ArgPos (Variadic Int) :> Procedure "mleast" (Maybe (Only Int))-@ +> type API = ArgPos (Variadic Int) :> Procedure "mleast" (Maybe (Only Int))+ * Support for default arguments with `Default` wrapper:-@-type API = ArgPos (Default Int) :> Procedure "foo" (Only Int)-@ +> type API = ArgPos (Default Int) :> Procedure "foo" (Only Int)+ -} module Servant.DB.PostgreSQL(- module Reexport+ -- * Support for composite types+ module Servant.DB.PostgreSQL.Composite+ -- * Support for variadic types+ , module Servant.DB.PostgreSQL.Variadic+ -- * Deriving of DB clients+ , module Servant.DB.PostgreSQL.HasDB ) where -import Servant.DB.PostgreSQL.Composite as Reexport-import Servant.DB.PostgreSQL.HasDB as Reexport-import Servant.DB.PostgreSQL.Variadic as Reexport+import Servant.DB.PostgreSQL.Composite+import Servant.DB.PostgreSQL.HasDB+import Servant.DB.PostgreSQL.Variadic
src/Servant/DB/PostgreSQL/HasDB.hs view
@@ -52,21 +52,21 @@ -- | Deriving several procedures to query DB API ----- @--- type API = Procedure "time" Integer--- :<|> ArgNamed "a" Int :> Procedure "square" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ time :: MyMonad (Only Integer)--- square :: Int -> MyMonad (Only Int)--- (time, square) = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = Procedure "time" Integer+-- > :<|> ArgNamed "a" Int :> Procedure "square" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > time :: MyMonad (Only Integer)+-- > square :: Int -> MyMonad (Only Int)+-- > (time, square) = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive separate endpoints with the following SQL calls:+-- -- >>> SELECT time();+-- -- >>> SELECT square("a" => ?); instance (HasDB api1 m, HasDB api2 m) => HasDB (api1 :<|> api2) m where type DB (api1 :<|> api2) m = DB api1 m :<|> DB api2 m@@ -78,18 +78,17 @@ -- | Deriving several procedures to query DB API ----- @--- type API = "public" :> Procedure "time" (Only Integer)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ time :: MyMonad (Only Integer)--- time = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = "public" :> Procedure "time" (Only Integer)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > time :: MyMonad (Only Integer)+-- > time = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- The `time` function will call DB with the:+-- -- >>> SELECT public.time(); -- -- Note that there could be only one schema marker. If there are more than one@@ -105,18 +104,17 @@ -- | Deriving call to DB procedure with named arguments ----- @--- type API = ArgNamed "a" Int :> ArgNamed "b" Int :> Procedure "sum" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbSum :: Int -> Int -> MyMonad (Only Int)--- dbSum = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = ArgNamed "a" Int :> ArgNamed "b" Int :> Procedure "sum" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbSum :: Int -> Int -> MyMonad (Only Int)+-- > dbSum = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM sum("a" => ?, "b" => ?) AS t; instance {-# OVERLAPPABLE #-} (KnownSymbol n, ToField a, HasDB api m) => HasDB (ArgNamed n a :> api) m where type DB (ArgNamed n a :> api) m = a -> DB api m@@ -129,18 +127,17 @@ -- | Deriving call to DB procedure with named variadic arguments ----- @--- type API = ArgNamed "arr" (Variadic Int) :> Procedure "mleast" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbMleast :: Variadic Int -> MyMonad (Only Int)--- dbMleast = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = ArgNamed "arr" (Variadic Int) :> Procedure "mleast" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbMleast :: Variadic Int -> MyMonad (Only Int)+-- > dbMleast = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM mleast(VARIADIC "arr" => ?) AS t; instance {-# OVERLAPPING #-} (KnownSymbol n, ToField a, HasDB api m) => HasDB (ArgNamed n (Variadic a) :> api) m where type DB (ArgNamed n (Variadic a) :> api) m = Variadic a -> DB api m@@ -153,18 +150,17 @@ -- | Deriving call to DB procedure with named default arguments ----- @--- type API = ArgNamed "a" (Defaultable Int) :> Procedure "foo" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbFoo :: Defaultable Int -> MyMonad (Only Int)--- dbFoo = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = ArgNamed "a" (Defaultable Int) :> Procedure "foo" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbFoo :: Defaultable Int -> MyMonad (Only Int)+-- > dbFoo = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM default(DEFAULT) AS t; instance {-# OVERLAPPING #-} (KnownSymbol n, ToField a, HasDB api m) => HasDB (ArgNamed n (Default a) :> api) m where type DB (ArgNamed n (Default a) :> api) m = Default a -> DB api m@@ -177,18 +173,17 @@ -- | Deriving call to DB procedure with positional arguments ----- @--- type API = Arg Int :> Arg Int :> Procedure "sum" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbSum :: Int -> Int -> MyMonad (Only Int)--- dbSum = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = Arg Int :> Arg Int :> Procedure "sum" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbSum :: Int -> Int -> MyMonad (Only Int)+-- > dbSum = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM sum(?, ?) AS t; instance {-# OVERLAPPABLE #-} (ToField a, HasDB api m) => HasDB (ArgPos a :> api) m where type DB (ArgPos a :> api) m = a -> DB api m@@ -200,18 +195,17 @@ -- | Deriving call to DB procedure with positional variadic arguments ----- @--- type API = ArgPos (Variadic Int) :> Procedure "mleast" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbMleast :: Variadic Int -> MyMonad (Only Int)--- dbMleast = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = ArgPos (Variadic Int) :> Procedure "mleast" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbMleast :: Variadic Int -> MyMonad (Only Int)+-- > dbMleast = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM mleast(VARIADIC ?) AS t; instance {-# OVERLAPPING #-} (ToField a, HasDB api m) => HasDB (ArgPos (Variadic a) :> api) m where type DB (ArgPos (Variadic a) :> api) m = Variadic a -> DB api m@@ -223,18 +217,17 @@ -- | Deriving call to DB procedure with positional default arguments ----- @--- type API = ArgPos (Default Int) :> Procedure "foo" (Only Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ dbFoo :: Default Int -> MyMonad (Only Int)--- dbFoo = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = ArgPos (Default Int) :> Procedure "foo" (Only Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > dbFoo :: Default Int -> MyMonad (Only Int)+-- > dbFoo = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM foo(DEFAULT) AS t; instance {-# OVERLAPPING #-} (ToField a, HasDB api m) => HasDB (ArgPos (Default a) :> api) m where type DB (ArgPos (Default a) :> api) m = Default a -> DB api m@@ -246,21 +239,20 @@ -- | Deriving call to DB procedure with no return type ----- @--- data User -- user data--- instance ToRow User------ type API = Arg "user" User :> Procedure "registerUser" ()------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ getUsers :: User -> MyMonad ()--- getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > data User -- user data+-- > instance ToRow User+-- >+-- > type API = Arg "user" User :> Procedure "registerUser" ()+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > getUsers :: User -> MyMonad ()+-- > getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT registerUser("user" => ?); -- -- And the instance expects that `users` function return type is `SETOF user`.@@ -278,21 +270,20 @@ -- | Deriving call to DB procedure with multiple result ----- @--- data User -- user data--- instance FromRow User------ type API = Procedure "users" [User]------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ getUsers :: MyMonad [User]--- getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > data User -- user data+-- > instance FromRow User+-- >+-- > type API = Procedure "users" [User]+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > getUsers :: MyMonad [User]+-- > getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM users() AS t; -- -- And the instance expects that `users` function return type is `SETOF user`.@@ -316,21 +307,20 @@ -- | Deriving call to DB procedure with optional result ----- @--- data User -- user data--- instance FromRow User------ type API = ArgPos Int :> Procedure "user" (Maybe User)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ getUsers :: MyMonad (Maybe User)--- getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > data User -- user data+-- > instance FromRow User+-- >+-- > type API = ArgPos Int :> Procedure "user" (Maybe User)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > getUsers :: MyMonad (Maybe User)+-- > getUsers = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM user(?) AS t; instance {-# OVERLAPPING #-} (KnownSymbol n, FromRow a, MonadPostgres m) => HasDB (Procedure n (Maybe a)) m where@@ -348,18 +338,17 @@ -- | Deriving call to DB procedure with single result ----- @--- type API = Arg "a" Int -> Procedure "squareReturning" (Int, Int)------ data MyMonad m a -- Your application monad with connection pool and logger--- instance HasPostgres m--- instance MonadLogger m------ square :: Int -> MyMonad (Int, Int)--- square = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad)--- @+-- > type API = Arg "a" Int -> Procedure "squareReturning" (Int, Int)+-- >+-- > data MyMonad m a -- Your application monad with connection pool and logger+-- > instance HasPostgres m+-- > instance MonadLogger m+-- >+-- > square :: Int -> MyMonad (Int, Int)+-- > square = deriveDB (Proxy :: Proxy API) (Proxy :: Proxy MyMonad) -- -- Upper example will derive the following SQL call:+-- -- >>> SELECT * FROM squareReturning() AS t; -- -- The instance expects that return type of SQL stored function is a single row.