-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Database persistence using generics
--
-- Please see the README on GitHub at
-- https://github.com/thma/generic-persistence#readme
@package generic-persistence
@version 0.4.0.0
module Database.GP.Conn
-- | This module defines a wrapper around an HDBC IConnection. Using this
-- wrapper Conn simplifies the signature of the functions in the
-- GP module. It allows to use any HDBC connection without having
-- to define a new function for each connection type. It also provides
-- additional attributes to the connection, like the database type and
-- the implicit commit flag. These attributes can be used to implement
-- database specific functionality, modify transaction behaviour, etc.
--
-- This code has been inspired by the HDBC ConnectionWrapper and some
-- parts have been copied verbatim from the HDBC Database.HDBC.Types
-- module.
--
-- This module also defines a ConnectionPool type, which provides basic
-- connection pooling functionality.
--
-- A wrapper around an HDBC IConnection.
data Conn
Conn :: Database -> Bool -> conn -> Conn
-- | The database type
[db] :: Conn -> Database
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[implicitCommit] :: Conn -> Bool
-- | The wrapped connection
[connection] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => Database -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
MySQL :: Database
SQLite :: Database
Oracle :: Database
MSSQL :: Database
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => Database -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
withResource :: Pool a -> (a -> IO r) -> IO r
instance GHC.Enum.Enum Database.GP.Conn.Database
instance GHC.Classes.Eq Database.GP.Conn.Database
instance GHC.Show.Show Database.GP.Conn.Database
instance Database.HDBC.Types.IConnection Database.GP.Conn.Conn
module Database.GP.TypeInfo
-- | A data type holding meta-data about a type. The Phantom type parameter
-- a ensures type safety for reflective functions that use this
-- type to create type instances.
data TypeInfo a
fieldNames :: TypeInfo a -> [String]
fieldTypes :: TypeInfo a -> [SomeTypeRep]
constructorName :: TypeInfo a -> String
-- | this function is a smart constructor for TypeInfo objects. It takes a
-- value of type a and returns a `TypeInfo a` object. If the
-- type has no named fields, an error is thrown. If the type has more
-- than one constructor, an error is thrown.
typeInfo :: forall a. (HasConstructor (Rep a), HasSelectors (Rep a), Generic a) => TypeInfo a
class HasConstructor (f :: Type -> Type)
genericConstrName :: HasConstructor f => f x -> String
class HasSelectors rep
selectors :: HasSelectors rep => [(String, SomeTypeRep)]
instance forall k (a :: k). GHC.Show.Show (Database.GP.TypeInfo.TypeInfo a)
instance forall k (f :: k -> *) (x :: GHC.Generics.Meta). Database.GP.TypeInfo.HasSelectors f => Database.GP.TypeInfo.HasSelectors (GHC.Generics.M1 GHC.Generics.D x f)
instance forall k (f :: k -> *) (x :: GHC.Generics.Meta). Database.GP.TypeInfo.HasSelectors f => Database.GP.TypeInfo.HasSelectors (GHC.Generics.M1 GHC.Generics.C x f)
instance (GHC.Generics.Selector s, Data.Typeable.Internal.Typeable t) => Database.GP.TypeInfo.HasSelectors (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 GHC.Generics.R t))
instance forall k (a :: k -> *) (b :: k -> *). (Database.GP.TypeInfo.HasSelectors a, Database.GP.TypeInfo.HasSelectors b) => Database.GP.TypeInfo.HasSelectors (a GHC.Generics.:*: b)
instance Database.GP.TypeInfo.HasSelectors GHC.Generics.U1
instance Database.GP.TypeInfo.HasConstructor f => Database.GP.TypeInfo.HasConstructor (GHC.Generics.D1 c f)
instance (Database.GP.TypeInfo.HasConstructor x, Database.GP.TypeInfo.HasConstructor y) => Database.GP.TypeInfo.HasConstructor (x GHC.Generics.:+: y)
instance GHC.Generics.Constructor c => Database.GP.TypeInfo.HasConstructor (GHC.Generics.C1 c f)
module Database.GP.Entity
-- | This is the Entity class. It is a type class that is used to define
-- the mapping between a Haskell product type in record notation and a
-- database table. The class has a default implementation for all
-- methods. The default implementation uses the type information to
-- determine a simple 1:1 mapping.
--
-- That means that - the type name is used as the table name and the -
-- field names are used as the column names. - A field named
-- 'typeNameID' is used as the primary key field.
--
-- The default implementation can be overridden by defining a custom
-- instance for a type.
--
-- Please note the following constraints, which apply to all valid Entity
-- type, but that are not explicitely encoded in the type class
-- definition:
--
--
-- - The type must be a product type in record notation.
-- - The type must have exactly one constructor.
-- - There must be single primary key field, compund primary keys are
-- not supported.
--
class (Generic a, HasConstructor (Rep a), HasSelectors (Rep a)) => Entity a
-- | Converts a database row to a value of type a.
fromRow :: Entity a => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: Entity a => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
-- | Converts a database row to a value of type a.
fromRow :: (Entity a, GFromRow (Rep a)) => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: (Entity a, GToRow (Rep a)) => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
-- | A convenience function: returns the name of the column for a field of
-- a type a.
columnNameFor :: forall a. Entity a => String -> String
-- | Returns a string representation of a value of type a.
toString :: forall a. (Generic a, GShow' (Rep a)) => a -> String
gtoRow :: GToRow f => f a -> [SqlValue]
class GToRow f
class GFromRow f
maybeFieldTypeFor :: forall a. Entity a => String -> Maybe TypeRep
-- | This module defines a wrapper around an HDBC IConnection. Using this
-- wrapper Conn simplifies the signature of the functions in the
-- GP module. It allows to use any HDBC connection without having
-- to define a new function for each connection type. It also provides
-- additional attributes to the connection, like the database type and
-- the implicit commit flag. These attributes can be used to implement
-- database specific functionality, modify transaction behaviour, etc.
--
-- This code has been inspired by the HDBC ConnectionWrapper and some
-- parts have been copied verbatim from the HDBC Database.HDBC.Types
-- module.
--
-- This module also defines a ConnectionPool type, which provides basic
-- connection pooling functionality.
--
-- A wrapper around an HDBC IConnection.
data Conn
Conn :: Database -> Bool -> conn -> Conn
-- | The database type
[db] :: Conn -> Database
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[implicitCommit] :: Conn -> Bool
-- | The wrapped connection
[connection] :: Conn -> conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
MySQL :: Database
SQLite :: Database
Oracle :: Database
MSSQL :: Database
instance (GHC.TypeNats.KnownNat (Database.GP.Entity.NumFields f), Database.GP.Entity.GFromRow f, Database.GP.Entity.GFromRow g) => Database.GP.Entity.GFromRow (f GHC.Generics.:*: g)
instance Database.GP.Entity.GFromRow GHC.Generics.U1
instance Data.Convertible.Base.Convertible Database.HDBC.SqlValue.SqlValue a => Database.GP.Entity.GFromRow (GHC.Generics.K1 i a)
instance forall k (a :: k -> *) i (c :: GHC.Generics.Meta). Database.GP.Entity.GFromRow a => Database.GP.Entity.GFromRow (GHC.Generics.M1 i c a)
instance Database.GP.Entity.GToRow GHC.Generics.U1
instance Data.Convertible.Base.Convertible a Database.HDBC.SqlValue.SqlValue => Database.GP.Entity.GToRow (GHC.Generics.K1 i a)
instance forall k (a :: k -> *) (b :: k -> *). (Database.GP.Entity.GToRow a, Database.GP.Entity.GToRow b) => Database.GP.Entity.GToRow (a GHC.Generics.:*: b)
instance forall k (a :: k -> *) i (c :: GHC.Generics.Meta). Database.GP.Entity.GToRow a => Database.GP.Entity.GToRow (GHC.Generics.M1 i c a)
module Database.GP.Query
data WhereClauseExpr
data Field
field :: String -> Field
whereClauseExprToSql :: forall a. Entity a => WhereClauseExpr -> String
whereClauseValues :: WhereClauseExpr -> [SqlValue]
(&&.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 3 &&.
(||.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 2 ||.
(=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 =.
(>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >.
(<.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <.
(>=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >=.
(<=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <=.
(<>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <>.
like :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 `like`
contains :: Convertible a SqlValue => Field -> a -> WhereClauseExpr
infixl 4 `contains`
between :: (Convertible a1 SqlValue, Convertible a2 SqlValue) => Field -> (a1, a2) -> WhereClauseExpr
infixl 4 `between`
in' :: Convertible b SqlValue => Field -> [b] -> WhereClauseExpr
infixl 4 `in'`
isNull :: Field -> WhereClauseExpr
not' :: WhereClauseExpr -> WhereClauseExpr
params :: Int -> [String]
sqlFun :: String -> Field -> Field
allEntries :: WhereClauseExpr
idColumn :: forall a. Entity a => String
byId :: Convertible a SqlValue => a -> WhereClauseExpr
instance GHC.Classes.Eq Database.GP.Query.CompareOp
instance GHC.Show.Show Database.GP.Query.CompareOp
instance GHC.Classes.Eq Database.GP.Query.Field
instance GHC.Show.Show Database.GP.Query.Field
instance GHC.Classes.Eq Database.GP.Query.WhereClauseExpr
instance GHC.Show.Show Database.GP.Query.WhereClauseExpr
module Database.GP.SqlGenerator
-- | This module defines some basic SQL statements for Record Data Types
-- that are instances of Entity. The SQL statements are generated
-- using Haskell generics to provide compile time reflection
-- capabilities.
--
-- A function that returns an SQL insert statement for an entity. Type
-- a must be an instance of Data. The function will use the
-- field names of the data type to generate the column names in the
-- insert statement. The values of the fields will be used as the values
-- in the insert statement. Output example: INSERT INTO Person (id, name,
-- age, address) VALUES (123456, Alice, 25, "123 Main St");
insertStmtFor :: forall a. Entity a => String
-- | A function that returns an SQL update statement for an entity. Type
-- a must be an instance of Entity.
updateStmtFor :: forall a. Entity a => String
-- | A function that returns an SQL select statement for an entity. Type
-- a must be an instance of Entity. The function takes a where
-- clause expression as parameter. This expression is used to filter the
-- result set.
selectFromStmt :: forall a. Entity a => WhereClauseExpr -> String
deleteStmtFor :: forall a. Entity a => String
createTableStmtFor :: forall a. Entity a => Database -> String
dropTableStmtFor :: forall a. Entity a => String
data WhereClauseExpr
data Field
field :: String -> Field
whereClauseValues :: WhereClauseExpr -> [SqlValue]
(&&.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 3 &&.
(||.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 2 ||.
(=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 =.
(>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >.
(<.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <.
(>=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >=.
(<=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <=.
(<>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <>.
like :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 `like`
contains :: Convertible a SqlValue => Field -> a -> WhereClauseExpr
infixl 4 `contains`
between :: (Convertible a1 SqlValue, Convertible a2 SqlValue) => Field -> (a1, a2) -> WhereClauseExpr
infixl 4 `between`
in' :: Convertible b SqlValue => Field -> [b] -> WhereClauseExpr
infixl 4 `in'`
isNull :: Field -> WhereClauseExpr
not' :: WhereClauseExpr -> WhereClauseExpr
sqlFun :: String -> Field -> Field
allEntries :: WhereClauseExpr
byId :: Convertible a SqlValue => a -> WhereClauseExpr
module Database.GP.GenericPersistenceSafe
-- | A function that retrieves an entity from a database. The function
-- takes entity id as parameter. If an entity with the given id exists in
-- the database, it is returned as a Just value. If no such entity
-- exists, Nothing is returned. An error is thrown if there are more than
-- one entity with the given id.
selectById :: forall a id. (Entity a, Convertible id SqlValue) => Conn -> id -> IO (Either PersistenceException a)
-- | This function retrieves all entities of type a that match
-- some query criteria. The function takes an HDBC connection and a
-- WhereClauseExpr as parameters. The type a is
-- determined by the context of the function call. The function returns a
-- (possibly empty) list of all matching entities. The
-- WhereClauseExpr is typically constructed using any tiny query
-- dsl based on infix operators.
select :: forall a. Entity a => Conn -> WhereClauseExpr -> IO (Either PersistenceException [a])
-- | This function converts a list of database rows, represented as a
-- `[[SqlValue]]` to a list of entities. The function takes an HDBC
-- connection and a list of database rows as parameters. The type
-- a is determined by the context of the function call. The
-- function returns a (possibly empty) list of all matching entities. The
-- function is used internally by retrieveAll and
-- retrieveAllWhere. But it can also be used to convert the
-- result of a custom SQL query to a list of entities.
entitiesFromRows :: forall a. Entity a => Conn -> [[SqlValue]] -> IO (Either PersistenceException [a])
-- | A function that persists an entity to a database. The function takes
-- an HDBC connection and an entity as parameters. The entity is either
-- inserted or updated, depending on whether it already exists in the
-- database. The required SQL statements are generated dynamically using
-- Haskell generics and reflection
persist :: forall a. Entity a => Conn -> a -> IO (Either PersistenceException ())
-- | A function that explicitely inserts an entity into a database.
insert :: forall a. Entity a => Conn -> a -> IO (Either PersistenceException ())
-- | A function that inserts a list of entities into a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The insert-statement is compiled only once and then
-- executed for each entity.
insertMany :: forall a. Entity a => Conn -> [a] -> IO (Either PersistenceException ())
-- | A function that explicitely updates an entity in a database.
update :: forall a. Entity a => Conn -> a -> IO (Either PersistenceException ())
-- | A function that updates a list of entities in a database. The function
-- takes an HDBC connection and a list of entities as parameters. The
-- update-statement is compiled only once and then executed for each
-- entity.
updateMany :: forall a. Entity a => Conn -> [a] -> IO (Either PersistenceException ())
-- | A function that deletes an entity from a database. The function takes
-- an HDBC connection and an entity as parameters.
delete :: forall a. Entity a => Conn -> a -> IO (Either PersistenceException ())
-- | A function that deletes a list of entities from a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The delete-statement is compiled only once and then
-- executed for each entity.
deleteMany :: forall a. Entity a => Conn -> [a] -> IO (Either PersistenceException ())
-- | set up a table for a given entity type. The table is dropped (if
-- existing) and recreated. The function takes an HDBC connection as
-- parameter.
setupTableFor :: forall a. Entity a => Conn -> IO ()
-- | A function that returns the primary key value of an entity as a
-- SqlValue. The function takes an HDBC connection and an entity as
-- parameters.
idValue :: forall a. Entity a => Conn -> a -> IO SqlValue
-- | This module defines a wrapper around an HDBC IConnection. Using this
-- wrapper Conn simplifies the signature of the functions in the
-- GP module. It allows to use any HDBC connection without having
-- to define a new function for each connection type. It also provides
-- additional attributes to the connection, like the database type and
-- the implicit commit flag. These attributes can be used to implement
-- database specific functionality, modify transaction behaviour, etc.
--
-- This code has been inspired by the HDBC ConnectionWrapper and some
-- parts have been copied verbatim from the HDBC Database.HDBC.Types
-- module.
--
-- This module also defines a ConnectionPool type, which provides basic
-- connection pooling functionality.
--
-- A wrapper around an HDBC IConnection.
data Conn
Conn :: Database -> Bool -> conn -> Conn
-- | The database type
[db] :: Conn -> Database
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[implicitCommit] :: Conn -> Bool
-- | The wrapped connection
[connection] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => Database -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
MySQL :: Database
SQLite :: Database
Oracle :: Database
MSSQL :: Database
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => Database -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
withResource :: Pool a -> (a -> IO r) -> IO r
-- | This is the Entity class. It is a type class that is used to define
-- the mapping between a Haskell product type in record notation and a
-- database table. The class has a default implementation for all
-- methods. The default implementation uses the type information to
-- determine a simple 1:1 mapping.
--
-- That means that - the type name is used as the table name and the -
-- field names are used as the column names. - A field named
-- 'typeNameID' is used as the primary key field.
--
-- The default implementation can be overridden by defining a custom
-- instance for a type.
--
-- Please note the following constraints, which apply to all valid Entity
-- type, but that are not explicitely encoded in the type class
-- definition:
--
--
-- - The type must be a product type in record notation.
-- - The type must have exactly one constructor.
-- - There must be single primary key field, compund primary keys are
-- not supported.
--
class (Generic a, HasConstructor (Rep a), HasSelectors (Rep a)) => Entity a
-- | Converts a database row to a value of type a.
fromRow :: Entity a => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: Entity a => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
-- | Converts a database row to a value of type a.
fromRow :: (Entity a, GFromRow (Rep a)) => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: (Entity a, GToRow (Rep a)) => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
class GToRow f
class GFromRow f
-- | A convenience function: returns the name of the column for a field of
-- a type a.
columnNameFor :: forall a. Entity a => String -> String
maybeFieldTypeFor :: forall a. Entity a => String -> Maybe TypeRep
-- | Returns a string representation of a value of type a.
toString :: forall a. (Generic a, GShow' (Rep a)) => a -> String
-- | A data type holding meta-data about a type. The Phantom type parameter
-- a ensures type safety for reflective functions that use this
-- type to create type instances.
data TypeInfo a
-- | this function is a smart constructor for TypeInfo objects. It takes a
-- value of type a and returns a `TypeInfo a` object. If the
-- type has no named fields, an error is thrown. If the type has more
-- than one constructor, an error is thrown.
typeInfo :: forall a. (HasConstructor (Rep a), HasSelectors (Rep a), Generic a) => TypeInfo a
-- | This is the "safe" version of the module
-- Database.GP.GenericPersistence. It uses Either to return errors.
--
-- This module defines RDBMS Persistence operations for Record Data Types
-- that are instances of Data. I call instances of such a data
-- type Entities.
--
-- The Persistence operations are using Haskell generics to provide
-- compile time reflection capabilities. HDBC is used to access the
-- RDBMS.
--
-- exceptions that may occur during persistence operations
data PersistenceException
EntityNotFound :: String -> PersistenceException
DuplicateInsert :: String -> PersistenceException
DatabaseError :: String -> PersistenceException
NoUniqueKey :: String -> PersistenceException
data WhereClauseExpr
data Field
field :: String -> Field
(&&.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 3 &&.
(||.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 2 ||.
(=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 =.
(>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >.
(<.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <.
(>=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >=.
(<=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <=.
(<>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <>.
like :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 `like`
contains :: Convertible a SqlValue => Field -> a -> WhereClauseExpr
infixl 4 `contains`
between :: (Convertible a1 SqlValue, Convertible a2 SqlValue) => Field -> (a1, a2) -> WhereClauseExpr
infixl 4 `between`
in' :: Convertible b SqlValue => Field -> [b] -> WhereClauseExpr
infixl 4 `in'`
isNull :: Field -> WhereClauseExpr
not' :: WhereClauseExpr -> WhereClauseExpr
sqlFun :: String -> Field -> Field
allEntries :: WhereClauseExpr
byId :: Convertible a SqlValue => a -> WhereClauseExpr
instance GHC.Exception.Type.Exception Database.GP.GenericPersistenceSafe.PersistenceException
instance GHC.Classes.Eq Database.GP.GenericPersistenceSafe.PersistenceException
instance GHC.Show.Show Database.GP.GenericPersistenceSafe.PersistenceException
instance GHC.Enum.Enum a => Data.Convertible.Base.Convertible Database.HDBC.SqlValue.SqlValue a
instance GHC.Enum.Enum a => Data.Convertible.Base.Convertible a Database.HDBC.SqlValue.SqlValue
module Database.GP.GenericPersistence
-- | This module defines RDBMS Persistence operations for Record Data Types
-- that are instances of Data. I call instances of such a data
-- type Entities.
--
-- The Persistence operations are using Haskell generics to provide
-- compile time reflection capabilities. HDBC is used to access the
-- RDBMS.
--
-- A function that retrieves an entity from a database. The function
-- takes entity id as parameter. If an entity with the given id exists in
-- the database, it is returned as a Just value. If no such entity
-- exists, Nothing is returned. An error is thrown if there are more than
-- one entity with the given id.
selectById :: forall a id. (Entity a, Convertible id SqlValue) => Conn -> id -> IO (Maybe a)
-- | This function retrieves all entities of type a from a
-- database. The function takes an HDBC connection as parameter. The type
-- a is determined by the context of the function call.
-- retrieveAll :: forall a. (Entity a) => Conn -> IO [a]
-- retrieveAll conn = do eitherExRow <- GpSafe.retrieveAll @a conn
-- case eitherExRow of Left ex -> throw ex Right rows -> pure rows
--
-- This function retrieves all entities of type a that match
-- some query criteria. The function takes an HDBC connection and a
-- WhereClauseExpr as parameters. The type a is
-- determined by the context of the function call. The function returns a
-- (possibly empty) list of all matching entities. The
-- WhereClauseExpr is typically constructed using any tiny query
-- dsl based on infix operators.
select :: forall a. Entity a => Conn -> WhereClauseExpr -> IO [a]
-- | This function converts a list of database rows, represented as a
-- `[[SqlValue]]` to a list of entities. The function takes an HDBC
-- connection and a list of database rows as parameters. The type
-- a is determined by the context of the function call. The
-- function returns a (possibly empty) list of all matching entities. The
-- function is used internally by retrieveAll and
-- retrieveAllWhere. But it can also be used to convert the
-- result of a custom SQL query to a list of entities.
entitiesFromRows :: forall a. Entity a => Conn -> [[SqlValue]] -> IO [a]
-- | A function that persists an entity to a database. The function takes
-- an HDBC connection and an entity as parameters. The entity is either
-- inserted or updated, depending on whether it already exists in the
-- database. The required SQL statements are generated dynamically using
-- Haskell generics and reflection
persist :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that explicitely inserts an entity into a database.
insert :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that inserts a list of entities into a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The insert-statement is compiled only once and then
-- executed for each entity.
insertMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | A function that explicitely updates an entity in a database.
update :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that updates a list of entities in a database. The function
-- takes an HDBC connection and a list of entities as parameters. The
-- update-statement is compiled only once and then executed for each
-- entity.
updateMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | A function that deletes an entity from a database. The function takes
-- an HDBC connection and an entity as parameters.
delete :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that deletes a list of entities from a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The delete-statement is compiled only once and then
-- executed for each entity.
deleteMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | set up a table for a given entity type. The table is dropped (if
-- existing) and recreated. The function takes an HDBC connection as
-- parameter.
setupTableFor :: forall a. Entity a => Conn -> IO ()
-- | A function that returns the primary key value of an entity as a
-- SqlValue. The function takes an HDBC connection and an entity as
-- parameters.
idValue :: forall a. Entity a => Conn -> a -> IO SqlValue
-- | This module defines a wrapper around an HDBC IConnection. Using this
-- wrapper Conn simplifies the signature of the functions in the
-- GP module. It allows to use any HDBC connection without having
-- to define a new function for each connection type. It also provides
-- additional attributes to the connection, like the database type and
-- the implicit commit flag. These attributes can be used to implement
-- database specific functionality, modify transaction behaviour, etc.
--
-- This code has been inspired by the HDBC ConnectionWrapper and some
-- parts have been copied verbatim from the HDBC Database.HDBC.Types
-- module.
--
-- This module also defines a ConnectionPool type, which provides basic
-- connection pooling functionality.
--
-- A wrapper around an HDBC IConnection.
data Conn
Conn :: Database -> Bool -> conn -> Conn
-- | The database type
[db] :: Conn -> Database
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[implicitCommit] :: Conn -> Bool
-- | The wrapped connection
[connection] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => Database -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
MySQL :: Database
SQLite :: Database
Oracle :: Database
MSSQL :: Database
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => Database -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
withResource :: Pool a -> (a -> IO r) -> IO r
-- | This is the Entity class. It is a type class that is used to define
-- the mapping between a Haskell product type in record notation and a
-- database table. The class has a default implementation for all
-- methods. The default implementation uses the type information to
-- determine a simple 1:1 mapping.
--
-- That means that - the type name is used as the table name and the -
-- field names are used as the column names. - A field named
-- 'typeNameID' is used as the primary key field.
--
-- The default implementation can be overridden by defining a custom
-- instance for a type.
--
-- Please note the following constraints, which apply to all valid Entity
-- type, but that are not explicitely encoded in the type class
-- definition:
--
--
-- - The type must be a product type in record notation.
-- - The type must have exactly one constructor.
-- - There must be single primary key field, compund primary keys are
-- not supported.
--
class (Generic a, HasConstructor (Rep a), HasSelectors (Rep a)) => Entity a
-- | Converts a database row to a value of type a.
fromRow :: Entity a => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: Entity a => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
-- | Converts a database row to a value of type a.
fromRow :: (Entity a, GFromRow (Rep a)) => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: (Entity a, GToRow (Rep a)) => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
class GToRow f
class GFromRow f
-- | A convenience function: returns the name of the column for a field of
-- a type a.
columnNameFor :: forall a. Entity a => String -> String
maybeFieldTypeFor :: forall a. Entity a => String -> Maybe TypeRep
-- | Returns a string representation of a value of type a.
toString :: forall a. (Generic a, GShow' (Rep a)) => a -> String
-- | A data type holding meta-data about a type. The Phantom type parameter
-- a ensures type safety for reflective functions that use this
-- type to create type instances.
data TypeInfo a
-- | this function is a smart constructor for TypeInfo objects. It takes a
-- value of type a and returns a `TypeInfo a` object. If the
-- type has no named fields, an error is thrown. If the type has more
-- than one constructor, an error is thrown.
typeInfo :: forall a. (HasConstructor (Rep a), HasSelectors (Rep a), Generic a) => TypeInfo a
-- | This is the "safe" version of the module
-- Database.GP.GenericPersistence. It uses Either to return errors.
--
-- This module defines RDBMS Persistence operations for Record Data Types
-- that are instances of Data. I call instances of such a data
-- type Entities.
--
-- The Persistence operations are using Haskell generics to provide
-- compile time reflection capabilities. HDBC is used to access the
-- RDBMS.
--
-- exceptions that may occur during persistence operations
data PersistenceException
EntityNotFound :: String -> PersistenceException
DuplicateInsert :: String -> PersistenceException
DatabaseError :: String -> PersistenceException
NoUniqueKey :: String -> PersistenceException
data WhereClauseExpr
data Field
field :: String -> Field
(&&.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 3 &&.
(||.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 2 ||.
(=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 =.
(>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >.
(<.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <.
(>=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >=.
(<=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <=.
(<>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <>.
like :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 `like`
contains :: Convertible a SqlValue => Field -> a -> WhereClauseExpr
infixl 4 `contains`
between :: (Convertible a1 SqlValue, Convertible a2 SqlValue) => Field -> (a1, a2) -> WhereClauseExpr
infixl 4 `between`
in' :: Convertible b SqlValue => Field -> [b] -> WhereClauseExpr
infixl 4 `in'`
isNull :: Field -> WhereClauseExpr
not' :: WhereClauseExpr -> WhereClauseExpr
sqlFun :: String -> Field -> Field
allEntries :: WhereClauseExpr
byId :: Convertible a SqlValue => a -> WhereClauseExpr
module Database.GP
-- | This module defines RDBMS Persistence operations for Record Data Types
-- that are instances of Data. I call instances of such a data
-- type Entities.
--
-- The Persistence operations are using Haskell generics to provide
-- compile time reflection capabilities. HDBC is used to access the
-- RDBMS.
--
-- A function that retrieves an entity from a database. The function
-- takes entity id as parameter. If an entity with the given id exists in
-- the database, it is returned as a Just value. If no such entity
-- exists, Nothing is returned. An error is thrown if there are more than
-- one entity with the given id.
selectById :: forall a id. (Entity a, Convertible id SqlValue) => Conn -> id -> IO (Maybe a)
-- | This function retrieves all entities of type a from a
-- database. The function takes an HDBC connection as parameter. The type
-- a is determined by the context of the function call.
-- retrieveAll :: forall a. (Entity a) => Conn -> IO [a]
-- retrieveAll conn = do eitherExRow <- GpSafe.retrieveAll @a conn
-- case eitherExRow of Left ex -> throw ex Right rows -> pure rows
--
-- This function retrieves all entities of type a that match
-- some query criteria. The function takes an HDBC connection and a
-- WhereClauseExpr as parameters. The type a is
-- determined by the context of the function call. The function returns a
-- (possibly empty) list of all matching entities. The
-- WhereClauseExpr is typically constructed using any tiny query
-- dsl based on infix operators.
select :: forall a. Entity a => Conn -> WhereClauseExpr -> IO [a]
-- | This function converts a list of database rows, represented as a
-- `[[SqlValue]]` to a list of entities. The function takes an HDBC
-- connection and a list of database rows as parameters. The type
-- a is determined by the context of the function call. The
-- function returns a (possibly empty) list of all matching entities. The
-- function is used internally by retrieveAll and
-- retrieveAllWhere. But it can also be used to convert the
-- result of a custom SQL query to a list of entities.
entitiesFromRows :: forall a. Entity a => Conn -> [[SqlValue]] -> IO [a]
-- | A function that persists an entity to a database. The function takes
-- an HDBC connection and an entity as parameters. The entity is either
-- inserted or updated, depending on whether it already exists in the
-- database. The required SQL statements are generated dynamically using
-- Haskell generics and reflection
persist :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that explicitely inserts an entity into a database.
insert :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that inserts a list of entities into a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The insert-statement is compiled only once and then
-- executed for each entity.
insertMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | A function that explicitely updates an entity in a database.
update :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that updates a list of entities in a database. The function
-- takes an HDBC connection and a list of entities as parameters. The
-- update-statement is compiled only once and then executed for each
-- entity.
updateMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | A function that deletes an entity from a database. The function takes
-- an HDBC connection and an entity as parameters.
delete :: forall a. Entity a => Conn -> a -> IO ()
-- | A function that deletes a list of entities from a database. The
-- function takes an HDBC connection and a list of entities as
-- parameters. The delete-statement is compiled only once and then
-- executed for each entity.
deleteMany :: forall a. Entity a => Conn -> [a] -> IO ()
-- | set up a table for a given entity type. The table is dropped (if
-- existing) and recreated. The function takes an HDBC connection as
-- parameter.
setupTableFor :: forall a. Entity a => Conn -> IO ()
-- | A function that returns the primary key value of an entity as a
-- SqlValue. The function takes an HDBC connection and an entity as
-- parameters.
idValue :: forall a. Entity a => Conn -> a -> IO SqlValue
-- | This module defines a wrapper around an HDBC IConnection. Using this
-- wrapper Conn simplifies the signature of the functions in the
-- GP module. It allows to use any HDBC connection without having
-- to define a new function for each connection type. It also provides
-- additional attributes to the connection, like the database type and
-- the implicit commit flag. These attributes can be used to implement
-- database specific functionality, modify transaction behaviour, etc.
--
-- This code has been inspired by the HDBC ConnectionWrapper and some
-- parts have been copied verbatim from the HDBC Database.HDBC.Types
-- module.
--
-- This module also defines a ConnectionPool type, which provides basic
-- connection pooling functionality.
--
-- A wrapper around an HDBC IConnection.
data Conn
Conn :: Database -> Bool -> conn -> Conn
-- | The database type
[db] :: Conn -> Database
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[implicitCommit] :: Conn -> Bool
-- | The wrapped connection
[connection] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => Database -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
MySQL :: Database
SQLite :: Database
Oracle :: Database
MSSQL :: Database
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => Database -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
withResource :: Pool a -> (a -> IO r) -> IO r
-- | This is the Entity class. It is a type class that is used to define
-- the mapping between a Haskell product type in record notation and a
-- database table. The class has a default implementation for all
-- methods. The default implementation uses the type information to
-- determine a simple 1:1 mapping.
--
-- That means that - the type name is used as the table name and the -
-- field names are used as the column names. - A field named
-- 'typeNameID' is used as the primary key field.
--
-- The default implementation can be overridden by defining a custom
-- instance for a type.
--
-- Please note the following constraints, which apply to all valid Entity
-- type, but that are not explicitely encoded in the type class
-- definition:
--
--
-- - The type must be a product type in record notation.
-- - The type must have exactly one constructor.
-- - There must be single primary key field, compund primary keys are
-- not supported.
--
class (Generic a, HasConstructor (Rep a), HasSelectors (Rep a)) => Entity a
-- | Converts a database row to a value of type a.
fromRow :: Entity a => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: Entity a => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
-- | Converts a database row to a value of type a.
fromRow :: (Entity a, GFromRow (Rep a)) => Conn -> [SqlValue] -> IO a
-- | Converts a value of type a to a database row.
toRow :: (Entity a, GToRow (Rep a)) => Conn -> a -> IO [SqlValue]
-- | Returns the name of the primary key field for a type a.
idField :: Entity a => String
-- | Returns a list of tuples that map field names to column names for a
-- type a.
fieldsToColumns :: Entity a => [(String, String)]
-- | Returns the name of the table for a type a.
tableName :: Entity a => String
class GToRow f
class GFromRow f
-- | A convenience function: returns the name of the column for a field of
-- a type a.
columnNameFor :: forall a. Entity a => String -> String
maybeFieldTypeFor :: forall a. Entity a => String -> Maybe TypeRep
-- | Returns a string representation of a value of type a.
toString :: forall a. (Generic a, GShow' (Rep a)) => a -> String
-- | A data type holding meta-data about a type. The Phantom type parameter
-- a ensures type safety for reflective functions that use this
-- type to create type instances.
data TypeInfo a
-- | this function is a smart constructor for TypeInfo objects. It takes a
-- value of type a and returns a `TypeInfo a` object. If the
-- type has no named fields, an error is thrown. If the type has more
-- than one constructor, an error is thrown.
typeInfo :: forall a. (HasConstructor (Rep a), HasSelectors (Rep a), Generic a) => TypeInfo a
-- | This is the "safe" version of the module
-- Database.GP.GenericPersistence. It uses Either to return errors.
--
-- This module defines RDBMS Persistence operations for Record Data Types
-- that are instances of Data. I call instances of such a data
-- type Entities.
--
-- The Persistence operations are using Haskell generics to provide
-- compile time reflection capabilities. HDBC is used to access the
-- RDBMS.
--
-- exceptions that may occur during persistence operations
data PersistenceException
EntityNotFound :: String -> PersistenceException
DuplicateInsert :: String -> PersistenceException
DatabaseError :: String -> PersistenceException
NoUniqueKey :: String -> PersistenceException
data WhereClauseExpr
data Field
field :: String -> Field
(&&.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 3 &&.
(||.) :: WhereClauseExpr -> WhereClauseExpr -> WhereClauseExpr
infixl 2 ||.
(=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 =.
(>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >.
(<.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <.
(>=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 >=.
(<=.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <=.
(<>.) :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 <>.
like :: Convertible b SqlValue => Field -> b -> WhereClauseExpr
infixl 4 `like`
contains :: Convertible a SqlValue => Field -> a -> WhereClauseExpr
infixl 4 `contains`
between :: (Convertible a1 SqlValue, Convertible a2 SqlValue) => Field -> (a1, a2) -> WhereClauseExpr
infixl 4 `between`
in' :: Convertible b SqlValue => Field -> [b] -> WhereClauseExpr
infixl 4 `in'`
isNull :: Field -> WhereClauseExpr
not' :: WhereClauseExpr -> WhereClauseExpr
sqlFun :: String -> Field -> Field
allEntries :: WhereClauseExpr