@@ 1,6 1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.42.0. By combining all the individual C code files into this
+** version 3.43.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ 16,6 16,9 @@
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
+**
+** The content in this amalgamation comes from Fossil check-in
+** 310099cce5a487035fa535dd3002c59ac7f.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ 50,11 53,11 @@
** used on lines of code that actually
** implement parts of coverage testing.
**
-** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false
+** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false
** and the correct answer is still obtained,
** though perhaps more slowly.
**
-** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true
+** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true
** and the correct answer is still obtained,
** though perhaps more slowly.
**
@@ 456,9 459,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.42.0"
-#define SQLITE_VERSION_NUMBER 3042000
-#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0"
+#define SQLITE_VERSION "3.43.2"
+#define SQLITE_VERSION_NUMBER 3043002
+#define SQLITE_SOURCE_ID "2023-10-10 12:14:04 4310099cce5a487035fa535dd3002c59ac7f1d1bec68d7cf317fd3e769484790"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ 838,6 841,7 @@ SQLITE_API int sqlite3_exec(
#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))
@@ 1500,7 1504,7 @@ struct sqlite3_io_methods {
** 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]]
@@ 2764,7 2768,7 @@ struct sqlite3_mem_methods {
** 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]]
@@ 3045,6 3049,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
**
** ^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*);
@@ 3698,8 3703,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
** 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
@@ 4068,7 4075,7 @@ SQLITE_API int sqlite3_open_v2(
** 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>
@@ 4181,7 4188,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
/*
** 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
@@ 4729,6 4736,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
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
**
@@ 4891,7 4933,7 @@ typedef struct sqlite3_context sqlite3_context;
** 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
@@ 5570,14 5612,26 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
** ^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.
@@ 5794,7 5848,7 @@ SQLITE_API int sqlite3_create_window_function(
** [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>
@@ 8471,7 8525,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#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
@@ 9503,8 9558,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections
-** unlock-notify callback may also be canceled by closing the blocked
+** unlock-notify callback is cancelled. ^The blocked connections
+** unlock-notify callback may also be cancelled by closing the blocked
** connection using [sqlite3_close()].
**
** The unlock-notify callback is not reentrant. If an application invokes
@@ 9927,7 9982,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** [[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>
@@ 10117,7 10172,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
** 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
@@ 10546,7 10601,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** 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
@@ 13064,7 13119,7 @@ struct Fts5PhraseIter {
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 2 */
void *(*xUserData)(Fts5Context*);
@@ 13293,8 13348,8 @@ struct Fts5ExtensionApi {
** 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;
@@ 13342,7 13397,7 @@ struct fts5_api {
int (*xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_tokenizer *pTokenizer,
void (*xDestroy)(void*)
);
@@ 13351,7 13406,7 @@ struct fts5_api {
int (*xFindTokenizer)(
fts5_api *pApi,
const char *zName,
- void **ppContext,
+ void **ppUserData,
fts5_tokenizer *pTokenizer
);
@@ 13359,7 13414,7 @@ struct fts5_api {
int (*xCreateFunction)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
@@ 13470,7 13525,7 @@ struct fts5_api {
** level of recursion for each term. A stack overflow can result
** if the number of terms is too large. In practice, most SQL
** never has more than 3 or 4 terms. Use a value of 0 to disable
-** any limit on the number of terms in a compount SELECT.
+** any limit on the number of terms in a compound SELECT.
*/
#ifndef SQLITE_MAX_COMPOUND_SELECT
# define SQLITE_MAX_COMPOUND_SELECT 500
@@ 14573,8 14628,31 @@ typedef INT16_TYPE LogEst;
** the end of buffer S. This macro returns true if P points to something
** contained within the buffer S.
*/
-#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
+#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
+/*
+** P is one byte past the end of a large buffer. Return true if a span of bytes
+** between S..E crosses the end of that buffer. In other words, return true
+** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1.
+**
+** S is the start of the span. E is one byte past the end of end of span.
+**
+** P
+** |-----------------| FALSE
+** |-------|
+** S E
+**
+** P
+** |-----------------|
+** |-------| TRUE
+** S E
+**
+** P
+** |-----------------|
+** |-------| FALSE
+** S E
+*/
+#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P)))
/*
** Macros to determine whether the machine is big or little endian,
@@ 14808,7 14886,7 @@ struct BusyHandler {
/*
** Name of table that holds the database schema.
**
-** The PREFERRED names are used whereever possible. But LEGACY is also
+** The PREFERRED names are used wherever possible. But LEGACY is also
** used for backwards compatibility.
**
** 1. Queries can use either the PREFERRED or the LEGACY names
@@ 14922,6 15000,7 @@ typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
+typedef struct FpDecode FpDecode;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
@@ 14940,6 15019,7 @@ typedef struct Parse Parse;
typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
+typedef struct RCStr RCStr;
typedef struct RenameToken RenameToken;
typedef struct Returning Returning;
typedef struct RowSet RowSet;
@@ 15577,6 15657,10 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
# define enable_simulated_io_errors()
#endif
+#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
+SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*);
+#endif
+
#endif /* SQLITE_PAGER_H */
/************** End of pager.h ***********************************************/
@@ 15906,9 15990,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
-#endif
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
@@ 16383,7 16465,7 @@ typedef struct VdbeOpList VdbeOpList;
/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\
/* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\
-/* 32 */ 0x41, 0x01, 0x01, 0x01, 0x41, 0x01, 0x41, 0x41,\
+/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\
/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
@@ 16395,7 16477,7 @@ typedef struct VdbeOpList VdbeOpList;
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
-/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,\
+/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
@@ 16577,7 16659,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** The VdbeCoverage macros are used to set a coverage testing point
** for VDBE branch instructions. The coverage testing points are line
** numbers in the sqlite3.c source file. VDBE branch coverage testing
-** only works with an amalagmation build. That's ok since a VDBE branch
+** only works with an amalgamation build. That's ok since a VDBE branch
** coverage build designed for testing the test suite only. No application
** should ever ship with VDBE branch coverage measuring turned on.
**
@@ 16595,7 16677,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** // NULL option is not possible
**
** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested
-** // in distingishing equal and not-equal.
+** // in distinguishing equal and not-equal.
**
** Every VDBE branch operation must be tagged with one of the macros above.
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
@@ 16605,7 16687,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** During testing, the test application will invoke
** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback
** routine that is invoked as each bytecode branch is taken. The callback
-** contains the sqlite3.c source line number ov the VdbeCoverage macro and
+** contains the sqlite3.c source line number of the VdbeCoverage macro and
** flags to indicate whether or not the branch was taken. The test application
** is responsible for keeping track of this and reporting byte-code branches
** that are never taken.
@@ 16944,7 17026,7 @@ SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
/*
** Default synchronous levels.
**
-** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ
+** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ
** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1.
**
** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS
@@ 16983,7 17065,7 @@ struct Db {
** An instance of the following structure stores a database schema.
**
** Most Schema objects are associated with a Btree. The exception is
-** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
+** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing.
** In shared cache mode, a single Schema object can be shared by multiple
** Btrees that refer to the same underlying BtShared object.
**
@@ 17094,7 17176,7 @@ struct Lookaside {
LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
- LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
+ LookasideSlot *pSmallInit; /* List of small buffers not previously used */
LookasideSlot *pSmallFree; /* List of available small buffers */
void *pMiddle; /* First byte past end of full-size buffers and
** the first byte of LOOKASIDE_SMALL buffers */
@@ 17111,7 17193,7 @@ struct LookasideSlot {
#define EnableLookaside db->lookaside.bDisable--;\
db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
-/* Size of the smaller allocations in two-size lookside */
+/* Size of the smaller allocations in two-size lookaside */
#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
# define LOOKASIDE_SMALL 0
#else
@@ 17450,6 17532,7 @@ struct sqlite3 {
#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
+#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ 17532,6 17615,7 @@ struct FuncDestructor {
** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
+** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!!
@@ 17539,7 17623,7 @@ struct FuncDestructor {
**
** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the
** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is
-** used internally and if set means tha the function has side effects.
+** used internally and if set means that the function has side effects.
** SQLITE_INNOCUOUS is used by application code and means "not unsafe".
** See multiple instances of tag-20230109-1.
*/
@@ 17550,6 17634,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
+#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
/* 0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
@@ 18129,7 18214,7 @@ struct FKey {
** foreign key.
**
** The OE_Default value is a place holder that means to use whatever
-** conflict resolution algorthm is required from context.
+** conflict resolution algorithm is required from context.
**
** The following symbolic values are used to record which type
** of conflict resolution action to take.
@@ 18543,7 18628,7 @@ struct Expr {
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 134217728 times likelihood
- ** TK_IN: ephemerial table holding RHS
+ ** TK_IN: ephemeral table holding RHS
** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
@@ 18625,6 18710,8 @@ struct Expr {
*/
#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
+#define ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0)
+#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=0)
#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
@@ 18813,7 18900,7 @@ struct SrcItem {
unsigned notCte :1; /* This item may not match a CTE */
unsigned isUsing :1; /* u3.pUsing is valid */
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
- unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */
+ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
@@ 19349,6 19436,9 @@ struct Parse {
int regRoot; /* Register holding root page number for new objects */
int nMaxArg; /* Max args passed to user function by sub-program */
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ 19362,12 19452,9 @@ struct Parse {
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
Returning *pReturning; /* The RETURNING clause */
} u1;
- u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
-#endif
+ LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
@@ 19491,6 19578,7 @@ struct AuthContext {
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
+#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
@@ 19633,6 19721,25 @@ struct sqlite3_str {
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
+/*
+** The following object is the header for an "RCStr" or "reference-counted
+** string". An RCStr is passed around and used like any other char*
+** that has been dynamically allocated. The important interface
+** differences:
+**
+** 1. RCStr strings are reference counted. They are deallocated
+** when the reference count reaches zero.
+**
+** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
+** sqlite3_free()
+**
+** 3. Make a (read-only) copy of a read-only RCStr string using
+** sqlite3RCStrRef().
+*/
+struct RCStr {
+ u64 nRCRef; /* Number of references */
+ /* Total structure size should be a multiple of 8 bytes for alignment */
+};
/*
** A pointer to this structure is used to communicate information
@@ 19659,7 19766,7 @@ typedef struct {
/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
** parameters are for temporary use during development, to help find
-** optimial values for parameters in the query planner. The should not
+** optimal values for parameters in the query planner. The should not
** be used on trunk check-ins. They are a temporary mechanism available
** for transient development builds only.
**
@@ 19685,6 19792,7 @@ struct Sqlite3Config {
u8 bUseCis; /* Use covering indices for full-scans */
u8 bSmallMalloc; /* Avoid large memory allocations if true */
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
+ u8 bUseLongDouble; /* Make use of long double */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ 19771,6 19879,7 @@ struct Walker {
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
int walkerDepth; /* Number of subqueries */
u16 eCode; /* A small processing code */
+ u16 mWFlags; /* Use-dependent flags */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
@@ 19810,6 19919,7 @@ struct DbFixer {
/* Forward declarations */
SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
@@ 20191,6 20301,20 @@ struct PrintfArguments {
sqlite3_value **apArg; /* The argument values */
};
+/*
+** An instance of this object receives the decoding of a floating point
+** value into an approximate decimal representation.
+*/
+struct FpDecode {
+ char sign; /* '+' or '-' */
+ char isSpecial; /* 1: Infinity 2: NaN */
+ int n; /* Significant digits in the decode */
+ int iDP; /* Location of the decimal point */
+ char *z; /* Start of significant digits */
+ char zBuf[24]; /* Storage for significant digits */
+};
+
+SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
@@ 20481,7 20605,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int)
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int);
SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int);
SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int);
-SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int);
+SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int);
SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
@@ 20630,6 20754,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
+
SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
SQLITE_PRIVATE i64 sqlite3RealToI64(double);
SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*);
@@ 20734,6 20859,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
+SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*));
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
@@ 20841,6 20967,11 @@ SQLITE_PRIVATE void sqlite3OomClear(sqlite3*);
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
+SQLITE_PRIVATE char *sqlite3RCStrRef(char*);
+SQLITE_PRIVATE void sqlite3RCStrUnref(char*);
+SQLITE_PRIVATE char *sqlite3RCStrNew(u64);
+SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64);
+
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64);
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
@@ 21092,6 21223,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
#define sqlite3SelectExprHeight(x) 0
#define sqlite3ExprCheckHeight(x,y)
#endif
+SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int);
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
@@ 21377,9 21509,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
"4_BYTE_ALIGNED_MALLOC",
#endif
-#ifdef SQLITE_64BIT_STATS
- "64BIT_STATS",
-#endif
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
@@ 21716,6 21845,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
#endif
+#ifdef SQLITE_LEGACY_JSON_VALID
+ "LEGACY_JSON_VALID",
+#endif
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
"LIKE_DOESNT_MATCH_BLOBS",
#endif
@@ 22350,6 22482,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
+ sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@@ 22579,6 22712,9 @@ typedef struct VdbeSorter VdbeSorter;
/* Elements of the linked list at Vdbe.pAuxData */
typedef struct AuxData AuxData;
+/* A cache of large TEXT or BLOB values in a VdbeCursor */
+typedef struct VdbeTxtBlbCache VdbeTxtBlbCache;
+
/* Types of VDBE cursors */
#define CURTYPE_BTREE 0
#define CURTYPE_SORTER 1
@@ 22610,6 22746,7 @@ struct VdbeCursor {
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
+ Bool colCache:1; /* pCache pointer is initialized and non-NULL */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
union { /* pBtx for isEphermeral. pAltMap otherwise */
Btree *pBtx; /* Separate file holding temporary table */
@@ 22650,6 22787,7 @@ struct VdbeCursor {
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
u64 maskUsed; /* Mask of columns used by this cursor */
#endif
+ VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
@@ 22662,13 22800,26 @@ struct VdbeCursor {
#define IsNullCursor(P) \
((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
-
/*
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
*/
#define CACHE_STALE 0
/*
+** Large TEXT or BLOB values can be slow to load, so we want to avoid
+** loading them more than once. For that reason, large TEXT and BLOB values
+** can be stored in a cache defined by this object, and attached to the
+** VdbeCursor using the pCache field.
+*/
+struct VdbeTxtBlbCache {
+ char *pCValue; /* A RCStr buffer to hold the value */
+ i64 iOffset; /* File offset of the row being cached */
+ int iCol; /* Column for which the cache is valid */
+ u32 cacheStatus; /* Vdbe.cacheCtr value */
+ u32 colCacheCtr; /* Column cache counter */
+};
+
+/*
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
@@ 22988,16 23139,18 @@ struct Vdbe {
u32 nWrite; /* Number of write operations that have occurred */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
+ u16 nResAlloc; /* Column slots allocated to aColName[] */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 eVdbeState; /* On of the VDBE_*_STATE values */
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
- bft explain:2; /* True if EXPLAIN present on SQL command */
+ bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */
bft changeCntOn:1; /* True to update the change-counter */
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
+ bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */
@@ 23044,7 23197,7 @@ struct PreUpdate {
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
- Table *pTab; /* Schema object being upated */
+ Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
};
@@ 23134,6 23287,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int);
SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
+SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
@@ 23730,8 23884,8 @@ struct DateTime {
*/
static int getDigits(const char *zDate, const char *zFormat, ...){
/* The aMx[] array translates the 3rd character of each format
- ** spec into a max size: a b c d e f */
- static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 };
+ ** spec into a max size: a b c d e f */
+ static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 };
va_list ap;
int cnt = 0;
char nextC;
@@ 24072,17 24226,14 @@ static void computeYMD(DateTime *p){
** Compute the Hour, Minute, and Seconds from the julian day number.
*/
static void computeHMS(DateTime *p){
- int s;
+ int day_ms, day_min; /* milliseconds, minutes into the day */
if( p->validHMS ) return;
computeJD(p);
- s = (int)((p->iJD + 43200000) % 86400000);
- p->s = s/1000.0;
- s = (int)p->s;
- p->s -= s;
- p->h = s/3600;
- s -= p->h*3600;
- p->m = s/60;
- p->s += s - p->m*60;
+ day_ms = (int)((p->iJD + 43200000) % 86400000);
+ p->s = (day_ms % 60000)/1000.0;
+ day_min = day_ms/60000;
+ p->m = day_min % 60;
+ p->h = day_min / 60;
p->rawS = 0;
p->validHMS = 1;
}
@@ 24262,6 24413,25 @@ static const struct {
};
/*
+** If the DateTime p is raw number, try to figure out if it is
+** a julian day number of a unix timestamp. Set the p value
+** appropriately.
+*/
+static void autoAdjustDate(DateTime *p){
+ if( !p->rawS || p->validJD ){
+ p->rawS = 0;
+ }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
+ && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
+ ){
+ double r = p->s*1000.0 + 210866760000000.0;
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlite3_int64)(r + 0.5);
+ p->validJD = 1;
+ p->rawS = 0;
+ }
+}
+
+/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
**
@@ 24304,19 24474,8 @@ static int parseModifier(
*/
if( sqlite3_stricmp(z, "auto")==0 ){
if( idx>1 ) return 1; /* IMP: R-33611-57934 */
- if( !p->rawS || p->validJD ){
- rc = 0;
- p->rawS = 0;
- }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
- && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
- ){
- r = p->s*1000.0 + 210866760000000.0;
- clearYMD_HMS_TZ(p);
- p->iJD = (sqlite3_int64)(r + 0.5);
- p->validJD = 1;
- p->rawS = 0;
- rc = 0;
- }
+ autoAdjustDate(p);
+ rc = 0;
}
break;
}
@@ 24482,18 24641,73 @@ static int parseModifier(
case '9': {
double rRounder;
int i;
- for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
+ int Y,M,D,h,m,x;
+ const char *z2 = z;
+ char z0 = z[0];
+ for(n=1; z[n]; n++){
+ if( z[n]==':' ) break;
+ if( sqlite3Isspace(z[n]) ) break;
+ if( z[n]=='-' ){
+ if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break;
+ if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
+ }
+ }
if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
- rc = 1;
+ assert( rc==1 );
break;
}
- if( z[n]==':' ){
+ if( z[n]=='-' ){
+ /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the
+ ** specified number of years, months, and days. MM is limited to
+ ** the range 0-11 and DD is limited to 0-30.
+ */
+ if( z0!='+' && z0!='-' ) break; /* Must start with +/- */
+ if( n==5 ){
+ if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break;
+ }else{
+ assert( n==6 );
+ if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break;
+ z++;
+ }
+ if( M>=12 ) break; /* M range 0..11 */
+ if( D>=31 ) break; /* D range 0..30 */
+ computeYMD_HMS(p);
+ p->validJD = 0;
+ if( z0=='-' ){
+ p->Y -= Y;
+ p->M -= M;
+ D = -D;
+ }else{
+ p->Y += Y;
+ p->M += M;
+ }
+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+ p->Y += x;
+ p->M -= x*12;
+ computeJD(p);
+ p->validHMS = 0;
+ p->validYMD = 0;
+ p->iJD += (i64)D*86400000;
+ if( z[11]==0 ){
+ rc = 0;
+ break;
+ }
+ if( sqlite3Isspace(z[11])
+ && getDigits(&z[12], "20c:20e", &h, &m)==2
+ ){
+ z2 = &z[12];
+ n = 2;
+ }else{
+ break;
+ }
+ }
+ if( z2[n]==':' ){
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
** specified number of hours, minutes, seconds, and fractional seconds
** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
** omitted.
*/
- const char *z2 = z;
+
DateTime tx;
sqlite3_int64 day;
if( !sqlite3Isdigit(*z2) ) z2++;
@@ 24503,7 24717,7 @@ static int parseModifier(
tx.iJD -= 43200000;
day = tx.iJD/86400000;
tx.iJD -= day*86400000;
- if( z[0]=='-' ) tx.iJD = -tx.iJD;
+ if( z0=='-' ) tx.iJD = -tx.iJD;
computeJD(p);
clearYMD_HMS_TZ(p);
p->iJD += tx.iJD;
@@ 24519,7 24733,7 @@ static int parseModifier(
if( n>10 || n<3 ) break;
if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
computeJD(p);
- rc = 1;
+ assert( rc==1 );
rRounder = r<0 ? -0.5 : +0.5;
for(i=0; i<ArraySize(aXformType); i++){
if( aXformType[i].nName==n
@@ 24528,7 24742,6 @@ static int parseModifier(
){
switch( i ){
case 4: { /* Special processing to add months */
- int x;
assert( strcmp(aXformType[i].zName,"month")==0 );
computeYMD_HMS(p);
p->M += (int)r;
@@ 24687,7 24900,7 @@ static void datetimeFunc(
zBuf[16] = '0' + (x.m)%10;
zBuf[17] = ':';
if( x.useSubsec ){
- s = (int)1000.0*x.s;
+ s = (int)(1000.0*x.s + 0.5);
zBuf[18] = '0' + (s/10000)%10;
zBuf[19] = '0' + (s/1000)%10;
zBuf[20] = '.';
@@ 24734,7 24947,7 @@ static void timeFunc(
zBuf[4] = '0' + (x.m)%10;
zBuf[5] = ':';
if( x.useSubsec ){
- s = (int)1000.0*x.s;
+ s = (int)(1000.0*x.s + 0.5);
zBuf[6] = '0' + (s/10000)%10;
zBuf[7] = '0' + (s/1000)%10;
zBuf[8] = '.';
@@ 24805,7 25018,7 @@ static void dateFunc(
** %M minute 00-59
** %s seconds since 1970-01-01
** %S seconds 00-59
-** %w day of week 0-6 sunday==0
+** %w day of week 0-6 Sunday==0
** %W week of year 00-53
** %Y year 0000-9999
** %% %
@@ 24946,6 25159,117 @@ static void cdateFunc(
}
/*
+** timediff(DATE1, DATE2)
+**
+** Return the amount of time that must be added to DATE2 in order to
+** convert it into DATE2. The time difference format is:
+**
+** +YYYY-MM-DD HH:MM:SS.SSS
+**
+** The initial "+" becomes "-" if DATE1 occurs before DATE2. For
+** date/time values A and B, the following invariant should hold:
+**
+** datetime(A) == (datetime(B, timediff(A,B))
+**
+** Both DATE arguments must be either a julian day number, or an
+** ISO-8601 string. The unix timestamps are not supported by this
+** routine.
+*/
+static void timediffFunc(
+ sqlite3_context *context,
+ int NotUsed1,
+ sqlite3_value **argv
+){
+ char sign;
+ int Y, M;
+ DateTime d1, d2;
+ sqlite3_str sRes;
+ UNUSED_PARAMETER(NotUsed1);
+ if( isDate(context, 1, &argv[0], &d1) ) return;
+ if( isDate(context, 1, &argv[1], &d2) ) return;
+ computeYMD_HMS(&d1);
+ computeYMD_HMS(&d2);
+ if( d1.iJD>=d2.iJD ){
+ sign = '+';
+ Y = d1.Y - d2.Y;
+ if( Y ){
+ d2.Y = d1.Y;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ M = d1.M - d2.M;
+ if( M<0 ){
+ Y--;
+ M += 12;
+ }
+ if( M!=0 ){
+ d2.M = d1.M;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ while( d1.iJD<d2.iJD ){
+ M--;
+ if( M<0 ){
+ M = 11;
+ Y--;
+ }
+ d2.M--;
+ if( d2.M<1 ){
+ d2.M = 12;
+ d2.Y--;
+ }
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ d1.iJD -= d2.iJD;
+ d1.iJD += (u64)1486995408 * (u64)100000;
+ }else /* d1<d2 */{
+ sign = '-';
+ Y = d2.Y - d1.Y;
+ if( Y ){
+ d2.Y = d1.Y;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ M = d2.M - d1.M;
+ if( M<0 ){
+ Y--;
+ M += 12;
+ }
+ if( M!=0 ){
+ d2.M = d1.M;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ while( d1.iJD>d2.iJD ){
+ M--;
+ if( M<0 ){
+ M = 11;
+ Y--;
+ }
+ d2.M++;
+ if( d2.M>12 ){
+ d2.M = 1;
+ d2.Y++;
+ }
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ d1.iJD = d2.iJD - d1.iJD;
+ d1.iJD += (u64)1486995408 * (u64)100000;
+ }
+ d1.validYMD = 0;
+ d1.validHMS = 0;
+ d1.validTZ = 0;
+ computeYMD_HMS(&d1);
+ sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
+ sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
+ sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
+ sqlite3ResultStrAccum(context, &sRes);
+}
+
+
+/*
** current_timestamp()
**
** This function returns the same value as datetime('now').
@@ 25019,6 25343,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
PURE_DATE(time, -1, 0, 0, timeFunc ),
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
+ PURE_DATE(timediff, 2, 0, 0, timediffFunc ),
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
@@ 25172,7 25497,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
** transaction has been committed. Injecting a fault at this point
- ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
+ ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM
** but the transaction is committed anyway.
**
** The core must call OsFileControl() though, not OsFileControlHint(),
@@ 25793,7 26118,7 @@ static void *sqlite3MemMalloc(int nByte){
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since
-** cases where pPrior==0 will have been intecepted and dealt with
+** cases where pPrior==0 will have been intercepted and dealt with
** by higher-level routines.
*/
static void sqlite3MemFree(void *pPrior){
@@ 25881,7 26206,7 @@ static int sqlite3MemInit(void *NotUsed){
return SQLITE_OK;
}
len = sizeof(cpuCount);
- /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
+ /* One usually wants to use hw.activecpu for MT decisions, but not here */
sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
if( cpuCount>1 ){
/* defer MT decisions to system malloc */
@@ 28348,7 28673,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
/*
** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
-** are necessary under two condidtions: (1) Debug builds and (2) using
+** are necessary under two conditions: (1) Debug builds and (2) using
** home-grown mutexes. Encapsulate these conditions into a single #define.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
@@ 28849,7 29174,7 @@ struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
#ifdef SQLITE_DEBUG
- volatile int nRef; /* Number of enterances */
+ volatile int nRef; /* Number of entrances */
volatile DWORD owner; /* Thread holding this mutex */
volatile LONG trace; /* True to trace changes */
#endif
@@ 30221,57 30546,6 @@ static const et_info fmtinfo[] = {
** %!S Like %S but prefer the zName over the zAlias
*/
-/* Floating point constants used for rounding */
-static const double arRound[] = {
- 5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
- 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
-};
-
-/*
-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
-** conversions will work.
-*/
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** "*val" is a double such that 0.1 <= *val < 10.0
-** Return the ascii code for the leading digit of *val, then
-** multiply "*val" by 10.0 to renormalize.
-**
-** Example:
-** input: *val = 3.14159
-** output: *val = 1.4159 function return = '3'
-**
-** The counter *cnt is incremented each time. After counter exceeds
-** 16 (the number of significant digits in a 64-bit float) '0' is
-** always returned.
-*/
-static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
- int digit;
- LONGDOUBLE_TYPE d;
- if( (*cnt)<=0 ) return '0';
- (*cnt)--;
- digit = (int)*val;
- d = digit;
- digit += '0';
- *val = (*val - d)*10.0;
- return (char)digit;
-}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** "*val" is a u64. *msd is a divisor used to extract the
-** most significant digit of *val. Extract that most significant
-** digit and return it.
-*/
-static char et_getdigit_int(u64 *val, u64 *msd){
- u64 x = (*val)/(*msd);
- *val -= x*(*msd);
- if( *msd>=10 ) *msd /= 10;
- return '0' + (char)(x & 15);
-}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-
/*
** Set the StrAccum object to an error mode.
*/
@@ 30363,20 30637,15 @@ SQLITE_API void sqlite3_str_vappendf(
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
- LONGDOUBLE_TYPE realvalue; /* Value for real types */
- sqlite_uint64 msd; /* Divisor to get most-significant-digit
- ** of longvalue */
+ double realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char *zOut; /* Rendering buffer */
int nOut; /* Size of the rendering buffer */
char *zExtra = 0; /* Malloced memory used by some conversion */
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int exp, e2; /* exponent of real numbers */
- int nsd; /* Number of significant digits returned */
- double rounder; /* Used for rounding floating point values */
+ int exp, e2; /* exponent of real numbers */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
-#endif
+
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
@@ 30651,94 30920,61 @@ SQLITE_API void sqlite3_str_vappendf(
break;
case etFLOAT:
case etEXP:
- case etGENERIC:
+ case etGENERIC: {
+ FpDecode s;
+ int iRound;
+ int j;
+
if( bArgList ){
realvalue = getDoubleArg(pArgList);
}else{
realvalue = va_arg(ap,double);
}
-#ifdef SQLITE_OMIT_FLOATING_POINT
- length = 0;
-#else
if( precision<0 ) precision = 6; /* Set default precision */
#ifdef SQLITE_FP_PRECISION_LIMIT
if( precision>SQLITE_FP_PRECISION_LIMIT ){
precision = SQLITE_FP_PRECISION_LIMIT;
}
#endif
- if( realvalue<0.0 ){
- realvalue = -realvalue;
- prefix = '-';
+ if( xtype==etFLOAT ){
+ iRound = -precision;
+ }else if( xtype==etGENERIC ){
+ iRound = precision;
}else{
- prefix = flag_prefix;
+ iRound = precision+1;
}
- exp = 0;
- if( xtype==etGENERIC && precision>0 ) precision--;
- testcase( precision>0xfff );
- if( realvalue<1.0e+16
- && realvalue==(LONGDOUBLE_TYPE)(longvalue = (u64)realvalue)
- ){
- /* Number is a pure integer that can be represented as u64 */
- for(msd=1; msd*10<=longvalue; msd *= 10, exp++){}
- if( exp>precision && xtype!=etFLOAT ){
- u64 rnd = msd/2;
- int kk = precision;
- while( kk-- > 0 ){ rnd /= 10; }
- longvalue += rnd;
- }
- }else{
- msd = 0;
- longvalue = 0; /* To prevent a compiler warning */
- idx = precision & 0xfff;
- rounder = arRound[idx%10];
- while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; }
- if( xtype==etFLOAT ){
- double rx = (double)realvalue;
- sqlite3_uint64 u;
- int ex;
- memcpy(&u, &rx, sizeof(u));
- ex = -1023 + (int)((u>>52)&0x7ff);
- if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16;
- realvalue += rounder;
- }
- if( sqlite3IsNaN((double)realvalue) ){
- if( flag_zeropad ){
- bufpt = "null";
- length = 4;
+ sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
+ if( s.isSpecial ){
+ if( s.isSpecial==2 ){
+ bufpt = flag_zeropad ? "null" : "NaN";
+ length = sqlite3Strlen30(bufpt);
+ break;
+ }else if( flag_zeropad ){
+ s.z[0] = '9';
+ s.iDP = 1000;
+ s.n = 1;
+ }else{
+ memcpy(buf, "-Inf", 5);
+ bufpt = buf;
+ if( s.sign=='-' ){
+ /* no-op */
+ }else if( flag_prefix ){
+ buf[0] = flag_prefix;
}else{
- bufpt = "NaN";
- length = 3;
+ bufpt++;
}
+ length = sqlite3Strlen30(bufpt);
break;
}
-
- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
- if( ALWAYS(realvalue>0.0) ){
- LONGDOUBLE_TYPE scale = 1.0;
- while( realvalue>=1e100*scale && exp<=350){ scale*=1e100;exp+=100;}
- while( realvalue>=1e10*scale && exp<=350 ){ scale*=1e10; exp+=10; }
- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
- realvalue /= scale;
- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
- if( exp>350 ){
- if( flag_zeropad ){
- realvalue = 9.0;
- exp = 999;
- }else{
- bufpt = buf;
- buf[0] = prefix;
- memcpy(buf+(prefix!=0),"Inf",4);
- length = 3+(prefix!=0);
- break;
- }
- }
- if( xtype!=etFLOAT ){
- realvalue += rounder;
- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
- }
- }
}
+ if( s.sign=='-' ){
+ prefix = '-';
+ }else{
+ prefix = flag_prefix;
+ }
+
+ exp = s.iDP-1;
+ if( xtype==etGENERIC && precision>0 ) precision--;
/*
** If the field type is etGENERIC, then convert to either etEXP
@@ 30758,9 30994,8 @@ SQLITE_API void sqlite3_str_vappendf(
if( xtype==etEXP ){
e2 = 0;
}else{
- e2 = exp;
+ e2 = s.iDP - 1;
}
- nsd = 16 + flag_altform2*10;
bufpt = buf;
{
i64 szBufNeeded; /* Size of a temporary buffer needed */
@@ 30778,16 31013,12 @@ SQLITE_API void sqlite3_str_vappendf(
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
+ j = 0;
if( e2<0 ){
*(bufpt++) = '0';
- }else if( msd>0 ){
- for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit_int(&longvalue,&msd);
- if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
- }
}else{
for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ *(bufpt++) = j<s.n ? s.z[j++] : '0';
if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
}
}
@@ 30797,19 31028,12 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
- for(e2++; e2<0; precision--, e2++){
- assert( precision>0 );
+ for(e2++; e2<0 && precision>0; precision--, e2++){
*(bufpt++) = '0';
}
/* Significant digits after the decimal point */
- if( msd>0 ){
- while( (precision--)>0 ){
- *(bufpt++) = et_getdigit_int(&longvalue,&msd);
- }
- }else{
- while( (precision--)>0 ){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
- }
+ while( (precision--)>0 ){
+ *(bufpt++) = j<s.n ? s.z[j++] : '0';
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
@@ 30825,6 31049,7 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* Add the "eNNN" suffix */
if( xtype==etEXP ){
+ exp = s.iDP - 1;
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
@@ 30858,8 31083,8 @@ SQLITE_API void sqlite3_str_vappendf(
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
-#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break;
+ }
case etSIZE:
if( !bArgList ){
*(va_arg(ap,int*)) = pAccum->nChar;
@@ 31583,6 31808,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
va_end(ap);
}
+
+/*****************************************************************************
+** Reference counted string storage
+*****************************************************************************/
+
+/*
+** Increase the reference count of the string by one.
+**
+** The input parameter is returned.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ p->nRCRef++;
+ return z;
+}
+
+/*
+** Decrease the reference count by one. Free the string when the
+** reference count reaches zero.
+*/
+SQLITE_PRIVATE void sqlite3RCStrUnref(char *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef>0 );
+ if( p->nRCRef>=2 ){
+ p->nRCRef--;
+ }else{
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Create a new string that is capable of holding N bytes of text, not counting
+** the zero byte at the end. The string is uninitialized.
+**
+** The reference count is initially 1. Call sqlite3RCStrUnref() to free the
+** newly allocated string.
+**
+** This routine returns 0 on an OOM.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){
+ RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 );
+ if( p==0 ) return 0;
+ p->nRCRef = 1;
+ return (char*)&p[1];
+}
+
+/*
+** Change the size of the string so that it is able to hold N bytes.
+** The string might be reallocated, so return the new allocation.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){
+ RCStr *p = (RCStr*)z;
+ RCStr *pNew;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef==1 );
+ pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1);
+ if( pNew==0 ){
+ sqlite3_free(p);
+ return 0;
+ }else{
+ return (char*)&pNew[1];
+ }
+}
+
/************** End of printf.c **********************************************/
/************** Begin file treeview.c ****************************************/
/*
@@ 32230,7 32524,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
};
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
assert( pExpr->pRight );
- assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
+ assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op
+ == TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
zUniOp = azOp[x];
break;
@@ 33889,7 34184,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
/*
** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
** or to bypass normal error detection during testing in order to let
-** execute proceed futher downstream.
+** execute proceed further downstream.
**
** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The
** sqlite3FaultSim() function only returns non-zero during testing.
@@ 34006,6 34301,23 @@ SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){
*/
SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){
if( rc==SQLITE_IOERR_NOMEM ) return;
+#ifdef SQLITE_USE_SEH
+ if( rc==SQLITE_IOERR_IN_PAGE ){
+ int ii;
+ int iErr;
+ sqlite3BtreeEnterAll(db);
+ for(ii=0; ii<db->nDb; ii++){
+ if( db->aDb[ii].pBt ){
+ iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt));
+ if( iErr ){
+ db->iSysErrno = iErr;
+ }
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ return;
+ }
+#endif
rc &= 0xff;
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
@@ 34251,43 34563,40 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){
return h;
}
-/*
-** Compute 10 to the E-th power. Examples: E==1 results in 10.
-** E==2 results in 100. E==50 results in 1.0e50.
+/* Double-Double multiplication. (x[0],x[1]) *= (y,yy)
**
-** This routine only works for values of E between 1 and 341.
+** Reference:
+** T. J. Dekker, "A Floating-Point Technique for Extending the
+** Available Precision". 1971-07-26.
*/
-static LONGDOUBLE_TYPE sqlite3Pow10(int E){
-#if defined(_MSC_VER)
- static const LONGDOUBLE_TYPE x[] = {
- 1.0e+001L,
- 1.0e+002L,
- 1.0e+004L,
- 1.0e+008L,
- 1.0e+016L,
- 1.0e+032L,
- 1.0e+064L,
- 1.0e+128L,
- 1.0e+256L
- };
- LONGDOUBLE_TYPE r = 1.0;
- int i;
- assert( E>=0 && E<=307 );
- for(i=0; E!=0; i++, E >>=1){
- if( E & 1 ) r *= x[i];
- }
- return r;
-#else
- LONGDOUBLE_TYPE x = 10.0;
- LONGDOUBLE_TYPE r = 1.0;
- while(1){
- if( E & 1 ) r *= x;
- E >>= 1;
- if( E==0 ) break;
- x *= x;
- }
- return r;
-#endif
+static void dekkerMul2(volatile double *x, double y, double yy){
+ /*
+ ** The "volatile" keywords on parameter x[] and on local variables
+ ** below are needed force intermediate results to be truncated to
+ ** binary64 rather than be carried around in an extended-precision
+ ** format. The truncation is necessary for the Dekker algorithm to
+ ** work. Intel x86 floating point might omit the truncation without
+ ** the use of volatile.
+ */
+ volatile double tx, ty, p, q, c, cc;
+ double hx, hy;
+ u64 m;
+ memcpy(&m, (void*)&x[0], 8);
+ m &= 0xfffffffffc000000LL;
+ memcpy(&hx, &m, 8);
+ tx = x[0] - hx;
+ memcpy(&m, &y, 8);
+ m &= 0xfffffffffc000000LL;
+ memcpy(&hy, &m, 8);
+ ty = y - hy;
+ p = hx*hy;
+ q = hx*ty + tx*hy;
+ c = p+q;
+ cc = p - c + q + tx*ty;
+ cc = x[0]*yy + x[1]*y + cc;
+ x[0] = c + cc;
+ x[1] = c - x[0];
+ x[1] += cc;
}
/*
@@ 34328,12 34637,11 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
- i64 s = 0; /* significand */
+ u64 s = 0; /* significand */
int d = 0; /* adjust exponent for shifting decimal point */
int esign = 1; /* sign of exponent */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
- double result;
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
@@ 34373,7 34681,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
while( z<zEnd && sqlite3Isdigit(*z) ){
s = s*10 + (*z - '0');
z+=incr; nDigit++;
- if( s>=((LARGEST_INT64-9)/10) ){
+ if( s>=((LARGEST_UINT64-9)/10) ){
/* skip non-significant significand digits
** (increase exponent by d to shift decimal left) */
while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
@@ 34388,7 34696,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) ){
- if( s<((LARGEST_INT64-9)/10) ){
+ if( s<((LARGEST_UINT64-9)/10) ){
s = s*10 + (*z - '0');
d--;
nDigit++;
@@ 34428,79 34736,89 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
do_atof_calc:
- /* adjust exponent by d, and update sign */
- e = (e*esign) + d;
- if( e<0 ) {
- esign = -1;
- e *= -1;
- } else {
- esign = 1;
+ /* Zero is a special case */
+ if( s==0 ){
+ *pResult = sign<0 ? -0.0 : +0.0;
+ goto atof_return;
}
- if( s==0 ) {
- /* In the IEEE 754 standard, zero is signed. */
- result = sign<0 ? -(double)0 : (double)0;
- } else {
- /* Attempt to reduce exponent.
- **
- ** Branches that are not required for the correct answer but which only
- ** help to obtain the correct answer faster are marked with special
- ** comments, as a hint to the mutation tester.
- */
- while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
- if( esign>0 ){
- if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
- s *= 10;
- }else{
- if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
- s /= 10;
- }
- e--;
- }
+ /* adjust exponent by d, and update sign */
+ e = (e*esign) + d;
- /* adjust the sign of significand */
- s = sign<0 ? -s : s;
+ /* Try to adjust the exponent to make it smaller */
+ while( e>0 && s<(LARGEST_UINT64/10) ){
+ s *= 10;
+ e--;
+ }
+ while( e<0 && (s%10)==0 ){
+ s /= 10;
+ e++;
+ }
- if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
- result = (double)s;
+ if( e==0 ){
+ *pResult = s;
+ }else if( sqlite3Config.bUseLongDouble ){
+ LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
+ if( e>0 ){
+ while( e>=100 ){ e-=100; r *= 1.0e+100L; }
+ while( e>=10 ){ e-=10; r *= 1.0e+10L; }
+ while( e>=1 ){ e-=1; r *= 1.0e+01L; }
}else{
- /* attempt to handle extremely small/large numbers better */
- if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
- if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
- if( esign<0 ){
- result = s / scale;
- result /= 1.0e+308;
- }else{
- result = s * scale;
- result *= 1.0e+308;
- }
- }else{ assert( e>=342 );
- if( esign<0 ){
- result = 0.0*s;
- }else{
+ while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
+ while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
+ while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
+ }
+ assert( r>=0.0 );
+ if( r>+1.7976931348623157081452742373e+308L ){
#ifdef INFINITY
- result = INFINITY*s;
+ *pResult = +INFINITY;
#else
- result = 1e308*1e308*s; /* Infinity */
+ *pResult = 1.0e308*10.0;
#endif
- }
- }
- }else{
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
- if( esign<0 ){
- result = s / scale;
- }else{
- result = s * scale;
- }
+ }else{
+ *pResult = (double)r;
+ }
+ }else{
+ double rr[2];
+ u64 s2;
+ rr[0] = (double)s;
+ s2 = (u64)rr[0];
+ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+ if( e>0 ){
+ while( e>=100 ){
+ e -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( e>=10 ){
+ e -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( e>=1 ){
+ e -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
+ }
+ }else{
+ while( e<=-100 ){
+ e += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( e<=-10 ){
+ e += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( e<=-1 ){
+ e += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
}
}
+ *pResult = rr[0]+rr[1];
+ if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
}
+ if( sign<0 ) *pResult = -*pResult;
+ assert( !sqlite3IsNaN(*pResult) );
- /* store the result */
- *pResult = result;
-
- /* return true if number and no extra non-whitespace chracters after */
+atof_return:
+ /* return true if number and no extra non-whitespace characters after */
if( z==zEnd && nDigit>0 && eValid && eType>0 ){
return eType;
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
@@ 34636,7 34954,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
/* This test and assignment is needed only to suppress UB warnings
** from clang and -fsanitize=undefined. This test and assignment make
** the code a little larger and slower, and no harm comes from omitting
- ** them, but we must appaise the undefined-behavior pharisees. */
+ ** them, but we must appease the undefined-behavior pharisees. */
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
}else if( neg ){
*pNum = -(i64)u;
@@ 34714,7 35032,9 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
- return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
+ int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789"));
+ if( z[n] ) n++;
+ return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8);
}
}
@@ 34794,6 35114,153 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
}
/*
+** Decode a floating-point value into an approximate decimal
+** representation.
+**
+** Round the decimal representation to n significant digits if
+** n is positive. Or round to -n signficant digits after the
+** decimal point if n is negative. No rounding is performed if
+** n is zero.
+**
+** The significant digits of the decimal representation are
+** stored in p->z[] which is a often (but not always) a pointer
+** into the middle of p->zBuf[]. There are p->n significant digits.
+** The p->z[] array is *not* zero-terminated.
+*/
+SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
+ int i;
+ u64 v;
+ int e, exp = 0;
+ p->isSpecial = 0;
+ p->z = p->zBuf;
+
+ /* Convert negative numbers to positive. Deal with Infinity, 0.0, and
+ ** NaN. */
+ if( r<0.0 ){
+ p->sign = '-';
+ r = -r;
+ }else if( r==0.0 ){
+ p->sign = '+';
+ p->n = 1;
+ p->iDP = 1;
+ p->z = "0";
+ return;
+ }else{
+ p->sign = '+';
+ }
+ memcpy(&v,&r,8);
+ e = v>>52;
+ if( (e&0x7ff)==0x7ff ){
+ p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
+ p->n = 0;
+ p->iDP = 0;
+ return;
+ }
+
+ /* Multiply r by powers of ten until it lands somewhere in between
+ ** 1.0e+19 and 1.0e+17.
+ */
+ if( sqlite3Config.bUseLongDouble ){
+ LONGDOUBLE_TYPE rr = r;
+ if( rr>=1.0e+19 ){
+ while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
+ while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
+ while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
+ }else{
+ while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
+ while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
+ while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
+ }
+ v = (u64)rr;
+ }else{
+ /* If high-precision floating point is not available using "long double",
+ ** then use Dekker-style double-double computation to increase the
+ ** precision.
+ **
+ ** The error terms on constants like 1.0e+100 computed using the
+ ** decimal extension, for example as follows:
+ **
+ ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
+ */
+ double rr[2];
+ rr[0] = r;
+ rr[1] = 0.0;
+ if( rr[0]>9.223372036854774784e+18 ){
+ while( rr[0]>9.223372036854774784e+118 ){
+ exp += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( rr[0]>9.223372036854774784e+28 ){
+ exp += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( rr[0]>9.223372036854774784e+18 ){
+ exp += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
+ }
+ }else{
+ while( rr[0]<9.223372036854774784e-83 ){
+ exp -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( rr[0]<9.223372036854774784e+07 ){
+ exp -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( rr[0]<9.22337203685477478e+17 ){
+ exp -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
+ }
+ }
+ v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
+ }
+
+
+ /* Extract significant digits. */
+ i = sizeof(p->zBuf)-1;
+ assert( v>0 );
+ while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; }
+ assert( i>=0 && i<sizeof(p->zBuf)-1 );
+ p->n = sizeof(p->zBuf) - 1 - i;
+ assert( p->n>0 );
+ assert( p->n<sizeof(p->zBuf) );
+ p->iDP = p->n + exp;
+ if( iRound<0 ){
+ iRound = p->iDP - iRound;
+ if( iRound==0 && p->zBuf[i+1]>='5' ){
+ iRound = 1;
+ p->zBuf[i--] = '0';
+ p->n++;
+ p->iDP++;
+ }
+ }
+ if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
+ char *z = &p->zBuf[i+1];
+ if( iRound>mxRound ) iRound = mxRound;
+ p->n = iRound;
+ if( z[iRound]>='5' ){
+ int j = iRound-1;
+ while( 1 /*exit-by-break*/ ){
+ z[j]++;
+ if( z[j]<='9' ) break;
+ z[j] = '0';
+ if( j==0 ){
+ p->z[i--] = '1';
+ p->n++;
+ p->iDP++;
+ break;
+ }else{
+ j--;
+ }
+ }
+ }
+ }
+ p->z = &p->zBuf[i+1];
+ assert( i+p->n < sizeof(p->zBuf) );
+ while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
+}
+
+/*
** Try to convert z into an unsigned 32-bit integer. Return true on
** success and false if there is an error.
**
@@ 35321,7 35788,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
}
/*
-** Attempt to add, substract, or multiply the 64-bit signed value iB against
+** Attempt to add, subtract, or multiply the 64-bit signed value iB against
** the other 64-bit signed integer at *pA and store the result in *pA.
** Return 0 on success. Or if the operation would have resulted in an
** overflow, leave *pA unchanged and return 1.
@@ 35634,7 36101,7 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam
#define SQLITE_HWTIME_H
/*
-** The following routine only works on pentium-class (or newer) processors.
+** The following routine only works on Pentium-class (or newer) processors.
** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value. This can be used for high-res
** profiling.
@@ 35806,7 36273,7 @@ static void insertElement(
}
-/* Resize the hash table so that it cantains "new_size" buckets.
+/* Resize the hash table so that it contains "new_size" buckets.
**
** The hash table might fail to resize if sqlite3_malloc() fails or
** if the new size is the same as the prior size.
@@ 37192,7 37659,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){
** This source file is organized into divisions where the logic for various
** subfunctions is contained within the appropriate division. PLEASE
** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
-** in the correct division and should be clearly labeled.
+** in the correct division and should be clearly labelled.
**
** The layout of divisions is as follows:
**
@@ 37779,7 38246,7 @@ static int robustFchown(int fd, uid_t uid, gid_t gid){
/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "unix" VFSes. Return SQLITE_OK opon successfully updating the
+** "unix" VFSes. Return SQLITE_OK upon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
*/
@@ 38301,7 38768,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released. To work around this problem, each unixInodeInfo object
-** maintains a count of the number of pending locks on tha inode.
+** maintains a count of the number of pending locks on the inode.
** When an attempt is made to close an unixFile, if there are
** other unixFile open on the same inode that are holding locks, the call
** to close() the file descriptor is deferred until all of the locks clear.
@@ 38315,7 38782,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** not posix compliant. Under LinuxThreads, a lock created by thread
** A cannot be modified or overridden by a different thread B.
** Only thread A can modify the lock. Locking behavior is correct
-** if the appliation uses the newer Native Posix Thread Library (NPTL)
+** if the application uses the newer Native Posix Thread Library (NPTL)
** on linux - with NPTL a lock created by thread A can override locks
** in thread B. But there is no way to know at compile-time which
** threading library is being used. So there is no way to know at
@@ 38517,7 38984,7 @@ static void storeLastErrno(unixFile *pFile, int error){
}
/*
-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
+** Close all file descriptors accumulated in the unixInodeInfo->pUnused list.
*/
static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
@@ 38880,7 39347,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** slightly in order to be compatible with Windows95 systems simultaneously
** accessing the same database file, in case that is ever required.
**
- ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
+ ** Symbols defined in os.h identify the 'pending byte' and the 'reserved
** byte', each single bytes at well known offsets, and the 'shared byte
** range', a range of 510 bytes at a well known offset.
**
@@ 38888,7 39355,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** byte'. If this is successful, 'shared byte range' is read-locked
** and the lock on the 'pending byte' released. (Legacy note: When
** SQLite was first developed, Windows95 systems were still very common,
- ** and Widnows95 lacks a shared-lock capability. So on Windows95, a
+ ** and Windows95 lacks a shared-lock capability. So on Windows95, a
** single randomly selected by from the 'shared byte range' is locked.
** Windows95 is now pretty much extinct, but this work-around for the
** lack of shared-locks on Windows95 lives on, for backwards
@@ 38909,7 39376,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** obtaining a write-lock on the 'pending byte'. This ensures that no new
** SHARED locks can be obtained, but existing SHARED locks are allowed to
** persist. If the call to this function fails to obtain the EXCLUSIVE
- ** lock in this case, it holds the PENDING lock intead. The client may
+ ** lock in this case, it holds the PENDING lock instead. The client may
** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
** locks have cleared.
*/
@@ 38937,7 39404,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* Make sure the locking sequence is correct.
** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
+ ** (2) SQLite never explicitly requests a pending lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
@@ 40155,7 40622,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* Make sure the locking sequence is correct
** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
+ ** (2) SQLite never explicitly requests a pending lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
@@ 40271,7 40738,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
pInode->sharedByte, 1, 0)) ){
int failed2 = SQLITE_OK;
- /* now attemmpt to get the exclusive lock range */
+ /* now attempt to get the exclusive lock range */
failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
SHARED_SIZE, 1);
if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
@@ 40566,7 41033,7 @@ static int unixRead(
#endif
#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
+ /* Deal with as much of this read request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ 40718,7 41185,7 @@ static int unixWrite(
#endif
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
+ /* Deal with as much of this write request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ 40840,7 41307,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
** no-op. But go ahead and call fstat() to validate the file
** descriptor as we need a method to provoke a failure during
- ** coverate testing.
+ ** coverage testing.
*/
#ifdef SQLITE_NO_SYNC
{
@@ 43885,12 44352,17 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-#if OS_VXWORKS || _POSIX_C_SOURCE >= 199309L
+#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0
struct timespec sp;
-
sp.tv_sec = microseconds / 1000000;
sp.tv_nsec = (microseconds % 1000000) * 1000;
+
+ /* Almost all modern unix systems support nanosleep(). But if you are
+ ** compiling for one of the rare exceptions, you can use
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
+ ** usleep() is available) in order to bypass the use of nanosleep() */
nanosleep(&sp, NULL);
+
UNUSED_PARAMETER(NotUsed);
return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
@@ 46480,7 46952,7 @@ static struct win_syscall {
/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "win32" VFSes. Return SQLITE_OK opon successfully updating the
+** "win32" VFSes. Return SQLITE_OK upon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
*/
@@ 48060,7 48532,7 @@ static int winRead(
pFile->h, pBuf, amt, offset, pFile->locktype));
#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
+ /* Deal with as much of this read request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ 48138,7 48610,7 @@ static int winWrite(
pFile->h, pBuf, amt, offset, pFile->locktype));
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
+ /* Deal with as much of this write request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ 48248,7 48720,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
** all references to memory-mapped content are closed. That is doable,
** but involves adding a few branches in the common write code path which
** could slow down normal operations slightly. Hence, we have decided for
- ** now to simply make trancations a no-op if there are pending reads. We
+ ** now to simply make transactions a no-op if there are pending reads. We
** can maybe revisit this decision in the future.
*/
return SQLITE_OK;
@@ 48307,7 48779,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
#ifdef SQLITE_TEST
/*
** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occuring at the right times.
+** that syncs and fullsyncs are occurring at the right times.
*/
SQLITE_API int sqlite3_sync_count = 0;
SQLITE_API int sqlite3_fullsync_count = 0;
@@ 48664,7 49136,7 @@ static int winLock(sqlite3_file *id, int locktype){
*/
if( locktype==EXCLUSIVE_LOCK && res ){
assert( pFile->locktype>=SHARED_LOCK );
- res = winUnlockReadLock(pFile);
+ (void)winUnlockReadLock(pFile);
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
SHARED_SIZE, 0);
if( res ){
@@ 50068,6 50540,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
+ DWORD pid;
int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
int nMax, nBuf, nDir, nLen;
char *zBuf;
@@ 50280,7 50753,10 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
j = sqlite3Strlen30(zBuf);
sqlite3_randomness(15, &zBuf[j]);
+ pid = osGetCurrentProcessId();
for(i=0; i<15; i++, j++){
+ zBuf[j] += pid & 0xff;
+ pid >>= 8;
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
@@ 52645,7 53121,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
h = BITVEC_HASH(i++);
/* if there wasn't a hash collision, and this doesn't */
/* completely fill the hash, then just add it without */
- /* worring about sub-dividing and re-hashing. */
+ /* worrying about sub-dividing and re-hashing. */
if( !p->u.aHash[h] ){
if (p->nSet<(BITVEC_NINT-1)) {
goto bitvec_set_end;
@@ 52978,7 53454,7 @@ struct PCache {
** Return 1 if pPg is on the dirty list for pCache. Return 0 if not.
** This routine runs inside of assert() statements only.
*/
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
PgHdr *p;
for(p=pCache->pDirty; p; p=p->pDirtyNext){
@@ 52986,6 53462,16 @@ static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
}
return 0;
}
+static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
+ if( p==pPg ) return 0;
+ }
+ return 1;
+}
+#else
+# define pageOnDirtyList(A,B) 1
+# define pageNotOnDirtyList(A,B) 1
#endif
/*
@@ 53006,7 53492,7 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){
assert( pCache!=0 ); /* Every page has an associated PCache */
if( pPg->flags & PGHDR_CLEAN ){
assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
- assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */
+ assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */
}else{
assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
@@ 53142,7 53628,7 @@ static int numberOfCachePages(PCache *p){
return p->szCache;
}else{
i64 n;
- /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the
+ /* IMPLEMENTATION-OF: R-59858-46238 If the argument N is negative, then the
** number of cache pages is adjusted to be a number of pages that would
** use approximately abs(N*1024) bytes of memory based on the current
** page size. */
@@ 53630,7 54116,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
}
/*
-** Sort the list of pages in accending order by pgno. Pages are
+** Sort the list of pages in ascending order by pgno. Pages are
** connected by pDirty pointers. The pDirtyPrev pointers are
** corrupted by this sort.
**
@@ 53870,7 54356,7 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd
** If N is positive, then N pages worth of memory are allocated using a single
** sqlite3Malloc() call and that memory is used for the first N pages allocated.
** Or if N is negative, then -1024*N bytes of memory are allocated and used
-** for as many pages as can be accomodated.
+** for as many pages as can be accommodated.
**
** Only one of (2) or (3) can be used. Once the memory available to (2) or
** (3) is exhausted, subsequent allocations fail over to the general-purpose
@@ 53904,7 54390,7 @@ typedef struct PGroup PGroup;
** in memory directly after the associated page data, if the database is
** corrupt, code at the b-tree layer may overread the page buffer and
** read part of this structure before the corruption is detected. This
-** can cause a valgrind error if the unitialized gap is accessed. Using u16
+** can cause a valgrind error if the uninitialized gap is accessed. Using u16
** ensures there is no such gap, and therefore no bytes of uninitialized
** memory in the structure.
**
@@ 55124,7 55610,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
** The TEST primitive includes a "batch" number. The TEST primitive
** will only see elements that were inserted before the last change
** in the batch number. In other words, if an INSERT occurs between
-** two TESTs where the TESTs have the same batch nubmer, then the
+** two TESTs where the TESTs have the same batch number, then the
** value added by the INSERT will not be visible to the second TEST.
** The initial batch number is zero, so if the very first TEST contains
** a non-zero batch number, it will see all prior INSERTs.
@@ 55656,6 56142,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
# define sqlite3WalFramesize(z) 0
# define sqlite3WalFindFrame(x,y,z) 0
# define sqlite3WalFile(x) 0
+# undef SQLITE_USE_SEH
#else
#define WAL_SAVEPOINT_NDATA 4
@@ 55762,6 56249,10 @@ SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
#endif
+#ifdef SQLITE_USE_SEH
+SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*);
+#endif
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */
@@ 56047,7 56538,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** outstanding transactions have been abandoned, the pager is able to
** transition back to OPEN state, discarding the contents of the
** page-cache and any other in-memory state at the same time. Everything
-** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
+** is reloaded from disk (and, if necessary, hot-journal rollback performed)
** when a read-transaction is next opened on the pager (transitioning
** the pager into READER state). At that point the system has recovered
** from the error.
@@ 57420,7 57911,7 @@ static int readJournalHdr(
** + 4 bytes: super-journal name checksum.
** + 8 bytes: aJournalMagic[].
**
-** The super-journal page checksum is the sum of the bytes in thesuper-journal
+** The super-journal page checksum is the sum of the bytes in the super-journal
** name, where each byte is interpreted as a signed 8-bit integer.
**
** If zSuper is a NULL pointer (occurs for a single database transaction),
@@ 57473,7 57964,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){
}
pPager->journalOff += (nSuper+20);
- /* If the pager is in peristent-journal mode, then the physical
+ /* If the pager is in persistent-journal mode, then the physical
** journal-file may extend past the end of the super-journal name
** and 8 bytes of magic data just written to the file. This is
** dangerous because the code to rollback a hot-journal file
@@ 57643,7 58134,7 @@ static void pager_unlock(Pager *pPager){
/*
** This function is called whenever an IOERR or FULL error that requires
-** the pager to transition into the ERROR state may ahve occurred.
+** the pager to transition into the ERROR state may have occurred.
** The first argument is a pointer to the pager structure, the second
** the error-code about to be returned by a pager API function. The
** value returned is a copy of the second argument to this function.
@@ 57918,7 58409,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
/*
** Parameter aData must point to a buffer of pPager->pageSize bytes
-** of data. Compute and return a checksum based ont the contents of the
+** of data. Compute and return a checksum based on the contents of the
** page of data and the current value of pPager->cksumInit.
**
** This is not a real checksum. It is really just the sum of the
@@ 58884,7 59375,7 @@ static int pagerWalFrames(
assert( pPager->pWal );
assert( pList );
#ifdef SQLITE_DEBUG
- /* Verify that the page list is in accending order */
+ /* Verify that the page list is in ascending order */
for(p=pList; p && p->pDirty; p=p->pDirty){
assert( p->pgno < p->pDirty->pgno );
}
@@ 59015,7 59506,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
#ifndef SQLITE_OMIT_WAL
/*
** Check if the *-wal file that corresponds to the database opened by pPager
-** exists if the database is not empy, or verify that the *-wal file does
+** exists if the database is not empty, or verify that the *-wal file does
** not exist (by deleting it) if the database file is empty.
**
** If the database is not empty and the *-wal file exists, open the pager
@@ 60425,11 60916,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
-#else
-# define memJM 0
-#endif
int readOnly = 0; /* True if this is a read-only file */
int journalFileSize; /* Bytes to allocate for each journal fd */
char *zPathname = 0; /* Full path to database file */
@@ 60548,12 61035,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** specific formatting and order of the various filenames, so if the format
** changes here, be sure to change it there as well.
*/
+ assert( SQLITE_PTRSIZE==sizeof(Pager*) );
pPtr = (u8 *)sqlite3MallocZero(
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
journalFileSize * 2 + /* The two journal files */
- sizeof(pPager) + /* Space to hold a pointer */
+ SQLITE_PTRSIZE + /* Space to hold a pointer */
4 + /* Database prefix */
nPathname + 1 + /* database filename */
nUriByte + /* query parameters */
@@ 60574,7 61062,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
- memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
+ memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE;
/* Fill in the Pager.zFilename and pPager.zQueryParam fields */
pPtr += 4; /* Skip zero prefix */
@@ 60628,9 61116,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifndef SQLITE_OMIT_DESERIALIZE
pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
-#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
/* If the file was successfully opened for read/write access,
@@ 60767,7 61253,7 @@ act_like_temp_file:
/*
** Return the sqlite3_file for the main database given the name
-** of the corresonding WAL or Journal name as passed into
+** of the corresponding WAL or Journal name as passed into
** xOpen.
*/
SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
@@ 63052,7 63538,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
assert( pPager->eState!=PAGER_ERROR );
pPager->journalMode = (u8)eMode;
- /* When transistioning from TRUNCATE or PERSIST to any other journal
+ /* When transitioning from TRUNCATE or PERSIST to any other journal
** mode except WAL, unless the pager is in locking_mode=exclusive mode,
** delete the journal file.
*/
@@ 63480,6 63966,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
+#ifdef SQLITE_USE_SEH
+SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){
+ return sqlite3WalSystemErrno(pPager->pWal);
+}
+#endif
+
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
@@ 63770,7 64262,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0;
**
** Technically, the various VFSes are free to implement these locks however
** they see fit. However, compatibility is encouraged so that VFSes can
-** interoperate. The standard implemention used on both unix and windows
+** interoperate. The standard implementation used on both unix and windows
** is for the index number to indicate a byte offset into the
** WalCkptInfo.aLock[] array in the wal-index header. In other words, all
** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which
@@ 63846,7 64338,7 @@ struct WalIndexHdr {
** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
** for any aReadMark[] means that entry is unused. aReadMark[0] is
** a special case; its value is never used and it exists as a place-holder
-** to avoid having to offset aReadMark[] indexs by one. Readers holding
+** to avoid having to offset aReadMark[] indexes by one. Readers holding
** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
** directly from the database.
**
@@ 64014,7 64506,15 @@ struct Wal {
u32 iReCksum; /* On commit, recalculate checksums from here */
const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
+#ifdef SQLITE_USE_SEH
+ u32 lockMask; /* Mask of locks held */
+ void *pFree; /* Pointer to sqlite3_free() if exception thrown */
+ u32 *pWiValue; /* Value to write into apWiData[iWiPg] */
+ int iWiPg; /* Write pWiValue into apWiData[iWiPg] */
+ int iSysErrno; /* System error code following exception */
+#endif
#ifdef SQLITE_DEBUG
+ int nSehTry; /* Number of nested SEH_TRY{} blocks */
u8 lockError; /* True if a locking error has occurred */
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
@@ 64097,6 64597,113 @@ struct WalIterator {
)
/*
+** Structured Exception Handling (SEH) is a Windows-specific technique
+** for catching exceptions raised while accessing memory-mapped files.
+**
+** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and
+** deal with system-level errors that arise during WAL -shm file processing.
+** Without this compile-time option, any system-level faults that appear
+** while accessing the memory-mapped -shm file will cause a process-wide
+** signal to be deliver, which will more than likely cause the entire
+** process to exit.
+*/
+#ifdef SQLITE_USE_SEH
+#include <Windows.h>
+
+/* Beginning of a block of code in which an exception might occur */
+# define SEH_TRY __try { \
+ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \
+ VVA_ONLY(pWal->nSehTry++);
+
+/* The end of a block of code in which an exception might occur */
+# define SEH_EXCEPT(X) \
+ VVA_ONLY(pWal->nSehTry--); \
+ assert( pWal->nSehTry==0 ); \
+ } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X }
+
+/* Simulate a memory-mapping fault in the -shm file for testing purposes */
+# define SEH_INJECT_FAULT sehInjectFault(pWal)
+
+/*
+** The second argument is the return value of GetExceptionCode() for the
+** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code
+** indicates that the exception may have been caused by accessing the *-shm
+** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise.
+*/
+static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){
+ VVA_ONLY(pWal->nSehTry--);
+ if( eCode==EXCEPTION_IN_PAGE_ERROR ){
+ if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){
+ /* From MSDN: For this type of exception, the first element of the
+ ** ExceptionInformation[] array is a read-write flag - 0 if the exception
+ ** was thrown while reading, 1 if while writing. The second element is
+ ** the virtual address being accessed. The "third array element specifies
+ ** the underlying NTSTATUS code that resulted in the exception". */
+ pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2];
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/*
+** If one is configured, invoke the xTestCallback callback with 650 as
+** the argument. If it returns true, throw the same exception that is
+** thrown by the system if the *-shm file mapping is accessed after it
+** has been invalidated.
+*/
+static void sehInjectFault(Wal *pWal){
+ int res;
+ assert( pWal->nSehTry>0 );
+
+ res = sqlite3FaultSim(650);
+ if( res!=0 ){
+ ULONG_PTR aArg[3];
+ aArg[0] = 0;
+ aArg[1] = 0;
+ aArg[2] = (ULONG_PTR)res;
+ RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg);
+ }
+}
+
+/*
+** There are two ways to use this macro. To set a pointer to be freed
+** if an exception is thrown:
+**
+** SEH_FREE_ON_ERROR(0, pPtr);
+**
+** and to cancel the same:
+**
+** SEH_FREE_ON_ERROR(pPtr, 0);
+**
+** In the first case, there must not already be a pointer registered to
+** be freed. In the second case, pPtr must be the registered pointer.
+*/
+#define SEH_FREE_ON_ERROR(X,Y) \
+ assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y
+
+/*
+** There are two ways to use this macro. To arrange for pWal->apWiData[iPg]
+** to be set to pValue if an exception is thrown:
+**
+** SEH_SET_ON_ERROR(iPg, pValue);
+**
+** and to cancel the same:
+**
+** SEH_SET_ON_ERROR(0, 0);
+*/
+#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y
+
+#else
+# define SEH_TRY VVA_ONLY(pWal->nSehTry++);
+# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 );
+# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 );
+# define SEH_FREE_ON_ERROR(X,Y)
+# define SEH_SET_ON_ERROR(X,Y)
+#endif /* ifdef SQLITE_USE_SEH */
+
+
+/*
** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
** numbered from zero.
@@ 64168,6 64775,7 @@ static int walIndexPage(
int iPage, /* The page we seek */
volatile u32 **ppPage /* Write the page pointer here */
){
+ SEH_INJECT_FAULT;
if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
return walIndexPageRealloc(pWal, iPage, ppPage);
}
@@ 64179,6 64787,7 @@ static int walIndexPage(
*/
static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
assert( pWal->nWiData>0 && pWal->apWiData[0] );
+ SEH_INJECT_FAULT;
return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
}
@@ 64187,6 64796,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
*/
static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
assert( pWal->nWiData>0 && pWal->apWiData[0] );
+ SEH_INJECT_FAULT;
return (volatile WalIndexHdr*)pWal->apWiData[0];
}
@@ 64376,7 64986,7 @@ static int walDecodeFrame(
return 0;
}
- /* A frame is only valid if the page number is creater than zero.
+ /* A frame is only valid if the page number is greater than zero.
*/
pgno = sqlite3Get4byte(&aFrame[0]);
if( pgno==0 ){
@@ 64384,7 64994,7 @@ static int walDecodeFrame(
}
/* A frame is only valid if a checksum of the WAL header,
- ** all prior frams, the first 16 bytes of this frame-header,
+ ** all prior frames, the first 16 bytes of this frame-header,
** and the frame-data matches the checksum in the last 8
** bytes of this frame-header.
*/
@@ 64444,12 65054,18 @@ static int walLockShared(Wal *pWal, int lockIdx){
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
walLockName(lockIdx), rc ? "failed" : "ok"));
VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
+#ifdef SQLITE_USE_SEH
+ if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx);
+#endif
return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
if( pWal->exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
+#ifdef SQLITE_USE_SEH
+ pWal->lockMask &= ~(1 << lockIdx);
+#endif
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
@@ 64460,12 65076,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
walLockName(lockIdx), n, rc ? "failed" : "ok"));
VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
+#ifdef SQLITE_USE_SEH
+ if( rc==SQLITE_OK ){
+ pWal->lockMask |= (((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx));
+ }
+#endif
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
if( pWal->exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
+#ifdef SQLITE_USE_SEH
+ pWal->lockMask &= ~(((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx));
+#endif
WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
walLockName(lockIdx), n));
}
@@ 64557,6 65181,7 @@ static int walFramePage(u32 iFrame){
*/
static u32 walFramePgno(Wal *pWal, u32 iFrame){
int iHash = walFramePage(iFrame);
+ SEH_INJECT_FAULT;
if( iHash==0 ){
return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
}
@@ 64816,6 65441,7 @@ static int walIndexRecover(Wal *pWal){
/* Malloc a buffer to read frames into. */
szFrame = szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
+ SEH_FREE_ON_ERROR(0, aFrame);
if( !aFrame ){
rc = SQLITE_NOMEM_BKPT;
goto recovery_error;
@@ 64834,6 65460,7 @@ static int walIndexRecover(Wal *pWal){
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
assert( aShare!=0 || rc!=SQLITE_OK );
if( aShare==0 ) break;
+ SEH_SET_ON_ERROR(iPg, aShare);
pWal->apWiData[iPg] = aPrivate;
for(iFrame=iFirst; iFrame<=iLast; iFrame++){
@@ 64861,6 65488,7 @@ static int walIndexRecover(Wal *pWal){
}
}
pWal->apWiData[iPg] = aShare;
+ SEH_SET_ON_ERROR(0,0);
nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
nHdr32 = nHdr / sizeof(u32);
#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
@@ 64891,9 65519,11 @@ static int walIndexRecover(Wal *pWal){
}
}
#endif
+ SEH_INJECT_FAULT;
if( iFrame<=iLast ) break;
}
+ SEH_FREE_ON_ERROR(aFrame, 0);
sqlite3_free(aFrame);
}
@@ 64921,6 65551,7 @@ finished:
}else{
pInfo->aReadMark[i] = READMARK_NOT_USED;
}
+ SEH_INJECT_FAULT;
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc!=SQLITE_BUSY ){
goto recovery_error;
@@ 65078,7 65709,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
}
/*
-** Change the size to which the WAL file is trucated on each reset.
+** Change the size to which the WAL file is truncated on each reset.
*/
SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
if( pWal ) pWal->mxWalSize = iLimit;
@@ 65304,23 65935,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
- p = (WalIterator *)sqlite3_malloc64(nByte);
+ p = (WalIterator *)sqlite3_malloc64(nByte
+ + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
+ );
if( !p ){
return SQLITE_NOMEM_BKPT;
}
memset(p, 0, nByte);
p->nSegment = nSegment;
-
- /* Allocate temporary space used by the merge-sort routine. This block
- ** of memory will be freed before this function returns.
- */
- aTmp = (ht_slot *)sqlite3_malloc64(
- sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
- );
- if( !aTmp ){
- rc = SQLITE_NOMEM_BKPT;
- }
-
+ aTmp = (ht_slot*)&(((u8*)p)[nByte]);
+ SEH_FREE_ON_ERROR(0, p);
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
WalHashLoc sLoc;
@@ 65348,9 65972,8 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
}
}
- sqlite3_free(aTmp);
-
if( rc!=SQLITE_OK ){
+ SEH_FREE_ON_ERROR(p, 0);
walIteratorFree(p);
p = 0;
}
@@ 65576,13 66199,13 @@ static int walCheckpoint(
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
- u32 y = AtomicLoad(pInfo->aReadMark+i);
+ u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT;
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
- AtomicStore(pInfo->aReadMark+i, iMark);
+ AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT;
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc==SQLITE_BUSY ){
mxSafeFrame = y;
@@ 65603,8 66226,7 @@ static int walCheckpoint(
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
){
u32 nBackfill = pInfo->nBackfill;
-
- pInfo->nBackfillAttempted = mxSafeFrame;
+ pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
/* Sync the WAL to disk */
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
@@ 65635,6 66257,7 @@ static int walCheckpoint(
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
+ SEH_INJECT_FAULT;
if( AtomicLoad(&db->u1.isInterrupted) ){
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
break;
@@ 65664,7 66287,7 @@ static int walCheckpoint(
}
}
if( rc==SQLITE_OK ){
- AtomicStore(&pInfo->nBackfill, mxSafeFrame);
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
}
}
@@ 65686,6 66309,7 @@ static int walCheckpoint(
*/
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
assert( pWal->writeLock );
+ SEH_INJECT_FAULT;
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
rc = SQLITE_BUSY;
}else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
@@ 65717,6 66341,7 @@ static int walCheckpoint(
}
walcheckpoint_out:
+ SEH_FREE_ON_ERROR(pIter, 0);
walIteratorFree(pIter);
return rc;
}
@@ 65739,6 66364,93 @@ static void walLimitSize(Wal *pWal, i64 nMax){
}
}
+#ifdef SQLITE_USE_SEH
+/*
+** This is the "standard" exception handler used in a few places to handle
+** an exception thrown by reading from the *-shm mapping after it has become
+** invalid in SQLITE_USE_SEH builds. It is used as follows:
+**
+** SEH_TRY { ... }
+** SEH_EXCEPT( rc = walHandleException(pWal); )
+**
+** This function does three things:
+**
+** 1) Determines the locks that should be held, based on the contents of
+** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other
+** held locks are assumed to be transient locks that would have been
+** released had the exception not been thrown and are dropped.
+**
+** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free().
+**
+** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL
+**
+** 4) Returns SQLITE_IOERR.
+*/
+static int walHandleException(Wal *pWal){
+ if( pWal->exclusiveMode==0 ){
+ static const int S = 1;
+ static const int E = (1<<SQLITE_SHM_NLOCK);
+ int ii;
+ u32 mUnlock = pWal->lockMask & ~(
+ (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
+ | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
+ | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
+ );
+ for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){
+ if( (S<<ii) & mUnlock ) walUnlockShared(pWal, ii);
+ if( (E<<ii) & mUnlock ) walUnlockExclusive(pWal, ii, 1);
+ }
+ }
+ sqlite3_free(pWal->pFree);
+ pWal->pFree = 0;
+ if( pWal->pWiValue ){
+ pWal->apWiData[pWal->iWiPg] = pWal->pWiValue;
+ pWal->pWiValue = 0;
+ }
+ return SQLITE_IOERR_IN_PAGE;
+}
+
+/*
+** Assert that the Wal.lockMask mask, which indicates the locks held
+** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
+** and Wal.ckptLock variables. To be used as:
+**
+** assert( walAssertLockmask(pWal) );
+*/
+static int walAssertLockmask(Wal *pWal){
+ if( pWal->exclusiveMode==0 ){
+ static const int S = 1;
+ static const int E = (1<<SQLITE_SHM_NLOCK);
+ u32 mExpect = (
+ (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
+ | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
+ | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0)
+#endif
+ );
+ assert( mExpect==pWal->lockMask );
+ }
+ return 1;
+}
+
+/*
+** Return and zero the "system error" field set when an
+** EXCEPTION_IN_PAGE_ERROR exception is caught.
+*/
+SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){
+ int iRet = 0;
+ if( pWal ){
+ iRet = pWal->iSysErrno;
+ pWal->iSysErrno = 0;
+ }
+ return iRet;
+}
+
+#else
+# define walAssertLockmask(x) 1
+#endif /* ifdef SQLITE_USE_SEH */
+
/*
** Close a connection to a log file.
*/
@@ 65753,6 66465,8 @@ SQLITE_PRIVATE int sqlite3WalClose(
if( pWal ){
int isDelete = 0; /* True to unlink wal and wal-index files */
+ assert( walAssertLockmask(pWal) );
+
/* If an EXCLUSIVE lock can be obtained on the database file (using the
** ordinary, rollback-mode locking methods, this guarantees that the
** connection associated with this log file is the only connection to
@@ 65777,7 66491,7 @@ SQLITE_PRIVATE int sqlite3WalClose(
);
if( bPersist!=1 ){
/* Try to delete the WAL file if the checkpoint completed and
- ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
+ ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal
** mode (!bPersist) */
isDelete = 1;
}else if( pWal->mxWalSize>=0 ){
@@ 65844,7 66558,7 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
** give false-positive warnings about these accesses because the tools do not
** account for the double-read and the memory barrier. The use of mutexes
** here would be problematic as the memory being accessed is potentially
- ** shared among multiple processes and not all mutex implementions work
+ ** shared among multiple processes and not all mutex implementations work
** reliably in that environment.
*/
aHdr = walIndexHdr(pWal);
@@ 66295,6 67009,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
assert( pWal->nWiData>0 );
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
+ SEH_INJECT_FAULT;
if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
@@ 66344,7 67059,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
#endif
for(i=1; i<WAL_NREADER; i++){
- u32 thisMark = AtomicLoad(pInfo->aReadMark+i);
+ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT;
if( mxReadMark<=thisMark && thisMark<=mxFrame ){
assert( thisMark!=READMARK_NOT_USED );
mxReadMark = thisMark;
@@ 66410,7 67125,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** we can guarantee that the checkpointer that set nBackfill could not
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
*/
- pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1;
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
walShmBarrier(pWal);
if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
@@ 66426,6 67141,54 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
#ifdef SQLITE_ENABLE_SNAPSHOT
/*
+** This function does the work of sqlite3WalSnapshotRecover().
+*/
+static int walSnapshotRecover(
+ Wal *pWal, /* WAL handle */
+ void *pBuf1, /* Temp buffer pWal->szPage bytes in size */
+ void *pBuf2 /* Temp buffer pWal->szPage bytes in size */
+){
+ int szPage = (int)pWal->szPage;
+ int rc;
+ i64 szDb; /* Size of db file in bytes */
+
+ rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
+ if( rc==SQLITE_OK ){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ u32 i = pInfo->nBackfillAttempted;
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
+ WalHashLoc sLoc; /* Hash table location */
+ u32 pgno; /* Page number in db file */
+ i64 iDbOff; /* Offset of db file entry */
+ i64 iWalOff; /* Offset of wal file entry */
+
+ rc = walHashGet(pWal, walFramePage(i), &sLoc);
+ if( rc!=SQLITE_OK ) break;
+ assert( i - sLoc.iZero - 1 >=0 );
+ pgno = sLoc.aPgno[i-sLoc.iZero-1];
+ iDbOff = (i64)(pgno-1) * szPage;
+
+ if( iDbOff+szPage<=szDb ){
+ iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
+ rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
+ }
+
+ if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
+ break;
+ }
+ }
+
+ pInfo->nBackfillAttempted = i-1;
+ }
+ }
+
+ return rc;
+}
+
+/*
** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
** variable so that older snapshots can be accessed. To do this, loop
** through all wal frames from nBackfillAttempted to (nBackfill+1),
@@ 66450,50 67213,21 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
assert( pWal->readLock>=0 );
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
if( rc==SQLITE_OK ){
- volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
- int szPage = (int)pWal->szPage;
- i64 szDb; /* Size of db file in bytes */
-
- rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
- if( rc==SQLITE_OK ){
- void *pBuf1 = sqlite3_malloc(szPage);
- void *pBuf2 = sqlite3_malloc(szPage);
- if( pBuf1==0 || pBuf2==0 ){
- rc = SQLITE_NOMEM;
- }else{
- u32 i = pInfo->nBackfillAttempted;
- for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
- WalHashLoc sLoc; /* Hash table location */
- u32 pgno; /* Page number in db file */
- i64 iDbOff; /* Offset of db file entry */
- i64 iWalOff; /* Offset of wal file entry */
-
- rc = walHashGet(pWal, walFramePage(i), &sLoc);
- if( rc!=SQLITE_OK ) break;
- assert( i - sLoc.iZero - 1 >=0 );
- pgno = sLoc.aPgno[i-sLoc.iZero-1];
- iDbOff = (i64)(pgno-1) * szPage;
-
- if( iDbOff+szPage<=szDb ){
- iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
- rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
- }
-
- if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
- break;
- }
- }
-
- pInfo->nBackfillAttempted = i-1;
- }
+ void *pBuf1 = sqlite3_malloc(pWal->szPage);
+ void *pBuf2 = sqlite3_malloc(pWal->szPage);
+ if( pBuf1==0 || pBuf2==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pWal->ckptLock = 1;
+ SEH_TRY {
+ rc = walSnapshotRecover(pWal, pBuf1, pBuf2);
}
-
- sqlite3_free(pBuf1);
- sqlite3_free(pBuf2);
+ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ pWal->ckptLock = 0;
}
+
+ sqlite3_free(pBuf1);
+ sqlite3_free(pBuf2);
walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
}
@@ 66502,28 67236,20 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
#endif /* SQLITE_ENABLE_SNAPSHOT */
/*
-** Begin a read transaction on the database.
-**
-** This routine used to be called sqlite3OpenSnapshot() and with good reason:
-** it takes a snapshot of the state of the WAL and wal-index for the current
-** instant in time. The current thread will continue to use this snapshot.
-** Other threads might append new content to the WAL and wal-index but
-** that extra content is ignored by the current thread.
-**
-** If the database contents have changes since the previous read
-** transaction, then *pChanged is set to 1 before returning. The
-** Pager layer will use this to know that its cache is stale and
-** needs to be flushed.
+** This function does the work of sqlite3WalBeginReadTransaction() (see
+** below). That function simply calls this one inside an SEH_TRY{...} block.
*/
-SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
+static int walBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
#ifdef SQLITE_ENABLE_SNAPSHOT
+ int ckptLock = 0;
int bChanged = 0;
WalIndexHdr *pSnapshot = pWal->pSnapshot;
#endif
assert( pWal->ckptLock==0 );
+ assert( pWal->nSehTry>0 );
#ifdef SQLITE_ENABLE_SNAPSHOT
if( pSnapshot ){
@@ 66546,7 67272,7 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
if( rc!=SQLITE_OK ){
return rc;
}
- pWal->ckptLock = 1;
+ ckptLock = 1;
}
#endif
@@ 66610,16 67336,38 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
}
/* Release the shared CKPT lock obtained above. */
- if( pWal->ckptLock ){
+ if( ckptLock ){
assert( pSnapshot );
walUnlockShared(pWal, WAL_CKPT_LOCK);
- pWal->ckptLock = 0;
}
#endif
return rc;
}
/*
+** Begin a read transaction on the database.
+**
+** This routine used to be called sqlite3OpenSnapshot() and with good reason:
+** it takes a snapshot of the state of the WAL and wal-index for the current
+** instant in time. The current thread will continue to use this snapshot.
+** Other threads might append new content to the WAL and wal-index but
+** that extra content is ignored by the current thread.
+**
+** If the database contents have changes since the previous read
+** transaction, then *pChanged is set to 1 before returning. The
+** Pager layer will use this to know that its cache is stale and
+** needs to be flushed.
+*/
+SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
+ int rc;
+ SEH_TRY {
+ rc = walBeginReadTransaction(pWal, pChanged);
+ }
+ SEH_EXCEPT( rc = walHandleException(pWal); )
+ return rc;
+}
+
+/*
** Finish with a read transaction. All this does is release the
** read-lock.
*/
@@ 66639,7 67387,7 @@ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
** Return SQLITE_OK if successful, or an error code if an error occurs. If an
** error does occur, the final value of *piRead is undefined.
*/
-SQLITE_PRIVATE int sqlite3WalFindFrame(
+static int walFindFrame(
Wal *pWal, /* WAL handle */
Pgno pgno, /* Database page number to read data for */
u32 *piRead /* OUT: Frame number (or zero) */
@@ 66702,6 67450,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
}
nCollide = HASHTABLE_NSLOT;
iKey = walHash(pgno);
+ SEH_INJECT_FAULT;
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
@@ 66739,6 67488,30 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
}
/*
+** Search the wal file for page pgno. If found, set *piRead to the frame that
+** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
+** to zero.
+**
+** Return SQLITE_OK if successful, or an error code if an error occurs. If an
+** error does occur, the final value of *piRead is undefined.
+**
+** The difference between this function and walFindFrame() is that this
+** function wraps walFindFrame() in an SEH_TRY{...} block.
+*/
+SQLITE_PRIVATE int sqlite3WalFindFrame(
+ Wal *pWal, /* WAL handle */
+ Pgno pgno, /* Database page number to read data for */
+ u32 *piRead /* OUT: Frame number (or zero) */
+){
+ int rc;
+ SEH_TRY {
+ rc = walFindFrame(pWal, pgno, piRead);
+ }
+ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ return rc;
+}
+
+/*
** Read the contents of frame iRead from the wal file into buffer pOut
** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
** error code otherwise.
@@ 66819,12 67592,17 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
** time the read transaction on this connection was started, then
** the write is disallowed.
*/
- if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+ SEH_TRY {
+ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+ rc = SQLITE_BUSY_SNAPSHOT;
+ }
+ }
+ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+
+ if( rc!=SQLITE_OK ){
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
pWal->writeLock = 0;
- rc = SQLITE_BUSY_SNAPSHOT;
}
-
return rc;
}
@@ 66860,30 67638,33 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
Pgno iMax = pWal->hdr.mxFrame;
Pgno iFrame;
- /* Restore the clients cache of the wal-index header to the state it
- ** was in before the client began writing to the database.
- */
- memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
-
- for(iFrame=pWal->hdr.mxFrame+1;
- ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
- iFrame++
- ){
- /* This call cannot fail. Unless the page for which the page number
- ** is passed as the second argument is (a) in the cache and
- ** (b) has an outstanding reference, then xUndo is either a no-op
- ** (if (a) is false) or simply expels the page from the cache (if (b)
- ** is false).
- **
- ** If the upper layer is doing a rollback, it is guaranteed that there
- ** are no outstanding references to any page other than page 1. And
- ** page 1 is never written to the log until the transaction is
- ** committed. As a result, the call to xUndo may not fail.
+ SEH_TRY {
+ /* Restore the clients cache of the wal-index header to the state it
+ ** was in before the client began writing to the database.
*/
- assert( walFramePgno(pWal, iFrame)!=1 );
- rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
+ memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
+
+ for(iFrame=pWal->hdr.mxFrame+1;
+ ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
+ iFrame++
+ ){
+ /* This call cannot fail. Unless the page for which the page number
+ ** is passed as the second argument is (a) in the cache and
+ ** (b) has an outstanding reference, then xUndo is either a no-op
+ ** (if (a) is false) or simply expels the page from the cache (if (b)
+ ** is false).
+ **
+ ** If the upper layer is doing a rollback, it is guaranteed that there
+ ** are no outstanding references to any page other than page 1. And
+ ** page 1 is never written to the log until the transaction is
+ ** committed. As a result, the call to xUndo may not fail.
+ */
+ assert( walFramePgno(pWal, iFrame)!=1 );
+ rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
+ }
+ if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
- if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
+ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
}
return rc;
}
@@ 66927,7 67708,10 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
pWal->hdr.mxFrame = aWalData[0];
pWal->hdr.aFrameCksum[0] = aWalData[1];
pWal->hdr.aFrameCksum[1] = aWalData[2];
- walCleanupHash(pWal);
+ SEH_TRY {
+ walCleanupHash(pWal);
+ }
+ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
}
return rc;
@@ 67108,7 67892,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){
** Write a set of frames to the log. The caller must hold the write-lock
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
*/
-SQLITE_PRIVATE int sqlite3WalFrames(
+static int walFrames(
Wal *pWal, /* Wal handle to write to */
int szPage, /* Database page-size in bytes */
PgHdr *pList, /* List of dirty pages to write */
@@ 67219,7 68003,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
** checksums must be recomputed when the transaction is committed. */
if( iFirst && (p->pDirty || isCommit==0) ){
u32 iWrite = 0;
- VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
+ VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite);
assert( rc==SQLITE_OK || iWrite==0 );
if( iWrite>=iFirst ){
i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
@@ 67339,6 68123,29 @@ SQLITE_PRIVATE int sqlite3WalFrames(
}
/*
+** Write a set of frames to the log. The caller must hold the write-lock
+** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
+**
+** The difference between this function and walFrames() is that this
+** function wraps walFrames() in an SEH_TRY{...} block.
+*/
+SQLITE_PRIVATE int sqlite3WalFrames(
+ Wal *pWal, /* Wal handle to write to */
+ int szPage, /* Database page-size in bytes */
+ PgHdr *pList, /* List of dirty pages to write */
+ Pgno nTruncate, /* Database size after this commit */
+ int isCommit, /* True if this is a commit */
+ int sync_flags /* Flags to pass to OsSync() (or 0) */
+){
+ int rc;
+ SEH_TRY {
+ rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags);
+ }
+ SEH_EXCEPT( rc = walHandleException(pWal); )
+ return rc;
+}
+
+/*
** This routine is called to implement sqlite3_wal_checkpoint() and
** related interfaces.
**
@@ 67417,30 68224,33 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
/* Read the wal-index header. */
- if( rc==SQLITE_OK ){
- walDisableBlocking(pWal);
- rc = walIndexReadHdr(pWal, &isChanged);
- (void)walEnableBlocking(pWal);
- if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
- sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
+ SEH_TRY {
+ if( rc==SQLITE_OK ){
+ walDisableBlocking(pWal);
+ rc = walIndexReadHdr(pWal, &isChanged);
+ (void)walEnableBlocking(pWal);
+ if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
+ sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
+ }
}
- }
-
- /* Copy data from the log to the database file. */
- if( rc==SQLITE_OK ){
- if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
- }
+ /* Copy data from the log to the database file. */
+ if( rc==SQLITE_OK ){
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
+ }
- /* If no error occurred, set the output variables. */
- if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
- if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
- if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
+ /* If no error occurred, set the output variables. */
+ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
+ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
+ SEH_INJECT_FAULT;
+ if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
+ }
}
}
+ SEH_EXCEPT( rc = walHandleException(pWal); )
if( isChanged ){
/* If a new wal-index header was loaded before the checkpoint was
@@ 67517,7 68327,9 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
** locks are taken in this case). Nor should the pager attempt to
** upgrade to exclusive-mode following such an error.
*/
+#ifndef SQLITE_USE_SEH
assert( pWal->readLock>=0 || pWal->lockError );
+#endif
assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
if( op==0 ){
@@ 67618,16 68430,19 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
*/
SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){
int rc;
- rc = walLockShared(pWal, WAL_CKPT_LOCK);
- if( rc==SQLITE_OK ){
- WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
- if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
- || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted
- ){
- rc = SQLITE_ERROR_SNAPSHOT;
- walUnlockShared(pWal, WAL_CKPT_LOCK);
+ SEH_TRY {
+ rc = walLockShared(pWal, WAL_CKPT_LOCK);
+ if( rc==SQLITE_OK ){
+ WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
+ if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
+ || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted
+ ){
+ rc = SQLITE_ERROR_SNAPSHOT;
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
+ }
}
}
+ SEH_EXCEPT( rc = walHandleException(pWal); )
return rc;
}
@@ 67866,7 68681,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 0x81 0x00 becomes 0x00000080
** 0x82 0x00 becomes 0x00000100
** 0x80 0x7f becomes 0x0000007f
-** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
+** 0x81 0x91 0xd1 0xac 0x78 becomes 0x12345678
** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
**
** Variable length integers are used for rowids and to hold the number of
@@ 67949,7 68764,7 @@ typedef struct CellInfo CellInfo;
** page that has been loaded into memory. The information in this object
** is derived from the raw on-disk page content.
**
-** As each database page is loaded into memory, the pager allocats an
+** As each database page is loaded into memory, the pager allocates an
** instance of this object and zeros the first 8 bytes. (This is the
** "extra" information associated with each page of the pager.)
**
@@ 68405,7 69220,7 @@ struct IntegrityCk {
/*
** get2byteAligned(), unlike get2byte(), requires that its argument point to a
-** two-byte aligned address. get2bytea() is only used for accessing the
+** two-byte aligned address. get2byteAligned() is only used for accessing the
** cell addresses in a btree header.
*/
#if SQLITE_BYTEORDER==4321
@@ 68582,7 69397,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
**
** There is a corresponding leave-all procedures.
**
-** Enter the mutexes in accending order by BtShared pointer address
+** Enter the mutexes in ascending order by BtShared pointer address
** to avoid the possibility of deadlock when two threads with
** two or more btrees in common both try to lock all their btrees
** at the same instant.
@@ 68714,6 69529,7 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
/************** End of btmutex.c *********************************************/
/************** Begin file btree.c *******************************************/
+
/*
** 2004 April 6
**
@@ 70249,7 71065,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
Pgno ovfl;
- if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
+ if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
testcase( pSrc!=pPage );
*pRC = SQLITE_CORRUPT_BKPT;
return;
@@ 70350,7 71166,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
iCellStart = get2byte(&data[hdr+5]);
if( nCell>0 ){
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
- memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
+ memcpy(temp, data, usableSize);
src = temp;
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
@@ 70574,7 71390,7 @@ static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
**
** Even though the freeblock list was checked by btreeComputeFreeSpace(),
** that routine will not detect overlap between cells or freeblocks. Nor
-** does it detect cells or freeblocks that encrouch into the reserved bytes
+** does it detect cells or freeblocks that encroach into the reserved bytes
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
@@ 71033,68 71849,41 @@ SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){
/*
** Get a page from the pager and initialize it.
-**
-** If pCur!=0 then the page is being fetched as part of a moveToChild()
-** call. Do additional sanity checking on the page in this case.
-** And if the fetch fails, this routine must decrement pCur->iPage.
-**
-** The page is fetched as read-write unless pCur is not NULL and is
-** a read-only cursor.
-**
-** If an error occurs, then *ppPage is undefined. It
-** may remain unchanged, or it may be set to an invalid value.
*/
static int getAndInitPage(
BtShared *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
MemPage **ppPage, /* Write the page pointer here */
- BtCursor *pCur, /* Cursor to receive the page, or NULL */
int bReadOnly /* True for a read-only page */
){
int rc;
DbPage *pDbPage;
+ MemPage *pPage;
assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pCur==0 || ppPage==&pCur->pPage );
- assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
- assert( pCur==0 || pCur->iPage>0 );
if( pgno>btreePagecount(pBt) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto getAndInitPage_error1;
+ *ppPage = 0;
+ return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
if( rc ){
- goto getAndInitPage_error1;
+ *ppPage = 0;
+ return rc;
}
- *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
- if( (*ppPage)->isInit==0 ){
+ pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+ if( pPage->isInit==0 ){
btreePageFromDbPage(pDbPage, pgno, pBt);
- rc = btreeInitPage(*ppPage);
+ rc = btreeInitPage(pPage);
if( rc!=SQLITE_OK ){
- goto getAndInitPage_error2;
+ releasePage(pPage);
+ *ppPage = 0;
+ return rc;
}
}
- assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
- assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
-
- /* If obtaining a child page for a cursor, we must verify that the page is
- ** compatible with the root page. */
- if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
- rc = SQLITE_CORRUPT_PGNO(pgno);
- goto getAndInitPage_error2;
- }
+ assert( pPage->pgno==pgno || CORRUPT_DB );
+ assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
+ *ppPage = pPage;
return SQLITE_OK;
-
-getAndInitPage_error2:
- releasePage(*ppPage);
-getAndInitPage_error1:
- if( pCur ){
- pCur->iPage--;
- pCur->pPage = pCur->apPage[pCur->iPage];
- }
- testcase( pgno==0 );
- assert( pgno!=0 || rc!=SQLITE_OK );
- return rc;
}
/*
@@ 71177,7 71966,7 @@ static void pageReinit(DbPage *pData){
** call to btreeInitPage() will likely return SQLITE_CORRUPT.
** But no harm is done by this. And it is very important that
** btreeInitPage() be called on every btree page so we make
- ** the call for every page that comes in for re-initing. */
+ ** the call for every page that comes in for re-initializing. */
btreeInitPage(pPage);
}
}
@@ 71356,6 72145,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
+ /* Suppress false-positive compiler warning from PVS-Studio */
+ memset(&zDbHeader[16], 0, 8);
+
pBt = sqlite3MallocZero( sizeof(*pBt) );
if( pBt==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ 71572,7 72364,7 @@ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
- ** does cause a valgrind error when the 1 or 2 bytes of unitialized
+ ** does cause a valgrind error when the 1 or 2 bytes of uninitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
@@ 71807,7 72599,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
/*
** Return the number of bytes of space at the end of every page that
-** are intentually left unused. This is the "reserved" space that is
+** are intentionally left unused. This is the "reserved" space that is
** sometimes used by extensions.
**
** The value returned is the larger of the current reserve size and
@@ 72054,7 72846,6 @@ static int lockBtree(BtShared *pBt){
){
goto page1_init_failed;
}
- pBt->btsFlags |= BTS_PAGESIZE_FIXED;
assert( (pageSize & 7)==0 );
/* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
** integer at offset 20 is the number of bytes of space at the end of
@@ 72074,6 72865,7 @@ static int lockBtree(BtShared *pBt){
releasePageOne(pPage1);
pBt->usableSize = usableSize;
pBt->pageSize = pageSize;
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
freeTempSpace(pBt);
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
pageSize-usableSize);
@@ 72093,6 72885,7 @@ static int lockBtree(BtShared *pBt){
if( usableSize<480 ){
goto page1_init_failed;
}
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
pBt->pageSize = pageSize;
pBt->usableSize = usableSize;
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ 72271,7 73064,11 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
+static SQLITE_NOINLINE int btreeBeginTrans(
+ Btree *p, /* The btree in which to start the transaction */
+ int wrflag, /* True to start a write transaction */
+ int *pSchemaVersion /* Put schema version number here, if not NULL */
+){
BtShared *pBt = p->pBt;
Pager *pPager = pBt->pPager;
int rc = SQLITE_OK;
@@ 72443,6 73240,28 @@ trans_begun:
sqlite3BtreeLeave(p);
return rc;
}
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
+ BtShared *pBt;
+ if( p->sharable
+ || p->inTrans==TRANS_NONE
+ || (p->inTrans==TRANS_READ && wrflag!=0)
+ ){
+ return btreeBeginTrans(p,wrflag,pSchemaVersion);
+ }
+ pBt = p->pBt;
+ if( pSchemaVersion ){
+ *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
+ }
+ if( wrflag ){
+ /* This call makes sure that the pager has the correct number of
+ ** open savepoints. If the second parameter is greater than 0 and
+ ** the sub-journal is not already open, then it will be opened here.
+ */
+ return sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ }else{
+ return SQLITE_OK;
+ }
+}
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ 73538,7 74357,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){
pCur->curFlags &= ~BTCF_Pinned;
}
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
** payload to which the cursor is pointing.
@@ 73550,7 74368,6 @@ SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){
return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) +
(i64)(pCur->info.pPayload - pCur->pPage->aData);
}
-#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
/*
** Return the number of bytes of payload for the entry that pCur is
@@ 73576,7 74393,7 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){
** routine always returns 2147483647 (which is the largest record
** that SQLite can handle) or more. But returning a smaller value might
** prevent large memory allocations when trying to interpret a
-** corrupt datrabase.
+** corrupt database.
**
** The current implementation merely returns the size of the underlying
** database file.
@@ 74038,6 74855,7 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
** vice-versa).
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
+ int rc;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
@@ 74051,8 74869,18 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
- return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur,
- pCur->curPagerFlags);
+ rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags);
+ assert( pCur->pPage!=0 || rc!=SQLITE_OK );
+ if( rc==SQLITE_OK
+ && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
+ ){
+ releasePage(pCur->pPage);
+ rc = SQLITE_CORRUPT_PGNO(newPgno);
+ }
+ if( rc ){
+ pCur->pPage = pCur->apPage[--pCur->iPage];
+ }
+ return rc;
}
#ifdef SQLITE_DEBUG
@@ 74159,7 74987,7 @@ static int moveToRoot(BtCursor *pCur){
sqlite3BtreeClearCursor(pCur);
}
rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
- 0, pCur->curPagerFlags);
+ pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ 74271,7 75099,7 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
*pRes = 0;
rc = moveToLeftmost(pCur);
}else if( rc==SQLITE_EMPTY ){
- assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) );
*pRes = 1;
rc = SQLITE_OK;
}
@@ 74376,7 75204,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
/* If the requested key is one more than the previous key, then
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
- ** is still obtained without this case, only a little more slowely */
+ ** is still obtained without this case, only a little more slowly. */
if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
@@ 74772,10 75600,36 @@ bypass_moveto_root:
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
- pCur->ix = (u16)lwr;
- rc = moveToChild(pCur, chldPg);
- if( rc ) break;
- }
+
+ /* This block is similar to an in-lined version of:
+ **
+ ** pCur->ix = (u16)lwr;
+ ** rc = moveToChild(pCur, chldPg);
+ ** if( rc ) break;
+ */
+ pCur->info.nSize = 0;
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
+ if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ pCur->aiIdx[pCur->iPage] = (u16)lwr;
+ pCur->apPage[pCur->iPage] = pCur->pPage;
+ pCur->ix = 0;
+ pCur->iPage++;
+ rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags);
+ if( rc==SQLITE_OK
+ && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
+ ){
+ releasePage(pCur->pPage);
+ rc = SQLITE_CORRUPT_PGNO(chldPg);
+ }
+ if( rc ){
+ pCur->pPage = pCur->apPage[--pCur->iPage];
+ break;
+ }
+ /*
+ ***** End of in-lined moveToChild() call */
+ }
moveto_index_finish:
pCur->info.nSize = 0;
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
@@ 75559,7 76413,7 @@ static SQLITE_NOINLINE int clearCellOverflow(
/* Call xParseCell to compute the size of a cell. If the cell contains
** overflow, then invoke cellClearOverflow to clear out that overflow.
-** STore the result code (SQLITE_OK or some error code) in rc.
+** Store the result code (SQLITE_OK or some error code) in rc.
**
** Implemented as macro to force inlining for performance.
*/
@@ 76170,12 77024,13 @@ static int rebuildPage(
int k; /* Current slot in pCArray->apEnd[] */
u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
+ assert( nCell>0 );
assert( i<iEnd );
j = get2byte(&aData[hdr+5]);
if( NEVER(j>(u32)usableSize) ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
- for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
@@ 76238,7 77093,7 @@ static int rebuildPage(
** Finally, argument pBegin points to the byte immediately following the
** end of the space required by this page for the cell-pointer area (for
** all cells - not just those inserted by the current call). If the content
-** area must be extended to before this point in order to accomodate all
+** area must be extended to before this point in order to accommodate all
** cells in apCell[], then the cells do not fit and non-zero is returned.
*/
static int pageInsertArray(
@@ 76258,7 77113,7 @@ static int pageInsertArray(
u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
if( iEnd<=iFirst ) return 0;
- for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
pEnd = pCArray->apEnd[k];
while( 1 /*Exit by break*/ ){
int sz, rc;
@@ 76476,6 77331,7 @@ static int editPage(
return SQLITE_OK;
editpage_fail:
/* Unable to edit this page. Rebuild it from scratch instead. */
+ if( nNew<1 ) return SQLITE_CORRUPT_BKPT;
populateCellCache(pCArray, iNew, nNew);
return rebuildPage(pCArray, iNew, nNew, pPg);
}
@@ 76553,7 77409,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
- ** of the parent page are still manipulated by thh code below.
+ ** of the parent page are still manipulated by the code below.
** That is Ok, at this point the parent page is guaranteed to
** be marked as dirty. Returning an error code will cause a
** rollback, undoing any changes made to the parent page.
@@ 76829,7 77685,7 @@ static int balance_nonroot(
pgno = get4byte(pRight);
while( 1 ){
if( rc==SQLITE_OK ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
}
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
@@ 77143,7 77999,7 @@ static int balance_nonroot(
}
}
- /* Sanity check: For a non-corrupt database file one of the follwing
+ /* Sanity check: For a non-corrupt database file one of the following
** must be true:
** (1) We found one or more cells (cntNew[0])>0), or
** (2) pPage is a virtual root page. A virtual root page is when
@@ 77368,9 78224,9 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
- for(k=0; b.ixNx[k]<=j && ALWAYS(k<NB*2); k++){}
+ for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
- if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
@@ 77404,6 78260,8 @@ static int balance_nonroot(
for(i=1-nNew; i<nNew; i++){
int iPg = i<0 ? -i : i;
assert( iPg>=0 && iPg<nNew );
+ assert( iPg>=1 || i>=0 );
+ assert( iPg<ArraySize(cntOld) );
if( abDone[iPg] ) continue; /* Skip pages already processed */
if( i>=0 /* On the upwards pass, or... */
|| cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */
@@ 77760,7 78618,7 @@ static int btreeOverwriteContent(
){
int nData = pX->nData - iOffset;
if( nData<=0 ){
- /* Overwritting with zeros */
+ /* Overwriting with zeros */
int i;
for(i=0; i<iAmt && pDest[i]==0; i++){}
if( i<iAmt ){
@@ 77796,7 78654,7 @@ static int btreeOverwriteContent(
** cell.
*/
static SQLITE_NOINLINE int btreeOverwriteOverflowCell(
- BtCursor *pCur, /* Cursor pointing to cell to ovewrite */
+ BtCursor *pCur, /* Cursor pointing to cell to overwrite */
const BtreePayload *pX /* Content to write into the cell */
){
int iOffset; /* Next byte of pX->pData to write */
@@ 78543,7 79401,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
- int ptfFlags; /* Page-type flage for the root page of new table */
+ int ptfFlags; /* Page-type flags for the root page of new table */
assert( sqlite3BtreeHoldsMutex(p) );
assert( pBt->inTransaction==TRANS_WRITE );
@@ 78712,7 79570,7 @@ static int clearDatabasePage(
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
- rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
+ rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
&& sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
@@ 79378,7 80236,7 @@ static int checkTreePage(
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
pCheck->zPfx = "Tree %u page %u: ";
- pCheck->v0 = pCheck->v1 = iPage;
+ pCheck->v1 = iPage;
if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
@@ 79715,6 80573,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
}
#endif
+ sCheck.v0 = aRoot[i];
checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
}
pBt->db->flags = savedDbFlags;
@@ 81142,6 82001,40 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
}
/*
+** If pMem is already a string, detect if it is a zero-terminated
+** string, or make it into one if possible, and mark it as such.
+**
+** This is an optimization. Correct operation continues even if
+** this routine is a no-op.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
+ if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){
+ /* pMem must be a string, and it cannot be an ephemeral or static string */
+ return;
+ }
+ if( pMem->enc!=SQLITE_UTF8 ) return;
+ if( NEVER(pMem->z==0) ) return;
+ if( pMem->flags & MEM_Dyn ){
+ if( pMem->xDel==sqlite3_free
+ && sqlite3_msize(pMem->z) >= (u64)(pMem->n+1)
+ ){
+ pMem->z[pMem->n] = 0;
+ pMem->flags |= MEM_Term;
+ return;
+ }
+ if( pMem->xDel==(void(*)(void*))sqlite3RCStrUnref ){
+ /* Blindly assume that all RCStr objects are zero-terminated */
+ pMem->flags |= MEM_Term;
+ return;
+ }
+ }else if( pMem->szMalloc >= pMem->n+1 ){
+ pMem->z[pMem->n] = 0;
+ pMem->flags |= MEM_Term;
+ return;
+ }
+}
+
+/*
** It is already known that pMem contains an unterminated string.
** Add the zero terminator.
**
@@ 81403,36 82296,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){
}
/*
-** Convert a 64-bit IEEE double into a 64-bit signed integer.
-** If the double is out of range of a 64-bit signed integer then
-** return the closest available 64-bit signed integer.
-*/
-static SQLITE_NOINLINE i64 doubleToInt64(double r){
-#ifdef SQLITE_OMIT_FLOATING_POINT
- /* When floating-point is omitted, double and int64 are the same thing */
- return r;
-#else
- /*
- ** Many compilers we encounter do not define constants for the
- ** minimum and maximum 64-bit integers, or they define them
- ** inconsistently. And many do not understand the "LL" notation.
- ** So we define our own static constants here using nothing
- ** larger than a 32-bit integer constant.
- */
- static const i64 maxInt = LARGEST_INT64;
- static const i64 minInt = SMALLEST_INT64;
-
- if( r<=(double)minInt ){
- return minInt;
- }else if( r>=(double)maxInt ){
- return maxInt;
- }else{
- return (i64)r;
- }
-#endif
-}
-
-/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact. If pMem is
@@ 81458,7 82321,7 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){
testcase( flags & MEM_IntReal );
return pMem->u.i;
}else if( flags & MEM_Real ){
- return doubleToInt64(pMem->u.r);
+ return sqlite3RealToI64(pMem->u.r);
}else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
return memIntValue(pMem);
}else{
@@ 81520,7 82383,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
if( pMem->flags & MEM_IntReal ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
- i64 ix = doubleToInt64(pMem->u.r);