-- 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 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: -- -- 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 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: -- -- 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 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: -- -- 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 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: -- -- 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: -- -- -- -- 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: -- -- -- -- 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 ()