1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge the latest enhancements from trunk.

FossilOrigin-Name: 91e5c07eaf884d3598df8eb54f0910a80df48397
This commit is contained in:
drh
2016-04-29 16:01:18 +00:00
62 changed files with 2332 additions and 535 deletions

View File

@@ -1032,7 +1032,7 @@ FTS5_SRC = \
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
cp $(TOP)/ext/fts5/fts5parse.y . cp $(TOP)/ext/fts5/fts5parse.y .
rm -f fts5parse.h rm -f fts5parse.h
./lemon $(OPTS) fts5parse.y ./lemon$(BEXE) $(OPTS) fts5parse.y
fts5parse.h: fts5parse.c fts5parse.h: fts5parse.c
@@ -1164,8 +1164,9 @@ loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
# symbols that do not begin with "sqlite3_". It is run as part of the # symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script. # releasetest.tcl script.
# #
VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
checksymbols: sqlite3.lo checksymbols: sqlite3.lo
nm -g --defined-only sqlite3.o | egrep -v ' sqlite3(changeset|session)?_' ; test $$? -ne 0 nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
echo '0 errors out of 1 tests' echo '0 errors out of 1 tests'
# Build the amalgamation-autoconf package. The amalamgation-tarball target builds # Build the amalgamation-autoconf package. The amalamgation-tarball target builds

View File

@@ -24,12 +24,22 @@
*/ */
void usage(const char *zArgv0){ void usage(const char *zArgv0){
fprintf(stderr, fprintf(stderr,
"Usage: %s [-step NSTEP] TARGET-DB RBU-DB\n" "Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n"
"\n" "\n"
" Argument RBU-DB must be an RBU database containing an update suitable for\n" "Where options are:\n"
" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n" "\n"
" (the default value), this program attempts to apply the entire update to\n" " -step NSTEP\n"
" the target database.\n" " -vacuum\n"
"\n"
" If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
" database containing an update suitable for target database TARGET-DB.\n"
" Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n"
" RBU, and RBU-DB is used as the state database for the vacuum (refer to\n"
" API documentation for details).\n"
"\n"
" If NSTEP is set to less than or equal to zero (the default value), this \n"
" program attempts to perform the entire update or vacuum operation before\n"
" exiting\n"
"\n" "\n"
" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n" " If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
" to sqlite3rbu_step(). If the RBU update has not been completely applied\n" " to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
@@ -69,29 +79,43 @@ int main(int argc, char **argv){
char *zErrmsg; /* Error message, if any */ char *zErrmsg; /* Error message, if any */
sqlite3rbu *pRbu; /* RBU handle */ sqlite3rbu *pRbu; /* RBU handle */
int nStep = 0; /* Maximum number of step() calls */ int nStep = 0; /* Maximum number of step() calls */
int bVacuum = 0;
int rc; int rc;
sqlite3_int64 nProgress = 0; sqlite3_int64 nProgress = 0;
int nArg = argc-2;
/* Process command line arguments. Following this block local variables if( argc<3 ) usage(argv[0]);
** zTarget, zRbu and nStep are all set. */ for(i=1; i<nArg; i++){
if( argc==5 ){ const char *zArg = argv[i];
size_t nArg1 = strlen(argv[1]); int nArg = strlen(zArg);
if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]); if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
nStep = atoi(argv[2]); bVacuum = 1;
}else if( argc!=3 ){ }else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
usage(argv[0]); i++;
nStep = atoi(argv[i]);
}else{
usage(argv[0]);
}
} }
zTarget = argv[argc-2]; zTarget = argv[argc-2];
zRbu = argv[argc-1]; zRbu = argv[argc-1];
report_default_vfs(); report_default_vfs();
/* Open an RBU handle. If nStep is less than or equal to zero, call /* Open an RBU handle. A vacuum handle if -vacuum was specified, or a
** regular RBU update handle otherwise. */
if( bVacuum ){
pRbu = sqlite3rbu_vacuum(zTarget, zRbu);
}else{
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
}
report_rbu_vfs(pRbu);
/* If nStep is less than or equal to zero, call
** sqlite3rbu_step() until either the RBU has been completely applied ** sqlite3rbu_step() until either the RBU has been completely applied
** or an error occurs. Or, if nStep is greater than zero, call ** or an error occurs. Or, if nStep is greater than zero, call
** sqlite3rbu_step() a maximum of nStep times. */ ** sqlite3rbu_step() a maximum of nStep times. */
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
report_rbu_vfs(pRbu);
for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++); for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
nProgress = sqlite3rbu_progress(pRbu); nProgress = sqlite3rbu_progress(pRbu);
rc = sqlite3rbu_close(pRbu, &zErrmsg); rc = sqlite3rbu_close(pRbu, &zErrmsg);

98
ext/rbu/rbufault3.test Normal file
View File

@@ -0,0 +1,98 @@
# 2016 April 20
#
# 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.
#
#***********************************************************************
#
# This file contains fault injection tests for RBU vacuum operations.
#
source [file join [file dirname [info script]] rbu_common.tcl]
source $testdir/malloc_common.tcl
set ::testprefix rbufault3
foreach {fault errlist} {
oom-* {
{1 SQLITE_NOMEM}
{1 SQLITE_IOERR_NOMEM}
{1 {SQLITE_NOMEM - out of memory}}
}
ioerr-* {
{1 {SQLITE_IOERR - disk I/O error}}
{1 SQLITE_IOERR}
{1 SQLITE_IOERR_WRITE}
{1 SQLITE_IOERR_FSYNC}
{1 SQLITE_IOERR_READ}
{1 {SQLITE_IOERR - unable to open database: test.db2}}
{1 {SQLITE_ERROR - unable to open database: test.db2}}
{1 {SQLITE_ERROR - SQL logic error or missing database}}
}
cantopen* {
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
{1 {SQLITE_CANTOPEN - unable to open database file}}
{1 SQLITE_CANTOPEN}
}
} {
reset_db
do_execsql_test 0 {
CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
INSERT INTO target VALUES(1, 2, 3);
INSERT INTO target VALUES(4, 5, 6);
INSERT INTO target VALUES(7, 8, 9);
CREATE INDEX i1 ON target(z);
}
faultsim_save_and_close
do_faultsim_test 1 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_DONE} {*}$::errlist]
}
do_faultsim_test 2 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
}
forcedelete test.db2
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
faultsim_save_and_close
do_faultsim_test 3 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
}
}
finish_test

410
ext/rbu/rbuvacuum.test Normal file
View File

@@ -0,0 +1,410 @@
# 2016 April 15
#
# 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.
#
#***********************************************************************
#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbuvacuum
proc do_rbu_vacuum_test {tn step} {
uplevel [list do_test $tn.1 {
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
while 1 {
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
if {$step==1} { rbu close }
}
rbu close
} {SQLITE_DONE}]
uplevel [list do_execsql_test $tn.2 {
PRAGMA integrity_check
} ok]
}
foreach step {0 1} {
set ::testprefix rbuvacuum-step=$step
reset_db
# Simplest possible vacuum.
do_execsql_test 1.0 {
PRAGMA page_size = 1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
PRAGMA integrity_check;
} {ok}
do_rbu_vacuum_test 1.1 $step
# A vacuum that actually reclaims space.
do_execsql_test 1.2.1 {
INSERT INTO t1 VALUES(8, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(9, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(10, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(11, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(12, randomblob(900), randomblob(900));
PRAGMA page_count;
} {12}
do_execsql_test 1.2.2 {
DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
PRAGMA page_count;
} {12}
do_rbu_vacuum_test 1.2.3 $step
do_execsql_test 1.2.4 {
PRAGMA page_count;
} {3}
# Add an index to the table.
do_execsql_test 1.3.1 {
CREATE INDEX t1b ON t1(b);
INSERT INTO t1 VALUES(13, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(14, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(15, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(16, randomblob(900), randomblob(900));
PRAGMA page_count;
} {18}
do_execsql_test 1.3.2 {
DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
PRAGMA page_count;
} {18}
do_rbu_vacuum_test 1.3.3 $step
do_execsql_test 1.3.4 {
PRAGMA page_count;
} {5}
# WITHOUT ROWID table.
do_execsql_test 1.4.1 {
CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
INSERT INTO t2 VALUES(randomblob(900), 1, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 2, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 3, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 4, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 6, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 7, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 8, randomblob(900));
DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
PRAGMA page_count;
} {20}
do_rbu_vacuum_test 1.4.2 $step
do_execsql_test 1.4.3 {
PRAGMA page_count;
} {10}
# WITHOUT ROWID table with an index.
do_execsql_test 1.4.1 {
CREATE INDEX t2c ON t2(c);
INSERT INTO t2 VALUES(randomblob(900), 9, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 10, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 11, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 12, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 13, randomblob(900));
DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
PRAGMA page_count;
} {35}
do_rbu_vacuum_test 1.4.2 $step
do_execsql_test 1.4.3 {
PRAGMA page_count;
} {15}
do_execsql_test 1.4.4 {
VACUUM;
PRAGMA page_count;
} {15}
do_execsql_test 1.5.1 {
CREATE TABLE t3(a, b, c);
INSERT INTO t3 VALUES('a', 'b', 'c');
INSERT INTO t3 VALUES('d', 'e', 'f');
INSERT INTO t3 VALUES('g', 'h', 'i');
}
do_rbu_vacuum_test 1.5.2 $step
do_execsql_test 1.5.3 {
SELECT * FROM t3
} {a b c d e f g h i}
do_execsql_test 1.5.4 {
CREATE INDEX t3a ON t3(a);
CREATE INDEX t3b ON t3(b);
CREATE INDEX t3c ON t3(c);
INSERT INTO t3 VALUES('j', 'k', 'l');
DELETE FROM t3 WHERE a = 'g';
}
do_rbu_vacuum_test 1.5.5 $step
do_execsql_test 1.5.6 {
SELECT rowid, * FROM t3 ORDER BY b
} {1 a b c 2 d e f 4 j k l}
do_execsql_test 1.6.1 {
CREATE TABLE t4(a PRIMARY KEY, b, c);
INSERT INTO t4 VALUES('a', 'b', 'c');
INSERT INTO t4 VALUES('d', 'e', 'f');
INSERT INTO t4 VALUES('g', 'h', 'i');
}
do_rbu_vacuum_test 1.6.2 $step
do_execsql_test 1.6.3 {
SELECT * FROM t4
} {a b c d e f g h i}
do_execsql_test 1.6.4 {
CREATE INDEX t4a ON t4(a);
CREATE INDEX t4b ON t4(b);
CREATE INDEX t4c ON t4(c);
INSERT INTO t4 VALUES('j', 'k', 'l');
DELETE FROM t4 WHERE a='g';
}
do_rbu_vacuum_test 1.6.5 $step
do_execsql_test 1.6.6 {
SELECT * FROM t4 ORDER BY b
} {a b c d e f j k l}
reset_db
do_execsql_test 1.7.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
DELETE FROM t1 WHERE a=2;
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
DELETE FROM t1 WHERE a=4;
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
DELETE FROM t1 WHERE a=6;
SELECT * FROM t1;
} {1 one 3 three 5 five}
do_rbu_vacuum_test 1.7.1 $step
do_execsql_test 1.7.2 {
INSERT INTO t1 VALUES(NULL, 'seven');
SELECT * FROM t1;
} {1 one 3 three 5 five 7 seven}
reset_db
do_execsql_test 1.8.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
ANALYZE;
SELECT * FROM sqlite_stat1;
} {t1 i1 {6 1}}
do_rbu_vacuum_test 1.8.1 $step
do_execsql_test 1.7.2 {
SELECT * FROM sqlite_stat1;
} {t1 i1 {6 1}}
reset_db
do_execsql_test 1.9.0 {
PRAGMA page_size = 8192;
PRAGMA auto_vacuum = 2;
PRAGMA user_version = 412;
PRAGMA application_id = 413;
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
PRAGMA main.page_size;
PRAGMA main.auto_vacuum;
PRAGMA main.user_version;
PRAGMA main.application_id;
} {8192 2 412 413}
do_rbu_vacuum_test 1.9.1 $step
do_execsql_test 1.9.2 {
PRAGMA main.page_size;
PRAGMA main.auto_vacuum;
PRAGMA main.user_version;
PRAGMA main.application_id;
} {8192 2 412 413}
# Vacuum a database with a large sqlite_master table.
#
reset_db
do_test 1.10.1 {
for {set i 1} {$i < 50} {incr i} {
execsql "PRAGMA page_size = 1024"
execsql "CREATE TABLE t$i (a, b, c, PRIMARY KEY(a, b));"
execsql "
INSERT INTO t$i VALUES(1, 2, 3);
INSERT INTO t$i VALUES(4, 5, 6);
"
}
} {}
do_rbu_vacuum_test 1.10.2 $step
# Database with empty tables.
#
reset_db
do_execsql_test 1.11.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
INSERT INTO t4 VALUES(1, 2);
}
do_rbu_vacuum_test 1.11.2 $step
do_execsql_test 1.11.3 {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;
} {1 2}
reset_db
do_execsql_test 1.12.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 2);
}
do_rbu_vacuum_test 1.12.2 $step
do_execsql_test 1.12.3 {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;
} {1 2}
}
set ::testprefix rbuvacuum
#-------------------------------------------------------------------------
# Test some error cases:
#
# 2.1.* the db being vacuumed being in wal mode already.
# 2.2.* database modified mid vacuum.
#
reset_db
do_execsql_test 2.1.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(9, 10);
} wal
do_test 2.1.1 {
sqlite3rbu_vacuum rbu test.db state.db
rbu step
} {SQLITE_ERROR}
do_test 2.1.2 {
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
reset_db
do_execsql_test 2.2.0 {
CREATE TABLE tx(a PRIMARY KEY, b BLOB);
INSERT INTO tx VALUES(1, randomblob(900));
INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
}
db_save_and_close
for {set i 1} 1 {incr i} {
db_restore_and_reopen
sqlite3rbu_vacuum rbu test.db state.db
for {set step 0} {$step<$i} {incr step} { rbu step }
rbu close
if {[file exists test.db-wal]} break
execsql { INSERT INTO tx VALUES(20, 20) }
do_test 2.2.$i.1 {
sqlite3rbu_vacuum rbu test.db state.db
rbu step
} {SQLITE_BUSY}
do_test 2.2.$i.2 {
list [catch { rbu close } msg] $msg
} {1 {SQLITE_BUSY - database modified during rbu vacuum}}
}
#-------------------------------------------------------------------------
# Test that a database that uses custom collation sequences can be RBU
# vacuumed.
#
reset_db
forcedelete state.db
proc noop {args} {}
proc length_cmp {x y} {
set n1 [string length $x]
set n2 [string length $y]
return [expr $n1 - $n2]
}
sqlite3_create_collation_v2 db length length_cmp noop
do_execsql_test 3.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 'i');
INSERT INTO t1 VALUES(2, 'iiii');
INSERT INTO t1 VALUES(3, 'ii');
INSERT INTO t1 VALUES(4, 'iii');
SELECT a FROM t1 ORDER BY b COLLATE length;
} {1 3 4 2}
do_execsql_test 3.1 {
CREATE INDEX i1 ON t1(b COLLATE length);
}
do_test 3.2 {
sqlite3rbu_vacuum rbu test.db state.db
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.3 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 0]
sqlite3_create_collation_v2 $db1 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.4 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 1]
sqlite3_create_collation_v2 $db1 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.5 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 0]
set db2 [rbu db 1]
sqlite3_create_collation_v2 $db1 length length_cmp noop
sqlite3_create_collation_v2 $db2 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {0 SQLITE_DONE}
catch { db close }
finish_test

