{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
module Database.SQLite3 (
open,
close,
exec,
execPrint,
execWithCallback,
ExecCallback,
prepare,
prepareUtf8,
step,
stepNoCB,
reset,
finalize,
clearBindings,
bindParameterCount,
bindParameterName,
columnCount,
columnName,
bindSQLData,
bind,
bindNamed,
bindInt,
bindInt64,
bindDouble,
bindText,
bindBlob,
bindZeroBlob,
bindNull,
column,
columns,
typedColumns,
columnType,
columnInt64,
columnDouble,
columnText,
columnBlob,
lastInsertRowId,
changes,
createFunction,
createAggregate,
deleteFunction,
funcArgCount,
funcArgType,
funcArgInt64,
funcArgDouble,
funcArgText,
funcArgBlob,
funcResultSQLData,
funcResultInt64,
funcResultDouble,
funcResultText,
funcResultBlob,
funcResultZeroBlob,
funcResultNull,
getFuncContextDatabase,
createCollation,
deleteCollation,
interrupt,
interruptibly,
blobOpen,
blobClose,
blobReopen,
blobBytes,
blobRead,
blobReadBuf,
blobWrite,
backupInit,
backupFinish,
backupStep,
backupRemaining,
backupPagecount,
Database,
Statement,
SQLData(..),
SQLError(..),
ColumnType(..),
FuncContext,
FuncArgs,
Blob,
Backup,
StepResult(..),
BackupStepResult(..),
Error(..),
ParamIndex(..),
ColumnIndex(..),
ColumnCount,
ArgCount(..),
ArgIndex,
) where
import Database.SQLite3.Direct
( Database
, Statement
, ColumnType(..)
, StepResult(..)
, BackupStepResult(..)
, Error(..)
, ParamIndex(..)
, ColumnIndex(..)
, ColumnCount
, Utf8(..)
, FuncContext
, FuncArgs
, ArgCount(..)
, ArgIndex
, Blob
, Backup
, clearBindings
, bindParameterCount
, columnCount
, columnType
, columnBlob
, columnInt64
, columnDouble
, funcArgCount
, funcArgType
, funcArgInt64
, funcArgDouble
, funcArgBlob
, funcResultInt64
, funcResultDouble
, funcResultBlob
, funcResultZeroBlob
, funcResultNull
, getFuncContextDatabase
, lastInsertRowId
, changes
, interrupt
, blobBytes
, backupRemaining
, backupPagecount
)
import qualified Database.SQLite3.Direct as Direct
import Prelude hiding (error)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Control.Concurrent
import Control.Exception
import Control.Monad (when, zipWithM, zipWithM_)
import Data.ByteString (ByteString)
import Data.Int (Int64)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
import Data.Text.Encoding.Error (UnicodeException(..), lenientDecode)
import Data.Typeable
import Foreign.Ptr (Ptr)
data SQLData
= SQLInteger !Int64
| SQLFloat !Double
| SQLText !Text
| SQLBlob !ByteString
| SQLNull
deriving (SQLData -> SQLData -> Bool
(SQLData -> SQLData -> Bool)
-> (SQLData -> SQLData -> Bool) -> Eq SQLData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SQLData -> SQLData -> Bool
$c/= :: SQLData -> SQLData -> Bool
== :: SQLData -> SQLData -> Bool
$c== :: SQLData -> SQLData -> Bool
Eq, Int -> SQLData -> ShowS
[SQLData] -> ShowS
SQLData -> String
(Int -> SQLData -> ShowS)
-> (SQLData -> String) -> ([SQLData] -> ShowS) -> Show SQLData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SQLData] -> ShowS
$cshowList :: [SQLData] -> ShowS
show :: SQLData -> String
$cshow :: SQLData -> String
showsPrec :: Int -> SQLData -> ShowS
$cshowsPrec :: Int -> SQLData -> ShowS
Show, Typeable)
data SQLError = SQLError
{ SQLError -> Error
sqlError :: !Error
, SQLError -> Text
sqlErrorDetails :: Text
, SQLError -> Text
sqlErrorContext :: Text
}
deriving (SQLError -> SQLError -> Bool
(SQLError -> SQLError -> Bool)
-> (SQLError -> SQLError -> Bool) -> Eq SQLError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SQLError -> SQLError -> Bool
$c/= :: SQLError -> SQLError -> Bool
== :: SQLError -> SQLError -> Bool
$c== :: SQLError -> SQLError -> Bool
Eq, Typeable)
instance Show SQLError where
show :: SQLError -> String
show SQLError{ sqlError :: SQLError -> Error
sqlError = Error
code
, sqlErrorDetails :: SQLError -> Text
sqlErrorDetails = Text
details
, sqlErrorContext :: SQLError -> Text
sqlErrorContext = Text
context
}
= Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat
[ "SQLite3 returned "
, String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Error -> String
forall a. Show a => a -> String
show Error
code
, " while attempting to perform "
, Text
context
, ": "
, Text
details
]
instance Exception SQLError
fromUtf8 :: String -> Utf8 -> IO Text
fromUtf8 :: String -> Utf8 -> IO Text
fromUtf8 desc :: String
desc utf8 :: Utf8
utf8 = Text -> IO Text
forall a. a -> IO a
evaluate (Text -> IO Text) -> Text -> IO Text
forall a b. (a -> b) -> a -> b
$ String -> Utf8 -> Text
fromUtf8' String
desc Utf8
utf8
fromUtf8' :: String -> Utf8 -> Text
fromUtf8' :: String -> Utf8 -> Text
fromUtf8' desc :: String
desc (Utf8 bs :: ByteString
bs) =
OnDecodeError -> ByteString -> Text
decodeUtf8With (\_ c :: Maybe Word8
c -> UnicodeException -> Maybe Char
forall a e. Exception e => e -> a
throw (String -> Maybe Word8 -> UnicodeException
DecodeError String
desc Maybe Word8
c)) ByteString
bs
toUtf8 :: Text -> Utf8
toUtf8 :: Text -> Utf8
toUtf8 = ByteString -> Utf8
Utf8 (ByteString -> Utf8) -> (Text -> ByteString) -> Text -> Utf8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8
data DetailSource
= DetailDatabase Database
| DetailStatement Statement
| DetailMessage Utf8
renderDetailSource :: DetailSource -> IO Utf8
renderDetailSource :: DetailSource -> IO Utf8
renderDetailSource src :: DetailSource
src = case DetailSource
src of
DetailDatabase db :: Database
db ->
Database -> IO Utf8
Direct.errmsg Database
db
DetailStatement stmt :: Statement
stmt -> do
Database
db <- Statement -> IO Database
Direct.getStatementDatabase Statement
stmt
Database -> IO Utf8
Direct.errmsg Database
db
DetailMessage msg :: Utf8
msg ->
Utf8 -> IO Utf8
forall (m :: * -> *) a. Monad m => a -> m a
return Utf8
msg
throwSQLError :: DetailSource -> Text -> Error -> IO a
throwSQLError :: DetailSource -> Text -> Error -> IO a
throwSQLError detailSource :: DetailSource
detailSource context :: Text
context error :: Error
error = do
Utf8 details :: ByteString
details <- DetailSource -> IO Utf8
renderDetailSource DetailSource
detailSource
SQLError -> IO a
forall e a. Exception e => e -> IO a
throwIO $WSQLError :: Error -> Text -> Text -> SQLError
SQLError
{ sqlError :: Error
sqlError = Error
error
, sqlErrorDetails :: Text
sqlErrorDetails = OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode ByteString
details
, sqlErrorContext :: Text
sqlErrorContext = Text
context
}
checkError :: DetailSource -> Text -> Either Error a -> IO a
checkError :: DetailSource -> Text -> Either Error a -> IO a
checkError ds :: DetailSource
ds fn :: Text
fn = (Error -> IO a) -> (a -> IO a) -> Either Error a -> IO a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (DetailSource -> Text -> Error -> IO a
forall a. DetailSource -> Text -> Error -> IO a
throwSQLError DetailSource
ds Text
fn) a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
checkErrorMsg :: Text -> Either (Error, Utf8) a -> IO a
checkErrorMsg :: Text -> Either (Error, Utf8) a -> IO a
checkErrorMsg fn :: Text
fn result :: Either (Error, Utf8) a
result = case Either (Error, Utf8) a
result of
Left (err :: Error
err, msg :: Utf8
msg) -> DetailSource -> Text -> Error -> IO a
forall a. DetailSource -> Text -> Error -> IO a
throwSQLError (Utf8 -> DetailSource
DetailMessage Utf8
msg) Text
fn Error
err
Right a :: a
a -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
appendShow :: Show a => Text -> a -> Text
appendShow :: Text -> a -> Text
appendShow txt :: Text
txt a :: a
a = Text
txt Text -> Text -> Text
`T.append` (String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show) a
a
open :: Text -> IO Database
open :: Text -> IO Database
open path :: Text
path =
Utf8 -> IO (Either (Error, Utf8) Database)
Direct.open (Text -> Utf8
toUtf8 Text
path)
IO (Either (Error, Utf8) Database)
-> (Either (Error, Utf8) Database -> IO Database) -> IO Database
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Either (Error, Utf8) Database -> IO Database
forall a. Text -> Either (Error, Utf8) a -> IO a
checkErrorMsg ("open " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
path)
close :: Database -> IO ()
close :: Database -> IO ()
close db :: Database
db =
Database -> IO (Either Error ())
Direct.close Database
db IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "close"
interruptibly :: Database -> IO a -> IO a
#if MIN_VERSION_base(4,3,0)
interruptibly :: Database -> IO a -> IO a
interruptibly db :: Database
db io :: IO a
io
| Bool
rtsSupportsBoundThreads =
((forall a. IO a -> IO a) -> IO a) -> IO a
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO a) -> IO a)
-> ((forall a. IO a -> IO a) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \restore :: forall a. IO a -> IO a
restore -> do
MVar (Either SomeException a)
mv <- IO (MVar (Either SomeException a))
forall a. IO (MVar a)
newEmptyMVar
ThreadId
tid <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ IO a -> IO (Either SomeException a)
forall a. IO a -> IO (Either SomeException a)
try' (IO a -> IO a
forall a. IO a -> IO a
restore IO a
io) IO (Either SomeException a)
-> (Either SomeException a -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MVar (Either SomeException a) -> Either SomeException a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either SomeException a)
mv
let interruptAndWait :: IO ()
interruptAndWait =
IO () -> IO ()
forall a. IO a -> IO a
uninterruptibleMask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Database -> IO ()
interrupt Database
db
ThreadId -> IO ()
killThread ThreadId
tid
Either SomeException a
_ <- MVar (Either SomeException a) -> IO (Either SomeException a)
forall a. MVar a -> IO a
takeMVar MVar (Either SomeException a)
mv
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Either SomeException a
e <- MVar (Either SomeException a) -> IO (Either SomeException a)
forall a. MVar a -> IO a
takeMVar MVar (Either SomeException a)
mv IO (Either SomeException a) -> IO () -> IO (Either SomeException a)
forall a b. IO a -> IO b -> IO a
`onException` IO ()
interruptAndWait
(SomeException -> IO a)
-> (a -> IO a) -> Either SomeException a -> IO a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> IO a
forall e a. Exception e => e -> IO a
throwIO a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Either SomeException a
e
| Bool
otherwise = IO a
io
where
try' :: IO a -> IO (Either SomeException a)
try' :: IO a -> IO (Either SomeException a)
try' = IO a -> IO (Either SomeException a)
forall e a. Exception e => IO a -> IO (Either e a)
try
#else
interruptibly _db io = io
#endif
exec :: Database -> Text -> IO ()
exec :: Database -> Text -> IO ()
exec db :: Database
db sql :: Text
sql =
Database -> Utf8 -> IO (Either (Error, Utf8) ())
Direct.exec Database
db (Text -> Utf8
toUtf8 Text
sql)
IO (Either (Error, Utf8) ())
-> (Either (Error, Utf8) () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Either (Error, Utf8) () -> IO ()
forall a. Text -> Either (Error, Utf8) a -> IO a
checkErrorMsg ("exec " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
sql)
execPrint :: Database -> Text -> IO ()
execPrint :: Database -> Text -> IO ()
execPrint !Database
db !Text
sql =
Database -> IO () -> IO ()
forall a. Database -> IO a -> IO a
interruptibly Database
db (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Database -> Text -> ExecCallback -> IO ()
execWithCallback Database
db Text
sql (ExecCallback -> IO ()) -> ExecCallback -> IO ()
forall a b. (a -> b) -> a -> b
$ \_count :: ColumnCount
_count _colnames :: [Text]
_colnames -> Text -> IO ()
T.putStrLn (Text -> IO ()) -> ([Maybe Text] -> Text) -> [Maybe Text] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe Text] -> Text
showValues
where
showValues :: [Maybe Text] -> Text
showValues = Text -> [Text] -> Text
T.intercalate "|" ([Text] -> Text)
-> ([Maybe Text] -> [Text]) -> [Maybe Text] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text -> Text) -> [Maybe Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe "")
execWithCallback :: Database -> Text -> ExecCallback -> IO ()
execWithCallback :: Database -> Text -> ExecCallback -> IO ()
execWithCallback db :: Database
db sql :: Text
sql cb :: ExecCallback
cb =
Database -> Utf8 -> ExecCallback -> IO (Either (Error, Utf8) ())
Direct.execWithCallback Database
db (Text -> Utf8
toUtf8 Text
sql) ExecCallback
cb'
IO (Either (Error, Utf8) ())
-> (Either (Error, Utf8) () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Either (Error, Utf8) () -> IO ()
forall a. Text -> Either (Error, Utf8) a -> IO a
checkErrorMsg ("execWithCallback " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
sql)
where
cb' :: ExecCallback
cb' count :: ColumnCount
count namesUtf8 :: [Utf8]
namesUtf8 =
let names :: [Text]
names = (Utf8 -> Text) -> [Utf8] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Utf8 -> Text
fromUtf8'' [Utf8]
namesUtf8
{-# NOINLINE names #-}
in ExecCallback
cb ColumnCount
count [Text]
names ([Maybe Text] -> IO ())
-> ([Maybe Utf8] -> [Maybe Text]) -> [Maybe Utf8] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Utf8 -> Maybe Text) -> [Maybe Utf8] -> [Maybe Text]
forall a b. (a -> b) -> [a] -> [b]
map ((Utf8 -> Text) -> Maybe Utf8 -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Utf8 -> Text
fromUtf8'')
fromUtf8'' :: Utf8 -> Text
fromUtf8'' = String -> Utf8 -> Text
fromUtf8' "Database.SQLite3.execWithCallback: Invalid UTF-8"
type ExecCallback
= ColumnCount
-> [Text]
-> [Maybe Text]
-> IO ()
prepare :: Database -> Text -> IO Statement
prepare :: Database -> Text -> IO Statement
prepare db :: Database
db sql :: Text
sql = Database -> Utf8 -> IO Statement
prepareUtf8 Database
db (Text -> Utf8
toUtf8 Text
sql)
prepareUtf8 :: Database -> Utf8 -> IO Statement
prepareUtf8 :: Database -> Utf8 -> IO Statement
prepareUtf8 db :: Database
db sql :: Utf8
sql = do
Maybe Statement
m <- Database -> Utf8 -> IO (Either Error (Maybe Statement))
Direct.prepare Database
db Utf8
sql
IO (Either Error (Maybe Statement))
-> (Either Error (Maybe Statement) -> IO (Maybe Statement))
-> IO (Maybe Statement)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource
-> Text -> Either Error (Maybe Statement) -> IO (Maybe Statement)
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("prepare " Text -> Utf8 -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Utf8
sql)
case Maybe Statement
m of
Nothing -> String -> IO Statement
forall (m :: * -> *) a. MonadFail m => String -> m a
fail "Direct.SQLite3.prepare: empty query string"
Just stmt :: Statement
stmt -> Statement -> IO Statement
forall (m :: * -> *) a. Monad m => a -> m a
return Statement
stmt
step :: Statement -> IO StepResult
step :: Statement -> IO StepResult
step statement :: Statement
statement =
Statement -> IO (Either Error StepResult)
Direct.step Statement
statement IO (Either Error StepResult)
-> (Either Error StepResult -> IO StepResult) -> IO StepResult
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error StepResult -> IO StepResult
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "step"
stepNoCB :: Statement -> IO StepResult
stepNoCB :: Statement -> IO StepResult
stepNoCB statement :: Statement
statement =
Statement -> IO (Either Error StepResult)
Direct.stepNoCB Statement
statement IO (Either Error StepResult)
-> (Either Error StepResult -> IO StepResult) -> IO StepResult
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error StepResult -> IO StepResult
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "stepNoCB"
reset :: Statement -> IO ()
reset :: Statement -> IO ()
reset statement :: Statement
statement = do
Either Error ()
_ <- Statement -> IO (Either Error ())
Direct.reset Statement
statement
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
finalize :: Statement -> IO ()
finalize :: Statement -> IO ()
finalize statement :: Statement
statement = do
Either Error ()
_ <- Statement -> IO (Either Error ())
Direct.finalize Statement
statement
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
bindParameterName :: Statement -> ParamIndex -> IO (Maybe Text)
bindParameterName :: Statement -> ParamIndex -> IO (Maybe Text)
bindParameterName stmt :: Statement
stmt idx :: ParamIndex
idx = do
Maybe Utf8
m <- Statement -> ParamIndex -> IO (Maybe Utf8)
Direct.bindParameterName Statement
stmt ParamIndex
idx
case Maybe Utf8
m of
Nothing -> Maybe Text -> IO (Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Text
forall a. Maybe a
Nothing
Just name :: Utf8
name -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> IO Text -> IO (Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Utf8 -> IO Text
fromUtf8 String
desc Utf8
name
where
desc :: String
desc = "Database.SQLite3.bindParameterName: Invalid UTF-8"
columnName :: Statement -> ColumnIndex -> IO (Maybe Text)
columnName :: Statement -> ColumnCount -> IO (Maybe Text)
columnName stmt :: Statement
stmt idx :: ColumnCount
idx = do
Maybe Utf8
m <- Statement -> ColumnCount -> IO (Maybe Utf8)
Direct.columnName Statement
stmt ColumnCount
idx
case Maybe Utf8
m of
Just name :: Utf8
name -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> IO Text -> IO (Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Utf8 -> IO Text
fromUtf8 String
desc Utf8
name
Nothing -> do
ColumnCount
count <- Statement -> IO ColumnCount
Direct.columnCount Statement
stmt
if ColumnCount
idx ColumnCount -> ColumnCount -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 Bool -> Bool -> Bool
&& ColumnCount
idx ColumnCount -> ColumnCount -> Bool
forall a. Ord a => a -> a -> Bool
< ColumnCount
count
then SQLError -> IO (Maybe Text)
forall e a. Exception e => e -> IO a
throwIO SQLError
outOfMemory
else Maybe Text -> IO (Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Text
forall a. Maybe a
Nothing
where
desc :: String
desc = "Database.SQLite3.columnName: Invalid UTF-8"
outOfMemory :: SQLError
outOfMemory = $WSQLError :: Error -> Text -> Text -> SQLError
SQLError
{ sqlError :: Error
sqlError = Error
ErrorNoMemory
, sqlErrorDetails :: Text
sqlErrorDetails = "out of memory (sqlite3_column_name returned NULL)"
, sqlErrorContext :: Text
sqlErrorContext = "column name"
}
bindBlob :: Statement -> ParamIndex -> ByteString -> IO ()
bindBlob :: Statement -> ParamIndex -> ByteString -> IO ()
bindBlob statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex byteString :: ByteString
byteString =
Statement -> ParamIndex -> ByteString -> IO (Either Error ())
Direct.bindBlob Statement
statement ParamIndex
parameterIndex ByteString
byteString
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind blob"
bindZeroBlob :: Statement -> ParamIndex -> Int -> IO ()
bindZeroBlob :: Statement -> ParamIndex -> Int -> IO ()
bindZeroBlob statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex len :: Int
len =
Statement -> ParamIndex -> Int -> IO (Either Error ())
Direct.bindZeroBlob Statement
statement ParamIndex
parameterIndex Int
len
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind zeroblob"
bindDouble :: Statement -> ParamIndex -> Double -> IO ()
bindDouble :: Statement -> ParamIndex -> Double -> IO ()
bindDouble statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex datum :: Double
datum =
Statement -> ParamIndex -> Double -> IO (Either Error ())
Direct.bindDouble Statement
statement ParamIndex
parameterIndex Double
datum
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind double"
bindInt :: Statement -> ParamIndex -> Int -> IO ()
bindInt :: Statement -> ParamIndex -> Int -> IO ()
bindInt statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex datum :: Int
datum =
Statement -> ParamIndex -> Int64 -> IO (Either Error ())
Direct.bindInt64 Statement
statement
ParamIndex
parameterIndex
(Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
datum)
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind int"
bindInt64 :: Statement -> ParamIndex -> Int64 -> IO ()
bindInt64 :: Statement -> ParamIndex -> Int64 -> IO ()
bindInt64 statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex datum :: Int64
datum =
Statement -> ParamIndex -> Int64 -> IO (Either Error ())
Direct.bindInt64 Statement
statement ParamIndex
parameterIndex Int64
datum
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind int64"
bindNull :: Statement -> ParamIndex -> IO ()
bindNull :: Statement -> ParamIndex -> IO ()
bindNull statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex =
Statement -> ParamIndex -> IO (Either Error ())
Direct.bindNull Statement
statement ParamIndex
parameterIndex
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind null"
bindText :: Statement -> ParamIndex -> Text -> IO ()
bindText :: Statement -> ParamIndex -> Text -> IO ()
bindText statement :: Statement
statement parameterIndex :: ParamIndex
parameterIndex text :: Text
text =
Statement -> ParamIndex -> Utf8 -> IO (Either Error ())
Direct.bindText Statement
statement ParamIndex
parameterIndex (Text -> Utf8
toUtf8 Text
text)
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Statement -> DetailSource
DetailStatement Statement
statement) "bind text"
bindSQLData :: Statement -> ParamIndex -> SQLData -> IO ()
bindSQLData :: Statement -> ParamIndex -> SQLData -> IO ()
bindSQLData statement :: Statement
statement idx :: ParamIndex
idx datum :: SQLData
datum =
case SQLData
datum of
SQLInteger v :: Int64
v -> Statement -> ParamIndex -> Int64 -> IO ()
bindInt64 Statement
statement ParamIndex
idx Int64
v
SQLFloat v :: Double
v -> Statement -> ParamIndex -> Double -> IO ()
bindDouble Statement
statement ParamIndex
idx Double
v
SQLText v :: Text
v -> Statement -> ParamIndex -> Text -> IO ()
bindText Statement
statement ParamIndex
idx Text
v
SQLBlob v :: ByteString
v -> Statement -> ParamIndex -> ByteString -> IO ()
bindBlob Statement
statement ParamIndex
idx ByteString
v
SQLNull -> Statement -> ParamIndex -> IO ()
bindNull Statement
statement ParamIndex
idx
bind :: Statement -> [SQLData] -> IO ()
bind :: Statement -> [SQLData] -> IO ()
bind statement :: Statement
statement sqlData :: [SQLData]
sqlData = do
ParamIndex nParams :: Int
nParams <- Statement -> IO ParamIndex
bindParameterCount Statement
statement
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
nParams Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [SQLData] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SQLData]
sqlData) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail ("mismatched parameter count for bind. Prepared statement "String -> ShowS
forall a. [a] -> [a] -> [a]
++
"needs "String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
nParams String -> ShowS
forall a. [a] -> [a] -> [a]
++ ", " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([SQLData] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SQLData]
sqlData) String -> ShowS
forall a. [a] -> [a] -> [a]
++" given")
(ParamIndex -> SQLData -> IO ())
-> [ParamIndex] -> [SQLData] -> IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ (Statement -> ParamIndex -> SQLData -> IO ()
bindSQLData Statement
statement) [1..] [SQLData]
sqlData
bindNamed :: Statement -> [(T.Text, SQLData)] -> IO ()
bindNamed :: Statement -> [(Text, SQLData)] -> IO ()
bindNamed statement :: Statement
statement params :: [(Text, SQLData)]
params = do
ParamIndex nParams :: Int
nParams <- Statement -> IO ParamIndex
bindParameterCount Statement
statement
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
nParams Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [(Text, SQLData)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Text, SQLData)]
params) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail ("mismatched parameter count for bind. Prepared statement "String -> ShowS
forall a. [a] -> [a] -> [a]
++
"needs "String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
nParams String -> ShowS
forall a. [a] -> [a] -> [a]
++ ", " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([(Text, SQLData)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Text, SQLData)]
params) String -> ShowS
forall a. [a] -> [a] -> [a]
++" given")
((Text, SQLData) -> IO ()) -> [(Text, SQLData)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Text, SQLData) -> IO ()
bindIdx [(Text, SQLData)]
params
where
bindIdx :: (Text, SQLData) -> IO ()
bindIdx (name :: Text
name, val :: SQLData
val) = do
Maybe ParamIndex
idx <- Statement -> Utf8 -> IO (Maybe ParamIndex)
Direct.bindParameterIndex Statement
statement (Utf8 -> IO (Maybe ParamIndex)) -> Utf8 -> IO (Maybe ParamIndex)
forall a b. (a -> b) -> a -> b
$ Text -> Utf8
toUtf8 Text
name
case Maybe ParamIndex
idx of
Just i :: ParamIndex
i ->
Statement -> ParamIndex -> SQLData -> IO ()
bindSQLData Statement
statement ParamIndex
i SQLData
val
Nothing ->
String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail ("unknown named parameter "String -> ShowS
forall a. [a] -> [a] -> [a]
++Text -> String
forall a. Show a => a -> String
show Text
name)
columnText :: Statement -> ColumnIndex -> IO Text
columnText :: Statement -> ColumnCount -> IO Text
columnText statement :: Statement
statement columnIndex :: ColumnCount
columnIndex =
Statement -> ColumnCount -> IO Utf8
Direct.columnText Statement
statement ColumnCount
columnIndex
IO Utf8 -> (Utf8 -> IO Text) -> IO Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Utf8 -> IO Text
fromUtf8 "Database.SQLite3.columnText: Invalid UTF-8"
column :: Statement -> ColumnIndex -> IO SQLData
column :: Statement -> ColumnCount -> IO SQLData
column statement :: Statement
statement idx :: ColumnCount
idx = do
ColumnType
theType <- Statement -> ColumnCount -> IO ColumnType
columnType Statement
statement ColumnCount
idx
ColumnType -> Statement -> ColumnCount -> IO SQLData
typedColumn ColumnType
theType Statement
statement ColumnCount
idx
columns :: Statement -> IO [SQLData]
columns :: Statement -> IO [SQLData]
columns statement :: Statement
statement = do
ColumnCount
count <- Statement -> IO ColumnCount
columnCount Statement
statement
(ColumnCount -> IO SQLData) -> [ColumnCount] -> IO [SQLData]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Statement -> ColumnCount -> IO SQLData
column Statement
statement) [0..ColumnCount
countColumnCount -> ColumnCount -> ColumnCount
forall a. Num a => a -> a -> a
-1]
typedColumn :: ColumnType -> Statement -> ColumnIndex -> IO SQLData
typedColumn :: ColumnType -> Statement -> ColumnCount -> IO SQLData
typedColumn theType :: ColumnType
theType statement :: Statement
statement idx :: ColumnCount
idx = case ColumnType
theType of
IntegerColumn -> Int64 -> SQLData
SQLInteger (Int64 -> SQLData) -> IO Int64 -> IO SQLData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Statement -> ColumnCount -> IO Int64
columnInt64 Statement
statement ColumnCount
idx
FloatColumn -> Double -> SQLData
SQLFloat (Double -> SQLData) -> IO Double -> IO SQLData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Statement -> ColumnCount -> IO Double
columnDouble Statement
statement ColumnCount
idx
TextColumn -> Text -> SQLData
SQLText (Text -> SQLData) -> IO Text -> IO SQLData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Statement -> ColumnCount -> IO Text
columnText Statement
statement ColumnCount
idx
BlobColumn -> ByteString -> SQLData
SQLBlob (ByteString -> SQLData) -> IO ByteString -> IO SQLData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Statement -> ColumnCount -> IO ByteString
columnBlob Statement
statement ColumnCount
idx
NullColumn -> SQLData -> IO SQLData
forall (m :: * -> *) a. Monad m => a -> m a
return SQLData
SQLNull
typedColumns :: Statement -> [Maybe ColumnType] -> IO [SQLData]
typedColumns :: Statement -> [Maybe ColumnType] -> IO [SQLData]
typedColumns statement :: Statement
statement = (ColumnCount -> Maybe ColumnType -> IO SQLData)
-> [ColumnCount] -> [Maybe ColumnType] -> IO [SQLData]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM ColumnCount -> Maybe ColumnType -> IO SQLData
f [0..] where
f :: ColumnCount -> Maybe ColumnType -> IO SQLData
f idx :: ColumnCount
idx theType :: Maybe ColumnType
theType = case Maybe ColumnType
theType of
Nothing -> Statement -> ColumnCount -> IO SQLData
column Statement
statement ColumnCount
idx
Just t :: ColumnType
t -> ColumnType -> Statement -> ColumnCount -> IO SQLData
typedColumn ColumnType
t Statement
statement ColumnCount
idx
createFunction
:: Database
-> Text
-> Maybe ArgCount
-> Bool
-> (FuncContext -> FuncArgs -> IO ())
-> IO ()
createFunction :: Database
-> Text
-> Maybe ArgCount
-> Bool
-> (FuncContext -> FuncArgs -> IO ())
-> IO ()
createFunction db :: Database
db name :: Text
name nArgs :: Maybe ArgCount
nArgs isDet :: Bool
isDet fun :: FuncContext -> FuncArgs -> IO ()
fun =
Database
-> Utf8
-> Maybe ArgCount
-> Bool
-> (FuncContext -> FuncArgs -> IO ())
-> IO (Either Error ())
Direct.createFunction Database
db (Text -> Utf8
toUtf8 Text
name) Maybe ArgCount
nArgs Bool
isDet FuncContext -> FuncArgs -> IO ()
fun
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("createFunction " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
name)
createAggregate
:: Database
-> Text
-> Maybe ArgCount
-> a
-> (FuncContext -> FuncArgs -> a -> IO a)
-> (FuncContext -> a -> IO ())
-> IO ()
createAggregate :: Database
-> Text
-> Maybe ArgCount
-> a
-> (FuncContext -> FuncArgs -> a -> IO a)
-> (FuncContext -> a -> IO ())
-> IO ()
createAggregate db :: Database
db name :: Text
name nArgs :: Maybe ArgCount
nArgs initSt :: a
initSt xStep :: FuncContext -> FuncArgs -> a -> IO a
xStep xFinal :: FuncContext -> a -> IO ()
xFinal =
Database
-> Utf8
-> Maybe ArgCount
-> a
-> (FuncContext -> FuncArgs -> a -> IO a)
-> (FuncContext -> a -> IO ())
-> IO (Either Error ())
forall a.
Database
-> Utf8
-> Maybe ArgCount
-> a
-> (FuncContext -> FuncArgs -> a -> IO a)
-> (FuncContext -> a -> IO ())
-> IO (Either Error ())
Direct.createAggregate Database
db (Text -> Utf8
toUtf8 Text
name) Maybe ArgCount
nArgs a
initSt FuncContext -> FuncArgs -> a -> IO a
xStep FuncContext -> a -> IO ()
xFinal
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("createAggregate " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
name)
deleteFunction :: Database -> Text -> Maybe ArgCount -> IO ()
deleteFunction :: Database -> Text -> Maybe ArgCount -> IO ()
deleteFunction db :: Database
db name :: Text
name nArgs :: Maybe ArgCount
nArgs =
Database -> Utf8 -> Maybe ArgCount -> IO (Either Error ())
Direct.deleteFunction Database
db (Text -> Utf8
toUtf8 Text
name) Maybe ArgCount
nArgs
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("deleteFunction " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
name)
funcArgText :: FuncArgs -> ArgIndex -> IO Text
funcArgText :: FuncArgs -> ArgCount -> IO Text
funcArgText args :: FuncArgs
args argIndex :: ArgCount
argIndex =
FuncArgs -> ArgCount -> IO Utf8
Direct.funcArgText FuncArgs
args ArgCount
argIndex
IO Utf8 -> (Utf8 -> IO Text) -> IO Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Utf8 -> IO Text
fromUtf8 "Database.SQLite3.funcArgText: Invalid UTF-8"
funcResultSQLData :: FuncContext -> SQLData -> IO ()
funcResultSQLData :: FuncContext -> SQLData -> IO ()
funcResultSQLData ctx :: FuncContext
ctx datum :: SQLData
datum =
case SQLData
datum of
SQLInteger v :: Int64
v -> FuncContext -> Int64 -> IO ()
funcResultInt64 FuncContext
ctx Int64
v
SQLFloat v :: Double
v -> FuncContext -> Double -> IO ()
funcResultDouble FuncContext
ctx Double
v
SQLText v :: Text
v -> FuncContext -> Text -> IO ()
funcResultText FuncContext
ctx Text
v
SQLBlob v :: ByteString
v -> FuncContext -> ByteString -> IO ()
funcResultBlob FuncContext
ctx ByteString
v
SQLNull -> FuncContext -> IO ()
funcResultNull FuncContext
ctx
funcResultText :: FuncContext -> Text -> IO ()
funcResultText :: FuncContext -> Text -> IO ()
funcResultText ctx :: FuncContext
ctx value :: Text
value =
FuncContext -> Utf8 -> IO ()
Direct.funcResultText FuncContext
ctx (Text -> Utf8
toUtf8 Text
value)
createCollation
:: Database
-> Text
-> (Text -> Text -> Ordering)
-> IO ()
createCollation :: Database -> Text -> (Text -> Text -> Ordering) -> IO ()
createCollation db :: Database
db name :: Text
name cmp :: Text -> Text -> Ordering
cmp =
Database
-> Utf8 -> (Utf8 -> Utf8 -> Ordering) -> IO (Either Error ())
Direct.createCollation Database
db (Text -> Utf8
toUtf8 Text
name) Utf8 -> Utf8 -> Ordering
cmp'
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("createCollation " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
name)
where
cmp' :: Utf8 -> Utf8 -> Ordering
cmp' (Utf8 s1 :: ByteString
s1) (Utf8 s2 :: ByteString
s2) = Text -> Text -> Ordering
cmp (ByteString -> Text
fromUtf8'' ByteString
s1) (ByteString -> Text
fromUtf8'' ByteString
s2)
fromUtf8'' :: ByteString -> Text
fromUtf8'' = OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode
deleteCollation :: Database -> Text -> IO ()
deleteCollation :: Database -> Text -> IO ()
deleteCollation db :: Database
db name :: Text
name =
Database -> Utf8 -> IO (Either Error ())
Direct.deleteCollation Database
db (Text -> Utf8
toUtf8 Text
name)
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) ("deleteCollation " Text -> Text -> Text
forall a. Show a => Text -> a -> Text
`appendShow` Text
name)
blobOpen
:: Database
-> Text
-> Text
-> Text
-> Int64
-> Bool
-> IO Blob
blobOpen :: Database -> Text -> Text -> Text -> Int64 -> Bool -> IO Blob
blobOpen db :: Database
db zDb :: Text
zDb zTable :: Text
zTable zColumn :: Text
zColumn rowid :: Int64
rowid rw :: Bool
rw =
Database
-> Utf8 -> Utf8 -> Utf8 -> Int64 -> Bool -> IO (Either Error Blob)
Direct.blobOpen Database
db (Text -> Utf8
toUtf8 Text
zDb) (Text -> Utf8
toUtf8 Text
zTable) (Text -> Utf8
toUtf8 Text
zColumn) Int64
rowid Bool
rw
IO (Either Error Blob) -> (Either Error Blob -> IO Blob) -> IO Blob
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error Blob -> IO Blob
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobOpen"
blobClose :: Blob -> IO ()
blobClose :: Blob -> IO ()
blobClose blob :: Blob
blob@(Direct.Blob db :: Database
db _) =
Blob -> IO (Either Error ())
Direct.blobClose Blob
blob
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobClose"
blobReopen
:: Blob
-> Int64
-> IO ()
blobReopen :: Blob -> Int64 -> IO ()
blobReopen blob :: Blob
blob@(Direct.Blob db :: Database
db _) rowid :: Int64
rowid =
Blob -> Int64 -> IO (Either Error ())
Direct.blobReopen Blob
blob Int64
rowid
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobReopen"
blobRead
:: Blob
-> Int
-> Int
-> IO ByteString
blobRead :: Blob -> Int -> Int -> IO ByteString
blobRead blob :: Blob
blob@(Direct.Blob db :: Database
db _) len :: Int
len offset :: Int
offset =
Blob -> Int -> Int -> IO (Either Error ByteString)
Direct.blobRead Blob
blob Int
len Int
offset
IO (Either Error ByteString)
-> (Either Error ByteString -> IO ByteString) -> IO ByteString
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error ByteString -> IO ByteString
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobRead"
blobReadBuf :: Blob -> Ptr a -> Int -> Int -> IO ()
blobReadBuf :: Blob -> Ptr a -> Int -> Int -> IO ()
blobReadBuf blob :: Blob
blob@(Direct.Blob db :: Database
db _) buf :: Ptr a
buf len :: Int
len offset :: Int
offset =
Blob -> Ptr a -> Int -> Int -> IO (Either Error ())
forall a. Blob -> Ptr a -> Int -> Int -> IO (Either Error ())
Direct.blobReadBuf Blob
blob Ptr a
buf Int
len Int
offset
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobReadBuf"
blobWrite
:: Blob
-> ByteString
-> Int
-> IO ()
blobWrite :: Blob -> ByteString -> Int -> IO ()
blobWrite blob :: Blob
blob@(Direct.Blob db :: Database
db _) bs :: ByteString
bs offset :: Int
offset =
Blob -> ByteString -> Int -> IO (Either Error ())
Direct.blobWrite Blob
blob ByteString
bs Int
offset
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
db) "blobWrite"
backupInit
:: Database
-> Text
-> Database
-> Text
-> IO Backup
backupInit :: Database -> Text -> Database -> Text -> IO Backup
backupInit dstDb :: Database
dstDb dstName :: Text
dstName srcDb :: Database
srcDb srcName :: Text
srcName =
Database -> Utf8 -> Database -> Utf8 -> IO (Either Error Backup)
Direct.backupInit Database
dstDb (Text -> Utf8
toUtf8 Text
dstName) Database
srcDb (Text -> Utf8
toUtf8 Text
srcName)
IO (Either Error Backup)
-> (Either Error Backup -> IO Backup) -> IO Backup
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error Backup -> IO Backup
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
dstDb) "backupInit"
backupFinish :: Backup -> IO ()
backupFinish :: Backup -> IO ()
backupFinish backup :: Backup
backup@(Direct.Backup dstDb :: Database
dstDb _) =
Backup -> IO (Either Error ())
Direct.backupFinish Backup
backup
IO (Either Error ()) -> (Either Error () -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource -> Text -> Either Error () -> IO ()
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Database -> DetailSource
DetailDatabase Database
dstDb) "backupFinish"
backupStep :: Backup -> Int -> IO BackupStepResult
backupStep :: Backup -> Int -> IO BackupStepResult
backupStep backup :: Backup
backup pages :: Int
pages =
Backup -> Int -> IO (Either Error BackupStepResult)
Direct.backupStep Backup
backup Int
pages
IO (Either Error BackupStepResult)
-> (Either Error BackupStepResult -> IO BackupStepResult)
-> IO BackupStepResult
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DetailSource
-> Text -> Either Error BackupStepResult -> IO BackupStepResult
forall a. DetailSource -> Text -> Either Error a -> IO a
checkError (Utf8 -> DetailSource
DetailMessage "failed") "backupStep"