    {-# LINE 1 "Database/HDBC/Sqlite3/Statement.hsc" #-}
    -- -*- mode: haskell; -*-
    {-# CFILES hdbc-sqlite3-helper.c #-}
    -- Above line for Hugs
    module Database.HDBC.Sqlite3.Statement where
    import Database.HDBC.Types
    import Database.HDBC
    import Database.HDBC.Sqlite3.Types
    import Database.HDBC.Sqlite3.Utils
    import Foreign.C.Types
    import Foreign.ForeignPtr
    import Foreign.Ptr
    import Control.Concurrent.MVar
    import Foreign.C.String
    import Foreign.Marshal
    import Foreign.Storable
    import Control.Monad
    import qualified Data.ByteString as B
    import qualified Data.ByteString.UTF8 as BUTF8
    import Data.List
    import Control.Exception
    import Database.HDBC.DriverUtils

    {- One annoying thing about Sqlite is that a disconnect operation will actually
    fail if there are any active statements.  This is highly annoying, and makes
    for some somewhat complex algorithms. -}

    data StoState = Empty           -- ^ Not initialized or last execute\/fetchrow had no results
                  | Prepared Stmt   -- ^ Prepared but not executed
                  | Executed Stmt   -- ^ Executed and more rows are expected
                  | Exhausted Stmt  -- ^ Executed and at end of rows

    instance Show StoState where
        show :: StoState -> String
    show StoState
    Empty = String
    "Empty"
        show (Prepared Stmt
    _) = String
    "Prepared"
        show (Executed Stmt
    _) = String
    "Executed"
        show (Exhausted Stmt
    _) = String
    "Exhausted"

    data SState = SState {SState -> Sqlite3
    dbo :: Sqlite3,
                          SState -> MVar StoState
    stomv :: MVar StoState,
                          SState -> String
    querys :: String,
                          SState -> MVar [String]
    colnamesmv :: MVar [String],
                          SState -> Bool
    autoFinish :: Bool}

    newSth :: Sqlite3 -> ChildList -> Bool -> String -> IO Statement
    newSth :: Sqlite3 -> ChildList -> Bool -> String -> IO Statement
    newSth Sqlite3
    indbo ChildList
    mchildren Bool
    autoFinish String
    str =
        do newstomv <- StoState -> IO (MVar StoState)
    forall a. a -> IO (MVar a)
    newMVar StoState
    Empty
           newcolnamesmv <- newMVar []
           let sstate = SState{dbo :: Sqlite3
    dbo = Sqlite3
    indbo,
                               stomv :: MVar StoState
    stomv = MVar StoState
    newstomv,
                               querys :: String
    querys = String
    str,
                               colnamesmv :: MVar [String]
    colnamesmv = MVar [String]
    newcolnamesmv,
                               autoFinish :: Bool
    autoFinish = Bool
    autoFinish}
           modifyMVar_ (stomv sstate) (\StoState
    _ -> (SState -> IO Stmt
    fprepare SState
    sstate IO Stmt -> (Stmt -> IO StoState) -> IO StoState
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= StoState -> IO StoState
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (StoState -> IO StoState)
    -> (Stmt -> StoState) -> Stmt -> IO StoState
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Stmt -> StoState
    Prepared))
           let retval =
                   Statement {execute :: [SqlValue] -> IO Integer
    execute = SState -> [SqlValue] -> IO Integer
    forall {b}. Num b => SState -> [SqlValue] -> IO b
    fexecute SState
    sstate,
                               executeRaw :: IO ()
    executeRaw = Sqlite3 -> String -> IO ()
    fexecuteRaw Sqlite3
    indbo String
    str,
                               executeMany :: [[SqlValue]] -> IO ()
    executeMany = SState -> [[SqlValue]] -> IO ()
    fexecutemany SState
    sstate,
                               finish :: IO ()
    finish = SState -> IO ()
    public_ffinish SState
    sstate,
                               fetchRow :: IO (Maybe [SqlValue])
    fetchRow = SState -> IO (Maybe [SqlValue])
    ffetchrow SState
    sstate,
                               originalQuery :: String
    originalQuery = String
    str,
                               getColumnNames :: IO [String]
    getColumnNames = MVar [String] -> IO [String]
    forall a. MVar a -> IO a
    readMVar (SState -> MVar [String]
    colnamesmv SState
    sstate),
                               describeResult :: IO [(String, SqlColDesc)]
    describeResult = String -> IO [(String, SqlColDesc)]
    forall a. String -> IO a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "Sqlite3 backend does not support describeResult"}
           addChild mchildren retval
           return retval

    {- The deal with adding the \0 below is in response to an apparent bug in
    sqlite3.  See debian bug #343736.

    This function assumes that any existing query in the state has already
    been terminated.  (FIXME: should check this at runtime.... never run fprepare
    unless state is Empty)
    -}
    fprepare :: SState -> IO Stmt
    fprepare :: SState -> IO Stmt
    fprepare SState
    sstate = Sqlite3 -> (Ptr CSqlite3 -> IO Stmt) -> IO Stmt
    forall b. Sqlite3 -> (Ptr CSqlite3 -> IO b) -> IO b
    withRawSqlite3 (SState -> Sqlite3
    dbo SState
    sstate)
      (\Ptr CSqlite3
    p -> ByteString -> (CStringLen -> IO Stmt) -> IO Stmt
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
    B.useAsCStringLen (String -> ByteString
    BUTF8.fromString ((SState -> String
    querys SState
    sstate) String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "\0"))
       (\(Ptr CChar
    cs, Int
    cslen) -> (Ptr (Ptr CStmt) -> IO Stmt) -> IO Stmt
    forall a b. Storable a => (Ptr a -> IO b) -> IO b
    alloca
        (\(Ptr (Ptr CStmt)
    newp::Ptr (Ptr CStmt)) ->
         (do res <- Ptr CSqlite3
    -> Ptr CChar
    -> CInt
    -> Ptr (Ptr CStmt)
    -> Ptr (Ptr (Ptr CChar))
    -> IO CInt
    sqlite3_prepare Ptr CSqlite3
    p Ptr CChar
    cs (Int -> CInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    cslen) Ptr (Ptr CStmt)
    newp Ptr (Ptr (Ptr CChar))
    forall a. Ptr a
    nullPtr
             checkError ("prepare " ++ (show cslen) ++ ": " ++ (querys sstate))
                        (dbo sstate) res
             newo <- peek newp
             newForeignPtr sqlite3_finalizeptr newo
         )
         )
       )
       )

    {- General algorithm: find out how many columns we have, check the type
    of each to see if it's NULL.  If it's not, fetch it as text and return that.

    Note that execute() will have already loaded up the first row -- and we
    do that each time.  so this function returns the row that is already in sqlite,
    then loads the next row. -}
    ffetchrow :: SState -> IO (Maybe [SqlValue])
    ffetchrow :: SState -> IO (Maybe [SqlValue])
    ffetchrow SState
    sstate = MVar StoState
    -> (StoState -> IO (StoState, Maybe [SqlValue]))
    -> IO (Maybe [SqlValue])
    forall a b. MVar a -> (a -> IO (a, b)) -> IO b
    modifyMVar (SState -> MVar StoState
    stomv SState
    sstate) StoState -> IO (StoState, Maybe [SqlValue])
    dofetchrow
        where dofetchrow :: StoState -> IO (StoState, Maybe [SqlValue])
    dofetchrow StoState
    Empty = (StoState, Maybe [SqlValue]) -> IO (StoState, Maybe [SqlValue])
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (StoState
    Empty, Maybe [SqlValue]
    forall a. Maybe a
    Nothing)
              dofetchrow (Prepared Stmt
    _) =
                  SqlError -> IO (StoState, Maybe [SqlValue])
    forall a. SqlError -> IO a
    throwSqlError (SqlError -> IO (StoState, Maybe [SqlValue]))
    -> SqlError -> IO (StoState, Maybe [SqlValue])
    forall a b. (a -> b) -> a -> b
    $ SqlError {seState :: String
    seState = String
    "HDBC Sqlite3 fetchrow",
                                       seNativeError :: Int
    seNativeError = (-Int
    1),
                                       seErrorMsg :: String
    seErrorMsg = String
    "Attempt to fetch row from Statement that has not been executed.  Query was: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ (SState -> String
    querys SState
    sstate)}
              dofetchrow (Executed Stmt
    sto) = Stmt
    -> (Ptr CStmt -> IO (StoState, Maybe [SqlValue]))
    -> IO (StoState, Maybe [SqlValue])
    forall b. Stmt -> (Ptr CStmt -> IO b) -> IO b
    withStmt Stmt
    sto (\Ptr CStmt
    p ->
                  do ccount <- Ptr CStmt -> IO CInt
    sqlite3_column_count Ptr CStmt
    p
                     -- fetch the data
                     res <- mapM (getCol p) [0..(ccount - 1)]
                     r <- fstep (dbo sstate) p
                     if r
                        then return (Executed sto, Just res)
                        else if (autoFinish sstate)
                                then do ffinish (dbo sstate) sto
                                        return (Empty, Just res)
                                else return (Exhausted sto, Just res)
                                                              )
              dofetchrow (Exhausted Stmt
    sto) = (StoState, Maybe [SqlValue]) -> IO (StoState, Maybe [SqlValue])
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stmt -> StoState
    Exhausted Stmt
    sto, Maybe [SqlValue]
    forall a. Maybe a
    Nothing)

              getCol :: Ptr CStmt -> CInt -> IO SqlValue
    getCol Ptr CStmt
    p CInt
    icol =
                 do t <- Ptr CStmt -> CInt -> IO CInt
    sqlite3_column_type Ptr CStmt
    p CInt
    icol
                    if t == 5
    {-# LINE 121 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                       then return SqlNull
                       else do text <- sqlite3_column_text p icol
                               len <- sqlite3_column_bytes p icol
                               s <- B.packCStringLen (text, fromIntegral len)
                               case t of
                                 CInt
    1 -> SqlValue -> IO SqlValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SqlValue -> IO SqlValue) -> SqlValue -> IO SqlValue
    forall a b. (a -> b) -> a -> b
    $ Int64 -> SqlValue
    SqlInt64 (String -> Int64
    forall a. Read a => String -> a
    read (String -> Int64) -> String -> Int64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> String
    BUTF8.toString ByteString
    s)
    {-# LINE 127 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                                 CInt
    2   -> SqlValue -> IO SqlValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SqlValue -> IO SqlValue) -> SqlValue -> IO SqlValue
    forall a b. (a -> b) -> a -> b
    $ Double -> SqlValue
    SqlDouble (String -> Double
    forall a. Read a => String -> a
    read (String -> Double) -> String -> Double
    forall a b. (a -> b) -> a -> b
    $ ByteString -> String
    BUTF8.toString ByteString
    s)
    {-# LINE 128 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                                 CInt
    4    -> SqlValue -> IO SqlValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SqlValue -> IO SqlValue) -> SqlValue -> IO SqlValue
    forall a b. (a -> b) -> a -> b
    $ ByteString -> SqlValue
    SqlByteString ByteString
    s
    {-# LINE 129 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                                 CInt
    3    -> SqlValue -> IO SqlValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SqlValue -> IO SqlValue) -> SqlValue -> IO SqlValue
    forall a b. (a -> b) -> a -> b
    $ ByteString -> SqlValue
    SqlByteString ByteString
    s
    {-# LINE 130 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                                 CInt
    _                       -> SqlValue -> IO SqlValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SqlValue -> IO SqlValue) -> SqlValue -> IO SqlValue
    forall a b. (a -> b) -> a -> b
    $ ByteString -> SqlValue
    SqlByteString ByteString
    s

    fstep :: Sqlite3 -> Ptr CStmt -> IO Bool
    fstep :: Sqlite3 -> Ptr CStmt -> IO Bool
    fstep Sqlite3
    dbo Ptr CStmt
    p =
        do r <- Ptr CStmt -> IO CInt
    sqlite3_step Ptr CStmt
    p
           case r of
             CInt
    100 -> Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    True
    {-# LINE 137 "Database/HDBC/Sqlite3/Statement.hsc" #-}
             CInt
    101 -> Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
    {-# LINE 138 "Database/HDBC/Sqlite3/Statement.hsc" #-}
             CInt
    1 -> String -> Sqlite3 -> CInt -> IO ()
    checkError String
    "step" Sqlite3
    dbo CInt
    1
    {-# LINE 139 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                                       IO () -> IO Bool -> IO Bool
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (SqlError -> IO Bool
    forall a. SqlError -> IO a
    throwSqlError (SqlError -> IO Bool) -> SqlError -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ SqlError
                                              {seState :: String
    seState = String
    "",
                                               seNativeError :: Int
    seNativeError = Int
    0,
                                               seErrorMsg :: String
    seErrorMsg = String
    "In HDBC step, internal processing error (got SQLITE_ERROR with no error)"})
             CInt
    x -> String -> Sqlite3 -> CInt -> IO ()
    checkError String
    "step" Sqlite3
    dbo CInt
    x
                  IO () -> IO Bool -> IO Bool
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (SqlError -> IO Bool
    forall a. SqlError -> IO a
    throwSqlError (SqlError -> IO Bool) -> SqlError -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ SqlError
                                    {seState :: String
    seState = String
    "",
                                     seNativeError :: Int
    seNativeError = CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral CInt
    x,
                                     seErrorMsg :: String
    seErrorMsg = String
    "In HDBC step, internal processing error (got error code with no error)"})

    fexecute :: SState -> [SqlValue] -> IO b
    fexecute SState
    sstate [SqlValue]
    args = MVar StoState -> (StoState -> IO (StoState, b)) -> IO b
    forall a b. MVar a -> (a -> IO (a, b)) -> IO b
    modifyMVar (SState -> MVar StoState
    stomv SState
    sstate) StoState -> IO (StoState, b)
    forall {b}. Num b => StoState -> IO (StoState, b)
    doexecute
        where doexecute :: StoState -> IO (StoState, b)
    doexecute (Executed Stmt
    sto) = StoState -> IO (StoState, b)
    doexecute (Stmt -> StoState
    Prepared Stmt
    sto)
              doexecute (Exhausted Stmt
    sto) = StoState -> IO (StoState, b)
    doexecute (Stmt -> StoState
    Prepared Stmt
    sto)
              doexecute StoState
    Empty =     -- already cleaned up from last time
                  do sto <- SState -> IO Stmt
    fprepare SState
    sstate
                     doexecute (Prepared sto)
              doexecute (Prepared Stmt
    sto) = Stmt -> (Ptr CStmt -> IO (StoState, b)) -> IO (StoState, b)
    forall b. Stmt -> (Ptr CStmt -> IO b) -> IO b
    withStmt Stmt
    sto (\Ptr CStmt
    p ->
                  do c <- Ptr CStmt -> IO CInt
    sqlite3_bind_parameter_count Ptr CStmt
    p
                     when (c /= genericLength args)
                       (throwSqlError $ SqlError {seState = "",
                                             seNativeError = (-1),
                                             seErrorMsg = "In HDBC execute, received " ++ (show args) ++ " but expected " ++ (show c) ++ " args."})
                     sqlite3_reset p >>= checkError "execute (reset)" (dbo sstate)
                     zipWithM_ (bindArgs p) [1..c] args

                     {- Logic for handling counts of changes: look at the total
                        changes before and after the query.  If they differ,
                        then look at the local changes.  (The local change counter
                        appears to not be updated unless really running a query
                        that makes a change, according to the docs.)

                        This is OK thread-wise because SQLite doesn't support
                        using a given dbh in more than one thread anyway. -}
                     origtc <- withSqlite3 (dbo sstate) sqlite3_total_changes
                     r <- fstep (dbo sstate) p
                     newtc <- withSqlite3 (dbo sstate) sqlite3_total_changes
                     changes <- if origtc == newtc
                                   then return 0
                                   else withSqlite3 (dbo sstate) sqlite3_changes
                     fgetcolnames p >>= swapMVar (colnamesmv sstate)
                     if r
                        then return (Executed sto, fromIntegral changes)
                        else if (autoFinish sstate)
                                then do ffinish (dbo sstate) sto
                                        return (Empty, fromIntegral changes)
                                else return (Exhausted sto, fromIntegral changes)
                                                            )
              bindArgs :: Ptr CStmt -> CInt -> SqlValue -> IO ()
    bindArgs Ptr CStmt
    p CInt
    i SqlValue
    SqlNull =
                  Ptr CStmt -> CInt -> IO CInt
    sqlite3_bind_null Ptr CStmt
    p CInt
    i IO CInt -> (CInt -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
                    String -> Sqlite3 -> CInt -> IO ()
    checkError (String
    "execute (binding NULL column " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ (CInt -> String
    forall a. Show a => a -> String
    show CInt
    i) String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    ")")
                               (SState -> Sqlite3
    dbo SState
    sstate)
              bindArgs Ptr CStmt
    p CInt
    i (SqlByteString ByteString
    bs) =
                  ByteString -> (CStringLen -> IO ()) -> IO ()
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
    B.useAsCStringLen ByteString
    bs (Ptr CStmt -> CInt -> CStringLen -> IO ()
    forall {a}.
    Integral a =>
    Ptr CStmt -> CInt -> (Ptr CChar, a) -> IO ()
    bindCStringArgs Ptr CStmt
    p CInt
    i)
              bindArgs Ptr CStmt
    p CInt
    i SqlValue
    arg = Ptr CStmt -> CInt -> SqlValue -> IO ()
    bindArgs Ptr CStmt
    p CInt
    i (ByteString -> SqlValue
    SqlByteString (SqlValue -> ByteString
    forall a. Convertible SqlValue a => SqlValue -> a
    fromSql SqlValue
    arg))

              bindCStringArgs :: Ptr CStmt -> CInt -> (Ptr CChar, a) -> IO ()
    bindCStringArgs Ptr CStmt
    p CInt
    i (Ptr CChar
    cs, a
    len) =
                  do r <- Ptr CStmt -> CInt -> Ptr CChar -> CInt -> IO CInt
    sqlite3_bind_text2 Ptr CStmt
    p CInt
    i Ptr CChar
    cs (a -> CInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    len)
                     checkError ("execute (binding column " ++
                                 (show i) ++ ")") (dbo sstate) r

    fexecuteRaw :: Sqlite3 -> String -> IO ()
    fexecuteRaw :: Sqlite3 -> String -> IO ()
    fexecuteRaw Sqlite3
    dbo String
    query =
        Sqlite3 -> (Ptr CSqlite3 -> IO ()) -> IO ()
    forall b. Sqlite3 -> (Ptr CSqlite3 -> IO b) -> IO b
    withSqlite3 Sqlite3
    dbo
          (\Ptr CSqlite3
    p -> ByteString -> (CStringLen -> IO ()) -> IO ()
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
    B.useAsCStringLen (String -> ByteString
    BUTF8.fromString (String
    query String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "\0"))
           (\(Ptr CChar
    cs, Int
    cslen) -> do
              result <- Ptr CSqlite3
    -> Ptr CChar
    -> FunPtr (Ptr () -> CInt -> Ptr (Ptr CChar) -> Ptr (Ptr CChar))
    -> Ptr ()
    -> Ptr (Ptr CChar)
    -> IO CInt
    sqlite3_exec Ptr CSqlite3
    p Ptr CChar
    cs FunPtr (Ptr () -> CInt -> Ptr (Ptr CChar) -> Ptr (Ptr CChar))
    forall a. FunPtr a
    nullFunPtr Ptr ()
    forall a. Ptr a
    nullPtr Ptr (Ptr CChar)
    forall a. Ptr a
    nullPtr
              case result of
                CInt
    0 -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    {-# LINE 207 "Database/HDBC/Sqlite3/Statement.hsc" #-}
                CInt
    s -> do
                  String -> Sqlite3 -> CInt -> IO ()
    checkError String
    "exec" Sqlite3
    dbo CInt
    s
                  SqlError -> IO ()
    forall a. SqlError -> IO a
    throwSqlError (SqlError -> IO ()) -> SqlError -> IO ()
    forall a b. (a -> b) -> a -> b
    $ SqlError
                     {seState :: String
    seState = String
    "",
                      seNativeError :: Int
    seNativeError = CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral CInt
    s,
                      seErrorMsg :: String
    seErrorMsg = String
    "In sqlite3_exec, internal error"}
           )
          )

    fgetcolnames :: Ptr CStmt -> IO [String]
    fgetcolnames Ptr CStmt
    csth =
            do count <- Ptr CStmt -> IO CInt
    sqlite3_column_count Ptr CStmt
    csth
               mapM (getCol csth) [0..(count -1)]
        where getCol :: Ptr CStmt -> CInt -> IO String
    getCol Ptr CStmt
    csth CInt
    i =
                  do cstr <- Ptr CStmt -> CInt -> IO (Ptr CChar)
    sqlite3_column_name Ptr CStmt
    csth CInt
    i
                     bs <- B.packCString cstr
                     return (BUTF8.toString bs)

    fexecutemany :: SState -> [[SqlValue]] -> IO ()
    fexecutemany SState
    _ [] = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    fexecutemany SState
    sstate ([SqlValue]
    args:[]) =
        do SState -> [SqlValue] -> IO Integer
    forall {b}. Num b => SState -> [SqlValue] -> IO b
    fexecute SState
    sstate [SqlValue]
    args
           () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    fexecutemany SState
    sstate ([SqlValue]
    args:[[SqlValue]]
    arglist) =
        do SState -> [SqlValue] -> IO Integer
    forall {b}. Num b => SState -> [SqlValue] -> IO b
    fexecute (SState
    sstate { autoFinish = False }) [SqlValue]
    args
           SState -> [[SqlValue]] -> IO ()
    fexecutemany SState
    sstate [[SqlValue]]
    arglist

    --ffinish o = withForeignPtr o (\p -> sqlite3_finalize p >>= checkError "finish")
    -- Finish and change state
    public_ffinish :: SState -> IO ()
    public_ffinish SState
    sstate = MVar StoState -> (StoState -> IO StoState) -> IO ()
    forall a. MVar a -> (a -> IO a) -> IO ()
    modifyMVar_ (SState -> MVar StoState
    stomv SState
    sstate) StoState -> IO StoState
    worker
        where worker :: StoState -> IO StoState
    worker (StoState
    Empty) = StoState -> IO StoState
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return StoState
    Empty
              worker (Prepared Stmt
    sto) = Sqlite3 -> Stmt -> IO ()
    ffinish (SState -> Sqlite3
    dbo SState
    sstate) Stmt
    sto IO () -> IO StoState -> IO StoState
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StoState -> IO StoState
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return StoState
    Empty
              worker (Executed Stmt
    sto) = Sqlite3 -> Stmt -> IO ()
    ffinish (SState -> Sqlite3
    dbo SState
    sstate) Stmt
    sto IO () -> IO StoState -> IO StoState
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StoState -> IO StoState
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return StoState
    Empty
              worker (Exhausted Stmt
    sto) = Sqlite3 -> Stmt -> IO ()
    ffinish (SState -> Sqlite3
    dbo SState
    sstate) Stmt
    sto IO () -> IO StoState -> IO StoState
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StoState -> IO StoState
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return StoState
    Empty

    ffinish :: Sqlite3 -> Stmt -> IO ()
    ffinish Sqlite3
    dbo Stmt
    o = Stmt -> (Ptr CStmt -> IO ()) -> IO ()
    forall b. Stmt -> (Ptr CStmt -> IO b) -> IO b
    withRawStmt Stmt
    o (\Ptr CStmt
    p -> do r <- Ptr CStmt -> IO CInt
    sqlite3_finalize Ptr CStmt
    p
                                            checkError "finish" dbo r)

    foreign import ccall unsafe "hdbc-sqlite3-helper.h &sqlite3_finalize_finalizer"
      sqlite3_finalizeptr :: FunPtr ((Ptr CStmt) -> IO ())

    foreign import ccall unsafe "hdbc-sqlite3-helper.h sqlite3_finalize_app"
      sqlite3_finalize :: (Ptr CStmt) -> IO CInt

    foreign import ccall unsafe "hdbc-sqlite3-helper.h sqlite3_prepare2"
      sqlite3_prepare :: (Ptr CSqlite3) -> CString -> CInt -> Ptr (Ptr CStmt) -> Ptr (Ptr CString) -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_bind_parameter_count"
      sqlite3_bind_parameter_count :: (Ptr CStmt) -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_step"
      sqlite3_step :: (Ptr CStmt) -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_exec"
      sqlite3_exec :: (Ptr CSqlite3)
                   -> CString
                   -> FunPtr (Ptr () -> CInt -> Ptr CString -> Ptr CString)
                   -> Ptr ()
                   -> Ptr CString
                   -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_reset"
      sqlite3_reset :: (Ptr CStmt) -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_column_count"
      sqlite3_column_count :: (Ptr CStmt) -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_column_name"
      sqlite3_column_name :: Ptr CStmt -> CInt -> IO CString

    foreign import ccall unsafe "sqlite3.h sqlite3_column_type"
      sqlite3_column_type :: (Ptr CStmt) -> CInt -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_column_text"
      sqlite3_column_text :: (Ptr CStmt) -> CInt -> IO CString

    foreign import ccall unsafe "sqlite3.h sqlite3_column_bytes"
      sqlite3_column_bytes :: (Ptr CStmt) -> CInt -> IO CInt

    foreign import ccall unsafe "hdbc-sqlite3-helper.h sqlite3_bind_text2"
      sqlite3_bind_text2 :: (Ptr CStmt) -> CInt -> CString -> CInt -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_bind_null"
      sqlite3_bind_null :: (Ptr CStmt) -> CInt -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_changes"
      sqlite3_changes :: Ptr CSqlite3 -> IO CInt

    foreign import ccall unsafe "sqlite3.h sqlite3_total_changes"
      sqlite3_total_changes :: Ptr CSqlite3 -> IO CInt