File diff suppressed because it is too large Load Diff

View File

@@ -314,6 +314,38 @@ sqlite3rbu *sqlite3rbu_open(
const char *zState const char *zState
); );
/*
** Open an RBU handle to perform an RBU vacuum on database file zTarget.
** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
** that it can be suspended and resumed like an RBU update.
**
** The second argument to this function, which may not be NULL, identifies
** a database in which to store the state of the RBU vacuum operation if
** it is suspended. The first time sqlite3rbu_vacuum() is called, to start
** an RBU vacuum operation, the state database should either not exist or
** be empty (contain no tables). If an RBU vacuum is suspended by calling
** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
** returned SQLITE_DONE, the vacuum state is stored in the state database.
** The vacuum can be resumed by calling this function to open a new RBU
** handle specifying the same target and state databases.
**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
** of the state tables within the state database are zeroed. This way,
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
** new RBU vacuum operation.
**
** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
** describing the sqlite3rbu_create_vfs() API function below for
** a description of the complications associated with using RBU with
** zipvfs databases.
*/
sqlite3rbu *sqlite3rbu_vacuum(
const char *zTarget,
const char *zState
);
/* /*
** Internally, each RBU connection uses a separate SQLite database ** Internally, each RBU connection uses a separate SQLite database
** connection to access the target and rbu update databases. This ** connection to access the target and rbu update databases. This

View File

@@ -20,8 +20,9 @@
#include <tcl.h> #include <tcl.h>
#include <assert.h> #include <assert.h>
/* From main.c (apparently...) */ /* From main.c */
extern const char *sqlite3ErrName(int); extern const char *sqlite3ErrName(int);
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
@@ -66,7 +67,8 @@ static int test_sqlite3rbu_cmd(
{"create_rbu_delta", 2, ""}, /* 2 */ {"create_rbu_delta", 2, ""}, /* 2 */
{"savestate", 2, ""}, /* 3 */ {"savestate", 2, ""}, /* 3 */
{"dbMain_eval", 3, "SQL"}, /* 4 */ {"dbMain_eval", 3, "SQL"}, /* 4 */
{"bp_progress", 2, ""}, /* 5 */ {"bp_progress", 2, ""}, /* 5 */
{"db", 3, "RBU"}, /* 6 */
{0,0,0} {0,0,0}
}; };
int iCmd; int iCmd;
@@ -149,6 +151,22 @@ static int test_sqlite3rbu_cmd(
break; break;
} }
case 6: /* db */ {
int bArg;
if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){
ret = TCL_ERROR;
}else{
char zBuf[50];
sqlite3 *db = sqlite3rbu_db(pRbu, bArg);
if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){
ret = TCL_ERROR;
}else{
Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
}
}
break;
}
default: /* seems unlikely */ default: /* seems unlikely */
assert( !"cannot happen" ); assert( !"cannot happen" );
break; break;
@@ -187,6 +205,34 @@ static int test_sqlite3rbu(
return TCL_OK; return TCL_OK;
} }
/*
** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
*/
static int test_sqlite3rbu_vacuum(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3rbu *pRbu = 0;
const char *zCmd;
const char *zTarget;
const char *zStateDb = 0;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB");
return TCL_ERROR;
}
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
zStateDb = Tcl_GetString(objv[3]);
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
/* /*
** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
*/ */
@@ -274,6 +320,7 @@ int SqliteRbu_Init(Tcl_Interp *interp){
Tcl_ObjCmdProc *xProc; Tcl_ObjCmdProc *xProc;
} aObjCmd[] = { } aObjCmd[] = {
{ "sqlite3rbu", test_sqlite3rbu }, { "sqlite3rbu", test_sqlite3rbu },
{ "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum },
{ "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs }, { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
{ "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs }, { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
{ "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test }, { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },

View File

@@ -17,6 +17,7 @@ if {![info exists testdir]} {
} }
source [file join [file dirname [info script]] session_common.tcl] source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionfault set testprefix sessionfault

View File

@@ -17,6 +17,7 @@ if {![info exists testdir]} {
} }
source [file join [file dirname [info script]] session_common.tcl] source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionfault2 set testprefix sessionfault2
do_execsql_test 1.0.0 { do_execsql_test 1.0.0 {

View File

@@ -592,14 +592,19 @@ static int sessionChangeEqual(
int iCol; /* Used to iterate through table columns */ int iCol; /* Used to iterate through table columns */
for(iCol=0; iCol<pTab->nCol; iCol++){ for(iCol=0; iCol<pTab->nCol; iCol++){
int n1 = sessionSerialLen(a1); if( pTab->abPK[iCol] ){
int n2 = sessionSerialLen(a2); int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
return 0; return 0;
}
a1 += n1;
a2 += n2;
}else{
if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1);
if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2);
} }
if( pTab->abPK[iCol] || bLeftPkOnly==0 ) a1 += n1;
if( pTab->abPK[iCol] || bRightPkOnly==0 ) a2 += n2;
} }
return 1; return 1;

126
manifest
View File

@@ -1,6 +1,6 @@
C Merge\sall\srecent\senhancements\sfrom\strunk. C Merge\sthe\slatest\senhancements\sfrom\strunk.
D 2016-04-20T12:16:05.997 D 2016-04-29T16:01:18.190
F Makefile.in eba680121821b8a60940a81454316f47a341487a F Makefile.in 9e816d0323e418fbc0f8b2c05fc14e0b3763d9e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
@@ -222,7 +222,7 @@ F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rbu/rbu.c ba3983dceffa0938532e79142f391737513de023 F ext/rbu/rbu.c b2c0b5e6ae1a89affc0edfc127ebfa5f637a0ce4
F ext/rbu/rbu1.test 42bd835e019eff789ec241017965277baeb658b1 F ext/rbu/rbu1.test 42bd835e019eff789ec241017965277baeb658b1
F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d
F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
@@ -243,12 +243,14 @@ F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091 F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/sqlite3rbu.c 9097f1d95666dbef72ca61d5b6a13a84660735ac F ext/rbu/rbuvacuum.test 66e02cf299836770e718e95c36686be0b26dbda3
F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2 F ext/rbu/sqlite3rbu.c bf36625990c6865ecf08bd844d8097ed2d0a6958
F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d F ext/rbu/sqlite3rbu.h 2acd0a6344a6079de15c8dc9d84d3df83a665930
F ext/rbu/test_rbu.c 9bbdf6bd8efd58fbc4f192698df50569598fbb9e
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920 F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@@ -289,9 +291,9 @@ F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60 F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test ac1dfd77a0fb0ea310aee40a16645ef1b66d3f88 F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sqlite3session.c beb300cd1b5c5054062c8e6e807b10475e363410 F ext/session/sqlite3session.c beb43b6b888801bb006320bc236baa95f4cc32ae
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
F ext/session/test_session.c 464f2c8bf502795d95969387eb8e93f68c513c15 F ext/session/test_session.c 464f2c8bf502795d95969387eb8e93f68c513c15
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
@@ -329,18 +331,18 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39 F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
F src/delete.c 78eb999114ec04fcf1b7d123ccedb4b5b734930e F src/delete.c 78eb999114ec04fcf1b7d123ccedb4b5b734930e
F src/expr.c 17d4e745ef6a3fd2e4ef863f5f9a4912f1ba1198 F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb
F src/func.c 552d300265aed09eea21f68ac742a440550c0062 F src/func.c ef4c18c8a66143413ce41a58d582d2c14ddf78e1
F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015 F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002 F src/loadext.c 8b3a73f0624c5f7cadbd5cb89940783bee1d39a6
F src/main.c 5ac9dccc03faadd6f867f67b9018ff41eeeadb46 F src/main.c 405d13e3a4f7c5add9fb27702ae70ed0a6e32cca
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@@ -359,38 +361,38 @@ F src/os.c 4d83917f072ad958fba9235136fa2ed43df47905
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343 F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c d0b41a47eb5f0dc00e423a1723aadeab0e78c85f F src/os_unix.c 8422fba2eb592fbbb2d4006b6f2a67cad8951495
F src/os_win.c b169437dff859e308b3726594094a2f8ca922941 F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 476884ce8d8e845daf88f1b12b8ca446bac5fdc5 F src/pager.c 41559a2b4461a6cf4b24bedb47d4e303d02729b5
F src/pager.h 6656436178c295d0668520739118e71a46163b8e F src/pager.h 6656436178c295d0668520739118e71a46163b8e
F src/parse.y 2e1d371f99535ff29d1cd85052aa11cc636e21c8 F src/parse.y 2e1d371f99535ff29d1cd85052aa11cc636e21c8
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache.h 6b865be765d1ebd06145219550b10921c7da7cc9
F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05 F src/pcache1.c 7f51d2b541aab57596adf62db2c4bb025d34f04d
F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84 F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/rowset.c 49eb91c588a2bab36647368e031dc5b66928149d
F src/select.c 30217121bdf6b587462150b8ee9e1467f7a6036b F src/select.c fd4a7ce2937497181063cfedb92058ac89491a5d
F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6 F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6
F src/sqlite.h.in 64eb70a3b309751bebf73a5552a51244f68f0ea5 F src/sqlite.h.in 9984129d86243424b765fcb3f147c697bd20bb54
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2
F src/sqliteInt.h 0d9f22432cf553bab15e25cf168b57d93396922b F src/sqliteInt.h e6ac0d8f8cbb062a57882858b1deed1a7924314b
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060 F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060
F src/test1.c 457c601302b8a0f5960dffd17b6a2877603841dd F src/test1.c ee8fd5c32acb93fb6fe885ca4801cfab85f5563f
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test3.c 0df6f8dbb4cbaa7106397c70a271fa6a43659042
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1 F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723 F src/test6.c 2c014d4977efd6107ec9eef3dfdec56ac516f824
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3 F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75 F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
@@ -402,14 +404,14 @@ F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 5165f79b3aea5305627ac36dd7b9b5f124572da1 F src/test_config.c 5165f79b3aea5305627ac36dd7b9b5f124572da1
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c 7e73009d5297b603c11c66d7c7d6723d4b5c73e1 F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b
F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254 F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5 F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c da540964c675fde39487da2bc664096af97190d8 F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950 F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950
F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9 F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9
@@ -425,7 +427,7 @@ F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9 F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
F src/test_syscall.c 4889d374f5a5856b7951f7a67c6401f7b938c6f5 F src/test_syscall.c 268c072541162564a882c57f54a6fee12ef4a4d2
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4 F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9 F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c
@@ -439,9 +441,9 @@ F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c 187a0a2aaa3c5d2ccd2ab0143b2fd9e86d6bc816 F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
F src/vacuum.c c1a94413f8fa9d9b2cbe3af9a89377f777be676c F src/vacuum.c c1a94413f8fa9d9b2cbe3af9a89377f777be676c
F src/vdbe.c 226c51cced9aa6f66748f626413d3f0348f2fcb8 F src/vdbe.c 4f0378eb44406a6a61686dff7970fa314f0f44bd
F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170 F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170
F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd
F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
@@ -510,7 +512,7 @@ F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
F test/backup.test b79299a536a4c6d919094786595b95be56d02014 F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32 F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4 F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
@@ -551,7 +553,7 @@ F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485 F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
@@ -614,7 +616,7 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856 F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65 F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204 F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2 F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -646,7 +648,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10 F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528 F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519 F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc F test/e_vacuum.test 120f29ea56bdce4d43279527ece894ab5d1729d3
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8 F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0 F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
@@ -661,7 +663,7 @@ F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9 F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308 F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30 F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931 F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
@@ -810,7 +812,7 @@ F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21 F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711 F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 40523db3aa76d62bda71c26f824fa0eabc420f0e F test/hook.test 3b7b99d0eece6d279812c2aef6fa08bdfabc633e
F test/icu.test 73956798bace8982909c00476b216714a6d0559a F test/icu.test 73956798bace8982909c00476b216714a6d0559a
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
@@ -827,7 +829,7 @@ F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635 F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238 F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
@@ -864,7 +866,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577 F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307 F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
@@ -879,9 +881,9 @@ F test/like.test 81632c437a947bf1f7130b19537da6a1a844806a
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4 F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b F test/loadext.test 42a3b8166dfcadcb0e0c8710dc520d97c31a8b98
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7 F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5 F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00 F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12 F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
@@ -970,7 +972,7 @@ F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1 F test/pagerfault.test 42ff797b1e6426c141cc7ee8b7417c9f27427950
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0 F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
@@ -978,10 +980,10 @@ F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test cd1fa041074ed08eeaa563e4d1bacb0c69337ec1 F test/permutations.test b6b3e165fdc1b8c82a820033646dbfc6a7a01746
F test/pragma.test dd5313eee9c6d9d4726593a68ede8768d3b50ccc F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922 F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -989,7 +991,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test 36cd78b178c4eb0401d4f25754ef410fbd9df2a7 F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8 F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
@@ -1027,7 +1029,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686 F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61 F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61
@@ -1093,7 +1095,7 @@ F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77 F test/stat.test 66e95f97b9f724f9ab921d054ee0db3c2689f1ee
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
@@ -1103,7 +1105,7 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899 F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906 F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906
@@ -1112,9 +1114,11 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test c3d8c138f493207612960bbd6a8c50e84975e2ee
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl 7b740ee852c55e1e72b6ebe5044acee7aa4e5553 F test/tester.tcl 30c7a9be8601d1c1c9c93d013545ebcb28d64254
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1130,10 +1134,10 @@ F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660 F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2 F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
F test/tkt-2d1a5c67d.test d371279946622698ab393ff88cad9f5f6d82960b F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28 F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58 F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678 F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7 F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
@@ -1144,7 +1148,7 @@ F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407 F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1 F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894 F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa F test/tkt-5d863f876e.test 726e76d725f6fe0eb2fc8a522b721b79807380ee
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84 F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336 F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
@@ -1160,7 +1164,7 @@ F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5 F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223 F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667 F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67 F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6
F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8 F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9 F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
@@ -1399,7 +1403,7 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test 2d725c214b883e25ae6bb85ef228ecdfa03c6a7b F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372 F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
@@ -1415,7 +1419,7 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c cfbfe061a4b2766512f6b484882eee2c86a14506 F tool/lemon.c 83318dff3911e47f2b85e136e56aa1c4674a2d2b
F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6 F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1485,7 +1489,7 @@ 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 d7381efff47c0a2f307478f196d03df7534f19e3 eba27d4d17a76884292667d570d542e580ee3e77 P 1f709fbf931e4d75848fc90532e2bc67ccd47cd4 9d0a5ae00273686ea35b43bc2ffaa8775c176363
R b2d94baa5aa70083709fce61087ef618 R 53ca713e0bf5b0eed86d88e36153628f
U drh U drh
Z 09ace714760db63cbd8099bd8f9784df Z e98bb20abec63c17e483c921950d1a1a

View File

@@ -1 +1 @@
1f709fbf931e4d75848fc90532e2bc67ccd47cd4 91e5c07eaf884d3598df8eb54f0910a80df48397

View File

@@ -2360,7 +2360,7 @@ static void cacheEntryClear(Parse *pParse, struct yColCache *p){
} }
p->iReg = 0; p->iReg = 0;
pParse->nColCache--; pParse->nColCache--;
assert( cacheIsValid(pParse) ); assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
} }
@@ -2405,7 +2405,7 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->tempReg = 0; p->tempReg = 0;
p->lru = pParse->iCacheCnt++; p->lru = pParse->iCacheCnt++;
pParse->nColCache++; pParse->nColCache++;
assert( cacheIsValid(pParse) ); assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
return; return;
} }
} }

