direct-sqlite 2.3.27 → 2.3.28
raw patch · 10 files changed
+785/−201 lines, 10 filesdep −semigroupsdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: semigroups
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Database.SQLite3: ErrorAbortRollback :: Error
+ Database.SQLite3: ErrorAuthUser :: Error
+ Database.SQLite3: ErrorBusyRecovery :: Error
+ Database.SQLite3: ErrorBusySnapshot :: Error
+ Database.SQLite3: ErrorBusyTimeout :: Error
+ Database.SQLite3: ErrorCan'tOpenConvertedPath :: Error
+ Database.SQLite3: ErrorCan'tOpenDirtyWriteAheadLog :: Error
+ Database.SQLite3: ErrorCan'tOpenFullPath :: Error
+ Database.SQLite3: ErrorCan'tOpenIsDirectory :: Error
+ Database.SQLite3: ErrorCan'tOpenNotTempDirectory :: Error
+ Database.SQLite3: ErrorCan'tOpenSymlink :: Error
+ Database.SQLite3: ErrorConstraintCheck :: Error
+ Database.SQLite3: ErrorConstraintCommitHook :: Error
+ Database.SQLite3: ErrorConstraintDataType :: Error
+ Database.SQLite3: ErrorConstraintForeignKey :: Error
+ Database.SQLite3: ErrorConstraintFunction :: Error
+ Database.SQLite3: ErrorConstraintNotNull :: Error
+ Database.SQLite3: ErrorConstraintPinned :: Error
+ Database.SQLite3: ErrorConstraintPrimaryKey :: Error
+ Database.SQLite3: ErrorConstraintRowId :: Error
+ Database.SQLite3: ErrorConstraintTrigger :: Error
+ Database.SQLite3: ErrorConstraintUnique :: Error
+ Database.SQLite3: ErrorConstraintVirtualTable :: Error
+ Database.SQLite3: ErrorCorruptIndex :: Error
+ Database.SQLite3: ErrorCorruptSequence :: Error
+ Database.SQLite3: ErrorCorruptVirtualTable :: Error
+ Database.SQLite3: ErrorErrorMissingCollatingSquence :: Error
+ Database.SQLite3: ErrorErrorRetry :: Error
+ Database.SQLite3: ErrorErrorSnapshot :: Error
+ Database.SQLite3: ErrorIOAccess :: Error
+ Database.SQLite3: ErrorIOAuth :: Error
+ Database.SQLite3: ErrorIOBeginAtomic :: Error
+ Database.SQLite3: ErrorIOBlocked :: Error
+ Database.SQLite3: ErrorIOCheckReservedLock :: Error
+ Database.SQLite3: ErrorIOClose :: Error
+ Database.SQLite3: ErrorIOCommitAtomic :: Error
+ Database.SQLite3: ErrorIOConvertedPath :: Error
+ Database.SQLite3: ErrorIOCorruptFilesystem :: Error
+ Database.SQLite3: ErrorIOData :: Error
+ Database.SQLite3: ErrorIODelete :: Error
+ Database.SQLite3: ErrorIODeleteNoEntity :: Error
+ Database.SQLite3: ErrorIODirectoryClose :: Error
+ Database.SQLite3: ErrorIODirectoryFsync :: Error
+ Database.SQLite3: ErrorIOFstat :: Error
+ Database.SQLite3: ErrorIOFsync :: Error
+ Database.SQLite3: ErrorIOGetTempPath :: Error
+ Database.SQLite3: ErrorIOLock :: Error
+ Database.SQLite3: ErrorIOMmap :: Error
+ Database.SQLite3: ErrorIONoMemory :: Error
+ Database.SQLite3: ErrorIORead :: Error
+ Database.SQLite3: ErrorIOReadLock :: Error
+ Database.SQLite3: ErrorIORollbackAtomic :: Error
+ Database.SQLite3: ErrorIOSeek :: Error
+ Database.SQLite3: ErrorIOShmLock :: Error
+ Database.SQLite3: ErrorIOShmMap :: Error
+ Database.SQLite3: ErrorIOShmOpen :: Error
+ Database.SQLite3: ErrorIOShmSize :: Error
+ Database.SQLite3: ErrorIOShortRead :: Error
+ Database.SQLite3: ErrorIOTruncate :: Error
+ Database.SQLite3: ErrorIOUnlock :: Error
+ Database.SQLite3: ErrorIOVNode :: Error
+ Database.SQLite3: ErrorIOWrite :: Error
+ Database.SQLite3: ErrorLockedSharedCache :: Error
+ Database.SQLite3: ErrorLockedVirtualTable :: Error
+ Database.SQLite3: ErrorNoticeRecoverRollback :: Error
+ Database.SQLite3: ErrorNoticeRecoverWriteAheadLog :: Error
+ Database.SQLite3: ErrorOkLoadPermanently :: Error
+ Database.SQLite3: ErrorReadOnlyCan'tInit :: Error
+ Database.SQLite3: ErrorReadOnlyCan'tLock :: Error
+ Database.SQLite3: ErrorReadOnlyDatabaseMoved :: Error
+ Database.SQLite3: ErrorReadOnlyDirectory :: Error
+ Database.SQLite3: ErrorReadOnlyRecovery :: Error
+ Database.SQLite3: ErrorReadOnlyRollback :: Error
+ Database.SQLite3: ErrorWarningAutoIndex :: Error
+ Database.SQLite3: SQLOpenAutoProxy :: SQLOpenFlag
+ Database.SQLite3: SQLOpenCreate :: SQLOpenFlag
+ Database.SQLite3: SQLOpenDeleteOnClose :: SQLOpenFlag
+ Database.SQLite3: SQLOpenExclusive :: SQLOpenFlag
+ Database.SQLite3: SQLOpenFullMutex :: SQLOpenFlag
+ Database.SQLite3: SQLOpenMainDB :: SQLOpenFlag
+ Database.SQLite3: SQLOpenMainJournal :: SQLOpenFlag
+ Database.SQLite3: SQLOpenMasterJournal :: SQLOpenFlag
+ Database.SQLite3: SQLOpenMemory :: SQLOpenFlag
+ Database.SQLite3: SQLOpenNoFollow :: SQLOpenFlag
+ Database.SQLite3: SQLOpenNoMutex :: SQLOpenFlag
+ Database.SQLite3: SQLOpenPrivateCache :: SQLOpenFlag
+ Database.SQLite3: SQLOpenReadOnly :: SQLOpenFlag
+ Database.SQLite3: SQLOpenReadWrite :: SQLOpenFlag
+ Database.SQLite3: SQLOpenSharedCache :: SQLOpenFlag
+ Database.SQLite3: SQLOpenSubJournal :: SQLOpenFlag
+ Database.SQLite3: SQLOpenTempDB :: SQLOpenFlag
+ Database.SQLite3: SQLOpenTempJournal :: SQLOpenFlag
+ Database.SQLite3: SQLOpenTransientDB :: SQLOpenFlag
+ Database.SQLite3: SQLOpenURI :: SQLOpenFlag
+ Database.SQLite3: SQLOpenWAL :: SQLOpenFlag
+ Database.SQLite3: SQLVFSCustom :: Text -> SQLVFS
+ Database.SQLite3: SQLVFSDefault :: SQLVFS
+ Database.SQLite3: SQLVFSUnix :: SQLVFS
+ Database.SQLite3: SQLVFSUnixDotFile :: SQLVFS
+ Database.SQLite3: SQLVFSUnixExcl :: SQLVFS
+ Database.SQLite3: SQLVFSUnixNamedSem :: SQLVFS
+ Database.SQLite3: SQLVFSUnixNone :: SQLVFS
+ Database.SQLite3: data SQLOpenFlag
+ Database.SQLite3: data SQLVFS
+ Database.SQLite3: instance GHC.Classes.Eq Database.SQLite3.SQLOpenFlag
+ Database.SQLite3: instance GHC.Classes.Eq Database.SQLite3.SQLVFS
+ Database.SQLite3: instance GHC.Generics.Generic Database.SQLite3.SQLData
+ Database.SQLite3: instance GHC.Generics.Generic Database.SQLite3.SQLError
+ Database.SQLite3: instance GHC.Show.Show Database.SQLite3.SQLOpenFlag
+ Database.SQLite3: instance GHC.Show.Show Database.SQLite3.SQLVFS
+ Database.SQLite3: open2 :: Text -> [SQLOpenFlag] -> SQLVFS -> IO Database
+ Database.SQLite3.Bindings: c_sqlite3_extended_errcode :: Ptr CDatabase -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_open_v2 :: CString -> Ptr (Ptr CDatabase) -> CInt -> CString -> IO CError
+ Database.SQLite3.Bindings.Types: ErrorAbortRollback :: Error
+ Database.SQLite3.Bindings.Types: ErrorAuthUser :: Error
+ Database.SQLite3.Bindings.Types: ErrorBusyRecovery :: Error
+ Database.SQLite3.Bindings.Types: ErrorBusySnapshot :: Error
+ Database.SQLite3.Bindings.Types: ErrorBusyTimeout :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenConvertedPath :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenDirtyWriteAheadLog :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenFullPath :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenIsDirectory :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenNotTempDirectory :: Error
+ Database.SQLite3.Bindings.Types: ErrorCan'tOpenSymlink :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintCheck :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintCommitHook :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintDataType :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintForeignKey :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintFunction :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintNotNull :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintPinned :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintPrimaryKey :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintRowId :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintTrigger :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintUnique :: Error
+ Database.SQLite3.Bindings.Types: ErrorConstraintVirtualTable :: Error
+ Database.SQLite3.Bindings.Types: ErrorCorruptIndex :: Error
+ Database.SQLite3.Bindings.Types: ErrorCorruptSequence :: Error
+ Database.SQLite3.Bindings.Types: ErrorCorruptVirtualTable :: Error
+ Database.SQLite3.Bindings.Types: ErrorErrorMissingCollatingSquence :: Error
+ Database.SQLite3.Bindings.Types: ErrorErrorRetry :: Error
+ Database.SQLite3.Bindings.Types: ErrorErrorSnapshot :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOAccess :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOAuth :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOBeginAtomic :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOBlocked :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOCheckReservedLock :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOClose :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOCommitAtomic :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOConvertedPath :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOCorruptFilesystem :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOData :: Error
+ Database.SQLite3.Bindings.Types: ErrorIODelete :: Error
+ Database.SQLite3.Bindings.Types: ErrorIODeleteNoEntity :: Error
+ Database.SQLite3.Bindings.Types: ErrorIODirectoryClose :: Error
+ Database.SQLite3.Bindings.Types: ErrorIODirectoryFsync :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOFstat :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOFsync :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOGetTempPath :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOLock :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOMmap :: Error
+ Database.SQLite3.Bindings.Types: ErrorIONoMemory :: Error
+ Database.SQLite3.Bindings.Types: ErrorIORead :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOReadLock :: Error
+ Database.SQLite3.Bindings.Types: ErrorIORollbackAtomic :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOSeek :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOShmLock :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOShmMap :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOShmOpen :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOShmSize :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOShortRead :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOTruncate :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOUnlock :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOVNode :: Error
+ Database.SQLite3.Bindings.Types: ErrorIOWrite :: Error
+ Database.SQLite3.Bindings.Types: ErrorLockedSharedCache :: Error
+ Database.SQLite3.Bindings.Types: ErrorLockedVirtualTable :: Error
+ Database.SQLite3.Bindings.Types: ErrorNoticeRecoverRollback :: Error
+ Database.SQLite3.Bindings.Types: ErrorNoticeRecoverWriteAheadLog :: Error
+ Database.SQLite3.Bindings.Types: ErrorOkLoadPermanently :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyCan'tInit :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyCan'tLock :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyDatabaseMoved :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyDirectory :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyRecovery :: Error
+ Database.SQLite3.Bindings.Types: ErrorReadOnlyRollback :: Error
+ Database.SQLite3.Bindings.Types: ErrorWarningAutoIndex :: Error
+ Database.SQLite3.Bindings.Types: instance GHC.Generics.Generic Database.SQLite3.Bindings.Types.Error
+ Database.SQLite3.Direct: ErrorAbortRollback :: Error
+ Database.SQLite3.Direct: ErrorAuthUser :: Error
+ Database.SQLite3.Direct: ErrorBusyRecovery :: Error
+ Database.SQLite3.Direct: ErrorBusySnapshot :: Error
+ Database.SQLite3.Direct: ErrorBusyTimeout :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenConvertedPath :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenDirtyWriteAheadLog :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenFullPath :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenIsDirectory :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenNotTempDirectory :: Error
+ Database.SQLite3.Direct: ErrorCan'tOpenSymlink :: Error
+ Database.SQLite3.Direct: ErrorConstraintCheck :: Error
+ Database.SQLite3.Direct: ErrorConstraintCommitHook :: Error
+ Database.SQLite3.Direct: ErrorConstraintDataType :: Error
+ Database.SQLite3.Direct: ErrorConstraintForeignKey :: Error
+ Database.SQLite3.Direct: ErrorConstraintFunction :: Error
+ Database.SQLite3.Direct: ErrorConstraintNotNull :: Error
+ Database.SQLite3.Direct: ErrorConstraintPinned :: Error
+ Database.SQLite3.Direct: ErrorConstraintPrimaryKey :: Error
+ Database.SQLite3.Direct: ErrorConstraintRowId :: Error
+ Database.SQLite3.Direct: ErrorConstraintTrigger :: Error
+ Database.SQLite3.Direct: ErrorConstraintUnique :: Error
+ Database.SQLite3.Direct: ErrorConstraintVirtualTable :: Error
+ Database.SQLite3.Direct: ErrorCorruptIndex :: Error
+ Database.SQLite3.Direct: ErrorCorruptSequence :: Error
+ Database.SQLite3.Direct: ErrorCorruptVirtualTable :: Error
+ Database.SQLite3.Direct: ErrorErrorMissingCollatingSquence :: Error
+ Database.SQLite3.Direct: ErrorErrorRetry :: Error
+ Database.SQLite3.Direct: ErrorErrorSnapshot :: Error
+ Database.SQLite3.Direct: ErrorIOAccess :: Error
+ Database.SQLite3.Direct: ErrorIOAuth :: Error
+ Database.SQLite3.Direct: ErrorIOBeginAtomic :: Error
+ Database.SQLite3.Direct: ErrorIOBlocked :: Error
+ Database.SQLite3.Direct: ErrorIOCheckReservedLock :: Error
+ Database.SQLite3.Direct: ErrorIOClose :: Error
+ Database.SQLite3.Direct: ErrorIOCommitAtomic :: Error
+ Database.SQLite3.Direct: ErrorIOConvertedPath :: Error
+ Database.SQLite3.Direct: ErrorIOCorruptFilesystem :: Error
+ Database.SQLite3.Direct: ErrorIOData :: Error
+ Database.SQLite3.Direct: ErrorIODelete :: Error
+ Database.SQLite3.Direct: ErrorIODeleteNoEntity :: Error
+ Database.SQLite3.Direct: ErrorIODirectoryClose :: Error
+ Database.SQLite3.Direct: ErrorIODirectoryFsync :: Error
+ Database.SQLite3.Direct: ErrorIOFstat :: Error
+ Database.SQLite3.Direct: ErrorIOFsync :: Error
+ Database.SQLite3.Direct: ErrorIOGetTempPath :: Error
+ Database.SQLite3.Direct: ErrorIOLock :: Error
+ Database.SQLite3.Direct: ErrorIOMmap :: Error
+ Database.SQLite3.Direct: ErrorIONoMemory :: Error
+ Database.SQLite3.Direct: ErrorIORead :: Error
+ Database.SQLite3.Direct: ErrorIOReadLock :: Error
+ Database.SQLite3.Direct: ErrorIORollbackAtomic :: Error
+ Database.SQLite3.Direct: ErrorIOSeek :: Error
+ Database.SQLite3.Direct: ErrorIOShmLock :: Error
+ Database.SQLite3.Direct: ErrorIOShmMap :: Error
+ Database.SQLite3.Direct: ErrorIOShmOpen :: Error
+ Database.SQLite3.Direct: ErrorIOShmSize :: Error
+ Database.SQLite3.Direct: ErrorIOShortRead :: Error
+ Database.SQLite3.Direct: ErrorIOTruncate :: Error
+ Database.SQLite3.Direct: ErrorIOUnlock :: Error
+ Database.SQLite3.Direct: ErrorIOVNode :: Error
+ Database.SQLite3.Direct: ErrorIOWrite :: Error
+ Database.SQLite3.Direct: ErrorLockedSharedCache :: Error
+ Database.SQLite3.Direct: ErrorLockedVirtualTable :: Error
+ Database.SQLite3.Direct: ErrorNoticeRecoverRollback :: Error
+ Database.SQLite3.Direct: ErrorNoticeRecoverWriteAheadLog :: Error
+ Database.SQLite3.Direct: ErrorOkLoadPermanently :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyCan'tInit :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyCan'tLock :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyDatabaseMoved :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyDirectory :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyRecovery :: Error
+ Database.SQLite3.Direct: ErrorReadOnlyRollback :: Error
+ Database.SQLite3.Direct: ErrorWarningAutoIndex :: Error
+ Database.SQLite3.Direct: extendedErrcode :: Database -> IO Error
+ Database.SQLite3.Direct: open2 :: Utf8 -> Int -> Maybe Utf8 -> IO (Either (Error, Utf8) Database)
- Database.SQLite3: type ExecCallback = ColumnCount " Number of columns, which is the number of items in the following lists. This will be the same for every row." -> [Text] " List of column names. This will be the same for every row." -> [Maybe Text] " List of column values, as returned by 'columnText'." -> IO ()
+ Database.SQLite3: type ExecCallback = ColumnCount -> [Text] -> [Maybe Text] -> IO ()
- Database.SQLite3.Bindings: type CExecCallback a = Ptr a -> CColumnCount " Number of columns, which is the number of elements in the following arrays." -> Ptr CString " Array of column values, as returned by 'c_sqlite3_column_text'. Null values are represented as null pointers." -> Ptr CString " Array of column names" -> IO CInt " If the callback returns non-zero, then 'c_sqlite3_exec' returns @SQLITE_ABORT@ ('ErrorAbort')."
+ Database.SQLite3.Bindings: type CExecCallback a = Ptr a -> CColumnCount -> Ptr CString -> Ptr CString -> IO CInt
- Database.SQLite3.Bindings: type CFunc = Ptr CContext -> CArgCount -> Ptr (Ptr CValue) -> IO ()
+ Database.SQLite3.Bindings: type CFunc = Ptr CContext -> CArgCount -> Ptr Ptr CValue -> IO ()
- Database.SQLite3.Bindings: type CTraceCallback a = Ptr a -> CString " UTF-8 rendering of the SQL statement text as the statement first begins executing." -> IO ()
+ Database.SQLite3.Bindings: type CTraceCallback a = Ptr a -> CString -> IO ()
- Database.SQLite3.Direct: type ExecCallback = ColumnCount " Number of columns, which is the number of items in the following lists. This will be the same for every row." -> [Utf8] " List of column names. This will be the same for every row." -> [Maybe Utf8] " List of column values, as returned by 'columnText'." -> IO ()
+ Database.SQLite3.Direct: type ExecCallback = ColumnCount -> [Utf8] -> [Maybe Utf8] -> IO ()
Files
- Database/SQLite3.hs +85/−7
- Database/SQLite3/Bindings.hs +16/−0
- Database/SQLite3/Bindings/Types.hsc +229/−1
- Database/SQLite3/Direct.hs +36/−17
- cbits/sqlite3.c too large to diff
- cbits/sqlite3.h +264/−100
- cbits/sqlite3ext.h +22/−2
- changelog +3/−0
- direct-sqlite.cabal +2/−5
- test/Main.hs +128/−69
Database/SQLite3.hs view
@@ -1,10 +1,11 @@ {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveGeneric #-} module Database.SQLite3 ( -- * Connection management open,+ open2, close, -- * Simple query execution@@ -111,6 +112,8 @@ Database, Statement, SQLData(..),+ SQLOpenFlag(..),+ SQLVFS(..), SQLError(..), ColumnType(..), FuncContext,@@ -188,12 +191,14 @@ import Control.Monad (when, zipWithM, zipWithM_) import Data.ByteString (ByteString) import Data.Int (Int64)+import Data.Bits ((.|.)) 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)+import GHC.Generics data SQLData = SQLInteger !Int64@@ -201,8 +206,45 @@ | SQLText !Text | SQLBlob !ByteString | SQLNull- deriving (Eq, Show, Typeable)+ deriving (Eq, Show, Typeable, Generic) +-- | These flags are used when using the `open2` function.+-- <https://www.sqlite.org/c3ref/c_open_autoproxy.html>+data SQLOpenFlag+ = SQLOpenReadOnly -- Ok for sqlite3_open_v2()+ | SQLOpenReadWrite -- Ok for sqlite3_open_v2()+ | SQLOpenCreate -- Ok for sqlite3_open_v2()+ | SQLOpenDeleteOnClose -- VFS only+ | SQLOpenExclusive -- VFS only+ | SQLOpenAutoProxy -- VFS only+ | SQLOpenURI -- Ok for sqlite3_open_v2()+ | SQLOpenMemory -- Ok for sqlite3_open_v2()+ | SQLOpenMainDB -- VFS only+ | SQLOpenTempDB -- VFS only+ | SQLOpenTransientDB -- VFS only+ | SQLOpenMainJournal -- VFS only+ | SQLOpenTempJournal -- VFS only+ | SQLOpenSubJournal -- VFS only+ | SQLOpenMasterJournal -- VFS only+ | SQLOpenNoMutex -- Ok for sqlite3_open_v2()+ | SQLOpenFullMutex -- Ok for sqlite3_open_v2()+ | SQLOpenSharedCache -- Ok for sqlite3_open_v2()+ | SQLOpenPrivateCache -- Ok for sqlite3_open_v2()+ | SQLOpenWAL -- VFS only+ | SQLOpenNoFollow -- Ok for sqlite3_open_v2()+ deriving (Eq, Show)++-- | These VFS names are used when using the `open2` function.+data SQLVFS+ = SQLVFSDefault+ | SQLVFSUnix+ | SQLVFSUnixDotFile+ | SQLVFSUnixExcl+ | SQLVFSUnixNone+ | SQLVFSUnixNamedSem+ | SQLVFSCustom Text+ deriving (Eq, Show)+ -- | Exception thrown when SQLite3 reports an error. -- -- direct-sqlite may throw other types of exceptions if you misuse the API.@@ -215,7 +257,7 @@ -- ^ Indicates what action produced this error, -- e.g. @exec \"SELECT * FROM foo\"@ }- deriving (Eq, Typeable)+ deriving (Eq, Typeable, Generic) -- NB: SQLError is lazy in 'sqlErrorDetails' and 'sqlErrorContext', -- to defer message construction in the case where a user catches and@@ -290,6 +332,46 @@ Direct.open (toUtf8 path) >>= checkErrorMsg ("open " `appendShow` path) +-- | <https://www.sqlite.org/c3ref/open.html>+open2 :: Text -> [SQLOpenFlag] -> SQLVFS -> IO Database+open2 path flags zvfs =+ Direct.open2 (toUtf8 path) (makeFlag flags) (toMUtf8 zvfs)+ >>= checkErrorMsg ("open2 " `appendShow` path)+ where+ toMUtf8 = fmap toUtf8 . toMText++ toMText SQLVFSDefault = Nothing+ toMText SQLVFSUnix = Just "unix"+ toMText SQLVFSUnixDotFile = Just "unix-dotfile"+ toMText SQLVFSUnixExcl = Just "unix-excl"+ toMText SQLVFSUnixNone = Just "unix-none"+ toMText SQLVFSUnixNamedSem = Just "unix-namedsem"+ toMText (SQLVFSCustom custom) = Just custom++ makeFlag = foldr (.|.) 0 . fmap toNum++ toNum SQLOpenReadOnly = 0x00000001+ toNum SQLOpenReadWrite = 0x00000002+ toNum SQLOpenCreate = 0x00000004+ toNum SQLOpenDeleteOnClose = 0x00000008+ toNum SQLOpenExclusive = 0x00000010+ toNum SQLOpenAutoProxy = 0x00000020+ toNum SQLOpenURI = 0x00000040+ toNum SQLOpenMemory = 0x00000080+ toNum SQLOpenMainDB = 0x00000100+ toNum SQLOpenTempDB = 0x00000200+ toNum SQLOpenTransientDB = 0x00000400+ toNum SQLOpenMainJournal = 0x00000800+ toNum SQLOpenTempJournal = 0x00001000+ toNum SQLOpenSubJournal = 0x00002000+ toNum SQLOpenMasterJournal = 0x00004000+ toNum SQLOpenNoMutex = 0x00008000+ toNum SQLOpenFullMutex = 0x00010000+ toNum SQLOpenSharedCache = 0x00020000+ toNum SQLOpenPrivateCache = 0x00040000+ toNum SQLOpenWAL = 0x00080000+ toNum SQLOpenNoFollow = 0x01000000+ -- | <https://www.sqlite.org/c3ref/close.html> close :: Database -> IO () close db =@@ -302,7 +384,6 @@ -- It works by running the callback in a forked thread. If interrupted, -- it uses 'interrupt' to try to stop the operation. interruptibly :: Database -> IO a -> IO a-#if MIN_VERSION_base(4,3,0) interruptibly db io | rtsSupportsBoundThreads = mask $ \restore -> do@@ -335,9 +416,6 @@ where try' :: IO a -> IO (Either SomeException a) try' = try-#else-interruptibly _db io = io-#endif -- | Execute zero or more SQL statements delimited by semicolons. exec :: Database -> Text -> IO ()
Database/SQLite3/Bindings.hs view
@@ -4,8 +4,10 @@ -- * Connection management c_sqlite3_open,+ c_sqlite3_open_v2, c_sqlite3_close, c_sqlite3_errcode,+ c_sqlite3_extended_errcode, c_sqlite3_errmsg, c_sqlite3_interrupt, c_sqlite3_trace,@@ -138,6 +140,16 @@ foreign import ccall "sqlite3_open" c_sqlite3_open :: CString -> Ptr (Ptr CDatabase) -> IO CError +-- | <https://www.sqlite.org/c3ref/open.html>+--+-- This sets the @'Ptr CDatabase'@ even on failure.+foreign import ccall "sqlite3_open_v2"+ c_sqlite3_open_v2 :: CString+ -> Ptr (Ptr CDatabase)+ -> CInt+ -> CString+ -> IO CError+ -- | <https://www.sqlite.org/c3ref/close.html> foreign import ccall "sqlite3_close" c_sqlite3_close :: Ptr CDatabase -> IO CError@@ -145,6 +157,10 @@ -- | <https://www.sqlite.org/c3ref/errcode.html> foreign import ccall unsafe "sqlite3_errcode" c_sqlite3_errcode :: Ptr CDatabase -> IO CError++-- | <https://www.sqlite.org/c3ref/errcode.html>+foreign import ccall unsafe "sqlite3_extended_errcode"+ c_sqlite3_extended_errcode :: Ptr CDatabase -> IO CError -- | <https://www.sqlite.org/c3ref/errcode.html> foreign import ccall unsafe "sqlite3_errmsg"
Database/SQLite3/Bindings/Types.hsc view
@@ -2,6 +2,7 @@ {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveGeneric #-} module Database.SQLite3.Bindings.Types ( -- * Objects -- | <https://www.sqlite.org/c3ref/objlist.html>@@ -59,12 +60,14 @@ #include "cbits/sqlite3.h" #endif +import GHC.Generics import Foreign.C.Types import Foreign.Ptr -- Result code documentation copied from <https://www.sqlite.org/c3ref/c_abort.html> -- | <https://www.sqlite.org/c3ref/c_abort.html>+-- <https://www.sqlite.org/c3ref/c_abort_rollback.html> data Error = ErrorOK -- ^ Successful result | ErrorError -- ^ SQL error or missing database | ErrorInternal -- ^ Internal logic error in SQLite@@ -96,8 +99,83 @@ | ErrorWarning -- ^ Warnings from sqlite3_log() | ErrorRow -- ^ @sqlite3_step()@ has another row ready | ErrorDone -- ^ @sqlite3_step()@ has finished executing- deriving (Eq, Show) + | ErrorErrorMissingCollatingSquence+ | ErrorErrorRetry+ | ErrorErrorSnapshot+ | ErrorIORead+ | ErrorIOShortRead+ | ErrorIOWrite+ | ErrorIOFsync+ | ErrorIODirectoryFsync+ | ErrorIOTruncate+ | ErrorIOFstat+ | ErrorIOUnlock+ | ErrorIOReadLock+ | ErrorIOBlocked+ | ErrorIODelete+ | ErrorIONoMemory+ | ErrorIOAccess+ | ErrorIOCheckReservedLock+ | ErrorIOLock+ | ErrorIOClose+ | ErrorIODirectoryClose+ | ErrorIOShmOpen+ | ErrorIOShmSize+ | ErrorIOShmLock+ | ErrorIOShmMap+ | ErrorIOSeek+ | ErrorIODeleteNoEntity+ | ErrorIOMmap+ | ErrorIOGetTempPath+ | ErrorIOConvertedPath+ | ErrorIOVNode+ | ErrorIOAuth+ | ErrorIOBeginAtomic+ | ErrorIOCommitAtomic+ | ErrorIORollbackAtomic+ | ErrorIOData+ | ErrorIOCorruptFilesystem+ | ErrorLockedSharedCache+ | ErrorLockedVirtualTable+ | ErrorBusyRecovery+ | ErrorBusySnapshot+ | ErrorBusyTimeout+ | ErrorCan'tOpenNotTempDirectory+ | ErrorCan'tOpenIsDirectory+ | ErrorCan'tOpenFullPath+ | ErrorCan'tOpenConvertedPath+ | ErrorCan'tOpenDirtyWriteAheadLog+ | ErrorCan'tOpenSymlink+ | ErrorCorruptVirtualTable+ | ErrorCorruptSequence+ | ErrorCorruptIndex+ | ErrorReadOnlyRecovery+ | ErrorReadOnlyCan'tLock+ | ErrorReadOnlyRollback+ | ErrorReadOnlyDatabaseMoved+ | ErrorReadOnlyCan'tInit+ | ErrorReadOnlyDirectory+ | ErrorAbortRollback+ | ErrorConstraintCheck+ | ErrorConstraintCommitHook+ | ErrorConstraintForeignKey+ | ErrorConstraintFunction+ | ErrorConstraintNotNull+ | ErrorConstraintPrimaryKey+ | ErrorConstraintTrigger+ | ErrorConstraintUnique+ | ErrorConstraintVirtualTable+ | ErrorConstraintRowId+ | ErrorConstraintPinned+ | ErrorConstraintDataType+ | ErrorNoticeRecoverWriteAheadLog+ | ErrorNoticeRecoverRollback+ | ErrorWarningAutoIndex+ | ErrorAuthUser+ | ErrorOkLoadPermanently+ deriving (Eq, Show, Generic)+ -- | <https://www.sqlite.org/c3ref/c_blob.html> data ColumnType = IntegerColumn | FloatColumn@@ -293,6 +371,81 @@ #{const SQLITE_WARNING} -> ErrorWarning #{const SQLITE_ROW} -> ErrorRow #{const SQLITE_DONE} -> ErrorDone+ -- extended result codes+ #{const SQLITE_ERROR_MISSING_COLLSEQ} -> ErrorErrorMissingCollatingSquence+ #{const SQLITE_ERROR_RETRY} -> ErrorErrorRetry+ #{const SQLITE_ERROR_SNAPSHOT} -> ErrorErrorSnapshot+ #{const SQLITE_IOERR_READ} -> ErrorIORead+ #{const SQLITE_IOERR_SHORT_READ} -> ErrorIOShortRead+ #{const SQLITE_IOERR_WRITE} -> ErrorIOWrite+ #{const SQLITE_IOERR_FSYNC} -> ErrorIOFsync+ #{const SQLITE_IOERR_DIR_FSYNC} -> ErrorIODirectoryFsync+ #{const SQLITE_IOERR_TRUNCATE} -> ErrorIOTruncate+ #{const SQLITE_IOERR_FSTAT} -> ErrorIOFstat+ #{const SQLITE_IOERR_UNLOCK} -> ErrorIOUnlock+ #{const SQLITE_IOERR_RDLOCK} -> ErrorIOReadLock+ #{const SQLITE_IOERR_DELETE} -> ErrorIODelete+ #{const SQLITE_IOERR_BLOCKED} -> ErrorIOBlocked+ #{const SQLITE_IOERR_NOMEM} -> ErrorIONoMemory+ #{const SQLITE_IOERR_ACCESS} -> ErrorIOAccess+ #{const SQLITE_IOERR_CHECKRESERVEDLOCK} -> ErrorIOCheckReservedLock+ #{const SQLITE_IOERR_LOCK} -> ErrorIOLock+ #{const SQLITE_IOERR_CLOSE} -> ErrorIOClose+ #{const SQLITE_IOERR_DIR_CLOSE} -> ErrorIODirectoryClose+ #{const SQLITE_IOERR_SHMOPEN} -> ErrorIOShmOpen+ #{const SQLITE_IOERR_SHMSIZE} -> ErrorIOShmSize+ #{const SQLITE_IOERR_SHMLOCK} -> ErrorIOShmLock+ #{const SQLITE_IOERR_SHMMAP} -> ErrorIOShmMap+ #{const SQLITE_IOERR_SEEK} -> ErrorIOSeek+ #{const SQLITE_IOERR_DELETE_NOENT} -> ErrorIODeleteNoEntity+ #{const SQLITE_IOERR_MMAP} -> ErrorIOMmap+ #{const SQLITE_IOERR_GETTEMPPATH} -> ErrorIOGetTempPath+ #{const SQLITE_IOERR_CONVPATH} -> ErrorIOConvertedPath+ #{const SQLITE_IOERR_VNODE} -> ErrorIOVNode+ #{const SQLITE_IOERR_AUTH} -> ErrorIOAuth+ #{const SQLITE_IOERR_BEGIN_ATOMIC} -> ErrorIOBeginAtomic+ #{const SQLITE_IOERR_COMMIT_ATOMIC} -> ErrorIOCommitAtomic+ #{const SQLITE_IOERR_ROLLBACK_ATOMIC} -> ErrorIORollbackAtomic+ #{const SQLITE_IOERR_DATA} -> ErrorIOData+ #{const SQLITE_IOERR_CORRUPTFS} -> ErrorIOCorruptFilesystem+ #{const SQLITE_LOCKED_SHAREDCACHE} -> ErrorLockedSharedCache+ #{const SQLITE_LOCKED_VTAB} -> ErrorLockedVirtualTable+ #{const SQLITE_BUSY_RECOVERY} -> ErrorBusyRecovery+ #{const SQLITE_BUSY_SNAPSHOT} -> ErrorBusySnapshot+ #{const SQLITE_BUSY_TIMEOUT} -> ErrorBusyTimeout+ #{const SQLITE_CANTOPEN_NOTEMPDIR} -> ErrorCan'tOpenNotTempDirectory+ #{const SQLITE_CANTOPEN_ISDIR} -> ErrorCan'tOpenIsDirectory+ #{const SQLITE_CANTOPEN_FULLPATH} -> ErrorCan'tOpenFullPath+ #{const SQLITE_CANTOPEN_CONVPATH} -> ErrorCan'tOpenConvertedPath+ #{const SQLITE_CANTOPEN_DIRTYWAL} -> ErrorCan'tOpenDirtyWriteAheadLog+ #{const SQLITE_CANTOPEN_SYMLINK} -> ErrorCan'tOpenSymlink+ #{const SQLITE_CORRUPT_VTAB} -> ErrorCorruptVirtualTable+ #{const SQLITE_CORRUPT_SEQUENCE} -> ErrorCorruptSequence+ #{const SQLITE_CORRUPT_INDEX} -> ErrorCorruptIndex+ #{const SQLITE_READONLY_RECOVERY} -> ErrorReadOnlyRecovery+ #{const SQLITE_READONLY_CANTLOCK} -> ErrorReadOnlyCan'tLock+ #{const SQLITE_READONLY_ROLLBACK} -> ErrorReadOnlyRollback+ #{const SQLITE_READONLY_DBMOVED} -> ErrorReadOnlyDatabaseMoved+ #{const SQLITE_READONLY_CANTINIT} -> ErrorReadOnlyCan'tInit+ #{const SQLITE_READONLY_DIRECTORY} -> ErrorReadOnlyDirectory+ #{const SQLITE_ABORT_ROLLBACK} -> ErrorAbortRollback+ #{const SQLITE_CONSTRAINT_CHECK} -> ErrorConstraintCheck+ #{const SQLITE_CONSTRAINT_COMMITHOOK} -> ErrorConstraintCommitHook+ #{const SQLITE_CONSTRAINT_FOREIGNKEY} -> ErrorConstraintForeignKey+ #{const SQLITE_CONSTRAINT_FUNCTION} -> ErrorConstraintFunction+ #{const SQLITE_CONSTRAINT_NOTNULL} -> ErrorConstraintNotNull+ #{const SQLITE_CONSTRAINT_PRIMARYKEY} -> ErrorConstraintPrimaryKey+ #{const SQLITE_CONSTRAINT_TRIGGER} -> ErrorConstraintTrigger+ #{const SQLITE_CONSTRAINT_UNIQUE} -> ErrorConstraintUnique+ #{const SQLITE_CONSTRAINT_VTAB} -> ErrorConstraintVirtualTable+ #{const SQLITE_CONSTRAINT_ROWID} -> ErrorConstraintRowId+ #{const SQLITE_CONSTRAINT_PINNED} -> ErrorConstraintPinned+ #{const SQLITE_CONSTRAINT_DATATYPE} -> ErrorConstraintDataType+ #{const SQLITE_NOTICE_RECOVER_WAL} -> ErrorNoticeRecoverWriteAheadLog+ #{const SQLITE_NOTICE_RECOVER_ROLLBACK} -> ErrorNoticeRecoverRollback+ #{const SQLITE_WARNING_AUTOINDEX} -> ErrorWarningAutoIndex+ #{const SQLITE_AUTH_USER} -> ErrorAuthUser+ #{const SQLITE_OK_LOAD_PERMANENTLY} -> ErrorOkLoadPermanently _ -> error $ "decodeError " ++ show n encodeError :: Error -> CError@@ -328,6 +481,81 @@ ErrorWarning -> #const SQLITE_WARNING ErrorRow -> #const SQLITE_ROW ErrorDone -> #const SQLITE_DONE++ ErrorErrorMissingCollatingSquence -> #const SQLITE_ERROR_MISSING_COLLSEQ+ ErrorErrorRetry -> #const SQLITE_ERROR_RETRY+ ErrorErrorSnapshot -> #const SQLITE_ERROR_SNAPSHOT+ ErrorIORead -> #const SQLITE_IOERR_READ+ ErrorIOShortRead -> #const SQLITE_IOERR_SHORT_READ+ ErrorIOWrite -> #const SQLITE_IOERR_WRITE+ ErrorIOFsync -> #const SQLITE_IOERR_FSYNC+ ErrorIODirectoryFsync -> #const SQLITE_IOERR_DIR_FSYNC+ ErrorIOTruncate -> #const SQLITE_IOERR_TRUNCATE+ ErrorIOFstat -> #const SQLITE_IOERR_FSTAT+ ErrorIOUnlock -> #const SQLITE_IOERR_UNLOCK+ ErrorIOReadLock -> #const SQLITE_IOERR_RDLOCK+ ErrorIOBlocked -> #const SQLITE_IOERR_BLOCKED+ ErrorIODelete -> #const SQLITE_IOERR_DELETE+ ErrorIONoMemory -> #const SQLITE_IOERR_NOMEM+ ErrorIOAccess -> #const SQLITE_IOERR_ACCESS+ ErrorIOCheckReservedLock -> #const SQLITE_IOERR_CHECKRESERVEDLOCK+ ErrorIOLock -> #const SQLITE_IOERR_LOCK+ ErrorIOClose -> #const SQLITE_IOERR_CLOSE+ ErrorIODirectoryClose -> #const SQLITE_IOERR_DIR_CLOSE+ ErrorIOShmOpen -> #const SQLITE_IOERR_SHMOPEN+ ErrorIOShmSize -> #const SQLITE_IOERR_SHMSIZE+ ErrorIOShmLock -> #const SQLITE_IOERR_SHMLOCK+ ErrorIOShmMap -> #const SQLITE_IOERR_SHMMAP+ ErrorIOSeek -> #const SQLITE_IOERR_SEEK+ ErrorIODeleteNoEntity -> #const SQLITE_IOERR_DELETE_NOENT+ ErrorIOMmap -> #const SQLITE_IOERR_MMAP+ ErrorIOGetTempPath -> #const SQLITE_IOERR_GETTEMPPATH+ ErrorIOConvertedPath -> #const SQLITE_IOERR_CONVPATH+ ErrorIOVNode -> #const SQLITE_IOERR_VNODE+ ErrorIOAuth -> #const SQLITE_IOERR_AUTH+ ErrorIOBeginAtomic -> #const SQLITE_IOERR_BEGIN_ATOMIC+ ErrorIOCommitAtomic -> #const SQLITE_IOERR_COMMIT_ATOMIC+ ErrorIORollbackAtomic -> #const SQLITE_IOERR_ROLLBACK_ATOMIC+ ErrorIOData -> #const SQLITE_IOERR_DATA+ ErrorIOCorruptFilesystem -> #const SQLITE_IOERR_CORRUPTFS+ ErrorLockedSharedCache -> #const SQLITE_LOCKED_SHAREDCACHE+ ErrorLockedVirtualTable -> #const SQLITE_LOCKED_VTAB+ ErrorBusyRecovery -> #const SQLITE_BUSY_RECOVERY+ ErrorBusySnapshot -> #const SQLITE_BUSY_SNAPSHOT+ ErrorBusyTimeout -> #const SQLITE_BUSY_TIMEOUT+ ErrorCan'tOpenNotTempDirectory -> #const SQLITE_CANTOPEN_NOTEMPDIR+ ErrorCan'tOpenIsDirectory -> #const SQLITE_CANTOPEN_ISDIR+ ErrorCan'tOpenFullPath -> #const SQLITE_CANTOPEN_FULLPATH+ ErrorCan'tOpenConvertedPath -> #const SQLITE_CANTOPEN_CONVPATH+ ErrorCan'tOpenDirtyWriteAheadLog -> #const SQLITE_CANTOPEN_DIRTYWAL+ ErrorCan'tOpenSymlink -> #const SQLITE_CANTOPEN_SYMLINK+ ErrorCorruptVirtualTable -> #const SQLITE_CORRUPT_VTAB+ ErrorCorruptSequence -> #const SQLITE_CORRUPT_SEQUENCE+ ErrorCorruptIndex -> #const SQLITE_CORRUPT_INDEX+ ErrorReadOnlyRecovery -> #const SQLITE_READONLY_RECOVERY+ ErrorReadOnlyCan'tLock -> #const SQLITE_READONLY_CANTLOCK+ ErrorReadOnlyRollback -> #const SQLITE_READONLY_ROLLBACK+ ErrorReadOnlyDatabaseMoved -> #const SQLITE_READONLY_DBMOVED+ ErrorReadOnlyCan'tInit -> #const SQLITE_READONLY_CANTINIT+ ErrorReadOnlyDirectory -> #const SQLITE_READONLY_DIRECTORY+ ErrorAbortRollback -> #const SQLITE_ABORT_ROLLBACK+ ErrorConstraintCheck -> #const SQLITE_CONSTRAINT_CHECK+ ErrorConstraintCommitHook -> #const SQLITE_CONSTRAINT_COMMITHOOK+ ErrorConstraintForeignKey -> #const SQLITE_CONSTRAINT_FOREIGNKEY+ ErrorConstraintFunction -> #const SQLITE_CONSTRAINT_FUNCTION+ ErrorConstraintNotNull -> #const SQLITE_CONSTRAINT_NOTNULL+ ErrorConstraintPrimaryKey -> #const SQLITE_CONSTRAINT_PRIMARYKEY+ ErrorConstraintTrigger -> #const SQLITE_CONSTRAINT_TRIGGER+ ErrorConstraintUnique -> #const SQLITE_CONSTRAINT_UNIQUE+ ErrorConstraintVirtualTable -> #const SQLITE_CONSTRAINT_VTAB+ ErrorConstraintRowId -> #const SQLITE_CONSTRAINT_ROWID+ ErrorConstraintPinned -> #const SQLITE_CONSTRAINT_PINNED+ ErrorConstraintDataType -> #const SQLITE_CONSTRAINT_DATATYPE+ ErrorNoticeRecoverWriteAheadLog -> #const SQLITE_NOTICE_RECOVER_WAL+ ErrorNoticeRecoverRollback -> #const SQLITE_NOTICE_RECOVER_ROLLBACK+ ErrorWarningAutoIndex -> #const SQLITE_WARNING_AUTOINDEX+ ErrorAuthUser -> #const SQLITE_AUTH_USER+ ErrorOkLoadPermanently -> #const SQLITE_OK_LOAD_PERMANENTLY -- | <https://www.sqlite.org/c3ref/c_blob.html> newtype CColumnType = CColumnType CInt
Database/SQLite3/Direct.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables #-} -- |@@ -12,8 +11,10 @@ module Database.SQLite3.Direct ( -- * Connection management open,+ open2, close, errcode,+ extendedErrcode, errmsg, setTrace, getAutoCommit,@@ -151,10 +152,6 @@ import Foreign.C import qualified System.IO.Unsafe as IOU -#if !MIN_VERSION_base(4,11,0)-import Data.Semigroup (Semigroup)-#endif- newtype Database = Database (Ptr CDatabase) deriving (Eq, Show) @@ -259,19 +256,36 @@ BS.useAsCString path $ \path' -> alloca $ \database -> do rc <- c_sqlite3_open path' database- db <- Database <$> peek database- -- sqlite3_open returns a sqlite3 even on failure.- -- That's where we get a more descriptive error message.- case toResult () rc of- Left err -> do- msg <- errmsg db -- This returns "out of memory" if db is null.- _ <- close db -- This is harmless if db is null.- return $ Left (err, msg)- Right () ->- if db == Database nullPtr- then fail "sqlite3_open unexpectedly returned NULL"- else return $ Right db+ openHelper rc database +-- | <https://www.sqlite.org/c3ref/open.html>+open2 :: Utf8 -> Int -> Maybe Utf8 -> IO (Either (Error, Utf8) Database)+open2 (Utf8 path) flags mzvfs =+ BS.useAsCString path $ \path' ->+ useAsMaybeCString mzvfs $ \zvfs' ->+ alloca $ \database -> do+ rc <- c_sqlite3_open_v2 path' database (toEnum flags) zvfs'+ openHelper rc database++ where useAsMaybeCString :: Maybe Utf8 -> (CString -> IO a) -> IO a+ useAsMaybeCString (Just (Utf8 zvfs)) f = BS.useAsCString zvfs f+ useAsMaybeCString _ f = f nullPtr++openHelper :: CError -> Ptr (Ptr CDatabase) -> IO (Either (Error, Utf8) Database)+openHelper rc database = do+ db <- Database <$> peek database+ -- sqlite3_open and sqlite3_open_v2 return a sqlite3 even on failure.+ -- That's where we get a more descriptive error message.+ case toResult () rc of+ Left err -> do+ msg <- errmsg db -- This returns "out of memory" if db is null.+ _ <- close db -- This is harmless if db is null.+ return $ Left (err, msg)+ Right () ->+ if db == Database nullPtr+ then fail "sqlite3_open unexpectedly returned NULL"+ else return $ Right db+ -- | <https://www.sqlite.org/c3ref/close.html> close :: Database -> IO (Either Error ()) close (Database db) =@@ -294,6 +308,11 @@ errcode :: Database -> IO Error errcode (Database db) = decodeError <$> c_sqlite3_errcode db++-- | <https://www.sqlite.org/c3ref/errcode.html>+extendedErrcode :: Database -> IO Error+extendedErrcode (Database db) =+ decodeError <$> c_sqlite3_extended_errcode db -- | <https://www.sqlite.org/c3ref/errcode.html> errmsg :: Database -> IO Utf8
cbits/sqlite3.c view
file too large to diff
cbits/sqlite3.h view
@@ -146,9 +146,9 @@ ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */-#define SQLITE_VERSION "3.38.5"-#define SQLITE_VERSION_NUMBER 3038005-#define SQLITE_SOURCE_ID "2022-05-06 15:25:27 78d9c993d404cdfaa7fdd2973fa1052e3da9f66215cff9c5540ebe55c407d9fe"+#define SQLITE_VERSION "3.41.0"+#define SQLITE_VERSION_NUMBER 3041000+#define SQLITE_SOURCE_ID "2023-02-21 18:09:37 05941c2a04037fc3ed2ffae11f5d2260706f89431f463518740f72ada350866d" /* ** CAPI3REF: Run-Time Library Version Numbers@@ -563,6 +563,7 @@ #define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))+#define SQLITE_NOTICE_RBU (SQLITE_NOTICE | (3<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))@@ -670,13 +671,17 @@ ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods-** of an [sqlite3_io_methods] object.+** of an [sqlite3_io_methods] object. These values are ordered from+** lest restrictive to most restrictive.+**+** The argument to xLock() is always SHARED or higher. The argument to+** xUnlock is either SHARED or NONE. */-#define SQLITE_LOCK_NONE 0-#define SQLITE_LOCK_SHARED 1-#define SQLITE_LOCK_RESERVED 2-#define SQLITE_LOCK_PENDING 3-#define SQLITE_LOCK_EXCLUSIVE 4+#define SQLITE_LOCK_NONE 0 /* xUnlock() only */+#define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */+#define SQLITE_LOCK_RESERVED 2 /* xLock() only */+#define SQLITE_LOCK_PENDING 3 /* xLock() only */+#define SQLITE_LOCK_EXCLUSIVE 4 /* xLock() only */ /* ** CAPI3REF: Synchronization Type Flags@@ -754,7 +759,14 @@ ** <li> [SQLITE_LOCK_PENDING], or ** <li> [SQLITE_LOCK_EXCLUSIVE]. ** </ul>-** xLock() increases the lock. xUnlock() decreases the lock.+** xLock() upgrades the database file lock. In other words, xLock() moves the+** database file lock in the direction NONE toward EXCLUSIVE. The argument to+** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never+** SQLITE_LOCK_NONE. If the database file lock is already at or above the+** requested lock, then the call to xLock() is a no-op.+** xUnlock() downgrades the database file lock to either SHARED or NONE.+* If the lock is already at or below the requested lock state, then the call+** to xUnlock() is a no-op. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, ** PENDING, or EXCLUSIVE lock on the file. It returns true@@ -859,9 +871,8 @@ ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])-** into an integer that the pArg argument points to. This capability-** is used during testing and is only available when the SQLITE_TEST-** compile-time option is used.+** into an integer that the pArg argument points to.+** This capability is only available if SQLite is compiled with [SQLITE_DEBUG]. ** ** <li>[[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS@@ -1165,7 +1176,6 @@ ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed.-** </ul> ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect@@ -1178,10 +1188,16 @@ ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes.-** </ul> ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]]-** Used by the cksmvfs VFS module only.+** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the+** [checksum VFS shim] only.+**+** <li>[[SQLITE_FCNTL_RESET_CACHE]]+** If there is currently no transaction open on the database, and the+** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control+** purges the contents of the in-memory page cache. If there is an open+** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1@@ -1224,6 +1240,7 @@ #define SQLITE_FCNTL_CKPT_START 39 #define SQLITE_FCNTL_EXTERNAL_READER 40 #define SQLITE_FCNTL_CKSM_FILE 41+#define SQLITE_FCNTL_RESET_CACHE 42 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE@@ -1254,6 +1271,26 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; /*+** CAPI3REF: File Name+**+** Type [sqlite3_filename] is used by SQLite to pass filenames to the+** xOpen method of a [VFS]. It may be cast to (const char*) and treated+** as a normal, nul-terminated, UTF-8 buffer containing the filename, but+** may also be passed to special APIs such as:+**+** <ul>+** <li> sqlite3_filename_database()+** <li> sqlite3_filename_journal()+** <li> sqlite3_filename_wal()+** <li> sqlite3_uri_parameter()+** <li> sqlite3_uri_boolean()+** <li> sqlite3_uri_int64()+** <li> sqlite3_uri_key()+** </ul>+*/+typedef const char *sqlite3_filename;++/* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between@@ -1431,7 +1468,7 @@ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */- int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,+ int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);@@ -2147,7 +2184,7 @@ ** configuration for a database connection can only be changed when that ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by-** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.+** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd>@@ -2297,8 +2334,12 @@ ** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ** </ol> ** Because resetting a database is destructive and irreversible, the-** process requires the use of this obscure API and multiple steps to help-** ensure that it does not happen by accident.+** process requires the use of this obscure API and multiple steps to+** help ensure that it does not happen by accident. Because this+** feature must be capable of resetting corrupt databases, and+** shutting down virtual tables may require access to that corrupt+** storage, the library must abandon any installed virtual tables+** without calling their xDestroy() methods. ** ** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the@@ -2309,6 +2350,7 @@ ** <ul> ** <li> The [PRAGMA writable_schema=ON] statement. ** <li> The [PRAGMA journal_mode=OFF] statement.+** <li> The [PRAGMA schema_version=N] statement. ** <li> Writes to the [sqlite_dbpage] virtual table. ** <li> Direct writes to [shadow tables]. ** </ul>@@ -2636,8 +2678,12 @@ ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns.+**+** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether+** or not an interrupt is currently in effect for [database connection] D. */ SQLITE_API void sqlite3_interrupt(sqlite3*);+SQLITE_API int sqlite3_is_interrupted(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete@@ -3255,8 +3301,8 @@ ** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same ** information as is provided by the [sqlite3_profile()] callback. ** ^The P argument is a pointer to the [prepared statement] and the-** X argument points to a 64-bit integer which is the estimated of-** the number of nanosecond that the prepared statement took to run.+** X argument points to a 64-bit integer which is approximately+** the number of nanoseconds that the prepared statement took to run. ** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. ** ** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>@@ -3319,7 +3365,7 @@ ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to-** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for+** [sqlite3_step()] and [sqlite3_prepare()] and similar for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. **@@ -3344,6 +3390,13 @@ ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. **+** The progress handler callback would originally only be invoked from the+** bytecode engine. It still might be invoked during [sqlite3_prepare()]+** and similar because those routines might force a reparse of the schema+** which involves running the bytecode engine. However, beginning with+** SQLite version 3.41.0, the progress handler callback might also be+** invoked directly from [sqlite3_prepare()] while analyzing and generating+** code for complex queries. */ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); @@ -3380,13 +3433,18 @@ ** ** <dl> ** ^(<dt>[SQLITE_OPEN_READONLY]</dt>-** <dd>The database is opened in read-only mode. If the database does not-** already exist, an error is returned.</dd>)^+** <dd>The database is opened in read-only mode. If the database does+** not already exist, an error is returned.</dd>)^ ** ** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>-** <dd>The database is opened for reading and writing if possible, or reading-** only if the file is write protected by the operating system. In either-** case the database must already exist, otherwise an error is returned.</dd>)^+** <dd>The database is opened for reading and writing if possible, or+** reading only if the file is write protected by the operating+** system. In either case the database must already exist, otherwise+** an error is returned. For historical reasons, if opening in+** read-write mode fails due to OS-level permissions, an attempt is+** made to open it in read-only mode. [sqlite3_db_readonly()] can be+** used to determine whether the database is actually+** read-write.</dd>)^ ** ** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt> ** <dd>The database is opened for reading and writing, and is created if@@ -3424,6 +3482,9 @@ ** <dd>The database is opened [shared cache] enabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^+** The [use of shared cache mode is discouraged] and hence shared cache+** capabilities may be omitted from many builds of SQLite. In such cases,+** this option is a no-op. ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding@@ -3439,7 +3500,7 @@ ** to return an extended result code.</dd> ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>-** <dd>The database filename is not allowed to be a symbolic link</dd>+** <dd>The database filename is not allowed to contain a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the@@ -3698,10 +3759,10 @@ ** ** See the [URI filename] documentation for additional information. */-SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);-SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);-SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);-SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);+SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam);+SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault);+SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64);+SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N); /* ** CAPI3REF: Translate filenames@@ -3730,9 +3791,9 @@ ** return value from [sqlite3_db_filename()], then the result is ** undefined and is likely a memory access violation. */-SQLITE_API const char *sqlite3_filename_database(const char*);-SQLITE_API const char *sqlite3_filename_journal(const char*);-SQLITE_API const char *sqlite3_filename_wal(const char*);+SQLITE_API const char *sqlite3_filename_database(sqlite3_filename);+SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename);+SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename); /* ** CAPI3REF: Database File Corresponding To A Journal@@ -3798,14 +3859,14 @@ ** then the corresponding [sqlite3_module.xClose() method should also be ** invoked prior to calling sqlite3_free_filename(Y). */-SQLITE_API char *sqlite3_create_filename(+SQLITE_API sqlite3_filename sqlite3_create_filename( const char *zDatabase, const char *zJournal, const char *zWal, int nParam, const char **azParam );-SQLITE_API void sqlite3_free_filename(char*);+SQLITE_API void sqlite3_free_filename(sqlite3_filename); /* ** CAPI3REF: Error Codes And Messages@@ -5364,10 +5425,21 @@ ** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in ** schema structures such as [CHECK constraints], [DEFAULT clauses], ** [expression indexes], [partial indexes], or [generated columns].-** The SQLITE_DIRECTONLY flags is a security feature which is recommended-** for all [application-defined SQL functions], and especially for functions-** that have side-effects or that could potentially leak sensitive-** information.+** <p>+** The SQLITE_DIRECTONLY flag is recommended for any+** [application-defined SQL function]+** that has side-effects or that could potentially leak sensitive information.+** This will prevent attacks in which an application is tricked+** into using a database file that has had its schema surreptiously+** modified to invoke the application-defined function in ways that are+** harmful.+** <p>+** Some people say it is good practice to set SQLITE_DIRECTONLY on all+** [application-defined SQL functions], regardless of whether or not they+** are security sensitive, as doing so prevents those functions from being used+** inside of the database schema, and thus ensures that the database+** can be inspected and modified using generic tools (such as the [CLI])+** that do not have access to the application-defined functions. ** </dd> ** ** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>@@ -5574,6 +5646,28 @@ SQLITE_API int sqlite3_value_frombind(sqlite3_value*); /*+** CAPI3REF: Report the internal text encoding state of an sqlite3_value object+** METHOD: sqlite3_value+**+** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],+** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding+** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X)+** returns something other than SQLITE_TEXT, then the return value from+** sqlite3_value_encoding(X) is meaningless. ^Calls to+** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)],+** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or+** [sqlite3_value_bytes16(X)] might change the encoding of the value X and+** thus change the return from subsequent calls to sqlite3_value_encoding(X).+**+** This routine is intended for used by applications that test and validate+** the SQLite implementation. This routine is inquiring about the opaque+** internal state of an [sqlite3_value] object. Ordinary applications should+** not need to know what the internal state of an sqlite3_value object is and+** hence should not need to use this interface.+*/+SQLITE_API int sqlite3_value_encoding(sqlite3_value*);++/* ** CAPI3REF: Finding The Subtype Of SQL Values ** METHOD: sqlite3_value **@@ -5593,7 +5687,8 @@ ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a-** memory allocation fails.+** memory allocation fails. ^If V is a [pointer value], then the result+** of sqlite3_value_dup(V) is a NULL value. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer@@ -5624,7 +5719,7 @@ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory-** allocate error occurs.+** allocation error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the@@ -5829,9 +5924,10 @@ ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces.-** ^If the 3rd parameter to the sqlite3_result_text* interfaces-** is negative, then SQLite takes result text from the 2nd parameter-** through the first zero character.+** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces+** other than sqlite3_result_text64() is negative, then SQLite computes+** the string length itself by searching the 2nd parameter for the first+** zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined@@ -6276,6 +6372,28 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /*+** CAPI3REF: Return The Schema Name For A Database Connection+** METHOD: sqlite3+**+** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name+** for the N-th database on database connection D, or a NULL pointer of N is+** out of range. An N value of 0 means the main database file. An N of 1 is+** the "temp" schema. Larger values of N correspond to various ATTACH-ed+** databases.+**+** Space to hold the string that is returned by sqlite3_db_name() is managed+** by SQLite itself. The string might be deallocated by any operation that+** changes the schema, including [ATTACH] or [DETACH] or calls to+** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that+** occur on a different thread. Applications that need to+** remember the string long-term should make their own copy. Applications that+** are accessing the same database connection simultaneously on multiple+** threads should mutex-protect calls to this API and should make their own+** private copy of the result prior to releasing the mutex.+*/+SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);++/* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 **@@ -6305,7 +6423,7 @@ ** <li> [sqlite3_filename_wal()] ** </ul> */-SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);+SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only@@ -6442,7 +6560,7 @@ ** function C that is invoked prior to each autovacuum of the database ** file. ^The callback is passed a copy of the generic data pointer (P), ** the schema-name of the attached database that is being autovacuumed,-** the the size of the database file in pages, the number of free pages,+** the size of the database file in pages, the number of free pages, ** and the number of bytes per page, respectively. The callback should ** return the number of free pages that should be removed by the ** autovacuum. ^If the callback returns zero, then no autovacuum happens.@@ -6563,6 +6681,11 @@ ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false.)^ **+** This interface is omitted if SQLite is compiled with+** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE]+** compile-time option is recommended because the+** [use of shared cache mode is discouraged].+** ** ^Cache sharing is enabled and disabled for an entire process. ** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). ** In prior versions of SQLite,@@ -6661,7 +6784,7 @@ ** ^The soft heap limit may not be greater than the hard heap limit. ** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) ** is invoked with a value of N that is greater than the hard heap limit,-** the the soft heap limit is set to the value of the hard heap limit.+** the soft heap limit is set to the value of the hard heap limit. ** ^The soft heap limit is automatically enabled whenever the hard heap ** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and ** the soft heap limit is outside the range of 1..N, then the soft heap@@ -6923,15 +7046,6 @@ SQLITE_API void sqlite3_reset_auto_extension(void); /*-** The interface to the virtual-table mechanism is currently considered-** to be experimental. The interface might change in incompatible ways.-** If this is a problem for you, do not use the interface at this time.-**-** When the virtual-table mechanism stabilizes, we will declare the-** interface fixed, support it indefinitely, and remove this comment.-*/--/* ** Structures used by the virtual table interface */ typedef struct sqlite3_vtab sqlite3_vtab;@@ -7049,10 +7163,10 @@ ** when the omit flag is true there is no guarantee that the constraint will ** not be checked again using byte code.)^ **-** ^The idxNum and idxPtr values are recorded and passed into the+** ^The idxNum and idxStr values are recorded and passed into the ** [xFilter] method.-** ^[sqlite3_free()] is used to free idxPtr if and only if-** needToFreeIdxPtr is true.+** ^[sqlite3_free()] is used to free idxStr if and only if+** needToFreeIdxStr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate@@ -7172,7 +7286,7 @@ ** the [sqlite3_vtab_collation()] interface. For most real-world virtual ** tables, the collating sequence of constraints does not matter (for example ** because the constraints are numeric) and so the sqlite3_vtab_collation()-** interface is no commonly needed.+** interface is not commonly needed. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4@@ -7332,16 +7446,6 @@ SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /*-** The interface to the virtual-table mechanism defined above (back up-** to a comment remarkably similar to this one) is currently considered-** to be experimental. The interface might change in incompatible ways.-** If this is a problem for you, do not use the interface at this time.-**-** When the virtual-table mechanism stabilizes, we will declare the-** interface fixed, support it indefinitely, and remove this comment.-*/--/* ** CAPI3REF: A Handle To An Open BLOB ** KEYWORDS: {BLOB handle} {BLOB handles} **@@ -8956,7 +9060,7 @@ ** if the application incorrectly accesses the destination [database connection] ** and so no error code is reported, but the operations may malfunction ** nevertheless. Use of the destination database connection while a-** backup is in progress might also also cause a mutex deadlock.+** backup is in progress might also cause a mutex deadlock. ** ** If running in [shared cache mode], the application must ** guarantee that the shared cache used by the destination database@@ -9384,7 +9488,7 @@ */ #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */-#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */+#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ /*@@ -9544,7 +9648,7 @@ ** <li><p> Otherwise, "BINARY" is returned. ** </ol> */-SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);+SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); /* ** CAPI3REF: Determine if a virtual table query is DISTINCT@@ -9554,8 +9658,8 @@ ** of a [virtual table] implementation. The result of calling this ** interface from outside of xBestIndex() is undefined and probably harmful. **-** ^The sqlite3_vtab_distinct() interface returns an integer that is-** either 0, 1, or 2. The integer returned by sqlite3_vtab_distinct()+** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and+** 3. The integer returned by sqlite3_vtab_distinct() ** gives the virtual table additional information about how the query ** planner wants the output to be ordered. As long as the virtual table ** can meet the ordering requirements of the query planner, it may set@@ -9587,6 +9691,13 @@ ** that have the same value for all columns identified by "aOrderBy". ** ^However omitting the extra rows is optional. ** This mode is used for a DISTINCT query.+** <li value="3"><p>+** ^(If the sqlite3_vtab_distinct() interface returns 3, that means+** that the query planner needs only distinct rows but it does need the+** rows to be sorted.)^ ^The virtual table implementation is free to omit+** rows that are identical in all aOrderBy columns, if it wants to, but+** it is not required to omit any rows. This mode is used for queries+** that have both DISTINCT and ORDER BY clauses. ** </ol> ** ** ^For the purposes of comparing virtual table output values to see if the@@ -9694,21 +9805,20 @@ ** is undefined and probably harmful. ** ** The X parameter in a call to sqlite3_vtab_in_first(X,P) or-** sqlite3_vtab_in_next(X,P) must be one of the parameters to the+** sqlite3_vtab_in_next(X,P) should be one of the parameters to the ** xFilter method which invokes these routines, and specifically ** a parameter that was previously selected for all-at-once IN constraint ** processing use the [sqlite3_vtab_in()] interface in the ** [xBestIndex|xBestIndex method]. ^(If the X parameter is not ** an xFilter argument that was selected for all-at-once IN constraint-** processing, then these routines return [SQLITE_MISUSE])^ or perhaps-** exhibit some other undefined or harmful behavior.+** processing, then these routines return [SQLITE_ERROR].)^ ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: ** ** <blockquote><pre> ** for(rc=sqlite3_vtab_in_first(pList, &pVal);-** rc==SQLITE_OK && pVal+** rc==SQLITE_OK && pVal; ** rc=sqlite3_vtab_in_next(pList, &pVal) ** ){ ** // do something with pVal@@ -9806,6 +9916,10 @@ ** managed by the prepared statement S and will be automatically freed when ** S is finalized. **+** Not all values are available for all query elements. When a value is+** not available, the output variable is set to -1 if the value is numeric,+** or to NULL if it is a string (SQLITE_SCANSTAT_NAME).+** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be@@ -9833,12 +9947,24 @@ ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. **-** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>+** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt> ** <dd>^The "int" variable pointed to by the V parameter will be set to the-** "select-id" for the X-th loop. The select-id identifies which query or-** subquery the loop is part of. The main query has a select-id of zero.-** The select-id is the same value as is output in the first column-** of an [EXPLAIN QUERY PLAN] query.+** id for the X-th query plan element. The id value is unique within the+** statement. The select-id is the same value as is output in the first+** column of an [EXPLAIN QUERY PLAN] query.+**+** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt>+** <dd>The "int" variable pointed to by the V parameter will be set to the+** the id of the parent of the current query element, if applicable, or+** to zero if the query element has no parent. This is the same value as+** returned in the second column of an [EXPLAIN QUERY PLAN] query.+**+** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt>+** <dd>The sqlite3_int64 output value is set to the number of cycles,+** according to the processor time-stamp counter, that elapsed while the+** query element was being processed. This value is not available for+** all query elements - if it is unavailable the output variable is+** set to -1. ** </dl> */ #define SQLITE_SCANSTAT_NLOOP 0@@ -9847,12 +9973,14 @@ #define SQLITE_SCANSTAT_NAME 3 #define SQLITE_SCANSTAT_EXPLAIN 4 #define SQLITE_SCANSTAT_SELECTID 5+#define SQLITE_SCANSTAT_PARENTID 6+#define SQLITE_SCANSTAT_NCYCLE 7 /* ** CAPI3REF: Prepared Statement Scan Status ** METHOD: sqlite3_stmt **-** This interface returns information about the predicted and measured+** These interfaces return information about the predicted and measured ** performance for pStmt. Advanced applications can use this ** interface to compare the predicted and the measured performance and ** issue warnings and/or rerun [ANALYZE] if discrepancies are found.@@ -9863,20 +9991,26 @@ ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior-** of this interface is undefined.-** ^The requested measurement is written into a variable pointed to by-** the "pOut" parameter.-** Parameter "idx" identifies the specific loop to retrieve statistics for.-** Loops are numbered starting from zero. ^If idx is out of range - less than-** zero or greater than or equal to the total number of loops used to implement-** the statement - a non-zero value is returned and the variable that pOut-** points to is unchanged.+** of this interface is undefined. ^The requested measurement is written into+** a variable pointed to by the "pOut" parameter. **-** ^Statistics might not be available for all loops in all statements. ^In cases-** where there exist loops with no available statistics, this function behaves-** as if the loop did not exist - it returns non-zero and leave the variable-** that pOut points to unchanged.+** The "flags" parameter must be passed a mask of flags. At present only+** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX+** is specified, then status information is available for all elements+** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If+** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements+** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of+** the EXPLAIN QUERY PLAN output) are available. Invoking API+** sqlite3_stmt_scanstatus() is equivalent to calling+** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter. **+** Parameter "idx" identifies the specific query element to retrieve statistics+** for. Query elements are numbered starting from zero. A value of -1 may be+** to query for statistics regarding the entire query. ^If idx is out of range+** - less than -1 or greater than or equal to the total number of query+** elements used to implement the statement - a non-zero value is returned and+** the variable that pOut points to is unchanged.+** ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus(@@ -9885,8 +10019,21 @@ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ );+SQLITE_API int sqlite3_stmt_scanstatus_v2(+ sqlite3_stmt *pStmt, /* Prepared statement for which info desired */+ int idx, /* Index of loop to report on */+ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */+ int flags, /* Mask of flags defined below */+ void *pOut /* Result written here */+); /*+** CAPI3REF: Prepared Statement Scan Status+** KEYWORDS: {scan status flags}+*/+#define SQLITE_SCANSTAT_COMPLEX 0x0001++/* ** CAPI3REF: Zero Scan-Status Counters ** METHOD: sqlite3_stmt **@@ -9975,6 +10122,10 @@ ** function is not defined for operations on WITHOUT ROWID tables, or for ** DELETE operations on rowid tables. **+** ^The sqlite3_preupdate_hook(D,C,P) function returns the P argument from+** the previous call on the same [database connection] D, or NULL for+** the first call on D.+** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines@@ -10378,6 +10529,19 @@ */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double+#endif++#if defined(__wasi__)+# undef SQLITE_WASI+# define SQLITE_WASI 1+# undef SQLITE_OMIT_WAL+# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */+# ifndef SQLITE_OMIT_LOAD_EXTENSION+# define SQLITE_OMIT_LOAD_EXTENSION+# endif+# ifndef SQLITE_THREADSAFE+# define SQLITE_THREADSAFE 0+# endif #endif #ifdef __cplusplus
cbits/sqlite3ext.h view
@@ -331,9 +331,9 @@ const char *(*filename_journal)(const char*); const char *(*filename_wal)(const char*); /* Version 3.32.0 and later */- char *(*create_filename)(const char*,const char*,const char*,+ const char *(*create_filename)(const char*,const char*,const char*, int,const char**);- void (*free_filename)(char*);+ void (*free_filename)(const char*); sqlite3_file *(*database_file_object)(const char*); /* Version 3.34.0 and later */ int (*txn_state)(sqlite3*,const char*);@@ -351,6 +351,16 @@ int (*vtab_in)(sqlite3_index_info*,int,int); int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);+ /* Version 3.39.0 and later */+ int (*deserialize)(sqlite3*,const char*,unsigned char*,+ sqlite3_int64,sqlite3_int64,unsigned);+ unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,+ unsigned int);+ const char *(*db_name)(sqlite3*,int);+ /* Version 3.40.0 and later */+ int (*value_encoding)(sqlite3_value*);+ /* Version 3.41.0 and later */+ int (*is_interrupted)(sqlite3*); }; /*@@ -669,6 +679,16 @@ #define sqlite3_vtab_in sqlite3_api->vtab_in #define sqlite3_vtab_in_first sqlite3_api->vtab_in_first #define sqlite3_vtab_in_next sqlite3_api->vtab_in_next+/* Version 3.39.0 and later */+#ifndef SQLITE_OMIT_DESERIALIZE+#define sqlite3_deserialize sqlite3_api->deserialize+#define sqlite3_serialize sqlite3_api->serialize+#endif+#define sqlite3_db_name sqlite3_api->db_name+/* Version 3.40.0 and later */+#define sqlite3_value_encoding sqlite3_api->value_encoding+/* Version 3.41.0 and later */+#define sqlite3_is_interrupted sqlite3_api->is_interrupted #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
changelog view
@@ -1,3 +1,6 @@+v2.3.28:+ * Upgrade embedded sqlite library to 3.41.0.+ v2.3.27: * Add support for up to GHC 9.2 * Upgrade embedded sqlite library to 3.38.5.
direct-sqlite.cabal view
@@ -1,5 +1,5 @@ name: direct-sqlite-version: 2.3.27+version: 2.3.28 synopsis: Low-level binding to SQLite3. Includes UTF8 and BLOB support. description: This package is not very different from the other SQLite3 bindings out there, but it fixes a few deficiencies I was finding. As compared to@@ -54,15 +54,12 @@ Database.SQLite3.Bindings Database.SQLite3.Bindings.Types Database.SQLite3.Direct- build-depends: base >= 4.1 && < 5+ build-depends: base >= 4.11 && < 5 , bytestring >= 0.9.2.1 , text >= 0.11 default-language: Haskell2010 include-dirs: . ghc-options: -Wall -fwarn-tabs-- if impl(ghc < 8.0)- build-depends: semigroups >= 0.18 && < 0.20 if flag(systemlib) extra-libraries: sqlite3
test/Main.hs view
@@ -3,13 +3,14 @@ import Database.SQLite3 import qualified Database.SQLite3.Direct as Direct +import Control.Applicative import Control.Concurrent import Control.Exception-import Control.Monad (forM_, liftM3, when)+import Control.Monad (forM_, liftM3, unless)+import Data.Functor.Identity import Data.Text (Text) import Data.Text.Encoding.Error (UnicodeException(..)) import Data.Typeable-import Data.Monoid import System.Directory () import System.Exit (exitFailure) import System.IO@@ -23,7 +24,7 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T -data TestEnv =+data TestEnv f = TestEnv { conn :: Database -- ^ Database shared by all the tests@@ -32,10 +33,14 @@ -- This connection will be isolated from others. , withConnShared :: forall a. (Database -> IO a) -> IO a -- ^ Like 'withConn', but every invocation shares the same database.+ , withConnReadOnly :: forall a. f ((Database -> IO a) -> IO a)+ -- ^ Like 'withConn', but every invocation shares the same read-only database. } -regressionTests :: [TestEnv -> Test]-regressionTests =+type WithRoTestEnv = TestEnv Identity++regressionTests1 :: forall f. [TestEnv f -> Test]+regressionTests1 = [ TestLabel "Exec" . testExec , TestLabel "ExecCallback" . testExecCallback , TestLabel "Simple" . testSimplest@@ -61,12 +66,15 @@ , TestLabel "CustomAggr" . testCustomAggragate , TestLabel "CustomColl" . testCustomCollation , TestLabel "IncrBlobIO" . testIncrementalBlobIO- ] ++- (if rtsSupportsBoundThreads then- [ TestLabel "Interrupt" . testInterrupt- ] else [])+ ] <>+ [ TestLabel "Interrupt" . testInterrupt | rtsSupportsBoundThreads ] -featureTests :: [TestEnv -> Test]++regressionTests2 :: [WithRoTestEnv -> Test]+regressionTests2 = regressionTests1 <> [TestLabel "ReadOnly" . testReadOnly]+++featureTests :: forall f. [TestEnv f -> Test] featureTests = [ TestLabel "MultiRowInsert" . testMultiRowInsert ]@@ -87,7 +95,7 @@ withStmt :: Database -> Text -> (Statement -> IO a) -> IO a withStmt conn sql = bracket (prepare conn sql) finalize -testExec :: TestEnv -> Test+testExec :: forall f. TestEnv f -> Test testExec TestEnv{..} = TestCase $ do exec conn "" exec conn " "@@ -107,7 +115,7 @@ \INSERT INTO foo VALUES (null, ''); \ \INSERT INTO foo VALUES (null, 'null'); \ \INSERT INTO foo VALUES (null, null)"- withStmt conn ("SELECT * FROM foo") $ \stmt -> do+ withStmt conn "SELECT * FROM foo" $ \stmt -> do Row <- step stmt [SQLFloat 3.5, SQLNull] <- columns stmt Row <- step stmt@@ -121,12 +129,19 @@ Done <- step stmt return () +testReadOnly :: WithRoTestEnv -> Test+testReadOnly TestEnv{..} = TestCase $ do+ let reqCreate = "CREATE TABLE readonly (n FLOAT, t TEXT);"+ runIdentity withConnReadOnly $ \conn -> do+ Left SQLError{sqlError = ErrorReadOnly} <- try $ exec conn reqCreate+ return ()+ data Ex = Ex deriving (Show, Typeable) instance Exception Ex -testExecCallback :: TestEnv -> Test+testExecCallback :: forall f. TestEnv f -> Test testExecCallback TestEnv{..} = TestCase $ withConn $ \conn -> do chan <- newChan@@ -163,11 +178,11 @@ return () -testTracing :: TestEnv -> Test+testTracing :: forall f. TestEnv f -> Test testTracing TestEnv{..} = TestCase $ withConn $ \conn -> do chan <- newChan- let logger m = writeChan chan m+ let logger = writeChan chan Direct.setTrace conn (Just logger) withStmt conn "SELECT null" $ \stmt -> do Row <- step stmt@@ -200,7 +215,7 @@ -- Simplest SELECT-testSimplest :: TestEnv -> Test+testSimplest :: forall f. TestEnv f -> Test testSimplest TestEnv{..} = TestCase $ do stmt <- prepare conn "SELECT 1+1" Row <- step stmt@@ -209,7 +224,7 @@ finalize stmt assertEqual "1+1" (SQLInteger 2) res -testPrepare :: TestEnv -> Test+testPrepare :: forall f. TestEnv f -> Test testPrepare TestEnv{..} = TestCase $ do True <- shouldFail $ prepare conn "" True <- shouldFail $ prepare conn ";"@@ -237,15 +252,15 @@ exec conn "COMMIT" return () -testCloseBusy :: TestEnv -> Test+testCloseBusy :: forall f. TestEnv f -> Test testCloseBusy _ = TestCase $ do- conn <- open ":memory:"+ conn <- open2 ":memory:" [SQLOpenReadWrite, SQLOpenCreate] SQLVFSDefault stmt <- prepare conn "SELECT 1" Left SQLError{sqlError = ErrorBusy} <- try $ close conn finalize stmt close conn -testBind :: TestEnv -> Test+testBind :: forall f. TestEnv f -> Test testBind TestEnv{..} = TestCase $ do bracket (prepare conn "SELECT ?") finalize testBind1 bracket (prepare conn "SELECT ?+?") finalize testBind2@@ -278,7 +293,7 @@ assertEqual "blob vs. zeroblob" [SQLBlob bs, SQLBlob bs] res -- Test bindParameterCount-testBindParamCounts :: TestEnv -> Test+testBindParamCounts :: forall f. TestEnv f -> Test testBindParamCounts TestEnv{..} = TestCase $ do testCase "single $a" "SELECT $a" 1 testCase "3 unique ?NNNs" "SELECT (?1+?1+?1+?2+?3)" 3@@ -295,7 +310,7 @@ >>= assertEqual label expected -- Test bindParameterName-testBindParamName :: TestEnv -> Test+testBindParamName :: forall f. TestEnv f -> Test testBindParamName TestEnv{..} = TestCase $ do bracket (prepare conn "SELECT :v + :v2") finalize (testNames [Just ":v", Just ":v2"]) bracket (prepare conn "SELECT ?1 + ?1") finalize (testNames [Just "?1"])@@ -310,7 +325,7 @@ name <- bindParameterName stmt ndx assertEqual "name match" expecting name) $ zip [1..] names -testBindErrorValidation :: TestEnv -> Test+testBindErrorValidation :: forall f. TestEnv f -> Test testBindErrorValidation TestEnv{..} = TestCase $ do bracket (prepare conn "SELECT ?") finalize (assertFail . testException1) bracket (prepare conn "SELECT ?") finalize (assertFail . testException2)@@ -320,7 +335,7 @@ -- Invalid use, one param in q string, 2 given testException2 stmt = bind stmt [SQLInteger 1, SQLInteger 2] -testNamedBindParams :: TestEnv -> Test+testNamedBindParams :: forall f. TestEnv f -> Test testNamedBindParams TestEnv{..} = TestCase $ do withConn $ \conn -> do withStmt conn "SELECT :foo / :bar" $ \stmt -> do@@ -353,7 +368,7 @@ Done <- step stmt return () -testColumns :: TestEnv -> Test+testColumns :: forall f. TestEnv f -> Test testColumns TestEnv{..} = TestCase $ do withConn $ \conn -> do withStmt conn "CREATE TABLE foo (a INT)" command@@ -409,7 +424,7 @@ 0 <- columnCount stmt return () -testTypedColumns :: TestEnv -> Test+testTypedColumns :: forall f. TestEnv f -> Test testTypedColumns TestEnv{..} = TestCase $ do withConn $ \conn -> do withStmt conn "CREATE TABLE foo (a INT, b INT)" command@@ -442,7 +457,7 @@ 0 <- columnCount stmt return () -testColumnName :: TestEnv -> Test+testColumnName :: forall f. TestEnv f -> Test testColumnName TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE foo (id INTEGER PRIMARY KEY, abc TEXT, \"123\" REAL, über INT)"@@ -491,12 +506,12 @@ -- * ErrorLocked -- * ErrorBusy-testErrors :: TestEnv -> Test+testErrors :: forall f. TestEnv f -> Test testErrors TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE foo (n INT UNIQUE)" exec conn "INSERT INTO foo VALUES (3)"- expectError ErrorConstraint $+ expectError conn ErrorConstraint ErrorConstraintUnique $ exec conn "INSERT INTO foo VALUES (3)" -- Multiple NULLs are allowed when there's a UNIQUE constraint@@ -504,13 +519,13 @@ exec conn "INSERT INTO foo VALUES (null)" exec conn "CREATE TABLE bar (n INT NOT NULL)"- expectError ErrorConstraint $+ expectError conn ErrorConstraint ErrorConstraintNotNull$ exec conn "INSERT INTO bar VALUES (null)" withStmt conn "SELECT ?" $ \stmt -> do forM_ [-1, 0, 2] $ \i -> do- expectError ErrorRange $ bindSQLData stmt i $ SQLInteger 42- expectError ErrorRange $ bindSQLData stmt i SQLNull+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull bindSQLData stmt 1 $ SQLInteger 42 Row <- step stmt @@ -524,8 +539,8 @@ withStmt conn "SELECT 1" $ \stmt -> do forM_ [-1, 0, 1, 2] $ \i -> do- expectError ErrorRange $ bindSQLData stmt i $ SQLInteger 42- expectError ErrorRange $ bindSQLData stmt i SQLNull+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull bind stmt [] -- This should succeed. Don't whine that there aren't any -- parameters to bind! Row <- step stmt@@ -541,8 +556,8 @@ withStmt conn "SELECT ?5" $ \stmt -> do forM_ [-1, 0, 6, 7] $ \i -> do- expectError ErrorRange $ bindSQLData stmt i $ SQLInteger 42- expectError ErrorRange $ bindSQLData stmt i SQLNull+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42+ expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull bind stmt $ map SQLInteger [1..5] -- This succeeds, even though 1..4 aren't used. Row <- step stmt@@ -565,14 +580,14 @@ [SQLInteger 1, SQLInteger 2] <- columns stmt -- "DROP TABLE foo" should fail, now that the statement is running.- expectError ErrorLocked $ exec conn "DROP TABLE foo"+ expectError conn ErrorLocked ErrorLocked $ exec conn "DROP TABLE foo" withConnShared $ \conn -> do- expectError ErrorBusy $ exec conn "DROP TABLE foo"+ expectError conn ErrorBusy ErrorBusy $ exec conn "DROP TABLE foo" -- Apparently, we can pretend to drop the table, but we get ErrorBusy -- if we try to actually COMMIT it. exec conn "BEGIN; DROP TABLE foo"- expectError ErrorBusy $ exec conn "COMMIT"+ expectError conn ErrorBusy ErrorBusy $ exec conn "COMMIT" exec conn "ROLLBACK" @@ -583,9 +598,9 @@ 2 <- columnCount stmt [SQLInteger 5, SQLInteger 6] <- columns stmt - expectError ErrorLocked $ exec conn "DROP TABLE foo"+ expectError conn ErrorLocked ErrorLocked $ exec conn "DROP TABLE foo" withConnShared $ \conn ->- expectError ErrorBusy $ exec conn "DROP TABLE foo"+ expectError conn ErrorBusy ErrorBusy $ exec conn "DROP TABLE foo" Done <- step stmt 2 <- columnCount stmt@@ -603,9 +618,13 @@ err == ErrorSchema) -- SQLite 3.6.22 where- expectError err io = do+ expectError conn err extendedErr io = do Left SQLError{sqlError = err'} <- try io- assertEqual "testErrors: expectError" err err'+ assertEqual "testErrors: expectExtError" err err'+ err' <- Direct.errcode conn+ assertEqual "testErrors: expectExtError errcode" err err'+ extendedErr' <- Direct.extendedErrcode conn+ assertEqual "testErrors: expectExtError extendedErrcode" extendedErr extendedErr' foo123456 conn = exec conn "CREATE TABLE foo (a INT, b INT); \@@ -614,7 +633,7 @@ \INSERT INTO foo VALUES (5, 6)" -- Make sure data stored in a table comes back as-is.-testIntegrity :: TestEnv -> Test+testIntegrity :: forall f. TestEnv f -> Test testIntegrity TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE foo (i INT, f FLOAT, t TEXT, b BLOB, n TEXT)"@@ -638,7 +657,7 @@ True <- test [SQLInteger 0, SQLFloat 0.0, SQLText T.empty, SQLBlob B.empty, SQLNull] True <- test [SQLInteger minBound, SQLFloat (-1/0), SQLText "\0", SQLBlob (B8.pack "\0"), SQLNull]- True <- test [SQLInteger maxBound, SQLFloat (1/0), SQLText "\1114111", SQLBlob ("\255"), SQLNull]+ True <- test [SQLInteger maxBound, SQLFloat (1/0), SQLText "\1114111", SQLBlob "\255", SQLNull] -- SQLite3 turns NaN into SQLNull. True <- testWith (\_old new -> new === [SQLNull, SQLNull, SQLNull, SQLNull, SQLNull])@@ -646,7 +665,7 @@ return () -testDecodeError :: TestEnv -> Test+testDecodeError :: forall f. TestEnv f -> Test testDecodeError TestEnv{..} = TestCase $ do withStmt conn "SELECT ?" $ \stmt -> do Right () <- Direct.bindText stmt 1 invalidUtf8@@ -677,7 +696,7 @@ where invalidUtf8 = Direct.Utf8 $ B.pack [0x80] -testResultStats :: TestEnv -> Test+testResultStats :: forall f. TestEnv f -> Test testResultStats TestEnv{..} = TestCase $ withConn $ \conn -> do (0, 0, 0) <- stats conn@@ -705,7 +724,7 @@ (changes conn) (Direct.totalChanges conn) -testGetAutoCommit :: TestEnv -> Test+testGetAutoCommit :: forall f. TestEnv f -> Test testGetAutoCommit TestEnv{..} = TestCase $ withConn $ \conn -> do True <- Direct.getAutoCommit conn@@ -721,14 +740,14 @@ return () -testStatementSql :: TestEnv -> Test+testStatementSql :: forall f. TestEnv f -> Test testStatementSql TestEnv{..} = TestCase $ do let q1 = "SELECT 1+1" withStmt conn q1 $ \stmt -> do Just (Direct.Utf8 sql1) <- Direct.statementSql stmt T.encodeUtf8 q1 @=? sql1 -testCustomFunction :: TestEnv -> Test+testCustomFunction :: forall f. TestEnv f -> Test testCustomFunction TestEnv{..} = TestCase $ do withConn $ \conn -> do createFunction conn "repeat" (Just 2) True repeatString@@ -747,7 +766,7 @@ s <- funcArgText args 1 funcResultText ctx $ T.concat $ replicate (fromIntegral n) s -testCustomFunctionError :: TestEnv -> Test+testCustomFunctionError :: forall f. TestEnv f -> Test testCustomFunctionError TestEnv{..} = TestCase $ do withConn $ \conn -> do createFunction conn "fail" (Just 0) True throwError@@ -760,7 +779,7 @@ where throwError _ _ = error "error message" -testCustomAggragate :: TestEnv -> Test+testCustomAggragate :: forall f. TestEnv f -> Test testCustomAggragate TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE tbl (n INT)"@@ -780,7 +799,7 @@ n <- funcArgInt64 args 0 return (s + n) -testCustomCollation :: TestEnv -> Test+testCustomCollation :: forall f. TestEnv f -> Test testCustomCollation TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE tbl (n TEXT)"@@ -805,7 +824,7 @@ -- order by length first, then by lexicographical order cmpLen s1 s2 = compare (T.length s1) (T.length s2) <> compare s1 s2 -testIncrementalBlobIO :: TestEnv -> Test+testIncrementalBlobIO :: forall f. TestEnv f -> Test testIncrementalBlobIO TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE tbl (n BLOB)"@@ -822,7 +841,7 @@ s' <- columnBlob stmt 0 assertEqual "blobWrite" "aBCdefg" s' -testInterrupt :: TestEnv -> Test+testInterrupt :: forall f. TestEnv f -> Test testInterrupt TestEnv{..} = TestCase $ withConn $ \conn -> do exec conn "CREATE TABLE tbl (n INT)"@@ -848,7 +867,7 @@ where tripleSum = "SELECT sum(a.n + b.n + c.n) FROM tbl as a, tbl as b, tbl as c" -testMultiRowInsert :: TestEnv -> Test+testMultiRowInsert :: forall f. TestEnv f -> Test testMultiRowInsert TestEnv{..} = TestCase $ do withConn $ \conn -> do exec conn "CREATE TABLE foo (a INT, b INT)"@@ -869,14 +888,14 @@ Done <- step stmt return () --withTestEnv :: String -> (TestEnv -> IO a) -> IO a-withTestEnv tempDbName cb =+withTestEnv1 :: String -> (forall f. TestEnv f -> IO a) -> IO a+withTestEnv1 tempDbName cb = withConn $ \conn -> cb TestEnv- { conn = conn- , withConn = withConn- , withConnShared = withConnPath (T.pack tempDbName)+ { conn = conn+ , withConn = withConn+ , withConnShared = withConnPath (T.pack tempDbName)+ , withConnReadOnly = Const () } where withConn = withConnPath ":memory:"@@ -890,20 +909,60 @@ close conn return r -runTestGroup :: String -> [TestEnv -> Test] -> IO Bool-runTestGroup tempDbName tests = do+withTestEnv2 :: String -> (WithRoTestEnv -> IO a) -> IO a+withTestEnv2 tempDbName cb =+ withConn $ \conn ->+ cb TestEnv+ { conn = conn+ , withConn = withConn+ , withConnShared = withConnPath (T.pack tempDbName)+ [SQLOpenReadWrite, SQLOpenCreate]+ , withConnReadOnly = Identity $ withConnPath (T.pack tempDbName)+ [SQLOpenReadOnly]+ }+ where+ withConn = withConnPath ":memory:" [SQLOpenReadWrite, SQLOpenCreate]+ withConnPath path flags cb = do+ conn <- open2 path flags SQLVFSDefault+ r <- cb conn `onException` Direct.close conn+ -- If the callback throws an exception, try to close the DB.+ -- If closing fails (usually due to open 'Statement's),+ -- throw the original error, not the error produced by 'close'.+ -- Direct.close returns the error rather than throwing it.+ close conn+ return r++runTestGroup1 :: String -> (forall f. [TestEnv f -> Test]) -> IO Bool+runTestGroup1 tempDbName tests = do Counts{cases, tried, errors, failures} <-- withTestEnv tempDbName $ \env -> runTestTT $ TestList $ map ($ env) tests+ withTestEnv1 tempDbName $ \env -> runTestTT $ TestList $ map ($ env) tests return (cases == tried && errors == 0 && failures == 0) +runTestGroup2 :: String -> [WithRoTestEnv -> Test] -> IO Bool+runTestGroup2 tempDbName tests = do+ Counts{cases, tried, errors, failures} <-+ withTestEnv2 tempDbName $ \env -> runTestTT $ TestList $ map ($ env) tests+ return (cases == tried && errors == 0 && failures == 0)+ main :: IO () main = do mapM_ (`hSetBuffering` LineBuffering) [stdout, stderr] withTempFile "." "direct-sqlite-test-database" $ \tempDbName _hFile -> do open (T.pack tempDbName) >>= close- ok <- runTestGroup tempDbName regressionTests- when (not ok) exitFailure+ ok <- runTestGroup1 tempDbName regressionTests1+ unless ok exitFailure -- Signal failure if feature tests fail. I'd rather print a noisy warning -- instead, but cabal redirects test output to log files by default.- ok <- runTestGroup tempDbName featureTests- when (not ok) exitFailure+ ok <- runTestGroup1 tempDbName featureTests+ unless ok exitFailure+ withTempFile "." "direct-sqlite-test-database" $ \tempDbName _hFile -> do+ open2 (T.pack tempDbName)+ [SQLOpenReadWrite, SQLOpenCreate]+ SQLVFSDefault+ >>= close+ ok <- runTestGroup2 tempDbName regressionTests2+ unless ok exitFailure+ -- Signal failure if feature tests fail. I'd rather print a noisy warning+ -- instead, but cabal redirects test output to log files by default.+ ok <- runTestGroup1 tempDbName featureTests+ unless ok exitFailure