direct-sqlite 2.3 → 2.3.1
raw patch · 8 files changed
+336/−76 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Database.SQLite3: interrupt :: Database -> IO ()
+ Database.SQLite3.Bindings: c_sqlite3_interrupt :: Ptr CDatabase -> IO ()
+ Database.SQLite3.Bindings.Types: CColumnIndex :: CInt -> CColumnIndex
+ Database.SQLite3.Bindings.Types: CParamIndex :: CInt -> CParamIndex
+ Database.SQLite3.Bindings.Types: class FFIType public ffi | public -> ffi, ffi -> public
+ Database.SQLite3.Bindings.Types: encodeColumnType :: ColumnType -> CColumnType
+ Database.SQLite3.Bindings.Types: encodeError :: Error -> CError
+ Database.SQLite3.Bindings.Types: fromFFI :: FFIType public ffi => ffi -> public
+ Database.SQLite3.Bindings.Types: instance Enum CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Enum CParamIndex
+ Database.SQLite3.Bindings.Types: instance Eq CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Eq CColumnType
+ Database.SQLite3.Bindings.Types: instance Eq CError
+ Database.SQLite3.Bindings.Types: instance Eq CParamIndex
+ Database.SQLite3.Bindings.Types: instance FFIType ColumnIndex CColumnIndex
+ Database.SQLite3.Bindings.Types: instance FFIType ColumnType CColumnType
+ Database.SQLite3.Bindings.Types: instance FFIType Error CError
+ Database.SQLite3.Bindings.Types: instance FFIType ParamIndex CParamIndex
+ Database.SQLite3.Bindings.Types: instance Integral CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Integral CParamIndex
+ Database.SQLite3.Bindings.Types: instance Num CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Num CParamIndex
+ Database.SQLite3.Bindings.Types: instance Ord CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Ord CParamIndex
+ Database.SQLite3.Bindings.Types: instance Real CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Real CParamIndex
+ Database.SQLite3.Bindings.Types: instance Show CColumnIndex
+ Database.SQLite3.Bindings.Types: instance Show CParamIndex
+ Database.SQLite3.Bindings.Types: newtype CColumnIndex
+ Database.SQLite3.Bindings.Types: newtype CParamIndex
+ Database.SQLite3.Bindings.Types: toFFI :: FFIType public ffi => public -> ffi
+ Database.SQLite3.Bindings.Types: type CColumnCount = CColumnIndex
+ Database.SQLite3.Direct: interrupt :: Database -> IO ()
- Database.SQLite3: ColumnIndex :: CInt -> ColumnIndex
+ Database.SQLite3: ColumnIndex :: Int -> ColumnIndex
- Database.SQLite3: ParamIndex :: CInt -> ParamIndex
+ Database.SQLite3: ParamIndex :: Int -> ParamIndex
- Database.SQLite3.Bindings: c_sqlite3_bind_blob :: Ptr CStatement -> ParamIndex -> Ptr a -> CNumBytes -> Ptr CDestructor -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_bind_blob :: Ptr CStatement -> CParamIndex -> Ptr a -> CNumBytes -> Ptr CDestructor -> IO CError
- Database.SQLite3.Bindings: c_sqlite3_bind_double :: Ptr CStatement -> ParamIndex -> Double -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_bind_double :: Ptr CStatement -> CParamIndex -> Double -> IO CError
- Database.SQLite3.Bindings: c_sqlite3_bind_int64 :: Ptr CStatement -> ParamIndex -> Int64 -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_bind_int64 :: Ptr CStatement -> CParamIndex -> Int64 -> IO CError
- Database.SQLite3.Bindings: c_sqlite3_bind_null :: Ptr CStatement -> ParamIndex -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_bind_null :: Ptr CStatement -> CParamIndex -> IO CError
- Database.SQLite3.Bindings: c_sqlite3_bind_parameter_count :: Ptr CStatement -> IO ParamIndex
+ Database.SQLite3.Bindings: c_sqlite3_bind_parameter_count :: Ptr CStatement -> IO CParamIndex
- Database.SQLite3.Bindings: c_sqlite3_bind_parameter_name :: Ptr CStatement -> ParamIndex -> IO CString
+ Database.SQLite3.Bindings: c_sqlite3_bind_parameter_name :: Ptr CStatement -> CParamIndex -> IO CString
- Database.SQLite3.Bindings: c_sqlite3_bind_text :: Ptr CStatement -> ParamIndex -> CString -> CNumBytes -> Ptr CDestructor -> IO CError
+ Database.SQLite3.Bindings: c_sqlite3_bind_text :: Ptr CStatement -> CParamIndex -> CString -> CNumBytes -> Ptr CDestructor -> IO CError
- Database.SQLite3.Bindings: c_sqlite3_column_blob :: Ptr CStatement -> ColumnIndex -> IO (Ptr a)
+ Database.SQLite3.Bindings: c_sqlite3_column_blob :: Ptr CStatement -> CColumnIndex -> IO (Ptr a)
- Database.SQLite3.Bindings: c_sqlite3_column_bytes :: Ptr CStatement -> ColumnIndex -> IO CNumBytes
+ Database.SQLite3.Bindings: c_sqlite3_column_bytes :: Ptr CStatement -> CColumnIndex -> IO CNumBytes
- Database.SQLite3.Bindings: c_sqlite3_column_count :: Ptr CStatement -> IO ColumnCount
+ Database.SQLite3.Bindings: c_sqlite3_column_count :: Ptr CStatement -> IO CColumnCount
- Database.SQLite3.Bindings: c_sqlite3_column_double :: Ptr CStatement -> ColumnIndex -> IO Double
+ Database.SQLite3.Bindings: c_sqlite3_column_double :: Ptr CStatement -> CColumnIndex -> IO Double
- Database.SQLite3.Bindings: c_sqlite3_column_int64 :: Ptr CStatement -> ColumnIndex -> IO Int64
+ Database.SQLite3.Bindings: c_sqlite3_column_int64 :: Ptr CStatement -> CColumnIndex -> IO Int64
- Database.SQLite3.Bindings: c_sqlite3_column_text :: Ptr CStatement -> ColumnIndex -> IO CString
+ Database.SQLite3.Bindings: c_sqlite3_column_text :: Ptr CStatement -> CColumnIndex -> IO CString
- Database.SQLite3.Bindings: c_sqlite3_column_type :: Ptr CStatement -> ColumnIndex -> IO CColumnType
+ Database.SQLite3.Bindings: c_sqlite3_column_type :: Ptr CStatement -> CColumnIndex -> IO CColumnType
- Database.SQLite3.Bindings: type CExecCallback a = Ptr a -> ColumnCount -> Ptr CString -> Ptr CString -> CInt
+ Database.SQLite3.Bindings: type CExecCallback a = Ptr a -> CColumnCount -> Ptr CString -> Ptr CString -> CInt
- Database.SQLite3.Bindings.Types: ColumnIndex :: CInt -> ColumnIndex
+ Database.SQLite3.Bindings.Types: ColumnIndex :: Int -> ColumnIndex
- Database.SQLite3.Bindings.Types: ParamIndex :: CInt -> ParamIndex
+ Database.SQLite3.Bindings.Types: ParamIndex :: Int -> ParamIndex
- Database.SQLite3.Direct: ColumnIndex :: CInt -> ColumnIndex
+ Database.SQLite3.Direct: ColumnIndex :: Int -> ColumnIndex
- Database.SQLite3.Direct: ParamIndex :: CInt -> ParamIndex
+ Database.SQLite3.Direct: ParamIndex :: Int -> ParamIndex
Files
- Database/SQLite3.hs +4/−0
- Database/SQLite3/Bindings.hs +20/−15
- Database/SQLite3/Bindings/Types.hsc +100/−4
- Database/SQLite3/Direct.hs +29/−15
- cbits/sqlite3.c too large to diff
- cbits/sqlite3.h +133/−28
- direct-sqlite.cabal +11/−6
- test/Main.hs +39/−8
Database/SQLite3.hs view
@@ -45,6 +45,9 @@ columnText, columnBlob, + -- * Interrupting a long-running query+ interrupt,+ -- * Types Database, Statement,@@ -76,6 +79,7 @@ -- Re-exported from Database.SQLite3.Direct without modification. -- Note that if this module were in another package, source links would not -- be generated for these functions.+ , interrupt , clearBindings , bindParameterCount , columnCount
Database/SQLite3/Bindings.hs view
@@ -6,6 +6,7 @@ c_sqlite3_open, c_sqlite3_close, c_sqlite3_errmsg,+ c_sqlite3_interrupt, -- * Simple query execution -- | <http://sqlite.org/c3ref/exec.html>@@ -67,7 +68,11 @@ foreign import ccall "sqlite3_errmsg" c_sqlite3_errmsg :: Ptr CDatabase -> IO CString +-- | <http://www.sqlite.org/c3ref/interrupt.html>+foreign import ccall "sqlite3_interrupt"+ c_sqlite3_interrupt :: Ptr CDatabase -> IO () + foreign import ccall "sqlite3_exec" c_sqlite3_exec :: Ptr CDatabase@@ -79,7 +84,7 @@ type CExecCallback a = Ptr a- -> ColumnCount -- ^ Number of columns, which is the number of elements in+ -> CColumnCount -- ^ Number of columns, which is the number of elements in -- the following arrays. -> Ptr CString -- ^ Array of column names -> Ptr CString -- ^ Array of column values, as returned by@@ -150,21 +155,21 @@ -- necessarily the number of parameters. If numbered parameters like @?5@ -- are used, there may be gaps in the list. foreign import ccall unsafe "sqlite3_bind_parameter_count"- c_sqlite3_bind_parameter_count :: Ptr CStatement -> IO ParamIndex+ c_sqlite3_bind_parameter_count :: Ptr CStatement -> IO CParamIndex -- | <http://www.sqlite.org/c3ref/bind_parameter_name.html> foreign import ccall unsafe "sqlite3_bind_parameter_name"- c_sqlite3_bind_parameter_name :: Ptr CStatement -> ParamIndex -> IO CString+ c_sqlite3_bind_parameter_name :: Ptr CStatement -> CParamIndex -> IO CString -- | <http://www.sqlite.org/c3ref/column_count.html> foreign import ccall unsafe "sqlite3_column_count"- c_sqlite3_column_count :: Ptr CStatement -> IO ColumnCount+ c_sqlite3_column_count :: Ptr CStatement -> IO CColumnCount foreign import ccall unsafe "sqlite3_bind_blob" c_sqlite3_bind_blob :: Ptr CStatement- -> ParamIndex -- ^ Index of the SQL parameter to be set+ -> CParamIndex -- ^ Index of the SQL parameter to be set -> Ptr a -- ^ Value to bind to the parameter. -- -- /Warning:/ If this pointer is @NULL@, this@@ -176,7 +181,7 @@ foreign import ccall unsafe "sqlite3_bind_text" c_sqlite3_bind_text :: Ptr CStatement- -> ParamIndex+ -> CParamIndex -> CString -- ^ /Warning:/ If this pointer is @NULL@, this -- will bind a null value, rather than an empty text. -> CNumBytes -- ^ Length, in bytes. If this is negative,@@ -185,32 +190,32 @@ -> IO CError foreign import ccall unsafe "sqlite3_bind_double"- c_sqlite3_bind_double :: Ptr CStatement -> ParamIndex -> Double -> IO CError+ c_sqlite3_bind_double :: Ptr CStatement -> CParamIndex -> Double -> IO CError foreign import ccall unsafe "sqlite3_bind_int64"- c_sqlite3_bind_int64 :: Ptr CStatement -> ParamIndex -> Int64 -> IO CError+ c_sqlite3_bind_int64 :: Ptr CStatement -> CParamIndex -> Int64 -> IO CError foreign import ccall unsafe "sqlite3_bind_null"- c_sqlite3_bind_null :: Ptr CStatement -> ParamIndex -> IO CError+ c_sqlite3_bind_null :: Ptr CStatement -> CParamIndex -> IO CError foreign import ccall unsafe "sqlite3_column_type"- c_sqlite3_column_type :: Ptr CStatement -> ColumnIndex -> IO CColumnType+ c_sqlite3_column_type :: Ptr CStatement -> CColumnIndex -> IO CColumnType foreign import ccall unsafe "sqlite3_column_bytes"- c_sqlite3_column_bytes :: Ptr CStatement -> ColumnIndex -> IO CNumBytes+ c_sqlite3_column_bytes :: Ptr CStatement -> CColumnIndex -> IO CNumBytes foreign import ccall unsafe "sqlite3_column_blob"- c_sqlite3_column_blob :: Ptr CStatement -> ColumnIndex -> IO (Ptr a)+ c_sqlite3_column_blob :: Ptr CStatement -> CColumnIndex -> IO (Ptr a) foreign import ccall unsafe "sqlite3_column_text"- c_sqlite3_column_text :: Ptr CStatement -> ColumnIndex -> IO CString+ c_sqlite3_column_text :: Ptr CStatement -> CColumnIndex -> IO CString foreign import ccall unsafe "sqlite3_column_int64"- c_sqlite3_column_int64 :: Ptr CStatement -> ColumnIndex -> IO Int64+ c_sqlite3_column_int64 :: Ptr CStatement -> CColumnIndex -> IO Int64 foreign import ccall unsafe "sqlite3_column_double"- c_sqlite3_column_double :: Ptr CStatement -> ColumnIndex -> IO Double+ c_sqlite3_column_double :: Ptr CStatement -> CColumnIndex -> IO Double -- | <http://sqlite.org/c3ref/free.html>
Database/SQLite3/Bindings/Types.hsc view
@@ -1,4 +1,6 @@ {-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Database.SQLite3.Bindings.Types ( -- * Objects@@ -11,11 +13,13 @@ -- ** Error CError(..), decodeError,+ encodeError, Error(..), -- ** ColumnType CColumnType(..), decodeColumnType,+ encodeColumnType, ColumnType(..), -- * Indices@@ -23,10 +27,18 @@ ColumnIndex(..), ColumnCount, + -- ** Indices (FFI)+ CParamIndex(..),+ CColumnIndex(..),+ CColumnCount,+ -- * Miscellaneous CNumBytes(..), CDestructor, c_SQLITE_TRANSIENT,++ -- * Conversion to and from FFI types+ FFIType(..), ) where #ifdef direct_sqlite_systemlib@@ -105,7 +117,7 @@ -- -- See <http://www.sqlite.org/lang_expr.html#varparam> for the syntax of -- parameter placeholders, and how parameter indices are assigned.-newtype ParamIndex = ParamIndex CInt+newtype ParamIndex = ParamIndex Int deriving (Eq, Ord, Enum, Num, Real, Integral) -- | This just shows the underlying integer, without the data constructor.@@ -113,7 +125,7 @@ show (ParamIndex n) = show n -- | Index of a column in a result set. Column indices start from 0.-newtype ColumnIndex = ColumnIndex CInt+newtype ColumnIndex = ColumnIndex Int deriving (Eq, Ord, Enum, Num, Real, Integral) -- | This just shows the underlying integer, without the data constructor.@@ -123,6 +135,22 @@ -- | Number of columns in a result set. type ColumnCount = ColumnIndex +newtype CParamIndex = CParamIndex CInt+ deriving (Eq, Ord, Enum, Num, Real, Integral)++-- | This just shows the underlying integer, without the data constructor.+instance Show CParamIndex where+ show (CParamIndex n) = show n++newtype CColumnIndex = CColumnIndex CInt+ deriving (Eq, Ord, Enum, Num, Real, Integral)++-- | This just shows the underlying integer, without the data constructor.+instance Show CColumnIndex where+ show (CColumnIndex n) = show n++type CColumnCount = CColumnIndex+ newtype CNumBytes = CNumBytes CInt deriving (Eq, Ord, Show, Enum, Num, Real, Integral) @@ -131,13 +159,14 @@ -- @Ptr CDestructor@ = @sqlite3_destructor_type@ data CDestructor +-- | Tells SQLite3 to make its own private copy of the data c_SQLITE_TRANSIENT :: Ptr CDestructor c_SQLITE_TRANSIENT = intPtrToPtr (-1) -- | <http://www.sqlite.org/c3ref/c_abort.html> newtype CError = CError CInt- deriving Show+ deriving (Eq, Show) -- | Note that this is a partial function. If the error code is invalid, or -- perhaps introduced in a newer version of SQLite but this library has not@@ -182,10 +211,42 @@ #{const SQLITE_DONE} -> ErrorDone _ -> error $ "decodeError " ++ show n +encodeError :: Error -> CError+encodeError err = CError $ case err of+ ErrorOK -> #const SQLITE_OK+ ErrorError -> #const SQLITE_ERROR+ ErrorInternal -> #const SQLITE_INTERNAL+ ErrorPermission -> #const SQLITE_PERM+ ErrorAbort -> #const SQLITE_ABORT+ ErrorBusy -> #const SQLITE_BUSY+ ErrorLocked -> #const SQLITE_LOCKED+ ErrorNoMemory -> #const SQLITE_NOMEM+ ErrorReadOnly -> #const SQLITE_READONLY+ ErrorInterrupt -> #const SQLITE_INTERRUPT+ ErrorIO -> #const SQLITE_IOERR+ ErrorCorrupt -> #const SQLITE_CORRUPT+ ErrorNotFound -> #const SQLITE_NOTFOUND+ ErrorFull -> #const SQLITE_FULL+ ErrorCan'tOpen -> #const SQLITE_CANTOPEN+ ErrorProtocol -> #const SQLITE_PROTOCOL+ ErrorEmpty -> #const SQLITE_EMPTY+ ErrorSchema -> #const SQLITE_SCHEMA+ ErrorTooBig -> #const SQLITE_TOOBIG+ ErrorConstraint -> #const SQLITE_CONSTRAINT+ ErrorMismatch -> #const SQLITE_MISMATCH+ ErrorMisuse -> #const SQLITE_MISUSE+ ErrorNoLargeFileSupport -> #const SQLITE_NOLFS+ ErrorAuthorization -> #const SQLITE_AUTH+ ErrorFormat -> #const SQLITE_FORMAT+ ErrorRange -> #const SQLITE_RANGE+ ErrorNotADatabase -> #const SQLITE_NOTADB+ ErrorRow -> #const SQLITE_ROW+ ErrorDone -> #const SQLITE_DONE + -- | <http://www.sqlite.org/c3ref/c_blob.html> newtype CColumnType = CColumnType CInt- deriving Show+ deriving (Eq, Show) -- | Note that this is a partial function. -- See 'decodeError' for more information.@@ -197,3 +258,38 @@ #{const SQLITE_BLOB} -> BlobColumn #{const SQLITE_NULL} -> NullColumn _ -> error $ "decodeColumnType " ++ show n++encodeColumnType :: ColumnType -> CColumnType+encodeColumnType t = CColumnType $ case t of+ IntegerColumn -> #const SQLITE_INTEGER+ FloatColumn -> #const SQLITE_FLOAT+ TextColumn -> #const SQLITE_TEXT+ BlobColumn -> #const SQLITE_BLOB+ NullColumn -> #const SQLITE_NULL++------------------------------------------------------------------------+-- Conversion to and from FFI types++-- | The "Database.SQLite3" and "Database.SQLite3.Direct" modules use+-- higher-level representations of some types than those used in the+-- FFI signatures ("Database.SQLite3.Bindings"). This typeclass+-- helps with the conversions.+class FFIType public ffi | public -> ffi, ffi -> public where+ toFFI :: public -> ffi+ fromFFI :: ffi -> public++instance FFIType ParamIndex CParamIndex where+ toFFI (ParamIndex n) = CParamIndex (fromIntegral n)+ fromFFI (CParamIndex n) = ParamIndex (fromIntegral n)++instance FFIType ColumnIndex CColumnIndex where+ toFFI (ColumnIndex n) = CColumnIndex (fromIntegral n)+ fromFFI (CColumnIndex n) = ColumnIndex (fromIntegral n)++instance FFIType Error CError where+ toFFI = encodeError+ fromFFI = decodeError++instance FFIType ColumnType CColumnType where+ toFFI = encodeColumnType+ fromFFI = decodeColumnType
Database/SQLite3/Direct.hs view
@@ -11,6 +11,7 @@ open, close, errmsg,+ interrupt, -- * Simple query execution -- | <http://sqlite.org/c3ref/exec.html>@@ -160,6 +161,19 @@ close (Database db) = toResult () <$> c_sqlite3_close db +-- | <http://www.sqlite.org/c3ref/interrupt.html>+--+-- Cause any pending operation on the 'Database' handle to stop at its earliest+-- opportunity. This simply sets a flag and returns immediately. It does not+-- wait for the pending operation to finish.+--+-- You'll need to compile with @-threaded@ for this to do any good.+-- Without @-threaded@, FFI calls block the whole RTS, meaning 'interrupt'+-- would never run at the same time as 'step'.+interrupt :: Database -> IO ()+interrupt (Database db) =+ c_sqlite3_interrupt db+ -- | <http://www.sqlite.org/c3ref/errcode.html> errmsg :: Database -> IO Utf8 errmsg (Database db) =@@ -240,63 +254,63 @@ -- See 'ParamIndex' for more information. bindParameterCount :: Statement -> IO ParamIndex bindParameterCount (Statement stmt) =- c_sqlite3_bind_parameter_count stmt+ fromFFI <$> c_sqlite3_bind_parameter_count stmt -- | <http://www.sqlite.org/c3ref/bind_parameter_name.html> bindParameterName :: Statement -> ParamIndex -> IO (Maybe Utf8) bindParameterName (Statement stmt) idx =- c_sqlite3_bind_parameter_name stmt idx >>=+ c_sqlite3_bind_parameter_name stmt (toFFI idx) >>= packUtf8 Nothing Just -- | <http://www.sqlite.org/c3ref/column_count.html> columnCount :: Statement -> IO ColumnCount columnCount (Statement stmt) =- c_sqlite3_column_count stmt+ fromFFI <$> c_sqlite3_column_count stmt bindInt64 :: Statement -> ParamIndex -> Int64 -> IO (Either Error ()) bindInt64 (Statement stmt) idx value =- toResult () <$> c_sqlite3_bind_int64 stmt idx value+ toResult () <$> c_sqlite3_bind_int64 stmt (toFFI idx) value bindDouble :: Statement -> ParamIndex -> Double -> IO (Either Error ()) bindDouble (Statement stmt) idx value =- toResult () <$> c_sqlite3_bind_double stmt idx value+ toResult () <$> c_sqlite3_bind_double stmt (toFFI idx) value bindText :: Statement -> ParamIndex -> Utf8 -> IO (Either Error ()) bindText (Statement stmt) idx (Utf8 value) = unsafeUseAsCStringLenNoNull value $ \ptr len -> toResult () <$>- c_sqlite3_bind_text stmt idx ptr len c_SQLITE_TRANSIENT+ c_sqlite3_bind_text stmt (toFFI idx) ptr len c_SQLITE_TRANSIENT bindBlob :: Statement -> ParamIndex -> ByteString -> IO (Either Error ()) bindBlob (Statement stmt) idx value = unsafeUseAsCStringLenNoNull value $ \ptr len -> toResult () <$>- c_sqlite3_bind_blob stmt idx ptr len c_SQLITE_TRANSIENT+ c_sqlite3_bind_blob stmt (toFFI idx) ptr len c_SQLITE_TRANSIENT bindNull :: Statement -> ParamIndex -> IO (Either Error ()) bindNull (Statement stmt) idx =- toResult () <$> c_sqlite3_bind_null stmt idx+ toResult () <$> c_sqlite3_bind_null stmt (toFFI idx) columnType :: Statement -> ColumnIndex -> IO ColumnType columnType (Statement stmt) idx =- decodeColumnType <$> c_sqlite3_column_type stmt idx+ decodeColumnType <$> c_sqlite3_column_type stmt (toFFI idx) columnInt64 :: Statement -> ColumnIndex -> IO Int64 columnInt64 (Statement stmt) idx =- c_sqlite3_column_int64 stmt idx+ c_sqlite3_column_int64 stmt (toFFI idx) columnDouble :: Statement -> ColumnIndex -> IO Double columnDouble (Statement stmt) idx =- c_sqlite3_column_double stmt idx+ c_sqlite3_column_double stmt (toFFI idx) columnText :: Statement -> ColumnIndex -> IO Utf8 columnText (Statement stmt) idx = do- ptr <- c_sqlite3_column_text stmt idx- len <- c_sqlite3_column_bytes stmt idx+ ptr <- c_sqlite3_column_text stmt (toFFI idx)+ len <- c_sqlite3_column_bytes stmt (toFFI idx) Utf8 <$> packCStringLen ptr len columnBlob :: Statement -> ColumnIndex -> IO ByteString columnBlob (Statement stmt) idx = do- ptr <- c_sqlite3_column_blob stmt idx- len <- c_sqlite3_column_bytes stmt idx+ ptr <- c_sqlite3_column_blob stmt (toFFI idx)+ len <- c_sqlite3_column_bytes stmt (toFFI idx) packCStringLen ptr len
cbits/sqlite3.c view
file too large to diff
cbits/sqlite3.h view
@@ -107,9 +107,9 @@ ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */-#define SQLITE_VERSION "3.7.13"-#define SQLITE_VERSION_NUMBER 3007013-#define SQLITE_SOURCE_ID "2012-06-11 02:05:22 f5b5a13f7394dc143aa136f1d4faba6839eaa6dc"+#define SQLITE_VERSION "3.7.15"+#define SQLITE_VERSION_NUMBER 3007015+#define SQLITE_SOURCE_ID "2012-12-12 13:36:53 cd0b37c52658bfdf992b1e3dc467bae1835a94ae" /* ** CAPI3REF: Run-Time Library Version Numbers@@ -219,7 +219,8 @@ ** the opaque structure named "sqlite3". It is useful to think of an sqlite3 ** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]-** is its destructor. There are many other interfaces (such as+** and [sqlite3_close_v2()] are its destructors. There are many other+** interfaces (such as ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and ** [sqlite3_busy_timeout()] to name but three) that are methods on an ** sqlite3 object.@@ -266,28 +267,46 @@ /* ** CAPI3REF: Closing A Database Connection **-** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.-** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is-** successfully destroyed and all associated resources are deallocated.+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors+** for the [sqlite3] object.+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if+** the [sqlite3] object is successfully destroyed and all associated+** resources are deallocated. **-** Applications must [sqlite3_finalize | finalize] all [prepared statements]-** and [sqlite3_blob_close | close] all [BLOB handles] associated with-** the [sqlite3] object prior to attempting to close the object. ^If+** ^If the database connection is associated with unfinalized prepared+** statements or unfinished sqlite3_backup objects then sqlite3_close()+** will leave the database connection open and return [SQLITE_BUSY].+** ^If sqlite3_close_v2() is called with unfinalized prepared statements+** and unfinished sqlite3_backups, then the database connection becomes+** an unusable "zombie" which will automatically be deallocated when the+** last prepared statement is finalized or the last sqlite3_backup is+** finished. The sqlite3_close_v2() interface is intended for use with+** host languages that are garbage collected, and where the order in which+** destructors are called is arbitrary.+**+** Applications should [sqlite3_finalize | finalize] all [prepared statements],+** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated+** with the [sqlite3] object prior to attempting to close the object. ^If ** sqlite3_close() is called on a [database connection] that still has-** outstanding [prepared statements] or [BLOB handles], then it returns-** SQLITE_BUSY.+** outstanding [prepared statements], [BLOB handles], and/or+** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation+** of resources is deferred until all [prepared statements], [BLOB handles],+** and [sqlite3_backup] objects are also destroyed. **-** ^If [sqlite3_close()] is invoked while a transaction is open,+** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. **-** The C parameter to [sqlite3_close(C)] must be either a NULL+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]+** must be either a NULL ** pointer or an [sqlite3] object pointer obtained ** from [sqlite3_open()], [sqlite3_open16()], or ** [sqlite3_open_v2()], and not previously closed.-** ^Calling sqlite3_close() with a NULL pointer argument is a -** harmless no-op.+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer+** argument is a harmless no-op. */-SQLITE_API int sqlite3_close(sqlite3 *);+SQLITE_API int sqlite3_close(sqlite3*);+SQLITE_API int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function.@@ -455,10 +474,12 @@ #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))+#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))@@ -498,7 +519,7 @@ ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods]-** object returns an integer which is a vector of the these+** object returns an integer which is a vector of these ** bit values expressing I/O characteristics of the mass storage ** device that holds the file that the [sqlite3_io_methods] ** refers to.@@ -836,6 +857,26 @@ ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements.+**+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]+** ^This file-control may be invoked by SQLite on the database file handle+** shortly after it is opened in order to provide a custom VFS with access+** to the connections busy-handler callback. The argument is of type (void **)+** - an array of two (void *) values. The first (void *) actually points+** to a function of type (int (*)(void *)). In order to invoke the connections+** busy-handler, this function should be invoked with the second (void *) in+** the array as the only argument. If it returns non-zero, then the operation+** should be retried. If it returns zero, the custom VFS should abandon the+** current operation.+**+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]+** ^Application can invoke this file-control to have SQLite generate a+** temporary filename using the same algorithm that is followed to generate+** temporary filenames for TEMP tables and other internal uses. The+** argument should be a char** which will be filled with the filename+** written into memory obtained from [sqlite3_malloc()]. The caller should+** invoke [sqlite3_free()] on the result to avoid a memory leak.+** ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1@@ -852,6 +893,8 @@ #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 #define SQLITE_FCNTL_PRAGMA 14+#define SQLITE_FCNTL_BUSYHANDLER 15+#define SQLITE_FCNTL_TEMPFILENAME 16 /* ** CAPI3REF: Mutex Handle@@ -1548,11 +1591,39 @@ ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. **+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN+** <dd> This option takes a single integer argument which is interpreted as+** a boolean in order to enable or disable the use of covering indices for+** full table scans in the query optimizer. The default setting is determined+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"+** if that compile-time option is omitted.+** The ability to disable the use of covering indices for full table scans+** is because some incorrectly coded legacy applications might malfunction+** malfunction when the optimization is enabled. Providing the ability to+** disable the optimization allows the older, buggy application code to work+** without change even with newer versions of SQLite.+** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl>+**+** [[SQLITE_CONFIG_SQLLOG]]+** <dt>SQLITE_CONFIG_SQLLOG+** <dd>This option is only available if sqlite is compiled with the+** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).+** The second should be of type (void*). The callback is invoked by the library+** in three separate circumstances, identified by the value passed as the+** fourth parameter. If the fourth parameter is 0, then the database connection+** passed as the second argument has just been opened. The third argument+** points to a buffer containing the name of the main database file. If the+** fourth parameter is 1, then the SQL statement that the third parameter+** points to has just been executed. Or, if the fourth parameter is 2, then+** the connection being passed as the second parameter is being closed. The+** third parameter is passed NULL In this case.+** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */@@ -1573,6 +1644,8 @@ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */+#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ /* ** CAPI3REF: Database Connection Configuration Options@@ -2581,7 +2654,7 @@ ** an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the -** third argument to sqlite3_prepare_v2(). ^If the mode option is set to +** third argument to sqlite3_open_v2(). ^If the mode option is set to ** "rw", then the database is opened for read-write (but not create) ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had ** been set. ^Value "rwc" is equivalent to setting both @@ -2648,6 +2721,12 @@ ** codepage is currently defined. Filenames containing international ** characters must be converted to UTF-8 prior to passing them into ** sqlite3_open() or sqlite3_open_v2().+**+** <b>Note to Windows Runtime users:</b> The temporary directory must be set+** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various+** features that require the use of temporary files may fail.+**+** See also: [sqlite3_temp_directory] */ SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */@@ -2727,6 +2806,11 @@ ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ **+** ^The sqlite3_errstr() interface returns the English-language text+** that describes the [result code], as UTF-8.+** ^(Memory to hold the error message string is managed internally+** and must not be freed by the application)^.+** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces.@@ -2745,6 +2829,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*);+SQLITE_API const char *sqlite3_errstr(int); /* ** CAPI3REF: SQL Statement Object@@ -3140,8 +3225,11 @@ ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of <u>bytes</u> in the value, not the number of characters.)^-** ^If the fourth parameter is negative, the length of the string is+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()+** is negative, then the length of the string is ** the number of bytes up to the first zero terminator.+** If the fourth parameter to sqlite3_bind_blob() is negative, then+** the behavior is undefined. ** If a non-negative fourth parameter is provided to sqlite3_bind_text() ** or sqlite3_bind_text16() then that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL@@ -4138,11 +4226,11 @@ ** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. **-** ^The sqlite3_result_toobig() interface causes SQLite to throw an error-** indicating that a string or BLOB is too long to represent.+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an+** error indicating that a string or BLOB is too long to represent. **-** ^The sqlite3_result_nomem() interface causes SQLite to throw an error-** indicating that a memory allocation failed.+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an+** error indicating that a memory allocation failed. ** ** ^The sqlite3_result_int() interface sets the return value ** of the application-defined function to be the 32-bit signed integer@@ -4449,6 +4537,21 @@ ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided.+**+** <b>Note to Windows Runtime users:</b> The temporary directory must be set+** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various+** features that require the use of temporary files may fail. Here is an+** example of how to do this using C++ with the Windows Runtime:+**+** <blockquote><pre>+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->+** TemporaryFolder->Path->Data();+** char zPathBuf[MAX_PATH + 1];+** memset(zPathBuf, 0, sizeof(zPathBuf));+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),+** NULL, NULL);+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);+** </pre></blockquote> */ SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; @@ -4689,6 +4792,9 @@ ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. **+** This interface is threadsafe on processors where writing a+** 32-bit integer is atomic.+** ** See Also: [SQLite Shared-Cache Mode] */ SQLITE_API int sqlite3_enable_shared_cache(int);@@ -5494,7 +5600,6 @@ ** implementations are available in the SQLite core: ** ** <ul>-** <li> SQLITE_MUTEX_OS2 ** <li> SQLITE_MUTEX_PTHREADS ** <li> SQLITE_MUTEX_W32 ** <li> SQLITE_MUTEX_NOOP@@ -5502,9 +5607,9 @@ ** ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines ** that does no real locking and is appropriate for use in-** a single-threaded application. ^The SQLITE_MUTEX_OS2,-** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations-** are appropriate for use on OS/2, Unix, and Windows.+** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix+** and Windows. ** ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
direct-sqlite.cabal view
@@ -1,5 +1,5 @@ name: direct-sqlite-version: 2.3+version: 2.3.1 build-type: Simple license: BSD3 license-file: LICENSE@@ -22,6 +22,9 @@ . Release history: .+ [Version 2.3.1] Upgrade the bundled SQLite3 to 3.7.15. Add bindings for+ sqlite3_interrupt. Export Int rather than CInt.+ . [Version 2.3] Mark some FFI calls "unsafe", for a substantial performance benefit. .@@ -85,12 +88,14 @@ other-modules: StrictEq - ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind+ ghc-options: -Wall -threaded -fno-warn-name-shadowing -fno-warn-unused-do-bind - extensions: NamedFieldPuns- , OverloadedStrings- , Rank2Types- , RecordWildCards+ default-language: Haskell2010++ default-extensions: NamedFieldPuns+ , OverloadedStrings+ , Rank2Types+ , RecordWildCards build-depends: base , base16-bytestring
test/Main.hs view
@@ -1,13 +1,10 @@-{-# LANGUAGE ScopedTypeVariables #-}- import StrictEq import Database.SQLite3 import qualified Database.SQLite3.Direct as Direct -import Prelude hiding (catch) -- Remove this import when GHC 7.6 is released,- -- as Prelude no longer exports catch.-import Control.Exception (bracket, handleJust, try)+import Control.Concurrent+import Control.Exception import Control.Monad (forM_, when) import Data.Text (Text) import Data.Text.Encoding.Error (UnicodeException(..))@@ -47,7 +44,10 @@ , TestLabel "Errors" . testErrors , TestLabel "Integrity" . testIntegrity , TestLabel "DecodeError" . testDecodeError- ]+ ] +++ (if rtsSupportsBoundThreads then+ [ TestLabel "Interrupt" . testInterrupt+ ] else []) featureTests :: [TestEnv -> Test] featureTests =@@ -458,6 +458,29 @@ where invalidUtf8 = Direct.Utf8 $ B.pack [0x80] +testInterrupt :: TestEnv -> Test+testInterrupt TestEnv{..} = TestCase $+ withConn $ \conn -> do+ exec conn "CREATE TABLE tbl (n INT)"++ withStmt conn "INSERT INTO tbl VALUES (?)" $ \stmt -> do+ exec conn "BEGIN"+ forM_ [1..200] $ \i -> do+ reset stmt+ bind stmt [SQLInteger i]+ Done <- step stmt+ return ()+ exec conn "COMMIT"++ stmt <- prepare conn tripleSum+ _ <- forkIO $ threadDelay 100000 >> interrupt conn+ Left ErrorInterrupt <- Direct.step stmt+ Left ErrorInterrupt <- Direct.finalize stmt+ return ()++ where+ tripleSum = "SELECT sum(a.n + b.n + c.n) FROM tbl as a, tbl as b, tbl as c"+ testMultiRowInsert :: TestEnv -> Test testMultiRowInsert TestEnv{..} = TestCase $ do withConn $ \conn -> do@@ -491,8 +514,16 @@ , withConnShared = withConnPath sharedDBPath } where- withConn = withConnPath ":memory:"- withConnPath path = bracket (open path) close+ withConn = withConnPath ":memory:"+ withConnPath path cb = do+ conn <- open path+ 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 runTestGroup :: [TestEnv -> Test] -> IO Bool runTestGroup tests = do