View File

@@ -1386,6 +1386,14 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3 *db = sqlite3_context_db_handle(context); sqlite3 *db = sqlite3_context_db_handle(context);
char *zErrMsg = 0; char *zErrMsg = 0;
/* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc
** flag is set. See the sqlite3_enable_load_extension() API.
*/
if( (db->flags & SQLITE_LoadExtFunc)==0 ){
sqlite3_result_error(context, "not authorized", -1);
return;
}
if( argc==2 ){ if( argc==2 ){
zProc = (const char *)sqlite3_value_text(argv[1]); zProc = (const char *)sqlite3_value_text(argv[1]);
}else{ }else{

View File

@@ -55,7 +55,7 @@ void sqlite3HashClear(Hash *pH){
static unsigned int strHash(const char *z){ static unsigned int strHash(const char *z){
unsigned int h = 0; unsigned int h = 0;
unsigned char c; unsigned char c;
while( (c = (unsigned char)*z++)!=0 ){ while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
} }
return h; return h;
@@ -148,7 +148,7 @@ static HashElem *findElementWithHash(
int count; /* Number of elements left to test */ int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */ unsigned int h; /* The computed hash */
if( pH->ht ){ if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry; struct _ht *pEntry;
h = strHash(pKey) % pH->htsize; h = strHash(pKey) % pH->htsize;
pEntry = &pH->ht[h]; pEntry = &pH->ht[h];

View File

@@ -464,8 +464,9 @@ static int sqlite3LoadExtension(
/* Ticket #1863. To avoid a creating security problems for older /* Ticket #1863. To avoid a creating security problems for older
** applications that relink against newer versions of SQLite, the ** applications that relink against newer versions of SQLite, the
** ability to run load_extension is turned off by default. One ** ability to run load_extension is turned off by default. One
** must call sqlite3_enable_load_extension() to turn on extension ** must call either sqlite3_enable_load_extension(db) or
** loading. Otherwise you get the following error. ** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0)
** to turn on extension loading.
*/ */
if( (db->flags & SQLITE_LoadExtension)==0 ){ if( (db->flags & SQLITE_LoadExtension)==0 ){
if( pzErrMsg ){ if( pzErrMsg ){
@@ -604,9 +605,9 @@ void sqlite3CloseExtensions(sqlite3 *db){
int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
sqlite3_mutex_enter(db->mutex); sqlite3_mutex_enter(db->mutex);
if( onoff ){ if( onoff ){
db->flags |= SQLITE_LoadExtension; db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
}else{ }else{
db->flags &= ~SQLITE_LoadExtension; db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
} }
sqlite3_mutex_leave(db->mutex); sqlite3_mutex_leave(db->mutex);
return SQLITE_OK; return SQLITE_OK;

View File

@@ -804,6 +804,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
}; };
unsigned int i; unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ rc = SQLITE_ERROR; /* IMP: R-42790-23372 */

View File

@@ -4288,10 +4288,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
pShmNode->h = -1; pShmNode->h = -1;
pDbFd->pInode->pShmNode = pShmNode; pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode; pShmNode->pInode = pDbFd->pInode;
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( sqlite3GlobalConfig.bCoreMutex ){
if( pShmNode->mutex==0 ){ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
rc = SQLITE_NOMEM_BKPT; if( pShmNode->mutex==0 ){
goto shm_open_err; rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
} }
if( pInode->bProcessLock==0 ){ if( pInode->bProcessLock==0 ){
@@ -5416,14 +5418,14 @@ static const char *unixTempFileDir(void){
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){ for(i=0; i<=sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
if( zDir==0 ) continue; if( zDir==0 ) continue;
if( osStat(zDir, &buf) ) continue; if( osStat(zDir, &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue; if( !S_ISDIR(buf.st_mode) ) continue;
if( osAccess(zDir, 07) ) continue; if( osAccess(zDir, 03) ) continue;
break; return zDir;
} }
return zDir; return 0;
} }
/* /*
@@ -5439,9 +5441,11 @@ static int unixGetTempname(int nBuf, char *zBuf){
** using the io-error infrastructure to test that SQLite handles this ** using the io-error infrastructure to test that SQLite handles this
** function failing. ** function failing.
*/ */
zBuf[0] = 0;
SimulateIOError( return SQLITE_IOERR ); SimulateIOError( return SQLITE_IOERR );
zDir = unixTempFileDir(); zDir = unixTempFileDir();
if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
do{ do{
u64 r; u64 r;
sqlite3_randomness(sizeof(r), &r); sqlite3_randomness(sizeof(r), &r);

View File

@@ -1260,8 +1260,8 @@ int sqlite3_win32_reset_heap(){
int rc; int rc;
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
sqlite3_mutex_enter(pMaster); sqlite3_mutex_enter(pMaster);
sqlite3_mutex_enter(pMem); sqlite3_mutex_enter(pMem);
winMemAssertMagic(); winMemAssertMagic();
@@ -3169,9 +3169,8 @@ static int winLock(sqlite3_file *id, int locktype){
** the PENDING_LOCK byte is temporary. ** the PENDING_LOCK byte is temporary.
*/ */
newLocktype = pFile->locktype; newLocktype = pFile->locktype;
if( (pFile->locktype==NO_LOCK) if( pFile->locktype==NO_LOCK
|| ( (locktype==EXCLUSIVE_LOCK) || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
&& (pFile->locktype==RESERVED_LOCK))
){ ){
int cnt = 3; int cnt = 3;
while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
@@ -3765,10 +3764,12 @@ static int winOpenSharedMemory(winFile *pDbFd){
pShmNode->pNext = winShmNodeList; pShmNode->pNext = winShmNodeList;
winShmNodeList = pShmNode; winShmNodeList = pShmNode;
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( sqlite3GlobalConfig.bCoreMutex ){
if( pShmNode->mutex==0 ){ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
rc = SQLITE_IOERR_NOMEM_BKPT; if( pShmNode->mutex==0 ){
goto shm_open_err; rc = SQLITE_IOERR_NOMEM_BKPT;
goto shm_open_err;
}
} }
rc = winOpen(pDbFd->pVfs, rc = winOpen(pDbFd->pVfs,

View File

@@ -875,6 +875,7 @@ static int assert_pager_state(Pager *p){
** state. ** state.
*/ */
if( MEMDB ){ if( MEMDB ){
assert( !isOpen(p->fd) );
assert( p->noSync ); assert( p->noSync );
assert( p->journalMode==PAGER_JOURNALMODE_OFF assert( p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_MEMORY || p->journalMode==PAGER_JOURNALMODE_MEMORY
@@ -963,7 +964,7 @@ static int assert_pager_state(Pager *p){
** back to OPEN state. ** back to OPEN state.
*/ */
assert( pPager->errCode!=SQLITE_OK ); assert( pPager->errCode!=SQLITE_OK );
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
break; break;
} }
@@ -1175,6 +1176,8 @@ static int jrnlBufferSize(Pager *pPager){
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
} }
#else
# define jrnlBufferSize(x) 0
#endif #endif
/* /*
@@ -1868,13 +1871,17 @@ static void pager_unlock(Pager *pPager){
** it can safely move back to PAGER_OPEN state. This happens in both ** it can safely move back to PAGER_OPEN state. This happens in both
** normal and exclusive-locking mode. ** normal and exclusive-locking mode.
*/ */
assert( pPager->errCode==SQLITE_OK || !MEMDB );
if( pPager->errCode ){ if( pPager->errCode ){
assert( !MEMDB ); if( pPager->tempFile==0 ){
pager_reset(pPager); pager_reset(pPager);
pPager->changeCountDone = pPager->tempFile; pPager->changeCountDone = 0;
pPager->eState = PAGER_OPEN; pPager->eState = PAGER_OPEN;
pPager->errCode = SQLITE_OK; }else{
pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
}
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
pPager->errCode = SQLITE_OK;
} }
pPager->journalOff = 0; pPager->journalOff = 0;
@@ -1918,6 +1925,25 @@ static int pager_error(Pager *pPager, int rc){
static int pager_truncate(Pager *pPager, Pgno nPage); static int pager_truncate(Pager *pPager, Pgno nPage);
/*
** The write transaction open on the pager passed as the only argument is
** being committed. This function returns true if all dirty pages should
** be flushed to disk, or false otherwise. Pages should be flushed to disk
** unless one of the following is true:
**
** * The db is an in-memory database.
**
** * The db is a temporary database and the db file has not been opened.
**
** * The db is a temporary database and the cache contains less than
** C/4 dirty pages, where C is the configured cache-size.
*/
static int pagerFlushOnCommit(Pager *pPager){
if( pPager->tempFile==0 ) return 1;
if( !isOpen(pPager->fd) ) return 0;
return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
}
/* /*
** This routine ends a transaction. A transaction is usually ended by ** This routine ends a transaction. A transaction is usually ended by
** either a COMMIT or a ROLLBACK operation. This routine may be called ** either a COMMIT or a ROLLBACK operation. This routine may be called
@@ -2055,7 +2081,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
pagerFreeBitvecs(pPager); pagerFreeBitvecs(pPager);
pPager->nRec = 0; pPager->nRec = 0;
sqlite3PcacheCleanAll(pPager->pPCache); if( MEMDB || pagerFlushOnCommit(pPager) ){
sqlite3PcacheCleanAll(pPager->pPCache);
}else{
sqlite3PcacheClearWritable(pPager->pPCache);
}
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
if( pagerUseWal(pPager) ){ if( pagerUseWal(pPager) ){
@@ -2340,7 +2370,7 @@ static int pager_playback_one_page(
pPg = sqlite3PagerLookup(pPager, pgno); pPg = sqlite3PagerLookup(pPager, pgno);
} }
assert( pPg || !MEMDB ); assert( pPg || !MEMDB );
assert( pPager->eState!=PAGER_OPEN || pPg==0 ); assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
(isMainJrnl?"main-journal":"sub-journal") (isMainJrnl?"main-journal":"sub-journal")
@@ -2423,9 +2453,13 @@ static int pager_playback_one_page(
** be written out into the database file before its journal file ** be written out into the database file before its journal file
** segment is synced. If a crash occurs during or following this, ** segment is synced. If a crash occurs during or following this,
** database corruption may ensue. ** database corruption may ensue.
**
** Update: Another exception is for temp files that are not
** in-memory databases. In this case the page may have been dirty
** at the start of the transaction.
*/ */
assert( !pagerUseWal(pPager) ); assert( !pagerUseWal(pPager) );
sqlite3PcacheMakeClean(pPg); if( pPager->tempFile==0 ) sqlite3PcacheMakeClean(pPg);
} }
pager_set_pagehash(pPg); pager_set_pagehash(pPg);
@@ -3227,6 +3261,8 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
*/ */
assert( pPager->eState==PAGER_OPEN ); assert( pPager->eState==PAGER_OPEN );
assert( pPager->eLock>=SHARED_LOCK ); assert( pPager->eLock>=SHARED_LOCK );
assert( isOpen(pPager->fd) );
assert( pPager->tempFile==0 );
nPage = sqlite3WalDbsize(pPager->pWal); nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the /* If the number of pages in the database is not available from the
@@ -3234,14 +3270,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
** the database file. If the size of the database file is not an ** the database file. If the size of the database file is not an
** integer multiple of the page-size, round up the result. ** integer multiple of the page-size, round up the result.
*/ */
if( nPage==0 ){ if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
i64 n = 0; /* Size of db file in bytes */ i64 n = 0; /* Size of db file in bytes */
assert( isOpen(pPager->fd) || pPager->tempFile ); int rc = sqlite3OsFileSize(pPager->fd, &n);
if( isOpen(pPager->fd) ){ if( rc!=SQLITE_OK ){
int rc = sqlite3OsFileSize(pPager->fd, &n); return rc;
if( rc!=SQLITE_OK ){
return rc;
}
} }
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize); nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
} }
@@ -4317,8 +4350,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
/* This function is only called for rollback pagers in WRITER_DBMOD state. */ /* This function is only called for rollback pagers in WRITER_DBMOD state. */
assert( !pagerUseWal(pPager) ); assert( !pagerUseWal(pPager) );
assert( pPager->eState==PAGER_WRITER_DBMOD ); assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
assert( pPager->eLock==EXCLUSIVE_LOCK ); assert( pPager->eLock==EXCLUSIVE_LOCK );
assert( isOpen(pPager->fd) || pList->pDirty==0 );
/* If the file is a temp-file has not yet been opened, open it now. It /* If the file is a temp-file has not yet been opened, open it now. It
** is not possible for rc to be other than SQLITE_OK if this branch ** is not possible for rc to be other than SQLITE_OK if this branch
@@ -4992,6 +5026,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
if( rc==SQLITE_OK && !locked ){ if( rc==SQLITE_OK && !locked ){
Pgno nPage; /* Number of pages in database file */ Pgno nPage; /* Number of pages in database file */
assert( pPager->tempFile==0 );
rc = pagerPagecount(pPager, &nPage); rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
/* If the database is zero pages in size, that means that either (1) the /* If the database is zero pages in size, that means that either (1) the
@@ -5084,17 +5119,17 @@ int sqlite3PagerSharedLock(Pager *pPager){
/* This routine is only called from b-tree and only when there are no /* This routine is only called from b-tree and only when there are no
** outstanding pages. This implies that the pager state should either ** outstanding pages. This implies that the pager state should either
** be OPEN or READER. READER is only possible if the pager is or was in ** be OPEN or READER. READER is only possible if the pager is or was in
** exclusive access mode. ** exclusive access mode. */
*/
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
assert( assert_pager_state(pPager) ); assert( assert_pager_state(pPager) );
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } assert( pPager->errCode==SQLITE_OK );
if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
int bHotJournal = 1; /* True if there exists a hot journal-file */ int bHotJournal = 1; /* True if there exists a hot journal-file */
assert( !MEMDB ); assert( !MEMDB );
assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
rc = pager_wait_on_lock(pPager, SHARED_LOCK); rc = pager_wait_on_lock(pPager, SHARED_LOCK);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
@@ -5180,7 +5215,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
assert( rc==SQLITE_OK ); assert( rc==SQLITE_OK );
rc = pagerSyncHotJournal(pPager); rc = pagerSyncHotJournal(pPager);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = pager_playback(pPager, 1); rc = pager_playback(pPager, !pPager->tempFile);
pPager->eState = PAGER_OPEN; pPager->eState = PAGER_OPEN;
} }
}else if( !pPager->exclusiveMode ){ }else if( !pPager->exclusiveMode ){
@@ -5276,7 +5311,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
rc = pagerBeginReadTransaction(pPager); rc = pagerBeginReadTransaction(pPager);
} }
if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
rc = pagerPagecount(pPager, &pPager->dbSize); rc = pagerPagecount(pPager, &pPager->dbSize);
} }
@@ -5419,7 +5454,7 @@ int sqlite3PagerGet(
); );
if( rc==SQLITE_OK && pData ){ if( rc==SQLITE_OK && pData ){
if( pPager->eState>PAGER_READER ){ if( pPager->eState>PAGER_READER || pPager->tempFile ){
pPg = sqlite3PagerLookup(pPager, pgno); pPg = sqlite3PagerLookup(pPager, pgno);
} }
if( pPg==0 ){ if( pPg==0 ){
@@ -5486,7 +5521,8 @@ int sqlite3PagerGet(
goto pager_acquire_err; goto pager_acquire_err;
} }
if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){ assert( !isOpen(pPager->fd) || !MEMDB );
if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
if( pgno>pPager->mxPgno ){ if( pgno>pPager->mxPgno ){
rc = SQLITE_FULL; rc = SQLITE_FULL;
goto pager_acquire_err; goto pager_acquire_err;
@@ -5628,24 +5664,24 @@ static int pager_open_journal(Pager *pPager){
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
sqlite3MemJournalOpen(pPager->jfd); sqlite3MemJournalOpen(pPager->jfd);
}else{ }else{
const int flags = /* VFS flags to open journal file */ int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| int nSpill;
(pPager->tempFile ?
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): if( pPager->tempFile ){
(SQLITE_OPEN_MAIN_JOURNAL) flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
); nSpill = sqlite3Config.nStmtSpill;
}else{
flags |= SQLITE_OPEN_MAIN_JOURNAL;
nSpill = jrnlBufferSize(pPager);
}
/* Verify that the database still has the same name as it did when /* Verify that the database still has the same name as it did when
** it was originally opened. */ ** it was originally opened. */
rc = databaseIsUnmoved(pPager); rc = databaseIsUnmoved(pPager);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
#ifdef SQLITE_ENABLE_ATOMIC_WRITE rc = sqlite3JournalOpen (
rc = sqlite3JournalOpen( pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
); );
#else
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
#endif
} }
} }
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
@@ -6019,6 +6055,7 @@ int sqlite3PagerWrite(PgHdr *pPg){
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
return SQLITE_OK; return SQLITE_OK;
}else if( pPager->sectorSize > (u32)pPager->pageSize ){ }else if( pPager->sectorSize > (u32)pPager->pageSize ){
assert( pPager->tempFile==0 );
return pagerWriteLargeSector(pPg); return pagerWriteLargeSector(pPg);
}else{ }else{
return pager_write(pPg); return pager_write(pPg);
@@ -6325,17 +6362,21 @@ int sqlite3PagerCommitPhaseOne(
/* If a prior error occurred, report that error again. */ /* If a prior error occurred, report that error again. */
if( NEVER(pPager->errCode) ) return pPager->errCode; if( NEVER(pPager->errCode) ) return pPager->errCode;
/* Provide the ability to easily simulate an I/O error during testing */
if( (rc = sqlite3FaultSim(400))!=SQLITE_OK ) return rc;
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize)); pPager->zFilename, zMaster, pPager->dbSize));
/* If no database changes have been made, return early. */ /* If no database changes have been made, return early. */
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK; if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
if( MEMDB ){ assert( MEMDB==0 || pPager->tempFile );
assert( isOpen(pPager->fd) || pPager->tempFile );
if( 0==pagerFlushOnCommit(pPager) ){
/* If this is an in-memory db, or no pages have been written to, or this /* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is mostly a no-op. However, any ** function has already been called, it is mostly a no-op. However, any
** backup in progress needs to be restarted. ** backup in progress needs to be restarted. */
*/
sqlite3BackupRestart(pPager->pBackup); sqlite3BackupRestart(pPager->pBackup);
}else{ }else{
if( pagerUseWal(pPager) ){ if( pagerUseWal(pPager) ){
@@ -6674,10 +6715,10 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
} }
/* /*
** Return true if this is an in-memory pager. ** Return true if this is an in-memory or temp-file backed pager.
*/ */
int sqlite3PagerIsMemdb(Pager *pPager){ int sqlite3PagerIsMemdb(Pager *pPager){
return MEMDB; return pPager->tempFile;
} }
/* /*
@@ -6957,7 +6998,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
/* In order to be able to rollback, an in-memory database must journal /* In order to be able to rollback, an in-memory database must journal
** the page we are moving from. ** the page we are moving from.
*/ */
if( MEMDB ){ if( pPager->tempFile ){
rc = sqlite3PagerWrite(pPg); rc = sqlite3PagerWrite(pPg);
if( rc ) return rc; if( rc ) return rc;
} }
@@ -7014,7 +7055,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
assert( !pPgOld || pPgOld->nRef==1 ); assert( !pPgOld || pPgOld->nRef==1 );
if( pPgOld ){ if( pPgOld ){
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
if( MEMDB ){ if( pPager->tempFile ){
/* Do not discard pages from an in-memory database since we might /* Do not discard pages from an in-memory database since we might
** need to rollback later. Just move the page out of the way. */ ** need to rollback later. Just move the page out of the way. */
sqlite3PcacheMove(pPgOld, pPager->dbSize+1); sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
@@ -7031,7 +7072,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
** to exist, in case the transaction needs to roll back. Use pPgOld ** to exist, in case the transaction needs to roll back. Use pPgOld
** as the original page since it has already been allocated. ** as the original page since it has already been allocated.
*/ */
if( MEMDB ){ if( pPager->tempFile ){
assert( pPgOld ); assert( pPgOld );
sqlite3PcacheMove(pPgOld, origPgno); sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnrefNotNull(pPgOld); sqlite3PagerUnrefNotNull(pPgOld);
@@ -7284,7 +7325,8 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
** Unless this is an in-memory or temporary database, clear the pager cache. ** Unless this is an in-memory or temporary database, clear the pager cache.
*/ */
void sqlite3PagerClearCache(Pager *pPager){ void sqlite3PagerClearCache(Pager *pPager){
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager); assert( MEMDB==0 || pPager->tempFile );
if( pPager->tempFile==0 ) pager_reset(pPager);
} }
#endif #endif
@@ -7463,6 +7505,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0; pPager->pWal = 0;
pagerFixMaplimit(pPager); pagerFixMaplimit(pPager);
if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
} }
} }
return rc; return rc;

View File

@@ -254,7 +254,7 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
/* /*
** If the sqlite3PcacheFetch() routine is unable to allocate a new ** If the sqlite3PcacheFetch() routine is unable to allocate a new
** page because new clean pages are available for reuse and the cache ** page because no clean pages are available for reuse and the cache
** size limit has been reached, then this routine can be invoked to ** size limit has been reached, then this routine can be invoked to
** try harder to allocate a page. This routine might invoke the stress ** try harder to allocate a page. This routine might invoke the stress
** callback to spill dirty pages to the journal. It will then try to ** callback to spill dirty pages to the journal. It will then try to
@@ -439,6 +439,17 @@ void sqlite3PcacheCleanAll(PCache *pCache){
} }
} }
/*
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
*/
void sqlite3PcacheClearWritable(PCache *pCache){
PgHdr *p;
for(p=pCache->pDirty; p; p=p->pDirtyNext){
p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
}
pCache->pSynced = pCache->pDirtyTail;
}
/* /*
** Clear the PGHDR_NEED_SYNC flag from all dirty pages. ** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
*/ */
@@ -484,7 +495,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
** it must be that pgno==0. ** it must be that pgno==0.
*/ */
assert( p->pgno>0 ); assert( p->pgno>0 );
if( ALWAYS(p->pgno>pgno) ){ if( p->pgno>pgno ){
assert( p->flags&PGHDR_DIRTY ); assert( p->flags&PGHDR_DIRTY );
sqlite3PcacheMakeClean(p); sqlite3PcacheMakeClean(p);
} }
@@ -675,6 +686,17 @@ void sqlite3PcacheShrink(PCache *pCache){
*/ */
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
/*
** Return the number of dirty pages currently in the cache, as a percentage
** of the configured cache size.
*/
int sqlite3PCachePercentDirty(PCache *pCache){
PgHdr *pDirty;
int nDirty = 0;
int nCache = numberOfCachePages(pCache);
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
}
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/* /*

View File

@@ -99,6 +99,7 @@ void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
void sqlite3PcacheClearWritable(PCache*);
/* Change a page number. Used by incr-vacuum. */ /* Change a page number. Used by incr-vacuum. */
void sqlite3PcacheMove(PgHdr*, Pgno); void sqlite3PcacheMove(PgHdr*, Pgno);
@@ -173,4 +174,7 @@ void sqlite3PCacheSetDefault(void);
int sqlite3HeaderSizePcache(void); int sqlite3HeaderSizePcache(void);
int sqlite3HeaderSizePcache1(void); int sqlite3HeaderSizePcache1(void);
/* Number of dirty pages as a percentage of the configured cache size */
int sqlite3PCachePercentDirty(PCache*);
#endif /* _PCACHE_H_ */ #endif /* _PCACHE_H_ */

View File

@@ -690,8 +690,8 @@ static int pcache1Init(void *NotUsed){
#if SQLITE_THREADSAFE #if SQLITE_THREADSAFE
if( sqlite3GlobalConfig.bCoreMutex ){ if( sqlite3GlobalConfig.bCoreMutex ){
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
} }
#endif #endif
if( pcache1.separateCache if( pcache1.separateCache

View File

@@ -57,8 +57,9 @@
** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST ** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
** primitives are constant time. The cost of DESTROY is O(N). ** primitives are constant time. The cost of DESTROY is O(N).
** **
** There is an added cost of O(N) when switching between TEST and ** TEST and SMALLEST may not be used by the same RowSet. This used to
** SMALLEST primitives. ** be possible, but the feature was not used, so it was removed in order
** to simplify the code.
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -179,7 +180,9 @@ void sqlite3RowSetClear(RowSet *p){
*/ */
static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
assert( p!=0 ); assert( p!=0 );
if( p->nFresh==0 ){ if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* We could allocate a fresh RowSetEntry each time one is needed, but it
** is more efficient to pull a preallocated entry from the pool */
struct RowSetChunk *pNew; struct RowSetChunk *pNew;
pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
if( pNew==0 ){ if( pNew==0 ){
@@ -213,7 +216,9 @@ void sqlite3RowSetInsert(RowSet *p, i64 rowid){
pEntry->pRight = 0; pEntry->pRight = 0;
pLast = p->pLast; pLast = p->pLast;
if( pLast ){ if( pLast ){
if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/
/* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
** where possible */
p->rsFlags &= ~ROWSET_SORTED; p->rsFlags &= ~ROWSET_SORTED;
} }
pLast->pRight = pEntry; pLast->pRight = pEntry;
@@ -335,23 +340,29 @@ static struct RowSetEntry *rowSetNDeepTree(
){ ){
struct RowSetEntry *p; /* Root of the new tree */ struct RowSetEntry *p; /* Root of the new tree */
struct RowSetEntry *pLeft; /* Left subtree */ struct RowSetEntry *pLeft; /* Left subtree */
if( *ppList==0 ){ if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
/* Prevent unnecessary deep recursion when we run out of entries */
return 0; return 0;
} }
if( iDepth==1 ){ if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
/* This branch causes a *balanced* tree to be generated. A valid tree
** is still generated without this branch, but the tree is wildly
** unbalanced and inefficient. */
pLeft = rowSetNDeepTree(ppList, iDepth-1);
p = *ppList;
if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* It is safe to always return here, but the resulting tree
** would be unbalanced */
return pLeft;
}
p->pLeft = pLeft;
*ppList = p->pRight;
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
}else{
p = *ppList; p = *ppList;
*ppList = p->pRight; *ppList = p->pRight;
p->pLeft = p->pRight = 0; p->pLeft = p->pRight = 0;
return p;
} }
pLeft = rowSetNDeepTree(ppList, iDepth-1);
p = *ppList;
if( p==0 ){
return pLeft;
}
p->pLeft = pLeft;
*ppList = p->pRight;
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
return p; return p;
} }
@@ -378,40 +389,6 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
return p; return p;
} }
/*
** Take all the entries on p->pEntry and on the trees in p->pForest and
** sort them all together into one big ordered list on p->pEntry.
**
** This routine should only be called once in the life of a RowSet.
*/
static void rowSetToList(RowSet *p){
/* This routine is called only once */
assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
if( (p->rsFlags & ROWSET_SORTED)==0 ){
p->pEntry = rowSetEntrySort(p->pEntry);
}
/* While this module could theoretically support it, sqlite3RowSetNext()
** is never called after sqlite3RowSetText() for the same RowSet. So
** there is never a forest to deal with. Should this change, simply
** remove the assert() and the #if 0. */
assert( p->pForest==0 );
#if 0
while( p->pForest ){
struct RowSetEntry *pTree = p->pForest->pLeft;
if( pTree ){
struct RowSetEntry *pHead, *pTail;
rowSetTreeToList(pTree, &pHead, &pTail);
p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
}
p->pForest = p->pForest->pRight;
}
#endif
p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
}
/* /*
** Extract the smallest element from the RowSet. ** Extract the smallest element from the RowSet.
** Write the element into *pRowid. Return 1 on success. Return ** Write the element into *pRowid. Return 1 on success. Return
@@ -419,18 +396,30 @@ static void rowSetToList(RowSet *p){
** **
** After this routine has been called, the sqlite3RowSetInsert() ** After this routine has been called, the sqlite3RowSetInsert()
** routine may not be called again. ** routine may not be called again.
**
** This routine may not be called after sqlite3RowSetTest() has
** been used. Older versions of RowSet allowed that, but as the
** capability was not used by the code generator, it was removed
** for code economy.
*/ */
int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
assert( p!=0 ); assert( p!=0 );
assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */
/* Merge the forest into a single sorted list on first call */ /* Merge the forest into a single sorted list on first call */
if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/
if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
p->pEntry = rowSetEntrySort(p->pEntry);
}
p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT;
}
/* Return the next entry on the list */ /* Return the next entry on the list */
if( p->pEntry ){ if( p->pEntry ){
*pRowid = p->pEntry->v; *pRowid = p->pEntry->v;
p->pEntry = p->pEntry->pRight; p->pEntry = p->pEntry->pRight;
if( p->pEntry==0 ){ if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/
/* Free memory immediately, rather than waiting on sqlite3_finalize() */
sqlite3RowSetClear(p); sqlite3RowSetClear(p);
} }
return 1; return 1;
@@ -453,13 +442,15 @@ int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
/* This routine is never called after sqlite3RowSetNext() */ /* This routine is never called after sqlite3RowSetNext() */
assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
/* Sort entries into the forest on the first test of a new batch /* Sort entries into the forest on the first test of a new batch.
** To save unnecessary work, only do this when the batch number changes.
*/ */
if( iBatch!=pRowSet->iBatch ){ if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/
p = pRowSet->pEntry; p = pRowSet->pEntry;
if( p ){ if( p ){
struct RowSetEntry **ppPrevTree = &pRowSet->pForest; struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* Only sort the current set of entiries if they need it */
p = rowSetEntrySort(p); p = rowSetEntrySort(p);
} }
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){

View File

@@ -3785,14 +3785,18 @@ static int pushDownWhereTerms(
){ ){
Expr *pNew; Expr *pNew;
int nChng = 0; int nChng = 0;
Select *pX; /* For looping over compound SELECTs in pSubq */
if( pWhere==0 ) return 0; if( pWhere==0 ) return 0;
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ for(pX=pSubq; pX; pX=pX->pPrior){
testcase( pSubq->selFlags & SF_Aggregate ); if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
testcase( pSubq->selFlags & SF_Recursive ); testcase( pX->selFlags & SF_Aggregate );
return 0; /* restrictions (1) and (2) */ testcase( pX->selFlags & SF_Recursive );
testcase( pX!=pSubq );
return 0; /* restrictions (1) and (2) */
}
} }
if( pSubq->pLimit!=0 ){ if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */ return 0; /* restriction (3) */
} }
while( pWhere->op==TK_AND ){ while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);

View File

@@ -1932,12 +1932,30 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd> ** which case the new setting is not reported back. </dd>
** **
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
** There should be two additional arguments.
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argment to
** this interface is 0, then both the C-API and the SQL function are disabled.
** If the first argument is -1, then no changes are made to state of either the
** C-API or the SQL function.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
** is disabled or enabled following this call. The second parameter may
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
** </dl> ** </dl>
*/ */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
/* /*
@@ -5474,9 +5492,18 @@ int sqlite3_table_column_metadata(
** should free this memory by calling [sqlite3_free()]. ** should free this memory by calling [sqlite3_free()].
** **
** ^Extension loading must be enabled using ** ^Extension loading must be enabled using
** [sqlite3_enable_load_extension()] prior to calling this API, ** [sqlite3_enable_load_extension()] or
** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
** prior to calling this API,
** otherwise an error will be returned. ** otherwise an error will be returned.
** **
** <b>Security warning:</b> It is recommended that the
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
** interface. The use of the [sqlite3_enable_load_extension()] interface
** should be avoided. This will keep the SQL function [load_extension()]
** disabled and prevent SQL injections from giving attackers
** access to extension loading capabilities.
**
** See also the [load_extension() SQL function]. ** See also the [load_extension() SQL function].
*/ */
int sqlite3_load_extension( int sqlite3_load_extension(
@@ -5499,6 +5526,17 @@ int sqlite3_load_extension(
** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn ** to turn extension loading on and call it with onoff==0 to turn
** it back off again. ** it back off again.
**
** ^This interface enables or disables both the C-API
** [sqlite3_load_extension()] and the SQL function [load_extension()].
** Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
** to enable or disable only the C-API.
**
** <b>Security warning:</b> It is recommended that extension loading
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
*/ */
int sqlite3_enable_load_extension(sqlite3 *db, int onoff); int sqlite3_enable_load_extension(sqlite3 *db, int onoff);

View File

@@ -15,6 +15,33 @@
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
/* Special Comments:
**
** Some comments have special meaning to the tools that measure test
** coverage:
**
** NO_TEST - The branches on this line are not
** measured by branch coverage. This is
** used on lines of code that actually
** implement parts of coverage testing.
**
** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false
** and the correct answer is still obtained,
** though perhaps more slowly.
**
** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true
** and the correct answer is still obtained,
** though perhaps more slowly.
**
** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread
** that would be harmless and undetectable
** if it did occur.
**
** In all cases, the special comment must be enclosed in the usual
** slash-asterisk...asterisk-slash comment marks, with no spaces between the
** asterisks and the comment text.
*/
/* /*
** Make sure that rand_s() is available on Windows systems with MSVC 2005 ** Make sure that rand_s() is available on Windows systems with MSVC 2005
** or higher. ** or higher.
@@ -1383,13 +1410,14 @@ struct sqlite3 {
#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ #define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ #define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */ #define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */ #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
#define SQLITE_Fts3Tokenizer 0x20000000 /* Enable fts3_tokenizer(2) */ #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
/* /*

View File

@@ -1271,7 +1271,7 @@ static int sqlite3_mprintf_int64(
return TCL_ERROR; return TCL_ERROR;
} }
for(i=2; i<5; i++){ for(i=2; i<5; i++){
if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){ if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
return TCL_ERROR; return TCL_ERROR;
} }
@@ -5213,7 +5213,9 @@ static int vfs_unregister_all(
/* /*
** tclcmd: vfs_reregister_all ** tclcmd: vfs_reregister_all
** **
** Restore all VFSes that were removed using vfs_unregister_all ** Restore all VFSes that were removed using vfs_unregister_all. Taking
** care to put the linked list back together in the same order as it was
** in before vfs_unregister_all was invoked.
*/ */
static int vfs_reregister_all( static int vfs_reregister_all(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
@@ -5222,8 +5224,8 @@ static int vfs_reregister_all(
Tcl_Obj *CONST objv[] /* Command arguments */ Tcl_Obj *CONST objv[] /* Command arguments */
){ ){
int i; int i;
for(i=0; i<nVfs; i++){ for(i=nVfs-1; i>=0; i--){
sqlite3_vfs_register(apVfs[i], i==0); sqlite3_vfs_register(apVfs[i], 1);
} }
return TCL_OK; return TCL_OK;
} }
@@ -6988,6 +6990,7 @@ static int test_sqlite3_db_config(
{ "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY }, { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
}; };
int i; int i;
int v; int v;

View File

@@ -547,7 +547,7 @@ static int btree_from_db(
/* /*
** Usage: btree_ismemdb ID ** Usage: btree_ismemdb ID
** **
** Return true if the B-Tree is in-memory. ** Return true if the B-Tree is currently stored entirely in memory.
*/ */
static int btree_ismemdb( static int btree_ismemdb(
void *NotUsed, void *NotUsed,
@@ -557,6 +557,7 @@ static int btree_ismemdb(
){ ){
Btree *pBt; Btree *pBt;
int res; int res;
sqlite3_file *pFile;
if( argc!=2 ){ if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -566,7 +567,8 @@ static int btree_ismemdb(
pBt = sqlite3TestTextToPtr(argv[1]); pBt = sqlite3TestTextToPtr(argv[1]);
sqlite3_mutex_enter(pBt->db->mutex); sqlite3_mutex_enter(pBt->db->mutex);
sqlite3BtreeEnter(pBt); sqlite3BtreeEnter(pBt);
res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt)); pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
res = (pFile->pMethods==0);
sqlite3BtreeLeave(pBt); sqlite3BtreeLeave(pBt);
sqlite3_mutex_leave(pBt->db->mutex); sqlite3_mutex_leave(pBt->db->mutex);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res)); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));

View File

@@ -701,6 +701,10 @@ static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
return pVfs->xCurrentTime(pVfs, pTimeOut); return pVfs->xCurrentTime(pVfs, pTimeOut);
} }
static int cfGetLastError(sqlite3_vfs *pCfVfs, int n, char *z){
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
return pVfs->xGetLastError(pVfs, n, z);
}
static int processDevSymArgs( static int processDevSymArgs(
Tcl_Interp *interp, Tcl_Interp *interp,
@@ -827,7 +831,7 @@ static int crashEnableCmd(
cfRandomness, /* xRandomness */ cfRandomness, /* xRandomness */
cfSleep, /* xSleep */ cfSleep, /* xSleep */
cfCurrentTime, /* xCurrentTime */ cfCurrentTime, /* xCurrentTime */
0, /* xGetlastError */ cfGetLastError, /* xGetLastError */
0, /* xCurrentTimeInt64 */ 0, /* xCurrentTimeInt64 */
}; };
@@ -940,6 +944,27 @@ static int devSymObjCmd(
devsym_register(iDc, iSectorSize); devsym_register(iDc, iSectorSize);
return TCL_OK; return TCL_OK;
}
/*
** tclcmd: unregister_devsim
*/
static int dsUnregisterObjCmd(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
void devsym_unregister(void);
if( objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
devsym_unregister();
return TCL_OK;
} }
/* /*
@@ -1010,6 +1035,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
#endif #endif

View File

@@ -396,4 +396,11 @@ void devsym_register(int iDeviceChar, int iSectorSize){
} }
} }
void devsym_unregister(){
sqlite3_vfs_unregister(&devsym_vfs);
g.pVfs = 0;
g.iDeviceChar = 0;
g.iSectorSize = 0;
}
#endif #endif

View File

@@ -160,6 +160,7 @@ static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int jtSleep(sqlite3_vfs*, int microseconds); static int jtSleep(sqlite3_vfs*, int microseconds);
static int jtCurrentTime(sqlite3_vfs*, double*); static int jtCurrentTime(sqlite3_vfs*, double*);
static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int jtGetLastError(sqlite3_vfs*, int, char*);
static sqlite3_vfs jt_vfs = { static sqlite3_vfs jt_vfs = {
2, /* iVersion */ 2, /* iVersion */
@@ -179,7 +180,7 @@ static sqlite3_vfs jt_vfs = {
jtRandomness, /* xRandomness */ jtRandomness, /* xRandomness */
jtSleep, /* xSleep */ jtSleep, /* xSleep */
jtCurrentTime, /* xCurrentTime */ jtCurrentTime, /* xCurrentTime */
0, /* xGetLastError */ jtGetLastError, /* xGetLastError */
jtCurrentTimeInt64 /* xCurrentTimeInt64 */ jtCurrentTimeInt64 /* xCurrentTimeInt64 */
}; };
@@ -285,9 +286,10 @@ static int jtRead(
** b) The file-name specified when the file was opened matches ** b) The file-name specified when the file was opened matches
** all but the final 8 characters of the journal file name. ** all but the final 8 characters of the journal file name.
** **
** c) There is currently a reserved lock on the file. ** c) There is currently a reserved lock on the file. This
** condition is waived if the noLock argument is non-zero.
**/ **/
static jt_file *locateDatabaseHandle(const char *zJournal){ static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){
jt_file *pMain = 0; jt_file *pMain = 0;
enterJtMutex(); enterJtMutex();
for(pMain=g.pList; pMain; pMain=pMain->pNext){ for(pMain=g.pList; pMain; pMain=pMain->pNext){
@@ -295,7 +297,7 @@ static jt_file *locateDatabaseHandle(const char *zJournal){
if( (pMain->flags&SQLITE_OPEN_MAIN_DB) if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
&& ((int)strlen(pMain->zName)==nName) && ((int)strlen(pMain->zName)==nName)
&& 0==memcmp(pMain->zName, zJournal, nName) && 0==memcmp(pMain->zName, zJournal, nName)
&& (pMain->eLock>=SQLITE_LOCK_RESERVED) && ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock)
){ ){
break; break;
} }
@@ -517,7 +519,7 @@ static int jtWrite(
jt_file *p = (jt_file *)pFile; jt_file *p = (jt_file *)pFile;
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
if( iOfst==0 ){ if( iOfst==0 ){
jt_file *pMain = locateDatabaseHandle(p->zName); jt_file *pMain = locateDatabaseHandle(p->zName, 0);
assert( pMain ); assert( pMain );
if( iAmt==28 ){ if( iAmt==28 ){
@@ -562,7 +564,7 @@ static int jtWrite(
rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){ if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
jt_file *pMain = locateDatabaseHandle(p->zName); jt_file *pMain = locateDatabaseHandle(p->zName, 0);
int rc2 = readJournalFile(p, pMain); int rc2 = readJournalFile(p, pMain);
if( rc==SQLITE_OK ) rc = rc2; if( rc==SQLITE_OK ) rc = rc2;
} }
@@ -576,7 +578,7 @@ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){
jt_file *p = (jt_file *)pFile; jt_file *p = (jt_file *)pFile;
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){ if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){
/* Truncating a journal file. This is the end of a transaction. */ /* Truncating a journal file. This is the end of a transaction. */
jt_file *pMain = locateDatabaseHandle(p->zName); jt_file *pMain = locateDatabaseHandle(p->zName, 0);
closeTransaction(pMain); closeTransaction(pMain);
} }
if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
@@ -604,11 +606,10 @@ static int jtSync(sqlite3_file *pFile, int flags){
** jt_file.pWritable bitvec of the main database file associated with ** jt_file.pWritable bitvec of the main database file associated with
** this journal file. ** this journal file.
*/ */
pMain = locateDatabaseHandle(p->zName); pMain = locateDatabaseHandle(p->zName, 0);
assert(pMain);
/* Set the bitvec values */ /* Set the bitvec values */
if( pMain->pWritable ){ if( pMain && pMain->pWritable ){
pMain->nSync++; pMain->nSync++;
rc = readJournalFile(p, pMain); rc = readJournalFile(p, pMain);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
@@ -730,7 +731,7 @@ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int nPath = (int)strlen(zPath); int nPath = (int)strlen(zPath);
if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){
/* Deleting a journal file. The end of a transaction. */ /* Deleting a journal file. The end of a transaction. */
jt_file *pMain = locateDatabaseHandle(zPath); jt_file *pMain = locateDatabaseHandle(zPath, 0);
if( pMain ){ if( pMain ){
closeTransaction(pMain); closeTransaction(pMain);
} }
@@ -825,6 +826,10 @@ static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut); return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut);
} }
static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){
return g.pVfs->xGetLastError(g.pVfs, n, z);
}
/************************************************************************** /**************************************************************************
** Start of public API. ** Start of public API.
*/ */

View File

@@ -722,14 +722,20 @@ static int test_syscall(
}; };
int iCmd; int iCmd;
int rc; int rc;
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
if( objc<2 ){ if( objc<2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
return TCL_ERROR; return TCL_ERROR;
} }
rc = Tcl_GetIndexFromObjStruct(interp, if( pVfs->iVersion<3 || pVfs->xSetSystemCall==0 ){
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd Tcl_AppendResult(interp, "VFS does not support xSetSystemCall", 0);
); rc = TCL_ERROR;
}else{
rc = Tcl_GetIndexFromObjStruct(interp,
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
);
}
if( rc!=TCL_OK ) return rc; if( rc!=TCL_OK ) return rc;
return aCmd[iCmd].xCmd(clientData, interp, objc, objv); return aCmd[iCmd].xCmd(clientData, interp, objc, objv);
} }

View File

@@ -355,7 +355,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
int eValid = 1; /* True exponent is either not used or is well-formed */ int eValid = 1; /* True exponent is either not used or is well-formed */
double result; double result;
int nDigits = 0; int nDigits = 0;
int nonNum = 0; int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */ *pResult = 0.0; /* Default return value, in case of an error */
@@ -368,7 +368,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && z[i]==0; i+=2){} for(i=3-enc; i<length && z[i]==0; i+=2){}
nonNum = i<length; nonNum = i<length;
zEnd = z+i+enc-3; zEnd = &z[i^1];
z += (enc&1); z += (enc&1);
} }
@@ -384,9 +384,6 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
z+=incr; z+=incr;
} }
/* skip leading zeroes */
while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
/* copy max significant digits to significand */ /* copy max significant digits to significand */
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0'); s = s*10 + (*z - '0');
@@ -403,12 +400,13 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
z+=incr; z+=incr;
/* copy digits from after decimal to significand /* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */ ** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ while( z<zEnd && sqlite3Isdigit(*z) ){
s = s*10 + (*z - '0'); if( s<((LARGEST_INT64-9)/10) ){
z+=incr, nDigits++, d--; s = s*10 + (*z - '0');
d--;
}
z+=incr, nDigits++;
} }
/* skip non-significant digits */
while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
} }
if( z>=zEnd ) goto do_atof_calc; if( z>=zEnd ) goto do_atof_calc;
@@ -416,7 +414,12 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
if( *z=='e' || *z=='E' ){ if( *z=='e' || *z=='E' ){
z+=incr; z+=incr;
eValid = 0; eValid = 0;
if( z>=zEnd ) goto do_atof_calc;
/* This branch is needed to avoid a (harmless) buffer overread. The
** special comment alerts the mutation tester that the correct answer
** is obtained even if the branch is omitted */
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
/* get sign of exponent */ /* get sign of exponent */
if( *z=='-' ){ if( *z=='-' ){
esign = -1; esign = -1;
@@ -433,9 +436,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
} }
/* skip trailing spaces */ /* skip trailing spaces */
if( nDigits && eValid ){ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
}
do_atof_calc: do_atof_calc:
/* adjust exponent by d, and update sign */ /* adjust exponent by d, and update sign */
@@ -447,41 +448,51 @@ do_atof_calc:
esign = 1; esign = 1;
} }
/* if 0 significand */ if( s==0 ) {
if( !s ) { /* In the IEEE 754 standard, zero is signed. */
/* In the IEEE 754 standard, zero is signed. result = sign<0 ? -(double)0 : (double)0;
** Add the sign if we've seen at least one digit */
result = (sign<0 && nDigits) ? -(double)0 : (double)0;
} else { } else {
/* attempt to reduce exponent */ /* Attempt to reduce exponent.
if( esign>0 ){ **
while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10; ** Branches that are not required for the correct answer but which only
}else{ ** help to obtain the correct answer faster are marked with special
while( !(s%10) && e>0 ) e--,s/=10; ** comments, as a hint to the mutation tester.
*/
while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
if( esign>0 ){
if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
s *= 10;
}else{
if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
s /= 10;
}
e--;
} }
/* adjust the sign of significand */ /* adjust the sign of significand */
s = sign<0 ? -s : s; s = sign<0 ? -s : s;
/* if exponent, scale significand as appropriate if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
** and store in result. */ result = (double)s;
if( e ){ }else{
LONGDOUBLE_TYPE scale = 1.0; LONGDOUBLE_TYPE scale = 1.0;
/* attempt to handle extremely small/large numbers better */ /* attempt to handle extremely small/large numbers better */
if( e>307 && e<342 ){ if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
while( e%308 ) { scale *= 1.0e+1; e -= 1; } if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
if( esign<0 ){ while( e%308 ) { scale *= 1.0e+1; e -= 1; }
result = s / scale; if( esign<0 ){
result /= 1.0e+308; result = s / scale;
}else{ result /= 1.0e+308;
result = s * scale; }else{
result *= 1.0e+308; result = s * scale;
} result *= 1.0e+308;
}else if( e>=342 ){ }
if( esign<0 ){ }else{ assert( e>=342 );
result = 0.0*s; if( esign<0 ){
}else{ result = 0.0*s;
result = 1e308*1e308*s; /* Infinity */ }else{
result = 1e308*1e308*s; /* Infinity */
}
} }
}else{ }else{
/* 1.0e+22 is the largest power of 10 than can be /* 1.0e+22 is the largest power of 10 than can be
@@ -494,8 +505,6 @@ do_atof_calc:
result = s * scale; result = s * scale;
} }
} }
} else {
result = (double)s;
} }
} }
@@ -503,7 +512,7 @@ do_atof_calc:
*pResult = result; *pResult = result;
/* return true if number and no extra non-whitespace chracters after */ /* return true if number and no extra non-whitespace chracters after */
return z>=zEnd && nDigits>0 && eValid && nonNum==0; return z==zEnd && nDigits>0 && eValid && nonNum==0;
#else #else
return !sqlite3Atoi64(z, pResult, length, enc); return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */ #endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -565,7 +574,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
int neg = 0; /* assume positive */ int neg = 0; /* assume positive */
int i; int i;
int c = 0; int c = 0;
int nonNum = 0; int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
const char *zStart; const char *zStart;
const char *zEnd = zNum + length; const char *zEnd = zNum + length;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
@@ -576,7 +585,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && zNum[i]==0; i+=2){} for(i=3-enc; i<length && zNum[i]==0; i+=2){}
nonNum = i<length; nonNum = i<length;
zEnd = zNum+i+enc-3; zEnd = &zNum[i^1];
zNum += (enc&1); zNum += (enc&1);
} }
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr; while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
@@ -603,8 +612,11 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
testcase( i==18 ); testcase( i==18 );
testcase( i==19 ); testcase( i==19 );
testcase( i==20 ); testcase( i==20 );
if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) if( &zNum[i]<zEnd /* Extra bytes at the end */
|| i>19*incr || nonNum ){ || (i==0 && zStart==zNum) /* No digits */
|| i>19*incr /* Too many digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
/* zNum is empty or contains non-numeric text or is longer /* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */ ** than 19 digits (thus guaranteeing that it is too large) */
return 1; return 1;
@@ -646,7 +658,6 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER #ifndef SQLITE_OMIT_HEX_INTEGER
if( z[0]=='0' if( z[0]=='0'
&& (z[1]=='x' || z[1]=='X') && (z[1]=='x' || z[1]=='X')
&& sqlite3Isxdigit(z[2])
){ ){
u64 u = 0; u64 u = 0;
int i, k; int i, k;
@@ -1408,7 +1419,7 @@ LogEst sqlite3LogEst(u64 x){
if( x<2 ) return 0; if( x<2 ) return 0;
while( x<8 ){ y -= 10; x <<= 1; } while( x<8 ){ y -= 10; x <<= 1; }
}else{ }else{
while( x>255 ){ y += 40; x >>= 4; } while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; } while( x>15 ){ y += 10; x >>= 1; }
} }
return a[x&7] + y - 10; return a[x&7] + y - 10;

View File

@@ -215,7 +215,7 @@ static VdbeCursor *allocateCursor(
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor ); assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0; p->apCsr[iCur] = 0;
} }
@@ -292,7 +292,7 @@ static void applyAffinity(
if( affinity>=SQLITE_AFF_NUMERIC ){ if( affinity>=SQLITE_AFF_NUMERIC ){
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|| affinity==SQLITE_AFF_NUMERIC ); || affinity==SQLITE_AFF_NUMERIC );
if( (pRec->flags & MEM_Int)==0 ){ if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
if( (pRec->flags & MEM_Real)==0 ){ if( (pRec->flags & MEM_Real)==0 ){
if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
}else{ }else{
@@ -302,10 +302,13 @@ static void applyAffinity(
}else if( affinity==SQLITE_AFF_TEXT ){ }else if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real /* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string ** representation (blob and NULL do not get converted) but no string
** representation. ** representation. It would be harmless to repeat the conversion if
*/ ** there is already a string rep, but it is pointless to waste those
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ ** CPU cycles. */
sqlite3VdbeMemStringify(pRec, enc, 1); if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
if( (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
}
} }
pRec->flags &= ~(MEM_Real|MEM_Int); pRec->flags &= ~(MEM_Real|MEM_Int);
} }
@@ -542,7 +545,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
pOut = &p->aMem[pOp->p2]; pOut = &p->aMem[pOp->p2];
memAboutToChange(p, pOut); memAboutToChange(p, pOut);
if( VdbeMemDynamic(pOut) ){ if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
return out2PrereleaseWithClear(pOut); return out2PrereleaseWithClear(pOut);
}else{ }else{
pOut->flags = MEM_Int; pOut->flags = MEM_Int;

View File

@@ -164,7 +164,7 @@ foreach zOpenScript [list {
set file_dest temp set file_dest temp
}] { }] {
foreach rows_dest {0 3 10} { foreach rows_dest {0 3 10} {
foreach pgsz_dest {512 1024 2048} { foreach pgsz_dest {512 1024 2048 4096} {
foreach nPagePerStep {1 200} { foreach nPagePerStep {1 200} {
# Open the databases. # Open the databases.
@@ -176,17 +176,16 @@ foreach nPagePerStep {1 200} {
# in-memory destination is only possible if the initial destination # in-memory destination is only possible if the initial destination
# page size is the same as the source page size (in this case 1024 bytes). # page size is the same as the source page size (in this case 1024 bytes).
# #
set isMemDest [expr { set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
$zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
}]
if { $isMemDest==0 || $pgsz_dest == 1024 } { if 0 {
if 0 { puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile" puts -nonewline " (as $db_dest.$file_dest)"
puts -nonewline " (as $db_dest.$file_dest)" puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest" puts ""
puts "" }
}
if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
# Set up the content of the source database. # Set up the content of the source database.
execsql { execsql {

View File

@@ -15,7 +15,7 @@
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set testprefix cacheflush set testprefix cffault
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl
# Run the supplied SQL on a copy of the database currently stored on # Run the supplied SQL on a copy of the database currently stored on

View File

@@ -86,7 +86,7 @@ do_test 2.3 { db_write db 1 } {0 4 0}
do_test 2.4 { db_write db 0 } {0 0 0} do_test 2.4 { db_write db 0 } {0 0 0}
do_test 2.5 { db_write db 1 } {0 0 0} do_test 2.5 { db_write db 1 } {0 0 0}
ifcapable wal { if {[wal_is_capable]} {
do_test 2.6 { do_test 2.6 {
execsql { PRAGMA journal_mode = WAL } execsql { PRAGMA journal_mode = WAL }
db_write db 1 db_write db 1

View File

@@ -176,7 +176,7 @@ if {![nonzero_reserved_bytes]} {
# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the # EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
# auto_vacuum support property can be changed using VACUUM. # auto_vacuum support property can be changed using VACUUM.
# #
ifcapable wal { if {[wal_is_capable]} {
do_test e_vacuum-1.3.3.1 { do_test e_vacuum-1.3.3.1 {
execsql { PRAGMA journal_mode = wal } execsql { PRAGMA journal_mode = wal }
execsql { PRAGMA page_size ; PRAGMA auto_vacuum } execsql { PRAGMA page_size ; PRAGMA auto_vacuum }

View File

@@ -19,6 +19,7 @@ source $testdir/lock_common.tcl
foreach jm {rollback wal} { foreach jm {rollback wal} {
if {![wal_is_capable] && $jm=="wal"} continue
set testprefix exists-$jm set testprefix exists-$jm

View File

@@ -704,7 +704,7 @@ do_execsql_test 7.5.2.0 {
ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx'; ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
} }
ifcapable !session { if 0 {
# At time of writing, these two are broken. They demonstrate that the # At time of writing, these two are broken. They demonstrate that the
# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE # sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
# has been used to add a column with a default value other than NULL. # has been used to add a column with a default value other than NULL.

View File

@@ -134,7 +134,7 @@ do_test incrvacuum2-3.2 {
integrity_check incrvacuum2-3.3 integrity_check incrvacuum2-3.3
ifcapable wal { if {[wal_is_capable]} {
# At one point, when a specific page was being extracted from the b-tree # At one point, when a specific page was being extracted from the b-tree
# free-list (e.g. during an incremental-vacuum), all trunk pages that # free-list (e.g. during an incremental-vacuum), all trunk pages that
# occurred before the specific page in the free-list trunk were being # occurred before the specific page in the free-list trunk were being

View File

@@ -204,7 +204,7 @@ db close
# delete the journal file when committing the transaction that switches # delete the journal file when committing the transaction that switches
# the system to WAL mode. # the system to WAL mode.
# #
ifcapable wal { if {[wal_is_capable]} {
do_test journal2-2.1 { do_test journal2-2.1 {
faultsim_delete_and_reopen faultsim_delete_and_reopen
set ::oplog [list] set ::oplog [list]

View File

@@ -111,7 +111,7 @@ do_test loadext-1.2 {
# #
do_test loadext-1.3 { do_test loadext-1.3 {
sqlite3 db2 test.db sqlite3 db2 test.db
sqlite3_enable_load_extension db2 1 sqlite3_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql { catchsql {
SELECT half(1.0); SELECT half(1.0);
} db2 } db2
@@ -256,6 +256,7 @@ do_test loadext-4.2 {
} }
} {0 {{}}} } {0 {{}}}
# disable all extension loading
do_test loadext-4.3 { do_test loadext-4.3 {
sqlite3_enable_load_extension db 0 sqlite3_enable_load_extension db 0
catchsql { catchsql {
@@ -263,6 +264,15 @@ do_test loadext-4.3 {
} }
} {1 {not authorized}} } {1 {not authorized}}
# enable C-api extension loading only. Show that the SQL function
# still does not work.
do_test loadext-4.4 {
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql {
SELECT load_extension($::testextension,'testloadext_init')
}
} {1 {not authorized}}
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl

View File

@@ -423,8 +423,9 @@ do_test lock-6.5 {
# * there exists one or more active read-only statements, and # * there exists one or more active read-only statements, and
# * a transaction that modified zero database pages is committed. # * a transaction that modified zero database pages is committed.
# #
set temp_status unlocked #set temp_status unlocked
if {$TEMP_STORE>=2} {set temp_status unknown} #if {$TEMP_STORE>=2} {set temp_status unknown}
set temp_status unknown
do_test lock-7.1 { do_test lock-7.1 {
set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL] set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
sqlite3_step $STMT sqlite3_step $STMT

View File

@@ -684,22 +684,24 @@ do_faultsim_test pagerfault-14a -prep {
# is not possible to change the page-size of an in-memory database. Even # is not possible to change the page-size of an in-memory database. Even
# using the backup API. # using the backup API.
# #
if {$TEMP_STORE<2} { # Update: It is no longer possible to change the page size of any temp
do_faultsim_test pagerfault-14b -prep { # database after it has been created.
catch { db2 close } #
faultsim_restore_and_reopen do_faultsim_test pagerfault-14b -prep {
catch { db2 close }
faultsim_restore_and_reopen
sqlite3 db2 "" sqlite3 db2 ""
db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) } db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
} -body { } -body {
sqlite3_backup B db2 main db main sqlite3_backup B db2 main db main
B step 200 B step 200
set rc [B finish] set rc [B finish]
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR} if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] } if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
set {} {} set {} {}
} -test { } -test {
faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}} faultsim_test_result {1 {attempt to write a readonly database}} \
} {1 {sqlite3_backup_init() failed}}
} }
do_faultsim_test pagerfault-14c -prep { do_faultsim_test pagerfault-14c -prep {

View File

@@ -728,7 +728,7 @@ test_suite "inmemory_journal" -description {
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
fts3snippet.test mmapfault.test fts3snippet.test mmapfault.test sessionfault.test sessionfault2.test
# Exclude test scripts that use tcl IO to access journal files or count # Exclude test scripts that use tcl IO to access journal files or count
# the number of fsync() calls. # the number of fsync() calls.
@@ -942,7 +942,9 @@ test_suite "journaltest" -description {
unregister_jt_vfs unregister_jt_vfs
} -files [test_set $::allquicktests -exclude { } -files [test_set $::allquicktests -exclude {
wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test
async4.test bigfile.test backcompat.test async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
pager2.test *fault* rowal* snapshot* superlock* symlink.test
}] }]
if {[info commands register_demovfs] != ""} { if {[info commands register_demovfs] != ""} {
@@ -1050,15 +1052,13 @@ proc run_tests {name args} {
set ::G(isquick) 1 set ::G(isquick) 1
set ::G(perm:dbconfig) $options(-dbconfig) set ::G(perm:dbconfig) $options(-dbconfig)
uplevel $options(-initialize)
foreach file [lsort $options(-files)] { foreach file [lsort $options(-files)] {
uplevel $options(-initialize)
if {[file tail $file] == $file} { set file [file join $::testdir $file] } if {[file tail $file] == $file} { set file [file join $::testdir $file] }
slave_test_file $file slave_test_file $file
uplevel $options(-shutdown)
} }
uplevel $options(-shutdown)
unset ::G(perm:name) unset ::G(perm:name)
unset ::G(perm:prefix) unset ::G(perm:prefix)
unset ::G(perm:presql) unset ::G(perm:presql)

View File

@@ -1083,7 +1083,20 @@ do_test pragma-8.2.15 {
# "memory" or "disk" as appropriate. # "memory" or "disk" as appropriate.
# #
proc check_temp_store {} { proc check_temp_store {} {
db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)} db eval {
PRAGMA temp.cache_size = 1;
CREATE TEMP TABLE IF NOT EXISTS a(b);
DELETE FROM a;
INSERT INTO a VALUES(randomblob(1000));
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
}
db eval {PRAGMA database_list} { db eval {PRAGMA database_list} {
if {$name=="temp"} { if {$name=="temp"} {
set bt [btree_from_db db 1] set bt [btree_from_db db 1]

View File

@@ -221,7 +221,7 @@ ifcapable shared_cache {
# This will not work with the in-memory journal permutation, as opening # This will not work with the in-memory journal permutation, as opening
# [db2] switches the journal mode back to "memory" # [db2] switches the journal mode back to "memory"
# #
ifcapable wal { if {[wal_is_capable]} {
if {[permutation]!="inmemory_journal"} { if {[permutation]!="inmemory_journal"} {
sqlite3 db test.db sqlite3 db test.db

View File

@@ -527,4 +527,6 @@ do_faultsim_test quota-5.6 -prep {
} }
catch { sqlite3_quota_shutdown } catch { sqlite3_quota_shutdown }
catch { db close }
forcedelete test.db
finish_test finish_test

View File

@@ -968,6 +968,42 @@ do_execsql_test select4-16.3 {
ORDER BY t3.a; ORDER BY t3.a;
} {95 96 97 98 99} } {95 96 97 98 99}
# Ticket https://www.sqlite.org/src/tktview/f7f8c97e975978d45 on 2016-04-25
#
# The where push-down optimization from 2015-06-02 is suppose to disable
# on aggregate subqueries. But if the subquery is a compound where the
# last SELECT is non-aggregate but some other SELECT is an aggregate, the
# test is incomplete and the optimization is not properly disabled.
#
# The following test cases verify that the fix works.
#
do_execsql_test select4-17.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a int, b int);
INSERT INTO t1 VALUES(1,2),(1,18),(2,19);
SELECT x, y FROM (
SELECT 98 AS x, 99 AS y
UNION
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
) AS w WHERE y>=20
ORDER BY +x;
} {1 20 98 99}
do_execsql_test select4-17.2 {
SELECT x, y FROM (
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
UNION
SELECT 98 AS x, 99 AS y
) AS w WHERE y>=20
ORDER BY +x;
} {1 20 98 99}
do_catchsql_test select4-17.3 {
SELECT x, y FROM (
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3
UNION
SELECT 98 AS x, 99 AS y
) AS w WHERE y>=20
ORDER BY +x;
} {1 {LIMIT clause should come after UNION not before}}

View File

@@ -37,7 +37,7 @@ do_execsql_test stat-0.0 {
SELECT * FROM stat; SELECT * FROM stat;
} {} } {}
ifcapable wal { if {[wal_is_capable]} {
do_execsql_test stat-0.1 { do_execsql_test stat-0.1 {
PRAGMA journal_mode = WAL; PRAGMA journal_mode = WAL;
PRAGMA journal_mode = delete; PRAGMA journal_mode = delete;

View File

@@ -81,6 +81,7 @@ do_test sync-1.3 {
set sqlite_sync_count set sqlite_sync_count
} 11 } 11
ifcapable pager_pragmas { ifcapable pager_pragmas {
if {[permutation]!="journaltest"} {
do_test sync-1.4 { do_test sync-1.4 {
set sqlite_sync_count 0 set sqlite_sync_count 0
execsql { execsql {
@@ -94,6 +95,7 @@ ifcapable pager_pragmas {
set sqlite_sync_count set sqlite_sync_count
} 0 } 0
} }
}
finish_test finish_test

134
test/tempfault.test Normal file
View File

@@ -0,0 +1,134 @@
# 2016 April 11
#
# 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.
#
#***********************************************************************
#
# This file contains tests for fault-injection when SQLite is used with
# a temp file database.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix tempfault
# sqlite3_memdebug_vfs_oom_test 0
do_faultsim_test 1 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
}
} -body {
execsql { INSERT INTO t1 VALUES(5, 6) }
} -test {
faultsim_test_result {0 {}}
set rc [catch { execsql { SELECT * FROM t1 } } msg]
if {$rc==0 && $msg != "1 2 3 4 5 6" && $msg != "1 2 3 4"} {
error "data mismatch 1: $msg"
}
if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
error "data mismatch 2: $msg"
}
faultsim_integrity_check
}
do_faultsim_test 2 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql { UPDATE t1 SET a = randomblob(99) }
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
catch { db close }
do_faultsim_test 2.1 -faults * -prep {
if {[info commands db]==""} {
sqlite3 db ""
execsql {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
}
} -body {
execsql { UPDATE t1 SET a = randomblob(99) }
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
do_faultsim_test 3 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql {
BEGIN;
UPDATE t1 SET a = randomblob(99);
SAVEPOINT abc;
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
ROLLBACK TO abc;
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
ROLLBACK TO abc;
COMMIT;
}
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
do_faultsim_test 4 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql {
BEGIN;
UPDATE t1 SET a = randomblob(99);
SAVEPOINT abc;
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
ROLLBACK TO abc;
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
ROLLBACK TO abc;
COMMIT;
}
} -test {
faultsim_test_result {0 {}}
}
sqlite3_memdebug_vfs_oom_test 1
finish_test

356
test/temptable2.test Normal file
View File

@@ -0,0 +1,356 @@
# 2016 March 3
#
# 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
set testprefix temptable2
do_execsql_test 1.1 {
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
}
do_execsql_test 1.2 {
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100000 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM X;
} {}
do_execsql_test 1.3 {
PRAGMA temp.integrity_check;
} {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.1 {
CREATE TEMP TABLE t2(a, b);
INSERT INTO t2 VALUES(1, 2);
} {}
do_execsql_test 2.2 {
BEGIN;
INSERT INTO t2 VALUES(3, 4);
SELECT * FROM t2;
} {1 2 3 4}
do_execsql_test 2.3 {
ROLLBACK;
SELECT * FROM t2;
} {1 2}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t1;
} {1000}
do_execsql_test 3.1.2 {
BEGIN;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
ROLLBACK;
}
do_execsql_test 3.1.3 {
SELECT count(*) FROM t1;
} {1000}
do_execsql_test 3.1.4 { PRAGMA temp.integrity_check } {ok}
do_execsql_test 3.2.1 {
BEGIN;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
SAVEPOINT abc;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==1;
ROLLBACK TO abc;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==2;
COMMIT;
}
do_execsql_test 3.2.2 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<10 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t1;
PRAGMA temp.page_count;
} {10 9}
do_execsql_test 4.1.2 {
BEGIN;
UPDATE t1 SET b=randomblob(100);
ROLLBACK;
}
do_execsql_test 4.1.3 {
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t2;
SELECT count(*) FROM t1;
} {500 10}
do_test 4.1.4 {
set n [db one { PRAGMA temp.page_count }]
expr ($n >280 && $n < 300)
} 1
do_execsql_test 4.1.4 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
# Test that the temp database is now much bigger than the configured
# cache size (10 pages).
do_test 5.1.2 {
set n [db one { PRAGMA temp.page_count }]
expr ($n > 270 && $n < 290)
} {1}
do_execsql_test 5.1.3 {
BEGIN;
UPDATE t1 SET a=2;
UPDATE t2 SET a=randomblob(100);
SELECT count(*) FROM t1;
ROLLBACK;
} {1}
do_execsql_test 5.1.4 {
UPDATE t2 SET a=randomblob(100);
SELECT * FROM t1;
} {1 2}
do_execsql_test 5.1.5 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
# Test this:
#
# 1. Page is DIRTY at the start of a transaction.
# 2. Page is written out as part of the transaction.
# 3. Page is then read back in.
# 4. Transaction is rolled back. Is the page now clean or dirty?
#
# This actually does work. Step 4 marks the page as clean. But it also
# writes to the database file itself. So marking it clean is correct -
# the page does match the contents of the db file.
#
reset_db
do_execsql_test 6.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(x);
INSERT INTO t1 VALUES('one');
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
}
do_execsql_test 6.2 {
UPDATE t1 SET x='two'; -- step 1
BEGIN;
UPDATE t2 SET a=randomblob(100); -- step 2
SELECT * FROM t1; -- step 3
ROLLBACK; -- step 4
SELECT count(*) FROM t2;
SELECT * FROM t1;
} {two 500 two}
#-------------------------------------------------------------------------
#
reset_db
sqlite3 db ""
do_execsql_test 7.1 {
PRAGMA auto_vacuum=INCREMENTAL;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(900));
INSERT INTO t1 VALUES(zeroblob(900));
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
BEGIN;
DELETE FROM t1 WHERE rowid%2;
PRAGMA incremental_vacuum(4);
ROLLBACK;
PRAGMA integrity_check;
} {ok}
#-------------------------------------------------------------------------
# Try changing the page size using a backup operation when pages are
# stored in main-memory only.
#
reset_db
do_execsql_test 8.1 {
PRAGMA auto_vacuum = OFF;
CREATE TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<20 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
PRAGMA page_count;
} {13}
do_test 8.2 {
sqlite3 tmp ""
execsql {
PRAGMA auto_vacuum = OFF;
PRAGMA page_size = 8192;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
PRAGMA page_count;
} tmp
} {10}
do_test 8.3 {
sqlite3_backup B tmp main db main
B step 5
B finish
} {SQLITE_READONLY}
do_test 8.4 {
execsql {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
PRAGMA page_size;
} tmp
} {100 ok 8192}
do_test 8.5 {
tmp eval { UPDATE t1 SET a=randomblob(100) }
} {}
do_test 8.6 {
sqlite3_backup B tmp main db main
B step 1000
B finish
} {SQLITE_READONLY}
tmp close
#-------------------------------------------------------------------------
# Try inserts and deletes with a large db in auto-vacuum mode. Check
#
foreach {tn mode} {
1 delete
2 wal
} {
reset_db
sqlite3 db ""
do_execsql_test 9.$tn.1.1 {
PRAGMA cache_size = 15;
PRAGMA auto_vacuum = 1;
}
execsql "PRAGMA journal_mode = $mode"
do_execsql_test 9.$tn.1.2 {
CREATE TABLE tx(a, b);
CREATE INDEX i1 ON tx(a);
CREATE INDEX i2 ON tx(b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
}
for {set i 2} {$i<20} {incr i} {
do_execsql_test 9.$tn.$i.1 { DELETE FROM tx WHERE (random()%3)==0 }
do_execsql_test 9.$tn.$i.2 { PRAGMA integrity_check } ok
do_execsql_test 9.$tn.$i.3 {
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<400 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
}
do_execsql_test 9.$tn.$i.4 { PRAGMA integrity_check } ok
do_execsql_test 9.$tn.$i.5 {
BEGIN;
DELETE FROM tx WHERE (random()%3)==0;
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
COMMIT;
}
do_execsql_test 9.$tn.$i.6 { PRAGMA integrity_check } ok
}
}
#-------------------------------------------------------------------------
# When using mmap mode with a temp file, SQLite must search the cache
# before using a mapped page even when there is no write transaction
# open. For a temp file, the on-disk version may not be up to date.
#
sqlite3 db ""
do_execsql_test 10.0 {
PRAGMA cache_size = 50;
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(a);
CREATE TABLE t2(x, y);
INSERT INTO t2 VALUES(1, 2);
}
do_execsql_test 10.1 {
BEGIN;
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
COMMIT;
INSERT INTO t2 VALUES(3, 4);
}
if {[permutation]!="journaltest"} {
# The journaltest permutation does not support mmap, so this part of
# the test is omitted.
do_execsql_test 10.2 { PRAGMA mmap_size = 512000 } 512000
}
do_execsql_test 10.3 { SELECT * FROM t2 } {1 2 3 4}
do_execsql_test 10.4 { PRAGMA integrity_check } ok
finish_test

View File

@@ -1944,6 +1944,12 @@ proc wal_check_journal_mode {testname {db db}} {
} }
} }
proc wal_is_capable {} {
ifcapable !wal { return 0 }
if {[permutation]=="journaltest"} { return 0 }
return 1
}
proc permutation {} { proc permutation {} {
set perm "" set perm ""
catch {set perm $::G(perm:name)} catch {set perm $::G(perm:name)}

View File

@@ -19,7 +19,8 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set testprefix tkt-2d1a5c67d set testprefix tkt-2d1a5c67d
ifcapable {!wal || !vtab} {finish_test; return} ifcapable {!vtab} {finish_test; return}
if {[wal_is_capable]==0} {finish_test; return}
for {set ii 1} {$ii<=10} {incr ii} { for {set ii 1} {$ii<=10} {incr ii} {
do_test tkt-2d1a5c67d.1.$ii { do_test tkt-2d1a5c67d.1.$ii {

View File

@@ -18,7 +18,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl
ifcapable !wal { finish_test ; return } if {![wal_is_capable]} { finish_test ; return }
do_execsql_test tkt-313723c356.1 { do_execsql_test tkt-313723c356.1 {
PRAGMA page_size = 1024; PRAGMA page_size = 1024;

View File

@@ -18,7 +18,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/lock_common.tcl source $testdir/lock_common.tcl
set ::testprefix tkt-5d863f876e set ::testprefix tkt-5d863f876e
ifcapable !wal {finish_test ; return } if {![wal_is_capable]} {finish_test ; return }
do_multiclient_test tn { do_multiclient_test tn {
do_test $tn.1 { do_test $tn.1 {

View File

@@ -50,4 +50,6 @@ for {set i 0} {$i < 100} {incr i} {
} {ok} } {ok}
} }
catch { db close }
unregister_devsim
finish_test finish_test

View File

@@ -89,7 +89,7 @@ do_test zerodamage-2.1 {
concat [file_control_powersafe_overwrite db -1] [set ::max_journal_size] concat [file_control_powersafe_overwrite db -1] [set ::max_journal_size]
} {0 0 24704} } {0 0 24704}
ifcapable wal { if {[wal_is_capable]} {
# Run a WAL-mode transaction with POWERSAFE_OVERWRITE on to verify that the # Run a WAL-mode transaction with POWERSAFE_OVERWRITE on to verify that the
# WAL file does not get too big. # WAL file does not get too big.
# #

View File

@@ -4402,7 +4402,8 @@ void ReportTable(
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out, " */\n"); lineno++; fprintf(out, " */\n"); lineno++;
for(rp2=rp->next; rp2; rp2=rp2->next){ for(rp2=rp->next; rp2; rp2=rp2->next){
if( rp2->code==rp->code ){ if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
&& rp2->codeSuffix==rp->codeSuffix ){
fprintf(out," case %d: /* ", rp2->iRule); fprintf(out," case %d: /* ", rp2->iRule);
writeRuleText(out, rp2); writeRuleText(out, rp2);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;