hsSqlite3-0.0.1: src/Database/Sqlite3/Low.hs
{-# options -ffi #-}
module Database.Sqlite3.Low where
import System.IO
import Data.Word
import Foreign
import Foreign.C
import qualified Data.ByteString as B
foreign import ccall unsafe "sqlite3_open" open'
:: CString -> Ptr (Ptr Void) -> IO Int
foreign import ccall unsafe "sqlite3_close" close'
:: Ptr Void -> IO Int
foreign import ccall unsafe "sqlite3_errmsg" errmsg'
:: Ptr Void -> IO CString
foreign import ccall unsafe "sqlite3_prepare_v2" prepare'
:: Ptr Void -> CString -> Int -> Ptr (Ptr Void) -> Ptr CString -> IO Int
foreign import ccall unsafe "sqlite3_finalize" finalize'
:: Ptr Void -> IO Int
foreign import ccall unsafe "sqlite3_reset" reset'
:: Ptr Void -> IO Int
foreign import ccall unsafe "sqlite3_bind_int" bind_int'
:: Ptr Void -> Int -> Int -> IO Int
foreign import ccall unsafe "sqlite3_bind_text" bind_text'
:: Ptr Void -> Int -> CString -> Int -> Int -> IO Int
foreign import ccall unsafe "sqlite3_step" step'
:: Ptr Void -> IO Int
foreign import ccall unsafe "sqlite3_column_blob" column_blob'
:: Ptr Void -> Int -> IO CString
foreign import ccall unsafe "sqlite3_column_bytes" column_bytes'
:: Ptr Void -> Int -> IO Int
foreign import ccall unsafe "sqlite3_column_count" column_count'
:: Ptr Void -> IO Int
foreign import ccall unsafe "sqlite3_column_int" column_int'
:: Ptr Void -> Int -> IO Int
foreign import ccall unsafe "sqlite3_column_double" column_double'
:: Ptr Void -> Int -> IO Double
foreign import ccall unsafe "sqlite3_column_text" column_text'
:: Ptr Void -> Int -> IO CString
foreign import ccall unsafe "sqlite3_column_type" column_type'
:: Ptr Void -> Int -> IO Int
--
type Bytes = B.ByteString
type Void = Word8
data DB = DB (Ptr Void)
data Stmt = Stmt (Ptr Void)
open :: String -> IO DB
open path = do
pptr <- malloc
rc <- withCString path $ \cstr -> open' cstr pptr
ptr <- peek pptr
dbErrRc rc ptr "open"
return (DB ptr)
close :: DB -> IO ()
close (DB db) = do
rc <- close' db
dbErrRc rc db "close"
prepare :: DB -> String -> IO Stmt
prepare (DB db) sql = do
pptr <- malloc
rc <- withCStringLen sql $ \(sql',len) ->
prepare' db sql' len pptr nullPtr
dbErrRc rc db "prepare"
ptr <- peek pptr
return (Stmt ptr)
finalize :: Stmt -> IO ()
finalize (Stmt st) = do
rc <- finalize' st
errRc rc "finalize"
reset :: Stmt -> IO ()
reset (Stmt st) = do
rc <- reset' st
errRc rc "reset"
step :: Stmt -> IO Bool
step (Stmt st) = do
rc <- step' st
errIf (rc /= 100 && rc /= 101) ("step: "++show rc)
return (if rc == 101 then True else False)
bind_int :: Stmt -> Int -> Int -> IO ()
bind_int (Stmt st) num val = do
debug ("bind_int",st,num,val)
rc <- bind_int' st num val
errRc rc "bind_int"
bind_text :: Stmt -> Int -> String -> IO ()
bind_text (Stmt st) num str' =
(debug ("bind_text",st,num,str') >>) $
withCStringLen str' $ \(str,len) -> do
rc <- bind_text' st num str len (-1)
errRc rc "bind_text"
column_blob :: Stmt -> Int -> IO Bytes
column_blob (Stmt st) num = do
by <- column_bytes' st num
bl <- column_blob' st num
return $ B.packCStringLen (bl,by)
column_bytes :: Stmt -> Int -> IO Int
column_bytes (Stmt st) num = column_bytes' st num
column_count :: Stmt -> IO Int
column_count (Stmt st) = column_count' st
column_int :: Stmt -> Int -> IO Int
column_int (Stmt st) num = column_int' st num
column_double :: Stmt -> Int -> IO Double
column_double (Stmt st) = column_double' st
column_text :: Stmt -> Int -> IO String
column_text (Stmt st) num = do
by <- column_bytes' st num
tx <- column_text' st num
peekCStringLen (tx,by)
column_type :: Stmt -> Int -> IO Int
column_type (Stmt st) num = column_type' st num
--
debug :: Show a => a -> IO ()
--debug = hPutStr stderr . ("DEBUG: "++) . (++"\n") . show
debug _ = return ()
err msg = ioError $ userError $ "Sqlite3: "++msg
errIf False _ = return ()
errIf True msg = err $ "Foreign: "++msg
errRc 0 _ = return ()
errRc rc msg = err $ "Foreign: "++msg++": rc="++show rc
dbErrRc 0 _ _ = return ()
dbErrRc rc db msg = do
reason <- errmsg' db >>= peekCString
err $ "Foreign: "++msg++": (rc="++show rc++") "++reason