packages feed

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 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> ** &nbsp;  for(rc=sqlite3_vtab_in_first(pList, &pVal);-** &nbsp;      rc==SQLITE_OK && pVal+** &nbsp;      rc==SQLITE_OK && pVal; ** &nbsp;      rc=sqlite3_vtab_in_next(pList, &pVal) ** &nbsp;  ){ ** &nbsp;    // 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