mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Merge trunk into jni branch.
FossilOrigin-Name: 4f0aeeba0287e846908180eab6f7080ebe1323ebe49340771864d110e1ca5b2b
This commit is contained in:
14
Makefile.msc
14
Makefile.msc
@@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0
|
|||||||
USE_STDCALL = 0
|
USE_STDCALL = 0
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
# Set this non-0 to use structured exception handling (SEH) for WAL mode
|
||||||
|
# in the core library.
|
||||||
|
#
|
||||||
|
!IFNDEF USE_SEH
|
||||||
|
USE_SEH = 0
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
# Set this non-0 to have the shell executable link against the core dynamic
|
# Set this non-0 to have the shell executable link against the core dynamic
|
||||||
# link library.
|
# link library.
|
||||||
#
|
#
|
||||||
@@ -389,6 +396,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
|||||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
# Should structured exception handling (SEH) be enabled for WAL mode in
|
||||||
|
# the core library?
|
||||||
|
#
|
||||||
|
!IF $(USE_SEH)!=0
|
||||||
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
# These are the "extended" SQLite compilation options used when compiling for
|
# These are the "extended" SQLite compilation options used when compiling for
|
||||||
# the Windows 10 platform.
|
# the Windows 10 platform.
|
||||||
#
|
#
|
||||||
|
@@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0
|
|||||||
USE_STDCALL = 0
|
USE_STDCALL = 0
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
# Set this non-0 to use structured exception handling (SEH) for WAL mode
|
||||||
|
# in the core library.
|
||||||
|
#
|
||||||
|
!IFNDEF USE_SEH
|
||||||
|
USE_SEH = 0
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
# Set this non-0 to have the shell executable link against the core dynamic
|
# Set this non-0 to have the shell executable link against the core dynamic
|
||||||
# link library.
|
# link library.
|
||||||
#
|
#
|
||||||
@@ -311,6 +318,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
|||||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
# Should structured exception handling (SEH) be enabled for WAL mode in
|
||||||
|
# the core library?
|
||||||
|
#
|
||||||
|
!IF $(USE_SEH)!=0
|
||||||
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
# These are the "extended" SQLite compilation options used when compiling for
|
# These are the "extended" SQLite compilation options used when compiling for
|
||||||
# the Windows 10 platform.
|
# the Windows 10 platform.
|
||||||
#
|
#
|
||||||
|
@@ -179,7 +179,6 @@ SQLITE_OPT = \
|
|||||||
-DSQLITE_OMIT_DEPRECATED \
|
-DSQLITE_OMIT_DEPRECATED \
|
||||||
-DSQLITE_OMIT_UTF16 \
|
-DSQLITE_OMIT_UTF16 \
|
||||||
-DSQLITE_OMIT_SHARED_CACHE \
|
-DSQLITE_OMIT_SHARED_CACHE \
|
||||||
-DSQLITE_OMIT_WAL \
|
|
||||||
-DSQLITE_THREADSAFE=0 \
|
-DSQLITE_THREADSAFE=0 \
|
||||||
-DSQLITE_TEMP_STORE=2 \
|
-DSQLITE_TEMP_STORE=2 \
|
||||||
-DSQLITE_OS_KV_OPTIONAL=1 \
|
-DSQLITE_OS_KV_OPTIONAL=1 \
|
||||||
@@ -187,6 +186,12 @@ SQLITE_OPT = \
|
|||||||
-DSQLITE_USE_URI=1 \
|
-DSQLITE_USE_URI=1 \
|
||||||
-DSQLITE_WASM_ENABLE_C_TESTS \
|
-DSQLITE_WASM_ENABLE_C_TESTS \
|
||||||
-DSQLITE_C=$(sqlite3.c)
|
-DSQLITE_C=$(sqlite3.c)
|
||||||
|
#SQLITE_OPT += -DSQLITE_DEBUG
|
||||||
|
# Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file()
|
||||||
|
# (and thus sqlite3_js_vfs_create_file()). Those functions are
|
||||||
|
# deprecated and alternatives are in place, but this crash behavior
|
||||||
|
# can be used to find errant uses of sqlite3_js_vfs_create_file()
|
||||||
|
# in client code.
|
||||||
|
|
||||||
.NOTPARALLEL: $(sqlite3.h)
|
.NOTPARALLEL: $(sqlite3.h)
|
||||||
$(sqlite3.h):
|
$(sqlite3.h):
|
||||||
|
@@ -608,6 +608,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||||
["sqlite3_wasm_vfs_create_file", "int",
|
["sqlite3_wasm_vfs_create_file", "int",
|
||||||
"sqlite3_vfs*","string","*", "int"],
|
"sqlite3_vfs*","string","*", "int"],
|
||||||
|
["sqlite3_wasm_posix_create_file", "int", "string","*", "int"],
|
||||||
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -1357,6 +1357,74 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
If the current environment supports the POSIX file APIs, this routine
|
||||||
|
creates (or overwrites) the given file using those APIs. This is
|
||||||
|
primarily intended for use in Emscripten-based builds where the POSIX
|
||||||
|
APIs are transparently proxied by an in-memory virtual filesystem.
|
||||||
|
It may behave diffrently in other environments.
|
||||||
|
|
||||||
|
The first argument must be either a JS string or WASM C-string
|
||||||
|
holding the filename. Note that this routine does _not_ create
|
||||||
|
intermediary directories if the filename has a directory part.
|
||||||
|
|
||||||
|
The 2nd argument may either a valid WASM memory pointer, an
|
||||||
|
ArrayBuffer, or a Uint8Array. The 3rd must be the length, in
|
||||||
|
bytes, of the data array to copy. If the 2nd argument is an
|
||||||
|
ArrayBuffer or Uint8Array and the 3rd is not a positive integer
|
||||||
|
then the 3rd defaults to the array's byteLength value.
|
||||||
|
|
||||||
|
Results are undefined if data is a WASM pointer and dataLen is
|
||||||
|
exceeds data's bounds.
|
||||||
|
|
||||||
|
Throws if any arguments are invalid or if creating or writing to
|
||||||
|
the file fails.
|
||||||
|
|
||||||
|
Added in 3.43 as an alternative for the deprecated
|
||||||
|
sqlite3_js_vfs_create_file().
|
||||||
|
*/
|
||||||
|
capi.sqlite3_js_posix_create_file = function(filename, data, dataLen){
|
||||||
|
let pData;
|
||||||
|
if(data && wasm.isPtr(data)){
|
||||||
|
pData = data;
|
||||||
|
}else if(data instanceof ArrayBuffer || data instanceof Uint8Array){
|
||||||
|
pData = wasm.allocFromTypedArray(data);
|
||||||
|
if(arguments.length<3 || !util.isInt32(dataLen) || dataLen<0){
|
||||||
|
dataLen = data.byteLength;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
SQLite3Error.toss("Invalid 2nd argument for sqlite3_js_posix_create_file().");
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
if(!util.isInt32(dataLen) || dataLen<0){
|
||||||
|
SQLite3Error.toss("Invalid 3rd argument for sqlite3_js_posix_create_file().");
|
||||||
|
}
|
||||||
|
const rc = wasm.sqlite3_wasm_posix_create_file(filename, pData, dataLen);
|
||||||
|
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
|
||||||
|
capi.sqlite3_js_rc_str(rc));
|
||||||
|
}finally{
|
||||||
|
wasm.dealloc(pData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deprecation warning: this function does not work properly in
|
||||||
|
debug builds of sqlite3 because its out-of-scope use of the
|
||||||
|
sqlite3_vfs API triggers assertions in the core library. That
|
||||||
|
was unfortunately not discovered until 2023-08-11. This function
|
||||||
|
is now deprecated and should not be used in new code.
|
||||||
|
|
||||||
|
Alternative options:
|
||||||
|
|
||||||
|
- "unix" VFS and its variants can get equivalent functionality
|
||||||
|
with sqlite3_js_posix_create_file().
|
||||||
|
|
||||||
|
- OPFS: use either sqlite3.oo1.OpfsDb.importDb(), for the "opfs"
|
||||||
|
VFS, or the importDb() method of the PoolUtil object provided
|
||||||
|
by the "opfs-sahpool" OPFS (noting that its VFS name may differ
|
||||||
|
depending on client-side configuration). We cannot proxy those
|
||||||
|
from here because the former is necessarily asynchronous and
|
||||||
|
the latter requires information not available to this function.
|
||||||
|
|
||||||
Creates a file using the storage appropriate for the given
|
Creates a file using the storage appropriate for the given
|
||||||
sqlite3_vfs. The first argument may be a VFS name (JS string
|
sqlite3_vfs. The first argument may be a VFS name (JS string
|
||||||
only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or
|
only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or
|
||||||
@@ -1402,9 +1470,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
VFS nor the WASM environment imposes requirements which break it.
|
VFS nor the WASM environment imposes requirements which break it.
|
||||||
|
|
||||||
- "opfs": uses OPFS storage and creates directory parts of the
|
- "opfs": uses OPFS storage and creates directory parts of the
|
||||||
filename.
|
filename. It can only be used to import an SQLite3 database
|
||||||
|
file and will fail if given anything else.
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
|
capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
|
||||||
|
config.warn("sqlite3_js_vfs_create_file() is deprecated and",
|
||||||
|
"should be avoided because it can lead to C-level crashes.",
|
||||||
|
"See its documentation for alternative options.");
|
||||||
let pData;
|
let pData;
|
||||||
if(data){
|
if(data){
|
||||||
if(wasm.isPtr(data)){
|
if(wasm.isPtr(data)){
|
||||||
@@ -1432,7 +1504,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
|
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
|
||||||
capi.sqlite3_js_rc_str(rc));
|
capi.sqlite3_js_rc_str(rc));
|
||||||
}finally{
|
}finally{
|
||||||
wasm.dealloc(pData);
|
wasm.dealloc(pData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1168,11 +1168,41 @@ const installOpfsVfs = function callee(options){
|
|||||||
doDir(opt.directory, 0);
|
doDir(opt.directory, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO to support fiddle and worker1 db upload:
|
/**
|
||||||
//opfsUtil.createFile = function(absName, content=undefined){...}
|
Asynchronously imports the given bytes (a byte array or
|
||||||
//We have sqlite3.wasm.sqlite3_wasm_vfs_create_file() for this
|
ArrayBuffer) into the given database file.
|
||||||
//purpose but its interface and name are still under
|
|
||||||
//consideration.
|
It very specifically requires the input to be an SQLite3
|
||||||
|
database and throws if that's not the case. It does so in
|
||||||
|
order to prevent this function from taking on a larger scope
|
||||||
|
than it is specifically intended to. i.e. we do not want it to
|
||||||
|
become a convenience for importing arbitrary files into OPFS.
|
||||||
|
|
||||||
|
Throws on error. Resolves to the number of bytes written.
|
||||||
|
*/
|
||||||
|
opfsUtil.importDb = async function(filename, bytes){
|
||||||
|
if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes);
|
||||||
|
const n = bytes.byteLength;
|
||||||
|
if(n<512 || n%512!=0){
|
||||||
|
toss("Byte array size is invalid for an SQLite db.");
|
||||||
|
}
|
||||||
|
const header = "SQLite format 3";
|
||||||
|
for(let i = 0; i < header.length; ++i){
|
||||||
|
if( header.charCodeAt(i) !== bytes[i] ){
|
||||||
|
toss("Input does not contain an SQLite database header.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [hDir, fnamePart] = await opfsUtil.getDirForFilename(filename, true);
|
||||||
|
const hFile = await hDir.getFileHandle(fnamePart, {create:true});
|
||||||
|
const sah = await hFile.createSyncAccessHandle();
|
||||||
|
sah.truncate(0);
|
||||||
|
const nWrote = sah.write(bytes, {at: 0});
|
||||||
|
sah.close();
|
||||||
|
if(nWrote != n){
|
||||||
|
toss("Expected to write "+n+" bytes but wrote "+nWrote+".");
|
||||||
|
}
|
||||||
|
return nWrote;
|
||||||
|
};
|
||||||
|
|
||||||
if(sqlite3.oo1){
|
if(sqlite3.oo1){
|
||||||
const OpfsDb = function(...args){
|
const OpfsDb = function(...args){
|
||||||
@@ -1182,6 +1212,7 @@ const installOpfsVfs = function callee(options){
|
|||||||
};
|
};
|
||||||
OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
|
OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
|
||||||
sqlite3.oo1.OpfsDb = OpfsDb;
|
sqlite3.oo1.OpfsDb = OpfsDb;
|
||||||
|
OpfsDb.importDb = opfsUtil.importDb;
|
||||||
sqlite3.oo1.DB.dbCtorHelper.setVfsPostOpenSql(
|
sqlite3.oo1.DB.dbCtorHelper.setVfsPostOpenSql(
|
||||||
opfsVfs.pointer,
|
opfsVfs.pointer,
|
||||||
function(oo1Db, sqlite3){
|
function(oo1Db, sqlite3){
|
||||||
|
@@ -141,9 +141,6 @@
|
|||||||
#ifndef SQLITE_OMIT_UTF16
|
#ifndef SQLITE_OMIT_UTF16
|
||||||
# define SQLITE_OMIT_UTF16 1
|
# define SQLITE_OMIT_UTF16 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef SQLITE_OMIT_WAL
|
|
||||||
# define SQLITE_OMIT_WAL 1
|
|
||||||
#endif
|
|
||||||
#ifndef SQLITE_OS_KV_OPTIONAL
|
#ifndef SQLITE_OS_KV_OPTIONAL
|
||||||
# define SQLITE_OS_KV_OPTIONAL 1
|
# define SQLITE_OS_KV_OPTIONAL 1
|
||||||
#endif
|
#endif
|
||||||
@@ -295,7 +292,7 @@ SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_ptr(void){
|
|||||||
*/
|
*/
|
||||||
SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){
|
SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){
|
||||||
assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
|
assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
|
||||||
assert(0==(p & 0x7));
|
assert(0==((unsigned long long)p & 0x7));
|
||||||
if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
|
if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
|
||||||
PStack.pPos = p;
|
PStack.pPos = p;
|
||||||
}
|
}
|
||||||
@@ -1353,6 +1350,13 @@ int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
|
|||||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||||
** for use by the sqlite project's own JS/WASM bindings.
|
** for use by the sqlite project's own JS/WASM bindings.
|
||||||
**
|
**
|
||||||
|
** ACHTUNG: it was discovered on 2023-08-11 that, with SQLITE_DEBUG,
|
||||||
|
** this function's out-of-scope use of the sqlite3_vfs/file/io_methods
|
||||||
|
** APIs leads to triggering of assertions in the core library. Its use
|
||||||
|
** is now deprecated and VFS-specific APIs for importing files need to
|
||||||
|
** be found to replace it. sqlite3_wasm_posix_create_file() is
|
||||||
|
** suitable for the "unix" family of VFSes.
|
||||||
|
**
|
||||||
** Creates a new file using the I/O API of the given VFS, containing
|
** Creates a new file using the I/O API of the given VFS, containing
|
||||||
** the given number of bytes of the given data. If the file exists, it
|
** the given number of bytes of the given data. If the file exists, it
|
||||||
** is truncated to the given length and populated with the given
|
** is truncated to the given length and populated with the given
|
||||||
@@ -1398,7 +1402,14 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
|
|||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pFile = 0;
|
sqlite3_file *pFile = 0;
|
||||||
sqlite3_io_methods const *pIo;
|
sqlite3_io_methods const *pIo;
|
||||||
const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
||||||
|
#if 0 && defined(SQLITE_DEBUG)
|
||||||
|
| SQLITE_OPEN_MAIN_JOURNAL
|
||||||
|
/* ^^^^ This is for testing a horrible workaround to avoid
|
||||||
|
triggering a specific assert() in os_unix.c:unixOpen(). Please
|
||||||
|
do not enable this in real builds. */
|
||||||
|
#endif
|
||||||
|
;
|
||||||
int flagsOut = 0;
|
int flagsOut = 0;
|
||||||
int fileExisted = 0;
|
int fileExisted = 0;
|
||||||
int doUnlock = 0;
|
int doUnlock = 0;
|
||||||
@@ -1464,6 +1475,34 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||||
|
** for use by the sqlite project's own JS/WASM bindings.
|
||||||
|
**
|
||||||
|
** Creates or overwrites a file using the POSIX file API,
|
||||||
|
** i.e. Emscripten's virtual filesystem. Creates or truncates
|
||||||
|
** zFilename, appends pData bytes to it, and returns 0 on success or
|
||||||
|
** SQLITE_IOERR on error.
|
||||||
|
*/
|
||||||
|
SQLITE_WASM_EXPORT
|
||||||
|
int sqlite3_wasm_posix_create_file( const char *zFilename,
|
||||||
|
const unsigned char * pData,
|
||||||
|
int nData ){
|
||||||
|
int rc;
|
||||||
|
FILE * pFile = 0;
|
||||||
|
int fileExisted = 0;
|
||||||
|
size_t nWrote = 1;
|
||||||
|
|
||||||
|
if( !zFilename || nData<0 || (pData==0 && nData>0) ) return SQLITE_MISUSE;
|
||||||
|
pFile = fopen(zFilename, "w");
|
||||||
|
if( 0==pFile ) return SQLITE_IOERR;
|
||||||
|
if( nData>0 ){
|
||||||
|
nWrote = fwrite(pData, (size_t)nData, 1, pFile);
|
||||||
|
}
|
||||||
|
fclose(pFile);
|
||||||
|
return 1==nWrote ? 0 : SQLITE_IOERR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||||
** for use by the sqlite project's own JS/WASM bindings.
|
** for use by the sqlite project's own JS/WASM bindings.
|
||||||
|
@@ -355,6 +355,7 @@
|
|||||||
sqlite3_js_db_vfs: 'wasm:/api-c-style.md#sqlite3_js_db_vfs',
|
sqlite3_js_db_vfs: 'wasm:/api-c-style.md#sqlite3_js_db_vfs',
|
||||||
sqlite3_js_kvvfs_clear: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
|
sqlite3_js_kvvfs_clear: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
|
||||||
sqlite3_js_kvvfs_size: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
|
sqlite3_js_kvvfs_size: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
|
||||||
|
sqlite3_js_posix_create_file: 'wasm:/api-c-style.md#sqlite3_js_posix_create_file',
|
||||||
sqlite3_js_rc_str: 'wasm:/api-c-style.md#sqlite3_js_rc_str',
|
sqlite3_js_rc_str: 'wasm:/api-c-style.md#sqlite3_js_rc_str',
|
||||||
sqlite3_js_vfs_create_file: 'wasm:/api-c-style.md#sqlite3_js_vfs_create_file',
|
sqlite3_js_vfs_create_file: 'wasm:/api-c-style.md#sqlite3_js_vfs_create_file',
|
||||||
sqlite3_js_vfs_list: 'wasm:/api-c-style.md#sqlite3_js_vfs_list',
|
sqlite3_js_vfs_list: 'wasm:/api-c-style.md#sqlite3_js_vfs_list',
|
||||||
|
@@ -1657,7 +1657,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
.assert('number'===typeof rc[0])
|
.assert('number'===typeof rc[0])
|
||||||
.assert(rc[0]|0 === rc[0] /* is small integer */);
|
.assert(rc[0]|0 === rc[0] /* is small integer */);
|
||||||
})
|
})
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
.t({
|
.t({
|
||||||
name: 'sqlite3_js_db_export()',
|
name: 'sqlite3_js_db_export()',
|
||||||
predicate: ()=>true,
|
predicate: ()=>true,
|
||||||
@@ -1671,13 +1671,12 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
}
|
}
|
||||||
}/*sqlite3_js_db_export()*/)
|
}/*sqlite3_js_db_export()*/)
|
||||||
.t({
|
.t({
|
||||||
name: 'sqlite3_js_vfs_create_file() with db in default VFS',
|
name: 'sqlite3_js_posix_create_file()',
|
||||||
predicate: ()=>true,
|
predicate: ()=>true,
|
||||||
test: function(sqlite3){
|
test: function(sqlite3){
|
||||||
const db = this.db;
|
const db = this.db;
|
||||||
const pVfs = capi.sqlite3_js_db_vfs(db);
|
const filename = "sqlite3_js_posix_create_file.db";
|
||||||
const filename = "sqlite3_js_vfs_create_file().db";
|
capi.sqlite3_js_posix_create_file(filename, this.dbExport);
|
||||||
capi.sqlite3_js_vfs_create_file(pVfs, filename, this.dbExport);
|
|
||||||
delete this.dbExport;
|
delete this.dbExport;
|
||||||
const db2 = new sqlite3.oo1.DB(filename,'r');
|
const db2 = new sqlite3.oo1.DB(filename,'r');
|
||||||
try {
|
try {
|
||||||
@@ -1686,7 +1685,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
T.assert(n>0 && db2.selectValue(sql) === n);
|
T.assert(n>0 && db2.selectValue(sql) === n);
|
||||||
}finally{
|
}finally{
|
||||||
db2.close();
|
db2.close();
|
||||||
wasm.sqlite3_wasm_vfs_unlink(pVfs, filename);
|
wasm.sqlite3_wasm_vfs_unlink(0, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}/*sqlite3_js_vfs_create_file()*/)
|
}/*sqlite3_js_vfs_create_file()*/)
|
||||||
@@ -2907,7 +2906,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
.t({
|
.t({
|
||||||
name: 'OPFS db sanity checks',
|
name: 'OPFS db sanity checks',
|
||||||
test: async function(sqlite3){
|
test: async function(sqlite3){
|
||||||
const filename = this.opfsDbFile = 'sqlite3-tester1.db';
|
const filename = this.opfsDbFile = '/dir/sqlite3-tester1.db';
|
||||||
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
|
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
|
||||||
T.assert(pVfs);
|
T.assert(pVfs);
|
||||||
const unlink = this.opfsUnlink =
|
const unlink = this.opfsUnlink =
|
||||||
@@ -2935,22 +2934,23 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
}
|
}
|
||||||
}/*OPFS db sanity checks*/)
|
}/*OPFS db sanity checks*/)
|
||||||
.t({
|
.t({
|
||||||
name: 'OPFS export/import',
|
name: 'OPFS import',
|
||||||
test: async function(sqlite3){
|
test: async function(sqlite3){
|
||||||
let db;
|
let db;
|
||||||
try {
|
try {
|
||||||
const exp = this.opfsDbExport;
|
const exp = this.opfsDbExport;
|
||||||
delete this.opfsDbExport;
|
delete this.opfsDbExport;
|
||||||
capi.sqlite3_js_vfs_create_file("opfs", this.opfsDbFile, exp);
|
this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(this.opfsDbFile, exp);
|
||||||
const db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
|
db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
|
||||||
T.assert(6 === db.selectValue('select count(*) from p'));
|
T.assert(6 === db.selectValue('select count(*) from p')).
|
||||||
|
assert( this.opfsImportSize == exp.byteLength );
|
||||||
}finally{
|
}finally{
|
||||||
if(db) db.close();
|
if(db) db.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}/*OPFS export/import*/)
|
}/*OPFS export/import*/)
|
||||||
.t({
|
.t({
|
||||||
name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()',
|
name: '(Internal-use) OPFS utility APIs',
|
||||||
test: async function(sqlite3){
|
test: async function(sqlite3){
|
||||||
const filename = this.opfsDbFile;
|
const filename = this.opfsDbFile;
|
||||||
const pVfs = this.opfsVfs;
|
const pVfs = this.opfsVfs;
|
||||||
@@ -2959,8 +2959,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
delete this.opfsDbFile;
|
delete this.opfsDbFile;
|
||||||
delete this.opfsVfs;
|
delete this.opfsVfs;
|
||||||
delete this.opfsUnlink;
|
delete this.opfsUnlink;
|
||||||
unlink();
|
|
||||||
// Sanity-test sqlite3_js_vfs_create_file()...
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
|
ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
|
||||||
for client-side use. It is only for this project's own
|
for client-side use. It is only for this project's own
|
||||||
@@ -2968,39 +2966,19 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
any time.
|
any time.
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
const opfs = sqlite3.opfs;
|
const opfs = sqlite3.opfs;
|
||||||
const fSize = 1379;
|
const fSize = this.opfsImportSize;
|
||||||
|
delete this.opfsImportSize;
|
||||||
let sh;
|
let sh;
|
||||||
try{
|
try{
|
||||||
T.assert(!(await opfs.entryExists(filename)));
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
pVfs, filename, null, fSize
|
|
||||||
);
|
|
||||||
T.assert(await opfs.entryExists(filename));
|
T.assert(await opfs.entryExists(filename));
|
||||||
let fh = await opfs.rootDirectory.getFileHandle(filename);
|
const [dirHandle, filenamePart] = await opfs.getDirForFilename(filename, false);
|
||||||
|
const fh = await dirHandle.getFileHandle(filenamePart);
|
||||||
sh = await fh.createSyncAccessHandle();
|
sh = await fh.createSyncAccessHandle();
|
||||||
T.assert(fSize === await sh.getSize());
|
T.assert(fSize === await sh.getSize());
|
||||||
await sh.close();
|
await sh.close();
|
||||||
sh = undefined;
|
sh = undefined;
|
||||||
unlink();
|
unlink();
|
||||||
T.assert(!(await opfs.entryExists(filename)));
|
T.assert(!(await opfs.entryExists(filename)));
|
||||||
|
|
||||||
const ba = new Uint8Array([1,2,3,4,5]);
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
"opfs", filename, ba
|
|
||||||
);
|
|
||||||
T.assert(await opfs.entryExists(filename));
|
|
||||||
fh = await opfs.rootDirectory.getFileHandle(filename);
|
|
||||||
sh = await fh.createSyncAccessHandle();
|
|
||||||
T.assert(ba.byteLength === await sh.getSize());
|
|
||||||
await sh.close();
|
|
||||||
sh = undefined;
|
|
||||||
unlink();
|
|
||||||
|
|
||||||
T.mustThrowMatching(()=>{
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
"no-such-vfs", filename, ba
|
|
||||||
);
|
|
||||||
}, "SQLITE_NOTFOUND: Unknown sqlite3_vfs name: no-such-vfs");
|
|
||||||
}finally{
|
}finally{
|
||||||
if(sh) await sh.close();
|
if(sh) await sh.close();
|
||||||
unlink();
|
unlink();
|
||||||
@@ -3103,7 +3081,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
const conf2 = JSON.parse(JSON.stringify(sahPoolConfig));
|
const conf2 = JSON.parse(JSON.stringify(sahPoolConfig));
|
||||||
conf2.name += '-test2';
|
conf2.name += '-test2';
|
||||||
const POther = await inst(conf2);
|
const POther = await inst(conf2);
|
||||||
log("Installed second SAH instance as",conf2.name);
|
//log("Installed second SAH instance as",conf2.name);
|
||||||
T.assert(0 === POther.getFileCount())
|
T.assert(0 === POther.getFileCount())
|
||||||
.assert(true === await POther.removeVfs());
|
.assert(true === await POther.removeVfs());
|
||||||
|
|
||||||
|
55
manifest
55
manifest
@@ -1,11 +1,11 @@
|
|||||||
C Fix\sa\smakefile\sdeps\sproblem\swhich\scaused\sext/jni\sbuild\sto\sfail\sif\ssqlite3.c/h\swere\snot\screated\sbeforehand.
|
C Merge\strunk\sinto\sjni\sbranch.
|
||||||
D 2023-08-11T20:32:40.205
|
D 2023-08-11T21:24:08.276
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
F Makefile.in 5ad2d1e198306bc730f06f7545d3a8832225b1bfddbc648d97c0e0b9a35f67e9
|
F Makefile.in 5ad2d1e198306bc730f06f7545d3a8832225b1bfddbc648d97c0e0b9a35f67e9
|
||||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||||
F Makefile.msc 7248d860f71ab164b4cec3c415e6cc1bd9fee860c370d65bd8bb49e9572521e2
|
F Makefile.msc daad4a19e0b3c3c3b79b64d4ddbf75e3f506405e8d3f3f604d6f48b26043c51f
|
||||||
F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224
|
F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224
|
||||||
F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa
|
F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa
|
||||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||||
@@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
|||||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||||
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
|
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
|
||||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||||
F autoconf/Makefile.msc 20366d19fbfc3fceecce95344a2114069eaab4fc22e4f02430da167a1e2ddf04
|
F autoconf/Makefile.msc 00f11ce1f7904416fe841c33e7d789defe8c39e1df6b97e93ed2af3b1bbaf9d7
|
||||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||||
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
|
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
|
||||||
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
|
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
|
||||||
@@ -528,7 +528,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
|||||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||||
F ext/wasm/GNUmakefile 50a4bd40ee01a90badfc28d0042789740e47e2855d3b9acaa8801b6dc2763aba
|
F ext/wasm/GNUmakefile 8159bc5f9433fe21022c1a8e8c30cb1a523530ba9ef53bdf5d1e0a2186554806
|
||||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
||||||
@@ -541,16 +541,16 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
|||||||
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
|
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
|
||||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||||
F ext/wasm/api/sqlite3-api-glue.js cc6b0bb093bdb6279d4af259200b7b9e150e3796a8a3a4cd09a4928c43d25e56
|
F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js 76258e160bf6a89cc75a7d3c05646a054c8cab7219cd1e10bc20cacaad022131
|
F ext/wasm/api/sqlite3-api-prologue.js 5f283b096b98bfb1ee2f2201e7ff0489dff00e29e1030c30953bdb4f5b87f4bd
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js abb69b5e008961026bf5ff433d7116cb046359af92a5daf73208af2e7ac80ae7
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js abb69b5e008961026bf5ff433d7116cb046359af92a5daf73208af2e7ac80ae7
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e7a690e0e78ff4d563f2eca468f91db69f001ff4b79c6d2304cbb6f62dca437d
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e04fc2fda6a0200ef80efdbb4ddfa0254453558adb17ec3a230f93d2bf1d711c
|
||||||
F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f
|
F ext/wasm/api/sqlite3-wasm.c d4d4c2b349b43b7b861e6d2994299630fb79e07573ea6b61e28e8071b7d16b61
|
||||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||||
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
|
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
|
||||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||||
@@ -580,7 +580,7 @@ F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74
|
|||||||
F ext/wasm/index.html 4e7847b909f4ae0da8c829b150b79454050e53b3658431f138636257729cd42b
|
F ext/wasm/index.html 4e7847b909f4ae0da8c829b150b79454050e53b3658431f138636257729cd42b
|
||||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||||
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
|
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
|
||||||
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
|
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||||
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
|
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
|
||||||
@@ -595,7 +595,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
|||||||
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
||||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||||
F ext/wasm/tester1.c-pp.js b88dcad5424a652e8204c44a71bbc3deb22a4922c97ba792aedbabb7a6827b91
|
F ext/wasm/tester1.c-pp.js 64eb0ee6e695d5638d0f758f31a0ca2231e627ca5d768de3d8b44f9f494de8d4
|
||||||
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
||||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||||
@@ -628,7 +628,7 @@ F src/btreeInt.h 91a9e0c41a0e71fa91a742ec285c63dd8dcb38b73d14fae0ed7209174ff0fdc
|
|||||||
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
|
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
|
||||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||||
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
|
F src/ctime.c cff2b493de894383832347c3a3f936a05f4e089a92b42366838da1735f3848b5
|
||||||
F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
|
F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
|
||||||
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
|
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
|
||||||
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
|
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
|
||||||
@@ -643,7 +643,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
|||||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||||
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||||
F src/json.c 9c231a853268ce6aee2e300e26d4445ba42117374a2275f8e9537b2f912909d6
|
F src/json.c ae840f87b418f039f5d336b488933d09396bd31e6b31e855b93055ccaee4e255
|
||||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||||
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
|
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
|
||||||
F src/main.c fde8f13c876a658b4e8b74b77d875ca887915c174ea6a2f3122d80966f93d865
|
F src/main.c fde8f13c876a658b4e8b74b77d875ca887915c174ea6a2f3122d80966f93d865
|
||||||
@@ -670,8 +670,8 @@ F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d87210
|
|||||||
F src/os_unix.c 2e8b12107f75d1bd16412f312b4c5d5103191807a37836d3b81beb26436ad81b
|
F src/os_unix.c 2e8b12107f75d1bd16412f312b4c5d5103191807a37836d3b81beb26436ad81b
|
||||||
F src/os_win.c 7038223a1cda0a47e2ab4db47f63bf1833fe53ba0542f0f283a062ea13894103
|
F src/os_win.c 7038223a1cda0a47e2ab4db47f63bf1833fe53ba0542f0f283a062ea13894103
|
||||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||||
F src/pager.c 5ddf3a74c633a008ea6b2f5b3186167e88e2c8ca8a252ecab06ab3f1eb48e60f
|
F src/pager.c 993445a19b611d473ca007542ab3149840661a4c7e9f2d9e1ec008b7cc2abe78
|
||||||
F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
|
F src/pager.h 6e326bd05970a24dd28d41d3980b6964fbaa37b4da54a2c0d4e0c5bdb06ff187
|
||||||
F src/parse.y aeb7760d41cfa86465e3adba506500c021597049fd55f82a30e5b7045862c28c
|
F src/parse.y aeb7760d41cfa86465e3adba506500c021597049fd55f82a30e5b7045862c28c
|
||||||
F src/pcache.c 4cd4a0043167da9ba7e19b4d179a0e6354e7fe32c16f781ecf9bf0a5ff63b40b
|
F src/pcache.c 4cd4a0043167da9ba7e19b4d179a0e6354e7fe32c16f781ecf9bf0a5ff63b40b
|
||||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||||
@@ -685,7 +685,7 @@ F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
|
|||||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||||
F src/select.c 5f545a2c8702d4d3430bbb188cfec47d6c122d899061ef00cbe56af14591c574
|
F src/select.c 5f545a2c8702d4d3430bbb188cfec47d6c122d899061ef00cbe56af14591c574
|
||||||
F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40
|
F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40
|
||||||
F src/sqlite.h.in 7b07a33d2af82ee974aa91e6294abce0282b2f4c5934b291d2fff961810dd867
|
F src/sqlite.h.in 73a366c1c45d5ac9888cfe81c458826a44498531d106cfb4f328193ab5f6f17d
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
|
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
|
||||||
F src/sqliteInt.h 025ed58a41968ef80d64cdc194caa8dd207b0256b147253d762fdac7a62408f9
|
F src/sqliteInt.h 025ed58a41968ef80d64cdc194caa8dd207b0256b147253d762fdac7a62408f9
|
||||||
@@ -745,19 +745,19 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7
|
|||||||
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
|
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
|
||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||||
F src/tokenize.c 0fb405f9adf3f757c26bfc1ae6d58ac5dccbb918917ba9e5ef0e6673a06563d3
|
F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd5
|
||||||
F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd
|
F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd
|
||||||
F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
|
F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
|
||||||
F src/update.c 0bb9171afaa4d0b100ad946873bccda7aef90ffe083ef5c63668fce08c4df9da
|
F src/update.c 0bb9171afaa4d0b100ad946873bccda7aef90ffe083ef5c63668fce08c4df9da
|
||||||
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
|
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
|
||||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||||
F src/util.c b3532a95ad56db67b3acd3955e688e4cb80ebec6fd1f459a8eb51cceedd6de69
|
F src/util.c a40062117e705eb3339201842717a022092816b92479eead6397cde28af32ff9
|
||||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||||
F src/vdbe.c 346d848a0bf8128e3e3722c5406f4bde6c32d7093b93402c6f8e0718d19305c3
|
F src/vdbe.c 346d848a0bf8128e3e3722c5406f4bde6c32d7093b93402c6f8e0718d19305c3
|
||||||
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
|
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
|
||||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||||
F src/vdbeapi.c f37822f215740ede2a8fcae99bc13f2cc3a72dd0e1d22b81b9298c5ca67dbc38
|
F src/vdbeapi.c f37822f215740ede2a8fcae99bc13f2cc3a72dd0e1d22b81b9298c5ca67dbc38
|
||||||
F src/vdbeaux.c a586f445945eef6ad1fcd7c94f700faa1baea93c0dbd446291c7cf65966c8470
|
F src/vdbeaux.c e3aa5c46827cd95e0fc4d0f302fa3e901ab5f07258fdbb42709eeef40f63018d
|
||||||
F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
|
F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
|
||||||
F src/vdbemem.c 317b9f48708139db6239ade40c7980b4bc8233168383690d588dad6d8437f722
|
F src/vdbemem.c 317b9f48708139db6239ade40c7980b4bc8233168383690d588dad6d8437f722
|
||||||
F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015
|
F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015
|
||||||
@@ -765,8 +765,8 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
|
|||||||
F src/vdbevtab.c 57fa8f56478e5b5cb558cb425e7878515e0a105c54f96f1d1bbf4b9433529254
|
F src/vdbevtab.c 57fa8f56478e5b5cb558cb425e7878515e0a105c54f96f1d1bbf4b9433529254
|
||||||
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
|
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
|
||||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||||
F src/wal.c dd843f619ac60d5dadab7109cf402432ba74dde0c301505fd1c202add07659e3
|
F src/wal.c 02e10f033a6972bc7d50122b400318003199c504cda48f61ad404564505f4e89
|
||||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b
|
||||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||||
F src/where.c b8917792f1e0dbfa28fb29e6cd3d560060d69667be0ba4c491cbc772363264f5
|
F src/where.c b8917792f1e0dbfa28fb29e6cd3d560060d69667be0ba4c491cbc772363264f5
|
||||||
F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a
|
F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a
|
||||||
@@ -1272,7 +1272,7 @@ F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35
|
|||||||
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
|
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
|
||||||
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
|
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
|
||||||
F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x
|
F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x
|
||||||
F test/json101.test 94126d4291d4a00e45f6988ce885c410de69243490e46e70e9946cb6e6f9ea02
|
F test/json101.test 243b0a2650218ac5eafde6ce2a92a0e9d02bf24f62aec68693b69d9a693f120a
|
||||||
F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff
|
F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff
|
||||||
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
||||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||||
@@ -1538,7 +1538,7 @@ F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3
|
|||||||
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
|
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
|
||||||
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
|
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
|
||||||
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
|
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
|
||||||
F test/snapshot_fault.test f6c5ef7cb93bf92fbb4e864ecc5c87df7d3a250064838822db5b4d3a5563ede4
|
F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a
|
||||||
F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
|
F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
|
||||||
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
|
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
|
||||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||||
@@ -1898,6 +1898,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8
|
|||||||
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
|
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
|
||||||
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
||||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||||
|
F test/walseh1.test 82da37763b0d87942dccd191e58321532ce3d44b87ef36e04ff9ce13f382bbae
|
||||||
F test/walsetlk.test 34c901443b31ab720afc463f5b236c86ca5c4134402573dce91aa0761de8db5a
|
F test/walsetlk.test 34c901443b31ab720afc463f5b236c86ca5c4134402573dce91aa0761de8db5a
|
||||||
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
|
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
|
||||||
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
||||||
@@ -2012,7 +2013,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
|||||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||||
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
|
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
|
||||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||||
F tool/mkctimec.tcl 38e3db33210a200aae791635125052a643a27aa0619a0debf19aa9c55e1b2dde x
|
F tool/mkctimec.tcl aca4b83e49aecf10368cd5d11bc4847061041ade026db5bd8da17ef201f1403b x
|
||||||
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
||||||
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
|
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
|
||||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||||
@@ -2090,8 +2091,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 6c8538d83495ce65dbd7417263b3b06dbbb2a649e9a61a743911944599d75ffc
|
P 101de670774f63757180282763730aa53e70198bd7a674c27e6044632d39d22a 8a6b0c24937e855b710f97b4aea973eff53e6d43e1182842731547aa4b37db2a
|
||||||
R 00e08242dc8443215cfb70aa39f020b2
|
R f0a8c88fe7b9660119e5c4d560adb197
|
||||||
U stephan
|
U stephan
|
||||||
Z 4a14af7dfae41cdfaa811266b607e2bd
|
Z b7f921f442de7d419e4b8b5ee576c27d
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
101de670774f63757180282763730aa53e70198bd7a674c27e6044632d39d22a
|
4f0aeeba0287e846908180eab6f7080ebe1323ebe49340771864d110e1ca5b2b
|
@@ -60,9 +60,6 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||||
"4_BYTE_ALIGNED_MALLOC",
|
"4_BYTE_ALIGNED_MALLOC",
|
||||||
#endif
|
#endif
|
||||||
#ifdef SQLITE_64BIT_STATS
|
|
||||||
"64BIT_STATS",
|
|
||||||
#endif
|
|
||||||
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||||
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
|
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
|
||||||
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
||||||
@@ -399,6 +396,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||||||
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
||||||
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
|
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SQLITE_LEGACY_JSON_VALID
|
||||||
|
"LEGACY_JSON_VALID",
|
||||||
|
#endif
|
||||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||||
"LIKE_DOESNT_MATCH_BLOBS",
|
"LIKE_DOESNT_MATCH_BLOBS",
|
||||||
#endif
|
#endif
|
||||||
|
@@ -3009,7 +3009,13 @@ static void jsonValidFunc(
|
|||||||
){
|
){
|
||||||
JsonParse *p; /* The parse */
|
JsonParse *p; /* The parse */
|
||||||
UNUSED_PARAMETER(argc);
|
UNUSED_PARAMETER(argc);
|
||||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
|
||||||
|
#ifdef SQLITE_LEGACY_JSON_VALID
|
||||||
|
/* Incorrect legacy behavior was to return FALSE for a NULL input */
|
||||||
|
sqlite3_result_int(ctx, 0);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
p = jsonParseCached(ctx, argv[0], 0, 0);
|
p = jsonParseCached(ctx, argv[0], 0, 0);
|
||||||
if( p==0 || p->oom ){
|
if( p==0 || p->oom ){
|
||||||
sqlite3_result_error_nomem(ctx);
|
sqlite3_result_error_nomem(ctx);
|
||||||
|
@@ -7729,4 +7729,10 @@ int sqlite3PagerWalFramesize(Pager *pPager){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLITE_USE_SEH
|
||||||
|
int sqlite3PagerWalSystemErrno(Pager *pPager){
|
||||||
|
return sqlite3WalSystemErrno(pPager->pWal);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SQLITE_OMIT_DISKIO */
|
#endif /* SQLITE_OMIT_DISKIO */
|
||||||
|
@@ -240,4 +240,8 @@ void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
|||||||
# define enable_simulated_io_errors()
|
# define enable_simulated_io_errors()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLITE_USE_SEH
|
||||||
|
int sqlite3PagerWalSystemErrno(Pager*);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SQLITE_PAGER_H */
|
#endif /* SQLITE_PAGER_H */
|
||||||
|
@@ -528,6 +528,7 @@ int sqlite3_exec(
|
|||||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||||
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<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_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||||
|
@@ -433,7 +433,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
|||||||
testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
|
testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
|
||||||
testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
|
testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
|
||||||
testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
|
testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
|
||||||
testcase( z[0]=='9' );
|
testcase( z[0]=='9' ); testcase( z[0]=='.' );
|
||||||
*tokenType = TK_INTEGER;
|
*tokenType = TK_INTEGER;
|
||||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||||
if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
|
if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
|
||||||
|
17
src/util.c
17
src/util.c
@@ -141,6 +141,23 @@ void sqlite3ErrorClear(sqlite3 *db){
|
|||||||
*/
|
*/
|
||||||
void sqlite3SystemError(sqlite3 *db, int rc){
|
void sqlite3SystemError(sqlite3 *db, int rc){
|
||||||
if( rc==SQLITE_IOERR_NOMEM ) return;
|
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;
|
rc &= 0xff;
|
||||||
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
|
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
|
||||||
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
|
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
|
||||||
|
@@ -3372,6 +3372,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
|||||||
sqlite3VdbeLeave(p);
|
sqlite3VdbeLeave(p);
|
||||||
return SQLITE_BUSY;
|
return SQLITE_BUSY;
|
||||||
}else if( rc!=SQLITE_OK ){
|
}else if( rc!=SQLITE_OK ){
|
||||||
|
sqlite3SystemError(db, rc);
|
||||||
p->rc = rc;
|
p->rc = rc;
|
||||||
sqlite3RollbackAll(db, SQLITE_OK);
|
sqlite3RollbackAll(db, SQLITE_OK);
|
||||||
p->nChange = 0;
|
p->nChange = 0;
|
||||||
|
557
src/wal.c
557
src/wal.c
@@ -528,7 +528,13 @@ struct Wal {
|
|||||||
u32 iReCksum; /* On commit, recalculate checksums from here */
|
u32 iReCksum; /* On commit, recalculate checksums from here */
|
||||||
const char *zWalName; /* Name of WAL file */
|
const char *zWalName; /* Name of WAL file */
|
||||||
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
|
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 */
|
||||||
|
int iSysErrno; /* System error code following exception */
|
||||||
|
#endif
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
|
int nSehTry; /* Number of nested SEH_TRY{} blocks */
|
||||||
u8 lockError; /* True if a locking error has occurred */
|
u8 lockError; /* True if a locking error has occurred */
|
||||||
#endif
|
#endif
|
||||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||||
@@ -610,6 +616,100 @@ struct WalIterator {
|
|||||||
sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
|
sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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
|
||||||
|
|
||||||
|
#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)
|
||||||
|
#endif /* ifdef SQLITE_USE_SEH */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
|
** 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
|
** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
|
||||||
@@ -682,6 +782,7 @@ static int walIndexPage(
|
|||||||
int iPage, /* The page we seek */
|
int iPage, /* The page we seek */
|
||||||
volatile u32 **ppPage /* Write the page pointer here */
|
volatile u32 **ppPage /* Write the page pointer here */
|
||||||
){
|
){
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
|
if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
|
||||||
return walIndexPageRealloc(pWal, iPage, ppPage);
|
return walIndexPageRealloc(pWal, iPage, ppPage);
|
||||||
}
|
}
|
||||||
@@ -693,6 +794,7 @@ static int walIndexPage(
|
|||||||
*/
|
*/
|
||||||
static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
|
static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
|
||||||
assert( pWal->nWiData>0 && pWal->apWiData[0] );
|
assert( pWal->nWiData>0 && pWal->apWiData[0] );
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
|
return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,6 +803,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
|
|||||||
*/
|
*/
|
||||||
static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
|
static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
|
||||||
assert( pWal->nWiData>0 && pWal->apWiData[0] );
|
assert( pWal->nWiData>0 && pWal->apWiData[0] );
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
return (volatile WalIndexHdr*)pWal->apWiData[0];
|
return (volatile WalIndexHdr*)pWal->apWiData[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -958,12 +1061,18 @@ static int walLockShared(Wal *pWal, int lockIdx){
|
|||||||
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
|
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
|
||||||
walLockName(lockIdx), rc ? "failed" : "ok"));
|
walLockName(lockIdx), rc ? "failed" : "ok"));
|
||||||
VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
static void walUnlockShared(Wal *pWal, int lockIdx){
|
static void walUnlockShared(Wal *pWal, int lockIdx){
|
||||||
if( pWal->exclusiveMode ) return;
|
if( pWal->exclusiveMode ) return;
|
||||||
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
|
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
|
||||||
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
|
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)));
|
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
|
||||||
}
|
}
|
||||||
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
||||||
@@ -974,12 +1083,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
|||||||
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
||||||
walLockName(lockIdx), n, rc ? "failed" : "ok"));
|
walLockName(lockIdx), n, rc ? "failed" : "ok"));
|
||||||
VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
|
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
|
||||||
if( pWal->exclusiveMode ) return;
|
if( pWal->exclusiveMode ) return;
|
||||||
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
|
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
|
||||||
SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
|
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,
|
WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
|
||||||
walLockName(lockIdx), n));
|
walLockName(lockIdx), n));
|
||||||
}
|
}
|
||||||
@@ -1071,6 +1188,7 @@ static int walFramePage(u32 iFrame){
|
|||||||
*/
|
*/
|
||||||
static u32 walFramePgno(Wal *pWal, u32 iFrame){
|
static u32 walFramePgno(Wal *pWal, u32 iFrame){
|
||||||
int iHash = walFramePage(iFrame);
|
int iHash = walFramePage(iFrame);
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( iHash==0 ){
|
if( iHash==0 ){
|
||||||
return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
|
return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
|
||||||
}
|
}
|
||||||
@@ -1330,6 +1448,7 @@ static int walIndexRecover(Wal *pWal){
|
|||||||
/* Malloc a buffer to read frames into. */
|
/* Malloc a buffer to read frames into. */
|
||||||
szFrame = szPage + WAL_FRAME_HDRSIZE;
|
szFrame = szPage + WAL_FRAME_HDRSIZE;
|
||||||
aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
|
aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
|
||||||
|
SEH_FREE_ON_ERROR(0, aFrame);
|
||||||
if( !aFrame ){
|
if( !aFrame ){
|
||||||
rc = SQLITE_NOMEM_BKPT;
|
rc = SQLITE_NOMEM_BKPT;
|
||||||
goto recovery_error;
|
goto recovery_error;
|
||||||
@@ -1405,9 +1524,11 @@ static int walIndexRecover(Wal *pWal){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( iFrame<=iLast ) break;
|
if( iFrame<=iLast ) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SEH_FREE_ON_ERROR(aFrame, 0);
|
||||||
sqlite3_free(aFrame);
|
sqlite3_free(aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,6 +1556,7 @@ finished:
|
|||||||
}else{
|
}else{
|
||||||
pInfo->aReadMark[i] = READMARK_NOT_USED;
|
pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||||
}
|
}
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||||
}else if( rc!=SQLITE_BUSY ){
|
}else if( rc!=SQLITE_BUSY ){
|
||||||
goto recovery_error;
|
goto recovery_error;
|
||||||
@@ -1827,6 +1949,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
|||||||
memset(p, 0, nByte);
|
memset(p, 0, nByte);
|
||||||
p->nSegment = nSegment;
|
p->nSegment = nSegment;
|
||||||
aTmp = (ht_slot*)&(((u8*)p)[nByte]);
|
aTmp = (ht_slot*)&(((u8*)p)[nByte]);
|
||||||
|
SEH_FREE_ON_ERROR(0, p);
|
||||||
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
|
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
|
||||||
WalHashLoc sLoc;
|
WalHashLoc sLoc;
|
||||||
|
|
||||||
@@ -1855,6 +1978,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
|
SEH_FREE_ON_ERROR(p, 0);
|
||||||
walIteratorFree(p);
|
walIteratorFree(p);
|
||||||
p = 0;
|
p = 0;
|
||||||
}
|
}
|
||||||
@@ -2080,13 +2204,13 @@ static int walCheckpoint(
|
|||||||
mxSafeFrame = pWal->hdr.mxFrame;
|
mxSafeFrame = pWal->hdr.mxFrame;
|
||||||
mxPage = pWal->hdr.nPage;
|
mxPage = pWal->hdr.nPage;
|
||||||
for(i=1; i<WAL_NREADER; i++){
|
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 ){
|
if( mxSafeFrame>y ){
|
||||||
assert( y<=pWal->hdr.mxFrame );
|
assert( y<=pWal->hdr.mxFrame );
|
||||||
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
|
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
|
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);
|
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||||
}else if( rc==SQLITE_BUSY ){
|
}else if( rc==SQLITE_BUSY ){
|
||||||
mxSafeFrame = y;
|
mxSafeFrame = y;
|
||||||
@@ -2107,8 +2231,7 @@ static int walCheckpoint(
|
|||||||
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
|
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
|
||||||
){
|
){
|
||||||
u32 nBackfill = pInfo->nBackfill;
|
u32 nBackfill = pInfo->nBackfill;
|
||||||
|
pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
|
||||||
pInfo->nBackfillAttempted = mxSafeFrame;
|
|
||||||
|
|
||||||
/* Sync the WAL to disk */
|
/* Sync the WAL to disk */
|
||||||
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||||
@@ -2139,6 +2262,7 @@ static int walCheckpoint(
|
|||||||
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
||||||
i64 iOffset;
|
i64 iOffset;
|
||||||
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||||
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
||||||
break;
|
break;
|
||||||
@@ -2168,7 +2292,7 @@ static int walCheckpoint(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
AtomicStore(&pInfo->nBackfill, mxSafeFrame);
|
AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2190,6 +2314,7 @@ static int walCheckpoint(
|
|||||||
*/
|
*/
|
||||||
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
|
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
|
||||||
assert( pWal->writeLock );
|
assert( pWal->writeLock );
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
|
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
|
||||||
rc = SQLITE_BUSY;
|
rc = SQLITE_BUSY;
|
||||||
}else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
|
}else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
|
||||||
@@ -2221,6 +2346,7 @@ static int walCheckpoint(
|
|||||||
}
|
}
|
||||||
|
|
||||||
walcheckpoint_out:
|
walcheckpoint_out:
|
||||||
|
SEH_FREE_ON_ERROR(pIter, 0);
|
||||||
walIteratorFree(pIter);
|
walIteratorFree(pIter);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -2243,6 +2369,87 @@ 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) 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;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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.
|
** Close a connection to a log file.
|
||||||
*/
|
*/
|
||||||
@@ -2257,6 +2464,8 @@ int sqlite3WalClose(
|
|||||||
if( pWal ){
|
if( pWal ){
|
||||||
int isDelete = 0; /* True to unlink wal and wal-index files */
|
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
|
/* If an EXCLUSIVE lock can be obtained on the database file (using the
|
||||||
** ordinary, rollback-mode locking methods, this guarantees that the
|
** ordinary, rollback-mode locking methods, this guarantees that the
|
||||||
** connection associated with this log file is the only connection to
|
** connection associated with this log file is the only connection to
|
||||||
@@ -2799,6 +3008,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
|||||||
assert( pWal->nWiData>0 );
|
assert( pWal->nWiData>0 );
|
||||||
assert( pWal->apWiData[0]!=0 );
|
assert( pWal->apWiData[0]!=0 );
|
||||||
pInfo = walCkptInfo(pWal);
|
pInfo = walCkptInfo(pWal);
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
|
if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
|
||||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||||
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
|
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
|
||||||
@@ -2848,7 +3058,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for(i=1; i<WAL_NREADER; i++){
|
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 ){
|
if( mxReadMark<=thisMark && thisMark<=mxFrame ){
|
||||||
assert( thisMark!=READMARK_NOT_USED );
|
assert( thisMark!=READMARK_NOT_USED );
|
||||||
mxReadMark = thisMark;
|
mxReadMark = thisMark;
|
||||||
@@ -2914,7 +3124,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
|||||||
** we can guarantee that the checkpointer that set nBackfill could not
|
** we can guarantee that the checkpointer that set nBackfill could not
|
||||||
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
|
** 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);
|
walShmBarrier(pWal);
|
||||||
if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
|
if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
|
||||||
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
|
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
|
||||||
@@ -2929,6 +3139,53 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
#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;
|
||||||
|
pgno = sLoc.aPgno[i-sLoc.iZero];
|
||||||
|
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
|
** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
|
||||||
** variable so that older snapshots can be accessed. To do this, loop
|
** variable so that older snapshots can be accessed. To do this, loop
|
||||||
@@ -2954,50 +3211,21 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
|
|||||||
assert( pWal->readLock>=0 );
|
assert( pWal->readLock>=0 );
|
||||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
|
void *pBuf1 = sqlite3_malloc(pWal->szPage);
|
||||||
int szPage = (int)pWal->szPage;
|
void *pBuf2 = sqlite3_malloc(pWal->szPage);
|
||||||
i64 szDb; /* Size of db file in bytes */
|
if( pBuf1==0 || pBuf2==0 ){
|
||||||
|
rc = SQLITE_NOMEM;
|
||||||
rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
|
}else{
|
||||||
if( rc==SQLITE_OK ){
|
pWal->ckptLock = 1;
|
||||||
void *pBuf1 = sqlite3_malloc(szPage);
|
SEH_TRY {
|
||||||
void *pBuf2 = sqlite3_malloc(szPage);
|
rc = walSnapshotRecover(pWal, pBuf1, pBuf2);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
|
||||||
sqlite3_free(pBuf1);
|
pWal->ckptLock = 0;
|
||||||
sqlite3_free(pBuf2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite3_free(pBuf1);
|
||||||
|
sqlite3_free(pBuf2);
|
||||||
walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3006,28 +3234,20 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
|
|||||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Begin a read transaction on the database.
|
** This function does the work of sqlite3WalBeginReadTransaction() (see
|
||||||
**
|
** below). That function simply calls this one inside an SEH_TRY{...} block.
|
||||||
** 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.
|
|
||||||
*/
|
*/
|
||||||
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
static int walBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||||
int rc; /* Return code */
|
int rc; /* Return code */
|
||||||
int cnt = 0; /* Number of TryBeginRead attempts */
|
int cnt = 0; /* Number of TryBeginRead attempts */
|
||||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||||
|
int ckptLock = 0;
|
||||||
int bChanged = 0;
|
int bChanged = 0;
|
||||||
WalIndexHdr *pSnapshot = pWal->pSnapshot;
|
WalIndexHdr *pSnapshot = pWal->pSnapshot;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert( pWal->ckptLock==0 );
|
assert( pWal->ckptLock==0 );
|
||||||
|
assert( pWal->nSehTry>0 );
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||||
if( pSnapshot ){
|
if( pSnapshot ){
|
||||||
@@ -3050,7 +3270,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
|||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
pWal->ckptLock = 1;
|
ckptLock = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3114,15 +3334,37 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Release the shared CKPT lock obtained above. */
|
/* Release the shared CKPT lock obtained above. */
|
||||||
if( pWal->ckptLock ){
|
if( ckptLock ){
|
||||||
assert( pSnapshot );
|
assert( pSnapshot );
|
||||||
walUnlockShared(pWal, WAL_CKPT_LOCK);
|
walUnlockShared(pWal, WAL_CKPT_LOCK);
|
||||||
pWal->ckptLock = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return rc;
|
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.
|
||||||
|
*/
|
||||||
|
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
|
** Finish with a read transaction. All this does is release the
|
||||||
** read-lock.
|
** read-lock.
|
||||||
@@ -3143,7 +3385,7 @@ void sqlite3WalEndReadTransaction(Wal *pWal){
|
|||||||
** Return SQLITE_OK if successful, or an error code if an error occurs. If an
|
** 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.
|
** error does occur, the final value of *piRead is undefined.
|
||||||
*/
|
*/
|
||||||
int sqlite3WalFindFrame(
|
static int walFindFrame(
|
||||||
Wal *pWal, /* WAL handle */
|
Wal *pWal, /* WAL handle */
|
||||||
Pgno pgno, /* Database page number to read data for */
|
Pgno pgno, /* Database page number to read data for */
|
||||||
u32 *piRead /* OUT: Frame number (or zero) */
|
u32 *piRead /* OUT: Frame number (or zero) */
|
||||||
@@ -3206,6 +3448,7 @@ int sqlite3WalFindFrame(
|
|||||||
}
|
}
|
||||||
nCollide = HASHTABLE_NSLOT;
|
nCollide = HASHTABLE_NSLOT;
|
||||||
iKey = walHash(pgno);
|
iKey = walHash(pgno);
|
||||||
|
SEH_INJECT_FAULT;
|
||||||
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
|
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
|
||||||
u32 iFrame = iH + sLoc.iZero;
|
u32 iFrame = iH + sLoc.iZero;
|
||||||
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
|
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
|
||||||
@@ -3242,6 +3485,30 @@ int sqlite3WalFindFrame(
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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.
|
||||||
|
*/
|
||||||
|
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
|
** 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
|
** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
|
||||||
@@ -3323,12 +3590,17 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
|
|||||||
** time the read transaction on this connection was started, then
|
** time the read transaction on this connection was started, then
|
||||||
** the write is disallowed.
|
** 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);
|
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
||||||
pWal->writeLock = 0;
|
pWal->writeLock = 0;
|
||||||
rc = SQLITE_BUSY_SNAPSHOT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3364,30 +3636,33 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
|
|||||||
Pgno iMax = pWal->hdr.mxFrame;
|
Pgno iMax = pWal->hdr.mxFrame;
|
||||||
Pgno iFrame;
|
Pgno iFrame;
|
||||||
|
|
||||||
/* Restore the clients cache of the wal-index header to the state it
|
SEH_TRY {
|
||||||
** was in before the client began writing to the database.
|
/* 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.
|
|
||||||
*/
|
*/
|
||||||
assert( walFramePgno(pWal, iFrame)!=1 );
|
memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
|
||||||
rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
|
|
||||||
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -3431,7 +3706,10 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
|
|||||||
pWal->hdr.mxFrame = aWalData[0];
|
pWal->hdr.mxFrame = aWalData[0];
|
||||||
pWal->hdr.aFrameCksum[0] = aWalData[1];
|
pWal->hdr.aFrameCksum[0] = aWalData[1];
|
||||||
pWal->hdr.aFrameCksum[1] = aWalData[2];
|
pWal->hdr.aFrameCksum[1] = aWalData[2];
|
||||||
walCleanupHash(pWal);
|
SEH_TRY {
|
||||||
|
walCleanupHash(pWal);
|
||||||
|
}
|
||||||
|
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3612,7 +3890,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){
|
|||||||
** Write a set of frames to the log. The caller must hold the write-lock
|
** Write a set of frames to the log. The caller must hold the write-lock
|
||||||
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
|
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
|
||||||
*/
|
*/
|
||||||
int sqlite3WalFrames(
|
static int walFrames(
|
||||||
Wal *pWal, /* Wal handle to write to */
|
Wal *pWal, /* Wal handle to write to */
|
||||||
int szPage, /* Database page-size in bytes */
|
int szPage, /* Database page-size in bytes */
|
||||||
PgHdr *pList, /* List of dirty pages to write */
|
PgHdr *pList, /* List of dirty pages to write */
|
||||||
@@ -3723,7 +4001,7 @@ int sqlite3WalFrames(
|
|||||||
** checksums must be recomputed when the transaction is committed. */
|
** checksums must be recomputed when the transaction is committed. */
|
||||||
if( iFirst && (p->pDirty || isCommit==0) ){
|
if( iFirst && (p->pDirty || isCommit==0) ){
|
||||||
u32 iWrite = 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 );
|
assert( rc==SQLITE_OK || iWrite==0 );
|
||||||
if( iWrite>=iFirst ){
|
if( iWrite>=iFirst ){
|
||||||
i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
|
i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
|
||||||
@@ -3842,6 +4120,29 @@ int sqlite3WalFrames(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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.
|
||||||
|
*/
|
||||||
|
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
|
** This routine is called to implement sqlite3_wal_checkpoint() and
|
||||||
** related interfaces.
|
** related interfaces.
|
||||||
@@ -3921,30 +4222,33 @@ int sqlite3WalCheckpoint(
|
|||||||
|
|
||||||
|
|
||||||
/* Read the wal-index header. */
|
/* Read the wal-index header. */
|
||||||
if( rc==SQLITE_OK ){
|
SEH_TRY {
|
||||||
walDisableBlocking(pWal);
|
if( rc==SQLITE_OK ){
|
||||||
rc = walIndexReadHdr(pWal, &isChanged);
|
walDisableBlocking(pWal);
|
||||||
(void)walEnableBlocking(pWal);
|
rc = walIndexReadHdr(pWal, &isChanged);
|
||||||
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
|
(void)walEnableBlocking(pWal);
|
||||||
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
|
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 ){
|
/* Copy data from the log to the database file. */
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
|
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
|
||||||
rc = SQLITE_CORRUPT_BKPT;
|
rc = SQLITE_CORRUPT_BKPT;
|
||||||
}else{
|
}else{
|
||||||
rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
|
rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no error occurred, set the output variables. */
|
/* If no error occurred, set the output variables. */
|
||||||
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
|
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
|
||||||
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
|
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
|
||||||
if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
|
SEH_INJECT_FAULT;
|
||||||
|
if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SEH_EXCEPT( rc = walHandleException(pWal); )
|
||||||
|
|
||||||
if( isChanged ){
|
if( isChanged ){
|
||||||
/* If a new wal-index header was loaded before the checkpoint was
|
/* If a new wal-index header was loaded before the checkpoint was
|
||||||
@@ -4021,7 +4325,9 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op){
|
|||||||
** locks are taken in this case). Nor should the pager attempt to
|
** locks are taken in this case). Nor should the pager attempt to
|
||||||
** upgrade to exclusive-mode following such an error.
|
** upgrade to exclusive-mode following such an error.
|
||||||
*/
|
*/
|
||||||
|
#ifndef SQLITE_USE_SEH
|
||||||
assert( pWal->readLock>=0 || pWal->lockError );
|
assert( pWal->readLock>=0 || pWal->lockError );
|
||||||
|
#endif
|
||||||
assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
|
assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
|
||||||
|
|
||||||
if( op==0 ){
|
if( op==0 ){
|
||||||
@@ -4122,16 +4428,19 @@ int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
|
|||||||
*/
|
*/
|
||||||
int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){
|
int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){
|
||||||
int rc;
|
int rc;
|
||||||
rc = walLockShared(pWal, WAL_CKPT_LOCK);
|
SEH_TRY {
|
||||||
if( rc==SQLITE_OK ){
|
rc = walLockShared(pWal, WAL_CKPT_LOCK);
|
||||||
WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
|
if( rc==SQLITE_OK ){
|
||||||
if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
|
WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
|
||||||
|| pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted
|
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);
|
rc = SQLITE_ERROR_SNAPSHOT;
|
||||||
|
walUnlockShared(pWal, WAL_CKPT_LOCK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SEH_EXCEPT( rc = walHandleException(pWal); )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -151,5 +151,9 @@ int sqlite3WalWriteLock(Wal *pWal, int bLock);
|
|||||||
void sqlite3WalDb(Wal *pWal, sqlite3 *db);
|
void sqlite3WalDb(Wal *pWal, sqlite3 *db);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLITE_USE_SEH
|
||||||
|
int sqlite3WalSystemErrno(Wal*);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ifndef SQLITE_OMIT_WAL */
|
#endif /* ifndef SQLITE_OMIT_WAL */
|
||||||
#endif /* SQLITE_WAL_H */
|
#endif /* SQLITE_WAL_H */
|
||||||
|
@@ -923,9 +923,15 @@ do_execsql_test json-20.3 {
|
|||||||
# a NULL value as the JSON input.
|
# a NULL value as the JSON input.
|
||||||
#
|
#
|
||||||
db null NULL
|
db null NULL
|
||||||
do_execsql_test json-21.1 {
|
if {[db exists {SELECT * FROM pragma_compile_options WHERE compile_options LIKE '%legacy_json_valid%'}]} {
|
||||||
SELECT json_valid(NULL);
|
do_execsql_test json-21.1-legacy {
|
||||||
} NULL
|
SELECT json_valid(NULL);
|
||||||
|
} 0
|
||||||
|
} else {
|
||||||
|
do_execsql_test json-21.1-correct {
|
||||||
|
SELECT json_valid(NULL);
|
||||||
|
} NULL
|
||||||
|
}
|
||||||
do_execsql_test json-21.2 {
|
do_execsql_test json-21.2 {
|
||||||
SELECT json_error_position(NULL);
|
SELECT json_error_position(NULL);
|
||||||
} NULL
|
} NULL
|
||||||
|
@@ -23,6 +23,7 @@ set testprefix snapshot_fault
|
|||||||
# checkpointing the db.
|
# checkpointing the db.
|
||||||
#
|
#
|
||||||
do_faultsim_test 1.0 -prep {
|
do_faultsim_test 1.0 -prep {
|
||||||
|
catch { db2 close }
|
||||||
faultsim_delete_and_reopen
|
faultsim_delete_and_reopen
|
||||||
sqlite3 db2 test.db
|
sqlite3 db2 test.db
|
||||||
db2 eval {
|
db2 eval {
|
||||||
|
150
test/walseh1.test
Normal file
150
test/walseh1.test
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# 2021 August 16
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
source $testdir/malloc_common.tcl
|
||||||
|
set testprefix walseh1
|
||||||
|
|
||||||
|
set ::seh_countdown 0
|
||||||
|
set ::seh_errno 10
|
||||||
|
proc seh_faultsim_callback {iFault} {
|
||||||
|
if {$iFault==650} {
|
||||||
|
incr ::seh_countdown -1
|
||||||
|
if {$::seh_countdown==0} { return $::seh_errno }
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
proc seh_injectinstall {} {
|
||||||
|
sqlite3_test_control_fault_install seh_faultsim_callback
|
||||||
|
}
|
||||||
|
proc seh_injectuninstall {} {
|
||||||
|
sqlite3_test_control_fault_install
|
||||||
|
}
|
||||||
|
proc seh_injectstart {iFail} {
|
||||||
|
set ::seh_errno [expr 2+$iFail*10]
|
||||||
|
set ::seh_countdown $iFail
|
||||||
|
}
|
||||||
|
proc seh_injectstop {} {
|
||||||
|
set res [expr $::seh_countdown<=0]
|
||||||
|
set ::seh_countdown 0
|
||||||
|
set res
|
||||||
|
}
|
||||||
|
|
||||||
|
set FAULTSIM(seh) [list \
|
||||||
|
-injectinstall seh_injectinstall \
|
||||||
|
-injectstart seh_injectstart \
|
||||||
|
-injectstop seh_injectstop \
|
||||||
|
-injecterrlist {{1 {disk I/O error}}} \
|
||||||
|
-injectuninstall seh_injectuninstall \
|
||||||
|
]
|
||||||
|
|
||||||
|
proc test_system_errno {db expect} {
|
||||||
|
set serrno [sqlite3_system_errno $db]
|
||||||
|
if {$serrno!=$expect} {
|
||||||
|
error "surprising system_errno. Expected $expect, got $serrno"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
PRAGMA journal_mode = wal;
|
||||||
|
CREATE TABLE t1(x, y);
|
||||||
|
INSERT INTO t1 VALUES(1, 2);
|
||||||
|
INSERT INTO t1 VALUES(3, 4);
|
||||||
|
} {wal}
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
do_faultsim_test 1 -faults seh -prep {
|
||||||
|
catch { db2 close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
execsql { SELECT * FROM sqlite_schema }
|
||||||
|
sqlite3 db2 test.db
|
||||||
|
} -body {
|
||||||
|
execsql { SELECT * FROM t1 } db2
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4}}
|
||||||
|
if {$testrc} { test_system_errno db2 $::seh_errno }
|
||||||
|
}
|
||||||
|
catch { db2 close }
|
||||||
|
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
do_faultsim_test 2 -faults seh -prep {
|
||||||
|
catch { db close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { SELECT * FROM t1 }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4}}
|
||||||
|
if {$testrc} { test_system_errno db $::seh_errno }
|
||||||
|
}
|
||||||
|
|
||||||
|
do_faultsim_test 3 -faults seh -prep {
|
||||||
|
catch { db close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { INSERT INTO t1 VALUES(5, 6) }
|
||||||
|
execsql { SELECT * FROM t1 }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4 5 6}}
|
||||||
|
if {$testrc} { test_system_errno db $::seh_errno }
|
||||||
|
}
|
||||||
|
|
||||||
|
do_faultsim_test 4 -faults seh -prep {
|
||||||
|
catch { db close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { PRAGMA wal_checkpoint }
|
||||||
|
execsql { INSERT INTO t1 VALUES(7, 8) }
|
||||||
|
execsql { SELECT * FROM t1 }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4 7 8}}
|
||||||
|
if {$testrc} { test_system_errno db $::seh_errno }
|
||||||
|
}
|
||||||
|
catch { db close }
|
||||||
|
|
||||||
|
do_faultsim_test 5 -faults seh -prep {
|
||||||
|
catch { db close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
execsql {
|
||||||
|
PRAGMA cache_size = 5;
|
||||||
|
BEGIN;
|
||||||
|
WITH s(i) AS (
|
||||||
|
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
|
||||||
|
)
|
||||||
|
INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM s;
|
||||||
|
}
|
||||||
|
} -body {
|
||||||
|
execsql ROLLBACK
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}}
|
||||||
|
if {$testrc} { test_system_errno db $::seh_errno }
|
||||||
|
}
|
||||||
|
catch { db close }
|
||||||
|
|
||||||
|
do_faultsim_test 6 -faults seh -prep {
|
||||||
|
catch { db close }
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { PRAGMA wal_checkpoint = TRUNCATE }
|
||||||
|
execsql { INSERT INTO t1 VALUES(7, 8) }
|
||||||
|
execsql { SELECT * FROM t1 }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4 7 8}}
|
||||||
|
if {$testrc} { test_system_errno db $::seh_errno }
|
||||||
|
}
|
||||||
|
catch { db close }
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
||||||
|
|
@@ -180,6 +180,7 @@ set boolean_defnil_options {
|
|||||||
SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||||
SQLITE_INLINE_MEMCPY
|
SQLITE_INLINE_MEMCPY
|
||||||
SQLITE_INT64_TYPE
|
SQLITE_INT64_TYPE
|
||||||
|
SQLITE_LEGACY_JSON_VALID
|
||||||
SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||||
SQLITE_LOCK_TRACE
|
SQLITE_LOCK_TRACE
|
||||||
SQLITE_LOG_CACHE_SPILL
|
SQLITE_LOG_CACHE_SPILL
|
||||||
|
Reference in New Issue
Block a user