Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e3d4884d3 | |||
| 4c08735732 | |||
| d33bcb8a3c | |||
| 74588ceb31 | |||
| 77187faf5a | |||
| bf60baa985 | |||
| 3ba18adde5 | |||
| b9772e7fe8 | |||
| 3e1e14d818 | |||
| 68262d85ec | |||
| fa7b471c35 | |||
| 303a69b5ad | |||
| 33892c11a7 | |||
| 09ccaf72d1 | |||
| 9ecd7086c1 | |||
| c2c6fd18dd | |||
| 226cef4ef1 | |||
| d03024d814 | |||
| 2158a0c7ac | |||
| 7834551c1e | |||
| 05f1ba0ef8 | |||
| 3841372350 | |||
| 1273f8dafe | |||
| f21124f251 | |||
| 88a7973057 | |||
| 050dc5cff4 | |||
| 7e6f980bd4 | |||
| 70739addc2 | |||
| 3908fe90b1 | |||
| dfcdc663f2 | |||
| f0dae6d0a2 | |||
| 38688b0b1d | |||
| 9c1cf3235c | |||
| 617b7b42e3 | |||
| 52fb8e1945 | |||
| 83bebddbd9 | |||
| 52df6f5e5c | |||
| b2a0f75c06 | |||
| b3c4523c58 | |||
| 20554381d9 | |||
| f49759bf03 | |||
| 36494b8bc6 | |||
| 83e8ca54d1 | |||
| 6034846eb6 | |||
| 95b46c85e2 | |||
| 1c305122a2 | |||
| daaae7b9d1 | |||
| 9c6e07d2fa | |||
| 09e16491f6 | |||
| 526740b1b9 | |||
| 87d63c900d | |||
| 5e398e4cbd | |||
| 5e27e1dc49 | |||
| 489a224bea | |||
| 0a02c72e79 | |||
| 48b9a6dd6b |
+1
-1
@@ -2266,7 +2266,7 @@ clean:
|
||||
del /Q sqlite3.c sqlite3.h 2>NUL
|
||||
del /Q opcodes.c opcodes.h 2>NUL
|
||||
del /Q lemon.* lempar.c parse.* 2>NUL
|
||||
del /Q mkkeywordhash.* keywordhash.h 2>NUL
|
||||
del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
|
||||
del /Q notasharedlib.* 2>NUL
|
||||
-rmdir /Q/S .deps 2>NUL
|
||||
-rmdir /Q/S .libs 2>NUL
|
||||
|
||||
@@ -909,6 +909,7 @@ enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_update_limit
|
||||
enable_rtree
|
||||
enable_session
|
||||
enable_gcov
|
||||
@@ -1560,6 +1561,7 @@ Optional Features:
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
|
||||
--enable-rtree Enable the RTREE extension
|
||||
--enable-session Enable the SESSION extension
|
||||
--enable-gcov Enable coverage testing using gcov
|
||||
@@ -3929,13 +3931,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3932: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3934: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3935: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3937: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3938: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3940: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5141,7 +5143,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5144 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5146 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6666,11 +6668,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6669: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6671: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6673: \$? = $ac_status" >&5
|
||||
echo "$as_me:6675: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7005,11 +7007,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7008: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7010: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7012: \$? = $ac_status" >&5
|
||||
echo "$as_me:7014: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7110,11 +7112,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7113: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7115: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7117: \$? = $ac_status" >&5
|
||||
echo "$as_me:7119: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7165,11 +7167,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7168: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7170: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7172: \$? = $ac_status" >&5
|
||||
echo "$as_me:7174: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9545,7 +9547,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9548 "configure"
|
||||
#line 9550 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9641,7 +9643,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9644 "configure"
|
||||
#line 9646 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11539,6 +11541,20 @@ if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
# Check whether --enable-update-limit was given.
|
||||
if test "${enable_update_limit+set}" = set; then :
|
||||
enableval=$enable_update_limit; enable_udlimit=yes
|
||||
else
|
||||
enable_udlimit=no
|
||||
fi
|
||||
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
# Check whether --enable-rtree was given.
|
||||
|
||||
@@ -644,6 +644,16 @@ if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
|
||||
[Enable the UPDATE/DELETE LIMIT clause]),
|
||||
[enable_udlimit=yes],[enable_udlimit=no])
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
|
||||
+3
-2
@@ -195,8 +195,9 @@ static int seriesColumn(
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the rowid for the current row. In this implementation, the
|
||||
** rowid is the same as the output value.
|
||||
** Return the rowid for the current row. In this implementation, the
|
||||
** first row returned is assigned rowid value 1, and each subsequent
|
||||
** row a value 1 more than that of the previous.
|
||||
*/
|
||||
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
series_cursor *pCur = (series_cursor*)cur;
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# 2014 August 30
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set ::testprefix rbutemplimit
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
proc setup_databases {} {
|
||||
forcedelete test.db2
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
-- Create target database schema.
|
||||
--
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
|
||||
CREATE INDEX i1b ON t1(b);
|
||||
CREATE INDEX i1c ON t1(c);
|
||||
CREATE INDEX i2b ON t2(b);
|
||||
CREATE INDEX i2c ON t2(c);
|
||||
|
||||
-- Create a large RBU database.
|
||||
--
|
||||
ATTACH 'test.db2' AS rbu;
|
||||
CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000
|
||||
)
|
||||
INSERT INTO data_t1 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
|
||||
CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15000
|
||||
)
|
||||
INSERT INTO data_t2 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
|
||||
}
|
||||
db close
|
||||
}
|
||||
|
||||
proc run_rbu_cachesize {target rbu cachesize temp_limit} {
|
||||
sqlite3rbu rbu $target $rbu
|
||||
rbu temp_size_limit $temp_limit
|
||||
sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
|
||||
while 1 {
|
||||
set rc [rbu step]
|
||||
set ::A([rbu temp_size]) 1
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
}
|
||||
list [catch {rbu close} msg] $msg
|
||||
}
|
||||
|
||||
proc step_rbu_cachesize {target rbu stepsize cachesize temp_limit} {
|
||||
set res ""
|
||||
while 1 {
|
||||
sqlite3rbu rbu $target $rbu
|
||||
rbu temp_size_limit $temp_limit
|
||||
sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
|
||||
for {set i 0} {$i < $stepsize} {incr i} {
|
||||
set rc [rbu step]
|
||||
set ::A([rbu temp_size]) 1
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
}
|
||||
set res [list [catch {rbu close} msg] $msg]
|
||||
if {$res != "0 SQLITE_OK"} break
|
||||
}
|
||||
set res
|
||||
}
|
||||
|
||||
do_test 1.1.0 { setup_databases } {}
|
||||
|
||||
do_test 1.1.1 {
|
||||
unset -nocomplain ::A
|
||||
run_rbu_cachesize test.db test.db2 10 0
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
do_test 1.1.2 { llength [array names ::A] } 3
|
||||
|
||||
do_test 1.1.3 {
|
||||
foreach {a0 a1 a2} [lsort -integer [array names ::A]] {}
|
||||
list [expr $a0==0] \
|
||||
[expr $a1>1048576] [expr $a1<1200000] \
|
||||
[expr $a2>1500000] [expr $a2<1700000]
|
||||
} {1 1 1 1 1}
|
||||
|
||||
do_test 1.2.1 {
|
||||
setup_databases
|
||||
run_rbu_cachesize test.db test.db2 10 1000000
|
||||
} {1 SQLITE_FULL}
|
||||
do_test 1.2.2 { info commands rbu } {}
|
||||
|
||||
do_test 1.3.1 {
|
||||
setup_databases
|
||||
run_rbu_cachesize test.db test.db2 10 1300000
|
||||
} {1 SQLITE_FULL}
|
||||
do_test 1.3.2 { info commands rbu } {}
|
||||
|
||||
do_test 1.4.1 {
|
||||
setup_databases
|
||||
run_rbu_cachesize test.db test.db2 10 1800000
|
||||
} {0 SQLITE_DONE}
|
||||
do_test 1.4.2 { info commands rbu } {}
|
||||
|
||||
do_test 1.5.1 {
|
||||
setup_databases
|
||||
unset -nocomplain ::A
|
||||
step_rbu_cachesize test.db test.db2 1000 10 2400000
|
||||
} {0 SQLITE_DONE}
|
||||
do_test 1.5.2 { info commands rbu } {}
|
||||
|
||||
do_test 1.6.1 {
|
||||
setup_databases
|
||||
unset -nocomplain ::A
|
||||
step_rbu_cachesize test.db test.db2 1000 10 1400000
|
||||
} {1 SQLITE_FULL}
|
||||
do_test 1.6.2 { info commands rbu } {}
|
||||
|
||||
finish_test
|
||||
|
||||
+63
-5
@@ -371,6 +371,8 @@ struct sqlite3rbu {
|
||||
int pgsz;
|
||||
u8 *aBuf;
|
||||
i64 iWalCksum;
|
||||
i64 szTemp; /* Current size of all temp files in use */
|
||||
i64 szTempLimit; /* Total size limit for temp files */
|
||||
|
||||
/* Used in RBU vacuum mode only */
|
||||
int nRbu; /* Number of RBU VFS in the stack */
|
||||
@@ -379,23 +381,33 @@ struct sqlite3rbu {
|
||||
|
||||
/*
|
||||
** An rbu VFS is implemented using an instance of this structure.
|
||||
**
|
||||
** Variable pRbu is only non-NULL for automatically created RBU VFS objects.
|
||||
** It is NULL for RBU VFS objects created explicitly using
|
||||
** sqlite3rbu_create_vfs(). It is used to track the total amount of temp
|
||||
** space used by the RBU handle.
|
||||
*/
|
||||
struct rbu_vfs {
|
||||
sqlite3_vfs base; /* rbu VFS shim methods */
|
||||
sqlite3_vfs *pRealVfs; /* Underlying VFS */
|
||||
sqlite3_mutex *mutex; /* Mutex to protect pMain */
|
||||
sqlite3rbu *pRbu; /* Owner RBU object */
|
||||
rbu_file *pMain; /* Linked list of main db files */
|
||||
};
|
||||
|
||||
/*
|
||||
** Each file opened by an rbu VFS is represented by an instance of
|
||||
** the following structure.
|
||||
**
|
||||
** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable
|
||||
** "sz" is set to the current size of the database file.
|
||||
*/
|
||||
struct rbu_file {
|
||||
sqlite3_file base; /* sqlite3_file methods */
|
||||
sqlite3_file *pReal; /* Underlying file handle */
|
||||
rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */
|
||||
sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */
|
||||
i64 sz; /* Size of file in bytes (temp only) */
|
||||
|
||||
int openFlags; /* Flags this file was opened with */
|
||||
u32 iCookie; /* Cookie value for main db files */
|
||||
@@ -3409,6 +3421,7 @@ static void rbuCreateVfs(sqlite3rbu *p){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
|
||||
assert( pVfs );
|
||||
p->zVfsName = pVfs->zName;
|
||||
((rbu_vfs*)pVfs)->pRbu = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3781,6 +3794,7 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
|
||||
/* Close the open database handle and VFS object. */
|
||||
sqlite3_close(p->dbRbu);
|
||||
sqlite3_close(p->dbMain);
|
||||
assert( p->szTemp==0 );
|
||||
rbuDeleteVfs(p);
|
||||
sqlite3_free(p->aBuf);
|
||||
sqlite3_free(p->aFrame);
|
||||
@@ -3968,6 +3982,7 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
|
||||
*/
|
||||
|
||||
static void rbuUnlockShm(rbu_file *p){
|
||||
assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
|
||||
if( p->pRbu ){
|
||||
int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock;
|
||||
int i;
|
||||
@@ -3980,6 +3995,18 @@ static void rbuUnlockShm(rbu_file *p){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
|
||||
sqlite3rbu *pRbu = pFd->pRbu;
|
||||
i64 nDiff = nNew - pFd->sz;
|
||||
pRbu->szTemp += nDiff;
|
||||
pFd->sz = nNew;
|
||||
assert( pRbu->szTemp>=0 );
|
||||
if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an rbu file.
|
||||
*/
|
||||
@@ -4005,6 +4032,9 @@ static int rbuVfsClose(sqlite3_file *pFile){
|
||||
rbuUnlockShm(p);
|
||||
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
|
||||
}
|
||||
else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
|
||||
rbuUpdateTempSize(p, 0);
|
||||
}
|
||||
|
||||
/* Close the underlying file handle */
|
||||
rc = p->pReal->pMethods->xClose(p->pReal);
|
||||
@@ -4122,11 +4152,19 @@ static int rbuVfsWrite(
|
||||
assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
|
||||
rc = rbuCaptureDbWrite(p->pRbu, iOfst);
|
||||
}else{
|
||||
if( pRbu && pRbu->eStage==RBU_STAGE_OAL
|
||||
&& (p->openFlags & SQLITE_OPEN_WAL)
|
||||
&& iOfst>=pRbu->iOalSz
|
||||
){
|
||||
pRbu->iOalSz = iAmt + iOfst;
|
||||
if( pRbu ){
|
||||
if( pRbu->eStage==RBU_STAGE_OAL
|
||||
&& (p->openFlags & SQLITE_OPEN_WAL)
|
||||
&& iOfst>=pRbu->iOalSz
|
||||
){
|
||||
pRbu->iOalSz = iAmt + iOfst;
|
||||
}else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){
|
||||
i64 szNew = iAmt+iOfst;
|
||||
if( szNew>p->sz ){
|
||||
rc = rbuUpdateTempSize(p, szNew);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
|
||||
if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){
|
||||
@@ -4145,6 +4183,10 @@ static int rbuVfsWrite(
|
||||
*/
|
||||
static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
rbu_file *p = (rbu_file*)pFile;
|
||||
if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
|
||||
int rc = rbuUpdateTempSize(p, size);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
return p->pReal->pMethods->xTruncate(p->pReal, size);
|
||||
}
|
||||
|
||||
@@ -4534,6 +4576,8 @@ static int rbuVfsOpen(
|
||||
pDb->pWalFd = pFd;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pFd->pRbu = pRbuVfs->pRbu;
|
||||
}
|
||||
|
||||
if( oflags & SQLITE_OPEN_MAIN_DB
|
||||
@@ -4801,6 +4845,20 @@ int sqlite3rbu_create_vfs(const char *zName, const char *zParent){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Configure the aggregate temp file size limit for this RBU handle.
|
||||
*/
|
||||
sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){
|
||||
if( n>=0 ){
|
||||
pRbu->szTempLimit = n;
|
||||
}
|
||||
return pRbu->szTempLimit;
|
||||
}
|
||||
|
||||
sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){
|
||||
return pRbu->szTemp;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
@@ -352,6 +352,28 @@ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
|
||||
const char *zState
|
||||
);
|
||||
|
||||
/*
|
||||
** Configure a limit for the amount of temp space that may be used by
|
||||
** the RBU handle passed as the first argument. The new limit is specified
|
||||
** in bytes by the second parameter. If it is positive, the limit is updated.
|
||||
** If the second parameter to this function is passed zero, then the limit
|
||||
** is removed entirely. If the second parameter is negative, the limit is
|
||||
** not modified (this is useful for querying the current limit).
|
||||
**
|
||||
** In all cases the returned value is the current limit in bytes (zero
|
||||
** indicates unlimited).
|
||||
**
|
||||
** If the temp space limit is exceeded during operation, an SQLITE_FULL
|
||||
** error is returned.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64);
|
||||
|
||||
/*
|
||||
** Return the current amount of temp file space, in bytes, currently used by
|
||||
** the RBU handle passed as the only argument.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*);
|
||||
|
||||
/*
|
||||
** Internally, each RBU connection uses a separate SQLite database
|
||||
** connection to access the target and rbu update databases. This
|
||||
|
||||
+28
-10
@@ -69,16 +69,18 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
|
||||
int nArg;
|
||||
const char *zUsage;
|
||||
} aCmd[] = {
|
||||
{"step", 2, ""}, /* 0 */
|
||||
{"close", 2, ""}, /* 1 */
|
||||
{"create_rbu_delta", 2, ""}, /* 2 */
|
||||
{"savestate", 2, ""}, /* 3 */
|
||||
{"dbMain_eval", 3, "SQL"}, /* 4 */
|
||||
{"bp_progress", 2, ""}, /* 5 */
|
||||
{"db", 3, "RBU"}, /* 6 */
|
||||
{"state", 2, ""}, /* 7 */
|
||||
{"progress", 2, ""}, /* 8 */
|
||||
{"close_no_error", 2, ""}, /* 9 */
|
||||
{"step", 2, ""}, /* 0 */
|
||||
{"close", 2, ""}, /* 1 */
|
||||
{"create_rbu_delta", 2, ""}, /* 2 */
|
||||
{"savestate", 2, ""}, /* 3 */
|
||||
{"dbMain_eval", 3, "SQL"}, /* 4 */
|
||||
{"bp_progress", 2, ""}, /* 5 */
|
||||
{"db", 3, "RBU"}, /* 6 */
|
||||
{"state", 2, ""}, /* 7 */
|
||||
{"progress", 2, ""}, /* 8 */
|
||||
{"close_no_error", 2, ""}, /* 9 */
|
||||
{"temp_size_limit", 3, "LIMIT"}, /* 10 */
|
||||
{"temp_size", 2, ""}, /* 11 */
|
||||
{0,0,0}
|
||||
};
|
||||
int iCmd;
|
||||
@@ -193,6 +195,22 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nStep));
|
||||
break;
|
||||
}
|
||||
|
||||
case 10: /* temp_size_limit */ {
|
||||
sqlite3_int64 nLimit;
|
||||
if( Tcl_GetWideIntFromObj(interp, objv[2], &nLimit) ){
|
||||
ret = TCL_ERROR;
|
||||
}else{
|
||||
nLimit = sqlite3rbu_temp_size_limit(pRbu, nLimit);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nLimit));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 11: /* temp_size */ {
|
||||
sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz));
|
||||
break;
|
||||
}
|
||||
|
||||
default: /* seems unlikely */
|
||||
assert( !"cannot happen" );
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
C Trying\sagain\sto\sget\sout-of-tree\sbuilds\sto\swork\scorrectly.
|
||||
D 2017-08-22T19:49:34.691
|
||||
C Experimental\ssqlite3_stmt_retryable()\sinterface.
|
||||
D 2017-09-13T18:38:31.171
|
||||
F Makefile.in c644bbe8ebe4aae82ad6783eae6b6beea4c727b99ff97568b847ced5e2ac7afb
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 25b154da7f0b3d4924f27378c1f8d006285b80811f1ccf3ed953dbebf6282136
|
||||
F Makefile.msc 6a7a74bf60ad395098c0bd175ab054cd65ef85d7f034198d52bcc4d9e5fb4c6b
|
||||
F README.md f5c87359573c4d255425e588a56554b50fdcc2afba4e017a2e02a43701456afd
|
||||
F VERSION f81232df28e2d3ff049feefad5fbd5489cc33697f6bd2ecf61af7f0dde3b83d0
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -30,8 +30,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 2500b432572804093c9a2516e2b16dbcec5d797ea1cd654915cfecd1d7a39ee3 x
|
||||
F configure.ac 13f45f02e6c51dd0e347315b5401c3f047712b7f79b7f35619115c23755afcff
|
||||
F configure e691ad9b505f1f47bc5d99be9e1d49b1be9037e9cb3821c9b14c63c3d413d055 x
|
||||
F configure.ac bb85c1c53e952c8c7078a2f147eba613e0128b8b6e7780d64758d8fb29bcc695
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 1f8b8d4c9f5cfe40e679fee279cc9eb2da8e6eb74ad406028538d7864cc4b6cb
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -276,7 +276,7 @@ F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
|
||||
F ext/misc/series.c b0f5f346aca9b7ff7caaf0da2efb4ad462441abd4dcd92a460cb573b3ea2370b
|
||||
F ext/misc/series.c f3c0dba5c5c749ce1782b53076108f87cf0b71041eb6023f727a9c50681da564
|
||||
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
|
||||
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
@@ -318,11 +318,12 @@ F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff
|
||||
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
|
||||
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
|
||||
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
|
||||
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
|
||||
F ext/rbu/sqlite3rbu.c 920941a6ff7dbbea0970717c43662878fda5c37e43752de329f0fdd76680ab75
|
||||
F ext/rbu/sqlite3rbu.h 82c102e5ae41025e3b245d3d5944315f82811da85e2cd363a75caa97cbd0cd3e
|
||||
F ext/rbu/test_rbu.c ec18cfc69a104309df23c359e3c80306c9a6bdd1d2c53c8b70ae158e9832dcd6
|
||||
F ext/rbu/sqlite3rbu.c a1a303de8b90f987ef63bf9cef57f5d7dd7983a9e8aed3775a759d87ad57075d
|
||||
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
|
||||
F ext/rbu/test_rbu.c 7073979b9cc80912bb03599ac8d85ab5d3bf03cfacd3463f2dcdd7822997533a
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c cf84d52958a7ec6a506f1711e119db847ed6bb5dedde78a58e97503287afcda1
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
@@ -399,21 +400,21 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c e1a98bef27d6189df5c5b8b3c9b5e53d6b74bf9a936af97757c21e9ea6a5c6b2
|
||||
F src/btree.c 1c2b2f1714c411d7a9bc52c90d9dd7eab261261d5691ac0f67e1ced92419799c
|
||||
F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09
|
||||
F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc
|
||||
F src/build.c b47a0320c6d237718b8f493ac97d37d1071bce12aca668b15219187150c41295
|
||||
F src/build.c e71e96a67daf3d1dd23188423e66cd6af38017e2ec73fead5d2b57da2d3c7e16
|
||||
F src/callback.c 28a8ede982fde4129b828350f78f2c01fe7d12c74d1a0a05d7108ab36f308688
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
|
||||
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74
|
||||
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
|
||||
F src/delete.c 21a5f1812fdb599e9f7afb9f650bdabab60a3afd51d7e94e539c982f647b0023
|
||||
F src/expr.c 4ca86dc65f5ea478c665a5b4fe79d05f00432c9bd82237a896b45bd376bf1217
|
||||
F src/expr.c 0f611840217016cf2c5e72f2eb8e412e48511bf740ae1fd5b58dc5e409c6e738
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 5ff2c895fe087756d8085dc1a9bc229b5670e2a65c3929dd87c71e43649af333
|
||||
F src/func.c ed8888ae80b39f5a5d403954e4a05e0a38303523dff8143161439c142d31dec1
|
||||
F src/global.c 8a6ab6b4d91effb96ffa81b39f0d70c862abca157f8aaa194600a4a8b7923344
|
||||
F src/func.c b4d259af627e3cd9510cf08db37f0bcc88b1887c735169c74490c3739d5cf5c6
|
||||
F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
@@ -421,8 +422,8 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c d2d1bf12d2b5382450620d7cede84c7ffe57e6a89fa9a908f1aba68df2731cd9
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
|
||||
F src/main.c 42f6a2660c7a1d643cc7e863d2dcd630c6aa1e8343f5478b0592120ab84c97ba
|
||||
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
|
||||
F src/main.c 39f1375c02ea2d201bd09efcc09dcbb7ebce241280fa17bb7aa4ef7cc718061c
|
||||
F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
@@ -436,35 +437,35 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
F src/mutex_w32.c a898fa969823b100c0f5fdc57e54c9a1e419ab4d
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24
|
||||
F src/os.c 93e0979b9b55df29c0c4923f73b48e9d3fe728f01dd8ed4f6a9d2f1d79779bc8
|
||||
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c 489aa972ccc34f7b4770b891694b32101c59ddd4be4ef0ddd9a4da58c145c1a6
|
||||
F src/os_win.c 964165b66cde03abc72fe948198b01be608436894732eadb94c8720d2467f223
|
||||
F src/os_win.c 225432ab6512f63ab2f37eb76872f818b01f0483ba0bea04a7a1168be3070ea5
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c c1dc0609f04a0659519bb2b8ca1440a64b0ad82b6c2afd675f1a50f6c918321a
|
||||
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
|
||||
F src/pager.c 967168bba88d2dc790ed9618bd4ba7bfe475b67b521ef6da305a6425c592928f
|
||||
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
|
||||
F src/parse.y 52ef3cecd0934e9da4a45b585883a03243ad615d338ad94f44501a05891dcdfa
|
||||
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
|
||||
F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
|
||||
F src/pcache1.c 0b793738b5dddaf0a645784835c6b5557b1ecfaee339af9c26810c6ecdb273aa
|
||||
F src/pragma.c cd6aeda3587be6c5c08f9b2d45eae6068666a03c9d077c8c43cdb85fb0aa70f2
|
||||
F src/pcache.c 4bada070456980c3c1f16d58ec2e64e389ad77b935e3d77e0c96e7bbd397289c
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c 88d99aa4752894aaf4102eefd09b5e497f4277661aff69f8fff61f8611f19d14
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c 9e880c0efb5d7f9101bb34c0a87daf6e1e5284c34024fdb811e67bb02fdd299b
|
||||
F src/prepare.c 9a141a1b02dca53beaa9771699d390aafcac01f5d1f1c0ae6e23ded8dcdb709a
|
||||
F src/printf.c 40aee47ae9be4bd3dbdc8968bd07fddc027be8edec8daddf24d3391d36698a1c
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c c9b3d8444bbf6f167d84f41ca6f3672e2521cb163a8c706b19058dc82fffe9b8
|
||||
F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
|
||||
F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
|
||||
F src/sqlite.h.in f0bd1abf5e27bd22b3bcaae2a861c1efc4ab7e752bf7eb102355135617eb8199
|
||||
F src/shell.c dc398976107b68dadccce23d27d0fd16f8409b1d782612969866aab015799582
|
||||
F src/shell.c.in 30d6799f86445a8b989bed45c7d5f33c8192d838605e0abe99e0398892779974
|
||||
F src/sqlite.h.in eea8fde8bf4f3ab8b82ab3dce54f86b113f75cf48fd43ce92efd2f0cd7cc6e61
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h a1fd3aa82f967da436164e0728a7d6841651fd0c6e27b9044e0eb9f6c8462e47
|
||||
F src/sqliteInt.h bc0792db4ff887e4884d386188527e1cd7c16d496c8f3ba23333e68cee3e4f78
|
||||
F src/sqliteInt.h 0568e9b1aed70ea7db3630820e9e35ed6a87ea6ef3ae20693467d8eb255639e3
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 487951d81f9704800fd9f0ffdaa2f935a83ccb6be3575c2c4ef83e4789b4c828
|
||||
F src/test1.c 8513b17ca4a7a9ba28748535d178b6e472ec7394ae0eea53907f2d3bcdbab2df
|
||||
@@ -474,12 +475,12 @@ F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
||||
F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
|
||||
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
|
||||
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
|
||||
F src/test8.c 3f7d0cc4e12e06832ba3db4455cb16867ccadafa602eb6ff5fcf097bffce56ed
|
||||
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
|
||||
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
|
||||
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
|
||||
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e
|
||||
@@ -494,7 +495,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
|
||||
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
|
||||
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c c05f6c40bd6c8bfe5f1718212f81fd5687f91766
|
||||
F src/test_malloc.c 4f06a805de86be5216a127b3777ca2d5a1ff99d1a9238374ce136a47411be36c
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
|
||||
F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
|
||||
@@ -522,26 +523,26 @@ F src/treeview.c 2ee4a5dada213d5ab08a742af5c876cee6f1aaae65f10a61923f3fb63846afe
|
||||
F src/trigger.c 48e0f7ed6749ce4d50a695e09e20ce9cf84ecabf2691852c965a51e0b620eccc
|
||||
F src/update.c 5404be9e840717323a69209190cdbc9d0d34adaedaaf1d1a1069babf2c4171c0
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c 773843506ce694714bc96fe67c30c37015f90ef515d0e70f1f8d5c9c24088152
|
||||
F src/util.c ece10cb34b4a62cbb3aab8d711b67e93a2765e0b81d0f72458cb801a3ac60703
|
||||
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
|
||||
F src/vdbe.c 82fc4553a0986a06bdd0d2b03a424e159bba5c74802fabb2841aa6cd27ccd962
|
||||
F src/vdbe.c 0a0ef7f0759ee4c3ed5ff0c6e9641216d4b31ebb0fea9a7b5a9c4a86ce875ff3
|
||||
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
|
||||
F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
|
||||
F src/vdbeapi.c 05d6b14ab73952db0d73f6452d6960216997bd966a710266b2fe051f25326abc
|
||||
F src/vdbeaux.c 2dff8186d34e0e525838f77b2fac70bd480f0273a77015bf21b6a08f2792da82
|
||||
F src/vdbeInt.h 207b6ac7842768601bd5563a0c5dfad9b7dc10be5577d71d8fb53258bfd371f2
|
||||
F src/vdbeapi.c e706b81a65f879e7b9640248a386ef5f90e29d61169680e64803d2eafe407763
|
||||
F src/vdbeaux.c 0b2b1942102b33060bd960cc5c1d4997394ffa7f7189148dab4af5187fa09191
|
||||
F src/vdbeblob.c db3cf91060f6f4b2f1358a4200e844697990752177784c7c95da00b7ac9f1c7b
|
||||
F src/vdbemem.c 2f9d672af5260f0145787e1dc2c6985414987cc0dc575133a0dc17dda767d868
|
||||
F src/vdbesort.c fea2bea25f5e9ccd91e0760d7359f0365f9fba1aaeac7216c71cad78765f58e3
|
||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
|
||||
F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
|
||||
F src/vtab.c f1d5c23132fb0247af3e86146404112283ddedb6c518de0d4edc91cfb36970ef
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||
F src/wal.c 839db09792fead5052bb35e533fa485e134913d547d05b5f42e537b73e63f07a
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c 3ccfa8637f95355bff61144e01a615b8ef26f79c312880848da73f03367da1e6
|
||||
F src/where.c ad558533d6fe6578857635218633aa241e2428835763c46801be9e68d6ec0701
|
||||
F src/whereInt.h 93bb90b77d39901eda31b44d8e90da1351193ccfe96876f89b58a93a33b84c3d
|
||||
F src/wherecode.c e7be3b7f4c11908500cdf02b299d190d3742659533f58e0f4047962fdb5a48da
|
||||
F src/whereexpr.c fe1fe600d7334e91f3d9d487021362d543fba8ab2f1be5e0d68063d619379c05
|
||||
F src/where.c d97f97ca6017747b7361af7f168a640d667c41cd1d4e91c2c5b2bd7538815d07
|
||||
F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
|
||||
F src/wherecode.c e8c2ece5843ea56e6c90277d421f2d628f3f7b7c976642369cc519f008e1d2b1
|
||||
F src/whereexpr.c 4953ca4e769c047d0a00a1ba9085849626b1f3a6e89f6befcf5c38fa0722acdd
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -609,6 +610,7 @@ F test/bestindex1.test 0cf1bd2d7b97d3a3a8c10736125274f64765c4ee
|
||||
F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
|
||||
F test/bestindex3.test 578b6a52dab819e63f28e3640e04b32c85aed320
|
||||
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
|
||||
F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
|
||||
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -750,7 +752,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 3f9ba0b2594837c7beaa3ba824e2137cfe857308f020ec5a0c7a62b444e837b0
|
||||
F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
|
||||
@@ -833,7 +835,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
|
||||
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
||||
F test/fts3conf.test 60317efd562080e198b5bdc9fcd222ce32cf01d7
|
||||
F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65
|
||||
@@ -943,7 +945,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
|
||||
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
|
||||
F test/indexexpr1.test 84100e880154a4b645db9f4fc7642756d9a2b6011b68f73c8efda4d244816de9
|
||||
F test/indexexpr2.test 2237f1408efa921bd66d0a09ebf0208cb0c228c1bc3b3a18e9fb8fc87d6ed90b
|
||||
F test/indexexpr2.test fdccd5c13a57af59a8e392660953dbcaacc4699c433516372cfba52994aa503a
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -981,7 +983,7 @@ F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb2848
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c d2b8cfc91047ebf6cac4f3a04f19c3a864e4ecfd683bbb65c395df450b8dc79c
|
||||
F test/kvtest.c fcb38ffe3db028a3138b4818fc098359c80dc51a0d1278a91c99c554cc1abb92
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 67d7431c9b664254febce9e90fd2f47c7c75c8b38444e2a50ef9ec2776b84ca8
|
||||
@@ -999,7 +1001,7 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
|
||||
F test/lookaside.test 90052e87282de256d613fcf8c9cbb845e4001d2f
|
||||
F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
|
||||
F test/main.test bb75e406c9b64931f3dc7e7f04626633365bb22f
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
|
||||
@@ -1029,7 +1031,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
|
||||
F test/memsubsys1.test 6d268d0ae90f8d61a2356a1838665654d83de518
|
||||
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
|
||||
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
|
||||
F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
@@ -1055,7 +1057,7 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
|
||||
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
|
||||
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3
|
||||
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
|
||||
F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
|
||||
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
@@ -1093,11 +1095,12 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 3b94f8fd431d39fac4952eb5dc38e1bb2b4518e1ac967d66f5abc815c104aeb6
|
||||
F test/pragma.test f274259d6393b6681eb433beb8dd39a26ec06a4431052a4880b43b84912a3f58
|
||||
F test/permutations.test d911c9ba49088d22054a05dc73743f677872a92ac89288bcdeafa0ebf3f9c531
|
||||
F test/pragma.test c31b5e98998c160a4c85b1e04f590655c67f2daa7f73854640cd120610e3ac15
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
|
||||
F test/pragma5.test fd517f42ee847e126afbbbd9fd0fb9e5a4a61a962496a350adb8a22583fbdc37
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
|
||||
@@ -1218,7 +1221,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 7b1ab42b097b484c18d99e1d1c71a6a0c9c87a7a
|
||||
F test/speedtest1.c 7a6ec22e87f78ef98d523667593f5d818f6be4a1bcf5fe70d933aece058f32df
|
||||
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1256,7 +1259,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl eb7ec55fe074a909423c1de701f7c545417b8aa96787b8c3e7a79203f2cebec8
|
||||
F test/tester.tcl 9948bd856ce8a1c127f2f7900365387a42a917ce0dc87185bdd128fa5b11aff2
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1486,7 +1489,7 @@ F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c37
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
|
||||
F test/wal2.test 56b0bc95b8693a0be294f8d210c49025dd094bd7
|
||||
F test/wal2.test 6ac39b94a284ebac6efb6be93b0cdfe73ee6083f129555e3144d8a615e9900ef
|
||||
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
|
||||
@@ -1529,7 +1532,7 @@ F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 97a86ecdfa4c21684fdff501dbd2cb7397689be8676d0dbad1f5a0892c6b56a3
|
||||
F test/whereF.test 7c426e0bf303407910c21f79d3a6742f7b33c9b27b2dddd230dfc8c2508981a6
|
||||
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7
|
||||
@@ -1538,7 +1541,7 @@ F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
@@ -1552,7 +1555,7 @@ F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
|
||||
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
|
||||
F test/wordcount.c cb589cec469a1d90add05b1f8cee75c7210338d87a5afd65260ed5c0f4bbf8ac
|
||||
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
||||
@@ -1587,11 +1590,11 @@ F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
|
||||
F tool/mkshellc.tcl 69c38ecd7b74b2b0799a35ce20e1e3998e504d8c99c100ca4b98ae9d8f6279bc
|
||||
F tool/mksourceid.c 1db4636bf4249ac5d2d56fb06b0b30929bf7446a88c7048bb731a72a1c4767ea
|
||||
F tool/mkshellc.tcl 950c36f45941c12140e346a907fb66198bc2770ff7a17c749201e78d34bb3b0b
|
||||
F tool/mksourceid.c 30966d568654a4fd962fb324753e49429b7379e1f72d2be489ade963121f5943
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
|
||||
F tool/mksqlite3c.tcl a4b36eaa002ed00a0ab2c93d999a14f1acae98ff09a85382e5abc05a91edb82b
|
||||
F tool/mksqlite3c.tcl b258d679829a9305f5cf107b7d97b9bf23adb3773df42947fed5ef7b180dfbd9
|
||||
F tool/mksqlite3h.tcl f92f994d9709aeb9e2b6e6f9fc8b069d2f55202c8e23f453edc44390a25982dc
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
|
||||
@@ -1650,7 +1653,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5a037ac2da7449be3e26c36910ac5d865d7e74d3c25af0a10578c1f92fe2afea
|
||||
R 5f7cd0b5ad89a4d7783875a0ce64d27b
|
||||
P 87ccdf9cbb9284553330683d4971be4f523ce922089aee6dffccfc18b3004263
|
||||
R e43ecae42b6f451608f028a9fca6964c
|
||||
T *branch * sqlite3_stmt_retryable
|
||||
T *sym-sqlite3_stmt_retryable *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z ce17968a3f11b573ce5537607e65c92d
|
||||
Z 5c6219255517ab512c38a3a9f7c2d38b
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
a1b3337e949fc431e19a3d977d07a312bb253ab7fec6811c0221abd514985d55
|
||||
ebada0723ac91f288fe89baf4a7eb6383f71d6588afaf17467f45a56677de22d
|
||||
+104
-78
@@ -439,7 +439,8 @@ static void downgradeAllSharedCacheTableLocks(Btree *p){
|
||||
|
||||
#endif /* SQLITE_OMIT_SHARED_CACHE */
|
||||
|
||||
static void releasePage(MemPage *pPage);
|
||||
static void releasePage(MemPage *pPage); /* Forward reference */
|
||||
static void releasePageOne(MemPage *pPage); /* Forward reference */
|
||||
static void releasePageNotNull(MemPage *pPage); /* Forward reference */
|
||||
|
||||
/*
|
||||
@@ -774,7 +775,7 @@ static int btreeMoveto(
|
||||
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
|
||||
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
|
||||
if( pIdxKey->nField==0 ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_done;
|
||||
}
|
||||
}else{
|
||||
@@ -1399,7 +1400,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
||||
int sz = get2byte(&data[iFree+2]);
|
||||
int top = get2byte(&data[hdr+5]);
|
||||
if( iFree2 ){
|
||||
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
|
||||
sz2 = get2byte(&data[iFree2+2]);
|
||||
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
|
||||
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
|
||||
@@ -1488,16 +1489,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
||||
int pc = get2byte(&aData[iAddr]);
|
||||
int x;
|
||||
int usableSize = pPg->pBt->usableSize;
|
||||
int size; /* Size of the free slot */
|
||||
|
||||
assert( pc>0 );
|
||||
do{
|
||||
int size; /* Size of the free slot */
|
||||
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
|
||||
** increasing offset. */
|
||||
if( pc>usableSize-4 || pc<iAddr+4 ){
|
||||
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
|
||||
return 0;
|
||||
}
|
||||
while( pc<=usableSize-4 ){
|
||||
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
|
||||
** freeblock form a big-endian integer which is the size of the freeblock
|
||||
** in bytes, including the 4-byte header. */
|
||||
@@ -1505,7 +1500,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
||||
if( (x = size - nByte)>=0 ){
|
||||
testcase( x==4 );
|
||||
testcase( x==3 );
|
||||
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
|
||||
if( size+pc > usableSize ){
|
||||
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
|
||||
return 0;
|
||||
}else if( x<4 ){
|
||||
@@ -1526,7 +1521,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
||||
}
|
||||
iAddr = pc;
|
||||
pc = get2byte(&aData[pc]);
|
||||
}while( pc );
|
||||
if( pc<iAddr+size ) break;
|
||||
}
|
||||
if( pc ){
|
||||
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1640,7 +1639,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
u8 hdr; /* Page header size. 0 or 100 */
|
||||
u8 nFrag = 0; /* Reduction in fragmentation */
|
||||
u16 iOrigSize = iSize; /* Original value of iSize */
|
||||
u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */
|
||||
u16 x; /* Offset to cell content area */
|
||||
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
|
||||
unsigned char *data = pPage->aData; /* Page content */
|
||||
|
||||
@@ -1650,13 +1649,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
assert( iSize>=4 ); /* Minimum cell size is 4 */
|
||||
assert( iStart<=iLast );
|
||||
|
||||
/* Overwrite deleted information with zeros when the secure_delete
|
||||
** option is enabled */
|
||||
if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
|
||||
memset(&data[iStart], 0, iSize);
|
||||
}
|
||||
assert( iStart<=pPage->pBt->usableSize-4 );
|
||||
|
||||
/* The list of freeblocks must be in ascending order. Find the
|
||||
** spot on the list where iStart should be inserted.
|
||||
@@ -1673,7 +1666,9 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
}
|
||||
iPtr = iFreeBlk;
|
||||
}
|
||||
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
if( iFreeBlk>pPage->pBt->usableSize-4 ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
assert( iFreeBlk>iPtr || iFreeBlk==0 );
|
||||
|
||||
/* At this point:
|
||||
@@ -1709,19 +1704,25 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
data[hdr+7] -= nFrag;
|
||||
}
|
||||
if( iStart==get2byte(&data[hdr+5]) ){
|
||||
x = get2byte(&data[hdr+5]);
|
||||
if( iStart<=x ){
|
||||
/* The new freeblock is at the beginning of the cell content area,
|
||||
** so just extend the cell content area rather than create another
|
||||
** freelist entry */
|
||||
if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
put2byte(&data[hdr+1], iFreeBlk);
|
||||
put2byte(&data[hdr+5], iEnd);
|
||||
}else{
|
||||
/* Insert the new freeblock into the freelist */
|
||||
put2byte(&data[iPtr], iStart);
|
||||
put2byte(&data[iStart], iFreeBlk);
|
||||
put2byte(&data[iStart+2], iSize);
|
||||
}
|
||||
if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
|
||||
/* Overwrite deleted information with zeros when the secure_delete
|
||||
** option is enabled */
|
||||
memset(&data[iStart], 0, iSize);
|
||||
}
|
||||
put2byte(&data[iStart], iFreeBlk);
|
||||
put2byte(&data[iStart+2], iSize);
|
||||
pPage->nFree += iOrigSize;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -2109,6 +2110,8 @@ getAndInitPage_error:
|
||||
/*
|
||||
** Release a MemPage. This should be called once for each prior
|
||||
** call to btreeGetPage.
|
||||
**
|
||||
** Page1 is a special case and must be released using releasePageOne().
|
||||
*/
|
||||
static void releasePageNotNull(MemPage *pPage){
|
||||
assert( pPage->aData );
|
||||
@@ -2122,6 +2125,16 @@ static void releasePageNotNull(MemPage *pPage){
|
||||
static void releasePage(MemPage *pPage){
|
||||
if( pPage ) releasePageNotNull(pPage);
|
||||
}
|
||||
static void releasePageOne(MemPage *pPage){
|
||||
assert( pPage!=0 );
|
||||
assert( pPage->aData );
|
||||
assert( pPage->pBt );
|
||||
assert( pPage->pDbPage!=0 );
|
||||
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
||||
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
sqlite3PagerUnrefPageOne(pPage->pDbPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get an unused page.
|
||||
@@ -3000,7 +3013,7 @@ static int lockBtree(BtShared *pBt){
|
||||
}else{
|
||||
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
|
||||
if( isOpen==0 ){
|
||||
releasePage(pPage1);
|
||||
releasePageOne(pPage1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
@@ -3047,7 +3060,7 @@ static int lockBtree(BtShared *pBt){
|
||||
** zero and return SQLITE_OK. The caller will call this function
|
||||
** again with the correct page-size.
|
||||
*/
|
||||
releasePage(pPage1);
|
||||
releasePageOne(pPage1);
|
||||
pBt->usableSize = usableSize;
|
||||
pBt->pageSize = pageSize;
|
||||
freeTempSpace(pBt);
|
||||
@@ -3101,7 +3114,7 @@ static int lockBtree(BtShared *pBt){
|
||||
return SQLITE_OK;
|
||||
|
||||
page1_init_failed:
|
||||
releasePage(pPage1);
|
||||
releasePageOne(pPage1);
|
||||
pBt->pPage1 = 0;
|
||||
return rc;
|
||||
}
|
||||
@@ -3146,7 +3159,7 @@ static void unlockBtreeIfUnused(BtShared *pBt){
|
||||
assert( pPage1->aData );
|
||||
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
|
||||
pBt->pPage1 = 0;
|
||||
releasePageNotNull(pPage1);
|
||||
releasePageOne(pPage1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4068,7 +4081,7 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
|
||||
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
|
||||
testcase( pBt->nPage!=nPage );
|
||||
pBt->nPage = nPage;
|
||||
releasePage(pPage1);
|
||||
releasePageOne(pPage1);
|
||||
}
|
||||
assert( countValidCursors(pBt, 1)==0 );
|
||||
pBt->inTransaction = TRANS_READ;
|
||||
@@ -5375,7 +5388,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
pCur->ix = (u16)idx;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
@@ -6218,21 +6231,20 @@ static int fillInCell(
|
||||
){
|
||||
int nPayload;
|
||||
const u8 *pSrc;
|
||||
int nSrc, n, rc;
|
||||
int nSrc, n, rc, mn;
|
||||
int spaceLeft;
|
||||
MemPage *pOvfl = 0;
|
||||
MemPage *pToRelease = 0;
|
||||
MemPage *pToRelease;
|
||||
unsigned char *pPrior;
|
||||
unsigned char *pPayload;
|
||||
BtShared *pBt = pPage->pBt;
|
||||
Pgno pgnoOvfl = 0;
|
||||
BtShared *pBt;
|
||||
Pgno pgnoOvfl;
|
||||
int nHeader;
|
||||
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
|
||||
/* pPage is not necessarily writeable since pCell might be auxiliary
|
||||
** buffer space that is separate from the pPage buffer area */
|
||||
assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize]
|
||||
assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize]
|
||||
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
|
||||
/* Fill in the header. */
|
||||
@@ -6252,25 +6264,36 @@ static int fillInCell(
|
||||
}
|
||||
|
||||
/* Fill in the payload */
|
||||
pPayload = &pCell[nHeader];
|
||||
if( nPayload<=pPage->maxLocal ){
|
||||
/* This is the common case where everything fits on the btree page
|
||||
** and no overflow pages are required. */
|
||||
n = nHeader + nPayload;
|
||||
testcase( n==3 );
|
||||
testcase( n==4 );
|
||||
if( n<4 ) n = 4;
|
||||
*pnSize = n;
|
||||
spaceLeft = nPayload;
|
||||
pPrior = pCell;
|
||||
}else{
|
||||
int mn = pPage->minLocal;
|
||||
n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
|
||||
testcase( n==pPage->maxLocal );
|
||||
testcase( n==pPage->maxLocal+1 );
|
||||
if( n > pPage->maxLocal ) n = mn;
|
||||
spaceLeft = n;
|
||||
*pnSize = n + nHeader + 4;
|
||||
pPrior = &pCell[nHeader+n];
|
||||
assert( nSrc<=nPayload );
|
||||
testcase( nSrc<nPayload );
|
||||
memcpy(pPayload, pSrc, nSrc);
|
||||
memset(pPayload+nSrc, 0, nPayload-nSrc);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pPayload = &pCell[nHeader];
|
||||
|
||||
/* If we reach this point, it means that some of the content will need
|
||||
** to spill onto overflow pages.
|
||||
*/
|
||||
mn = pPage->minLocal;
|
||||
n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
|
||||
testcase( n==pPage->maxLocal );
|
||||
testcase( n==pPage->maxLocal+1 );
|
||||
if( n > pPage->maxLocal ) n = mn;
|
||||
spaceLeft = n;
|
||||
*pnSize = n + nHeader + 4;
|
||||
pPrior = &pCell[nHeader+n];
|
||||
pToRelease = 0;
|
||||
pgnoOvfl = 0;
|
||||
pBt = pPage->pBt;
|
||||
|
||||
/* At this point variables should be set as follows:
|
||||
**
|
||||
@@ -6296,8 +6319,35 @@ static int fillInCell(
|
||||
#endif
|
||||
|
||||
/* Write the payload into the local Cell and any extra into overflow pages */
|
||||
while( nPayload>0 ){
|
||||
while( 1 ){
|
||||
n = nPayload;
|
||||
if( n>spaceLeft ) n = spaceLeft;
|
||||
|
||||
/* If pToRelease is not zero than pPayload points into the data area
|
||||
** of pToRelease. Make sure pToRelease is still writeable. */
|
||||
assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
|
||||
|
||||
/* If pPayload is part of the data area of pPage, then make sure pPage
|
||||
** is still writeable */
|
||||
assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
|
||||
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
|
||||
if( nSrc>=n ){
|
||||
memcpy(pPayload, pSrc, n);
|
||||
}else if( nSrc>0 ){
|
||||
n = nSrc;
|
||||
memcpy(pPayload, pSrc, n);
|
||||
}else{
|
||||
memset(pPayload, 0, n);
|
||||
}
|
||||
nPayload -= n;
|
||||
if( nPayload<=0 ) break;
|
||||
pPayload += n;
|
||||
pSrc += n;
|
||||
nSrc -= n;
|
||||
spaceLeft -= n;
|
||||
if( spaceLeft==0 ){
|
||||
MemPage *pOvfl = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
|
||||
if( pBt->autoVacuum ){
|
||||
@@ -6350,30 +6400,6 @@ static int fillInCell(
|
||||
pPayload = &pOvfl->aData[4];
|
||||
spaceLeft = pBt->usableSize - 4;
|
||||
}
|
||||
n = nPayload;
|
||||
if( n>spaceLeft ) n = spaceLeft;
|
||||
|
||||
/* If pToRelease is not zero than pPayload points into the data area
|
||||
** of pToRelease. Make sure pToRelease is still writeable. */
|
||||
assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
|
||||
|
||||
/* If pPayload is part of the data area of pPage, then make sure pPage
|
||||
** is still writeable */
|
||||
assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
|
||||
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
|
||||
if( nSrc>0 ){
|
||||
if( n>nSrc ) n = nSrc;
|
||||
assert( pSrc );
|
||||
memcpy(pPayload, pSrc, n);
|
||||
}else{
|
||||
memset(pPayload, 0, n);
|
||||
}
|
||||
nPayload -= n;
|
||||
pPayload += n;
|
||||
pSrc += n;
|
||||
nSrc -= n;
|
||||
spaceLeft -= n;
|
||||
}
|
||||
releasePage(pToRelease);
|
||||
return SQLITE_OK;
|
||||
@@ -6405,7 +6431,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
|
||||
hdr = pPage->hdrOffset;
|
||||
testcase( pc==get2byte(&data[hdr+5]) );
|
||||
testcase( pc+sz==pPage->pBt->usableSize );
|
||||
if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
|
||||
if( pc+sz > pPage->pBt->usableSize ){
|
||||
*pRC = SQLITE_CORRUPT_BKPT;
|
||||
return;
|
||||
}
|
||||
@@ -7275,7 +7301,7 @@ static int balance_nonroot(
|
||||
/* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
|
||||
** that is more than 6 times the database page size. */
|
||||
assert( szScratch<=6*(int)pBt->pageSize );
|
||||
b.apCell = sqlite3ScratchMalloc( szScratch );
|
||||
b.apCell = sqlite3StackAllocRaw(0, szScratch );
|
||||
if( b.apCell==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto balance_cleanup;
|
||||
@@ -7853,7 +7879,7 @@ static int balance_nonroot(
|
||||
** Cleanup before returning.
|
||||
*/
|
||||
balance_cleanup:
|
||||
sqlite3ScratchFree(b.apCell);
|
||||
sqlite3StackFree(0, b.apCell);
|
||||
for(i=0; i<nOld; i++){
|
||||
releasePage(apOld[i]);
|
||||
}
|
||||
|
||||
+7
-4
@@ -598,13 +598,16 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
|
||||
*/
|
||||
static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
|
||||
Index *pIndex, *pNext;
|
||||
TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Record the number of outstanding lookaside allocations in schema Tables
|
||||
** prior to doing any free() operations. Since schema Tables do not use
|
||||
** lookaside, this number should not change. */
|
||||
TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ?
|
||||
db->lookaside.nOut : 0 );
|
||||
int nLookaside = 0;
|
||||
if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
|
||||
nLookaside = sqlite3LookasideUsed(db, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Delete all indices associated with this table. */
|
||||
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
|
||||
@@ -638,7 +641,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
|
||||
sqlite3DbFree(db, pTable);
|
||||
|
||||
/* Verify that no lookaside memory was used by schema tables */
|
||||
assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
|
||||
assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
|
||||
}
|
||||
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
|
||||
/* Do not delete the table until the reference count reaches zero. */
|
||||
|
||||
+17
-9
@@ -1687,6 +1687,19 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a SELECT-node callback for the expression walker that
|
||||
** always "fails". By "fail" in this case, we mean set
|
||||
** pWalker->eCode to zero and abort.
|
||||
**
|
||||
** This callback is used by multiple expression walkers.
|
||||
*/
|
||||
int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
** see if they are "constant" for some definition of constant. The
|
||||
@@ -1763,21 +1776,16 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
|
||||
testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
|
||||
testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */
|
||||
testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
Walker w;
|
||||
w.eCode = initFlag;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
@@ -1900,7 +1908,7 @@ int sqlite3ExprContainsSubquery(Expr *p){
|
||||
Walker w;
|
||||
w.eCode = 1;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -865,7 +865,8 @@ static void likeFunc(
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_like_count++;
|
||||
#endif
|
||||
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
|
||||
sqlite3_result_int(context,
|
||||
patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -199,6 +199,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
SQLITE_THREADSAFE==1, /* bFullMutex */
|
||||
SQLITE_USE_URI, /* bOpenUri */
|
||||
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
|
||||
0, /* bSmallMalloc */
|
||||
0x7ffffffe, /* mxStrlen */
|
||||
0, /* neverCorrupt */
|
||||
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
|
||||
@@ -211,9 +212,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, 0, /* mnHeap, mxHeap */
|
||||
SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */
|
||||
SQLITE_MAX_MMAP_SIZE, /* mxMmap */
|
||||
(void*)0, /* pScratch */
|
||||
0, /* szScratch */
|
||||
0, /* nScratch */
|
||||
(void*)0, /* pPage */
|
||||
0, /* szPage */
|
||||
SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
|
||||
|
||||
+17
-30
@@ -436,14 +436,8 @@ int sqlite3_config(int op, ...){
|
||||
sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_SCRATCH: {
|
||||
/* EVIDENCE-OF: R-08404-60887 There are three arguments to
|
||||
** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from
|
||||
** which the scratch allocations will be drawn, the size of each scratch
|
||||
** allocation (sz), and the maximum number of scratch allocations (N). */
|
||||
sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.szScratch = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.nScratch = va_arg(ap, int);
|
||||
case SQLITE_CONFIG_SMALL_MALLOC: {
|
||||
sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PAGECACHE: {
|
||||
@@ -664,7 +658,8 @@ int sqlite3_config(int op, ...){
|
||||
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
void *pStart;
|
||||
if( db->lookaside.nOut ){
|
||||
|
||||
if( sqlite3LookasideUsed(db,0)>0 ){
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
/* Free any existing lookaside buffer for this handle before
|
||||
@@ -692,16 +687,18 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
pStart = pBuf;
|
||||
}
|
||||
db->lookaside.pStart = pStart;
|
||||
db->lookaside.pInit = 0;
|
||||
db->lookaside.pFree = 0;
|
||||
db->lookaside.sz = (u16)sz;
|
||||
if( pStart ){
|
||||
int i;
|
||||
LookasideSlot *p;
|
||||
assert( sz > (int)sizeof(LookasideSlot*) );
|
||||
db->lookaside.nSlot = cnt;
|
||||
p = (LookasideSlot*)pStart;
|
||||
for(i=cnt-1; i>=0; i--){
|
||||
p->pNext = db->lookaside.pFree;
|
||||
db->lookaside.pFree = p;
|
||||
p->pNext = db->lookaside.pInit;
|
||||
db->lookaside.pInit = p;
|
||||
p = (LookasideSlot*)&((u8*)p)[sz];
|
||||
}
|
||||
db->lookaside.pEnd = p;
|
||||
@@ -712,6 +709,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
db->lookaside.pEnd = db;
|
||||
db->lookaside.bDisable = 1;
|
||||
db->lookaside.bMalloced = 0;
|
||||
db->lookaside.nSlot = 0;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_LOOKASIDE */
|
||||
return SQLITE_OK;
|
||||
@@ -1231,7 +1229,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
db->magic = SQLITE_MAGIC_CLOSED;
|
||||
sqlite3_mutex_free(db->mutex);
|
||||
assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */
|
||||
assert( sqlite3LookasideUsed(db,0)==0 );
|
||||
if( db->lookaside.bMalloced ){
|
||||
sqlite3_free(db->lookaside.pStart);
|
||||
}
|
||||
@@ -1508,9 +1506,13 @@ static int sqliteDefaultBusyCallback(
|
||||
*/
|
||||
int sqlite3InvokeBusyHandler(BusyHandler *p){
|
||||
int rc;
|
||||
if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0;
|
||||
if( p->xFunc==0 || p->nBusy<0 ){
|
||||
p->nTimeout++;
|
||||
return 0;
|
||||
}
|
||||
rc = p->xFunc(p->pArg, p->nBusy);
|
||||
if( rc==0 ){
|
||||
p->nTimeout++;
|
||||
p->nBusy = -1;
|
||||
}else{
|
||||
p->nBusy++;
|
||||
@@ -2175,7 +2177,8 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
|
||||
** checkpointed. If an error is encountered it is returned immediately -
|
||||
** no attempt is made to checkpoint any remaining databases.
|
||||
**
|
||||
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
|
||||
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART
|
||||
** or TRUNCATE.
|
||||
*/
|
||||
int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
@@ -3802,22 +3805,6 @@ int sqlite3_test_control(int op, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree);
|
||||
**
|
||||
** Pass pFree into sqlite3ScratchFree().
|
||||
** If sz>0 then allocate a scratch buffer into pNew.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_SCRATCHMALLOC: {
|
||||
void *pFree, **ppNew;
|
||||
int sz;
|
||||
sz = va_arg(ap, int);
|
||||
ppNew = va_arg(ap, void**);
|
||||
pFree = va_arg(ap, void*);
|
||||
if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
|
||||
sqlite3ScratchFree(pFree);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
|
||||
**
|
||||
** If parameter onoff is non-zero, configure the wrappers so that all
|
||||
|
||||
+8
-148
@@ -32,14 +32,6 @@ int sqlite3_release_memory(int n){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** An instance of the following object records the location of
|
||||
** each unused scratch buffer.
|
||||
*/
|
||||
typedef struct ScratchFreeslot {
|
||||
struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
|
||||
} ScratchFreeslot;
|
||||
|
||||
/*
|
||||
** State information local to the memory allocation subsystem.
|
||||
*/
|
||||
@@ -47,22 +39,12 @@ static SQLITE_WSD struct Mem0Global {
|
||||
sqlite3_mutex *mutex; /* Mutex to serialize access */
|
||||
sqlite3_int64 alarmThreshold; /* The soft heap limit */
|
||||
|
||||
/*
|
||||
** Pointers to the end of sqlite3GlobalConfig.pScratch memory
|
||||
** (so that a range test can be used to determine if an allocation
|
||||
** being freed came from pScratch) and a pointer to the list of
|
||||
** unused scratch allocations.
|
||||
*/
|
||||
void *pScratchEnd;
|
||||
ScratchFreeslot *pScratchFree;
|
||||
u32 nScratchFree;
|
||||
|
||||
/*
|
||||
** True if heap is nearly "full" where "full" is defined by the
|
||||
** sqlite3_soft_heap_limit() setting.
|
||||
*/
|
||||
int nearlyFull;
|
||||
} mem0 = { 0, 0, 0, 0, 0, 0 };
|
||||
} mem0 = { 0, 0, 0 };
|
||||
|
||||
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
||||
|
||||
@@ -132,28 +114,6 @@ int sqlite3MallocInit(void){
|
||||
}
|
||||
memset(&mem0, 0, sizeof(mem0));
|
||||
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
||||
if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
|
||||
&& sqlite3GlobalConfig.nScratch>0 ){
|
||||
int i, n, sz;
|
||||
ScratchFreeslot *pSlot;
|
||||
sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
|
||||
sqlite3GlobalConfig.szScratch = sz;
|
||||
pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
|
||||
n = sqlite3GlobalConfig.nScratch;
|
||||
mem0.pScratchFree = pSlot;
|
||||
mem0.nScratchFree = n;
|
||||
for(i=0; i<n-1; i++){
|
||||
pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
|
||||
pSlot = pSlot->pNext;
|
||||
}
|
||||
pSlot->pNext = 0;
|
||||
mem0.pScratchEnd = (void*)&pSlot[1];
|
||||
}else{
|
||||
mem0.pScratchEnd = 0;
|
||||
sqlite3GlobalConfig.pScratch = 0;
|
||||
sqlite3GlobalConfig.szScratch = 0;
|
||||
sqlite3GlobalConfig.nScratch = 0;
|
||||
}
|
||||
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|
||||
|| sqlite3GlobalConfig.nPage<=0 ){
|
||||
sqlite3GlobalConfig.pPage = 0;
|
||||
@@ -304,105 +264,6 @@ void *sqlite3_malloc64(sqlite3_uint64 n){
|
||||
return sqlite3Malloc(n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Each thread may only have a single outstanding allocation from
|
||||
** xScratchMalloc(). We verify this constraint in the single-threaded
|
||||
** case by setting scratchAllocOut to 1 when an allocation
|
||||
** is outstanding clearing it when the allocation is freed.
|
||||
*/
|
||||
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
|
||||
static int scratchAllocOut = 0;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Allocate memory that is to be used and released right away.
|
||||
** This routine is similar to alloca() in that it is not intended
|
||||
** for situations where the memory might be held long-term. This
|
||||
** routine is intended to get memory to old large transient data
|
||||
** structures that would not normally fit on the stack of an
|
||||
** embedded processor.
|
||||
*/
|
||||
void *sqlite3ScratchMalloc(int n){
|
||||
void *p;
|
||||
assert( n>0 );
|
||||
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
mem0.nScratchFree--;
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3Malloc(n);
|
||||
if( sqlite3GlobalConfig.bMemstat && p ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
|
||||
}
|
||||
assert( sqlite3_mutex_notheld(mem0.mutex) );
|
||||
|
||||
|
||||
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
|
||||
/* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
|
||||
** buffers per thread.
|
||||
**
|
||||
** This can only be checked in single-threaded mode.
|
||||
*/
|
||||
assert( scratchAllocOut==0 );
|
||||
if( p ) scratchAllocOut++;
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
void sqlite3ScratchFree(void *p){
|
||||
if( p ){
|
||||
|
||||
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
|
||||
/* Verify that no more than two scratch allocation per thread
|
||||
** is outstanding at one time. (This is only checked in the
|
||||
** single-threaded case since checking in the multi-threaded case
|
||||
** would be much more complicated.) */
|
||||
assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
|
||||
scratchAllocOut--;
|
||||
#endif
|
||||
|
||||
if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
|
||||
/* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
|
||||
ScratchFreeslot *pSlot;
|
||||
pSlot = (ScratchFreeslot*)p;
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
pSlot->pNext = mem0.pScratchFree;
|
||||
mem0.pScratchFree = pSlot;
|
||||
mem0.nScratchFree++;
|
||||
assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
/* Release memory back to the heap */
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
int iSize = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TRUE if p is a lookaside memory allocation from db
|
||||
*/
|
||||
@@ -493,7 +354,6 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
||||
#endif
|
||||
pBuf->pNext = db->lookaside.pFree;
|
||||
db->lookaside.pFree = pBuf;
|
||||
db->lookaside.nOut--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -654,16 +514,16 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
|
||||
assert( db->mallocFailed==0 );
|
||||
if( n>db->lookaside.sz ){
|
||||
db->lookaside.anStat[1]++;
|
||||
}else if( (pBuf = db->lookaside.pFree)==0 ){
|
||||
db->lookaside.anStat[2]++;
|
||||
}else{
|
||||
}else if( (pBuf = db->lookaside.pFree)!=0 ){
|
||||
db->lookaside.pFree = pBuf->pNext;
|
||||
db->lookaside.nOut++;
|
||||
db->lookaside.anStat[0]++;
|
||||
if( db->lookaside.nOut>db->lookaside.mxOut ){
|
||||
db->lookaside.mxOut = db->lookaside.nOut;
|
||||
}
|
||||
return (void*)pBuf;
|
||||
}else if( (pBuf = db->lookaside.pInit)!=0 ){
|
||||
db->lookaside.pInit = pBuf->pNext;
|
||||
db->lookaside.anStat[0]++;
|
||||
return (void*)pBuf;
|
||||
}else{
|
||||
db->lookaside.anStat[2]++;
|
||||
}
|
||||
}else if( db->mallocFailed ){
|
||||
return 0;
|
||||
|
||||
@@ -98,7 +98,7 @@ int sqlite3OsTruncate(sqlite3_file *id, i64 size){
|
||||
}
|
||||
int sqlite3OsSync(sqlite3_file *id, int flags){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
return id->pMethods->xSync(id, flags);
|
||||
return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
|
||||
}
|
||||
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
|
||||
@@ -5696,9 +5696,6 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
||||
EntropyGatherer e;
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
memset(zBuf, 0, nBuf);
|
||||
#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE
|
||||
rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */
|
||||
#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */
|
||||
e.a = (unsigned char*)zBuf;
|
||||
e.na = nBuf;
|
||||
e.nXor = 0;
|
||||
|
||||
+46
-24
@@ -616,6 +616,18 @@ struct PagerSavepoint {
|
||||
** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
|
||||
** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
|
||||
** sub-codes.
|
||||
**
|
||||
** syncFlags, walSyncFlags
|
||||
**
|
||||
** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03).
|
||||
** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode
|
||||
** and contains the flags used to sync the checkpoint operations in the
|
||||
** lower two bits, and sync flags used for transaction commits in the WAL
|
||||
** file in bits 0x04 and 0x08. In other words, to get the correct sync flags
|
||||
** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct
|
||||
** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note
|
||||
** that with synchronous=NORMAL in WAL mode, transaction commit is not synced
|
||||
** meaning that the 0x04 and 0x08 bits are both zero.
|
||||
*/
|
||||
struct Pager {
|
||||
sqlite3_vfs *pVfs; /* OS functions to use for IO */
|
||||
@@ -625,9 +637,8 @@ struct Pager {
|
||||
u8 noSync; /* Do not sync the journal if true */
|
||||
u8 fullSync; /* Do extra syncs of the journal for robustness */
|
||||
u8 extraSync; /* sync directory after journal delete */
|
||||
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
|
||||
u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
|
||||
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
|
||||
u8 walSyncFlags; /* See description above */
|
||||
u8 tempFile; /* zFilename is a temporary or immutable file */
|
||||
u8 noLock; /* Do not lock (except in WAL mode) */
|
||||
u8 readOnly; /* True for a read-only database */
|
||||
@@ -1304,6 +1315,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|
||||
|| szJ<16
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|
||||
|| len>=nMaster
|
||||
|| len>szJ-16
|
||||
|| len==0
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|
||||
@@ -3598,20 +3610,17 @@ void sqlite3PagerSetFlags(
|
||||
}
|
||||
if( pPager->noSync ){
|
||||
pPager->syncFlags = 0;
|
||||
pPager->ckptSyncFlags = 0;
|
||||
}else if( pgFlags & PAGER_FULLFSYNC ){
|
||||
pPager->syncFlags = SQLITE_SYNC_FULL;
|
||||
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
|
||||
}else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
|
||||
pPager->syncFlags = SQLITE_SYNC_NORMAL;
|
||||
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
|
||||
}else{
|
||||
pPager->syncFlags = SQLITE_SYNC_NORMAL;
|
||||
pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
|
||||
}
|
||||
pPager->walSyncFlags = pPager->syncFlags;
|
||||
pPager->walSyncFlags = (pPager->syncFlags<<2);
|
||||
if( pPager->fullSync ){
|
||||
pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
|
||||
pPager->walSyncFlags |= pPager->syncFlags;
|
||||
}
|
||||
if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
|
||||
pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
|
||||
}
|
||||
if( pgFlags & PAGER_CACHESPILL ){
|
||||
pPager->doNotSpill &= ~SPILLFLAG_OFF;
|
||||
@@ -4110,7 +4119,7 @@ int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
|
||||
pPager->exclusiveMode = 0;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
assert( db || pPager->pWal==0 );
|
||||
sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize,
|
||||
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
|
||||
(db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
|
||||
);
|
||||
pPager->pWal = 0;
|
||||
@@ -4918,13 +4927,11 @@ act_like_temp_file:
|
||||
assert( pPager->extraSync==0 );
|
||||
assert( pPager->syncFlags==0 );
|
||||
assert( pPager->walSyncFlags==0 );
|
||||
assert( pPager->ckptSyncFlags==0 );
|
||||
}else{
|
||||
pPager->fullSync = 1;
|
||||
pPager->extraSync = 0;
|
||||
pPager->syncFlags = SQLITE_SYNC_NORMAL;
|
||||
pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
|
||||
pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
|
||||
pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2);
|
||||
}
|
||||
/* pPager->pFirst = 0; */
|
||||
/* pPager->pFirstSynced = 0; */
|
||||
@@ -5344,7 +5351,8 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
** nothing to rollback, so this routine is a no-op.
|
||||
*/
|
||||
static void pagerUnlockIfUnused(Pager *pPager){
|
||||
if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
|
||||
if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
|
||||
assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
|
||||
pagerUnlockAndRollback(pPager);
|
||||
}
|
||||
}
|
||||
@@ -5630,25 +5638,39 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
|
||||
/*
|
||||
** Release a page reference.
|
||||
**
|
||||
** If the number of references to the page drop to zero, then the
|
||||
** page is added to the LRU list. When all references to all pages
|
||||
** are released, a rollback occurs and the lock on the database is
|
||||
** removed.
|
||||
** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be
|
||||
** used if we know that the page being released is not the last page.
|
||||
** The btree layer always holds page1 open until the end, so these first
|
||||
** to routines can be used to release any page other than BtShared.pPage1.
|
||||
**
|
||||
** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine
|
||||
** checks the total number of outstanding pages and if the number of
|
||||
** pages reaches zero it drops the database lock.
|
||||
*/
|
||||
void sqlite3PagerUnrefNotNull(DbPage *pPg){
|
||||
Pager *pPager;
|
||||
TESTONLY( Pager *pPager = pPg->pPager; )
|
||||
assert( pPg!=0 );
|
||||
pPager = pPg->pPager;
|
||||
if( pPg->flags & PGHDR_MMAP ){
|
||||
assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */
|
||||
pagerReleaseMapPage(pPg);
|
||||
}else{
|
||||
sqlite3PcacheRelease(pPg);
|
||||
}
|
||||
pagerUnlockIfUnused(pPager);
|
||||
/* Do not use this routine to release the last reference to page1 */
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
|
||||
}
|
||||
void sqlite3PagerUnref(DbPage *pPg){
|
||||
if( pPg ) sqlite3PagerUnrefNotNull(pPg);
|
||||
}
|
||||
void sqlite3PagerUnrefPageOne(DbPage *pPg){
|
||||
Pager *pPager;
|
||||
assert( pPg!=0 );
|
||||
assert( pPg->pgno==1 );
|
||||
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
|
||||
pPager = pPg->pPager;
|
||||
sqlite3PcacheRelease(pPg);
|
||||
pagerUnlockIfUnused(pPager);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called at the start of every write transaction.
|
||||
@@ -7372,7 +7394,7 @@ int sqlite3PagerCheckpoint(
|
||||
rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
|
||||
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
|
||||
pPager->pBusyHandlerArg,
|
||||
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
|
||||
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
|
||||
pnLog, pnCkpt
|
||||
);
|
||||
}
|
||||
@@ -7529,7 +7551,7 @@ int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
|
||||
if( rc==SQLITE_OK && pPager->pWal ){
|
||||
rc = pagerExclusiveLock(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
|
||||
rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
|
||||
pPager->pageSize, (u8*)pPager->pTmpSpace);
|
||||
pPager->pWal = 0;
|
||||
pagerFixMaplimit(pPager);
|
||||
|
||||
@@ -151,6 +151,7 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
|
||||
void sqlite3PagerRef(DbPage*);
|
||||
void sqlite3PagerUnref(DbPage*);
|
||||
void sqlite3PagerUnrefNotNull(DbPage*);
|
||||
void sqlite3PagerUnrefPageOne(DbPage*);
|
||||
|
||||
/* Operations on page references. */
|
||||
int sqlite3PagerWrite(DbPage*);
|
||||
|
||||
+2
-9
@@ -191,12 +191,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
||||
p->eCreate = 2;
|
||||
}
|
||||
}
|
||||
pPage->pDirtyNext = 0;
|
||||
pPage->pDirtyPrev = 0;
|
||||
}
|
||||
if( addRemove & PCACHE_DIRTYLIST_ADD ){
|
||||
assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
|
||||
|
||||
pPage->pDirtyPrev = 0;
|
||||
pPage->pDirtyNext = p->pDirty;
|
||||
if( pPage->pDirtyNext ){
|
||||
assert( pPage->pDirtyNext->pDirtyPrev==0 );
|
||||
@@ -513,11 +510,7 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
|
||||
if( (--p->nRef)==0 ){
|
||||
if( p->flags&PGHDR_CLEAN ){
|
||||
pcacheUnpin(p);
|
||||
}else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* Move the page to the head of the dirty list. If p->pDirtyPrev==0,
|
||||
** then page p is already at the head of the dirty list and the
|
||||
** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE
|
||||
** tag above. */
|
||||
}else{
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ struct PgHdr {
|
||||
i16 nRef; /* Number of users of this page */
|
||||
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
|
||||
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
|
||||
/* NB: pDirtyNext and pDirtyPrev are undefined if the
|
||||
** PgHdr object is not dirty */
|
||||
};
|
||||
|
||||
/* Bit values for PgHdr.flags */
|
||||
|
||||
+15
-12
@@ -137,7 +137,7 @@ struct PGroup {
|
||||
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
|
||||
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
|
||||
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
|
||||
unsigned int nCurrentPage; /* Number of purgeable pages allocated */
|
||||
unsigned int nPurgeable; /* Number of purgeable pages allocated */
|
||||
PgHdr1 lru; /* The beginning and end of the LRU list */
|
||||
};
|
||||
|
||||
@@ -151,11 +151,13 @@ struct PGroup {
|
||||
*/
|
||||
struct PCache1 {
|
||||
/* Cache configuration parameters. Page size (szPage) and the purgeable
|
||||
** flag (bPurgeable) are set when the cache is created. nMax may be
|
||||
** flag (bPurgeable) and the pnPurgeable pointer are all set when the
|
||||
** cache is created and are never changed thereafter. nMax may be
|
||||
** modified at any time by a call to the pcache1Cachesize() method.
|
||||
** The PGroup mutex must be held when accessing nMax.
|
||||
*/
|
||||
PGroup *pGroup; /* PGroup this cache belongs to */
|
||||
unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
|
||||
int szPage; /* Size of database content section */
|
||||
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
|
||||
int szAlloc; /* Total size of one pcache line */
|
||||
@@ -250,6 +252,7 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
||||
if( pcache1.isInit ){
|
||||
PgFreeslot *p;
|
||||
if( pBuf==0 ) sz = n = 0;
|
||||
if( n==0 ) sz = 0;
|
||||
sz = ROUNDDOWN8(sz);
|
||||
pcache1.szSlot = sz;
|
||||
pcache1.nSlot = pcache1.nFreeSlot = n;
|
||||
@@ -442,9 +445,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
|
||||
p->isBulkLocal = 0;
|
||||
p->isAnchor = 0;
|
||||
}
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage++;
|
||||
}
|
||||
(*pCache->pnPurgeable)++;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -465,9 +466,7 @@ static void pcache1FreePage(PgHdr1 *p){
|
||||
sqlite3_free(p);
|
||||
#endif
|
||||
}
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage--;
|
||||
}
|
||||
(*pCache->pnPurgeable)--;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -607,7 +606,7 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
|
||||
PGroup *pGroup = pCache->pGroup;
|
||||
PgHdr1 *p;
|
||||
assert( sqlite3_mutex_held(pGroup->mutex) );
|
||||
while( pGroup->nCurrentPage>pGroup->nMaxPage
|
||||
while( pGroup->nPurgeable>pGroup->nMaxPage
|
||||
&& (p=pGroup->lru.pLruPrev)->isAnchor==0
|
||||
){
|
||||
assert( p->pCache->pGroup==pGroup );
|
||||
@@ -778,6 +777,10 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
pCache->nMin = 10;
|
||||
pGroup->nMinPage += pCache->nMin;
|
||||
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
||||
pCache->pnPurgeable = &pGroup->nPurgeable;
|
||||
}else{
|
||||
static unsigned int dummyCurrentPage;
|
||||
pCache->pnPurgeable = &dummyCurrentPage;
|
||||
}
|
||||
pcache1LeaveMutex(pGroup);
|
||||
if( pCache->nHash==0 ){
|
||||
@@ -887,7 +890,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
pcache1FreePage(pPage);
|
||||
pPage = 0;
|
||||
}else{
|
||||
pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
|
||||
pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,7 +1071,7 @@ static void pcache1Unpin(
|
||||
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
|
||||
assert( PAGE_IS_PINNED(pPage) );
|
||||
|
||||
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
|
||||
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
|
||||
pcache1RemoveFromHash(pPage, 1);
|
||||
}else{
|
||||
/* Add the page to the PGroup LRU list. */
|
||||
@@ -1247,7 +1250,7 @@ void sqlite3PcacheStats(
|
||||
assert( PAGE_IS_UNPINNED(p) );
|
||||
nRecyclable++;
|
||||
}
|
||||
*pnCurrent = pcache1.grp.nCurrentPage;
|
||||
*pnCurrent = pcache1.grp.nPurgeable;
|
||||
*pnMax = (int)pcache1.grp.nMaxPage;
|
||||
*pnMin = (int)pcache1.grp.nMinPage;
|
||||
*pnRecyclable = nRecyclable;
|
||||
|
||||
+78
-75
@@ -298,16 +298,16 @@ static const PragmaName *pragmaLocate(const char *zName){
|
||||
/*
|
||||
** Helper subroutine for PRAGMA integrity_check:
|
||||
**
|
||||
** Generate code to output a single-column result row with the result
|
||||
** held in register regResult. Decrement the result count and halt if
|
||||
** the maximum number of result rows have been issued.
|
||||
** Generate code to output a single-column result row with a value of the
|
||||
** string held in register 3. Decrement the result count in register 1
|
||||
** and halt if the maximum number of result rows have been issued.
|
||||
*/
|
||||
static int integrityCheckResultRow(Vdbe *v, int regResult){
|
||||
static int integrityCheckResultRow(Vdbe *v){
|
||||
int addr;
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1234,13 +1234,11 @@ void sqlite3Pragma(
|
||||
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
||||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
|
||||
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
|
||||
}
|
||||
}
|
||||
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
|
||||
p = (FuncDef*)sqliteHashData(j);
|
||||
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1252,7 +1250,6 @@ void sqlite3Pragma(
|
||||
for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){
|
||||
Module *pMod = (Module*)sqliteHashData(j);
|
||||
sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1262,7 +1259,6 @@ void sqlite3Pragma(
|
||||
int i;
|
||||
for(i=0; i<ArraySize(aPragmaName); i++){
|
||||
sqlite3VdbeMultiLoad(v, 1, "s", aPragmaName[i].zName);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1488,12 +1484,11 @@ void sqlite3Pragma(
|
||||
|
||||
/* Do an integrity check on each database file */
|
||||
for(i=0; i<db->nDb; i++){
|
||||
HashElem *x;
|
||||
Hash *pTbls;
|
||||
int *aRoot;
|
||||
int cnt = 0;
|
||||
int mxIdx = 0;
|
||||
int nIdx;
|
||||
HashElem *x; /* For looping over tables in the schema */
|
||||
Hash *pTbls; /* Set of all tables in the schema */
|
||||
int *aRoot; /* Array of root page numbers of all btrees */
|
||||
int cnt = 0; /* Number of entries in aRoot[] */
|
||||
int mxIdx = 0; /* Maximum number of indexes for any table */
|
||||
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
if( iDb>=0 && i!=iDb ) continue;
|
||||
@@ -1508,8 +1503,9 @@ void sqlite3Pragma(
|
||||
assert( sqlite3SchemaMutexHeld(db, i, 0) );
|
||||
pTbls = &db->aDb[i].pSchema->tblHash;
|
||||
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
Table *pTab = sqliteHashData(x); /* Current table */
|
||||
Index *pIdx; /* An index on pTab */
|
||||
int nIdx; /* Number of indexes on pTab */
|
||||
if( HasRowid(pTab) ) cnt++;
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
|
||||
if( nIdx>mxIdx ) mxIdx = nIdx;
|
||||
@@ -1537,9 +1533,8 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
|
||||
P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
|
||||
integrityCheckResultRow(v, 2);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
@@ -1553,16 +1548,13 @@ void sqlite3Pragma(
|
||||
int r1 = -1;
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
if( pTab->pCheck==0
|
||||
&& (pTab->tabFlags & TF_HasNotNull)==0
|
||||
&& (pTab->pIndex==0 || isQuick)
|
||||
){
|
||||
continue; /* No additional checks needed for this table */
|
||||
}
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
/* reg[7] counts the number of entries in the table.
|
||||
** reg[8+i] counts the number of entries in the i-th index
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
|
||||
@@ -1583,7 +1575,7 @@ void sqlite3Pragma(
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pTab->aCol[j].zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
}
|
||||
/* Verify CHECK constraints */
|
||||
@@ -1606,57 +1598,62 @@ void sqlite3Pragma(
|
||||
zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
|
||||
pTab->zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeResolveLabel(v, addrCkOk);
|
||||
sqlite3ExprCachePop(pParse);
|
||||
}
|
||||
sqlite3ExprListDelete(db, pCheck);
|
||||
}
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
int ckUniq = sqlite3VdbeMakeLabel(v);
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
pPrior, r1);
|
||||
pPrior = pIdx;
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
|
||||
/* Verify that an index entry exists for the current table row */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
|
||||
pIdx->nColumn); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "row ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
|
||||
sqlite3VdbeLoadString(v, 4, " missing from index ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp4 = integrityCheckResultRow(v, 3);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
/* For UNIQUE indexes, verify that only one entry exists with the
|
||||
** current key. The entry is unique if (1) any column is NULL
|
||||
** or (2) the next entry has a different key */
|
||||
if( IsUniqueIndex(pIdx) ){
|
||||
int uniqOk = sqlite3VdbeMakeLabel(v);
|
||||
int jmp6;
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
|
||||
VdbeCoverage(v);
|
||||
if( !isQuick ){ /* Omit the remaining tests for quick_check */
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
int ckUniq = sqlite3VdbeMakeLabel(v);
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
pPrior, r1);
|
||||
pPrior = pIdx;
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
|
||||
/* Verify that an index entry exists for the current table row */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
|
||||
pIdx->nColumn); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "row ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
|
||||
sqlite3VdbeLoadString(v, 4, " missing from index ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp4 = integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
/* For UNIQUE indexes, verify that only one entry exists with the
|
||||
** current key. The entry is unique if (1) any column is NULL
|
||||
** or (2) the next entry has a different key */
|
||||
if( IsUniqueIndex(pIdx) ){
|
||||
int uniqOk = sqlite3VdbeMakeLabel(v);
|
||||
int jmp6;
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp6);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
|
||||
pIdx->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
|
||||
sqlite3VdbeGoto(v, jmp5);
|
||||
sqlite3VdbeResolveLabel(v, uniqOk);
|
||||
}
|
||||
jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp6);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
|
||||
pIdx->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
|
||||
sqlite3VdbeGoto(v, jmp5);
|
||||
sqlite3VdbeResolveLabel(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp4);
|
||||
sqlite3ResolvePartIdxLabel(pParse, jmp3);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, jmp4);
|
||||
sqlite3ResolvePartIdxLabel(pParse, jmp3);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, loopTop-1);
|
||||
@@ -1668,9 +1665,9 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
sqlite3VdbeLoadString(v, 3, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
|
||||
integrityCheckResultRow(v, 7);
|
||||
sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
@@ -1684,6 +1681,9 @@ void sqlite3Pragma(
|
||||
{ OP_IfNotZero, 1, 4, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0}, /* 3 */
|
||||
{ OP_Halt, 0, 0, 0}, /* 4 */
|
||||
{ OP_String8, 0, 3, 0}, /* 5 */
|
||||
{ OP_Goto, 0, 3, 0}, /* 6 */
|
||||
};
|
||||
VdbeOp *aOp;
|
||||
|
||||
@@ -1692,7 +1692,10 @@ void sqlite3Pragma(
|
||||
aOp[0].p2 = 1-mxErr;
|
||||
aOp[2].p4type = P4_STATIC;
|
||||
aOp[2].p4.z = "ok";
|
||||
aOp[5].p4type = P4_STATIC;
|
||||
aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
|
||||
}
|
||||
sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+26
-33
@@ -150,6 +150,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
||||
|
||||
db->init.busy = 1;
|
||||
|
||||
/* Construct the in-memory representation schema tables (sqlite_master or
|
||||
** sqlite_temp_master) by invoking the parser directly. The appropriate
|
||||
** table name will be inserted automatically by the parser so we can just
|
||||
@@ -158,7 +160,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
|
||||
azArg[1] = "1";
|
||||
azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
|
||||
"rootpage integer,sql text)";
|
||||
"rootpage int,sql text)";
|
||||
azArg[3] = 0;
|
||||
initData.db = db;
|
||||
initData.iDb = iDb;
|
||||
@@ -174,10 +176,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
*/
|
||||
pDb = &db->aDb[iDb];
|
||||
if( pDb->pBt==0 ){
|
||||
if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
|
||||
DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
assert( iDb==1 );
|
||||
DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
rc = SQLITE_OK;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* If there is not already a read-only (or read-write) transaction opened
|
||||
@@ -336,9 +338,13 @@ initone_error_out:
|
||||
sqlite3BtreeLeave(pDb->pBt);
|
||||
|
||||
error_out:
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
if( rc ){
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
}
|
||||
sqlite3ResetOneSchema(db, iDb);
|
||||
}
|
||||
db->init.busy = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -359,37 +365,24 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
|
||||
assert( db->init.busy==0 );
|
||||
rc = SQLITE_OK;
|
||||
db->init.busy = 1;
|
||||
ENC(db) = SCHEMA_ENC(db);
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetOneSchema(db, i);
|
||||
assert( db->nDb>0 );
|
||||
/* Do the main schema first */
|
||||
if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 0, pzErrMsg);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
/* All other schemas after the main schema. The "temp" schema must be last */
|
||||
for(i=db->nDb-1; i>0; i--){
|
||||
if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Once all the other databases have been initialized, load the schema
|
||||
** for the TEMP database. This is loaded last, as the TEMP database
|
||||
** schema may contain references to objects in other databases.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
assert( db->nDb>1 );
|
||||
if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 1, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetOneSchema(db, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
db->init.busy = 0;
|
||||
if( rc==SQLITE_OK && commit_internal ){
|
||||
if( commit_internal ){
|
||||
sqlite3CommitInternalChanges(db);
|
||||
}
|
||||
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+28
-40
@@ -1499,7 +1499,7 @@ static void sha3QueryFunc(
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
|
||||
#endif
|
||||
int sqlite3_shathree_init(
|
||||
sqlite3 *db,
|
||||
@@ -1611,7 +1611,7 @@ static void writefileFunc(
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
|
||||
#endif
|
||||
int sqlite3_fileio_init(
|
||||
sqlite3 *db,
|
||||
@@ -2139,7 +2139,7 @@ int sqlite3CompletionVtabInit(sqlite3 *db){
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
|
||||
#endif
|
||||
int sqlite3_completion_init(
|
||||
sqlite3 *db,
|
||||
@@ -2231,14 +2231,13 @@ struct ShellState {
|
||||
/*
|
||||
** These are the allowed shellFlgs values
|
||||
*/
|
||||
#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */
|
||||
#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */
|
||||
#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */
|
||||
#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */
|
||||
#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */
|
||||
#define SHFLG_Newlines 0x00000020 /* .dump --newline flag */
|
||||
#define SHFLG_CountChanges 0x00000040 /* .changes setting */
|
||||
#define SHFLG_Echo 0x00000080 /* .echo or --echo setting */
|
||||
#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
|
||||
#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
|
||||
#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
|
||||
#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
|
||||
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
|
||||
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
|
||||
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
|
||||
|
||||
/*
|
||||
** Macros for testing and setting shellFlgs
|
||||
@@ -2659,6 +2658,7 @@ static int shell_callback(
|
||||
int i;
|
||||
ShellState *p = (ShellState*)pArg;
|
||||
|
||||
if( azArg==0 ) return 0;
|
||||
switch( p->cMode ){
|
||||
case MODE_Line: {
|
||||
int w = 5;
|
||||
@@ -3009,6 +3009,7 @@ static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
|
||||
ShellText *p = (ShellText*)pArg;
|
||||
int i;
|
||||
UNUSED_PARAMETER(az);
|
||||
if( azArg==0 ) return 0;
|
||||
if( p->n ) appendText(p, "|", 0);
|
||||
for(i=0; i<nArg; i++){
|
||||
if( i ) appendText(p, ",", 0);
|
||||
@@ -3073,7 +3074,7 @@ static void createSelftestTable(ShellState *p){
|
||||
*/
|
||||
static void set_table_name(ShellState *p, const char *zName){
|
||||
int i, n;
|
||||
int cQuote;
|
||||
char cQuote;
|
||||
char *z;
|
||||
|
||||
if( p->zDestTable ){
|
||||
@@ -3255,18 +3256,10 @@ static int display_stats(
|
||||
}
|
||||
displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
|
||||
if( pArg->shellFlgs & SHFLG_Scratch ){
|
||||
displayStatLine(pArg, "Number of Scratch Allocations Used:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset);
|
||||
}
|
||||
displayStatLine(pArg, "Number of Scratch Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset);
|
||||
displayStatLine(pArg, "Largest Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Pcache Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Scratch Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
displayStatLine(pArg, "Deepest Parser Stack:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
|
||||
@@ -3624,7 +3617,7 @@ static int shell_exec(
|
||||
){
|
||||
sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
int rc2;
|
||||
int rc2, rc3;
|
||||
const char *zLeftover; /* Tail of unprocessed SQL */
|
||||
|
||||
if( pzErrMsg ){
|
||||
@@ -3725,13 +3718,23 @@ static int shell_exec(
|
||||
/* Finalize the statement just executed. If this fails, save a
|
||||
** copy of the error message. Otherwise, set zSql to point to the
|
||||
** next statement to execute. */
|
||||
rc3 = sqlite3_stmt_retryable(pStmt);
|
||||
rc2 = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_NOMEM ) rc = rc2;
|
||||
if( rc==SQLITE_OK ){
|
||||
zSql = zLeftover;
|
||||
while( IsSpace(zSql[0]) ) zSql++;
|
||||
}else if( pzErrMsg ){
|
||||
*pzErrMsg = save_err_msg(db);
|
||||
}else{
|
||||
if( rc==SQLITE_BUSY ){
|
||||
if( rc3 ){
|
||||
raw_printf(pArg->out, "Busy: might succeed on retry\n");
|
||||
}else{
|
||||
raw_printf(pArg->out, "Busy: cannot succeed - rollback required\n");
|
||||
}
|
||||
}
|
||||
if( pzErrMsg ){
|
||||
*pzErrMsg = save_err_msg(db);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear saved stmt handle */
|
||||
@@ -3890,7 +3893,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
||||
ShellState *p = (ShellState *)pArg;
|
||||
|
||||
UNUSED_PARAMETER(azNotUsed);
|
||||
if( nArg!=3 ) return 1;
|
||||
if( nArg!=3 || azArg==0 ) return 0;
|
||||
zTable = azArg[0];
|
||||
zType = azArg[1];
|
||||
zSql = azArg[2];
|
||||
@@ -7287,7 +7290,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "reserve", SQLITE_TESTCTRL_RESERVE },
|
||||
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
|
||||
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
|
||||
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
|
||||
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
|
||||
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
|
||||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
|
||||
@@ -7400,7 +7402,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_BITVEC_TEST:
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL:
|
||||
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
|
||||
case SQLITE_TESTCTRL_SCRATCHMALLOC:
|
||||
default:
|
||||
utf8_printf(stderr,
|
||||
"Error: CLI support for testctrl %s not implemented\n",
|
||||
@@ -7920,7 +7921,6 @@ static const char zOptions[] =
|
||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
|
||||
" -quote set output mode to 'quote'\n"
|
||||
" -scratch SIZE N use N slots of SZ bytes each for scratch memory\n"
|
||||
" -separator SEP set output column separator. Default: '|'\n"
|
||||
" -stats print memory stats before each finalize\n"
|
||||
" -version show SQLite version\n"
|
||||
@@ -8023,7 +8023,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdout_is_console = isatty(1);
|
||||
|
||||
#if USE_SYSTEM_SQLITE+0!=1
|
||||
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
|
||||
if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
|
||||
utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
|
||||
sqlite3_sourceid(), SQLITE_SOURCE_ID);
|
||||
exit(1);
|
||||
@@ -8118,16 +8118,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#else
|
||||
(void)cmdline_option_value(argc, argv, ++i);
|
||||
#endif
|
||||
}else if( strcmp(z,"-scratch")==0 ){
|
||||
int n, sz;
|
||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( sz>400000 ) sz = 400000;
|
||||
if( sz<2500 ) sz = 2500;
|
||||
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( n>10 ) n = 10;
|
||||
if( n<1 ) n = 1;
|
||||
sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
|
||||
data.shellFlgs |= SHFLG_Scratch;
|
||||
}else if( strcmp(z,"-pagecache")==0 ){
|
||||
int n, sz;
|
||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
@@ -8271,8 +8261,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdin_is_interactive = 0;
|
||||
}else if( strcmp(z,"-heap")==0 ){
|
||||
i++;
|
||||
}else if( strcmp(z,"-scratch")==0 ){
|
||||
i+=2;
|
||||
}else if( strcmp(z,"-pagecache")==0 ){
|
||||
i+=2;
|
||||
}else if( strcmp(z,"-lookaside")==0 ){
|
||||
|
||||
+25
-37
@@ -871,14 +871,13 @@ struct ShellState {
|
||||
/*
|
||||
** These are the allowed shellFlgs values
|
||||
*/
|
||||
#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */
|
||||
#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */
|
||||
#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */
|
||||
#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */
|
||||
#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */
|
||||
#define SHFLG_Newlines 0x00000020 /* .dump --newline flag */
|
||||
#define SHFLG_CountChanges 0x00000040 /* .changes setting */
|
||||
#define SHFLG_Echo 0x00000080 /* .echo or --echo setting */
|
||||
#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
|
||||
#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
|
||||
#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
|
||||
#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
|
||||
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
|
||||
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
|
||||
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
|
||||
|
||||
/*
|
||||
** Macros for testing and setting shellFlgs
|
||||
@@ -1299,6 +1298,7 @@ static int shell_callback(
|
||||
int i;
|
||||
ShellState *p = (ShellState*)pArg;
|
||||
|
||||
if( azArg==0 ) return 0;
|
||||
switch( p->cMode ){
|
||||
case MODE_Line: {
|
||||
int w = 5;
|
||||
@@ -1649,6 +1649,7 @@ static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
|
||||
ShellText *p = (ShellText*)pArg;
|
||||
int i;
|
||||
UNUSED_PARAMETER(az);
|
||||
if( azArg==0 ) return 0;
|
||||
if( p->n ) appendText(p, "|", 0);
|
||||
for(i=0; i<nArg; i++){
|
||||
if( i ) appendText(p, ",", 0);
|
||||
@@ -1713,7 +1714,7 @@ static void createSelftestTable(ShellState *p){
|
||||
*/
|
||||
static void set_table_name(ShellState *p, const char *zName){
|
||||
int i, n;
|
||||
int cQuote;
|
||||
char cQuote;
|
||||
char *z;
|
||||
|
||||
if( p->zDestTable ){
|
||||
@@ -1895,18 +1896,10 @@ static int display_stats(
|
||||
}
|
||||
displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
|
||||
if( pArg->shellFlgs & SHFLG_Scratch ){
|
||||
displayStatLine(pArg, "Number of Scratch Allocations Used:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset);
|
||||
}
|
||||
displayStatLine(pArg, "Number of Scratch Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset);
|
||||
displayStatLine(pArg, "Largest Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Pcache Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Scratch Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
displayStatLine(pArg, "Deepest Parser Stack:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
|
||||
@@ -2264,7 +2257,7 @@ static int shell_exec(
|
||||
){
|
||||
sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
int rc2;
|
||||
int rc2, rc3;
|
||||
const char *zLeftover; /* Tail of unprocessed SQL */
|
||||
|
||||
if( pzErrMsg ){
|
||||
@@ -2365,13 +2358,23 @@ static int shell_exec(
|
||||
/* Finalize the statement just executed. If this fails, save a
|
||||
** copy of the error message. Otherwise, set zSql to point to the
|
||||
** next statement to execute. */
|
||||
rc3 = sqlite3_stmt_retryable(pStmt);
|
||||
rc2 = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_NOMEM ) rc = rc2;
|
||||
if( rc==SQLITE_OK ){
|
||||
zSql = zLeftover;
|
||||
while( IsSpace(zSql[0]) ) zSql++;
|
||||
}else if( pzErrMsg ){
|
||||
*pzErrMsg = save_err_msg(db);
|
||||
}else{
|
||||
if( rc==SQLITE_BUSY ){
|
||||
if( rc3 ){
|
||||
raw_printf(pArg->out, "Busy: might succeed on retry\n");
|
||||
}else{
|
||||
raw_printf(pArg->out, "Busy: cannot succeed - rollback required\n");
|
||||
}
|
||||
}
|
||||
if( pzErrMsg ){
|
||||
*pzErrMsg = save_err_msg(db);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear saved stmt handle */
|
||||
@@ -2530,7 +2533,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
||||
ShellState *p = (ShellState *)pArg;
|
||||
|
||||
UNUSED_PARAMETER(azNotUsed);
|
||||
if( nArg!=3 ) return 1;
|
||||
if( nArg!=3 || azArg==0 ) return 0;
|
||||
zTable = azArg[0];
|
||||
zType = azArg[1];
|
||||
zSql = azArg[2];
|
||||
@@ -5927,7 +5930,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "reserve", SQLITE_TESTCTRL_RESERVE },
|
||||
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
|
||||
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
|
||||
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
|
||||
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
|
||||
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
|
||||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
|
||||
@@ -6040,7 +6042,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_BITVEC_TEST:
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL:
|
||||
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
|
||||
case SQLITE_TESTCTRL_SCRATCHMALLOC:
|
||||
default:
|
||||
utf8_printf(stderr,
|
||||
"Error: CLI support for testctrl %s not implemented\n",
|
||||
@@ -6560,7 +6561,6 @@ static const char zOptions[] =
|
||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
|
||||
" -quote set output mode to 'quote'\n"
|
||||
" -scratch SIZE N use N slots of SZ bytes each for scratch memory\n"
|
||||
" -separator SEP set output column separator. Default: '|'\n"
|
||||
" -stats print memory stats before each finalize\n"
|
||||
" -version show SQLite version\n"
|
||||
@@ -6663,7 +6663,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdout_is_console = isatty(1);
|
||||
|
||||
#if USE_SYSTEM_SQLITE+0!=1
|
||||
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
|
||||
if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
|
||||
utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
|
||||
sqlite3_sourceid(), SQLITE_SOURCE_ID);
|
||||
exit(1);
|
||||
@@ -6758,16 +6758,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#else
|
||||
(void)cmdline_option_value(argc, argv, ++i);
|
||||
#endif
|
||||
}else if( strcmp(z,"-scratch")==0 ){
|
||||
int n, sz;
|
||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( sz>400000 ) sz = 400000;
|
||||
if( sz<2500 ) sz = 2500;
|
||||
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( n>10 ) n = 10;
|
||||
if( n<1 ) n = 1;
|
||||
sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
|
||||
data.shellFlgs |= SHFLG_Scratch;
|
||||
}else if( strcmp(z,"-pagecache")==0 ){
|
||||
int n, sz;
|
||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
@@ -6911,8 +6901,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdin_is_interactive = 0;
|
||||
}else if( strcmp(z,"-heap")==0 ){
|
||||
i++;
|
||||
}else if( strcmp(z,"-scratch")==0 ){
|
||||
i+=2;
|
||||
}else if( strcmp(z,"-pagecache")==0 ){
|
||||
i+=2;
|
||||
}else if( strcmp(z,"-lookaside")==0 ){
|
||||
|
||||
+63
-65
@@ -115,7 +115,9 @@ extern "C" {
|
||||
** a string which identifies a particular check-in of SQLite
|
||||
** within its configuration management system. ^The SQLITE_SOURCE_ID
|
||||
** string contains the date and time of the check-in (UTC) and a SHA1
|
||||
** or SHA3-256 hash of the entire source tree.
|
||||
** or SHA3-256 hash of the entire source tree. If the source code has
|
||||
** been edited in any way since it was last checked in, then the last
|
||||
** four hexadecimal digits of the hash may be modified.
|
||||
**
|
||||
** See also: [sqlite3_libversion()],
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
@@ -139,7 +141,7 @@ extern "C" {
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
|
||||
** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
|
||||
** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
|
||||
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
|
||||
** </pre></blockquote>)^
|
||||
**
|
||||
@@ -149,9 +151,11 @@ extern "C" {
|
||||
** function is provided for use in DLLs since DLL users usually do not have
|
||||
** direct access to string constants within the DLL. ^The
|
||||
** sqlite3_libversion_number() function returns an integer equal to
|
||||
** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
|
||||
** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns
|
||||
** a pointer to a string constant whose value is the same as the
|
||||
** [SQLITE_SOURCE_ID] C preprocessor macro.
|
||||
** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built
|
||||
** using an edited copy of [the amalgamation], then the last four characters
|
||||
** of the hash might be different from [SQLITE_SOURCE_ID].)^
|
||||
**
|
||||
** See also: [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
@@ -1660,6 +1664,16 @@ struct sqlite3_mem_methods {
|
||||
** routines with a wrapper that simulations memory allocation failure or
|
||||
** tracks memory usage, for example. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
|
||||
** type int, interpreted as a boolean, which if true provides a hint to
|
||||
** SQLite that it should avoid large memory allocations if possible.
|
||||
** SQLite will run faster if it is free to make large memory allocations,
|
||||
** but some application might prefer to run slower in exchange for
|
||||
** guarantees about memory fragmentation that are possible if large
|
||||
** allocations are avoided. This hint is normally off.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
|
||||
** interpreted as a boolean, which enables or disables the collection of
|
||||
@@ -1677,25 +1691,7 @@ struct sqlite3_mem_methods {
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer
|
||||
** that SQLite can use for scratch memory. ^(There are three arguments
|
||||
** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte
|
||||
** aligned memory buffer from which the scratch allocations will be
|
||||
** drawn, the size of each scratch allocation (sz),
|
||||
** and the maximum number of scratch allocations (N).)^
|
||||
** The first argument must be a pointer to an 8-byte aligned buffer
|
||||
** of at least sz*N bytes of memory.
|
||||
** ^SQLite will not use more than one scratch buffers per thread.
|
||||
** ^SQLite will never request a scratch buffer that is more than 6
|
||||
** times the database page size.
|
||||
** ^If SQLite needs needs additional
|
||||
** scratch memory beyond what is provided by this configuration option, then
|
||||
** [sqlite3_malloc()] will be used to obtain the memory needed.<p>
|
||||
** ^When the application provides any amount of scratch memory using
|
||||
** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large
|
||||
** [sqlite3_malloc|heap allocations].
|
||||
** This can help [Robson proof|prevent memory allocation failures] due to heap
|
||||
** fragmentation in low-memory embedded systems.
|
||||
** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
@@ -1731,8 +1727,7 @@ struct sqlite3_mem_methods {
|
||||
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
||||
** that SQLite will use for all of its dynamic memory allocation needs
|
||||
** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and
|
||||
** [SQLITE_CONFIG_PAGECACHE].
|
||||
** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
|
||||
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
|
||||
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
|
||||
** [SQLITE_ERROR] if invoked otherwise.
|
||||
@@ -1925,7 +1920,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
|
||||
#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
|
||||
#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
|
||||
#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
|
||||
#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
|
||||
#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
|
||||
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
|
||||
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
|
||||
@@ -1946,6 +1941,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
|
||||
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
|
||||
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
|
||||
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -3146,10 +3142,10 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** ^If [URI filename] interpretation is enabled, and the filename argument
|
||||
** begins with "file:", then the filename is interpreted as a URI. ^URI
|
||||
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
|
||||
** set in the fourth argument to sqlite3_open_v2(), or if it has
|
||||
** set in the third argument to sqlite3_open_v2(), or if it has
|
||||
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
|
||||
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
|
||||
** As of SQLite version 3.7.7, URI filename interpretation is turned off
|
||||
** URI filename interpretation is turned off
|
||||
** by default, but future releases of SQLite might enable URI filename
|
||||
** interpretation by default. See "[URI filenames]" for additional
|
||||
** information.
|
||||
@@ -3768,6 +3764,18 @@ char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
|
||||
*/
|
||||
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If An SQL Statement Can Be Retried After SQLITE_BUSY
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_stmt_retryable(X) interface returns true (non-zero) if
|
||||
** the previous run of [prepared statement] X failed with an
|
||||
** [SQLITE_BUSY] error but might succeed if run again. If X has not been
|
||||
** previously run or if the previous run of X did not return SQLITE_BUSY,
|
||||
** then the result of this function is a meaningless boolean.
|
||||
*/
|
||||
int sqlite3_stmt_retryable(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
@@ -3823,8 +3831,9 @@ int sqlite3_stmt_busy(sqlite3_stmt*);
|
||||
** implementation of [application-defined SQL functions] are protected.
|
||||
** ^The sqlite3_value object returned by
|
||||
** [sqlite3_column_value()] is unprotected.
|
||||
** Unprotected sqlite3_value objects may only be used with
|
||||
** [sqlite3_result_value()] and [sqlite3_bind_value()].
|
||||
** Unprotected sqlite3_value objects may only be used as arguments
|
||||
** to [sqlite3_result_value()], [sqlite3_bind_value()], and
|
||||
** [sqlite3_value_dup()].
|
||||
** The [sqlite3_value_blob | sqlite3_value_type()] family of
|
||||
** interfaces require protected sqlite3_value objects.
|
||||
*/
|
||||
@@ -6250,15 +6259,20 @@ struct sqlite3_index_info {
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
@@ -7010,7 +7024,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
|
||||
@@ -7069,8 +7083,7 @@ int sqlite3_status64(
|
||||
** <dd>This parameter is the current amount of memory checked out
|
||||
** using [sqlite3_malloc()], either directly or indirectly. The
|
||||
** figure includes calls made to [sqlite3_malloc()] by the application
|
||||
** and internal memory usage by the SQLite library. Scratch memory
|
||||
** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
|
||||
** and internal memory usage by the SQLite library. Auxiliary page-cache
|
||||
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
|
||||
** this parameter. The amount returned is the sum of the allocation
|
||||
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
|
||||
@@ -7108,29 +7121,14 @@ int sqlite3_status64(
|
||||
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
|
||||
** <dd>This parameter returns the number of allocations used out of the
|
||||
** [scratch memory allocator] configured using
|
||||
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
|
||||
** in bytes. Since a single thread may only have one scratch allocation
|
||||
** outstanding at time, this parameter also reports the number of threads
|
||||
** using scratch memory at the same time.</dd>)^
|
||||
** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
|
||||
** <dd>No longer used.</dd>
|
||||
**
|
||||
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
|
||||
** <dd>This parameter returns the number of bytes of scratch memory
|
||||
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
|
||||
** buffer and where forced to overflow to [sqlite3_malloc()]. The values
|
||||
** returned include overflows because the requested allocation was too
|
||||
** larger (that is, because the requested allocation was larger than the
|
||||
** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
|
||||
** slots were available.
|
||||
** </dd>)^
|
||||
** <dd>No longer used.</dd>
|
||||
**
|
||||
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
|
||||
** <dd>This parameter records the largest memory allocation request
|
||||
** handed to [scratch memory allocator]. Only the value returned in the
|
||||
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
|
||||
** <dd>No longer used.</dd>
|
||||
**
|
||||
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
||||
** <dd>The *pHighwater parameter records the deepest parser stack.
|
||||
@@ -7143,12 +7141,12 @@ int sqlite3_status64(
|
||||
#define SQLITE_STATUS_MEMORY_USED 0
|
||||
#define SQLITE_STATUS_PAGECACHE_USED 1
|
||||
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
|
||||
#define SQLITE_STATUS_SCRATCH_USED 3
|
||||
#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
|
||||
#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */
|
||||
#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */
|
||||
#define SQLITE_STATUS_MALLOC_SIZE 5
|
||||
#define SQLITE_STATUS_PARSER_STACK 6
|
||||
#define SQLITE_STATUS_PAGECACHE_SIZE 7
|
||||
#define SQLITE_STATUS_SCRATCH_SIZE 8
|
||||
#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */
|
||||
#define SQLITE_STATUS_MALLOC_COUNT 9
|
||||
|
||||
/*
|
||||
|
||||
+8
-18
@@ -50,14 +50,6 @@
|
||||
# define SQLITE_TCLAPI
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make sure that rand_s() is available on Windows systems with MSVC 2005
|
||||
** or higher.
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER>=1400
|
||||
# define _CRT_RAND_S
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include the header file used to customize the compiler options for MSVC.
|
||||
** This should be done first so that it can successfully prevent spurious
|
||||
@@ -957,6 +949,7 @@ struct BusyHandler {
|
||||
int (*xFunc)(void *,int); /* The busy callback */
|
||||
void *pArg; /* First arg to busy callback */
|
||||
int nBusy; /* Incremented with each busy call */
|
||||
u32 nTimeout; /* Number of timeouts */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1245,9 +1238,9 @@ struct Lookaside {
|
||||
u32 bDisable; /* Only operate the lookaside when zero */
|
||||
u16 sz; /* Size of each buffer in bytes */
|
||||
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
|
||||
int nOut; /* Number of buffers currently checked out */
|
||||
int mxOut; /* Highwater mark for nOut */
|
||||
int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
|
||||
u32 nSlot; /* Number of lookaside slots allocated */
|
||||
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
|
||||
LookasideSlot *pInit; /* List of buffers not previously used */
|
||||
LookasideSlot *pFree; /* List of available buffers */
|
||||
void *pStart; /* First byte of available memory space */
|
||||
void *pEnd; /* First byte past end of available space */
|
||||
@@ -3268,6 +3261,7 @@ struct Sqlite3Config {
|
||||
int bFullMutex; /* True to enable full mutexing */
|
||||
int bOpenUri; /* True to interpret filenames as URIs */
|
||||
int bUseCis; /* Use covering indices for full-scans */
|
||||
int bSmallMalloc; /* Avoid large memory allocations if true */
|
||||
int mxStrlen; /* Maximum string length */
|
||||
int neverCorrupt; /* Database is always well-formed */
|
||||
int szLookaside; /* Default lookaside buffer size */
|
||||
@@ -3281,9 +3275,6 @@ struct Sqlite3Config {
|
||||
int mnReq, mxReq; /* Min and max heap requests sizes */
|
||||
sqlite3_int64 szMmap; /* mmap() space per open file */
|
||||
sqlite3_int64 mxMmap; /* Maximum value for szMmap */
|
||||
void *pScratch; /* Scratch memory */
|
||||
int szScratch; /* Size of each scratch buffer */
|
||||
int nScratch; /* Number of scratch buffers */
|
||||
void *pPage; /* Page cache memory */
|
||||
int szPage; /* Size of each page in pPage[] */
|
||||
int nPage; /* Number of pages in pPage[] */
|
||||
@@ -3370,6 +3361,7 @@ int sqlite3WalkSelectExpr(Walker*, Select*);
|
||||
int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
int sqlite3ExprWalkNoop(Walker*, Expr*);
|
||||
int sqlite3SelectWalkNoop(Walker*, Select*);
|
||||
int sqlite3SelectWalkFail(Walker*, Select*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3SelectWalkAssert2(Walker*, Select*);
|
||||
#endif
|
||||
@@ -3522,8 +3514,6 @@ void sqlite3DbFree(sqlite3*, void*);
|
||||
void sqlite3DbFreeNN(sqlite3*, void*);
|
||||
int sqlite3MallocSize(void*);
|
||||
int sqlite3DbMallocSize(sqlite3*, void*);
|
||||
void *sqlite3ScratchMalloc(int);
|
||||
void sqlite3ScratchFree(void*);
|
||||
void *sqlite3PageMalloc(int);
|
||||
void sqlite3PageFree(void*);
|
||||
void sqlite3MemSetDefault(void);
|
||||
@@ -3579,6 +3569,7 @@ sqlite3_int64 sqlite3StatusValue(int);
|
||||
void sqlite3StatusUp(int, int);
|
||||
void sqlite3StatusDown(int, int);
|
||||
void sqlite3StatusHighwater(int, int);
|
||||
int sqlite3LookasideUsed(sqlite3*,int*);
|
||||
|
||||
/* Access to mutexes used by sqlite3_status() */
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
@@ -4385,8 +4376,7 @@ SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
|
||||
#endif
|
||||
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
|
||||
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
|
||||
#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
|
||||
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
|
||||
#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */
|
||||
|
||||
/*
|
||||
** Threading interface
|
||||
|
||||
+30
-4
@@ -122,7 +122,6 @@ void sqlite3StatusHighwater(int op, int X){
|
||||
: sqlite3MallocMutex()) );
|
||||
assert( op==SQLITE_STATUS_MALLOC_SIZE
|
||||
|| op==SQLITE_STATUS_PAGECACHE_SIZE
|
||||
|| op==SQLITE_STATUS_SCRATCH_SIZE
|
||||
|| op==SQLITE_STATUS_PARSER_STACK );
|
||||
if( newValue>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = newValue;
|
||||
@@ -171,6 +170,28 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of LookasideSlot elements on the linked list
|
||||
*/
|
||||
static u32 countLookasideSlots(LookasideSlot *p){
|
||||
u32 cnt = 0;
|
||||
while( p ){
|
||||
p = p->pNext;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Count the number of slots of lookaside memory that are outstanding
|
||||
*/
|
||||
int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
|
||||
u32 nInit = countLookasideSlots(db->lookaside.pInit);
|
||||
u32 nFree = countLookasideSlots(db->lookaside.pFree);
|
||||
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
|
||||
return db->lookaside.nSlot - (nInit+nFree);
|
||||
}
|
||||
|
||||
/*
|
||||
** Query status information for a single database connection
|
||||
*/
|
||||
@@ -190,10 +211,15 @@ int sqlite3_db_status(
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
switch( op ){
|
||||
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
|
||||
*pCurrent = db->lookaside.nOut;
|
||||
*pHighwater = db->lookaside.mxOut;
|
||||
*pCurrent = sqlite3LookasideUsed(db, pHighwater);
|
||||
if( resetFlag ){
|
||||
db->lookaside.mxOut = db->lookaside.nOut;
|
||||
LookasideSlot *p = db->lookaside.pFree;
|
||||
if( p ){
|
||||
while( p->pNext ) p = p->pNext;
|
||||
p->pNext = db->lookaside.pInit;
|
||||
db->lookaside.pInit = db->lookaside.pFree;
|
||||
db->lookaside.pFree = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+11
-10
@@ -897,17 +897,18 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
case SQLITE_INDEX_CONSTRAINT_REGEXP:
|
||||
zOp = "regexp"; break;
|
||||
}
|
||||
if( zOp[0]=='L' ){
|
||||
zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
|
||||
zSep, zNewCol);
|
||||
} else {
|
||||
zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
|
||||
if( zOp ){
|
||||
if( zOp[0]=='L' ){
|
||||
zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
|
||||
zSep, zNewCol);
|
||||
} else {
|
||||
zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
|
||||
}
|
||||
string_concat(&zQuery, zNew, 1, &rc);
|
||||
zSep = "AND";
|
||||
pUsage->argvIndex = ++nArg;
|
||||
pUsage->omit = 1;
|
||||
}
|
||||
string_concat(&zQuery, zNew, 1, &rc);
|
||||
|
||||
zSep = "AND";
|
||||
pUsage->argvIndex = ++nArg;
|
||||
pUsage->omit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -414,6 +414,16 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
zOp = "glob"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_REGEXP:
|
||||
zOp = "regexp"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_NE:
|
||||
zOp = "ne"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNOT:
|
||||
zOp = "isnot"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
|
||||
zOp = "isnotnull"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNULL:
|
||||
zOp = "isnull"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_IS:
|
||||
zOp = "is"; break;
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
|
||||
|
||||
@@ -887,46 +887,6 @@ static int SQLITE_TCLAPI test_memdebug_log(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_config_scratch SIZE N
|
||||
**
|
||||
** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
|
||||
** The buffer is static and is of limited size. N might be
|
||||
** adjusted downward as needed to accommodate the requested size.
|
||||
** The revised value of N is returned.
|
||||
**
|
||||
** A negative SIZE causes the buffer pointer to be NULL.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_config_scratch(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int sz, N, rc;
|
||||
Tcl_Obj *pResult;
|
||||
static char *buf = 0;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
|
||||
free(buf);
|
||||
if( sz<0 ){
|
||||
buf = 0;
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, (void*)0, 0, 0);
|
||||
}else{
|
||||
buf = malloc( sz*N + 1 );
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
|
||||
}
|
||||
pResult = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
|
||||
Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
|
||||
Tcl_SetObjResult(interp, pResult);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_config_pagecache SIZE N
|
||||
**
|
||||
@@ -1538,7 +1498,6 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
|
||||
{ "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
|
||||
{ "sqlite3_memdebug_log", test_memdebug_log ,0 },
|
||||
{ "sqlite3_config_scratch", test_config_scratch ,0 },
|
||||
{ "sqlite3_config_pagecache", test_config_pagecache ,0 },
|
||||
{ "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
|
||||
{ "sqlite3_status", test_status ,0 },
|
||||
|
||||
+7
-3
@@ -491,7 +491,11 @@ do_atof_calc:
|
||||
if( esign<0 ){
|
||||
result = 0.0*s;
|
||||
}else{
|
||||
#ifdef INFINITY
|
||||
result = INFINITY*s;
|
||||
#else
|
||||
result = 1e308*1e308*s; /* Infinity */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@@ -1276,7 +1280,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
|
||||
** overflow, leave *pA unchanged and return 1.
|
||||
*/
|
||||
int sqlite3AddInt64(i64 *pA, i64 iB){
|
||||
#if GCC_VERSION>=5004000
|
||||
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
||||
return __builtin_add_overflow(*pA, iB, pA);
|
||||
#else
|
||||
i64 iA = *pA;
|
||||
@@ -1296,7 +1300,7 @@ int sqlite3AddInt64(i64 *pA, i64 iB){
|
||||
#endif
|
||||
}
|
||||
int sqlite3SubInt64(i64 *pA, i64 iB){
|
||||
#if GCC_VERSION>=5004000
|
||||
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
||||
return __builtin_sub_overflow(*pA, iB, pA);
|
||||
#else
|
||||
testcase( iB==SMALLEST_INT64+1 );
|
||||
@@ -1311,7 +1315,7 @@ int sqlite3SubInt64(i64 *pA, i64 iB){
|
||||
#endif
|
||||
}
|
||||
int sqlite3MulInt64(i64 *pA, i64 iB){
|
||||
#if GCC_VERSION>=5004000
|
||||
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
||||
return __builtin_mul_overflow(*pA, iB, pA);
|
||||
#else
|
||||
i64 iA = *pA;
|
||||
|
||||
+15
-5
@@ -2461,8 +2461,7 @@ case OP_Column: {
|
||||
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
|
||||
*/
|
||||
if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
goto op_column_corrupt;
|
||||
}
|
||||
}else{
|
||||
/* This is an optimization. By skipping over the first few tests
|
||||
@@ -2535,8 +2534,7 @@ case OP_Column: {
|
||||
zHdr = zEndHdr;
|
||||
}else{
|
||||
if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
goto op_column_corrupt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2631,6 +2629,15 @@ op_column_out:
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
break;
|
||||
|
||||
op_column_corrupt:
|
||||
if( aOp[0].p3>0 ){
|
||||
pOp = &aOp[aOp[0].p3-1];
|
||||
break;
|
||||
}else{
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Opcode: Affinity P1 P2 * P4 *
|
||||
@@ -7015,7 +7022,7 @@ case OP_Function: {
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: Init P1 P2 * P4 *
|
||||
/* Opcode: Init P1 P2 P3 P4 *
|
||||
** Synopsis: Start at P2
|
||||
**
|
||||
** Programs contain a single instance of this opcode as the very first
|
||||
@@ -7029,6 +7036,9 @@ case OP_Function: {
|
||||
**
|
||||
** Increment the value of P1 so that OP_Once opcodes will jump the
|
||||
** first time they are evaluated for this run.
|
||||
**
|
||||
** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
|
||||
** error is encountered.
|
||||
*/
|
||||
case OP_Init: { /* jump */
|
||||
char *zTrace;
|
||||
|
||||
@@ -393,6 +393,7 @@ struct Vdbe {
|
||||
bft usesStmtJournal:1; /* True if uses a statement journal */
|
||||
bft readOnly:1; /* True for statements that do not write */
|
||||
bft bIsReader:1; /* True for statements that read */
|
||||
bft retryable:1; /* True if the statement might succeed next time */
|
||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
|
||||
|
||||
+10
-1
@@ -398,7 +398,8 @@ void sqlite3_result_pointer(
|
||||
){
|
||||
Mem *pOut = pCtx->pOut;
|
||||
assert( sqlite3_mutex_held(pOut->db->mutex) );
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
sqlite3VdbeMemRelease(pOut);
|
||||
pOut->flags = MEM_Null;
|
||||
sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
|
||||
}
|
||||
void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
|
||||
@@ -1612,6 +1613,14 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
|
||||
return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the prepared statement failed with SQLITE_BUSY on its
|
||||
** previous run but might succeed if tried again.
|
||||
*/
|
||||
int sqlite3_stmt_retryable(sqlite3_stmt *pStmt){
|
||||
return pStmt ? ((Vdbe*)pStmt)->retryable : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the prepared statement is in need of being reset.
|
||||
*/
|
||||
|
||||
+15
-27
@@ -2158,27 +2158,6 @@ static void closeAllCursors(Vdbe *p){
|
||||
assert( p->pAuxData==0 );
|
||||
}
|
||||
|
||||
/*
|
||||
** Clean up the VM after a single run.
|
||||
*/
|
||||
static void Cleanup(Vdbe *p){
|
||||
sqlite3 *db = p->db;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
||||
** Vdbe.aMem[] arrays have already been cleaned up. */
|
||||
int i;
|
||||
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
|
||||
if( p->aMem ){
|
||||
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the number of result columns that will be returned by this SQL
|
||||
** statement. This is now set at compile time, rather than during
|
||||
@@ -2723,7 +2702,9 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
** or hit an 'OR FAIL' constraint and there are no deferred foreign
|
||||
** key constraints to hold up the transaction. This means a commit
|
||||
** is required. */
|
||||
db->busyHandler.nTimeout = 0;
|
||||
rc = vdbeCommit(db, p);
|
||||
p->retryable = db->busyHandler.nTimeout>0;
|
||||
}
|
||||
if( rc==SQLITE_BUSY && p->readOnly ){
|
||||
sqlite3VdbeLeave(p);
|
||||
@@ -2904,8 +2885,6 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
if( p->pc>=0 ){
|
||||
vdbeInvokeSqllog(p);
|
||||
sqlite3VdbeTransferError(p);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
if( p->runOnlyOnce ) p->expired = 1;
|
||||
}else if( p->rc && p->expired ){
|
||||
/* The expired flag was set on the VDBE before the first call
|
||||
@@ -2913,13 +2892,22 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
** called), set the database error in this case as well.
|
||||
*/
|
||||
sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
}
|
||||
|
||||
/* Reclaim all memory used by the VDBE
|
||||
/* Reset register contents and reclaim error message memory.
|
||||
*/
|
||||
Cleanup(p);
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
||||
** Vdbe.aMem[] arrays have already been cleaned up. */
|
||||
int i;
|
||||
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
|
||||
if( p->aMem ){
|
||||
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
|
||||
}
|
||||
#endif
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
|
||||
/* Save profiling information from this VDBE run.
|
||||
*/
|
||||
|
||||
+3
-5
@@ -1000,11 +1000,9 @@ int sqlite3VdbeSorterInit(
|
||||
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
|
||||
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
|
||||
|
||||
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
|
||||
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
|
||||
** large heap allocations.
|
||||
*/
|
||||
if( sqlite3GlobalConfig.pScratch==0 ){
|
||||
/* Avoid large memory allocations if the application has requested
|
||||
** SQLITE_CONFIG_SMALL_MALLOC. */
|
||||
if( sqlite3GlobalConfig.bSmallMalloc==0 ){
|
||||
assert( pSorter->iMemory==0 );
|
||||
pSorter->nMemory = pgsz;
|
||||
pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ char *sqlite3VdbeExpandSql(
|
||||
Mem *pVar; /* Value of a host parameter */
|
||||
StrAccum out; /* Accumulate the output here */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */
|
||||
Mem utf8; /* Used to convert UTF16 into UTF8 for display */
|
||||
#endif
|
||||
char zBase[100]; /* Initial working space */
|
||||
|
||||
|
||||
@@ -1798,9 +1798,7 @@ static int walCheckpoint(
|
||||
pInfo->nBackfillAttempted = mxSafeFrame;
|
||||
|
||||
/* Sync the WAL to disk */
|
||||
if( sync_flags ){
|
||||
rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
|
||||
}
|
||||
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
|
||||
/* If the database may grow as a result of this checkpoint, hint
|
||||
** about the eventual size of the db file to the VFS layer.
|
||||
@@ -1841,8 +1839,8 @@ static int walCheckpoint(
|
||||
i64 szDb = pWal->hdr.nPage*(i64)szPage;
|
||||
testcase( IS_BIG_INT(szDb) );
|
||||
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
|
||||
if( rc==SQLITE_OK && sync_flags ){
|
||||
rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2948,8 +2946,8 @@ static int walWriteToLog(
|
||||
iOffset += iFirstAmt;
|
||||
iAmt -= iFirstAmt;
|
||||
pContent = (void*)(iFirstAmt + (char*)pContent);
|
||||
assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
|
||||
rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK);
|
||||
assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 );
|
||||
rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags));
|
||||
if( iAmt==0 || rc ) return rc;
|
||||
}
|
||||
rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
|
||||
@@ -3119,10 +3117,10 @@ int sqlite3WalFrames(
|
||||
** an out-of-order write following a WAL restart could result in
|
||||
** database corruption. See the ticket:
|
||||
**
|
||||
** http://localhost:591/sqlite/info/ff5be73dee
|
||||
** https://sqlite.org/src/info/ff5be73dee
|
||||
*/
|
||||
if( pWal->syncHeader && sync_flags ){
|
||||
rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
|
||||
if( pWal->syncHeader ){
|
||||
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}
|
||||
@@ -3197,7 +3195,7 @@ int sqlite3WalFrames(
|
||||
** sector boundary is synced; the part of the last frame that extends
|
||||
** past the sector boundary is written after the sync.
|
||||
*/
|
||||
if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
|
||||
if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){
|
||||
int bSync = 1;
|
||||
if( pWal->padToSectorBoundary ){
|
||||
int sectorSize = sqlite3SectorSize(pWal->pWalFd);
|
||||
@@ -3213,7 +3211,7 @@ int sqlite3WalFrames(
|
||||
}
|
||||
if( bSync ){
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
|
||||
rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/* Additional values that can be added to the sync_flags argument of
|
||||
** sqlite3WalFrames():
|
||||
/* Macros for extracting appropriate sync flags for either transaction
|
||||
** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
|
||||
*/
|
||||
#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
|
||||
#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
|
||||
#define WAL_SYNC_FLAGS(X) ((X)&0x03)
|
||||
#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
|
||||
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
# define sqlite3WalOpen(x,y,z) 0
|
||||
|
||||
+61
-53
@@ -868,7 +868,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_IS );
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
|
||||
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
assert( pTerm->u.leftColumn>=(-1) );
|
||||
nTerm++;
|
||||
@@ -916,7 +916,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pUsage;
|
||||
|
||||
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
u8 op;
|
||||
u16 op;
|
||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||
if( pTerm->prereqRight & mUnusable ) continue;
|
||||
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
|
||||
@@ -924,34 +924,40 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
testcase( pTerm->eOperator & WO_IS );
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
|
||||
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
assert( pTerm->u.leftColumn>=(-1) );
|
||||
pIdxCons[j].iColumn = pTerm->u.leftColumn;
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
op = (u8)pTerm->eOperator & WO_ALL;
|
||||
op = pTerm->eOperator & WO_ALL;
|
||||
if( op==WO_IN ) op = WO_EQ;
|
||||
if( op==WO_MATCH ){
|
||||
op = pTerm->eMatchOp;
|
||||
}
|
||||
pIdxCons[j].op = op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
** following asserts verify this fact. */
|
||||
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
|
||||
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
|
||||
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
|
||||
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
||||
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
||||
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
|
||||
assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
|
||||
if( op==WO_AUX ){
|
||||
pIdxCons[j].op = pTerm->eMatchOp;
|
||||
}else if( op & (WO_ISNULL|WO_IS) ){
|
||||
if( op==WO_ISNULL ){
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
|
||||
}else{
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
|
||||
}
|
||||
}else{
|
||||
pIdxCons[j].op = (u8)op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
** following asserts verify this fact. */
|
||||
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
|
||||
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
|
||||
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
|
||||
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
||||
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
||||
assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
|
||||
|
||||
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
||||
){
|
||||
if( i<16 ) mNoOmit |= (1 << i);
|
||||
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
||||
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
|
||||
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
||||
){
|
||||
if( i<16 ) mNoOmit |= (1 << i);
|
||||
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
||||
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
@@ -4328,6 +4334,7 @@ static int exprIsDeterministic(Expr *p){
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = 1;
|
||||
w.xExprCallback = exprNodeIsDeterministic;
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
}
|
||||
@@ -4537,37 +4544,38 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||
**
|
||||
** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
|
||||
**
|
||||
** The rule of the previous sentence ensures thta if X is the bitmask for
|
||||
** a table T, then X-1 is the bitmask for all other tables to the left of T.
|
||||
** Knowing the bitmask for all tables to the left of a left join is
|
||||
** important. Ticket #3015.
|
||||
**
|
||||
** Note that bitmasks are created for all pTabList->nSrc tables in
|
||||
** pTabList, not just the first nTabList tables. nTabList is normally
|
||||
** equal to pTabList->nSrc but might be shortened to 1 if the
|
||||
** WHERE_OR_SUBCLAUSE flag is set.
|
||||
*/
|
||||
for(ii=0; ii<pTabList->nSrc; ii++){
|
||||
createMask(pMaskSet, pTabList->a[ii].iCursor);
|
||||
sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
{
|
||||
Bitmask mx = 0;
|
||||
for(ii=0; ii<pTabList->nSrc; ii++){
|
||||
Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
|
||||
assert( m>=mx );
|
||||
mx = m;
|
||||
}else{
|
||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||
**
|
||||
** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
|
||||
**
|
||||
** The rule of the previous sentence ensures thta if X is the bitmask for
|
||||
** a table T, then X-1 is the bitmask for all other tables to the left of T.
|
||||
** Knowing the bitmask for all tables to the left of a left join is
|
||||
** important. Ticket #3015.
|
||||
**
|
||||
** Note that bitmasks are created for all pTabList->nSrc tables in
|
||||
** pTabList, not just the first nTabList tables. nTabList is normally
|
||||
** equal to pTabList->nSrc but might be shortened to 1 if the
|
||||
** WHERE_OR_SUBCLAUSE flag is set.
|
||||
*/
|
||||
ii = 0;
|
||||
do{
|
||||
createMask(pMaskSet, pTabList->a[ii].iCursor);
|
||||
sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
|
||||
}while( (++ii)<pTabList->nSrc );
|
||||
#ifdef SQLITE_DEBUG
|
||||
{
|
||||
Bitmask mx = 0;
|
||||
for(ii=0; ii<pTabList->nSrc; ii++){
|
||||
Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
|
||||
assert( m>=mx );
|
||||
mx = m;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Analyze all of the subexpressions. */
|
||||
sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
|
||||
+1
-2
@@ -515,7 +515,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
||||
** WO_LE == SQLITE_INDEX_CONSTRAINT_LE
|
||||
** WO_GT == SQLITE_INDEX_CONSTRAINT_GT
|
||||
** WO_GE == SQLITE_INDEX_CONSTRAINT_GE
|
||||
** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH
|
||||
*/
|
||||
#define WO_IN 0x0001
|
||||
#define WO_EQ 0x0002
|
||||
@@ -523,7 +522,7 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
||||
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
|
||||
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
|
||||
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
|
||||
#define WO_MATCH 0x0040
|
||||
#define WO_AUX 0x0040 /* Op useful to virtual tables only */
|
||||
#define WO_IS 0x0080
|
||||
#define WO_ISNULL 0x0100
|
||||
#define WO_OR 0x0200 /* Two or more OR-connected terms */
|
||||
|
||||
+4
-4
@@ -1017,7 +1017,7 @@ static void codeDeferredSeek(
|
||||
*/
|
||||
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
|
||||
assert( nReg>0 );
|
||||
if( sqlite3ExprIsVector(p) ){
|
||||
if( p && sqlite3ExprIsVector(p) ){
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
if( (p->flags & EP_xIsSelect) ){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
@@ -1070,9 +1070,9 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
||||
}
|
||||
|
||||
/*
|
||||
** For an indexes on expression X, locate every instance of expression X in pExpr
|
||||
** and change that subexpression into a reference to the appropriate column of
|
||||
** the index.
|
||||
** For an indexes on expression X, locate every instance of expression X
|
||||
** in pExpr and change that subexpression into a reference to the appropriate
|
||||
** column of the index.
|
||||
*/
|
||||
static void whereIndexExprTrans(
|
||||
Index *pIdx, /* The Index */
|
||||
|
||||
+104
-63
@@ -312,48 +312,84 @@ static int isLikeOrGlob(
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Check to see if the given expression is of the form
|
||||
** Check to see if the pExpr expression is a form that needs to be passed
|
||||
** to the xBestIndex method of virtual tables. Forms of interest include:
|
||||
**
|
||||
** column OP expr
|
||||
** Expression Virtual Table Operator
|
||||
** ----------------------- ---------------------------------
|
||||
** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH
|
||||
** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB
|
||||
** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE
|
||||
** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP
|
||||
** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE
|
||||
** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE
|
||||
** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT
|
||||
** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT
|
||||
** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL
|
||||
**
|
||||
** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a
|
||||
** column of a virtual table.
|
||||
** In every case, "column" must be a column of a virtual table. If there
|
||||
** is a match, set *ppLeft to the "column" expression, set *ppRight to the
|
||||
** "expr" expression (even though in forms (6) and (8) the column is on the
|
||||
** right and the expression is on the left). Also set *peOp2 to the
|
||||
** appropriate virtual table operator. The return value is 1 or 2 if there
|
||||
** is a match. The usual return is 1, but if the RHS is also a column
|
||||
** of virtual table in forms (5) or (7) then return 2.
|
||||
**
|
||||
** If it is then return TRUE. If not, return FALSE.
|
||||
** If the expression matches none of the patterns above, return 0.
|
||||
*/
|
||||
static int isMatchOfColumn(
|
||||
static int isAuxiliaryVtabOperator(
|
||||
Expr *pExpr, /* Test this expression */
|
||||
unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */
|
||||
unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
|
||||
Expr **ppLeft, /* Column expression to left of MATCH/op2 */
|
||||
Expr **ppRight /* Expression to left of MATCH/op2 */
|
||||
){
|
||||
static const struct Op2 {
|
||||
const char *zOp;
|
||||
unsigned char eOp2;
|
||||
} aOp[] = {
|
||||
{ "match", SQLITE_INDEX_CONSTRAINT_MATCH },
|
||||
{ "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
|
||||
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
|
||||
{ "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
|
||||
};
|
||||
ExprList *pList;
|
||||
Expr *pCol; /* Column reference */
|
||||
int i;
|
||||
if( pExpr->op==TK_FUNCTION ){
|
||||
static const struct Op2 {
|
||||
const char *zOp;
|
||||
unsigned char eOp2;
|
||||
} aOp[] = {
|
||||
{ "match", SQLITE_INDEX_CONSTRAINT_MATCH },
|
||||
{ "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
|
||||
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
|
||||
{ "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
|
||||
};
|
||||
ExprList *pList;
|
||||
Expr *pCol; /* Column reference */
|
||||
int i;
|
||||
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return 0;
|
||||
}
|
||||
pList = pExpr->x.pList;
|
||||
if( pList==0 || pList->nExpr!=2 ){
|
||||
return 0;
|
||||
}
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
return 1;
|
||||
pList = pExpr->x.pList;
|
||||
if( pList==0 || pList->nExpr!=2 ){
|
||||
return 0;
|
||||
}
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
*ppRight = pList->a[0].pExpr;
|
||||
*ppLeft = pCol;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
|
||||
res++;
|
||||
}
|
||||
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
|
||||
res++;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
}
|
||||
*ppLeft = pLeft;
|
||||
*ppRight = pRight;
|
||||
if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE;
|
||||
if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT;
|
||||
if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -604,7 +640,7 @@ static void exprAnalyzeOrTerm(
|
||||
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
|
||||
assert( pAndTerm->pExpr );
|
||||
if( allowedOp(pAndTerm->pExpr->op)
|
||||
|| pAndTerm->eOperator==WO_MATCH
|
||||
|| pAndTerm->eOperator==WO_AUX
|
||||
){
|
||||
b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
|
||||
}
|
||||
@@ -1186,41 +1222,46 @@ static void exprAnalyze(
|
||||
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Add a WO_MATCH auxiliary term to the constraint set if the
|
||||
** current expression is of the form: column MATCH expr.
|
||||
/* Add a WO_AUX auxiliary term to the constraint set if the
|
||||
** current expression is of the form "column OP expr" where OP
|
||||
** is an operator that gets passed into virtual tables but which is
|
||||
** not normally optimized for ordinary tables. In other words, OP
|
||||
** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
|
||||
** This information is used by the xBestIndex methods of
|
||||
** virtual tables. The native query optimizer does not attempt
|
||||
** to do anything with MATCH functions.
|
||||
*/
|
||||
if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){
|
||||
int idxNew;
|
||||
if( pWC->op==TK_AND ){
|
||||
Expr *pRight, *pLeft;
|
||||
WhereTerm *pNewTerm;
|
||||
Bitmask prereqColumn, prereqExpr;
|
||||
int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight);
|
||||
while( res-- > 0 ){
|
||||
int idxNew;
|
||||
WhereTerm *pNewTerm;
|
||||
Bitmask prereqColumn, prereqExpr;
|
||||
|
||||
pRight = pExpr->x.pList->a[0].pExpr;
|
||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||
prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
|
||||
prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
|
||||
if( (prereqExpr & prereqColumn)==0 ){
|
||||
Expr *pNewExpr;
|
||||
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
|
||||
0, sqlite3ExprDup(db, pRight, 0));
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
|
||||
ExprSetProperty(pNewExpr, EP_FromJoin);
|
||||
prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
|
||||
prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
|
||||
if( (prereqExpr & prereqColumn)==0 ){
|
||||
Expr *pNewExpr;
|
||||
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
|
||||
0, sqlite3ExprDup(db, pRight, 0));
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
|
||||
ExprSetProperty(pNewExpr, EP_FromJoin);
|
||||
}
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
pNewTerm = &pWC->a[idxNew];
|
||||
pNewTerm->prereqRight = prereqExpr;
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_AUX;
|
||||
pNewTerm->eMatchOp = eOp2;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
pNewTerm->prereqAll = pTerm->prereqAll;
|
||||
}
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
pNewTerm = &pWC->a[idxNew];
|
||||
pNewTerm->prereqRight = prereqExpr;
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_MATCH;
|
||||
pNewTerm->eMatchOp = eOp2;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
pNewTerm->prereqAll = pTerm->prereqAll;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
# 2017 September 10
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# Test the virtual table interface. In particular the xBestIndex
|
||||
# method.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindex4
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Virtual table callback for a virtual table named $tbl.
|
||||
#
|
||||
proc vtab_cmd {method args} {
|
||||
|
||||
set binops(ne) !=
|
||||
set binops(eq) =
|
||||
set binops(isnot) "IS NOT"
|
||||
set binops(is) "IS"
|
||||
|
||||
set unops(isnotnull) "IS NOT NULL"
|
||||
set unops(isnull) "IS NULL"
|
||||
|
||||
set cols(0) a
|
||||
set cols(1) b
|
||||
set cols(2) c
|
||||
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t1(a, b, c)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
foreach {clist orderby mask} $args {}
|
||||
|
||||
set cost 1000000.0
|
||||
set ret [list]
|
||||
set str [list]
|
||||
|
||||
set v 0
|
||||
for {set i 0} {$i < [llength $clist]} {incr i} {
|
||||
array unset C
|
||||
array set C [lindex $clist $i]
|
||||
if {$C(usable)} {
|
||||
if {[info exists binops($C(op))]} {
|
||||
lappend ret omit $i
|
||||
lappend str "$cols($C(column)) $binops($C(op)) %$v%"
|
||||
incr v
|
||||
set cost [expr $cost / 2]
|
||||
}
|
||||
if {[info exists unops($C(op))]} {
|
||||
lappend ret omit $i
|
||||
lappend str "$cols($C(column)) $unops($C(op))"
|
||||
incr v
|
||||
set cost [expr $cost / 2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lappend ret idxstr [join $str " AND "]
|
||||
lappend ret cost $cost
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
set q [lindex $args 1]
|
||||
set a [lindex $args 2]
|
||||
for {set v 0} {$v < [llength $a]} {incr v} {
|
||||
set val [lindex $a $v]
|
||||
set q [string map [list %$v% '$val'] $q]
|
||||
}
|
||||
if {$q==""} { set q 1 }
|
||||
lappend ::xFilterQueries "WHERE $q"
|
||||
return [list sql "SELECT rowid, * FROM t1x WHERE $q"]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
proc vtab_simple {method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t2(x)"
|
||||
}
|
||||
xBestIndex {
|
||||
return [list cost 999999.0]
|
||||
}
|
||||
xFilter {
|
||||
return [list sql "SELECT rowid, * FROM t2x"]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
|
||||
proc do_vtab_query_test {tn query result} {
|
||||
set ::xFilterQueries [list]
|
||||
uplevel [list
|
||||
do_test $tn [string map [list %QUERY% $query] {
|
||||
set r [execsql {%QUERY%}]
|
||||
set r [concat $::xFilterQueries $r]
|
||||
set r
|
||||
}] [list {*}$result]
|
||||
]
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd');
|
||||
CREATE TABLE t1x(a INTEGER, b TEXT, c REAL);
|
||||
INSERT INTO t1x VALUES(1, 2, 3);
|
||||
INSERT INTO t1x VALUES(4, 5, 6);
|
||||
INSERT INTO t1x VALUES(7, 8, 9);
|
||||
|
||||
CREATE VIRTUAL TABLE t2 USING tcl('vtab_simple');
|
||||
CREATE TABLE t2x(x INTEGER);
|
||||
INSERT INTO t2x VALUES(1);
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.1 { SELECT * FROM t1 WHERE a!='hello'; } {
|
||||
"WHERE a != 'hello'"
|
||||
1 2 3.0 4 5 6.0 7 8 9.0
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.2.1 { SELECT * FROM t1 WHERE b!=8 } {
|
||||
"WHERE b != '8'"
|
||||
1 2 3.0 4 5 6.0
|
||||
}
|
||||
do_vtab_query_test 1.2.2 { SELECT * FROM t1 WHERE 8!=b } {
|
||||
"WHERE b != '8'"
|
||||
1 2 3.0 4 5 6.0
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.3 { SELECT * FROM t1 WHERE c IS NOT 3 } {
|
||||
"WHERE c IS NOT '3'"
|
||||
4 5 6.0 7 8 9.0
|
||||
}
|
||||
do_vtab_query_test 1.3.2 { SELECT * FROM t1 WHERE 3 IS NOT c } {
|
||||
"WHERE c IS NOT '3'"
|
||||
4 5 6.0 7 8 9.0
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.4.1 { SELECT * FROM t1, t2 WHERE x != a } {
|
||||
"WHERE a != '1'"
|
||||
4 5 6.0 1 7 8 9.0 1
|
||||
}
|
||||
do_vtab_query_test 1.4.2 { SELECT * FROM t1, t2 WHERE a != x } {
|
||||
"WHERE a != '1'"
|
||||
4 5 6.0 1 7 8 9.0 1
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.5.1 { SELECT * FROM t1 WHERE a IS NOT NULL } {
|
||||
"WHERE a IS NOT NULL"
|
||||
1 2 3.0 4 5 6.0 7 8 9.0
|
||||
}
|
||||
do_vtab_query_test 1.5.2 { SELECT * FROM t1 WHERE NULL IS NOT a } {
|
||||
"WHERE a IS NOT ''"
|
||||
1 2 3.0 4 5 6.0 7 8 9.0
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.6.1 { SELECT * FROM t1 WHERE a IS NULL } {
|
||||
"WHERE a IS NULL"
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.6.2 { SELECT * FROM t1 WHERE NULL IS a } {
|
||||
"WHERE a IS ''"
|
||||
}
|
||||
|
||||
do_vtab_query_test 1.7.1 { SELECT * FROM t1 WHERE (a, b) IS (1, 2) } {
|
||||
"WHERE a IS '1' AND b IS '2'"
|
||||
1 2 3.0
|
||||
}
|
||||
do_vtab_query_test 1.7.2 { SELECT * FROM t1 WHERE (5, 4) IS (b, a) } {
|
||||
{WHERE b IS '5' AND a IS '4'}
|
||||
4 5 6.0
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
do_execsql_test 2.0.0 {
|
||||
DELETE FROM t1x;
|
||||
INSERT INTO t1x VALUES('a', 'b', 'c');
|
||||
}
|
||||
do_execsql_test 2.0.1 { SELECT * FROM t1 } {a b c}
|
||||
do_execsql_test 2.0.2 { SELECT * FROM t1 WHERE (a, b) != ('a', 'b'); } {}
|
||||
|
||||
do_execsql_test 2.1.0 {
|
||||
DELETE FROM t1x;
|
||||
INSERT INTO t1x VALUES(7, 8, 9);
|
||||
}
|
||||
do_execsql_test 2.1.1 { SELECT * FROM t1 } {7 8 9.0}
|
||||
do_execsql_test 2.1.2 { SELECT * FROM t1 WHERE (a, b) != (7, '8') } {}
|
||||
do_execsql_test 2.1.3 { SELECT * FROM t1 WHERE a!=7 OR b!='8' }
|
||||
do_execsql_test 2.1.4 { SELECT * FROM t1 WHERE a!=7 OR b!='8' }
|
||||
|
||||
|
||||
do_execsql_test 2.2.1 {
|
||||
CREATE TABLE t3(a INTEGER, b TEXT);
|
||||
INSERT INTO t3 VALUES(45, 46);
|
||||
}
|
||||
do_execsql_test 2.2.2 { SELECT * FROM t3 WHERE (a, b) != (45, 46); }
|
||||
do_execsql_test 2.2.3 { SELECT * FROM t3 WHERE (a, b) != ('45', '46'); }
|
||||
do_execsql_test 2.2.4 { SELECT * FROM t3 WHERE (a, b) == (45, 46); } {45 46}
|
||||
do_execsql_test 2.2.5 { SELECT * FROM t3 WHERE (a, b) == ('45', '46'); } {45 46}
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Test the != operator on a virtual table with column affinities.
|
||||
#
|
||||
proc vtab_simple_integer {method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t4(x INTEGER)"
|
||||
}
|
||||
xBestIndex {
|
||||
return [list cost 999999.0]
|
||||
}
|
||||
xFilter {
|
||||
return [list sql "SELECT rowid, * FROM t4x"]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t4x(a INTEGER);
|
||||
INSERT INTO t4x VALUES(245);
|
||||
CREATE VIRTUAL TABLE t4 USING tcl('vtab_simple_integer');
|
||||
}
|
||||
do_execsql_test 3.1 { SELECT rowid, * FROM t4 WHERE x=245; } {1 245}
|
||||
do_execsql_test 3.2 { SELECT rowid, * FROM t4 WHERE x='245'; } {1 245}
|
||||
do_execsql_test 3.3 { SELECT rowid, * FROM t4 WHERE x!=245; } {}
|
||||
do_execsql_test 3.4 { SELECT rowid, * FROM t4 WHERE x!='245'; } {}
|
||||
|
||||
do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+3
-3
@@ -188,24 +188,24 @@ do_eqp_test 3.1.1 {
|
||||
do_eqp_test 3.1.2 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t1 AS sub}
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
do_eqp_test 3.1.3 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t1 AS sub}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
do_eqp_test 3.1.4 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
det 3.2.1 {
|
||||
|
||||
+43
-41
@@ -136,47 +136,49 @@ do_execsql_test 2.2.2 { COMMIT }
|
||||
do_execsql_test 2.2.3 { SELECT * FROM t1 } {{a b c} {a b c}}
|
||||
fts3_integrity 2.2.4 db t1
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4;
|
||||
REPLACE INTO t3(docid, content) VALUES (1, 'one two');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0100000002000000'}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
REPLACE INTO t3(docid, content) VALUES (2, 'one two three four');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'four'
|
||||
} {X'0200000003000000'}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
REPLACE INTO t3(docid, content) VALUES (1, 'one two three four five six');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0200000005000000'}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
UPDATE OR REPLACE t3 SET docid = 2 WHERE docid=1;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0100000006000000'}
|
||||
|
||||
do_execsql_test 3.5 {
|
||||
UPDATE OR REPLACE t3 SET docid = 3 WHERE docid=2;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0100000006000000'}
|
||||
|
||||
do_execsql_test 3.6 {
|
||||
REPLACE INTO t3(docid, content) VALUES (3, 'one two');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0100000002000000'}
|
||||
|
||||
do_execsql_test 3.7 {
|
||||
REPLACE INTO t3(docid, content) VALUES (NULL, 'one two three four');
|
||||
REPLACE INTO t3(docid, content) VALUES (NULL, 'one two three four five six');
|
||||
SELECT docid FROM t3;
|
||||
} {3 4 5}
|
||||
|
||||
do_execsql_test 3.8 {
|
||||
UPDATE OR REPLACE t3 SET docid = 5, content='three four' WHERE docid = 4;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0200000002000000'}
|
||||
if {$tcl_platform(byteOrder)=="littleEndian"} {
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4;
|
||||
REPLACE INTO t3(docid, content) VALUES (1, 'one two');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0100000002000000'}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
REPLACE INTO t3(docid, content) VALUES (2, 'one two three four');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'four'
|
||||
} {X'0200000003000000'}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
REPLACE INTO t3(docid, content) VALUES (1, 'one two three four five six');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0200000005000000'}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
UPDATE OR REPLACE t3 SET docid = 2 WHERE docid=1;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0100000006000000'}
|
||||
|
||||
do_execsql_test 3.5 {
|
||||
UPDATE OR REPLACE t3 SET docid = 3 WHERE docid=2;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six'
|
||||
} {X'0100000006000000'}
|
||||
|
||||
do_execsql_test 3.6 {
|
||||
REPLACE INTO t3(docid, content) VALUES (3, 'one two');
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0100000002000000'}
|
||||
|
||||
do_execsql_test 3.7 {
|
||||
REPLACE INTO t3(docid, content) VALUES(NULL,'one two three four');
|
||||
REPLACE INTO t3(docid, content) VALUES(NULL,'one two three four five six');
|
||||
SELECT docid FROM t3;
|
||||
} {3 4 5}
|
||||
|
||||
do_execsql_test 3.8 {
|
||||
UPDATE OR REPLACE t3 SET docid = 5, content='three four' WHERE docid = 4;
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0200000002000000'}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the xSavepoint is invoked correctly if the first write
|
||||
|
||||
+25
-26
@@ -57,10 +57,7 @@ do_eqp_test 3.1.1 {
|
||||
SELECT b FROM t1 WHERE b IS NOT NULL AND a IS NULL
|
||||
GROUP BY b COLLATE nocase
|
||||
ORDER BY b COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=? AND b>?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
} {/USE TEMP B-TREE FOR GROUP BY/}
|
||||
|
||||
do_execsql_test 3.2.0 {
|
||||
CREATE TABLE t2(x);
|
||||
@@ -88,28 +85,30 @@ do_execsql_test 3.3.0 {
|
||||
CREATE TABLE t3(x);
|
||||
}
|
||||
|
||||
do_eqp_test 3.3.1 {
|
||||
SELECT json_extract(x, '$.b') FROM t2
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
|
||||
do_execsql_test 3.3.2 {
|
||||
CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b'));
|
||||
} {}
|
||||
|
||||
do_eqp_test 3.3.3 {
|
||||
SELECT json_extract(x, '$.b') FROM t3
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX i3 (<expr>=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
ifcapable json1 {
|
||||
do_eqp_test 3.3.1 {
|
||||
SELECT json_extract(x, '$.b') FROM t2
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
|
||||
do_execsql_test 3.3.2 {
|
||||
CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b'));
|
||||
} {}
|
||||
|
||||
do_eqp_test 3.3.3 {
|
||||
SELECT json_extract(x, '$.b') FROM t3
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX i3 (<expr>=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 3.4.0 {
|
||||
|
||||
@@ -741,16 +741,6 @@ static int display_stats(
|
||||
"Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
|
||||
iCur, iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(out,
|
||||
"Number of Scratch Allocations Used: %d (max %d)\n",
|
||||
iCur, iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
|
||||
fprintf(out,
|
||||
"Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
|
||||
iCur, iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(out, "Largest Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
@@ -758,10 +748,6 @@ static int display_stats(
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(out, "Largest Pcache Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(out, "Largest Scratch Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
|
||||
|
||||
@@ -33,7 +33,6 @@ test_set_config_pagecache 0 0
|
||||
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_scratch 0 0
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
sqlite3 db test.db
|
||||
|
||||
+2
-137
@@ -16,7 +16,7 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
sqlite3_reset_auto_extension
|
||||
|
||||
# This test assumes that no page-cache or scratch buffers are installed
|
||||
# This test assumes that no page-cache buffers are installed
|
||||
# by default when a new database connection is opened. As a result, it
|
||||
# will not work with the "memsubsys1" permutation.
|
||||
#
|
||||
@@ -156,12 +156,11 @@ do_test memsubsys1-3.2.5 {
|
||||
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 0
|
||||
|
||||
# Test 4: Activate both PAGECACHE and SCRATCH.
|
||||
# Test 4: Activate PAGECACHE
|
||||
#
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache [expr 1024+$xtra_size] 50
|
||||
sqlite3_config_scratch 6000 2
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-4 {PRAGMA page_size=1024}
|
||||
@@ -177,144 +176,10 @@ do_test memsubsys1-4.5 {
|
||||
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
|
||||
expr {$maxreq<7000}
|
||||
} 1
|
||||
do_test memsubsys1-4.6 {
|
||||
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 1
|
||||
|
||||
# Test 5: Activate both PAGECACHE and SCRATCH. But make the page size is
|
||||
# such that the SCRATCH allocations are too small.
|
||||
#
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
|
||||
sqlite3_config_scratch 4000 2
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
|
||||
#show_memstats
|
||||
do_test memsubsys1-5.3 {
|
||||
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
|
||||
} {/^2[34]$/}
|
||||
do_test memsubsys1-5.4 {
|
||||
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
|
||||
expr {$maxreq>4096}
|
||||
} 1
|
||||
do_test memsubsys1-5.5 {
|
||||
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 0
|
||||
do_test memsubsys1-5.6 {
|
||||
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
|
||||
expr {$s_ovfl>6000}
|
||||
} 1
|
||||
|
||||
# Test 6: Activate both PAGECACHE and SCRATCH with a 4k page size.
|
||||
# Make it so that SCRATCH is large enough
|
||||
#
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
|
||||
sqlite3_config_scratch 25300 1
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-6 {PRAGMA page_size=4096}
|
||||
#show_memstats
|
||||
do_test memsubsys1-6.3 {
|
||||
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
|
||||
} {/^2[34]$/}
|
||||
#do_test memsubsys1-6.4 {
|
||||
# set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
|
||||
# expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)}
|
||||
#} 1
|
||||
do_test memsubsys1-6.5 {
|
||||
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 1
|
||||
do_test memsubsys1-6.6 {
|
||||
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
|
||||
} 0
|
||||
|
||||
# Test 7: Activate both PAGECACHE and SCRATCH with a 4k page size.
|
||||
# Set cache_size small so that no PAGECACHE overflow occurs. Verify
|
||||
# that maximum allocation size is small.
|
||||
#
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
|
||||
sqlite3_config_scratch 25300 1
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-7 {
|
||||
PRAGMA page_size=4096;
|
||||
PRAGMA cache_size=10;
|
||||
PRAGMA temp_store=memory;
|
||||
}
|
||||
#show_memstats
|
||||
do_test memsubsys1-7.3 {
|
||||
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
|
||||
expr {$pg_used<24}
|
||||
} 1
|
||||
do_test memsubsys1-7.4 {
|
||||
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
|
||||
} 0
|
||||
do_test memsubsys1-7.5 {
|
||||
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
|
||||
expr {$maxreq<(4100 + 8200*[nonzero_reserved_bytes])}
|
||||
} 1
|
||||
do_test memsubsys1-7.6 {
|
||||
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 1
|
||||
do_test memsubsys1-7.7 {
|
||||
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
|
||||
} 0
|
||||
|
||||
# Test 8: Disable PAGECACHE. Make available SCRATCH zero. Verify that
|
||||
# the SCRATCH overflow logic works.
|
||||
#
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache 0 0
|
||||
sqlite3_config_scratch 25000 0
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
do_test memsubsys1-8.1 {
|
||||
set pg_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
|
||||
} 0
|
||||
do_test memsubsys1-8.2 {
|
||||
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
|
||||
} 0
|
||||
do_test memsubsys1-8.3 {
|
||||
sqlite3 db :memory:
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(zeroblob(400));
|
||||
INSERT INTO t1 VALUES(zeroblob(400));
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
}
|
||||
expr {[lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]>0}
|
||||
} 1
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_memstatus 0
|
||||
sqlite3_initialize
|
||||
do_test memsubsys1-8.4 {
|
||||
sqlite3 db :memory:
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(zeroblob(400));
|
||||
INSERT INTO t1 VALUES(zeroblob(400));
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
SELECT rowid FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
|
||||
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_memstatus 1
|
||||
sqlite3_config_scratch 0 0
|
||||
sqlite3_config_lookaside 100 500
|
||||
sqlite3_config serialized
|
||||
sqlite3_initialize
|
||||
|
||||
+5
-3
@@ -366,8 +366,10 @@ do_realnum_test nan-4.35 {
|
||||
}
|
||||
} {0.0 real}
|
||||
|
||||
|
||||
|
||||
|
||||
do_realnum_test nan-4.40 {
|
||||
db eval {
|
||||
SELECT cast('-1e999' AS real);
|
||||
}
|
||||
} {-inf}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -455,33 +455,31 @@ lappend ::testsuitelist xxx
|
||||
# Define the permutation test suites:
|
||||
#
|
||||
|
||||
# Run some tests using pre-allocated page and scratch blocks.
|
||||
# Run some tests using pre-allocated page blocks.
|
||||
#
|
||||
# mmap1.test is excluded because a good number of its tests depend on
|
||||
# the page-cache being larger than the database. But this permutation
|
||||
# causes the effective limit on the page-cache to be just 24 pages.
|
||||
#
|
||||
test_suite "memsubsys1" -description {
|
||||
Tests using pre-allocated page and scratch blocks
|
||||
Tests using pre-allocated page blocks
|
||||
} -files [
|
||||
test_set $::allquicktests -exclude ioerr5.test malloc5.test mmap1.test
|
||||
] -initialize {
|
||||
test_set_config_pagecache 4096 24
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_scratch 25000 1
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
} -shutdown {
|
||||
test_restore_config_pagecache
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_scratch 0 0
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
}
|
||||
|
||||
# Run some tests using pre-allocated page and scratch blocks. This time
|
||||
# Run some tests using pre-allocated page blocks. This time
|
||||
# the allocations are too small to use in most cases.
|
||||
#
|
||||
# Both ioerr5.test and malloc5.test are excluded because they test the
|
||||
@@ -489,21 +487,19 @@ test_suite "memsubsys1" -description {
|
||||
# This functionality is disabled if a pre-allocated page block is provided.
|
||||
#
|
||||
test_suite "memsubsys2" -description {
|
||||
Tests using small pre-allocated page and scratch blocks
|
||||
Tests using small pre-allocated page blocks
|
||||
} -files [
|
||||
test_set $::allquicktests -exclude ioerr5.test malloc5.test
|
||||
] -initialize {
|
||||
test_set_config_pagecache 512 5
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_scratch 1000 1
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
} -shutdown {
|
||||
test_restore_config_pagecache
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_scratch 0 0
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
}
|
||||
|
||||
@@ -1932,6 +1932,28 @@ do_test 23.5 {
|
||||
PRAGMA foreign_key_list(t2);
|
||||
}
|
||||
} {0 0 t1 y {} {NO ACTION} {NO ACTION} NONE}
|
||||
db2 close
|
||||
|
||||
reset_db
|
||||
do_execsql_test 24.0 {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES('a', 'b', 'c');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
set r [db one {SELECT rootpage FROM sqlite_master WHERE name = 't1'}]
|
||||
db close
|
||||
hexio_write test.db [expr $r*1024 - 16] 000000000000000701040f0f1f616263
|
||||
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 24.1 {
|
||||
SELECT * FROM t1;
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 24.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 {{database disk image is malformed}}}
|
||||
|
||||
database_never_corrupt
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# 2017 August 25
|
||||
#
|
||||
# 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 implements regression tests for SQLite library.
|
||||
#
|
||||
# This file implements tests for the PRAGMA command. Specifically,
|
||||
# those pragmas enabled at build time by setting:
|
||||
#
|
||||
# -DSQLITE_INTROSPECTION_PRAGMAS
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix pragma5
|
||||
|
||||
if { [catch {db one "SELECT count(*) FROM pragma_function_list"}] } {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db function external external
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA table_info(pragma_function_list)
|
||||
} {
|
||||
0 name {} 0 {} 0
|
||||
1 builtin {} 0 {} 0
|
||||
}
|
||||
do_execsql_test 1.1 {
|
||||
SELECT * FROM pragma_function_list WHERE name='upper'
|
||||
} {upper 1}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT * FROM pragma_function_list WHERE name LIKE 'exter%';
|
||||
} {external 0}
|
||||
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 2.0 {
|
||||
PRAGMA table_info(pragma_module_list)
|
||||
} {
|
||||
0 name {} 0 {} 0
|
||||
}
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM pragma_module_list WHERE name='fts5'
|
||||
} {fts5}
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
PRAGMA table_info(pragma_pragma_list)
|
||||
} {
|
||||
0 name {} 0 {} 0
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM pragma_pragma_list WHERE name='pragma_list'
|
||||
} {pragma_list}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -25,7 +25,6 @@ static const char zHelp[] =
|
||||
" --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n"
|
||||
" --repeat N Repeat each SELECT N times (default: 1)\n"
|
||||
" --reprepare Reprepare each statement upon every invocation\n"
|
||||
" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
|
||||
" --serialized Set serialized threading mode\n"
|
||||
" --singlethread Set single-threaded mode - disables all mutexing\n"
|
||||
" --sqlonly No-op. Only show the SQL that would have been run.\n"
|
||||
@@ -1649,7 +1648,6 @@ int main(int argc, char **argv){
|
||||
int pageSize = 0; /* Desired page size. 0 means default */
|
||||
int nPCache = 0, szPCache = 0;/* --pcache configuration */
|
||||
int doPCache = 0; /* True if --pcache is seen */
|
||||
int nScratch = 0, szScratch=0;/* --scratch configuration */
|
||||
int showStats = 0; /* True for --stats */
|
||||
int nThread = 0; /* --threads value */
|
||||
int mmapSize = 0; /* How big of a memory map to use */
|
||||
@@ -1661,7 +1659,6 @@ int main(int argc, char **argv){
|
||||
void *pHeap = 0; /* Allocated heap space */
|
||||
void *pLook = 0; /* Allocated lookaside space */
|
||||
void *pPCache = 0; /* Allocated storage for pcache */
|
||||
void *pScratch = 0; /* Allocated storage for scratch */
|
||||
int iCur, iHi; /* Stats values, current and "highwater" */
|
||||
int i; /* Loop counter */
|
||||
int rc; /* API return code */
|
||||
@@ -1741,11 +1738,6 @@ int main(int argc, char **argv){
|
||||
i += 1;
|
||||
}else if( strcmp(z,"reprepare")==0 ){
|
||||
g.bReprepare = 1;
|
||||
}else if( strcmp(z,"scratch")==0 ){
|
||||
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
|
||||
nScratch = integerValue(argv[i+1]);
|
||||
szScratch = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
#if SQLITE_VERSION_NUMBER>=3006000
|
||||
}else if( strcmp(z,"serialized")==0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
|
||||
@@ -1816,13 +1808,6 @@ int main(int argc, char **argv){
|
||||
rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
|
||||
if( rc ) fatal_error("pcache configuration failed: %d\n", rc);
|
||||
}
|
||||
if( nScratch>0 && szScratch>0 ){
|
||||
pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
|
||||
if( pScratch==0 ) fatal_error("cannot allocate %lld-byte scratch\n",
|
||||
nScratch*(sqlite3_int64)szScratch);
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
|
||||
if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
|
||||
}
|
||||
if( nLook>=0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
|
||||
}
|
||||
@@ -1939,14 +1924,10 @@ int main(int argc, char **argv){
|
||||
#endif
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
|
||||
printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi);
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHi, 0);
|
||||
printf("-- Scratch Overflow Bytes: %d (max %d)\n", iCur,iHi);
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
|
||||
printf("-- Largest Allocation: %d bytes\n",iHi);
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
|
||||
printf("-- Largest Pcache Allocation: %d bytes\n",iHi);
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0);
|
||||
printf("-- Largest Scratch Allocation: %d bytes\n", iHi);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1959,7 +1940,6 @@ int main(int argc, char **argv){
|
||||
/* Release memory */
|
||||
free( pLook );
|
||||
free( pPCache );
|
||||
free( pScratch );
|
||||
free( pHeap );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1241,14 +1241,6 @@ proc show_memstats {} {
|
||||
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
|
||||
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
||||
output1 "Page-cache overflow: $val"
|
||||
set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
|
||||
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
||||
output1 "Scratch memory used: $val"
|
||||
set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
|
||||
set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0]
|
||||
set val [format {now %10d max %10d max-size %10d} \
|
||||
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
||||
output1 "Scratch overflow: $val"
|
||||
ifcapable yytrackmaxstackdepth {
|
||||
set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0]
|
||||
set val [format { max %10d} [lindex $x 2]]
|
||||
|
||||
+3
-3
@@ -1191,7 +1191,7 @@ if {$::tcl_platform(platform) == "unix"} {
|
||||
#
|
||||
foreach {tn sql reslist} {
|
||||
1 { } {10 0 4 0 6 0}
|
||||
2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2}
|
||||
2 { PRAGMA checkpoint_fullfsync = 1 } {10 6 4 3 6 3}
|
||||
3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0}
|
||||
} {
|
||||
ifcapable default_ckptfullfsync {
|
||||
@@ -1261,8 +1261,8 @@ foreach {tn settings restart_sync commit_sync ckpt_sync} {
|
||||
6 {0 1 full} {0 2} {0 1} {0 2}
|
||||
|
||||
7 {1 0 off} {0 0} {0 0} {0 0}
|
||||
8 {1 0 normal} {1 0} {0 0} {0 2}
|
||||
9 {1 0 full} {2 0} {1 0} {0 2}
|
||||
8 {1 0 normal} {0 1} {0 0} {0 2}
|
||||
9 {1 0 full} {1 1} {1 0} {0 2}
|
||||
|
||||
10 {1 1 off} {0 0} {0 0} {0 0}
|
||||
11 {1 1 normal} {0 1} {0 0} {0 2}
|
||||
|
||||
@@ -176,4 +176,26 @@ do_execsql_test 5.5 {
|
||||
} {4}
|
||||
do_test 5.6 { expr [db status vmstep]<200 } 1
|
||||
|
||||
# 2017-09-04 ticket b899b6042f97f52d
|
||||
# Segfault on correlated subquery...
|
||||
#
|
||||
ifcapable json1 {
|
||||
do_execsql_test 6.1 {
|
||||
CREATE TABLE t6(x);
|
||||
SELECT * FROM t6 WHERE 1 IN (SELECT value FROM json_each(x));
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
DROP TABLE t6;
|
||||
CREATE TABLE t6(a,b,c);
|
||||
INSERT INTO t6 VALUES
|
||||
(0,null,'{"a":0,"b":[3,4,5],"c":{"x":4.5,"y":7.8}}'),
|
||||
(1,null,'{"a":1,"b":[3,4,5],"c":{"x":4.5,"y":7.8}}'),
|
||||
(2,null,'{"a":9,"b":[3,4,5],"c":{"x":4.5,"y":7.8}}');
|
||||
SELECT * FROM t6
|
||||
WHERE (EXISTS (SELECT 1 FROM json_each(t6.c) AS x WHERE x.value=1));
|
||||
} {1 {} {{"a":1,"b":[3,4,5],"c":{"x":4.5,"y":7.8}}}}
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-2
@@ -9,8 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is recovery from transient manditory locks
|
||||
# that sometimes appear on database files due to anti-virus software.
|
||||
# focus of this script is the Win32 heap implementation.
|
||||
#
|
||||
|
||||
if {$tcl_platform(platform)!="windows"} return
|
||||
|
||||
@@ -633,14 +633,10 @@ int main(int argc, char **argv){
|
||||
printf("%s Outstanding Allocations: %d (max %d)\n",zTag,iCur,iHiwtr);
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, 0);
|
||||
printf("%s Pcache Overflow Bytes: %d (max %d)\n",zTag,iCur,iHiwtr);
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, 0);
|
||||
printf("%s Scratch Overflow Bytes: %d (max %d)\n",zTag,iCur,iHiwtr);
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, 0);
|
||||
printf("%s Largest Allocation: %d bytes\n",zTag,iHiwtr);
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, 0);
|
||||
printf("%s Largest Pcache Allocation: %d bytes\n",zTag,iHiwtr);
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, 0);
|
||||
printf("%s Largest Scratch Allocation: %d bytes\n",zTag,iHiwtr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+3
-1
@@ -25,8 +25,9 @@ puts $out {/* DO NOT EDIT!
|
||||
** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
|
||||
*/}
|
||||
set in [open $topdir/src/shell.c.in rb]
|
||||
while {![eof $in]} {
|
||||
while {1} {
|
||||
set lx [gets $in]
|
||||
if {[eof $in]} break;
|
||||
if {[regexp {^INCLUDE } $lx]} {
|
||||
set cfile [lindex $lx 1]
|
||||
puts $out "/************************* Begin $cfile ******************/"
|
||||
@@ -34,6 +35,7 @@ while {![eof $in]} {
|
||||
while {![eof $in2]} {
|
||||
set lx [gets $in2]
|
||||
if {[regexp {^#include "sqlite} $lx]} continue
|
||||
set lx [string map [list __declspec(dllexport) {}] $lx]
|
||||
puts $out $lx
|
||||
}
|
||||
close $in2
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
** SHA3 hash of the manifest file.
|
||||
**
|
||||
** (2) All individual file hashes in the manifest are verified. If any
|
||||
** source file has changed, the SHA3 hash ends with "-modified".
|
||||
** source file has changed, the SHA3 hash ends with "modified".
|
||||
**
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
@@ -844,7 +844,7 @@ int main(int argc, char **argv){
|
||||
fclose(in);
|
||||
sha3sum_file(zManifest, 256, zHash);
|
||||
if( !allValid ){
|
||||
printf("%s %.55s-modified\n", zDate, zHash);
|
||||
printf("%s %.60salt1\n", zDate, zHash);
|
||||
}else{
|
||||
printf("%s %s\n", zDate, zHash);
|
||||
}
|
||||
|
||||
+37
-1
@@ -242,7 +242,13 @@ proc copy_file {filename} {
|
||||
}
|
||||
}
|
||||
append line $funcname $rest
|
||||
puts $out $line
|
||||
if {$funcname=="sqlite3_sourceid" && !$linemacros} {
|
||||
# The sqlite3_sourceid() routine is synthesized at the end of
|
||||
# the amalgamation
|
||||
puts $out "/* $line */"
|
||||
} else {
|
||||
puts $out $line
|
||||
}
|
||||
} else {
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
}
|
||||
@@ -396,4 +402,34 @@ foreach file {
|
||||
copy_file tsrc/$file
|
||||
}
|
||||
|
||||
# Synthesize an alternative sqlite3_sourceid() implementation that
|
||||
# that tries to detects changes in the amalgamation source text
|
||||
# and modify returns a modified source-id if changes are detected.
|
||||
#
|
||||
# The only detection mechanism we have is the __LINE__ macro. So only
|
||||
# edits that changes the number of lines of source code are detected.
|
||||
#
|
||||
if {!$linemacros} {
|
||||
flush $out
|
||||
set in2 [open sqlite3.c]
|
||||
set cnt 0
|
||||
set oldsrcid {}
|
||||
while {![eof $in2]} {
|
||||
incr cnt
|
||||
gets $in2 line
|
||||
if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
|
||||
}
|
||||
close $in2
|
||||
regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
|
||||
puts $out \
|
||||
"#if __LINE__!=[expr {$cnt+0}]
|
||||
#undef SQLITE_SOURCE_ID
|
||||
$oldsrcid
|
||||
#endif
|
||||
/* Return the source-id for this library */
|
||||
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
|
||||
}
|
||||
puts $out \
|
||||
"/************************** End of sqlite3.c ******************************/"
|
||||
|
||||
close $out
|
||||
|
||||
Reference in New Issue
Block a user