-- 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.6.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 :: Bool -> conn -> Conn
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[$sel:implicitCommit:Conn] :: Conn -> Bool
-- | The wrapped connection
[$sel:connection:Conn] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => TxHandling -> conn -> Conn
data TxHandling
AutoCommit :: TxHandling
ExplicitCommit :: TxHandling
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => TxHandling -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
-- | Take a resource from the pool, perform an action with it and return it
-- to the pool afterwards.
--
--
-- - If the pool has an idle resource available, it is used
-- immediately.
-- - Otherwise, if the maximum number of resources has not yet been
-- reached, a new resource is created and used.
-- - If the maximum number of resources has been reached, this function
-- blocks until a resource becomes available.
--
--
-- If the action throws an exception of any type, the resource is
-- destroyed and not returned to the pool.
--
-- It probably goes without saying that you should never manually destroy
-- a pooled resource, as doing so will almost certainly cause a
-- subsequent user (who expects the resource to be valid) to throw an
-- exception.
withResource :: Pool a -> (a -> IO r) -> IO r
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
($sel:fieldNames:TypeInfo) :: TypeInfo a -> [String]
($sel:fieldTypes:TypeInfo) :: TypeInfo a -> [SomeTypeRep]
($sel:constructorName:TypeInfo) :: 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 (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.HasConstructor f => Database.GP.TypeInfo.HasConstructor (GHC.Generics.D1 c f)
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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
-- | 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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
-- | A convenience function: returns the name of the column for a field of
-- a type a.
columnNameFor :: forall a. Entity a => String -> 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 :: Bool -> conn -> Conn
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[$sel:implicitCommit:Conn] :: Conn -> Bool
-- | The wrapped connection
[$sel:connection:Conn] :: Conn -> conn
data TxHandling
AutoCommit :: TxHandling
ExplicitCommit :: TxHandling
-- | Returns Just index of the primary key field for a type a. if
-- the type has no primary key field, Nothing is returned.
maybeIdFieldIndex :: forall a. Entity a => Maybe Int
-- | returns the index of a field of an entity. The index is the position
-- of the field in the list of fields of the entity. If no such field
-- exists, an error is thrown. The function takes an field name as
-- parameters, the type of the entity is determined by the context.
fieldIndex :: forall a. Entity a => String -> Int
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 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 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`
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
byIdColumn :: WhereClauseExpr
orderBy :: WhereClauseExpr -> NonEmpty (Field, SortOrder) -> WhereClauseExpr
infixl 1 `orderBy`
data SortOrder
ASC :: SortOrder
DESC :: SortOrder
limit :: WhereClauseExpr -> Int -> WhereClauseExpr
limitOffset :: WhereClauseExpr -> (Int, Int) -> WhereClauseExpr
-- | Non-empty (and non-strict) list type.
data () => NonEmpty a
(:|) :: a -> [a] -> NonEmpty a
infixr 5 :|
instance GHC.Show.Show Database.GP.Query.SortOrder
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
insertReturningStmtFor :: 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
-- | A function that returns the column type for a field of an entity.
-- TODO: Support other databases than just SQLite and Postgres.
columnTypeFor :: forall a. Entity a => Database -> String -> 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`
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
byIdColumn :: WhereClauseExpr
orderBy :: WhereClauseExpr -> NonEmpty (Field, SortOrder) -> WhereClauseExpr
infixl 1 `orderBy`
data SortOrder
ASC :: SortOrder
DESC :: SortOrder
limit :: WhereClauseExpr -> Int -> WhereClauseExpr
limitOffset :: WhereClauseExpr -> (Int, Int) -> WhereClauseExpr
-- | Non-empty (and non-strict) list type.
data () => NonEmpty a
(:|) :: a -> [a] -> NonEmpty a
infixr 5 :|
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
SQLite :: Database
instance GHC.Classes.Eq Database.GP.SqlGenerator.Database
instance GHC.Show.Show Database.GP.SqlGenerator.Database
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])
sql :: QuasiQuoter
-- | 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)
-- | 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 => Database -> Conn -> IO ()
-- | 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 :: Bool -> conn -> Conn
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[$sel:implicitCommit:Conn] :: Conn -> Bool
-- | The wrapped connection
[$sel:connection:Conn] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => TxHandling -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
SQLite :: Database
data TxHandling
AutoCommit :: TxHandling
ExplicitCommit :: TxHandling
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => TxHandling -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
-- | Take a resource from the pool, perform an action with it and return it
-- to the pool afterwards.
--
--
-- - If the pool has an idle resource available, it is used
-- immediately.
-- - Otherwise, if the maximum number of resources has not yet been
-- reached, a new resource is created and used.
-- - If the maximum number of resources has been reached, this function
-- blocks until a resource becomes available.
--
--
-- If the action throws an exception of any type, the resource is
-- destroyed and not returned to the pool.
--
-- It probably goes without saying that you should never manually destroy
-- a pooled resource, as doing so will almost certainly cause a
-- subsequent user (who expects the resource to be valid) to throw an
-- exception.
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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
-- | 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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
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
-- | 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`
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
orderBy :: WhereClauseExpr -> NonEmpty (Field, SortOrder) -> WhereClauseExpr
infixl 1 `orderBy`
data SortOrder
ASC :: SortOrder
DESC :: SortOrder
limit :: WhereClauseExpr -> Int -> WhereClauseExpr
limitOffset :: WhereClauseExpr -> (Int, Int) -> WhereClauseExpr
-- | returns the index of a field of an entity. The index is the position
-- of the field in the list of fields of the entity. If no such field
-- exists, an error is thrown. The function takes an field name as
-- parameters, the type of the entity is determined by the context.
fieldIndex :: forall a. Entity a => String -> Int
handleDuplicateInsert :: SomeException -> PersistenceException
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]
-- | A function that constructs a list of entities from a list of rows. The
-- function takes an HDBC connection and a list of rows as parameters.
-- The type a is determined by the context of the function call.
-- The function returns a list of entities. This can be useful if you
-- want to use your own SQL queries.
entitiesFromRows :: forall a. Entity a => Conn -> [[SqlValue]] -> IO [a]
sql :: QuasiQuoter
-- | 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
-- | 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 => Database -> Conn -> IO ()
-- | 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 :: Bool -> conn -> Conn
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[$sel:implicitCommit:Conn] :: Conn -> Bool
-- | The wrapped connection
[$sel:connection:Conn] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => TxHandling -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
SQLite :: Database
data TxHandling
AutoCommit :: TxHandling
ExplicitCommit :: TxHandling
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => TxHandling -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
-- | Take a resource from the pool, perform an action with it and return it
-- to the pool afterwards.
--
--
-- - If the pool has an idle resource available, it is used
-- immediately.
-- - Otherwise, if the maximum number of resources has not yet been
-- reached, a new resource is created and used.
-- - If the maximum number of resources has been reached, this function
-- blocks until a resource becomes available.
--
--
-- If the action throws an exception of any type, the resource is
-- destroyed and not returned to the pool.
--
-- It probably goes without saying that you should never manually destroy
-- a pooled resource, as doing so will almost certainly cause a
-- subsequent user (who expects the resource to be valid) to throw an
-- exception.
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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
-- | 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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
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
-- | 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`
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
orderBy :: WhereClauseExpr -> NonEmpty (Field, SortOrder) -> WhereClauseExpr
infixl 1 `orderBy`
data SortOrder
ASC :: SortOrder
DESC :: SortOrder
limit :: WhereClauseExpr -> Int -> WhereClauseExpr
limitOffset :: WhereClauseExpr -> (Int, Int) -> WhereClauseExpr
-- | Non-empty (and non-strict) list type.
data () => NonEmpty a
(:|) :: a -> [a] -> NonEmpty a
infixr 5 :|
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]
-- | A function that constructs a list of entities from a list of rows. The
-- function takes an HDBC connection and a list of rows as parameters.
-- The type a is determined by the context of the function call.
-- The function returns a list of entities. This can be useful if you
-- want to use your own SQL queries.
entitiesFromRows :: forall a. Entity a => Conn -> [[SqlValue]] -> IO [a]
sql :: QuasiQuoter
-- | 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
-- | 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 => Database -> Conn -> IO ()
-- | 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 :: Bool -> conn -> Conn
-- | If True, the GenericPersistence functions will commit the transaction
-- after each operation.
[$sel:implicitCommit:Conn] :: Conn -> Bool
-- | The wrapped connection
[$sel:connection:Conn] :: Conn -> conn
-- | a smart constructor for the Conn type.
connect :: forall conn. IConnection conn => TxHandling -> conn -> Conn
-- | An enumeration of the supported database types.
data Database
Postgres :: Database
SQLite :: Database
data TxHandling
AutoCommit :: TxHandling
ExplicitCommit :: TxHandling
-- | A pool of connections.
type ConnectionPool = Pool Conn
-- | Creates a connection pool.
createConnPool :: IConnection conn => TxHandling -> String -> (String -> IO conn) -> Double -> Int -> IO ConnectionPool
-- | Take a resource from the pool, perform an action with it and return it
-- to the pool afterwards.
--
--
-- - If the pool has an idle resource available, it is used
-- immediately.
-- - Otherwise, if the maximum number of resources has not yet been
-- reached, a new resource is created and used.
-- - If the maximum number of resources has been reached, this function
-- blocks until a resource becomes available.
--
--
-- If the action throws an exception of any type, the resource is
-- destroyed and not returned to the pool.
--
-- It probably goes without saying that you should never manually destroy
-- a pooled resource, as doing so will almost certainly cause a
-- subsequent user (who expects the resource to be valid) to throw an
-- exception.
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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
-- | 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
-- | Returns True if the primary key field for a type a is
-- autoincremented by the database.
autoIncrement :: Entity a => Bool
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
-- | 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`
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
orderBy :: WhereClauseExpr -> NonEmpty (Field, SortOrder) -> WhereClauseExpr
infixl 1 `orderBy`
data SortOrder
ASC :: SortOrder
DESC :: SortOrder
limit :: WhereClauseExpr -> Int -> WhereClauseExpr
limitOffset :: WhereClauseExpr -> (Int, Int) -> WhereClauseExpr
-- | Non-empty (and non-strict) list type.
data () => NonEmpty a
(:|) :: a -> [a] -> NonEmpty a
infixr 5 :|
-- | SqlValue is the main type for expressing Haskell values to SQL
-- databases.
--
-- INTRODUCTION TO SQLVALUE
--
-- This type is used to marshall Haskell data to and from database APIs.
-- HDBC driver interfaces will do their best to use the most accurate and
-- efficient way to send a particular value to the database server.
--
-- Values read back from the server are constructed with the most
-- appropriate SqlValue constructor. fromSql or
-- safeFromSql can then be used to convert them into whatever type
-- is needed locally in Haskell.
--
-- Most people will use toSql and fromSql instead of
-- manipulating SqlValues directly.
--
-- EASY CONVERSIONS BETWEEN HASKELL TYPES
--
-- Conversions are powerful; for instance, you can call fromSql on
-- a SqlInt32 and get a String or a Double out of it. This class attempts
-- to Do The Right Thing whenever possible, and will raise an error when
-- asked to do something incorrect. In particular, when converting to any
-- type except a Maybe, SqlNull as the input will cause an error
-- to be raised.
--
-- Conversions are implemented in terms of the Data.Convertible
-- module, part of the convertible package. You can refer to its
-- documentation, and import that module, if you wish to parse the Left
-- result from safeFromSql yourself, or write your own conversion
-- instances.
--
-- Here are some notes about conversion:
--
--
-- - Fractions of a second are not preserved on time values
-- - There is no safeToSql because toSql never
-- fails.
--
--
-- See also toSql, safeFromSql, fromSql,
-- nToSql, iToSql, posixToSql.
--
-- ERROR CONDITIONS
--
-- There may sometimes be an error during conversion. For instance, if
-- you have a SqlString and are attempting to convert it to an
-- Integer, but it doesn't parse as an Integer, you will get an error.
-- This will be indicated as an exception if using fromSql, or a
-- Left result if using safeFromSql.
--
-- SPECIAL NOTE ON POSIXTIME
--
-- Note that a NominalDiffTime or POSIXTime is converted to
-- SqlDiffTime by toSql. HDBC cannot differentiate between
-- NominalDiffTime and POSIXTime since they are the same
-- underlying type. You must construct SqlPOSIXTime manually or
-- via posixToSql, or use SqlUTCTime.
--
-- DETAILS ON SQL TYPES
--
-- HDBC database backends are expected to marshal date and time data back
-- and forth using the appropriate representation for the underlying
-- database engine. Databases such as PostgreSQL with builtin date and
-- time types should see automatic conversion between these Haskell types
-- to database types. Other databases will be presented with an integer
-- or a string. Care should be taken to use the same type on the Haskell
-- side as you use on the database side. For instance, if your database
-- type lacks timezone information, you ought not to use ZonedTime, but
-- instead LocalTime or UTCTime. Database type systems are not always as
-- rich as Haskell. For instance, for data stored in a TIMESTAMP WITHOUT
-- TIME ZONE column, HDBC may not be able to tell if it is intended as
-- UTCTime or LocalTime data, and will happily convert it to both, upon
-- your request. It is your responsibility to ensure that you treat
-- timezone issues with due care.
--
-- This behavior also exists for other types. For instance, many
-- databases do not have a Rational type, so they will just use the show
-- function and store a Rational as a string.
--
-- The conversion between Haskell types and database types is complex,
-- and generic code in HDBC or its backends cannot possibly accomodate
-- every possible situation. In some cases, you may be best served by
-- converting your Haskell type to a String, and passing that to the
-- database.
--
-- UNICODE AND BYTESTRINGS
--
-- Beginning with HDBC v2.0, interactions with a database are presumed to
-- occur in UTF-8.
--
-- To accomplish this, whenever a ByteString must be converted to or from
-- a String, the ByteString is assumed to be in UTF-8 encoding, and will
-- be decoded or encoded as appropriate. Database drivers will generally
-- present text or string data they have received from the database as a
-- SqlValue holding a ByteString, which fromSql will automatically
-- convert to a String, and thus automatically decode UTF-8, when you
-- need it. In the other direction, database drivers will generally
-- convert a SqlString to a ByteString in UTF-8 encoding before
-- passing it to the database engine.
--
-- If you are handling some sort of binary data that is not in UTF-8, you
-- can of course work with the ByteString directly, which will bypass any
-- conversion.
--
-- Due to lack of support by database engines, lazy ByteStrings are not
-- passed to database drivers. When you use toSql on a lazy
-- ByteString, it will be converted to a strict ByteString for storage.
-- Similarly, fromSql will convert a strict ByteString to a lazy
-- ByteString if you demand it.
--
-- EQUALITY OF SQLVALUE
--
-- Two SqlValues are considered to be equal if one of these hold. The
-- first comparison that can be made is controlling; if none of these
-- comparisons can be made, then they are not equal:
--
--
-- - Both are NULL
-- - Both represent the same type and the encapsulated values are
-- considered equal by applying (==) to them
-- - The values of each, when converted to a string, are equal
--
--
-- STRING VERSIONS OF TIMES
--
-- Default string representations are given as comments below where such
-- are non-obvious. These are used for fromSql when a
-- String is desired. They are also defaults for representing data
-- to SQL backends, though individual backends may override them when a
-- different format is demanded by the underlying database. Date and time
-- formats use ISO8601 date format, with HH:MM:SS added for time, and
-- -HHMM added for timezone offsets.
--
-- DEPRECATED CONSTRUCTORS
--
-- SqlEpochTime and SqlTimeDiff are no longer created
-- automatically by any toSql or fromSql functions or
-- database backends. They may still be manually constructed, but are
-- expected to be removed in a future version. Although these two
-- constructures will be removed, support for marshalling to and from the
-- old System.Time data will be maintained as long as System.Time is,
-- simply using the newer data types for conversion.
data () => SqlValue
-- | Convert from an SqlValue to a Haskell value. Any problem is
-- indicated by calling error. This function is simply a
-- restricted-type wrapper around convert. See extended notes on
-- SqlValue.
fromSql :: Convertible SqlValue a => SqlValue -> a
-- | Convert a value to an SqlValue. This function is simply a
-- restricted-type wrapper around convert. See extended notes on
-- SqlValue.
toSql :: Convertible a SqlValue => a -> SqlValue
-- | A quick way to do a query. Similar to preparing, executing, and then
-- calling fetchAllRows on a statement. See also
-- quickQuery'.
quickQuery :: IConnection conn => conn -> String -> [SqlValue] -> IO [[SqlValue]]
-- | Execute a single SQL query. Returns the number of rows modified (see
-- execute for details). The second parameter is a list of
-- replacement values, if any.
run :: IConnection conn => conn -> String -> [SqlValue] -> IO Integer
-- | Commit any pending data to the database.
--
-- Required to make any changes take effect.
commit :: IConnection conn => conn -> IO ()
-- | Roll back to the state the database was in prior to the last
-- commit or rollback.
rollback :: IConnection conn => conn -> IO ()
-- | Execute some code. If any uncaught exception occurs, run
-- rollback and re-raise it. Otherwise, run commit and
-- return.
--
-- This function, therefore, encapsulates the logical property that a
-- transaction is all about: all or nothing.
--
-- The IConnection object passed in is passed directly to the
-- specified function as a convenience.
--
-- This function traps all uncaught exceptions, not just
-- SqlErrors. Therefore, you will get a rollback for any exception that
-- you don't handle. That's probably what you want anyway.
--
-- Since all operations in HDBC are done in a transaction, this function
-- doesn't issue an explicit "begin" to the server. You should ideally
-- have called commit or rollback before calling this
-- function. If you haven't, this function will commit or rollback more
-- than just the changes made in the included action.
--
-- If there was an error while running rollback, this error will
-- not be reported since the original exception will be propogated back.
-- (You'd probably like to know about the root cause for all of this
-- anyway.) Feedback on this behavior is solicited.
withTransaction :: IConnection conn => conn -> (conn -> IO a) -> IO a
-- | Execute an SQL string, which may contain multiple queries. This is
-- intended for situations where you need to run DML or DDL queries and
-- aren't interested in results.
runRaw :: IConnection conn => conn -> String -> IO ()
-- | Disconnect from the remote database.
--
-- You do not need to explicitly close an IConnection object, but you may
-- do so if you so desire. If you don't, the object will disconnect from
-- the database in a sane way when it is garbage-collected. However, a
-- disconnection may raise an error, so you are encouraged to explicitly
-- call disconnect. Also, garbage collection may not run when the
-- program terminates, and some databases really like an explicit
-- disconnect.
--
-- So, bottom line is, you're best off calling disconnect
-- directly, but the world won't end if you forget.
--
-- This function discards any data not committed already. Database driver
-- implementators should explicitly call rollback if their
-- databases don't do this automatically on disconnect.
--
-- Bad Things (TM) could happen if you call this while you have
-- Statements active. In more precise language, the results in
-- such situations are undefined and vary by database. So don't do it.
disconnect :: IConnection conn => conn -> IO ()