direct-sqlite 2.3.28 → 2.3.29
raw patch · 8 files changed
+646/−178 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Database.SQLite3: SQLOpenExResCode :: SQLOpenFlag
+ Database.SQLite3: withDatabase :: Text -> (Database -> IO a) -> IO a
+ Database.SQLite3: withStatement :: Database -> Text -> (Statement -> IO a) -> IO a
+ Database.SQLite3.Bindings: c_sqlite3_extended_result_codes :: Ptr CDatabase -> Bool -> IO CError
+ Database.SQLite3.Direct: setExtendedResultCodes :: Database -> Bool -> IO (Either Error ())
Files
- Database/SQLite3.hs +17/−0
- Database/SQLite3/Bindings.hs +5/−0
- Database/SQLite3/Direct.hs +6/−0
- cbits/sqlite3.c too large to diff
- cbits/sqlite3.h +507/−122
- cbits/sqlite3ext.h +10/−0
- direct-sqlite.cabal +27/−11
- test/Main.hs +74/−45
Database/SQLite3.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE DeriveGeneric #-} module Database.SQLite3 ( -- * Connection management+ withDatabase, open, open2, close,@@ -16,6 +17,7 @@ ExecCallback, -- * Statement management+ withStatement, prepare, prepareUtf8, step,@@ -232,6 +234,7 @@ | SQLOpenPrivateCache -- Ok for sqlite3_open_v2() | SQLOpenWAL -- VFS only | SQLOpenNoFollow -- Ok for sqlite3_open_v2()+ | SQLOpenExResCode -- Extended result codes deriving (Eq, Show) -- | These VFS names are used when using the `open2` function.@@ -326,6 +329,12 @@ appendShow :: Show a => Text -> a -> Text appendShow txt a = txt `T.append` (T.pack . show) a +-- | Manage a connection to a database in an exception-safe way (with 'bracket')+withDatabase :: Text -- ^ connection string+ -> (Database -> IO a) -- ^ user program+ -> IO a+withDatabase path = bracket (open path) close+ -- | <https://www.sqlite.org/c3ref/open.html> open :: Text -> IO Database open path =@@ -371,6 +380,7 @@ toNum SQLOpenPrivateCache = 0x00040000 toNum SQLOpenWAL = 0x00080000 toNum SQLOpenNoFollow = 0x01000000+ toNum SQLOpenExResCode = 0x02000000 -- | <https://www.sqlite.org/c3ref/close.html> close :: Database -> IO ()@@ -458,6 +468,13 @@ -- for every row. -> [Maybe Text] -- ^ List of column values, as returned by 'columnText'. -> IO ()++-- | Bracket 'prepare' and 'finalize'. Useful for stepping multiple times through a 'Statement'+withStatement :: Database -- ^ DB connection+ -> Text -- ^ SQL statement+ -> (Statement -> IO a) -- ^ User program+ -> IO a+withStatement db sql = bracket (prepare db sql) finalize -- | <https://www.sqlite.org/c3ref/prepare.html> --
Database/SQLite3/Bindings.hs view
@@ -9,6 +9,7 @@ c_sqlite3_errcode, c_sqlite3_extended_errcode, c_sqlite3_errmsg,+ c_sqlite3_extended_result_codes, c_sqlite3_interrupt, c_sqlite3_trace, CTraceCallback,@@ -165,6 +166,10 @@ -- | <https://www.sqlite.org/c3ref/errcode.html> foreign import ccall unsafe "sqlite3_errmsg" c_sqlite3_errmsg :: Ptr CDatabase -> IO CString++-- | <https://www.sqlite.org/c3ref/extended_result_codes.html>+foreign import ccall unsafe "sqlite3_extended_result_codes"+ c_sqlite3_extended_result_codes :: Ptr CDatabase -> Bool -> IO CError -- | <https://www.sqlite.org/c3ref/interrupt.html> foreign import ccall "sqlite3_interrupt"
Database/SQLite3/Direct.hs view
@@ -16,6 +16,7 @@ errcode, extendedErrcode, errmsg,+ setExtendedResultCodes, setTrace, getAutoCommit, setSharedCacheEnabled,@@ -313,6 +314,11 @@ extendedErrcode :: Database -> IO Error extendedErrcode (Database db) = decodeError <$> c_sqlite3_extended_errcode db++-- | <https://www.sqlite.org/c3ref/extended_result_codes.html>+setExtendedResultCodes :: Database -> Bool -> IO (Either Error ())+setExtendedResultCodes (Database db) enabled =+ toResult () <$> c_sqlite3_extended_result_codes db enabled -- | <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.41.0"-#define SQLITE_VERSION_NUMBER 3041000-#define SQLITE_SOURCE_ID "2023-02-21 18:09:37 05941c2a04037fc3ed2ffae11f5d2260706f89431f463518740f72ada350866d"+#define SQLITE_VERSION "3.45.0"+#define SQLITE_VERSION_NUMBER 3045000+#define SQLITE_SOURCE_ID "2024-01-15 17:01:13 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d" /* ** CAPI3REF: Run-Time Library Version Numbers@@ -528,6 +528,7 @@ #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))+#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))@@ -1190,7 +1191,7 @@ ** by clients within the current process, only within other processes. ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]]-** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the+** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the ** [checksum VFS shim] only. ** ** <li>[[SQLITE_FCNTL_RESET_CACHE]]@@ -1655,20 +1656,23 @@ ** must ensure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running.</b> **-** The sqlite3_config() interface-** may only be invoked prior to library initialization using-** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].-** ^If sqlite3_config() is called after [sqlite3_initialize()] and before-** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.-** Note, however, that ^sqlite3_config() can be called as part of the-** implementation of an application-defined [sqlite3_os_init()].-** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. **+** For most configuration options, the sqlite3_config() interface+** may only be invoked prior to library initialization using+** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].+** The exceptional configuration options that may be invoked at any time+** are called "anytime configuration options".+** ^If sqlite3_config() is called after [sqlite3_initialize()] and before+** [sqlite3_shutdown()] with a first argument that is not an anytime+** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE.+** Note, however, that ^sqlite3_config() can be called as part of the+** implementation of an application-defined [sqlite3_os_init()].+** ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code].@@ -1776,6 +1780,23 @@ ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. **+** Most of the configuration options for sqlite3_config()+** will only work if invoked prior to [sqlite3_initialize()] or after+** [sqlite3_shutdown()]. The few exceptions to this rule are called+** "anytime configuration options".+** ^Calling [sqlite3_config()] with a first argument that is not an+** anytime configuration option in between calls to [sqlite3_initialize()] and+** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE.+**+** The set of anytime configuration options can change (by insertions+** and/or deletions) from one release of SQLite to the next.+** As of SQLite version 3.42.0, the complete set of anytime configuration+** options is:+** <ul>+** <li> SQLITE_CONFIG_LOG+** <li> SQLITE_CONFIG_PCACHE_HDRSZ+** </ul>+** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_config()] to make sure that@@ -2106,7 +2127,7 @@ ** is stored in each sorted record and the required column values loaded ** from the database as records are returned in sorted order. The default ** value for this option is to never use this optimization. Specifying a-** negative value for this option restores the default behaviour.+** negative value for this option restores the default behavior. ** This option is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. **@@ -2122,28 +2143,28 @@ ** compile-time option is not set, then the default maximum is 1073741824. ** </dl> */-#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */-#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */-#define SQLITE_CONFIG_SERIALIZED 3 /* nil */-#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */-#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */-#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */-#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */-#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */-#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */-#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */-#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */-#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */-#define SQLITE_CONFIG_PCACHE 14 /* no-op */-#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */-#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */-#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_SINGLETHREAD 1 /* nil */+#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */+#define SQLITE_CONFIG_SERIALIZED 3 /* nil */+#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */+#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */+#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */+#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */+#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */+#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */+#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */+#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */+#define SQLITE_CONFIG_PCACHE 14 /* no-op */+#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */+#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */+#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* */-#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */+#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */+#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */@@ -2281,7 +2302,7 @@ ** database handle, SQLite checks if this will mean that there are now no ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to-** override this behaviour. The first parameter passed to this operation+** override this behavior. The first parameter passed to this operation ** is an integer - positive to disable checkpoints-on-close, or zero (the ** default) to enable them, and negative to leave the setting unchanged. ** The second parameter is a pointer to an integer@@ -2378,7 +2399,7 @@ ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DML]]-** <dt>SQLITE_DBCONFIG_DQS_DML</td>+** <dt>SQLITE_DBCONFIG_DQS_DML</dt> ** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DML statements ** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The@@ -2387,7 +2408,7 @@ ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DDL]]-** <dt>SQLITE_DBCONFIG_DQS_DDL</td>+** <dt>SQLITE_DBCONFIG_DQS_DDL</dt> ** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DDL statements, ** such as CREATE TABLE and CREATE INDEX. The@@ -2396,7 +2417,7 @@ ** </dd> ** ** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]-** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>+** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</dt> ** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to ** assume that database schemas are untainted by malicious content. ** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite@@ -2416,7 +2437,7 @@ ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]-** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>+** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly ** created database file to have a schema format version number (the 4-byte@@ -2425,7 +2446,7 @@ ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, ** newly created databases are generally not understandable by SQLite versions ** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there-** is now scarcely any need to generated database files that are compatible+** is now scarcely any need to generate database files that are compatible ** all the way back to version 3.0.0, and so this setting is of little ** practical use, but is provided so that SQLite can continue to claim the ** ability to generate new database files that are compatible with version@@ -2434,8 +2455,40 @@ ** the [VACUUM] command will fail with an obscure error when attempting to ** process a table with generated columns and a descending index. This is ** not considered a bug since SQLite versions 3.3.0 and earlier do not support-** either generated columns or decending indexes.+** either generated columns or descending indexes. ** </dd>+**+** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]+** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>+** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in+** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears+** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()+** statistics. For statistics to be collected, the flag must be set on+** the database handle both when the SQL statement is prepared and when it+** is stepped. The flag is set (collection of statistics is enabled)+** by default. This option takes two arguments: an integer and a pointer to+** an integer.. The first argument is 1, 0, or -1 to enable, disable, or+** leave unchanged the statement scanstatus option. If the second argument+** is not NULL, then the value of the statement scanstatus setting after+** processing the first argument is written into the integer that the second+** argument points to.+** </dd>+**+** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]+** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</dt>+** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order+** in which tables and indexes are scanned so that the scans start at the end+** and work toward the beginning rather than starting at the beginning and+** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the+** same as setting [PRAGMA reverse_unordered_selects]. This option takes+** two arguments which are an integer and a pointer to an integer. The first+** argument is 1, 0, or -1 to enable, disable, or leave unchanged the+** reverse scan order flag, respectively. If the second argument is not NULL,+** then 0 or 1 is written into the integer that the second argument points to+** depending on if the reverse scan order flag is set after processing the+** first argument.+** </dd>+** ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */@@ -2456,7 +2509,9 @@ #define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ #define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */-#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */+#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */+#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */+#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes@@ -2681,6 +2736,7 @@ ** ** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether ** or not an interrupt is currently in effect for [database connection] D.+** It returns 1 if an interrupt is currently in effect, or 0 otherwise. */ SQLITE_API void sqlite3_interrupt(sqlite3*); SQLITE_API int sqlite3_is_interrupted(sqlite3*);@@ -3334,8 +3390,10 @@ ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. **-** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides-** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2().+** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P)+** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or+** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each+** database connection may have at most one trace callback. ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently@@ -3704,7 +3762,7 @@ ** as F) must be one of: ** <ul> ** <li> A database filename pointer created by the SQLite core and-** passed into the xOpen() method of a VFS implemention, or+** passed into the xOpen() method of a VFS implementation, or ** <li> A filename obtained from [sqlite3_db_filename()], or ** <li> A new filename constructed using [sqlite3_create_filename()]. ** </ul>@@ -3817,7 +3875,7 @@ /* ** CAPI3REF: Create and Destroy VFS Filenames **-** These interfces are provided for use by [VFS shim] implementations and+** These interfaces are provided for use by [VFS shim] implementations and ** are not useful outside of that context. ** ** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of@@ -3896,14 +3954,17 @@ ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language-** text that describes the error, as either UTF-8 or UTF-16 respectively.+** text that describes the error, as either UTF-8 or UTF-16 respectively,+** or NULL if no error message is available.+** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** 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.+** ^The sqlite3_errstr(E) interface returns the English-language text+** that describes the [result code] E, as UTF-8, or NULL if E is not an+** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. **@@ -4365,6 +4426,41 @@ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); /*+** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement+** METHOD: sqlite3_stmt+**+** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN+** setting for [prepared statement] S. If E is zero, then S becomes+** a normal prepared statement. If E is 1, then S behaves as if+** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if+** its SQL text began with "[EXPLAIN QUERY PLAN]".+**+** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.+** SQLite tries to avoid a reprepare, but a reprepare might be necessary+** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.+**+** Because of the potential need to reprepare, a call to+** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be+** reprepared because it was created using [sqlite3_prepare()] instead of+** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and+** hence has no saved SQL text with which to reprepare.+**+** Changing the explain setting for a prepared statement does not change+** the original SQL text for the statement. Hence, if the SQL text originally+** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)+** is called to convert the statement into an ordinary statement, the EXPLAIN+** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)+** output, even though the statement now acts like a normal SQL statement.+**+** This routine returns SQLITE_OK if the explain mode is successfully+** changed, or an error code if the explain mode could not be changed.+** The explain mode cannot be changed while a statement is active.+** Hence, it is good practice to call [sqlite3_reset(S)]+** immediately prior to calling sqlite3_stmt_explain(S,E).+*/+SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);++/* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt **@@ -4527,7 +4623,7 @@ ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative.-** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that+** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is@@ -5206,20 +5302,33 @@ ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. **-** ^If the most recent call to [sqlite3_step(S)] for the-** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],-** or if [sqlite3_step(S)] has never before been called on S,-** then [sqlite3_reset(S)] returns [SQLITE_OK].+** ^The return code from [sqlite3_reset(S)] indicates whether or not+** the previous evaluation of prepared statement S completed successfully.+** ^If [sqlite3_step(S)] has never before been called on S or if+** [sqlite3_step(S)] has not been called since the previous call+** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return+** [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code].+** ^The [sqlite3_reset(S)] interface might also return an [error code]+** if there were no prior errors but the process of resetting+** the prepared statement caused a new error. ^For example, if an+** [INSERT] statement with a [RETURNING] clause is only stepped one time,+** that one call to [sqlite3_step(S)] might return SQLITE_ROW but+** the overall statement might still fail and the [sqlite3_reset(S)] call+** might return SQLITE_BUSY if locking constraints prevent the+** database change from committing. Therefore, it is important that+** applications check the return code from [sqlite3_reset(S)] even if+** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines}@@ -5430,7 +5539,7 @@ ** [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+** into using a database file that has had its schema surreptitiously ** modified to invoke the application-defined function in ways that are ** harmful. ** <p>@@ -5466,13 +5575,27 @@ ** </dd> ** ** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>-** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call+** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.-** Specifying this flag makes no difference for scalar or aggregate user-** functions. However, if it is not specified for a user-defined window-** function, then any sub-types belonging to arguments passed to the window-** function may be discarded before the window function is called (i.e.-** sqlite3_value_subtype() will always return 0).+** This flag instructs SQLite to omit some corner-case optimizations that+** might disrupt the operation of the [sqlite3_value_subtype()] function,+** causing it to return zero rather than the correct subtype().+** SQL functions that invokes [sqlite3_value_subtype()] should have this+** property. If the SQLITE_SUBTYPE property is omitted, then the return+** value from [sqlite3_value_subtype()] might sometimes be zero even though+** a non-zero subtype was specified by the function argument expression.+**+** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>+** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call+** [sqlite3_result_subtype()] to cause a sub-type to be associated with its+** result.+** Every function that invokes [sqlite3_result_subtype()] should have this+** property. If it does not, then the call to [sqlite3_result_subtype()]+** might become a no-op if the function is used as term in an+** [expression index]. On the other hand, SQL functions that never invoke+** [sqlite3_result_subtype()] should avoid setting this property, as the+** purpose of this property is to disable certain optimizations that are+** incompatible with subtypes. ** </dd> ** </dl> */@@ -5480,6 +5603,7 @@ #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000+#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions@@ -5676,6 +5800,12 @@ ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function.+**+** Every [application-defined SQL function] that invoke this interface+** should include the [SQLITE_SUBTYPE] property in the text+** encoding argument when the function is [sqlite3_create_function|registered].+** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()+** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -5774,48 +5904,56 @@ ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to-** associate metadata with argument values. If the same value is passed to-** multiple invocations of the same SQL function during query execution, under-** some circumstances the associated metadata may be preserved. An example-** of where this might be useful is in a regular-expression matching-** function. The compiled version of the regular expression can be stored as-** metadata associated with the pattern string.+** associate auxiliary data with argument values. If the same argument+** value is passed to multiple invocations of the same SQL function during+** query execution, under some circumstances the associated auxiliary data+** might be preserved. An example of where this might be useful is in a+** regular-expression matching function. The compiled version of the regular+** expression can be stored as auxiliary data associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. **-** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata+** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data ** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument ** value to the application-defined function. ^N is zero for the left-most-** function argument. ^If there is no metadata+** function argument. ^If there is no auxiliary data ** associated with the function argument, the sqlite3_get_auxdata(C,N) interface ** returns a NULL pointer. **-** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th-** argument of the application-defined function. ^Subsequent+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the+** N-th argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent-** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or-** NULL if the metadata has been discarded.+** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or+** NULL if the auxiliary data has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly-** once, when the metadata is discarded.-** SQLite is free to discard the metadata at any time, including: <ul>+** once, when the auxiliary data is discarded.+** SQLite is free to discard the auxiliary data at any time, including: <ul> ** <li> ^(when the corresponding function parameter changes)^, or ** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or ** <li> ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or ** <li> ^(during the original sqlite3_set_auxdata() call when a memory-** allocation error occurs.)^ </ul>+** allocation error occurs.)^+** <li> ^(during the original sqlite3_set_auxdata() call if the function+** is evaluated during query planning instead of during query execution,+** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul> **-** Note the last bullet in particular. The destructor X in+** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after-** sqlite3_set_auxdata() has been called.+** sqlite3_set_auxdata() has been called. Furthermore, a call to+** sqlite3_get_auxdata() that occurs immediately after a corresponding call+** to sqlite3_set_auxdata() might still return NULL if an out-of-memory+** condition occurred during the sqlite3_set_auxdata() call or if the+** function is being evaluated during query planning rather than during+** query execution. **-** ^(In practice, metadata is preserved between function calls for+** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ **@@ -5825,10 +5963,67 @@ ** ** These routines must be called from the same thread in which ** the SQL function is running.+**+** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +/*+** CAPI3REF: Database Connection Client Data+** METHOD: sqlite3+**+** These functions are used to associate one or more named pointers+** with a [database connection].+** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P+** to be attached to [database connection] D using name N. Subsequent+** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P+** or a NULL pointer if there were no prior calls to+** sqlite3_set_clientdata() with the same values of D and N.+** Names are compared using strcmp() and are thus case sensitive.+**+** If P and X are both non-NULL, then the destructor X is invoked with+** argument P on the first of the following occurrences:+** <ul>+** <li> An out-of-memory error occurs during the call to+** sqlite3_set_clientdata() which attempts to register pointer P.+** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made+** with the same D and N parameters.+** <li> The database connection closes. SQLite does not make any guarantees+** about the order in which destructors are called, only that all+** destructors will be called exactly once at some point during the+** database connection closing process.+** </ul>+**+** SQLite does not do anything with client data other than invoke+** destructors on the client data at the appropriate time. The intended+** use for client data is to provide a mechanism for wrapper libraries+** to store additional information about an SQLite database connection.+**+** There is no limit (other than available memory) on the number of different+** client data pointers (with different names) that can be attached to a+** single database connection. However, the implementation is optimized+** for the case of having only one or two different client data names.+** Applications and wrapper libraries are discouraged from using more than+** one client data name each.+**+** There is no way to enumerate the client data pointers+** associated with a database connection. The N parameter can be thought+** of as a secret key such that only code that knows the secret key is able+** to access the associated data.+**+** Security Warning: These interfaces should not be exposed in scripting+** languages or in other circumstances where it might be possible for an+** an attacker to invoke them. Any agent that can invoke these interfaces+** can probably also take control of the process.+**+** Database connection client data is only available for SQLite+** version 3.44.0 ([dateof:3.44.0]) and later.+**+** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].+*/+SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);+SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior@@ -6030,6 +6225,20 @@ ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite.+**+** Every [application-defined SQL function] that invokes this interface+** should include the [SQLITE_RESULT_SUBTYPE] property in its+** text encoding argument when the SQL function is+** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]+** property is omitted from the function that invokes sqlite3_result_subtype(),+** then in some cases the sqlite3_result_subtype() might fail to set+** the result subtype.+**+** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any+** SQL function that invokes the sqlite3_result_subtype() interface+** and that does not have the SQLITE_RESULT_SUBTYPE property will raise+** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1+** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -6201,6 +6410,13 @@ ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs.+**+** If a negative argument is passed to sqlite3_sleep() the results vary by+** VFS and operating system. Some system treat a negative argument as an+** instruction to sleep forever. Others understand it to mean do not sleep+** at all. ^In SQLite version 3.42.0 and later, a negative+** argument passed into sqlite3_sleep() is changed to zero before it is relayed+** down into the xSleep method of the VFS. */ SQLITE_API int sqlite3_sleep(int); @@ -6454,7 +6670,7 @@ SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); /*-** CAPI3REF: Allowed return values from [sqlite3_txn_state()]+** CAPI3REF: Allowed return values from sqlite3_txn_state() ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file.@@ -6586,7 +6802,7 @@ ** ^Each call to the sqlite3_autovacuum_pages() interface overrides all ** previous invocations for that database connection. ^If the callback ** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,-** then the autovacuum steps callback is cancelled. The return value+** then the autovacuum steps callback is canceled. The return value ** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might ** be some other error code if something goes wrong. The current ** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other@@ -7105,6 +7321,10 @@ /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*);+ /* The methods above are in versions 1 through 3 of the sqlite_module object.+ ** Those below are for version 4 and greater. */+ int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,+ const char *zTabName, int mFlags, char **pzErr); }; /*@@ -7592,7 +7812,7 @@ ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an-** open blob handle results in undefined behaviour. ^Calling this routine+** open blob handle results in undefined behavior. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the@@ -7819,18 +8039,20 @@ ** ** ^(Some systems (for example, Windows 95) do not support the operation ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()-** will always return SQLITE_BUSY. The SQLite core only ever uses-** sqlite3_mutex_try() as an optimization so this is acceptable-** behavior.)^+** will always return SQLITE_BUSY. In most cases the SQLite core only uses+** sqlite3_mutex_try() as an optimization, so this is acceptable+** behavior. The exceptions are unix builds that set the+** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working+** sqlite3_mutex_try() is required.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered by the ** calling thread or is not currently allocated. **-** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or-** sqlite3_mutex_leave() is a NULL pointer, then all three routines-** behave as no-ops.+** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),+** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,+** then any of the four routines behaves as a no-op. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */@@ -8072,6 +8294,7 @@ #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 #define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */+#define SQLITE_TESTCTRL_FK_NO_ACTION 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10@@ -8079,6 +8302,7 @@ #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */+#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */@@ -8100,7 +8324,8 @@ #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33-#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */+#define SQLITE_TESTCTRL_USELONGDOUBLE 34+#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking@@ -9556,7 +9781,7 @@ ** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt> ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the-** the [xConnect] or [xCreate] methods of a [virtual table] implmentation+** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** prohibits that virtual table from being used from within triggers and ** views. ** </dd>@@ -9564,18 +9789,28 @@ ** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt> ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the-** the [xConnect] or [xCreate] methods of a [virtual table] implmentation+** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** identify that virtual table as being safe to use from within triggers ** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the ** virtual table can do no serious harm even if it is controlled by a ** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS ** flag unless absolutely necessary. ** </dd>+**+** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]<dt>SQLITE_VTAB_USES_ALL_SCHEMAS</dt>+** <dd>Calls of the form+** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the+** the [xConnect] or [xCreate] methods of a [virtual table] implementation+** instruct the query planner to begin at least a read transaction on+** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the+** virtual table is used.+** </dd> ** </dl> */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 #define SQLITE_VTAB_INNOCUOUS 2 #define SQLITE_VTAB_DIRECTONLY 3+#define SQLITE_VTAB_USES_ALL_SCHEMAS 4 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy@@ -9736,7 +9971,7 @@ ** communicated to the xBestIndex method as a ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use ** this constraint, it must set the corresponding-** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under+** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under ** the usual mode of handling IN operators, SQLite generates [bytecode] ** that invokes the [xFilter|xFilter() method] once for each value ** on the right-hand side of the IN operator.)^ Thus the virtual table@@ -10165,7 +10400,7 @@ ** When the [sqlite3_blob_write()] API is used to update a blob column, ** the pre-update hook is invoked with SQLITE_DELETE. This is because the ** in this case the new values are not available. In this case, when a-** callback made with op==SQLITE_DELETE is actuall a write using the+** callback made with op==SQLITE_DELETE is actually a write using the ** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns ** the index of the column being written. In other cases, where the ** pre-update hook is being invoked for some other reason, including a@@ -10426,6 +10661,13 @@ ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. **+** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,+** the returned buffer content will remain accessible and unchanged+** until either the next write operation on the connection or when+** the connection is closed, and applications must not modify the+** buffer. If the bit had been clear, the returned buffer will not+** be accessed by SQLite after the call.+** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs.@@ -10474,6 +10716,9 @@ ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. **+** Applications must not modify the buffer P or invalidate it before+** the database connection D is closed.+** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation.@@ -10482,6 +10727,13 @@ ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the ** function returns SQLITE_ERROR. **+** The deserialized database should not be in [WAL mode]. If the database+** is in WAL mode, then any attempt to use the database file will result+** in an [SQLITE_CANTOPEN] error. The application can set the+** [file format version numbers] (bytes 18 and 19) of the input database P+** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the+** database file into rollback mode and work around this limitation.+** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning.@@ -10750,16 +11002,20 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /*-** CAPIREF: Conigure a Session Object+** CAPI3REF: Configure a Session Object ** METHOD: sqlite3_session ** ** This method is used to configure a session object after it has been-** created. At present the only valid value for the second parameter is-** [SQLITE_SESSION_OBJCONFIG_SIZE].+** created. At present the only valid values for the second parameter are+** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. **-** Arguments for sqlite3session_object_config()+*/+SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);++/*+** CAPI3REF: Options for sqlite3session_object_config **-** The following values may passed as the the 4th parameter to+** The following values may passed as the the 2nd parameter to ** sqlite3session_object_config(). ** ** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>@@ -10775,12 +11031,21 @@ ** ** It is an error (SQLITE_MISUSE) to attempt to modify this setting after ** the first table has been attached to the session object.-*/-SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);--/*+**+** <dt>SQLITE_SESSION_OBJCONFIG_ROWID <dd>+** This option is used to set, clear or query the flag that enables+** collection of data for tables with no explicit PRIMARY KEY.+**+** Normally, tables with no explicit PRIMARY KEY are simply ignored+** by the sessions module. However, if this flag is set, it behaves+** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted+** as their leftmost columns.+**+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after+** the first table has been attached to the session object. */-#define SQLITE_SESSION_OBJCONFIG_SIZE 1+#define SQLITE_SESSION_OBJCONFIG_SIZE 1+#define SQLITE_SESSION_OBJCONFIG_ROWID 2 /* ** CAPI3REF: Enable Or Disable A Session Object@@ -11542,6 +11807,18 @@ /*+** CAPI3REF: Upgrade the Schema of a Changeset/Patchset+*/+SQLITE_API int sqlite3changeset_upgrade(+ sqlite3 *db,+ const char *zDb,+ int nIn, const void *pIn, /* Input changeset */+ int *pnOut, void **ppOut /* OUT: Inverse of input */+);++++/* ** CAPI3REF: Changegroup Handle ** ** A changegroup is an object used to combine two or more@@ -11588,6 +11865,38 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); /*+** CAPI3REF: Add a Schema to a Changegroup+** METHOD: sqlite3_changegroup_schema+**+** This method may be used to optionally enforce the rule that the changesets+** added to the changegroup handle must match the schema of database zDb+** ("main", "temp", or the name of an attached database). If+** sqlite3changegroup_add() is called to add a changeset that is not compatible+** with the configured schema, SQLITE_SCHEMA is returned and the changegroup+** object is left in an undefined state.+**+** A changeset schema is considered compatible with the database schema in+** the same way as for sqlite3changeset_apply(). Specifically, for each+** table in the changeset, there exists a database table with:+**+** <ul>+** <li> The name identified by the changeset, and+** <li> at least as many columns as recorded in the changeset, and+** <li> the primary key columns in the same position as recorded in+** the changeset.+** </ul>+**+** The output of the changegroup object always has the same schema as the+** database nominated using this function. In cases where changesets passed+** to sqlite3changegroup_add() have fewer columns than the corresponding table+** in the database schema, these are filled in using the default column+** values from the database schema. This makes it possible to combined+** changesets that have different numbers of columns for a single table+** within a changegroup, provided that they are otherwise compatible.+*/+SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);++/* ** CAPI3REF: Add A Changeset To A Changegroup ** METHOD: sqlite3_changegroup **@@ -11655,13 +11964,18 @@ ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the-** case, this function fails with SQLITE_SCHEMA. If the input changeset-** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is-** returned. Or, if an out-of-memory condition occurs during processing, this-** function returns SQLITE_NOMEM. In all cases, if an error occurs the state-** of the final contents of the changegroup is undefined.+** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup+** object has been configured with a database schema using the+** sqlite3changegroup_schema() API, then it is possible to combine changesets+** with different numbers of columns for a single table, provided that+** they are otherwise compatible. **-** If no error occurs, SQLITE_OK is returned.+** If the input changeset appears to be corrupt and the corruption is+** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition+** occurs during processing, this function returns SQLITE_NOMEM.+**+** In all cases, if an error occurs the state of the final contents of the+** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); @@ -11913,9 +12227,30 @@ ** Invert the changeset before applying it. This is equivalent to inverting ** a changeset using sqlite3changeset_invert() before applying it. It is ** an error to specify this flag with a patchset.+**+** <dt>SQLITE_CHANGESETAPPLY_IGNORENOOP <dd>+** Do not invoke the conflict handler callback for any changes that+** would not actually modify the database even if they were applied.+** Specifically, this means that the conflict handler is not invoked+** for:+** <ul>+** <li>a delete change if the row being deleted cannot be found,+** <li>an update change if the modified fields are already set to+** their new values in the conflicting row, or+** <li>an insert change if all fields of the conflicting row match+** the row being inserted.+** </ul>+**+** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>+** If this flag it set, then all foreign key constraints in the target+** database behave as if they were declared with "ON UPDATE NO ACTION ON+** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL+** or SET DEFAULT. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_INVERT 0x0002+#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004+#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 /* ** CAPI3REF: Constants Passed To The Conflict Handler@@ -12481,8 +12816,11 @@ ** created with the "columnsize=0" option. ** ** xColumnText:-** This function attempts to retrieve the text of column iCol of the-** current document. If successful, (*pz) is set to point to a buffer+** If parameter iCol is less than zero, or greater than or equal to the+** number of columns in the table, SQLITE_RANGE is returned.+**+** Otherwise, this function attempts to retrieve the text of column iCol of+** the current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values@@ -12492,8 +12830,10 @@ ** Returns the number of phrases in the current query expression. ** ** xPhraseSize:-** Returns the number of tokens in phrase iPhrase of the query. Phrases-** are numbered starting from zero.+** If parameter iCol is less than zero, or greater than or equal to the+** number of phrases in the current query, as returned by xPhraseCount,+** 0 is returned. Otherwise, this function returns the number of tokens in+** phrase iPhrase of the query. Phrases are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within@@ -12509,12 +12849,13 @@ ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value-** output by xInstCount().+** output by xInstCount(). If iIdx is less than zero or greater than+** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. **-** Usually, output parameter *piPhrase is set to the phrase number, *piCol+** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the-** first token of the phrase. Returns SQLITE_OK if successful, or an error-** code (i.e. SQLITE_NOMEM) if an error occurs.+** first token of the phrase. SQLITE_OK is returned if successful, or an+** error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the ** "detail=none" or "detail=column" option.@@ -12540,6 +12881,10 @@ ** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. **+** If parameter iPhrase is less than zero, or greater than or equal to+** the number of phrases in the query, as returned by xPhraseCount(),+** this function returns SQLITE_RANGE.+** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.@@ -12654,6 +12999,39 @@ ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above.+**+** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)+** This is used to access token iToken of phrase iPhrase of the current+** query. Before returning, output parameter *ppToken is set to point+** to a buffer containing the requested token, and *pnToken to the+** size of this buffer in bytes.+**+** If iPhrase or iToken are less than zero, or if iPhrase is greater than+** or equal to the number of phrases in the query as reported by+** xPhraseCount(), or if iToken is equal to or greater than the number of+** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken+ are both zeroed.+**+** The output text is not a copy of the query text that specified the+** token. It is the output of the tokenizer module. For tokendata=1+** tables, this includes any embedded 0x00 and trailing data.+**+** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)+** This is used to access token iToken of phrase hit iIdx within the+** current row. If iIdx is less than zero or greater than or equal to the+** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,+** output variable (*ppToken) is set to point to a buffer containing the+** matching document token, and (*pnToken) to the size of that buffer in+** bytes. This API is not available if the specified token matches a+** prefix query term. In that case both output variables are always set+** to 0.+**+** The output text is not a copy of the document text that was tokenized.+** It is the output of the tokenizer module. For tokendata=1 tables, this+** includes any embedded 0x00 and trailing data.+**+** This API can be quite slow if used with an FTS5 table created with the+** "detail=none" or "detail=column" option. */ struct Fts5ExtensionApi { int iVersion; /* Currently always set to 3 */@@ -12691,6 +13069,13 @@ int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);++ /* Below this point are iVersion>=3 only */+ int (*xQueryToken)(Fts5Context*,+ int iPhrase, int iToken,+ const char **ppToken, int *pnToken+ );+ int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); }; /*@@ -12885,8 +13270,8 @@ ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only-** provide synonyms when tokenizing document text (method (2)) or query-** text (method (3)), not both. Doing so will not cause any errors, but is+** provide synonyms when tokenizing document text (method (3)) or query+** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer;@@ -12934,7 +13319,7 @@ int (*xCreateTokenizer)( fts5_api *pApi, const char *zName,- void *pContext,+ void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) );@@ -12943,7 +13328,7 @@ int (*xFindTokenizer)( fts5_api *pApi, const char *zName,- void **ppContext,+ void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -12951,7 +13336,7 @@ int (*xCreateFunction)( fts5_api *pApi, const char *zName,- void *pContext,+ void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) );
cbits/sqlite3ext.h view
@@ -361,6 +361,11 @@ int (*value_encoding)(sqlite3_value*); /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*);+ /* Version 3.43.0 and later */+ int (*stmt_explain)(sqlite3_stmt*,int);+ /* Version 3.44.0 and later */+ void *(*get_clientdata)(sqlite3*,const char*);+ int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; /*@@ -689,6 +694,11 @@ #define sqlite3_value_encoding sqlite3_api->value_encoding /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted+/* Version 3.43.0 and later */+#define sqlite3_stmt_explain sqlite3_api->stmt_explain+/* Version 3.44.0 and later */+#define sqlite3_get_clientdata sqlite3_api->get_clientdata+#define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
direct-sqlite.cabal view
@@ -1,5 +1,5 @@ name: direct-sqlite-version: 2.3.28+version: 2.3.29 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@@ -24,6 +24,7 @@ cbits/sqlite3ext.h changelog cabal-version: >= 1.10+tested-with: GHC == 8.8.4 || == 8.10.7 || == 9.0.2 || == 9.2.8 || == 9.4.8 || == 9.6.4 || == 9.8.1 source-repository head type: git@@ -49,17 +50,26 @@ default: True description: Enable json1 extension. +flag mathfunctions+ default: False+ description: Enable built-in mathematical functions++flag dbstat+ default: True+ description: Enable dbstat virtual table+ library- exposed-modules: Database.SQLite3- Database.SQLite3.Bindings- Database.SQLite3.Bindings.Types- Database.SQLite3.Direct- build-depends: base >= 4.11 && < 5- , bytestring >= 0.9.2.1- , text >= 0.11- default-language: Haskell2010- include-dirs: .- ghc-options: -Wall -fwarn-tabs+ exposed-modules: Database.SQLite3+ Database.SQLite3.Bindings+ Database.SQLite3.Bindings.Types+ Database.SQLite3.Direct+ build-depends: base >= 4.11 && < 5+ , bytestring >= 0.9.2.1+ , text >= 0.11+ build-tool-depends: hsc2hs:hsc2hs+ default-language: Haskell2010+ include-dirs: .+ ghc-options: -Wall -fwarn-tabs if flag(systemlib) extra-libraries: sqlite3@@ -84,6 +94,12 @@ if flag(json1) cc-options: -DSQLITE_ENABLE_JSON1++ if flag(mathfunctions)+ cc-options: -DSQLITE_ENABLE_MATH_FUNCTIONS++ if flag(dbstat)+ cc-options: -DSQLITE_ENABLE_DBSTAT_VTAB test-suite test type: exitcode-stdio-1.0
test/Main.hs view
@@ -8,7 +8,6 @@ import Control.Exception import Control.Monad (forM_, liftM3, unless) import Data.Functor.Identity-import Data.Text (Text) import Data.Text.Encoding.Error (UnicodeException(..)) import Data.Typeable import System.Directory ()@@ -55,6 +54,7 @@ , TestLabel "TypedColumns" . testTypedColumns , TestLabel "ColumnName" . testColumnName , TestLabel "Errors" . testErrors+ , TestLabel "ExtendedErrors". testExtendedErrors , TestLabel "Integrity" . testIntegrity , TestLabel "DecodeError" . testDecodeError , TestLabel "ResultStats" . testResultStats@@ -92,9 +92,6 @@ Left e -> return $ isUserError e Right _ -> return False -withStmt :: Database -> Text -> (Statement -> IO a) -> IO a-withStmt conn sql = bracket (prepare conn sql) finalize- testExec :: forall f. TestEnv f -> Test testExec TestEnv{..} = TestCase $ do exec conn ""@@ -115,7 +112,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+ withStatement conn "SELECT * FROM foo" $ \stmt -> do Row <- step stmt [SQLFloat 3.5, SQLNull] <- columns stmt Row <- step stmt@@ -184,14 +181,14 @@ chan <- newChan let logger = writeChan chan Direct.setTrace conn (Just logger)- withStmt conn "SELECT null" $ \stmt -> do+ withStatement conn "SELECT null" $ \stmt -> do Row <- step stmt res <- columns stmt Done <- step stmt assertEqual "tracing" [SQLNull] res Direct.Utf8 msg <- readChan chan assertEqual "tracing" "SELECT null" msg- withStmt conn "SELECT 1+?" $ \stmt -> do+ withStatement conn "SELECT 1+?" $ \stmt -> do bind stmt [SQLInteger 2] Row <- step stmt Done <- step stmt@@ -229,19 +226,19 @@ True <- shouldFail $ prepare conn "" True <- shouldFail $ prepare conn ";" withConn $ \conn -> do- withStmt conn+ withStatement conn "CREATE TABLE foo (a INT, b INT); \ \INSERT INTO foo VALUES (1, 2); \ \INSERT INTO foo VALUES (3, 4)" $ \stmt -> do Done <- step stmt return ()- withStmt conn+ withStatement conn "BEGIN; INSERT INTO foo VALUES (5, 6); COMMIT" $ \stmt -> do Done <- step stmt return ()- withStmt conn+ withStatement conn "SELECT * FROM foo" $ \stmt -> do Done <- step stmt -- No row was inserted, because only the CREATE TABLE@@ -338,7 +335,7 @@ testNamedBindParams :: forall f. TestEnv f -> Test testNamedBindParams TestEnv{..} = TestCase $ do withConn $ \conn -> do- withStmt conn "SELECT :foo / :bar" $ \stmt -> do+ withStatement conn "SELECT :foo / :bar" $ \stmt -> do -- Test that we get something back for known names Just fooIdx <- Direct.bindParameterIndex stmt ":foo" Just barIdx <- Direct.bindParameterIndex stmt ":bar"@@ -351,7 +348,7 @@ [SQLInteger 2] <- columns stmt Done <- step stmt return ()- withStmt conn "SELECT @n1+@n2" $ \stmt -> do+ withStatement conn "SELECT @n1+@n2" $ \stmt -> do -- Test that we get something back for known names Just _n1 <- Direct.bindParameterIndex stmt "@n1" Just _n2 <- Direct.bindParameterIndex stmt "@n2"@@ -360,7 +357,7 @@ Nothing <- Direct.bindParameterIndex stmt ":n1" Nothing <- Direct.bindParameterIndex stmt ":n2" return ()- withStmt conn "SELECT :foo / :bar,:t" $ \stmt -> do+ withStatement conn "SELECT :foo / :bar,:t" $ \stmt -> do bindNamed stmt [(":t", SQLText "txt"), (":foo", SQLInteger 6), (":bar", SQLInteger 2)] Row <- step stmt 2 <- columnCount stmt@@ -371,20 +368,20 @@ testColumns :: forall f. TestEnv f -> Test testColumns TestEnv{..} = TestCase $ do withConn $ \conn -> do- withStmt conn "CREATE TABLE foo (a INT)" command- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "CREATE TABLE foo (a INT)" command+ withStatement conn "SELECT * FROM foo" $ \stmt -> do 1 <- columnCount stmt exec conn "ALTER TABLE foo ADD COLUMN b INT" Done <- step stmt 2 <- columnCount stmt return ()- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "SELECT * FROM foo" $ \stmt -> do 2 <- columnCount stmt Done <- step stmt 2 <- columnCount stmt return ()- withStmt conn "INSERT INTO foo VALUES (1, 2)" command- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "INSERT INTO foo VALUES (1, 2)" command+ withStatement conn "SELECT * FROM foo" $ \stmt -> do 2 <- columnCount stmt Row <- step stmt 2 <- columnCount stmt@@ -392,9 +389,9 @@ Done <- step stmt 2 <- columnCount stmt return ()- withStmt conn "INSERT INTO foo VALUES (3, 4)" command- withStmt conn "INSERT INTO foo VALUES (5, 6)" command- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "INSERT INTO foo VALUES (3, 4)" command+ withStatement conn "INSERT INTO foo VALUES (5, 6)" command+ withStatement conn "SELECT * FROM foo" $ \stmt -> do 2 <- columnCount stmt exec conn "ALTER TABLE foo ADD COLUMN c INT" Row <- step stmt@@ -427,10 +424,10 @@ testTypedColumns :: forall f. TestEnv f -> 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+ withStatement conn "CREATE TABLE foo (a INT, b INT)" command+ withStatement conn "INSERT INTO foo VALUES (1, 2)" command+ withStatement conn "INSERT INTO foo VALUES (3, 4)" command+ withStatement conn "SELECT * FROM foo" $ \stmt -> do Row <- step stmt 2 <- columnCount stmt [SQLInteger 1, SQLInteger 2] <- typedColumns stmt [Nothing, Nothing]@@ -440,7 +437,7 @@ Done <- step stmt 2 <- columnCount stmt return ()- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "SELECT * FROM foo" $ \stmt -> do Row <- step stmt 2 <- columnCount stmt [SQLText "1", SQLText "2"] <- typedColumns stmt [Just TextColumn, Just TextColumn]@@ -463,7 +460,7 @@ exec conn "CREATE TABLE foo (id INTEGER PRIMARY KEY, abc TEXT, \"123\" REAL, über INT)" exec conn "INSERT INTO foo (abc, \"123\", über) VALUES ('hello', 3.14, 456)" - withStmt conn "SELECT id AS id, abc AS x, \"123\" AS y, über AS ü FROM foo"+ withStatement conn "SELECT id AS id, abc AS x, \"123\" AS y, über AS ü FROM foo" $ \stmt -> do let checkNames = do 4 <- columnCount stmt@@ -485,7 +482,7 @@ -- Column names without AS clauses may change in future versions of SQLite. -- This test will fail if they do.- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "SELECT * FROM foo" $ \stmt -> do 4 <- columnCount stmt Nothing <- columnName stmt (-1) Just "id" <- columnName stmt 0@@ -522,7 +519,7 @@ expectError conn ErrorConstraint ErrorConstraintNotNull$ exec conn "INSERT INTO bar VALUES (null)" - withStmt conn "SELECT ?" $ \stmt -> do+ withStatement conn "SELECT ?" $ \stmt -> do forM_ [-1, 0, 2] $ \i -> do expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42 expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull@@ -537,7 +534,7 @@ SQLInteger 42 <- column stmt 0 return () - withStmt conn "SELECT 1" $ \stmt -> do+ withStatement conn "SELECT 1" $ \stmt -> do forM_ [-1, 0, 1, 2] $ \i -> do expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42 expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull@@ -547,14 +544,14 @@ SQLInteger 1 <- column stmt 0 return () - withStmt conn "SELECT :bar" $ \stmt -> do+ withStatement conn "SELECT :bar" $ \stmt -> do shouldFail $ bindNamed stmt [(":missing", SQLInteger 42)] bindNamed stmt [(":bar", SQLInteger 1)] Row <- step stmt SQLInteger 1 <- column stmt 0 return () - withStmt conn "SELECT ?5" $ \stmt -> do+ withStatement conn "SELECT ?5" $ \stmt -> do forM_ [-1, 0, 6, 7] $ \i -> do expectError conn ErrorRange ErrorRange $ bindSQLData stmt i $ SQLInteger 42 expectError conn ErrorRange ErrorRange $ bindSQLData stmt i SQLNull@@ -569,7 +566,7 @@ -- throw SQLITE_ABORT. withConnShared $ \conn -> do foo123456 conn- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "SELECT * FROM foo" $ \stmt -> do -- "DROP TABLE foo" should succeed, since the statement -- isn't running yet. exec conn "DROP TABLE foo"@@ -632,13 +629,45 @@ \INSERT INTO foo VALUES (3, 4); \ \INSERT INTO foo VALUES (5, 6)" +testExtendedErrors :: forall f . TestEnv f -> Test+testExtendedErrors TestEnv{..} = TestCase $ do+ -- opening a connection with extended results mode+ conn <- open2 ":memory:" [SQLOpenReadWrite, SQLOpenCreate, SQLOpenExResCode] SQLVFSDefault+ exec conn "CREATE TABLE foo (a INT NOT NULL, b INT);"+ res <- Direct.exec conn "INSERT INTO foo (a, b) VALUES (NULL, 0);"+ case res of+ Left err ->+ assertEqual "testExtendedErrors: expected an extended error code, but got the wrong error code" err+ (ErrorConstraintNotNull, "NOT NULL constraint failed: foo.a")+ Right () ->+ assertFailure "testExtendedErrors: exec should have return extended error code, but succeeded"+ close conn++ -- setting a connection to extended results mode after it's opened+ withConn $ \conn -> do+ exec conn "CREATE TABLE foo (a INT UNIQUE);"+ exec conn "INSERT INTO foo (a) VALUES (1);"++ res <- Direct.exec conn "INSERT INTO foo (a) VALUES (1);"+ assertEqual "testExtendedErrors: expected a primary error code" res+ (Left (ErrorConstraint, "UNIQUE constraint failed: foo.a"))++ res2 <- Direct.setExtendedResultCodes conn True+ case res2 of+ Left err -> assertFailure $+ "testExtendedErrors: failed to enable extended result codes, got error " <> show err+ Right () -> do+ res3 <- Direct.exec conn "INSERT INTO foo (a) VALUES (1);"+ assertEqual "testExtendedErrors: expected an extended error code" res3+ (Left (ErrorConstraintUnique, "UNIQUE constraint failed: foo.a"))+ -- Make sure data stored in a table comes back as-is. 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)"- withStmt conn "INSERT INTO foo VALUES (?, ?, ?, ?, ?)" $ \insert ->- withStmt conn "SELECT * FROM foo" $ \select -> do+ withStatement conn "INSERT INTO foo VALUES (?, ?, ?, ?, ?)" $ \insert ->+ withStatement conn "SELECT * FROM foo" $ \select -> do let test = testWith (===) testWith f values = do@@ -667,7 +696,7 @@ testDecodeError :: forall f. TestEnv f -> Test testDecodeError TestEnv{..} = TestCase $ do- withStmt conn "SELECT ?" $ \stmt -> do+ withStatement conn "SELECT ?" $ \stmt -> do Right () <- Direct.bindText stmt 1 invalidUtf8 Row <- step stmt Left (DecodeError "Database.SQLite3.columnText: Invalid UTF-8" _)@@ -678,12 +707,12 @@ -- data to a table on disk and reading it back. withConnShared $ \conn -> do exec conn "CREATE TABLE testDecodeError (a TEXT)"- withStmt conn "INSERT INTO testDecodeError VALUES (?)" $ \stmt -> do+ withStatement conn "INSERT INTO testDecodeError VALUES (?)" $ \stmt -> do Right () <- Direct.bindText stmt 1 invalidUtf8 Done <- step stmt return () withConnShared $ \conn -> do- withStmt conn "SELECT * FROM testDecodeError" $ \stmt -> do+ withStatement conn "SELECT * FROM testDecodeError" $ \stmt -> do Row <- step stmt TextColumn <- columnType stmt 0 txt <- Direct.columnText stmt 0@@ -743,7 +772,7 @@ testStatementSql :: forall f. TestEnv f -> Test testStatementSql TestEnv{..} = TestCase $ do let q1 = "SELECT 1+1"- withStmt conn q1 $ \stmt -> do+ withStatement conn q1 $ \stmt -> do Just (Direct.Utf8 sql1) <- Direct.statementSql stmt T.encodeUtf8 q1 @=? sql1 @@ -751,7 +780,7 @@ testCustomFunction TestEnv{..} = TestCase $ do withConn $ \conn -> do createFunction conn "repeat" (Just 2) True repeatString- withStmt conn "SELECT repeat(3,'abc')" $ \stmt -> do+ withStatement conn "SELECT repeat(3,'abc')" $ \stmt -> do Row <- step stmt [SQLText "abcabcabc"] <- columns stmt Done <- step stmt@@ -785,7 +814,7 @@ exec conn "CREATE TABLE tbl (n INT)" exec conn "INSERT INTO tbl(n) VALUES (12), (-3), (7)" createAggregate conn "mysum" (Just 1) 0 mySumStep funcResultInt64- withStmt conn "SELECT mysum(n) FROM tbl" $ \stmt -> do+ withStatement conn "SELECT mysum(n) FROM tbl" $ \stmt -> do Row <- step stmt [SQLInteger 16] <- columns stmt Done <- step stmt@@ -805,7 +834,7 @@ exec conn "CREATE TABLE tbl (n TEXT)" exec conn "INSERT INTO tbl(n) VALUES ('dog'),('mouse'),('ox'),('cat')" createCollation conn "len" cmpLen- withStmt conn "SELECT * FROM tbl ORDER BY n COLLATE len" $ \stmt -> do+ withStatement conn "SELECT * FROM tbl ORDER BY n COLLATE len" $ \stmt -> do Row <- step stmt [SQLText "ox"] <- columns stmt Row <- step stmt@@ -836,7 +865,7 @@ assertEqual "blobRead" "cdef" s blobWrite blob "BC" 1 blobClose blob- withStmt conn "SELECT n FROM tbl" $ \stmt -> do+ withStatement conn "SELECT n FROM tbl" $ \stmt -> do Row <- step stmt s' <- columnBlob stmt 0 assertEqual "blobWrite" "aBCdefg" s'@@ -846,7 +875,7 @@ withConn $ \conn -> do exec conn "CREATE TABLE tbl (n INT)" - withStmt conn "INSERT INTO tbl VALUES (?)" $ \stmt -> do+ withStatement conn "INSERT INTO tbl VALUES (?)" $ \stmt -> do exec conn "BEGIN" forM_ [1..200] $ \i -> do reset stmt@@ -880,7 +909,7 @@ Right () -> do -- Make sure multi-row insert actually worked 2 <- changes conn- withStmt conn "SELECT * FROM foo" $ \stmt -> do+ withStatement conn "SELECT * FROM foo" $ \stmt -> do Row <- step stmt [SQLInteger 1, SQLInteger 2] <- columns stmt Row <- step stmt