{-# LANGUAGE RankNTypes #-} -- #hide {-| Basic type class & type definitions for DB interfacing. -} module Database.HSQL.Types (SQL,TableId,Connection(..) ,ColId,Nullability,ColDef,FieldReader,FieldReading,Statement(..) ,SqlBind(..),SqlType(..),SqlError(..)) where import Control.Concurrent.MVar(MVar) import Control.Exception(throw) import Foreign(nullPtr) import Foreign.C(CString,peekCStringLen) import DB.HSQL.Type(SqlType(..)) import DB.HSQL.Error(SqlError(..)) -- | A table column ID. type ColId = String -- | Whether fields of a table col may be NULL. type Nullability = Bool -- | Description of the properties of a table column. type ColDef = (ColId, SqlType, Nullability) -- | An SQL Query. type SQL = String -- | A table ID. type TableId = String -- | A 'Connection' type represents a connection to a database, -- through which you can operate on the it. -- In order to create the connection you need to use the @connect@ function -- from the module for your prefered backend. data Connection = Connection { -- | disconnect action connDisconnect :: IO (), -- | query execution action (without return value) connExecute :: SQL -> IO (), -- | query action with return value connQuery :: SQL -> IO Statement, -- | retrieval of the names of the tables in reach connTables :: IO [TableId], -- | retrieval of the field defs of a table connDescribe :: TableId -> IO [ColDef], -- | begin of a transaction connBeginTransaction :: IO (), -- | commit of a pending transaction connCommitTransaction :: IO (), -- | rollback of a pending transaction connRollbackTransaction :: IO (), -- | closing state of the connection connClosed :: MVar Bool } -- | A DB generic field extraction function, specifiable by -- field definition, receiving the content code and its length. type FieldReader t = ColDef -- ^ field type spec -> CString -- ^ field content code -> Int -- ^ field content length -> IO t -- ^ field read action -- | An extraction of a field of type to be specified by requester, -- from a row index with source `ColDef', applying an appropriate -- `FieldReader'. type FieldReading = forall t . Int -- ^ field (column) index -> ColDef -- ^ source field type spec -> FieldReader t -- ^ field reader to be applied -> IO t -- ^ field read action -- | The 'Statement' type represents a result from the execution of given -- SQL query. data Statement = Statement { -- | DB connection the statement depends on stmtConn :: Connection, -- | close action stmtClose :: IO (), -- | incrementation of the row pointer and indication -- whether this is still in range of available rows stmtFetch :: IO Bool, -- | a `FieldReading' function applicable for each row stmtGetCol :: FieldReading, -- | field descriptors for each result table column stmtFields :: [ColDef], -- | check whether the statement is closed stmtClosed :: MVar Bool } -- | Equivalent to Show and Read adapted to SQL expressions. class SqlBind a where -- | show as an SQL expression toSqlValue:: a-> SQL -- | read from an SQL expression in text representation, -- by support of its `SqlType' fromSqlValue:: SqlType-> SQL-> Maybe a -- | read from SQL expression in binary representation, -- by support of its `ColDef' and code size info. -- This allows for faster conversion for e.g. integral numeric types, -- etc. fromSqlCStringLen:: ColDef -> CString -- ^ binary content of SQL expression -> Int -- ^ size of binary content -> IO a fromSqlCStringLen (name,sqlType,_) cstr cstrLen | cstr == nullPtr = throw (SqlFetchNull name) | otherwise = do str <- peekCStringLen (cstr, cstrLen) case fromSqlValue sqlType str of Nothing -> throw (SqlBadTypeCast name sqlType) Just v -> return v