direct-sqlite 2.3.4 → 2.3.5
raw patch · 7 files changed
+244/−37 lines, 7 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Database.SQLite3: prepareUtf8 :: Database -> Utf8 -> IO Statement
+ Database.SQLite3: typedColumns :: Statement -> [Maybe ColumnType] -> IO [SQLData]
+ Database.SQLite3.Bindings: c_sqlite3_get_autocommit :: Ptr CDatabase -> IO CInt
+ Database.SQLite3.Direct: getAutoCommit :: Database -> IO Bool
Files
- Database/SQLite3.hs +35/−10
- Database/SQLite3/Bindings.hs +5/−0
- Database/SQLite3/Direct.hs +19/−0
- cbits/sqlite3.c too large to diff
- cbits/sqlite3.h +111/−26
- direct-sqlite.cabal +16/−1
- test/Main.hs +58/−0
Database/SQLite3.hs view
@@ -16,6 +16,7 @@ -- * Statement management prepare,+ prepareUtf8, step, reset, finalize,@@ -45,6 +46,7 @@ -- datum contains invalid UTF-8. column, columns,+ typedColumns, columnType, columnInt64, columnDouble,@@ -110,7 +112,7 @@ import Control.Applicative ((<$>)) import Control.Concurrent import Control.Exception-import Control.Monad (when, zipWithM_)+import Control.Monad (when, zipWithM, zipWithM_) import Data.ByteString (ByteString) import Data.Int (Int64) import Data.Maybe (fromMaybe)@@ -294,7 +296,7 @@ cb' count namesUtf8 = let names = map fromUtf8'' namesUtf8 {-# NOINLINE names #-}- in \valuesUtf8 -> cb count names (map (fmap fromUtf8'') valuesUtf8)+ in cb count names . map (fmap fromUtf8'') fromUtf8'' = fromUtf8' "Database.SQLite3.execWithCallback: Invalid UTF-8" @@ -314,8 +316,17 @@ -- -- If the query string contains no SQL statements, this 'fail's. prepare :: Database -> Text -> IO Statement-prepare db sql = do- m <- Direct.prepare db (toUtf8 sql)+prepare db sql = prepareUtf8 db (toUtf8 sql)+ +-- | <http://www.sqlite.org/c3ref/prepare.html>+--+-- It can help to avoid redundant Utf8 to Text conversion if you already+-- have Utf8 +--+-- If the query string contains no SQL statements, this 'fail's.+prepareUtf8 :: Database -> Utf8 -> IO Statement+prepareUtf8 db sql = do+ m <- Direct.prepare db sql >>= checkError (DetailDatabase db) ("prepare " `appendShow` sql) case m of Nothing -> fail "Direct.SQLite3.prepare: empty query string"@@ -483,14 +494,28 @@ column :: Statement -> ColumnIndex -> IO SQLData column statement idx = do theType <- columnType statement idx- case theType of- IntegerColumn -> SQLInteger <$> columnInt64 statement idx- FloatColumn -> SQLFloat <$> columnDouble statement idx- TextColumn -> SQLText <$> columnText statement idx- BlobColumn -> SQLBlob <$> columnBlob statement idx- NullColumn -> return SQLNull+ typedColumn theType statement idx columns :: Statement -> IO [SQLData] columns statement = do count <- columnCount statement mapM (column statement) [0..count-1]++typedColumn :: ColumnType -> Statement -> ColumnIndex -> IO SQLData+typedColumn theType statement idx = case theType of+ IntegerColumn -> SQLInteger <$> columnInt64 statement idx+ FloatColumn -> SQLFloat <$> columnDouble statement idx+ TextColumn -> SQLText <$> columnText statement idx+ BlobColumn -> SQLBlob <$> columnBlob statement idx+ NullColumn -> return SQLNull++-- |+-- This avoids extra API calls using the list of column types.+-- If passed types do not correspond to the actual types, the values will be +-- converted according to the rules at <http://www.sqlite.org/c3ref/column_blob.html>.+-- If the list contains more items that number of columns, the result is undefined.+typedColumns :: Statement -> [Maybe ColumnType] -> IO [SQLData]+typedColumns statement = zipWithM f [0..] where+ f idx theType = case theType of+ Nothing -> column statement idx+ Just t -> typedColumn t statement idx
Database/SQLite3/Bindings.hs view
@@ -10,6 +10,7 @@ c_sqlite3_trace, CTraceCallback, mkCTraceCallback,+ c_sqlite3_get_autocommit, -- * Simple query execution -- | <http://sqlite.org/c3ref/exec.html>@@ -90,6 +91,10 @@ -> Ptr a -- ^ Context passed to the callback -> IO (Ptr ()) -- ^ Returns context pointer from previously -- registered trace++-- | <http://www.sqlite.org/c3ref/get_autocommit.html>+foreign import ccall unsafe "sqlite3_get_autocommit"+ c_sqlite3_get_autocommit :: Ptr CDatabase -> IO CInt foreign import ccall "sqlite3_exec"
Database/SQLite3/Direct.hs view
@@ -13,6 +13,7 @@ close, errmsg, setTrace,+ getAutoCommit, -- * Simple query execution -- | <http://sqlite.org/c3ref/exec.html>@@ -309,6 +310,24 @@ output msg _ <- c_sqlite3_trace db cb nullPtr return ()++-- | <http://www.sqlite.org/c3ref/get_autocommit.html>+--+-- Return 'True' if the connection is in autocommit mode, or 'False' if a+-- transaction started with @BEGIN@ is still active.+--+-- Be warned that some errors roll back the transaction automatically,+-- and that @ROLLBACK@ will throw an error if no transaction is active.+-- Use 'getAutoCommit' to avoid such an error:+--+-- @+-- autocommit <- 'getAutoCommit' conn+-- 'Control.Monad.when' (not autocommit) $+-- 'Database.SQLite3.exec' conn \"ROLLBACK\"+-- @+getAutoCommit :: Database -> IO Bool+getAutoCommit (Database db) =+ (/= 0) <$> c_sqlite3_get_autocommit db -- | <http://www.sqlite.org/c3ref/prepare.html> --
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.15.2"-#define SQLITE_VERSION_NUMBER 3007015-#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"+#define SQLITE_VERSION "3.7.17"+#define SQLITE_VERSION_NUMBER 3007017+#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668" /* ** CAPI3REF: Run-Time Library Version Numbers@@ -288,7 +288,7 @@ ** [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+** sqlite3_close_v2() is called on a [database connection] that still has ** 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],@@ -425,6 +425,8 @@ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */+#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */+#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */@@ -475,6 +477,7 @@ #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_IOERR_MMAP (SQLITE_IOERR | (24<<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))@@ -483,7 +486,19 @@ #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))+#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))+#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))+#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))+#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))+#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))+#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))+#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))+#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))+#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))+#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))+#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))+#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations@@ -723,6 +738,9 @@ void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */+ int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);+ int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);+ /* Methods above are valid for version 3 */ /* Additional methods may be added in future releases */ }; @@ -859,7 +877,8 @@ ** 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+** ^The [SQLITE_FCNTL_BUSYHANDLER]+** 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@@ -870,13 +889,24 @@ ** current operation. ** ** <li>[[SQLITE_FCNTL_TEMPFILENAME]]-** ^Application can invoke this file-control to have SQLite generate a+** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] 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. **+** <li>[[SQLITE_FCNTL_MMAP_SIZE]]+** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the+** maximum number of bytes that will be used for memory-mapped I/O.+** The argument is a pointer to a value of type sqlite3_int64 that+** is an advisory maximum number of bytes in the file to memory map. The+** pointer is overwritten with the old value. The limit is not changed if+** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This+** file-control is used internally to implement [PRAGMA mmap_size].+** ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1@@ -895,6 +925,7 @@ #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_TEMPFILENAME 16+#define SQLITE_FCNTL_MMAP_SIZE 18 /* ** CAPI3REF: Mutex Handle@@ -1561,7 +1592,9 @@ ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>-** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a+** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite+** global [error log].+** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the@@ -1607,12 +1640,12 @@ ** <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>+** </dd> ** ** [[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+** [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@@ -1622,7 +1655,23 @@ ** 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.+** third parameter is passed NULL In this case. An example of using this+** configuration option can be seen in the "test_sqllog.c" source file in+** the canonical SQLite source tree.</dd>+**+** [[SQLITE_CONFIG_MMAP_SIZE]]+** <dt>SQLITE_CONFIG_MMAP_SIZE+** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values+** that are the default mmap size limit (the default setting for+** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.+** The default setting can be overridden by each database connection using+** either the [PRAGMA mmap_size] command, or by using the+** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size+** cannot be changed at run-time. Nor may the maximum allowed mmap size+** exceed the compile-time maximum mmap size set by the+** [SQLITE_MAX_MMAP_SIZE] compile-time option. +** If either argument to this option is negative, then that argument is+** changed to its compile-time default. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */@@ -1646,6 +1695,7 @@ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */+#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ /* ** CAPI3REF: Database Connection Configuration Options@@ -2479,6 +2529,9 @@ ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ **+** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit+** the length of [bound parameter] expansion in the output of sqlite3_trace().+** ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time@@ -2670,7 +2723,7 @@ ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in-** a URI filename, its value overrides any behaviour requested by setting+** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** </ul> **@@ -3017,7 +3070,8 @@ ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL-** statement and try to run it again.+** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY]+** retries will occur before sqlite3_step() gives up and returns an error. ** </li> ** ** <li>@@ -3221,6 +3275,9 @@ ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter.+** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()+** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter+** is ignored and the end result is the same as sqlite3_bind_null(). ** ** ^(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@@ -3988,7 +4045,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),+ void*,sqlite3_int64); #endif /*@@ -4068,14 +4126,17 @@ ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ **-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is-** less than or equal to zero or if a memory allocate error occurs.+** ^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. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory-** allocation.)^+** allocation.)^ Within the xFinal callback, it is customary to set+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** pointless memory allocations occur. ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes.@@ -4173,7 +4234,7 @@ ** the content before returning. ** ** The typedef is necessary to work around problems in certain-** C++ compilers. See ticket #2191.+** C++ compilers. */ typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0)@@ -4972,11 +5033,20 @@ ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an-** SQLite extension library contained in the file zFile.+** [SQLite extension] library contained in the file zFile. If+** the file cannot be loaded directly, attempts are made to load+** with various operating-system specific extensions added.+** So for example, if "samplelib" cannot be loaded, then names like+** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might+** be tried also. ** ** ^The entry point is zProc.-** ^zProc may be 0, in which case the name of the entry point-** defaults to "sqlite3_extension_init".+** ^(zProc may be 0, in which case SQLite will try to come up with an+** entry point name on its own. It first tries "sqlite3_extension_init".+** If that does not work, it constructs a name "sqlite3_X_init" where the+** X is consists of the lower-case equivalent of all ASCII alphabetic+** characters in the filename from the last "/" to the first following+** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the@@ -5002,11 +5072,11 @@ ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are-** unprepared to deal with extension loading, and as a means of disabling-** extension loading while evaluating user-entered SQL, the following API+** unprepared to deal with [extension loading], and as a means of disabling+** [extension loading] while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. **-** ^Extension loading is off by default. See ticket #1863.+** ^Extension loading is off by default. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again.@@ -5018,7 +5088,7 @@ ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that-** xEntryPoint() is the entry point for a statically linked SQLite extension+** xEntryPoint() is the entry point for a statically linked [SQLite extension] ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes@@ -6369,7 +6439,7 @@ ** parameter to help it determined what action to take: ** ** <table border=1 width=85% align=center>-** <tr><th> createFlag <th> Behaviour when page is not already in cache+** <tr><th> createFlag <th> Behavior when page is not already in cache ** <tr><td> 0 <td> Do not allocate a new page. Return NULL. ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. ** Otherwise return NULL.@@ -6799,9 +6869,24 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /*+** CAPI3REF: String Globbing+*+** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches+** the glob pattern P, and it returns non-zero if string X does not match+** the glob pattern P. ^The definition of glob pattern matching used in+** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the+** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case+** sensitive.+**+** Note that this routine returns zero on a match and non-zero if the strings+** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].+*/+SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);++/* ** CAPI3REF: Error Logging Interface **-** ^The [sqlite3_log()] interface writes a message into the error log+** ^The [sqlite3_log()] interface writes a message into the [error log] ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** used with [sqlite3_snprintf()] to generate the final output string.
direct-sqlite.cabal view
@@ -1,5 +1,5 @@ name: direct-sqlite-version: 2.3.4+version: 2.3.5 build-type: Simple license: BSD3 license-file: LICENSE@@ -21,6 +21,8 @@ . Release history: .+ [Version 2.3.5] Add support to compile bundled SQLite3 with full-text search. Upgrade bundled SQLite3 to 3.7.17.+ . [Version 2.3.4] Work around a linker error on some systems; add column-name reporting. .@@ -68,6 +70,10 @@ description: Use the system-wide sqlite library default: False +flag fulltextsearch+ description: Enable full-text search when using the bundled sqlite library+ default: True+ Library exposed-modules: Database.SQLite3@@ -78,11 +84,19 @@ if flag(systemlib) { cpp-options: -Ddirect_sqlite_systemlib extra-libraries: sqlite3+ if flag(fulltextsearch) {+ buildable: False+ } } else { if !os(windows) { extra-libraries: pthread } c-sources: cbits/sqlite3.c+ if flag(fulltextsearch) {+ cc-options: -DSQLITE_ENABLE_FTS3+ -DSQLITE_ENABLE_FTS3_PARENTHESIS+ -DSQLITE_ENABLE_FTS4+ } } include-dirs: .@@ -110,6 +124,7 @@ , OverloadedStrings , Rank2Types , RecordWildCards+ , ScopedTypeVariables build-depends: base , base16-bytestring
test/Main.hs view
@@ -45,11 +45,13 @@ , TestLabel "Params" . testBindParamName , TestLabel "Params" . testBindErrorValidation , TestLabel "Columns" . testColumns+ , TestLabel "TypedColumns" . testTypedColumns , TestLabel "ColumnName" . testColumnName , TestLabel "Errors" . testErrors , TestLabel "Integrity" . testIntegrity , TestLabel "DecodeError" . testDecodeError , TestLabel "ResultStats" . testResultStats+ , TestLabel "GetAutoCommit" . testGetAutoCommit , TestLabel "Debug" . testStatementSql , TestLabel "Debug" . testTracing ] ++@@ -356,6 +358,39 @@ 0 <- columnCount stmt return () +testTypedColumns :: TestEnv -> Test+testTypedColumns TestEnv{..} = TestCase $ do+ withConn $ \conn -> do+ withStmt conn "CREATE TABLE foo (a INT, b INT)" command+ withStmt conn "INSERT INTO foo VALUES (1, 2)" command+ withStmt conn "INSERT INTO foo VALUES (3, 4)" command+ withStmt conn "SELECT * FROM foo" $ \stmt -> do+ Row <- step stmt+ 2 <- columnCount stmt+ [SQLInteger 1, SQLInteger 2] <- typedColumns stmt [Nothing, Nothing]+ Row <- step stmt+ 2 <- columnCount stmt+ [SQLInteger 3, SQLInteger 4] <- typedColumns stmt [Just IntegerColumn, Just IntegerColumn]+ Done <- step stmt+ 2 <- columnCount stmt+ return ()+ withStmt conn "SELECT * FROM foo" $ \stmt -> do+ Row <- step stmt+ 2 <- columnCount stmt+ [SQLText "1", SQLText "2"] <- typedColumns stmt [Just TextColumn, Just TextColumn]+ Row <- step stmt+ 2 <- columnCount stmt+ [SQLFloat 3.0, SQLFloat 4.0] <- typedColumns stmt [Just FloatColumn, Just FloatColumn]+ Done <- step stmt+ 2 <- columnCount stmt+ return ()+ where+ command stmt = do+ 0 <- columnCount stmt+ Done <- step stmt+ 0 <- columnCount stmt+ return ()+ testColumnName :: TestEnv -> Test testColumnName TestEnv{..} = TestCase $ do withConn $ \conn -> do@@ -612,6 +647,29 @@ liftM3 (,,) (lastInsertRowId conn) (changes conn) (Direct.totalChanges conn)++testGetAutoCommit :: TestEnv -> Test+testGetAutoCommit TestEnv{..} = TestCase $+ withConn $ \conn -> do+ True <- Direct.getAutoCommit conn+ exec conn "BEGIN"+ False <- Direct.getAutoCommit conn+ Left (ErrorError, _) <- Direct.exec conn "BEGIN"+ False <- Direct.getAutoCommit conn++ exec conn "ROLLBACK"+ True <- Direct.getAutoCommit conn+ Left (ErrorError, _) <- Direct.exec conn "ROLLBACK"+ True <- Direct.getAutoCommit conn++ exec conn "BEGIN"+ False <- Direct.getAutoCommit conn+ Left (ErrorFull, _) <- Direct.exec conn+ "PRAGMA max_page_count=1; CREATE TABLE foo (a INT)"+ True <- Direct.getAutoCommit conn+ Left (ErrorError, _) <- Direct.exec conn "ROLLBACK"++ return () testStatementSql :: TestEnv -> Test testStatementSql TestEnv{..} = TestCase $ do