Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b361ff381 | |||
| 799730bf81 | |||
| 5e18d40200 | |||
| 48cd59a57d | |||
| 39f98c52d0 | |||
| b1c6995c58 | |||
| cf7e7557b5 | |||
| 57a07ba9a9 | |||
| 44aebff246 | |||
| 40cf36ff17 | |||
| 2f55511dfa | |||
| 2e55b04da4 | |||
| 99f5de771f | |||
| 2aab11fa5a | |||
| 54606bbc14 | |||
| 4a030c6430 | |||
| 20ae3264b8 | |||
| 288327ed81 | |||
| afb8cd977d | |||
| 14faa061fd | |||
| a3fa140fb4 | |||
| aa50271a24 | |||
| 396794f0ee | |||
| 2075fb08e6 | |||
| cb6d66becc | |||
| 8443533178 | |||
| 14cee38be8 | |||
| 75ab50ce8f | |||
| 3104c4d6f4 | |||
| 10c0a2a7c9 | |||
| 609d5846ba | |||
| 05accd2216 | |||
| ad975d539e | |||
| 9bf0136384 | |||
| c6daa01c05 | |||
| 15af62acff | |||
| e5f06fdc87 | |||
| 97a7e5e68c | |||
| 45164826b7 | |||
| 0a5ced4c1e | |||
| b283a0cde9 | |||
| ead01fd272 | |||
| 6c96358601 | |||
| ae20690e2c | |||
| 835f22deda | |||
| dc7adf20bb | |||
| b1ec87afdb | |||
| 1de86ca17f | |||
| d456e92ce0 | |||
| 23ee893752 | |||
| 7ff5d522bf | |||
| 2d36f065e2 | |||
| 6572c16ae1 | |||
| 7694e06461 | |||
| 83b74f29c5 | |||
| b7a208686a | |||
| 2e8bfb67d4 | |||
| 6bcfe8b61f | |||
| 518aca114f | |||
| 26f7977c53 | |||
| f602a16123 | |||
| 191dd06195 | |||
| 94d49697b5 | |||
| cdce61e133 | |||
| 333f80562b | |||
| 132dde5cdf | |||
| 1a55dedf7b | |||
| 1aea63032a | |||
| 46f0035b48 | |||
| bff4b6367c | |||
| 58e3812988 | |||
| beccf1d16f | |||
| a6dddd9bde | |||
| 2c03652b45 | |||
| b5895e50f9 | |||
| f9986d90d1 | |||
| 303a094466 | |||
| 2bb5f4478e | |||
| 977cbe78b3 | |||
| ee65eea4af | |||
| f89157653a | |||
| eacd29d484 | |||
| 5313f2e12e | |||
| 497116007e | |||
| fc26f7cfed | |||
| 7111c93c40 | |||
| f1b5ff73cb | |||
| 8f2ce91462 | |||
| 7512cb47e8 | |||
| 07d683fdbc | |||
| 1454b26c17 | |||
| 0f52455a35 | |||
| 8ca7b177bb | |||
| 0cb64edc95 | |||
| 4926fec967 | |||
| 02d436b1f6 | |||
| c5896b5cbb | |||
| 77fac879d2 | |||
| 02267cc213 | |||
| 74f598b677 | |||
| 199f56b984 | |||
| 741c2772db | |||
| 2160ca5f8d | |||
| e11003d5ba | |||
| 8a878f239c | |||
| 752b102e9b | |||
| 745be369c7 | |||
| 70b8d6bbcc | |||
| 6f07734349 | |||
| f3c57ff54c | |||
| 926957f0a6 | |||
| ad2d5baf1f | |||
| 0e55da2ef8 | |||
| b5a2592a9e | |||
| 7180de2aa4 | |||
| b9f11f932d | |||
| 67330a1224 | |||
| 7082371de7 | |||
| 9131ab9386 | |||
| 7f8def285e | |||
| d87efd7221 | |||
| 41113b6429 |
+3
-3
@@ -82,7 +82,6 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
OPT_FEATURE_FLAGS += -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK
|
||||
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
|
||||
@@ -1032,7 +1031,7 @@ FTS5_SRC = \
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
cp $(TOP)/ext/fts5/fts5parse.y .
|
||||
rm -f fts5parse.h
|
||||
./lemon $(OPTS) fts5parse.y
|
||||
./lemon$(BEXE) $(OPTS) fts5parse.y
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
@@ -1164,8 +1163,9 @@ loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
|
||||
# symbols that do not begin with "sqlite3_". It is run as part of the
|
||||
# releasetest.tcl script.
|
||||
#
|
||||
VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
|
||||
checksymbols: sqlite3.lo
|
||||
nm -g --defined-only sqlite3.o | egrep -v ' sqlite3(changeset|session)?_' ; test $$? -ne 0
|
||||
nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
|
||||
echo '0 errors out of 1 tests'
|
||||
|
||||
# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
|
||||
|
||||
@@ -264,6 +264,15 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Enable support for the session extension if the SESSION=1 argument is
|
||||
# present on the nmake command-line
|
||||
#
|
||||
!IFNDEF SESSION
|
||||
SESSION = 0
|
||||
!ENDIF
|
||||
!IF $(SESSION)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
!ENDIF
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
|
||||
@@ -249,6 +249,15 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Enable support for the session extension if the SESSION=1 argument is
|
||||
# present on the nmake command-line
|
||||
#
|
||||
!IFNDEF SESSION
|
||||
SESSION = 0
|
||||
!ENDIF
|
||||
!IF $(SESSION)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
!ENDIF
|
||||
|
||||
@@ -122,6 +122,18 @@ fi
|
||||
AC_SUBST(JSON1_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-session
|
||||
#
|
||||
AC_ARG_ENABLE(session, [AS_HELP_STRING(
|
||||
[--enable-session], [enable the session extension [default=no]])],
|
||||
[], [enable_session=no])
|
||||
if test x"$enable_session" == "xyes"; then
|
||||
SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
AC_SUBST(SESSION_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-static-shell
|
||||
#
|
||||
|
||||
@@ -908,6 +908,7 @@ enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_rtree
|
||||
enable_session
|
||||
enable_gcov
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@@ -1556,6 +1557,7 @@ Optional Features:
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-rtree Enable the RTREE extension
|
||||
--enable-session Enable the SESSION extension
|
||||
--enable-gcov Enable coverage testing using gcov
|
||||
|
||||
Optional Packages:
|
||||
@@ -3923,13 +3925,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:3926: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3928: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3929: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3931: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3932: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3934: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5135,7 +5137,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5138 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5140 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6660,11 +6662,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:6663: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6665: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6667: \$? = $ac_status" >&5
|
||||
echo "$as_me:6669: \$? = $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.
|
||||
@@ -6999,11 +7001,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:7002: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7004: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7006: \$? = $ac_status" >&5
|
||||
echo "$as_me:7008: \$? = $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.
|
||||
@@ -7104,11 +7106,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:7107: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7109: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7111: \$? = $ac_status" >&5
|
||||
echo "$as_me:7113: \$? = $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
|
||||
@@ -7159,11 +7161,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:7162: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7164: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7166: \$? = $ac_status" >&5
|
||||
echo "$as_me:7168: \$? = $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
|
||||
@@ -9539,7 +9541,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9542 "configure"
|
||||
#line 9544 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9635,7 +9637,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9638 "configure"
|
||||
#line 9640 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11494,6 +11496,20 @@ if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the SESSION extension
|
||||
# Check whether --enable-session was given.
|
||||
if test "${enable_session+set}" = set; then :
|
||||
enableval=$enable_session; enable_session=yes
|
||||
else
|
||||
enable_session=no
|
||||
fi
|
||||
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
|
||||
@@ -615,6 +615,16 @@ if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the SESSION extension
|
||||
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]),
|
||||
[enable_session=yes],[enable_session=no])
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
|
||||
@@ -458,7 +458,7 @@ static int testTokenizerNext(
|
||||
if( pCsr->iLangid & 0x00000001 ){
|
||||
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = pToken[i];
|
||||
}else{
|
||||
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = testTolower(pToken[i]);
|
||||
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = (char)testTolower(pToken[i]);
|
||||
}
|
||||
pCsr->iToken++;
|
||||
pCsr->iInput = (int)(p - pCsr->aInput);
|
||||
|
||||
@@ -398,8 +398,8 @@ static void showSegmentStats(sqlite3 *db, const char *zTab){
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW
|
||||
&& (nLeaf = sqlite3_column_int(pStmt, 0))>0
|
||||
){
|
||||
nIdx = sqlite3_column_int(pStmt, 5);
|
||||
sqlite3_int64 sz;
|
||||
nIdx = sqlite3_column_int(pStmt, 5);
|
||||
printf("For level %d:\n", i);
|
||||
printf(" Number of indexes...................... %9d\n", nIdx);
|
||||
printf(" Number of leaf segments................ %9d\n", nLeaf);
|
||||
|
||||
@@ -345,11 +345,11 @@ int sqlite3Fts5HashWrite(
|
||||
if( pHash->eDetail==FTS5_DETAIL_FULL ){
|
||||
pPtr[p->nData++] = 0x01;
|
||||
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
|
||||
p->iCol = iCol;
|
||||
p->iCol = (i16)iCol;
|
||||
p->iPos = 0;
|
||||
}else{
|
||||
bNew = 1;
|
||||
p->iCol = iPos = iCol;
|
||||
p->iCol = (i16)(iPos = iCol);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3244,7 +3244,7 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
||||
if( aiCol==aiColEnd ) goto setoutputs_col_out;
|
||||
}
|
||||
if( *aiCol==iPrev ){
|
||||
*aOut++ = (iPrev - iPrevOut) + 2;
|
||||
*aOut++ = (u8)((iPrev - iPrevOut) + 2);
|
||||
iPrevOut = iPrev;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-11
@@ -354,15 +354,17 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
** http://www.icu-project.org/userguide/posix.html#case_mappings
|
||||
*/
|
||||
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
const UChar *zInput;
|
||||
UChar *zOutput = 0;
|
||||
int nInput;
|
||||
int nOut;
|
||||
const UChar *zInput; /* Pointer to input string */
|
||||
UChar *zOutput = 0; /* Pointer to output buffer */
|
||||
int nInput; /* Size of utf-16 input string in bytes */
|
||||
int nOut; /* Size of output buffer in bytes */
|
||||
int cnt;
|
||||
int bToUpper; /* True for toupper(), false for tolower() */
|
||||
UErrorCode status;
|
||||
const char *zLocale = 0;
|
||||
|
||||
assert(nArg==1 || nArg==2);
|
||||
bToUpper = (sqlite3_user_data(p)!=0);
|
||||
if( nArg==2 ){
|
||||
zLocale = (const char *)sqlite3_value_text(apArg[1]);
|
||||
}
|
||||
@@ -386,19 +388,23 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
}
|
||||
zOutput = zNew;
|
||||
status = U_ZERO_ERROR;
|
||||
if( sqlite3_user_data(p) ){
|
||||
if( bToUpper ){
|
||||
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}else{
|
||||
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}
|
||||
if( !U_SUCCESS(status) ){
|
||||
if( status==U_BUFFER_OVERFLOW_ERROR ) continue;
|
||||
icuFunctionError(p,
|
||||
sqlite3_user_data(p) ? "u_strToUpper" : "u_strToLower", status);
|
||||
return;
|
||||
|
||||
if( U_SUCCESS(status) ){
|
||||
sqlite3_result_text16(p, zOutput, nOut, xFree);
|
||||
}else if( status==U_BUFFER_OVERFLOW_ERROR ){
|
||||
assert( cnt==0 );
|
||||
continue;
|
||||
}else{
|
||||
icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sqlite3_result_text16(p, zOutput, nOut, xFree);
|
||||
assert( 0 ); /* Unreachable */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+4
-4
@@ -625,10 +625,10 @@ static int amatchLoadOneRule(
|
||||
}else{
|
||||
memset(pRule, 0, sizeof(*pRule));
|
||||
pRule->zFrom = &pRule->zTo[nTo+1];
|
||||
pRule->nFrom = nFrom;
|
||||
pRule->nFrom = (amatch_len)nFrom;
|
||||
memcpy(pRule->zFrom, zFrom, nFrom+1);
|
||||
memcpy(pRule->zTo, zTo, nTo+1);
|
||||
pRule->nTo = nTo;
|
||||
pRule->nTo = (amatch_len)nTo;
|
||||
pRule->rCost = rCost;
|
||||
pRule->iLang = (int)iLang;
|
||||
}
|
||||
@@ -1081,7 +1081,7 @@ static void amatchAddWord(
|
||||
pWord->rCost = rCost;
|
||||
pWord->iSeq = pCur->nWord++;
|
||||
amatchWriteCost(pWord);
|
||||
pWord->nMatch = nMatch;
|
||||
pWord->nMatch = (short)nMatch;
|
||||
pWord->pNext = pCur->pAllWords;
|
||||
pCur->pAllWords = pWord;
|
||||
pWord->sCost.zKey = pWord->zCost;
|
||||
@@ -1162,7 +1162,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){
|
||||
#endif
|
||||
nWord = (int)strlen(pWord->zWord+2);
|
||||
if( nWord+20>nBuf ){
|
||||
nBuf = nWord+100;
|
||||
nBuf = (char)(nWord+100);
|
||||
zBuf = sqlite3_realloc(zBuf, nBuf);
|
||||
if( zBuf==0 ) return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
+2
-2
@@ -344,10 +344,10 @@ static int fuzzerLoadOneRule(
|
||||
memset(pRule, 0, sizeof(*pRule));
|
||||
pRule->zFrom = pRule->zTo;
|
||||
pRule->zFrom += nTo + 1;
|
||||
pRule->nFrom = nFrom;
|
||||
pRule->nFrom = (fuzzer_len)nFrom;
|
||||
memcpy(pRule->zFrom, zFrom, nFrom+1);
|
||||
memcpy(pRule->zTo, zTo, nTo+1);
|
||||
pRule->nTo = nTo;
|
||||
pRule->nTo = (fuzzer_len)nTo;
|
||||
pRule->rCost = nCost;
|
||||
pRule->iRuleset = (int)iRuleset;
|
||||
}
|
||||
|
||||
+5
-5
@@ -136,7 +136,7 @@ struct ReCompiled {
|
||||
static void re_add_state(ReStateSet *pSet, int newState){
|
||||
unsigned i;
|
||||
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
|
||||
pSet->aState[pSet->nState++] = newState;
|
||||
pSet->aState[pSet->nState++] = (ReStateNumber)newState;
|
||||
}
|
||||
|
||||
/* Extract the next unicode character from *pzIn and return it. Advance
|
||||
@@ -358,7 +358,7 @@ static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
|
||||
p->aArg[i] = p->aArg[i-1];
|
||||
}
|
||||
p->nState++;
|
||||
p->aOp[iBefore] = op;
|
||||
p->aOp[iBefore] = (char)op;
|
||||
p->aArg[iBefore] = arg;
|
||||
return iBefore;
|
||||
}
|
||||
@@ -677,12 +677,12 @@ const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
|
||||
unsigned x = pRe->aArg[i];
|
||||
if( x<=127 ){
|
||||
pRe->zInit[j++] = x;
|
||||
pRe->zInit[j++] = (unsigned char)x;
|
||||
}else if( x<=0xfff ){
|
||||
pRe->zInit[j++] = 0xc0 | (x>>6);
|
||||
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else if( x<=0xffff ){
|
||||
pRe->zInit[j++] = 0xd0 | (x>>12);
|
||||
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
|
||||
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else{
|
||||
|
||||
+10
-10
@@ -390,7 +390,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
|
||||
/* Special processing if either string is empty */
|
||||
if( nA==0 ){
|
||||
cBprev = dc;
|
||||
cBprev = (char)dc;
|
||||
for(xB=res=0; (cB = zB[xB])!=0; xB++){
|
||||
res += insertOrDeleteCost(cBprev, cB, zB[xB+1])/FINAL_INS_COST_DIV;
|
||||
cBprev = cB;
|
||||
@@ -398,7 +398,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
return res;
|
||||
}
|
||||
if( nB==0 ){
|
||||
cAprev = dc;
|
||||
cAprev = (char)dc;
|
||||
for(xA=res=0; (cA = zA[xA])!=0; xA++){
|
||||
res += insertOrDeleteCost(cAprev, cA, zA[xA+1]);
|
||||
cAprev = cA;
|
||||
@@ -420,8 +420,8 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
|
||||
/* Compute the Wagner edit distance */
|
||||
m[0] = 0;
|
||||
cx[0] = dc;
|
||||
cBprev = dc;
|
||||
cx[0] = (char)dc;
|
||||
cBprev = (char)dc;
|
||||
for(xB=1; xB<=nB; xB++){
|
||||
cBnext = zB[xB];
|
||||
cB = zB[xB-1];
|
||||
@@ -429,7 +429,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
m[xB] = m[xB-1] + insertOrDeleteCost(cBprev, cB, cBnext);
|
||||
cBprev = cB;
|
||||
}
|
||||
cAprev = dc;
|
||||
cAprev = (char)dc;
|
||||
for(xA=1; xA<=nA; xA++){
|
||||
int lastA = (xA==nA);
|
||||
cA = zA[xA-1];
|
||||
@@ -476,7 +476,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
d = m[xB];
|
||||
dc = cx[xB];
|
||||
m[xB] = totalCost;
|
||||
cx[xB] = ncx;
|
||||
cx[xB] = (char)ncx;
|
||||
cBprev = cB;
|
||||
}
|
||||
cAprev = cA;
|
||||
@@ -711,9 +711,9 @@ static int editDist3ConfigLoad(
|
||||
if( nExtra<0 ) nExtra = 0;
|
||||
pCost = sqlite3_malloc64( sizeof(*pCost) + nExtra );
|
||||
if( pCost==0 ){ rc = SQLITE_NOMEM; break; }
|
||||
pCost->nFrom = nFrom;
|
||||
pCost->nTo = nTo;
|
||||
pCost->iCost = iCost;
|
||||
pCost->nFrom = (u8)nFrom;
|
||||
pCost->nTo = (u8)nTo;
|
||||
pCost->iCost = (u16)iCost;
|
||||
memcpy(pCost->a, zFrom, nFrom);
|
||||
memcpy(pCost->a + nFrom, zTo, nTo);
|
||||
pCost->pNext = pLang->pCost;
|
||||
@@ -1616,7 +1616,7 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){
|
||||
zIn += sz;
|
||||
nIn -= sz;
|
||||
if( c<=127 ){
|
||||
zOut[nOut++] = c;
|
||||
zOut[nOut++] = (unsigned char)c;
|
||||
}else{
|
||||
int xTop, xBtm, x;
|
||||
xTop = sizeof(translit)/sizeof(translit[0]) - 1;
|
||||
|
||||
+40
-16
@@ -24,12 +24,22 @@
|
||||
*/
|
||||
void usage(const char *zArgv0){
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-step NSTEP] TARGET-DB RBU-DB\n"
|
||||
"Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n"
|
||||
"\n"
|
||||
" Argument RBU-DB must be an RBU database containing an update suitable for\n"
|
||||
" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n"
|
||||
" (the default value), this program attempts to apply the entire update to\n"
|
||||
" the target database.\n"
|
||||
"Where options are:\n"
|
||||
"\n"
|
||||
" -step NSTEP\n"
|
||||
" -vacuum\n"
|
||||
"\n"
|
||||
" If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
|
||||
" database containing an update suitable for target database TARGET-DB.\n"
|
||||
" Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n"
|
||||
" RBU, and RBU-DB is used as the state database for the vacuum (refer to\n"
|
||||
" API documentation for details).\n"
|
||||
"\n"
|
||||
" If NSTEP is set to less than or equal to zero (the default value), this \n"
|
||||
" program attempts to perform the entire update or vacuum operation before\n"
|
||||
" exiting\n"
|
||||
"\n"
|
||||
" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
|
||||
" to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
|
||||
@@ -69,29 +79,43 @@ int main(int argc, char **argv){
|
||||
char *zErrmsg; /* Error message, if any */
|
||||
sqlite3rbu *pRbu; /* RBU handle */
|
||||
int nStep = 0; /* Maximum number of step() calls */
|
||||
int bVacuum = 0;
|
||||
int rc;
|
||||
sqlite3_int64 nProgress = 0;
|
||||
int nArg = argc-2;
|
||||
|
||||
/* Process command line arguments. Following this block local variables
|
||||
** zTarget, zRbu and nStep are all set. */
|
||||
if( argc==5 ){
|
||||
size_t nArg1 = strlen(argv[1]);
|
||||
if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]);
|
||||
nStep = atoi(argv[2]);
|
||||
}else if( argc!=3 ){
|
||||
usage(argv[0]);
|
||||
if( argc<3 ) usage(argv[0]);
|
||||
for(i=1; i<nArg; i++){
|
||||
const char *zArg = argv[i];
|
||||
int nArg = strlen(zArg);
|
||||
if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
|
||||
bVacuum = 1;
|
||||
}else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
|
||||
i++;
|
||||
nStep = atoi(argv[i]);
|
||||
}else{
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
zTarget = argv[argc-2];
|
||||
zRbu = argv[argc-1];
|
||||
|
||||
report_default_vfs();
|
||||
|
||||
/* Open an RBU handle. If nStep is less than or equal to zero, call
|
||||
/* Open an RBU handle. A vacuum handle if -vacuum was specified, or a
|
||||
** regular RBU update handle otherwise. */
|
||||
if( bVacuum ){
|
||||
pRbu = sqlite3rbu_vacuum(zTarget, zRbu);
|
||||
}else{
|
||||
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
|
||||
}
|
||||
report_rbu_vfs(pRbu);
|
||||
|
||||
/* If nStep is less than or equal to zero, call
|
||||
** sqlite3rbu_step() until either the RBU has been completely applied
|
||||
** or an error occurs. Or, if nStep is greater than zero, call
|
||||
** sqlite3rbu_step() a maximum of nStep times. */
|
||||
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
|
||||
report_rbu_vfs(pRbu);
|
||||
for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
|
||||
nProgress = sqlite3rbu_progress(pRbu);
|
||||
rc = sqlite3rbu_close(pRbu, &zErrmsg);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# 2016 April 20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains fault injection tests for RBU vacuum operations.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set ::testprefix rbufault3
|
||||
|
||||
foreach {fault errlist} {
|
||||
oom-* {
|
||||
{1 SQLITE_NOMEM}
|
||||
{1 SQLITE_IOERR_NOMEM}
|
||||
{1 {SQLITE_NOMEM - out of memory}}
|
||||
}
|
||||
|
||||
ioerr-* {
|
||||
{1 {SQLITE_IOERR - disk I/O error}}
|
||||
{1 SQLITE_IOERR}
|
||||
{1 SQLITE_IOERR_WRITE}
|
||||
{1 SQLITE_IOERR_FSYNC}
|
||||
{1 SQLITE_IOERR_READ}
|
||||
{1 {SQLITE_IOERR - unable to open database: test.db2}}
|
||||
{1 {SQLITE_ERROR - unable to open database: test.db2}}
|
||||
{1 {SQLITE_ERROR - SQL logic error or missing database}}
|
||||
}
|
||||
|
||||
cantopen* {
|
||||
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
|
||||
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
|
||||
{1 {SQLITE_CANTOPEN - unable to open database file}}
|
||||
{1 SQLITE_CANTOPEN}
|
||||
}
|
||||
|
||||
} {
|
||||
|
||||
reset_db
|
||||
do_execsql_test 0 {
|
||||
CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
|
||||
INSERT INTO target VALUES(1, 2, 3);
|
||||
INSERT INTO target VALUES(4, 5, 6);
|
||||
INSERT INTO target VALUES(7, 8, 9);
|
||||
CREATE INDEX i1 ON target(z);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -faults $fault -prep {
|
||||
faultsim_restore_and_reopen
|
||||
forcedelete test.db2
|
||||
} -body {
|
||||
sqlite3rbu_vacuum rbu test.db test.db2
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
rbu close
|
||||
} -test {
|
||||
eval [list faultsim_test_result {0 SQLITE_DONE} {*}$::errlist]
|
||||
}
|
||||
|
||||
do_faultsim_test 2 -faults $fault -prep {
|
||||
faultsim_restore_and_reopen
|
||||
forcedelete test.db2
|
||||
} -body {
|
||||
sqlite3rbu_vacuum rbu test.db test.db2
|
||||
rbu step
|
||||
rbu close
|
||||
} -test {
|
||||
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
|
||||
}
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3rbu_vacuum rbu test.db test.db2
|
||||
rbu step
|
||||
rbu close
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 3 -faults $fault -prep {
|
||||
faultsim_restore_and_reopen
|
||||
forcedelete test.db2
|
||||
} -body {
|
||||
sqlite3rbu_vacuum rbu test.db test.db2
|
||||
rbu step
|
||||
rbu close
|
||||
} -test {
|
||||
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
# 2016 April 15
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests for the RBU module. More specifically, it
|
||||
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
|
||||
# expected.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set ::testprefix rbuvacuum
|
||||
|
||||
proc do_rbu_vacuum_test {tn step} {
|
||||
uplevel [list do_test $tn.1 {
|
||||
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
|
||||
while 1 {
|
||||
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
if {$step==1} { rbu close }
|
||||
}
|
||||
rbu close
|
||||
} {SQLITE_DONE}]
|
||||
|
||||
uplevel [list do_execsql_test $tn.2 {
|
||||
PRAGMA integrity_check
|
||||
} ok]
|
||||
}
|
||||
|
||||
foreach step {0 1} {
|
||||
|
||||
set ::testprefix rbuvacuum-step=$step
|
||||
reset_db
|
||||
|
||||
# Simplest possible vacuum.
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8, 9);
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
do_rbu_vacuum_test 1.1 $step
|
||||
|
||||
# A vacuum that actually reclaims space.
|
||||
do_execsql_test 1.2.1 {
|
||||
INSERT INTO t1 VALUES(8, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(9, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(10, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(11, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(12, randomblob(900), randomblob(900));
|
||||
PRAGMA page_count;
|
||||
} {12}
|
||||
do_execsql_test 1.2.2 {
|
||||
DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
|
||||
PRAGMA page_count;
|
||||
} {12}
|
||||
do_rbu_vacuum_test 1.2.3 $step
|
||||
do_execsql_test 1.2.4 {
|
||||
PRAGMA page_count;
|
||||
} {3}
|
||||
|
||||
# Add an index to the table.
|
||||
do_execsql_test 1.3.1 {
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
INSERT INTO t1 VALUES(13, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(14, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(15, randomblob(900), randomblob(900));
|
||||
INSERT INTO t1 VALUES(16, randomblob(900), randomblob(900));
|
||||
PRAGMA page_count;
|
||||
} {18}
|
||||
do_execsql_test 1.3.2 {
|
||||
DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
|
||||
PRAGMA page_count;
|
||||
} {18}
|
||||
do_rbu_vacuum_test 1.3.3 $step
|
||||
do_execsql_test 1.3.4 {
|
||||
PRAGMA page_count;
|
||||
} {5}
|
||||
|
||||
# WITHOUT ROWID table.
|
||||
do_execsql_test 1.4.1 {
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
|
||||
INSERT INTO t2 VALUES(randomblob(900), 1, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 2, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 3, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 4, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 6, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 7, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 8, randomblob(900));
|
||||
|
||||
DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
|
||||
PRAGMA page_count;
|
||||
} {20}
|
||||
do_rbu_vacuum_test 1.4.2 $step
|
||||
do_execsql_test 1.4.3 {
|
||||
PRAGMA page_count;
|
||||
} {10}
|
||||
|
||||
# WITHOUT ROWID table with an index.
|
||||
do_execsql_test 1.4.1 {
|
||||
CREATE INDEX t2c ON t2(c);
|
||||
|
||||
INSERT INTO t2 VALUES(randomblob(900), 9, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 10, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 11, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 12, randomblob(900));
|
||||
INSERT INTO t2 VALUES(randomblob(900), 13, randomblob(900));
|
||||
|
||||
DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
|
||||
PRAGMA page_count;
|
||||
} {35}
|
||||
do_rbu_vacuum_test 1.4.2 $step
|
||||
do_execsql_test 1.4.3 {
|
||||
PRAGMA page_count;
|
||||
} {15}
|
||||
do_execsql_test 1.4.4 {
|
||||
VACUUM;
|
||||
PRAGMA page_count;
|
||||
} {15}
|
||||
|
||||
do_execsql_test 1.5.1 {
|
||||
CREATE TABLE t3(a, b, c);
|
||||
INSERT INTO t3 VALUES('a', 'b', 'c');
|
||||
INSERT INTO t3 VALUES('d', 'e', 'f');
|
||||
INSERT INTO t3 VALUES('g', 'h', 'i');
|
||||
}
|
||||
do_rbu_vacuum_test 1.5.2 $step
|
||||
do_execsql_test 1.5.3 {
|
||||
SELECT * FROM t3
|
||||
} {a b c d e f g h i}
|
||||
do_execsql_test 1.5.4 {
|
||||
CREATE INDEX t3a ON t3(a);
|
||||
CREATE INDEX t3b ON t3(b);
|
||||
CREATE INDEX t3c ON t3(c);
|
||||
INSERT INTO t3 VALUES('j', 'k', 'l');
|
||||
DELETE FROM t3 WHERE a = 'g';
|
||||
}
|
||||
do_rbu_vacuum_test 1.5.5 $step
|
||||
do_execsql_test 1.5.6 {
|
||||
SELECT rowid, * FROM t3 ORDER BY b
|
||||
} {1 a b c 2 d e f 4 j k l}
|
||||
|
||||
do_execsql_test 1.6.1 {
|
||||
CREATE TABLE t4(a PRIMARY KEY, b, c);
|
||||
INSERT INTO t4 VALUES('a', 'b', 'c');
|
||||
INSERT INTO t4 VALUES('d', 'e', 'f');
|
||||
INSERT INTO t4 VALUES('g', 'h', 'i');
|
||||
}
|
||||
do_rbu_vacuum_test 1.6.2 $step
|
||||
do_execsql_test 1.6.3 {
|
||||
SELECT * FROM t4
|
||||
} {a b c d e f g h i}
|
||||
do_execsql_test 1.6.4 {
|
||||
CREATE INDEX t4a ON t4(a);
|
||||
CREATE INDEX t4b ON t4(b);
|
||||
CREATE INDEX t4c ON t4(c);
|
||||
|
||||
INSERT INTO t4 VALUES('j', 'k', 'l');
|
||||
DELETE FROM t4 WHERE a='g';
|
||||
}
|
||||
do_rbu_vacuum_test 1.6.5 $step
|
||||
do_execsql_test 1.6.6 {
|
||||
SELECT * FROM t4 ORDER BY b
|
||||
} {a b c d e f j k l}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.7.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
|
||||
INSERT INTO t1 VALUES(NULL, 'one');
|
||||
INSERT INTO t1 VALUES(NULL, 'two');
|
||||
DELETE FROM t1 WHERE a=2;
|
||||
INSERT INTO t1 VALUES(NULL, 'three');
|
||||
INSERT INTO t1 VALUES(NULL, 'four');
|
||||
DELETE FROM t1 WHERE a=4;
|
||||
INSERT INTO t1 VALUES(NULL, 'five');
|
||||
INSERT INTO t1 VALUES(NULL, 'six');
|
||||
DELETE FROM t1 WHERE a=6;
|
||||
SELECT * FROM t1;
|
||||
} {1 one 3 three 5 five}
|
||||
do_rbu_vacuum_test 1.7.1 $step
|
||||
do_execsql_test 1.7.2 {
|
||||
INSERT INTO t1 VALUES(NULL, 'seven');
|
||||
SELECT * FROM t1;
|
||||
} {1 one 3 three 5 five 7 seven}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.8.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(NULL, 'one');
|
||||
INSERT INTO t1 VALUES(NULL, 'two');
|
||||
INSERT INTO t1 VALUES(NULL, 'three');
|
||||
INSERT INTO t1 VALUES(NULL, 'four');
|
||||
INSERT INTO t1 VALUES(NULL, 'five');
|
||||
INSERT INTO t1 VALUES(NULL, 'six');
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1;
|
||||
} {t1 i1 {6 1}}
|
||||
do_rbu_vacuum_test 1.8.1 $step
|
||||
do_execsql_test 1.7.2 {
|
||||
SELECT * FROM sqlite_stat1;
|
||||
} {t1 i1 {6 1}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.9.0 {
|
||||
PRAGMA page_size = 8192;
|
||||
PRAGMA auto_vacuum = 2;
|
||||
PRAGMA user_version = 412;
|
||||
PRAGMA application_id = 413;
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(NULL, 'one');
|
||||
INSERT INTO t1 VALUES(NULL, 'two');
|
||||
INSERT INTO t1 VALUES(NULL, 'three');
|
||||
INSERT INTO t1 VALUES(NULL, 'four');
|
||||
INSERT INTO t1 VALUES(NULL, 'five');
|
||||
INSERT INTO t1 VALUES(NULL, 'six');
|
||||
|
||||
PRAGMA main.page_size;
|
||||
PRAGMA main.auto_vacuum;
|
||||
PRAGMA main.user_version;
|
||||
PRAGMA main.application_id;
|
||||
} {8192 2 412 413}
|
||||
|
||||
do_rbu_vacuum_test 1.9.1 $step
|
||||
do_execsql_test 1.9.2 {
|
||||
PRAGMA main.page_size;
|
||||
PRAGMA main.auto_vacuum;
|
||||
PRAGMA main.user_version;
|
||||
PRAGMA main.application_id;
|
||||
} {8192 2 412 413}
|
||||
|
||||
# Vacuum a database with a large sqlite_master table.
|
||||
#
|
||||
reset_db
|
||||
do_test 1.10.1 {
|
||||
for {set i 1} {$i < 50} {incr i} {
|
||||
execsql "PRAGMA page_size = 1024"
|
||||
execsql "CREATE TABLE t$i (a, b, c, PRIMARY KEY(a, b));"
|
||||
execsql "
|
||||
INSERT INTO t$i VALUES(1, 2, 3);
|
||||
INSERT INTO t$i VALUES(4, 5, 6);
|
||||
"
|
||||
}
|
||||
} {}
|
||||
do_rbu_vacuum_test 1.10.2 $step
|
||||
|
||||
# Database with empty tables.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 1.11.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t4 VALUES(1, 2);
|
||||
}
|
||||
do_rbu_vacuum_test 1.11.2 $step
|
||||
do_execsql_test 1.11.3 {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
SELECT * FROM t4;
|
||||
} {1 2}
|
||||
reset_db
|
||||
do_execsql_test 1.12.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
do_rbu_vacuum_test 1.12.2 $step
|
||||
do_execsql_test 1.12.3 {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
SELECT * FROM t4;
|
||||
} {1 2}
|
||||
}
|
||||
set ::testprefix rbuvacuum
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test some error cases:
|
||||
#
|
||||
# 2.1.* the db being vacuumed being in wal mode already.
|
||||
# 2.2.* database modified mid vacuum.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
} wal
|
||||
do_test 2.1.1 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
rbu step
|
||||
} {SQLITE_ERROR}
|
||||
do_test 2.1.2 {
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.2.0 {
|
||||
CREATE TABLE tx(a PRIMARY KEY, b BLOB);
|
||||
INSERT INTO tx VALUES(1, randomblob(900));
|
||||
INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
|
||||
INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
|
||||
INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
|
||||
INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
|
||||
}
|
||||
db_save_and_close
|
||||
for {set i 1} 1 {incr i} {
|
||||
db_restore_and_reopen
|
||||
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
for {set step 0} {$step<$i} {incr step} { rbu step }
|
||||
rbu close
|
||||
if {[file exists test.db-wal]} break
|
||||
|
||||
execsql { INSERT INTO tx VALUES(20, 20) }
|
||||
|
||||
do_test 2.2.$i.1 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
rbu step
|
||||
} {SQLITE_BUSY}
|
||||
do_test 2.2.$i.2 {
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_BUSY - database modified during rbu vacuum}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a database that uses custom collation sequences can be RBU
|
||||
# vacuumed.
|
||||
#
|
||||
reset_db
|
||||
forcedelete state.db
|
||||
proc noop {args} {}
|
||||
proc length_cmp {x y} {
|
||||
set n1 [string length $x]
|
||||
set n2 [string length $y]
|
||||
return [expr $n1 - $n2]
|
||||
}
|
||||
sqlite3_create_collation_v2 db length length_cmp noop
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'i');
|
||||
INSERT INTO t1 VALUES(2, 'iiii');
|
||||
INSERT INTO t1 VALUES(3, 'ii');
|
||||
INSERT INTO t1 VALUES(4, 'iii');
|
||||
SELECT a FROM t1 ORDER BY b COLLATE length;
|
||||
} {1 3 4 2}
|
||||
do_execsql_test 3.1 {
|
||||
CREATE INDEX i1 ON t1(b COLLATE length);
|
||||
}
|
||||
|
||||
do_test 3.2 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_ERROR - no such collation sequence: length}}
|
||||
|
||||
do_test 3.3 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set db1 [rbu db 0]
|
||||
sqlite3_create_collation_v2 $db1 length length_cmp noop
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_ERROR - no such collation sequence: length}}
|
||||
|
||||
do_test 3.4 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set db1 [rbu db 1]
|
||||
sqlite3_create_collation_v2 $db1 length length_cmp noop
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_ERROR - no such collation sequence: length}}
|
||||
|
||||
do_test 3.5 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set db1 [rbu db 0]
|
||||
set db2 [rbu db 1]
|
||||
|
||||
sqlite3_create_collation_v2 $db1 length length_cmp noop
|
||||
sqlite3_create_collation_v2 $db2 length length_cmp noop
|
||||
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
|
||||
catch { db close }
|
||||
finish_test
|
||||
|
||||
+579
-179
File diff suppressed because it is too large
Load Diff
@@ -314,6 +314,38 @@ sqlite3rbu *sqlite3rbu_open(
|
||||
const char *zState
|
||||
);
|
||||
|
||||
/*
|
||||
** Open an RBU handle to perform an RBU vacuum on database file zTarget.
|
||||
** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
|
||||
** that it can be suspended and resumed like an RBU update.
|
||||
**
|
||||
** The second argument to this function, which may not be NULL, identifies
|
||||
** a database in which to store the state of the RBU vacuum operation if
|
||||
** it is suspended. The first time sqlite3rbu_vacuum() is called, to start
|
||||
** an RBU vacuum operation, the state database should either not exist or
|
||||
** be empty (contain no tables). If an RBU vacuum is suspended by calling
|
||||
** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
|
||||
** returned SQLITE_DONE, the vacuum state is stored in the state database.
|
||||
** The vacuum can be resumed by calling this function to open a new RBU
|
||||
** handle specifying the same target and state databases.
|
||||
**
|
||||
** This function does not delete the state database after an RBU vacuum
|
||||
** is completed, even if it created it. However, if the call to
|
||||
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
|
||||
** of the state tables within the state database are zeroed. This way,
|
||||
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
|
||||
** new RBU vacuum operation.
|
||||
**
|
||||
** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
|
||||
** describing the sqlite3rbu_create_vfs() API function below for
|
||||
** a description of the complications associated with using RBU with
|
||||
** zipvfs databases.
|
||||
*/
|
||||
sqlite3rbu *sqlite3rbu_vacuum(
|
||||
const char *zTarget,
|
||||
const char *zState
|
||||
);
|
||||
|
||||
/*
|
||||
** Internally, each RBU connection uses a separate SQLite database
|
||||
** connection to access the target and rbu update databases. This
|
||||
|
||||
+49
-2
@@ -20,8 +20,9 @@
|
||||
#include <tcl.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* From main.c (apparently...) */
|
||||
/* From main.c */
|
||||
extern const char *sqlite3ErrName(int);
|
||||
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
|
||||
|
||||
void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
|
||||
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
|
||||
@@ -66,7 +67,8 @@ static int test_sqlite3rbu_cmd(
|
||||
{"create_rbu_delta", 2, ""}, /* 2 */
|
||||
{"savestate", 2, ""}, /* 3 */
|
||||
{"dbMain_eval", 3, "SQL"}, /* 4 */
|
||||
{"bp_progress", 2, ""}, /* 5 */
|
||||
{"bp_progress", 2, ""}, /* 5 */
|
||||
{"db", 3, "RBU"}, /* 6 */
|
||||
{0,0,0}
|
||||
};
|
||||
int iCmd;
|
||||
@@ -149,6 +151,22 @@ static int test_sqlite3rbu_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 6: /* db */ {
|
||||
int bArg;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){
|
||||
ret = TCL_ERROR;
|
||||
}else{
|
||||
char zBuf[50];
|
||||
sqlite3 *db = sqlite3rbu_db(pRbu, bArg);
|
||||
if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){
|
||||
ret = TCL_ERROR;
|
||||
}else{
|
||||
Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: /* seems unlikely */
|
||||
assert( !"cannot happen" );
|
||||
break;
|
||||
@@ -187,6 +205,34 @@ static int test_sqlite3rbu(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
|
||||
*/
|
||||
static int test_sqlite3rbu_vacuum(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3rbu *pRbu = 0;
|
||||
const char *zCmd;
|
||||
const char *zTarget;
|
||||
const char *zStateDb = 0;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zCmd = Tcl_GetString(objv[1]);
|
||||
zTarget = Tcl_GetString(objv[2]);
|
||||
zStateDb = Tcl_GetString(objv[3]);
|
||||
|
||||
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
|
||||
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
|
||||
*/
|
||||
@@ -274,6 +320,7 @@ int SqliteRbu_Init(Tcl_Interp *interp){
|
||||
Tcl_ObjCmdProc *xProc;
|
||||
} aObjCmd[] = {
|
||||
{ "sqlite3rbu", test_sqlite3rbu },
|
||||
{ "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum },
|
||||
{ "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
|
||||
{ "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
|
||||
{ "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
|
||||
|
||||
@@ -17,6 +17,7 @@ if {![info exists testdir]} {
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionfault
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ if {![info exists testdir]} {
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
set testprefix sessionfault2
|
||||
|
||||
do_execsql_test 1.0.0 {
|
||||
|
||||
@@ -278,19 +278,18 @@ static int sessionVarintGet(u8 *aBuf, int *piVal){
|
||||
return getVarint32(aBuf, *piVal);
|
||||
}
|
||||
|
||||
/* Load an unaligned and unsigned 32-bit integer */
|
||||
#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
|
||||
|
||||
/*
|
||||
** Read a 64-bit big-endian integer value from buffer aRec[]. Return
|
||||
** the value read.
|
||||
*/
|
||||
static sqlite3_int64 sessionGetI64(u8 *aRec){
|
||||
return (((sqlite3_int64)aRec[0]) << 56)
|
||||
+ (((sqlite3_int64)aRec[1]) << 48)
|
||||
+ (((sqlite3_int64)aRec[2]) << 40)
|
||||
+ (((sqlite3_int64)aRec[3]) << 32)
|
||||
+ (((sqlite3_int64)aRec[4]) << 24)
|
||||
+ (((sqlite3_int64)aRec[5]) << 16)
|
||||
+ (((sqlite3_int64)aRec[6]) << 8)
|
||||
+ (((sqlite3_int64)aRec[7]) << 0);
|
||||
u64 x = SESSION_UINT32(aRec);
|
||||
u32 y = SESSION_UINT32(aRec+4);
|
||||
x = (x<<32) + y;
|
||||
return (sqlite3_int64)x;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -592,14 +591,19 @@ static int sessionChangeEqual(
|
||||
int iCol; /* Used to iterate through table columns */
|
||||
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
int n1 = sessionSerialLen(a1);
|
||||
int n2 = sessionSerialLen(a2);
|
||||
if( pTab->abPK[iCol] ){
|
||||
int n1 = sessionSerialLen(a1);
|
||||
int n2 = sessionSerialLen(a2);
|
||||
|
||||
if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
|
||||
return 0;
|
||||
if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
|
||||
return 0;
|
||||
}
|
||||
a1 += n1;
|
||||
a2 += n2;
|
||||
}else{
|
||||
if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1);
|
||||
if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2);
|
||||
}
|
||||
if( pTab->abPK[iCol] || bLeftPkOnly==0 ) a1 += n1;
|
||||
if( pTab->abPK[iCol] || bRightPkOnly==0 ) a2 += n2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -935,9 +939,9 @@ static int sessionTableInfo(
|
||||
int nDbCol = 0;
|
||||
int nThis;
|
||||
int i;
|
||||
u8 *pAlloc;
|
||||
u8 *pAlloc = 0;
|
||||
char **azCol = 0;
|
||||
u8 *abPK;
|
||||
u8 *abPK = 0;
|
||||
|
||||
assert( pazCol && pabPK );
|
||||
|
||||
@@ -1593,9 +1597,9 @@ static void sessionDeleteTable(SessionTable *pList){
|
||||
pNext = pTab->pNext;
|
||||
for(i=0; i<pTab->nChange; i++){
|
||||
SessionChange *p;
|
||||
SessionChange *pNext;
|
||||
for(p=pTab->apChange[i]; p; p=pNext){
|
||||
pNext = p->pNext;
|
||||
SessionChange *pNextChange;
|
||||
for(p=pTab->apChange[i]; p; p=pNextChange){
|
||||
pNextChange = p->pNext;
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
@@ -2882,7 +2886,6 @@ static int sessionChangesetNext(
|
||||
** modified fields are present in the new.* record. The old.* record
|
||||
** is currently completely empty. This block shifts the PK fields from
|
||||
** new.* to old.*, to accommodate the code that reads these arrays. */
|
||||
int i;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
assert( p->apValue[i]==0 );
|
||||
assert( p->abPK[i]==0 || p->apValue[i+p->nCol] );
|
||||
@@ -3655,7 +3658,7 @@ static int sessionConflictHandler(
|
||||
void *pCtx, /* First argument for conflict handler */
|
||||
int *pbReplace /* OUT: Set to true if PK row is found */
|
||||
){
|
||||
int res; /* Value returned by conflict handler */
|
||||
int res = 0; /* Value returned by conflict handler */
|
||||
int rc;
|
||||
int nCol;
|
||||
int op;
|
||||
|
||||
@@ -314,7 +314,8 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){
|
||||
pObj = Tcl_NewStringObj(z, n);
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB:
|
||||
default:
|
||||
assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
|
||||
Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("b", 1));
|
||||
pObj = Tcl_NewByteArrayObj(
|
||||
sqlite3_value_blob(pVal),
|
||||
@@ -871,7 +872,6 @@ static int test_sqlite3session_foreach(
|
||||
|
||||
pOld = Tcl_NewObj();
|
||||
if( op!=SQLITE_INSERT ){
|
||||
int i;
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
@@ -880,7 +880,6 @@ static int test_sqlite3session_foreach(
|
||||
}
|
||||
pNew = Tcl_NewObj();
|
||||
if( op!=SQLITE_DELETE ){
|
||||
int i;
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
C Add\sand\sadjust\scomments.
|
||||
D 2016-04-12T16:11:52.808
|
||||
F Makefile.in eba680121821b8a60940a81454316f47a341487a
|
||||
C Add\sthe\sexperimental\sSQLITE_FCNTL_WIN32_GET_HANDLE\sfile\scontrol.
|
||||
D 2016-05-03T19:36:54.758
|
||||
F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
|
||||
F Makefile.msc a7f34be67d16284e4208370365a9728094861194
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION 5d234da9b5dae329fab75ff75884cfe0a9cb3fda
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -10,11 +10,11 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40
|
||||
F autoconf/Makefile.msc dc0d0500e4a827cb3891d08d846dd6dd40241b51
|
||||
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
|
||||
F autoconf/Makefile.msc ac014aab0b8314d6baa30cbd1dd4ce983f306b5d
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff
|
||||
F autoconf/configure.ac e2299fe80eb256dafdc68cf250e37ea1a0a6ec71
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -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 dbd42c55ca6b65e0fb37ef54121755f26a890edf x
|
||||
F configure.ac 89e4e02a83d8a1528011f8395621b8c3186b4089
|
||||
F configure df9f793ad47eaeb3648a9090fbc0b96955e88b5a x
|
||||
F configure.ac 02b972db825685b4b0cca0234b2aa97f71bd15a5
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html e2118945e5f07ed146b45c9cd2b2dd6eabb8ebf2
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -81,7 +81,7 @@ F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
|
||||
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
|
||||
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
|
||||
F ext/fts3/fts3_test.c 11e36437b0f3f2266acea5b4787f615e4337a237
|
||||
F ext/fts3/fts3_test.c a940cf104d545ad1abf926956ce65db2aa5af0cf
|
||||
F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
|
||||
F ext/fts3/fts3_tokenizer.c 3cf21cd2212db17a88d4ef7da0fd8a80275979a1
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
@@ -91,7 +91,7 @@ F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5
|
||||
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
|
||||
@@ -103,8 +103,8 @@ F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458
|
||||
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
|
||||
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
|
||||
F ext/fts5/fts5_expr.c 5ca4bafe29aa3d27683c90e836192e4aefd20a3f
|
||||
F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337
|
||||
F ext/fts5/fts5_index.c fdd82bb421a5d1e64d004acb43f4dd9970c8d2b3
|
||||
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
|
||||
F ext/fts5/fts5_index.c b429e23fabb57506f71e406997cc46b89190dc97
|
||||
F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55
|
||||
F ext/fts5/fts5_storage.c 3309c6a8e34b974513016fd1ef47c83f5898f94c
|
||||
F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
|
||||
@@ -201,28 +201,28 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c 4bdf4c5daedabcd8e6eb6e6a377657f7b978f9f7
|
||||
F ext/icu/icu.c 43df9d8ef2fae7a325100ebd713ab089dc829dd7
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb
|
||||
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c b9c88d5c3b6ecd8c731ffdd7f5b3d902857f8c96
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 598bbc45516227701558becdd38f4e6fe8e97cc2
|
||||
F ext/misc/spellfix.c bf1b922c2750698e9a3d4c50cce6974adb7e93be
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/rbu/rbu.c ba3983dceffa0938532e79142f391737513de023
|
||||
F ext/rbu/rbu.c b2c0b5e6ae1a89affc0edfc127ebfa5f637a0ce4
|
||||
F ext/rbu/rbu1.test 42bd835e019eff789ec241017965277baeb658b1
|
||||
F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d
|
||||
F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
|
||||
@@ -243,12 +243,14 @@ F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
|
||||
F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091
|
||||
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
|
||||
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
|
||||
F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
|
||||
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
|
||||
F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
F ext/rbu/sqlite3rbu.c 007fc4db8c0b95c7ef10162b5864921ef5cc8106
|
||||
F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2
|
||||
F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d
|
||||
F ext/rbu/rbuvacuum.test 66e02cf299836770e718e95c36686be0b26dbda3
|
||||
F ext/rbu/sqlite3rbu.c bf36625990c6865ecf08bd844d8097ed2d0a6958
|
||||
F ext/rbu/sqlite3rbu.h 2acd0a6344a6079de15c8dc9d84d3df83a665930
|
||||
F ext/rbu/test_rbu.c 9bbdf6bd8efd58fbc4f192698df50569598fbb9e
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
@@ -289,11 +291,11 @@ F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
|
||||
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
|
||||
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
|
||||
F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
|
||||
F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40
|
||||
F ext/session/sessionfault2.test ac1dfd77a0fb0ea310aee40a16645ef1b66d3f88
|
||||
F ext/session/sqlite3session.c 2fc72bd989c424a15802da766c7ebd8eed47bcf6
|
||||
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
|
||||
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
|
||||
F ext/session/sqlite3session.c 37485891b4add26cf61495df193c419f36556a32
|
||||
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
|
||||
F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce
|
||||
F ext/session/test_session.c 464f2c8bf502795d95969387eb8e93f68c513c15
|
||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
@@ -322,32 +324,32 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
|
||||
F src/btree.c 3ae6aea66cc4e13d30162ff0d0d43c7088e34abf
|
||||
F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9
|
||||
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
|
||||
F src/build.c 1944d95f0250ec72dab939f8319a12e237aaad61
|
||||
F src/build.c 42e8ee74dfa3a4b99bfb2c201f8a66ab50688d95
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
|
||||
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
|
||||
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
|
||||
F src/delete.c 78eb999114ec04fcf1b7d123ccedb4b5b734930e
|
||||
F src/expr.c 17d4e745ef6a3fd2e4ef863f5f9a4912f1ba1198
|
||||
F src/delete.c 362f89f8e6783e672c4ab06b90fca0177f9a576d
|
||||
F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb
|
||||
F src/func.c 552d300265aed09eea21f68ac742a440550c0062
|
||||
F src/func.c ef4c18c8a66143413ce41a58d582d2c14ddf78e1
|
||||
F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
|
||||
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
|
||||
F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002
|
||||
F src/main.c 5ac9dccc03faadd6f867f67b9018ff41eeeadb46
|
||||
F src/loadext.c 8b3a73f0624c5f7cadbd5cb89940783bee1d39a6
|
||||
F src/main.c 405d13e3a4f7c5add9fb27702ae70ed0a6e32cca
|
||||
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memjournal.c 2815ef7684671d93a1ec6a31e1e63c45de4b4d31
|
||||
F src/memjournal.c 95752936c11dc6995672d1dd783cd633eea0cc95
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
@@ -355,42 +357,42 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c ca10edb445ad2c5fdc7285b49d72bcdf261fa23e
|
||||
F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1
|
||||
F src/os.c 4d83917f072ad958fba9235136fa2ed43df47905
|
||||
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c bde4844f0849cab5924c6a81178f8500774ce76b
|
||||
F src/os_win.c b169437dff859e308b3726594094a2f8ca922941
|
||||
F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
|
||||
F src/os_win.c 75edd38c5efbb177cbfdce7128635a2bb53cf16c
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d
|
||||
F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56
|
||||
F src/pager.c a8d30c49c231e9a20d05257613db922532588963
|
||||
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
|
||||
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
|
||||
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
|
||||
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
|
||||
F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05
|
||||
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
|
||||
F src/pcache.h 6b865be765d1ebd06145219550b10921c7da7cc9
|
||||
F src/pcache1.c 7f51d2b541aab57596adf62db2c4bb025d34f04d
|
||||
F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e
|
||||
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
|
||||
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
|
||||
F src/select.c d9b8628acb98f1a38921888d823a6b70c7a7774b
|
||||
F src/shell.c b7922fa264f8c8d72a5ec6dd0b091e15a93c4de5
|
||||
F src/sqlite.h.in c8f41612dc1a9b5212a891e1b65a5f589b8b884a
|
||||
F src/rowset.c 49eb91c588a2bab36647368e031dc5b66928149d
|
||||
F src/select.c fd4a7ce2937497181063cfedb92058ac89491a5d
|
||||
F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6
|
||||
F src/sqlite.h.in 07a295a39a41cfd136bf63bdcfe478caaee78042
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2
|
||||
F src/sqliteInt.h b3744b29555b83054f315f62d61b3a6558fa9e1c
|
||||
F src/sqliteInt.h f4a53f3547dab80dc7db975fa1192d9bad1f38e8
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
F src/tclsqlite.c 56569acc73d36e836b64aefecbbb709a92ba0077
|
||||
F src/test1.c 7187b7e924bfc97780e6fd2a40dad94a32bddca0
|
||||
F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060
|
||||
F src/test1.c 7862c314d742153639ecb6ec2daf29936cc066cd
|
||||
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
||||
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
|
||||
F src/test3.c 0df6f8dbb4cbaa7106397c70a271fa6a43659042
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
F src/test6.c 2c014d4977efd6107ec9eef3dfdec56ac516f824
|
||||
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
|
||||
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
@@ -402,21 +404,21 @@ F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c 7003f6f35134de6f19c6588f44783e43390ea277
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
|
||||
F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b
|
||||
F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950
|
||||
F src/test_multiplex.c 6a9de820fcaaf506c59aa14bc8693822333cea48
|
||||
F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c
|
||||
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
|
||||
F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196
|
||||
F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f
|
||||
F src/test_osinst.c ad0233b1dabb0390e25edded4ebd79a2a61538c6
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
@@ -425,40 +427,40 @@ F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
|
||||
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
|
||||
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_syscall.c 268c072541162564a882c57f54a6fee12ef4a4d2
|
||||
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61
|
||||
F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c
|
||||
F src/tokenize.c 3b29883b0ce4a6c6f643965b66b5ca6613178e59
|
||||
F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373
|
||||
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
|
||||
F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c 187a0a2aaa3c5d2ccd2ab0143b2fd9e86d6bc816
|
||||
F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
|
||||
F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52
|
||||
F src/vdbe.c d3843a66d74a7696477ee5141e5eb9a7e5e2401c
|
||||
F src/vdbe.c 4bad04212736526845fda9ca674afafb10078b2b
|
||||
F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170
|
||||
F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd
|
||||
F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
|
||||
F src/vdbeaux.c ace1875da40b7185e604586768d5ac90de7e4f7f
|
||||
F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77
|
||||
F src/vdbemem.c 5cfef60e60e19cab6275d1b975bf4c791d575beb
|
||||
F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062
|
||||
F src/vdbesort.c 0a8f98366ae794442e6d1ef71d9553226d885d19
|
||||
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
|
||||
F src/vtab.c 23b6cdfa996152d43b390504ed4a942c8caf3a00
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b
|
||||
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
|
||||
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
|
||||
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
|
||||
F src/where.c 24ab561466d92d313747c04edb1a36a7af8663be
|
||||
F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34
|
||||
F src/wherecode.c 8fdad9fbba723df1c1e8d07e7ea8507572040340
|
||||
F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a
|
||||
F src/where.c 019e5b10dedcf54ef077ce23dd8fce38d614dcf4
|
||||
F src/whereInt.h 3b1fc240e322613ba4e9dc857ca9c7c3390acc74
|
||||
F src/wherecode.c 28951741be3974701186281ced0564e9586a0db3
|
||||
F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -510,7 +512,7 @@ F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
|
||||
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
|
||||
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
@@ -551,7 +553,7 @@ F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
|
||||
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
@@ -610,12 +612,12 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
|
||||
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
|
||||
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
F test/delete4.test 738044ee892ee0c84e0848e36ba92c55f907d52b
|
||||
F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
|
||||
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
@@ -642,7 +644,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
|
||||
F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
|
||||
F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc
|
||||
F test/e_vacuum.test 120f29ea56bdce4d43279527ece894ab5d1729d3
|
||||
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
||||
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
|
||||
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
|
||||
@@ -657,12 +659,12 @@ F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
|
||||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
|
||||
F test/filectrl.test c6547e6c3c4c3ef9707a0b3dc147de718135cacc
|
||||
F test/filefmt.test e4edbdc637ca9576ccf4337a3cce627d9df7a56c
|
||||
F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c
|
||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||
@@ -806,7 +808,7 @@ F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 40523db3aa76d62bda71c26f824fa0eabc420f0e
|
||||
F test/hook.test 3b7b99d0eece6d279812c2aef6fa08bdfabc633e
|
||||
F test/icu.test 73956798bace8982909c00476b216714a6d0559a
|
||||
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
@@ -823,7 +825,7 @@ F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
|
||||
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
|
||||
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
|
||||
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
|
||||
F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac
|
||||
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
|
||||
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
|
||||
@@ -845,7 +847,7 @@ F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
|
||||
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
|
||||
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
|
||||
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
|
||||
F test/intpkey.test 70aab09756b9bd3bcb6b0358f971d7bbace46522
|
||||
F test/intpkey.test 153b70e32d008f4f4b2dff8daf448a6110b62a9c
|
||||
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
|
||||
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
|
||||
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
|
||||
@@ -860,7 +862,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
|
||||
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
|
||||
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
|
||||
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
@@ -875,9 +877,9 @@ F test/like.test 81632c437a947bf1f7130b19537da6a1a844806a
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
|
||||
F test/loadext.test 42a3b8166dfcadcb0e0c8710dc520d97c31a8b98
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5
|
||||
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
|
||||
@@ -966,7 +968,7 @@ F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
|
||||
F test/pagerfault.test 42ff797b1e6426c141cc7ee8b7417c9f27427950
|
||||
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
|
||||
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
|
||||
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
|
||||
@@ -975,10 +977,10 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test cd1fa041074ed08eeaa563e4d1bacb0c69337ec1
|
||||
F test/pragma.test afbf028be1c35b68f57db8eb015c4a3c59d8f28e
|
||||
F test/permutations.test b6b3e165fdc1b8c82a820033646dbfc6a7a01746
|
||||
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
@@ -986,7 +988,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
|
||||
F test/quota.test 36cd78b178c4eb0401d4f25754ef410fbd9df2a7
|
||||
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
|
||||
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
@@ -996,7 +998,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl f2519836bebefcc7db36b4946e8028d4885baa59
|
||||
F test/releasetest.tcl 7d80014d0245b3f9d02d393d420bf03ca155aec0
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
|
||||
@@ -1024,7 +1026,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c
|
||||
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61
|
||||
@@ -1051,7 +1053,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test b3df199cef9bc722d4078c893a7093d31174ea11
|
||||
F test/shell1.test 023657b3f8ba108dbd5ff2ebc8fceb3cf6d4ff9f
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd
|
||||
F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9
|
||||
@@ -1065,7 +1067,7 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/snapshot.test 9ed24c792fb05382814258daf68b2256f23de57f
|
||||
F test/snapshot.test 3adc4ef09d407b501f899a6c329bdf45dc725c1b
|
||||
F test/snapshot_fault.test 062ff0438a074978d45e9f9a92e7ad459b74ee73
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||
@@ -1073,7 +1075,7 @@ F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
|
||||
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
|
||||
F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
|
||||
F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
|
||||
F test/sort5.test d3041ce3c475aa04142a959ae56ef6593f98a99f
|
||||
F test/sort5.test e47ec7a490b9b36787755874175d8f413a3883d9
|
||||
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
|
||||
@@ -1083,14 +1085,14 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 21af8db2492a903835b654517ac8d90aed0af91f
|
||||
F test/speedtest1.c 4476f7030775507f060d27b789e1f4123c5a5866
|
||||
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
|
||||
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77
|
||||
F test/stat.test 66e95f97b9f724f9ab921d054ee0db3c2689f1ee
|
||||
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
||||
F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f
|
||||
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
|
||||
@@ -1100,7 +1102,7 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
|
||||
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
|
||||
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
|
||||
F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899
|
||||
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
|
||||
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906
|
||||
@@ -1109,9 +1111,11 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
|
||||
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl 7b740ee852c55e1e72b6ebe5044acee7aa4e5553
|
||||
F test/tester.tcl 3ace46dee55f07e28a1e3ab03258b929fefcee5b
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1127,10 +1131,10 @@ F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
|
||||
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
|
||||
F test/tkt-2d1a5c67d.test d371279946622698ab393ff88cad9f5f6d82960b
|
||||
F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
|
||||
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
||||
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
|
||||
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
|
||||
F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
|
||||
F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e
|
||||
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
|
||||
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
|
||||
@@ -1141,7 +1145,7 @@ F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
|
||||
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
|
||||
F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
|
||||
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
|
||||
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa
|
||||
F test/tkt-5d863f876e.test 726e76d725f6fe0eb2fc8a522b721b79807380ee
|
||||
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
|
||||
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
|
||||
@@ -1157,7 +1161,7 @@ F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed
|
||||
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
|
||||
F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
|
||||
F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667
|
||||
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
|
||||
F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6
|
||||
F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8
|
||||
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
|
||||
F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
|
||||
@@ -1396,7 +1400,7 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
|
||||
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||
F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test 2d725c214b883e25ae6bb85ef228ecdfa03c6a7b
|
||||
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
@@ -1412,10 +1416,10 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c cfbfe061a4b2766512f6b484882eee2c86a14506
|
||||
F tool/lemon.c f38a55106d79b7a4c063abb958517d6c47dc6ac7
|
||||
F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
|
||||
F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22
|
||||
F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
|
||||
@@ -1436,7 +1440,7 @@ F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
|
||||
F tool/showdb.c 82dca79a999b2701c62417636345e9974151fdad
|
||||
F tool/showdb.c c695a5d5c8110640e0d9fadf5e254da90c79c36e
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c bda40d6e395df7edb6e9ea630784d3d762c35b4b
|
||||
@@ -1450,7 +1454,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c ca315aca4e2d24233e8f2000edea5880c53d1875
|
||||
F tool/srcck1.c 4f65e1a6748e42f24c0ea629dddc934d821c729a
|
||||
F tool/srcck1.c 4c39bdfa9a92edd20233ee720df84dbeb2417602
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
|
||||
@@ -1482,7 +1486,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 b35bb928b25492f6dd71ccf9c250cb9f0cce09ff
|
||||
R 042928a9099251248649d958d8ea8130
|
||||
P bcaa650e8796984b275eceba0ed477f360295d01
|
||||
R 7e9bbb4137cb671c555aabb8a094cd9b
|
||||
T *branch * win32GetHandle
|
||||
T *sym-win32GetHandle *
|
||||
T -sym-trunk *
|
||||
U mistachkin
|
||||
Z 2dd922c09a9ceb4b9c3491d0203a672b
|
||||
Z e75ba582b3d5fa180704c51e0604373b
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
541c6da23850673f5d2a2e31c3967b796ee2effc
|
||||
b6ddabe1818c36007c476a31e2e35755630a5f14
|
||||
@@ -1086,6 +1086,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
|
||||
zType = z + sqlite3Strlen30(z) + 1;
|
||||
memcpy(zType, pType->z, pType->n);
|
||||
zType[pType->n] = 0;
|
||||
sqlite3Dequote(zType);
|
||||
pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
}
|
||||
|
||||
+3
-2
@@ -239,11 +239,12 @@ void sqlite3DeleteFrom(
|
||||
int addrBypass = 0; /* Address of jump over the delete logic */
|
||||
int addrLoop = 0; /* Top of the delete loop */
|
||||
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
|
||||
int bComplex; /* True if there are triggers or FKs or or
|
||||
** subqueries in the WHERE clause */
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
int isView; /* True if attempting to delete from a view */
|
||||
Trigger *pTrigger; /* List of table triggers, if required */
|
||||
int bComplex; /* True if there are either triggers or FKs */
|
||||
#endif
|
||||
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
@@ -271,7 +272,6 @@ void sqlite3DeleteFrom(
|
||||
#else
|
||||
# define pTrigger 0
|
||||
# define isView 0
|
||||
# define bComplex 0
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VIEW
|
||||
# undef isView
|
||||
@@ -374,6 +374,7 @@ void sqlite3DeleteFrom(
|
||||
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
||||
{
|
||||
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
|
||||
if( pWhere && ExprHasProperty(pWhere, EP_Subquery) ) bComplex = 1;
|
||||
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
|
||||
if( HasRowid(pTab) ){
|
||||
/* For a rowid table, initialize the RowSet to an empty set */
|
||||
|
||||
+2
-2
@@ -2360,7 +2360,7 @@ static void cacheEntryClear(Parse *pParse, struct yColCache *p){
|
||||
}
|
||||
p->iReg = 0;
|
||||
pParse->nColCache--;
|
||||
assert( cacheIsValid(pParse) );
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
}
|
||||
|
||||
|
||||
@@ -2405,7 +2405,7 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
pParse->nColCache++;
|
||||
assert( cacheIsValid(pParse) );
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1386,6 +1386,14 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
char *zErrMsg = 0;
|
||||
|
||||
/* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc
|
||||
** flag is set. See the sqlite3_enable_load_extension() API.
|
||||
*/
|
||||
if( (db->flags & SQLITE_LoadExtFunc)==0 ){
|
||||
sqlite3_result_error(context, "not authorized", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
if( argc==2 ){
|
||||
zProc = (const char *)sqlite3_value_text(argv[1]);
|
||||
}else{
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ void sqlite3HashClear(Hash *pH){
|
||||
static unsigned int strHash(const char *z){
|
||||
unsigned int h = 0;
|
||||
unsigned char c;
|
||||
while( (c = (unsigned char)*z++)!=0 ){
|
||||
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
|
||||
}
|
||||
return h;
|
||||
@@ -148,7 +148,7 @@ static HashElem *findElementWithHash(
|
||||
int count; /* Number of elements left to test */
|
||||
unsigned int h; /* The computed hash */
|
||||
|
||||
if( pH->ht ){
|
||||
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
struct _ht *pEntry;
|
||||
h = strHash(pKey) % pH->htsize;
|
||||
pEntry = &pH->ht[h];
|
||||
|
||||
+5
-4
@@ -464,8 +464,9 @@ static int sqlite3LoadExtension(
|
||||
/* Ticket #1863. To avoid a creating security problems for older
|
||||
** applications that relink against newer versions of SQLite, the
|
||||
** ability to run load_extension is turned off by default. One
|
||||
** must call sqlite3_enable_load_extension() to turn on extension
|
||||
** loading. Otherwise you get the following error.
|
||||
** must call either sqlite3_enable_load_extension(db) or
|
||||
** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0)
|
||||
** to turn on extension loading.
|
||||
*/
|
||||
if( (db->flags & SQLITE_LoadExtension)==0 ){
|
||||
if( pzErrMsg ){
|
||||
@@ -604,9 +605,9 @@ void sqlite3CloseExtensions(sqlite3 *db){
|
||||
int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( onoff ){
|
||||
db->flags |= SQLITE_LoadExtension;
|
||||
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
|
||||
}else{
|
||||
db->flags &= ~SQLITE_LoadExtension;
|
||||
db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
|
||||
}
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_OK;
|
||||
|
||||
@@ -804,6 +804,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
|
||||
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
|
||||
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
|
||||
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
|
||||
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
|
||||
};
|
||||
unsigned int i;
|
||||
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
** This file contains code use to implement an in-memory rollback journal.
|
||||
** The in-memory rollback journal is used to journal transactions for
|
||||
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
|
||||
**
|
||||
** Update: The in-memory journal is also used to temporarily cache
|
||||
** smaller journals that are not critical for power-loss recovery.
|
||||
** For example, statement journals that are not too big will be held
|
||||
** entirely in memory, thus reducing the number of file I/O calls, and
|
||||
** more importantly, reducing temporary file creation events. If these
|
||||
** journals become too large for memory, they are spilled to disk. But
|
||||
** in the common case, they are usually small and no file I/O needs to
|
||||
** occur.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
||||
@@ -81,13 +81,11 @@ int sqlite3_memdebug_vfs_oom_test = 1;
|
||||
** of this would be completely automatic if SQLite were coded using
|
||||
** C++ instead of plain old C.
|
||||
*/
|
||||
int sqlite3OsClose(sqlite3_file *pId){
|
||||
int rc = SQLITE_OK;
|
||||
void sqlite3OsClose(sqlite3_file *pId){
|
||||
if( pId->pMethods ){
|
||||
rc = pId->pMethods->xClose(pId);
|
||||
pId->pMethods->xClose(pId);
|
||||
pId->pMethods = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
@@ -305,12 +303,10 @@ int sqlite3OsOpenMalloc(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsCloseFree(sqlite3_file *pFile){
|
||||
int rc = SQLITE_OK;
|
||||
void sqlite3OsCloseFree(sqlite3_file *pFile){
|
||||
assert( pFile );
|
||||
rc = sqlite3OsClose(pFile);
|
||||
sqlite3OsClose(pFile);
|
||||
sqlite3_free(pFile);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -160,7 +160,7 @@ int sqlite3OsInit(void);
|
||||
/*
|
||||
** Functions for accessing sqlite3_file methods
|
||||
*/
|
||||
int sqlite3OsClose(sqlite3_file*);
|
||||
void sqlite3OsClose(sqlite3_file*);
|
||||
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
|
||||
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
|
||||
int sqlite3OsTruncate(sqlite3_file*, i64 size);
|
||||
@@ -205,6 +205,6 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
|
||||
** sqlite3_malloc() to obtain space for the file-handle structure.
|
||||
*/
|
||||
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
|
||||
int sqlite3OsCloseFree(sqlite3_file *);
|
||||
void sqlite3OsCloseFree(sqlite3_file *);
|
||||
|
||||
#endif /* _SQLITE_OS_H_ */
|
||||
|
||||
+22
-14
@@ -405,7 +405,7 @@ static struct unix_syscall {
|
||||
#else
|
||||
{ "pread64", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
|
||||
#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
|
||||
|
||||
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
||||
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
||||
@@ -423,7 +423,7 @@ static struct unix_syscall {
|
||||
#else
|
||||
{ "pwrite64", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
|
||||
aSyscall[13].pCurrent)
|
||||
|
||||
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
|
||||
@@ -4288,10 +4288,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
pShmNode->h = -1;
|
||||
pDbFd->pInode->pShmNode = pShmNode;
|
||||
pShmNode->pInode = pDbFd->pInode;
|
||||
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->mutex==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->mutex==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
}
|
||||
|
||||
if( pInode->bProcessLock==0 ){
|
||||
@@ -5410,20 +5412,24 @@ static const char *unixTempFileDir(void){
|
||||
"/tmp",
|
||||
"."
|
||||
};
|
||||
unsigned int i;
|
||||
unsigned int i = 0;
|
||||
struct stat buf;
|
||||
const char *zDir = sqlite3_temp_directory;
|
||||
|
||||
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
|
||||
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
|
||||
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
|
||||
if( zDir==0 ) continue;
|
||||
if( osStat(zDir, &buf) ) continue;
|
||||
if( !S_ISDIR(buf.st_mode) ) continue;
|
||||
if( osAccess(zDir, 07) ) continue;
|
||||
break;
|
||||
while(1){
|
||||
if( zDir!=0
|
||||
&& osStat(zDir, &buf)==0
|
||||
&& S_ISDIR(buf.st_mode)
|
||||
&& osAccess(zDir, 03)==0
|
||||
){
|
||||
return zDir;
|
||||
}
|
||||
if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
|
||||
zDir = azDirs[i++];
|
||||
}
|
||||
return zDir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5439,9 +5445,11 @@ static int unixGetTempname(int nBuf, char *zBuf){
|
||||
** using the io-error infrastructure to test that SQLite handles this
|
||||
** function failing.
|
||||
*/
|
||||
zBuf[0] = 0;
|
||||
SimulateIOError( return SQLITE_IOERR );
|
||||
|
||||
zDir = unixTempFileDir();
|
||||
if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
|
||||
do{
|
||||
u64 r;
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
|
||||
+16
-9
@@ -1260,8 +1260,8 @@ int sqlite3_win32_reset_heap(){
|
||||
int rc;
|
||||
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
|
||||
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
|
||||
MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
|
||||
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
|
||||
sqlite3_mutex_enter(pMaster);
|
||||
sqlite3_mutex_enter(pMem);
|
||||
winMemAssertMagic();
|
||||
@@ -3169,9 +3169,8 @@ static int winLock(sqlite3_file *id, int locktype){
|
||||
** the PENDING_LOCK byte is temporary.
|
||||
*/
|
||||
newLocktype = pFile->locktype;
|
||||
if( (pFile->locktype==NO_LOCK)
|
||||
|| ( (locktype==EXCLUSIVE_LOCK)
|
||||
&& (pFile->locktype==RESERVED_LOCK))
|
||||
if( pFile->locktype==NO_LOCK
|
||||
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
|
||||
){
|
||||
int cnt = 3;
|
||||
while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
|
||||
@@ -3435,6 +3434,12 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_WIN32_GET_HANDLE: {
|
||||
LPHANDLE phFile = (LPHANDLE)pArg;
|
||||
*phFile = pFile->h;
|
||||
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#ifdef SQLITE_TEST
|
||||
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
|
||||
LPHANDLE phFile = (LPHANDLE)pArg;
|
||||
@@ -3765,10 +3770,12 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
pShmNode->pNext = winShmNodeList;
|
||||
winShmNodeList = pShmNode;
|
||||
|
||||
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->mutex==0 ){
|
||||
rc = SQLITE_IOERR_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->mutex==0 ){
|
||||
rc = SQLITE_IOERR_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
}
|
||||
|
||||
rc = winOpen(pDbFd->pVfs,
|
||||
|
||||
+88
-45
@@ -872,6 +872,7 @@ static int assert_pager_state(Pager *p){
|
||||
** state.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
assert( !isOpen(p->fd) );
|
||||
assert( p->noSync );
|
||||
assert( p->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| p->journalMode==PAGER_JOURNALMODE_MEMORY
|
||||
@@ -958,7 +959,7 @@ static int assert_pager_state(Pager *p){
|
||||
** back to OPEN state.
|
||||
*/
|
||||
assert( pPager->errCode!=SQLITE_OK );
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1170,6 +1171,8 @@ static int jrnlBufferSize(Pager *pPager){
|
||||
|
||||
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
|
||||
}
|
||||
#else
|
||||
# define jrnlBufferSize(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1818,13 +1821,17 @@ static void pager_unlock(Pager *pPager){
|
||||
** it can safely move back to PAGER_OPEN state. This happens in both
|
||||
** normal and exclusive-locking mode.
|
||||
*/
|
||||
assert( pPager->errCode==SQLITE_OK || !MEMDB );
|
||||
if( pPager->errCode ){
|
||||
assert( !MEMDB );
|
||||
pager_reset(pPager);
|
||||
pPager->changeCountDone = pPager->tempFile;
|
||||
pPager->eState = PAGER_OPEN;
|
||||
pPager->errCode = SQLITE_OK;
|
||||
if( pPager->tempFile==0 ){
|
||||
pager_reset(pPager);
|
||||
pPager->changeCountDone = 0;
|
||||
pPager->eState = PAGER_OPEN;
|
||||
}else{
|
||||
pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
|
||||
}
|
||||
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
|
||||
pPager->errCode = SQLITE_OK;
|
||||
}
|
||||
|
||||
pPager->journalOff = 0;
|
||||
@@ -1868,6 +1875,25 @@ static int pager_error(Pager *pPager, int rc){
|
||||
|
||||
static int pager_truncate(Pager *pPager, Pgno nPage);
|
||||
|
||||
/*
|
||||
** The write transaction open on the pager passed as the only argument is
|
||||
** being committed. This function returns true if all dirty pages should
|
||||
** be flushed to disk, or false otherwise. Pages should be flushed to disk
|
||||
** unless one of the following is true:
|
||||
**
|
||||
** * The db is an in-memory database.
|
||||
**
|
||||
** * The db is a temporary database and the db file has not been opened.
|
||||
**
|
||||
** * The db is a temporary database and the cache contains less than
|
||||
** C/4 dirty pages, where C is the configured cache-size.
|
||||
*/
|
||||
static int pagerFlushOnCommit(Pager *pPager){
|
||||
if( pPager->tempFile==0 ) return 1;
|
||||
if( !isOpen(pPager->fd) ) return 0;
|
||||
return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine ends a transaction. A transaction is usually ended by
|
||||
** either a COMMIT or a ROLLBACK operation. This routine may be called
|
||||
@@ -2006,7 +2032,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
sqlite3BitvecDestroy(pPager->pInJournal);
|
||||
pPager->pInJournal = 0;
|
||||
pPager->nRec = 0;
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
if( MEMDB || pagerFlushOnCommit(pPager) ){
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
}else{
|
||||
sqlite3PcacheClearWritable(pPager->pPCache);
|
||||
}
|
||||
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
@@ -2291,7 +2321,7 @@ static int pager_playback_one_page(
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
assert( pPg || !MEMDB );
|
||||
assert( pPager->eState!=PAGER_OPEN || pPg==0 );
|
||||
assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
|
||||
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
|
||||
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
|
||||
(isMainJrnl?"main-journal":"sub-journal")
|
||||
@@ -2374,9 +2404,13 @@ static int pager_playback_one_page(
|
||||
** be written out into the database file before its journal file
|
||||
** segment is synced. If a crash occurs during or following this,
|
||||
** database corruption may ensue.
|
||||
**
|
||||
** Update: Another exception is for temp files that are not
|
||||
** in-memory databases. In this case the page may have been dirty
|
||||
** at the start of the transaction.
|
||||
*/
|
||||
assert( !pagerUseWal(pPager) );
|
||||
sqlite3PcacheMakeClean(pPg);
|
||||
if( pPager->tempFile==0 ) sqlite3PcacheMakeClean(pPg);
|
||||
}
|
||||
pager_set_pagehash(pPg);
|
||||
|
||||
@@ -3168,6 +3202,8 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
*/
|
||||
assert( pPager->eState==PAGER_OPEN );
|
||||
assert( pPager->eLock>=SHARED_LOCK );
|
||||
assert( isOpen(pPager->fd) );
|
||||
assert( pPager->tempFile==0 );
|
||||
nPage = sqlite3WalDbsize(pPager->pWal);
|
||||
|
||||
/* If the number of pages in the database is not available from the
|
||||
@@ -3175,14 +3211,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
** the database file. If the size of the database file is not an
|
||||
** integer multiple of the page-size, round up the result.
|
||||
*/
|
||||
if( nPage==0 ){
|
||||
if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
|
||||
i64 n = 0; /* Size of db file in bytes */
|
||||
assert( isOpen(pPager->fd) || pPager->tempFile );
|
||||
if( isOpen(pPager->fd) ){
|
||||
int rc = sqlite3OsFileSize(pPager->fd, &n);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
int rc = sqlite3OsFileSize(pPager->fd, &n);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
|
||||
}
|
||||
@@ -4258,8 +4291,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
|
||||
|
||||
/* This function is only called for rollback pagers in WRITER_DBMOD state. */
|
||||
assert( !pagerUseWal(pPager) );
|
||||
assert( pPager->eState==PAGER_WRITER_DBMOD );
|
||||
assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
|
||||
assert( pPager->eLock==EXCLUSIVE_LOCK );
|
||||
assert( isOpen(pPager->fd) || pList->pDirty==0 );
|
||||
|
||||
/* If the file is a temp-file has not yet been opened, open it now. It
|
||||
** is not possible for rc to be other than SQLITE_OK if this branch
|
||||
@@ -4927,6 +4961,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
if( rc==SQLITE_OK && !locked ){
|
||||
Pgno nPage; /* Number of pages in database file */
|
||||
|
||||
assert( pPager->tempFile==0 );
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If the database is zero pages in size, that means that either (1) the
|
||||
@@ -5019,17 +5054,17 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
/* This routine is only called from b-tree and only when there are no
|
||||
** outstanding pages. This implies that the pager state should either
|
||||
** be OPEN or READER. READER is only possible if the pager is or was in
|
||||
** exclusive access mode.
|
||||
*/
|
||||
** exclusive access mode. */
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
|
||||
assert( assert_pager_state(pPager) );
|
||||
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
|
||||
if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
|
||||
assert( pPager->errCode==SQLITE_OK );
|
||||
|
||||
if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
|
||||
int bHotJournal = 1; /* True if there exists a hot journal-file */
|
||||
|
||||
assert( !MEMDB );
|
||||
assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
|
||||
|
||||
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -5115,7 +5150,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = pagerSyncHotJournal(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_playback(pPager, 1);
|
||||
rc = pager_playback(pPager, !pPager->tempFile);
|
||||
pPager->eState = PAGER_OPEN;
|
||||
}
|
||||
}else if( !pPager->exclusiveMode ){
|
||||
@@ -5211,7 +5246,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
rc = pagerBeginReadTransaction(pPager);
|
||||
}
|
||||
|
||||
if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
|
||||
if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
|
||||
rc = pagerPagecount(pPager, &pPager->dbSize);
|
||||
}
|
||||
|
||||
@@ -5344,7 +5379,7 @@ int sqlite3PagerGet(
|
||||
);
|
||||
|
||||
if( rc==SQLITE_OK && pData ){
|
||||
if( pPager->eState>PAGER_READER ){
|
||||
if( pPager->eState>PAGER_READER || pPager->tempFile ){
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
if( pPg==0 ){
|
||||
@@ -5411,7 +5446,8 @@ int sqlite3PagerGet(
|
||||
goto pager_acquire_err;
|
||||
}
|
||||
|
||||
if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
|
||||
assert( !isOpen(pPager->fd) || !MEMDB );
|
||||
if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
|
||||
if( pgno>pPager->mxPgno ){
|
||||
rc = SQLITE_FULL;
|
||||
goto pager_acquire_err;
|
||||
@@ -5553,24 +5589,24 @@ static int pager_open_journal(Pager *pPager){
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
|
||||
sqlite3MemJournalOpen(pPager->jfd);
|
||||
}else{
|
||||
const int flags = /* VFS flags to open journal file */
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
|
||||
(pPager->tempFile ?
|
||||
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
|
||||
(SQLITE_OPEN_MAIN_JOURNAL)
|
||||
);
|
||||
int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
int nSpill;
|
||||
|
||||
if( pPager->tempFile ){
|
||||
flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
|
||||
nSpill = sqlite3Config.nStmtSpill;
|
||||
}else{
|
||||
flags |= SQLITE_OPEN_MAIN_JOURNAL;
|
||||
nSpill = jrnlBufferSize(pPager);
|
||||
}
|
||||
|
||||
/* Verify that the database still has the same name as it did when
|
||||
** it was originally opened. */
|
||||
rc = databaseIsUnmoved(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
rc = sqlite3JournalOpen(
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
|
||||
rc = sqlite3JournalOpen (
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
|
||||
);
|
||||
#else
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
|
||||
@@ -5941,6 +5977,7 @@ int sqlite3PagerWrite(PgHdr *pPg){
|
||||
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
|
||||
return SQLITE_OK;
|
||||
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
assert( pPager->tempFile==0 );
|
||||
return pagerWriteLargeSector(pPg);
|
||||
}else{
|
||||
return pager_write(pPg);
|
||||
@@ -6173,17 +6210,21 @@ int sqlite3PagerCommitPhaseOne(
|
||||
/* If a prior error occurred, report that error again. */
|
||||
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
||||
|
||||
/* Provide the ability to easily simulate an I/O error during testing */
|
||||
if( (rc = sqlite3FaultSim(400))!=SQLITE_OK ) return rc;
|
||||
|
||||
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
|
||||
pPager->zFilename, zMaster, pPager->dbSize));
|
||||
|
||||
/* If no database changes have been made, return early. */
|
||||
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
|
||||
|
||||
if( MEMDB ){
|
||||
assert( MEMDB==0 || pPager->tempFile );
|
||||
assert( isOpen(pPager->fd) || pPager->tempFile );
|
||||
if( 0==pagerFlushOnCommit(pPager) ){
|
||||
/* If this is an in-memory db, or no pages have been written to, or this
|
||||
** function has already been called, it is mostly a no-op. However, any
|
||||
** backup in progress needs to be restarted.
|
||||
*/
|
||||
** backup in progress needs to be restarted. */
|
||||
sqlite3BackupRestart(pPager->pBackup);
|
||||
}else{
|
||||
if( pagerUseWal(pPager) ){
|
||||
@@ -6522,10 +6563,10 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if this is an in-memory pager.
|
||||
** Return true if this is an in-memory or temp-file backed pager.
|
||||
*/
|
||||
int sqlite3PagerIsMemdb(Pager *pPager){
|
||||
return MEMDB;
|
||||
return pPager->tempFile;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6805,7 +6846,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
/* In order to be able to rollback, an in-memory database must journal
|
||||
** the page we are moving from.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
rc = sqlite3PagerWrite(pPg);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
@@ -6862,7 +6903,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
assert( !pPgOld || pPgOld->nRef==1 );
|
||||
if( pPgOld ){
|
||||
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
/* Do not discard pages from an in-memory database since we might
|
||||
** need to rollback later. Just move the page out of the way. */
|
||||
sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
|
||||
@@ -6879,7 +6920,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
** to exist, in case the transaction needs to roll back. Use pPgOld
|
||||
** as the original page since it has already been allocated.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
assert( pPgOld );
|
||||
sqlite3PcacheMove(pPgOld, origPgno);
|
||||
sqlite3PagerUnrefNotNull(pPgOld);
|
||||
@@ -7132,7 +7173,8 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
|
||||
** Unless this is an in-memory or temporary database, clear the pager cache.
|
||||
*/
|
||||
void sqlite3PagerClearCache(Pager *pPager){
|
||||
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
|
||||
assert( MEMDB==0 || pPager->tempFile );
|
||||
if( pPager->tempFile==0 ) pager_reset(pPager);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7311,6 +7353,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
|
||||
pPager->pageSize, (u8*)pPager->pTmpSpace);
|
||||
pPager->pWal = 0;
|
||||
pagerFixMaplimit(pPager);
|
||||
if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
||||
+10
-1
@@ -68,7 +68,11 @@ typedef struct PgHdr DbPage;
|
||||
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
|
||||
|
||||
/*
|
||||
** Numeric constants that encode the journalmode.
|
||||
** Numeric constants that encode the journalmode.
|
||||
**
|
||||
** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
|
||||
** are exposed in the API via the "PRAGMA journal_mode" command and
|
||||
** therefore cannot be changed without a compatibility break.
|
||||
*/
|
||||
#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
|
||||
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
|
||||
@@ -86,6 +90,11 @@ typedef struct PgHdr DbPage;
|
||||
|
||||
/*
|
||||
** Flags for sqlite3PagerSetFlags()
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** PAGER_FULLFSYNC == SQLITE_FullFSync
|
||||
** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
|
||||
** PAGER_CACHE_SPILL == SQLITE_CacheSpill
|
||||
*/
|
||||
#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
|
||||
#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
|
||||
|
||||
+24
-2
@@ -254,7 +254,7 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
|
||||
|
||||
/*
|
||||
** If the sqlite3PcacheFetch() routine is unable to allocate a new
|
||||
** page because new clean pages are available for reuse and the cache
|
||||
** page because no clean pages are available for reuse and the cache
|
||||
** size limit has been reached, then this routine can be invoked to
|
||||
** try harder to allocate a page. This routine might invoke the stress
|
||||
** callback to spill dirty pages to the journal. It will then try to
|
||||
@@ -439,6 +439,17 @@ void sqlite3PcacheCleanAll(PCache *pCache){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
|
||||
*/
|
||||
void sqlite3PcacheClearWritable(PCache *pCache){
|
||||
PgHdr *p;
|
||||
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
||||
p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
|
||||
}
|
||||
pCache->pSynced = pCache->pDirtyTail;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
|
||||
*/
|
||||
@@ -484,7 +495,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
|
||||
** it must be that pgno==0.
|
||||
*/
|
||||
assert( p->pgno>0 );
|
||||
if( ALWAYS(p->pgno>pgno) ){
|
||||
if( p->pgno>pgno ){
|
||||
assert( p->flags&PGHDR_DIRTY );
|
||||
sqlite3PcacheMakeClean(p);
|
||||
}
|
||||
@@ -675,6 +686,17 @@ void sqlite3PcacheShrink(PCache *pCache){
|
||||
*/
|
||||
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
|
||||
|
||||
/*
|
||||
** Return the number of dirty pages currently in the cache, as a percentage
|
||||
** of the configured cache size.
|
||||
*/
|
||||
int sqlite3PCachePercentDirty(PCache *pCache){
|
||||
PgHdr *pDirty;
|
||||
int nDirty = 0;
|
||||
int nCache = numberOfCachePages(pCache);
|
||||
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
|
||||
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
|
||||
@@ -99,6 +99,7 @@ void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
|
||||
void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
|
||||
void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
|
||||
void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
|
||||
void sqlite3PcacheClearWritable(PCache*);
|
||||
|
||||
/* Change a page number. Used by incr-vacuum. */
|
||||
void sqlite3PcacheMove(PgHdr*, Pgno);
|
||||
@@ -173,4 +174,7 @@ void sqlite3PCacheSetDefault(void);
|
||||
int sqlite3HeaderSizePcache(void);
|
||||
int sqlite3HeaderSizePcache1(void);
|
||||
|
||||
/* Number of dirty pages as a percentage of the configured cache size */
|
||||
int sqlite3PCachePercentDirty(PCache*);
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
||||
+2
-2
@@ -690,8 +690,8 @@ static int pcache1Init(void *NotUsed){
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
|
||||
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
|
||||
pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
|
||||
pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
|
||||
}
|
||||
#endif
|
||||
if( pcache1.separateCache
|
||||
|
||||
+47
-56
@@ -57,8 +57,9 @@
|
||||
** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
|
||||
** primitives are constant time. The cost of DESTROY is O(N).
|
||||
**
|
||||
** There is an added cost of O(N) when switching between TEST and
|
||||
** SMALLEST primitives.
|
||||
** TEST and SMALLEST may not be used by the same RowSet. This used to
|
||||
** be possible, but the feature was not used, so it was removed in order
|
||||
** to simplify the code.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -179,7 +180,9 @@ void sqlite3RowSetClear(RowSet *p){
|
||||
*/
|
||||
static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
|
||||
assert( p!=0 );
|
||||
if( p->nFresh==0 ){
|
||||
if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* We could allocate a fresh RowSetEntry each time one is needed, but it
|
||||
** is more efficient to pull a preallocated entry from the pool */
|
||||
struct RowSetChunk *pNew;
|
||||
pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
|
||||
if( pNew==0 ){
|
||||
@@ -213,7 +216,9 @@ void sqlite3RowSetInsert(RowSet *p, i64 rowid){
|
||||
pEntry->pRight = 0;
|
||||
pLast = p->pLast;
|
||||
if( pLast ){
|
||||
if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
|
||||
if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
|
||||
** where possible */
|
||||
p->rsFlags &= ~ROWSET_SORTED;
|
||||
}
|
||||
pLast->pRight = pEntry;
|
||||
@@ -335,23 +340,29 @@ static struct RowSetEntry *rowSetNDeepTree(
|
||||
){
|
||||
struct RowSetEntry *p; /* Root of the new tree */
|
||||
struct RowSetEntry *pLeft; /* Left subtree */
|
||||
if( *ppList==0 ){
|
||||
return 0;
|
||||
if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
/* Prevent unnecessary deep recursion when we run out of entries */
|
||||
return 0;
|
||||
}
|
||||
if( iDepth==1 ){
|
||||
if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
/* This branch causes a *balanced* tree to be generated. A valid tree
|
||||
** is still generated without this branch, but the tree is wildly
|
||||
** unbalanced and inefficient. */
|
||||
pLeft = rowSetNDeepTree(ppList, iDepth-1);
|
||||
p = *ppList;
|
||||
if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* It is safe to always return here, but the resulting tree
|
||||
** would be unbalanced */
|
||||
return pLeft;
|
||||
}
|
||||
p->pLeft = pLeft;
|
||||
*ppList = p->pRight;
|
||||
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
|
||||
}else{
|
||||
p = *ppList;
|
||||
*ppList = p->pRight;
|
||||
p->pLeft = p->pRight = 0;
|
||||
return p;
|
||||
}
|
||||
pLeft = rowSetNDeepTree(ppList, iDepth-1);
|
||||
p = *ppList;
|
||||
if( p==0 ){
|
||||
return pLeft;
|
||||
}
|
||||
p->pLeft = pLeft;
|
||||
*ppList = p->pRight;
|
||||
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -378,59 +389,37 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Take all the entries on p->pEntry and on the trees in p->pForest and
|
||||
** sort them all together into one big ordered list on p->pEntry.
|
||||
**
|
||||
** This routine should only be called once in the life of a RowSet.
|
||||
*/
|
||||
static void rowSetToList(RowSet *p){
|
||||
|
||||
/* This routine is called only once */
|
||||
assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
|
||||
|
||||
if( (p->rsFlags & ROWSET_SORTED)==0 ){
|
||||
p->pEntry = rowSetEntrySort(p->pEntry);
|
||||
}
|
||||
|
||||
/* While this module could theoretically support it, sqlite3RowSetNext()
|
||||
** is never called after sqlite3RowSetText() for the same RowSet. So
|
||||
** there is never a forest to deal with. Should this change, simply
|
||||
** remove the assert() and the #if 0. */
|
||||
assert( p->pForest==0 );
|
||||
#if 0
|
||||
while( p->pForest ){
|
||||
struct RowSetEntry *pTree = p->pForest->pLeft;
|
||||
if( pTree ){
|
||||
struct RowSetEntry *pHead, *pTail;
|
||||
rowSetTreeToList(pTree, &pHead, &pTail);
|
||||
p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
|
||||
}
|
||||
p->pForest = p->pForest->pRight;
|
||||
}
|
||||
#endif
|
||||
p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the smallest element from the RowSet.
|
||||
** Write the element into *pRowid. Return 1 on success. Return
|
||||
** 0 if the RowSet is already empty.
|
||||
**
|
||||
** After this routine has been called, the sqlite3RowSetInsert()
|
||||
** routine may not be called again.
|
||||
** routine may not be called again.
|
||||
**
|
||||
** This routine may not be called after sqlite3RowSetTest() has
|
||||
** been used. Older versions of RowSet allowed that, but as the
|
||||
** capability was not used by the code generator, it was removed
|
||||
** for code economy.
|
||||
*/
|
||||
int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
|
||||
assert( p!=0 );
|
||||
assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */
|
||||
|
||||
/* Merge the forest into a single sorted list on first call */
|
||||
if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
|
||||
if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
p->pEntry = rowSetEntrySort(p->pEntry);
|
||||
}
|
||||
p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT;
|
||||
}
|
||||
|
||||
/* Return the next entry on the list */
|
||||
if( p->pEntry ){
|
||||
*pRowid = p->pEntry->v;
|
||||
p->pEntry = p->pEntry->pRight;
|
||||
if( p->pEntry==0 ){
|
||||
if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
/* Free memory immediately, rather than waiting on sqlite3_finalize() */
|
||||
sqlite3RowSetClear(p);
|
||||
}
|
||||
return 1;
|
||||
@@ -453,13 +442,15 @@ int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
|
||||
/* This routine is never called after sqlite3RowSetNext() */
|
||||
assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
|
||||
|
||||
/* Sort entries into the forest on the first test of a new batch
|
||||
/* Sort entries into the forest on the first test of a new batch.
|
||||
** To save unnecessary work, only do this when the batch number changes.
|
||||
*/
|
||||
if( iBatch!=pRowSet->iBatch ){
|
||||
if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
p = pRowSet->pEntry;
|
||||
if( p ){
|
||||
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
|
||||
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
|
||||
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* Only sort the current set of entiries if they need it */
|
||||
p = rowSetEntrySort(p);
|
||||
}
|
||||
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
|
||||
|
||||
+29
-16
@@ -74,7 +74,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pOffset);
|
||||
sqlite3WithDelete(db, p->pWith);
|
||||
if( p->pWith ) sqlite3WithDelete(db, p->pWith);
|
||||
if( bFree ) sqlite3DbFree(db, p);
|
||||
p = pPrior;
|
||||
bFree = 1;
|
||||
@@ -169,7 +169,7 @@ void sqlite3SelectSetName(Select *p, const char *zName){
|
||||
** Delete the given Select structure and all of its substructures.
|
||||
*/
|
||||
void sqlite3SelectDelete(sqlite3 *db, Select *p){
|
||||
clearSelect(db, p, 1);
|
||||
if( p ) clearSelect(db, p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1789,20 +1789,20 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
|
||||
** Get a VDBE for the given parser context. Create a new one if necessary.
|
||||
** If an error occurs, return NULL and leave a message in pParse.
|
||||
*/
|
||||
Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( v==0 ){
|
||||
v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
|
||||
if( v ) sqlite3VdbeAddOp0(v, OP_Init);
|
||||
if( pParse->pToplevel==0
|
||||
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
|
||||
){
|
||||
pParse->okConstFactor = 1;
|
||||
}
|
||||
|
||||
static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){
|
||||
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
|
||||
if( v ) sqlite3VdbeAddOp0(v, OP_Init);
|
||||
if( pParse->pToplevel==0
|
||||
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
|
||||
){
|
||||
pParse->okConstFactor = 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
return v ? v : allocVdbe(pParse);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -3785,12 +3785,18 @@ static int pushDownWhereTerms(
|
||||
){
|
||||
Expr *pNew;
|
||||
int nChng = 0;
|
||||
Select *pX; /* For looping over compound SELECTs in pSubq */
|
||||
if( pWhere==0 ) return 0;
|
||||
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
|
||||
return 0; /* restrictions (1) and (2) */
|
||||
for(pX=pSubq; pX; pX=pX->pPrior){
|
||||
if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
|
||||
testcase( pX->selFlags & SF_Aggregate );
|
||||
testcase( pX->selFlags & SF_Recursive );
|
||||
testcase( pX!=pSubq );
|
||||
return 0; /* restrictions (1) and (2) */
|
||||
}
|
||||
}
|
||||
if( pSubq->pLimit!=0 ){
|
||||
return 0; /* restriction (3) */
|
||||
return 0; /* restriction (3) */
|
||||
}
|
||||
while( pWhere->op==TK_AND ){
|
||||
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
|
||||
@@ -5092,6 +5098,13 @@ int sqlite3Select(
|
||||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||
** original setting of the SF_Distinct flag, not the current setting */
|
||||
assert( sDistinct.isTnct );
|
||||
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x400 ){
|
||||
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If there is an ORDER BY clause, then create an ephemeral index to
|
||||
|
||||
+231
-85
@@ -669,6 +669,7 @@ struct ShellState {
|
||||
#define MODE_Csv 7 /* Quote strings, numbers are plain */
|
||||
#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
|
||||
#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
|
||||
#define MODE_Pretty 10 /* Pretty-print schemas */
|
||||
|
||||
static const char *modeDescr[] = {
|
||||
"line",
|
||||
@@ -681,6 +682,7 @@ static const char *modeDescr[] = {
|
||||
"csv",
|
||||
"explain",
|
||||
"ascii",
|
||||
"prettyprint",
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1054,7 +1056,70 @@ static int shell_callback(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MODE_Semi:
|
||||
case MODE_Semi: { /* .schema and .fullschema output */
|
||||
utf8_printf(p->out, "%s;\n", azArg[0]);
|
||||
break;
|
||||
}
|
||||
case MODE_Pretty: { /* .schema and .fullschema with --indent */
|
||||
char *z;
|
||||
int j;
|
||||
int nParen = 0;
|
||||
char cEnd = 0;
|
||||
char c;
|
||||
int nLine = 0;
|
||||
assert( nArg==1 );
|
||||
if( azArg[0]==0 ) break;
|
||||
if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
|
||||
|| sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
|
||||
){
|
||||
utf8_printf(p->out, "%s;\n", azArg[0]);
|
||||
break;
|
||||
}
|
||||
z = sqlite3_mprintf("%s", azArg[0]);
|
||||
j = 0;
|
||||
for(i=0; IsSpace(z[i]); i++){}
|
||||
for(; (c = z[i])!=0; i++){
|
||||
if( IsSpace(c) ){
|
||||
if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
|
||||
}else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
|
||||
j--;
|
||||
}
|
||||
z[j++] = c;
|
||||
}
|
||||
while( j>0 && IsSpace(z[j-1]) ){ j--; }
|
||||
z[j] = 0;
|
||||
if( strlen30(z)>=79 ){
|
||||
for(i=j=0; (c = z[i])!=0; i++){
|
||||
if( c==cEnd ){
|
||||
cEnd = 0;
|
||||
}else if( c=='"' || c=='\'' || c=='`' ){
|
||||
cEnd = c;
|
||||
}else if( c=='[' ){
|
||||
cEnd = ']';
|
||||
}else if( c=='(' ){
|
||||
nParen++;
|
||||
}else if( c==')' ){
|
||||
nParen--;
|
||||
if( nLine>0 && nParen==0 && j>0 ){
|
||||
utf8_printf(p->out, "%.*s\n", j, z);
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
z[j++] = c;
|
||||
if( nParen==1 && (c=='(' || c==',' || c=='\n') ){
|
||||
if( c=='\n' ) j--;
|
||||
utf8_printf(p->out, "%.*s\n ", j, z);
|
||||
j = 0;
|
||||
nLine++;
|
||||
while( IsSpace(z[i+1]) ){ i++; }
|
||||
}
|
||||
}
|
||||
z[j] = 0;
|
||||
}
|
||||
utf8_printf(p->out, "%s;\n", z);
|
||||
sqlite3_free(z);
|
||||
break;
|
||||
}
|
||||
case MODE_List: {
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
@@ -1069,8 +1134,6 @@ static int shell_callback(
|
||||
utf8_printf(p->out, "%s", z);
|
||||
if( i<nArg-1 ){
|
||||
utf8_printf(p->out, "%s", p->colSeparator);
|
||||
}else if( p->cMode==MODE_Semi ){
|
||||
utf8_printf(p->out, ";%s", p->rowSeparator);
|
||||
}else{
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
@@ -1670,7 +1733,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
|
||||
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
|
||||
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
|
||||
){
|
||||
for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1689,6 +1752,104 @@ static void explain_data_delete(ShellState *p){
|
||||
p->iIndent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Disable and restore .wheretrace and .selecttrace settings.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
extern int sqlite3SelectTrace;
|
||||
static int savedSelectTrace;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
extern int sqlite3WhereTrace;
|
||||
static int savedWhereTrace;
|
||||
#endif
|
||||
static void disable_debug_trace_modes(void){
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
savedSelectTrace = sqlite3SelectTrace;
|
||||
sqlite3SelectTrace = 0;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
savedWhereTrace = sqlite3WhereTrace;
|
||||
sqlite3WhereTrace = 0;
|
||||
#endif
|
||||
}
|
||||
static void restore_debug_trace_modes(void){
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
sqlite3SelectTrace = savedSelectTrace;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
sqlite3WhereTrace = savedWhereTrace;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a prepared statement
|
||||
*/
|
||||
static void exec_prepared_stmt(
|
||||
ShellState *pArg, /* Pointer to ShellState */
|
||||
sqlite3_stmt *pStmt, /* Statment to run */
|
||||
int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */
|
||||
){
|
||||
int rc;
|
||||
|
||||
/* perform the first step. this will tell us if we
|
||||
** have a result set or not and how wide it is.
|
||||
*/
|
||||
rc = sqlite3_step(pStmt);
|
||||
/* if we have a result set... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* if we have a callback... */
|
||||
if( xCallback ){
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
}else{
|
||||
do{
|
||||
rc = sqlite3_step(pStmt);
|
||||
} while( rc == SQLITE_ROW );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute a statement or set of statements. Print
|
||||
** any result rows/columns depending on the current mode
|
||||
@@ -1716,6 +1877,7 @@ static int shell_exec(
|
||||
}
|
||||
|
||||
while( zSql[0] && (SQLITE_OK == rc) ){
|
||||
static const char *zStmtSql;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
|
||||
if( SQLITE_OK != rc ){
|
||||
if( pzErrMsg ){
|
||||
@@ -1728,6 +1890,8 @@ static int shell_exec(
|
||||
while( IsSpace(zSql[0]) ) zSql++;
|
||||
continue;
|
||||
}
|
||||
zStmtSql = sqlite3_sql(pStmt);
|
||||
while( IsSpace(zStmtSql[0]) ) zStmtSql++;
|
||||
|
||||
/* save off the prepared statment handle and reset row count */
|
||||
if( pArg ){
|
||||
@@ -1737,15 +1901,15 @@ static int shell_exec(
|
||||
|
||||
/* echo the sql statement if echo on */
|
||||
if( pArg && pArg->echoOn ){
|
||||
const char *zStmtSql = sqlite3_sql(pStmt);
|
||||
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
|
||||
}
|
||||
|
||||
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
|
||||
if( pArg && pArg->autoEQP ){
|
||||
if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
|
||||
sqlite3_stmt *pExplain;
|
||||
char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s",
|
||||
sqlite3_sql(pStmt));
|
||||
char *zEQP;
|
||||
disable_debug_trace_modes();
|
||||
zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
|
||||
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
@@ -1757,13 +1921,27 @@ static int shell_exec(
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
sqlite3_free(zEQP);
|
||||
if( pArg->autoEQP>=2 ){
|
||||
/* Also do an EXPLAIN for ".eqp full" mode */
|
||||
zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
|
||||
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
explain_data_prepare(pArg, pExplain);
|
||||
exec_prepared_stmt(pArg, pExplain, xCallback);
|
||||
explain_data_delete(pArg);
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
sqlite3_free(zEQP);
|
||||
}
|
||||
restore_debug_trace_modes();
|
||||
}
|
||||
|
||||
if( pArg ){
|
||||
pArg->cMode = pArg->mode;
|
||||
if( pArg->autoExplain
|
||||
&& sqlite3_column_count(pStmt)==8
|
||||
&& sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0
|
||||
&& sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
|
||||
){
|
||||
pArg->cMode = MODE_Explain;
|
||||
}
|
||||
@@ -1775,63 +1953,7 @@ static int shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the first step. this will tell us if we
|
||||
** have a result set or not and how wide it is.
|
||||
*/
|
||||
rc = sqlite3_step(pStmt);
|
||||
/* if we have a result set... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* if we have a callback... */
|
||||
if( xCallback ){
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
}else{
|
||||
do{
|
||||
rc = sqlite3_step(pStmt);
|
||||
} while( rc == SQLITE_ROW );
|
||||
}
|
||||
}
|
||||
|
||||
exec_prepared_stmt(pArg, pStmt, xCallback);
|
||||
explain_data_delete(pArg);
|
||||
|
||||
/* print usage stats if stats on */
|
||||
@@ -2021,10 +2143,10 @@ static char zHelp[] =
|
||||
" If TABLE specified, only dump tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".echo on|off Turn command echo on or off\n"
|
||||
".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n"
|
||||
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
|
||||
".exit Exit this program\n"
|
||||
".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"
|
||||
".fullschema Show schema and the content of sqlite_stat tables\n"
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
|
||||
".headers on|off Turn display of headers on or off\n"
|
||||
".help Show this message\n"
|
||||
".import FILE TABLE Import data from FILE into TABLE\n"
|
||||
@@ -2060,9 +2182,8 @@ static char zHelp[] =
|
||||
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
|
||||
".save FILE Write in-memory database into FILE\n"
|
||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
|
||||
".schema ?TABLE? Show the CREATE statements\n"
|
||||
" If TABLE specified, only show tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
|
||||
" Add --indent for pretty-printing\n"
|
||||
".separator COL ?ROW? Change the column separator and optionally the row\n"
|
||||
" separator for both the output mode and .import\n"
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
@@ -2933,6 +3054,17 @@ static int shellNomemError(void){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the string as a command-line option with either one or two
|
||||
** initial "-" characters.
|
||||
*/
|
||||
static int optionMatch(const char *zStr, const char *zOpt){
|
||||
if( zStr[0]!='-' ) return 0;
|
||||
zStr++;
|
||||
if( zStr[0]=='-' ) zStr++;
|
||||
return strcmp(zStr, zOpt)==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** If an input line begins with "." then invoke this routine to
|
||||
** process that line.
|
||||
@@ -3181,9 +3313,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
if( strcmp(azArg[1],"full")==0 ){
|
||||
p->autoEQP = 2;
|
||||
}else{
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
}
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .eqp on|off\n");
|
||||
raw_printf(stderr, "Usage: .eqp on|off|full\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
@@ -3219,15 +3355,19 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
ShellState data;
|
||||
char *zErrMsg = 0;
|
||||
int doStats = 0;
|
||||
memcpy(&data, p, sizeof(data));
|
||||
data.showHeader = 0;
|
||||
data.cMode = data.mode = MODE_Semi;
|
||||
if( nArg==2 && optionMatch(azArg[1], "indent") ){
|
||||
data.cMode = data.mode = MODE_Pretty;
|
||||
nArg = 1;
|
||||
}
|
||||
if( nArg!=1 ){
|
||||
raw_printf(stderr, "Usage: .fullschema\n");
|
||||
raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
open_db(p, 0);
|
||||
memcpy(&data, p, sizeof(data));
|
||||
data.showHeader = 0;
|
||||
data.cMode = data.mode = MODE_Semi;
|
||||
rc = sqlite3_exec(p->db,
|
||||
"SELECT sql FROM"
|
||||
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
|
||||
@@ -3862,7 +4002,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
memcpy(&data, p, sizeof(data));
|
||||
data.showHeader = 0;
|
||||
data.cMode = data.mode = MODE_Semi;
|
||||
if( nArg==2 ){
|
||||
if( nArg>=2 && optionMatch(azArg[1], "indent") ){
|
||||
data.cMode = data.mode = MODE_Pretty;
|
||||
nArg--;
|
||||
if( nArg==2 ) azArg[1] = azArg[2];
|
||||
}
|
||||
if( nArg==2 && azArg[1][0]!='-' ){
|
||||
int i;
|
||||
for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
|
||||
if( strcmp(azArg[1],"sqlite_master")==0 ){
|
||||
@@ -3917,7 +4062,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
|
||||
raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
@@ -3935,7 +4080,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
|
||||
extern int sqlite3SelectTrace;
|
||||
sqlite3SelectTrace = integerValue(azArg[1]);
|
||||
}else
|
||||
#endif
|
||||
@@ -4195,17 +4339,18 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
static const char *azBool[] = { "off", "on", "full", "unk" };
|
||||
int i;
|
||||
if( nArg!=1 ){
|
||||
raw_printf(stderr, "Usage: .show\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","explain",
|
||||
p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
|
||||
utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
|
||||
utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
|
||||
utf8_printf(p->out, "%12.12s: ", "nullvalue");
|
||||
output_c_string(p->out, p->nullValue);
|
||||
@@ -4218,7 +4363,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
utf8_printf(p->out,"%12.12s: ", "rowseparator");
|
||||
output_c_string(p->out, p->rowSeparator);
|
||||
raw_printf(p->out, "\n");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
|
||||
utf8_printf(p->out, "%12.12s: ", "width");
|
||||
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
|
||||
raw_printf(p->out, "%d ", p->colWidth[i]);
|
||||
@@ -4633,7 +4778,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
|
||||
extern int sqlite3WhereTrace;
|
||||
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
|
||||
}else
|
||||
#endif
|
||||
@@ -5301,6 +5445,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
data.echoOn = 1;
|
||||
}else if( strcmp(z,"-eqp")==0 ){
|
||||
data.autoEQP = 1;
|
||||
}else if( strcmp(z,"-eqpfull")==0 ){
|
||||
data.autoEQP = 2;
|
||||
}else if( strcmp(z,"-stats")==0 ){
|
||||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-scanstats")==0 ){
|
||||
|
||||
+73
-1
@@ -966,6 +966,12 @@ struct sqlite3_io_methods {
|
||||
** on whether or not the file has been renamed, moved, or deleted since it
|
||||
** was first opened.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
|
||||
** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
|
||||
** underlying native file handle associated with a file handle. This file
|
||||
** control interprets its argument as a pointer to a native file handle and
|
||||
** writes the resulting value there.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
|
||||
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
|
||||
** opcode causes the xFileControl method to swap the file handle with the one
|
||||
@@ -1016,6 +1022,7 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_RBU 26
|
||||
#define SQLITE_FCNTL_VFS_POINTER 27
|
||||
#define SQLITE_FCNTL_JOURNAL_POINTER 28
|
||||
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -1932,12 +1939,30 @@ struct sqlite3_mem_methods {
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the new setting is not reported back. </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
|
||||
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
|
||||
** interface independently of the [load_extension()] SQL function.
|
||||
** The [sqlite3_enable_load_extension()] API enables or disables both the
|
||||
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
|
||||
** There should be two additional arguments.
|
||||
** When the first argument to this interface is 1, then only the C-API is
|
||||
** enabled and the SQL function remains disabled. If the first argment to
|
||||
** this interface is 0, then both the C-API and the SQL function are disabled.
|
||||
** If the first argument is -1, then no changes are made to state of either the
|
||||
** C-API or the SQL function.
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
|
||||
** is disabled or enabled following this call. The second parameter may
|
||||
** be a NULL pointer, in which case the new setting is not reported back.
|
||||
** </dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
||||
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
|
||||
|
||||
|
||||
/*
|
||||
@@ -5474,9 +5499,18 @@ int sqlite3_table_column_metadata(
|
||||
** should free this memory by calling [sqlite3_free()].
|
||||
**
|
||||
** ^Extension loading must be enabled using
|
||||
** [sqlite3_enable_load_extension()] prior to calling this API,
|
||||
** [sqlite3_enable_load_extension()] or
|
||||
** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
|
||||
** prior to calling this API,
|
||||
** otherwise an error will be returned.
|
||||
**
|
||||
** <b>Security warning:</b> It is recommended that the
|
||||
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
|
||||
** interface. The use of the [sqlite3_enable_load_extension()] interface
|
||||
** should be avoided. This will keep the SQL function [load_extension()]
|
||||
** disabled and prevent SQL injections from giving attackers
|
||||
** access to extension loading capabilities.
|
||||
**
|
||||
** See also the [load_extension() SQL function].
|
||||
*/
|
||||
int sqlite3_load_extension(
|
||||
@@ -5499,6 +5533,17 @@ int sqlite3_load_extension(
|
||||
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
|
||||
** to turn extension loading on and call it with onoff==0 to turn
|
||||
** it back off again.
|
||||
**
|
||||
** ^This interface enables or disables both the C-API
|
||||
** [sqlite3_load_extension()] and the SQL function [load_extension()].
|
||||
** Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
|
||||
** to enable or disable only the C-API.
|
||||
**
|
||||
** <b>Security warning:</b> It is recommended that extension loading
|
||||
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
|
||||
** rather than this interface, so the [load_extension()] SQL function
|
||||
** remains disabled. This will prevent SQL injections from giving attackers
|
||||
** access to extension loading capabilities.
|
||||
*/
|
||||
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
||||
|
||||
@@ -8128,6 +8173,33 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Compare the ages of two snapshot handles.
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
|
||||
** of two valid snapshot handles.
|
||||
**
|
||||
** If the two snapshot handles are not associated with the same database
|
||||
** file, the result of the comparison is undefined.
|
||||
**
|
||||
** Additionally, the result of the comparison is only valid if both of the
|
||||
** snapshot handles were obtained by calling sqlite3_snapshot_get() since the
|
||||
** last time the wal file was deleted. The wal file is deleted when the
|
||||
** database is changed back to rollback mode or when the number of database
|
||||
** clients drops to zero. If either snapshot handle was obtained before the
|
||||
** wal file was last deleted, the value returned by this function
|
||||
** is undefined.
|
||||
**
|
||||
** Otherwise, this API returns a negative value if P1 refers to an older
|
||||
** snapshot than P2, zero if the two handles refer to the same database
|
||||
** snapshot, and a positive value if P1 is a newer snapshot than P2.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
||||
sqlite3_snapshot *p1,
|
||||
sqlite3_snapshot *p2
|
||||
);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
||||
+81
-22
@@ -15,6 +15,33 @@
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
||||
/* Special Comments:
|
||||
**
|
||||
** Some comments have special meaning to the tools that measure test
|
||||
** coverage:
|
||||
**
|
||||
** NO_TEST - The branches on this line are not
|
||||
** measured by branch coverage. This is
|
||||
** used on lines of code that actually
|
||||
** implement parts of coverage testing.
|
||||
**
|
||||
** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false
|
||||
** and the correct answer is still obtained,
|
||||
** though perhaps more slowly.
|
||||
**
|
||||
** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true
|
||||
** and the correct answer is still obtained,
|
||||
** though perhaps more slowly.
|
||||
**
|
||||
** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread
|
||||
** that would be harmless and undetectable
|
||||
** if it did occur.
|
||||
**
|
||||
** In all cases, the special comment must be enclosed in the usual
|
||||
** slash-asterisk...asterisk-slash comment marks, with no spaces between the
|
||||
** asterisks and the comment text.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Make sure that rand_s() is available on Windows systems with MSVC 2005
|
||||
** or higher.
|
||||
@@ -1350,6 +1377,11 @@ struct sqlite3 {
|
||||
|
||||
/*
|
||||
** Possible values for the sqlite3.flags.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** SQLITE_FullFSync == PAGER_FULLFSYNC
|
||||
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
|
||||
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
|
||||
*/
|
||||
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
|
||||
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
|
||||
@@ -1377,13 +1409,14 @@ struct sqlite3 {
|
||||
#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
|
||||
#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
|
||||
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
|
||||
#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
|
||||
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
|
||||
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
|
||||
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
|
||||
#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */
|
||||
#define SQLITE_Fts3Tokenizer 0x20000000 /* Enable fts3_tokenizer(2) */
|
||||
#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
|
||||
#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
|
||||
#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
|
||||
#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
|
||||
#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
|
||||
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
|
||||
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
|
||||
|
||||
|
||||
/*
|
||||
@@ -1484,6 +1517,13 @@ struct FuncDestructor {
|
||||
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
|
||||
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
|
||||
** are assert() statements in the code to verify this.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
|
||||
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
|
||||
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
|
||||
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
|
||||
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
|
||||
*/
|
||||
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
||||
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
|
||||
@@ -2483,6 +2523,9 @@ struct SrcList {
|
||||
/*
|
||||
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
|
||||
** and the WhereInfo.wctrlFlags member.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** WHERE_USE_LIMIT == SF_FixedLimit
|
||||
*/
|
||||
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
|
||||
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
|
||||
@@ -2543,15 +2586,16 @@ struct NameContext {
|
||||
/*
|
||||
** Allowed values for the NameContext, ncFlags field.
|
||||
**
|
||||
** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and
|
||||
** SQLITE_FUNC_MINMAX.
|
||||
** Value constraints (all checked via assert()):
|
||||
** NC_HasAgg == SF_HasAgg
|
||||
** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
|
||||
**
|
||||
*/
|
||||
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
|
||||
#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */
|
||||
#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
|
||||
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
|
||||
#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */
|
||||
#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
|
||||
#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
|
||||
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
||||
|
||||
@@ -2600,24 +2644,30 @@ struct Select {
|
||||
/*
|
||||
** Allowed values for Select.selFlags. The "SF" prefix stands for
|
||||
** "Select Flag".
|
||||
**
|
||||
** Value constraints (all checked via assert())
|
||||
** SF_HasAgg == NC_HasAgg
|
||||
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
|
||||
** SF_FixedLimit == WHERE_USE_LIMIT
|
||||
*/
|
||||
#define SF_Distinct 0x00001 /* Output should be DISTINCT */
|
||||
#define SF_All 0x00002 /* Includes the ALL keyword */
|
||||
#define SF_Resolved 0x00004 /* Identifiers have been resolved */
|
||||
#define SF_Aggregate 0x00008 /* Contains aggregate functions */
|
||||
#define SF_UsesEphemeral 0x00010 /* Uses the OpenEphemeral opcode */
|
||||
#define SF_Expanded 0x00020 /* sqlite3SelectExpand() called on this */
|
||||
#define SF_HasTypeInfo 0x00040 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x00080 /* Part of a compound query */
|
||||
#define SF_Values 0x00100 /* Synthesized from VALUES clause */
|
||||
#define SF_MultiValue 0x00200 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x00400 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x00800 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
|
||||
#define SF_HasAgg 0x00010 /* Contains aggregate functions */
|
||||
#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
|
||||
#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
|
||||
#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x00100 /* Part of a compound query */
|
||||
#define SF_Values 0x00200 /* Synthesized from VALUES clause */
|
||||
#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
|
||||
#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
|
||||
#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
|
||||
#define SF_Converted 0x08000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x10000 /* Include hidden columns in output */
|
||||
#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
|
||||
|
||||
|
||||
/*
|
||||
@@ -2928,6 +2978,15 @@ struct AuthContext {
|
||||
|
||||
/*
|
||||
** Bitfield flags for P5 value in various opcodes.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
|
||||
** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
|
||||
** OPFLAG_BULKCSR == BTREE_BULKLOAD
|
||||
** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
|
||||
** OPFLAG_FORDELETE == BTREE_FORDELETE
|
||||
** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
|
||||
** OPFLAG_AUXDELETE == BTREE_AUXDELETE
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
|
||||
/* Also used in P2 (not P5) of OP_Delete */
|
||||
|
||||
+1
-1
@@ -3035,7 +3035,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
/* set ppHook to point at pUpdateHook or pRollbackHook, depending on
|
||||
** whether [$db update_hook] or [$db rollback_hook] was invoked.
|
||||
*/
|
||||
Tcl_Obj **ppHook;
|
||||
Tcl_Obj **ppHook = 0;
|
||||
if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook;
|
||||
if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook;
|
||||
if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook;
|
||||
|
||||
+70
-8
@@ -1271,7 +1271,7 @@ static int sqlite3_mprintf_int64(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for(i=2; i<5; i++){
|
||||
if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
|
||||
if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
|
||||
Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2359,6 +2359,31 @@ static int test_snapshot_free(
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
|
||||
*/
|
||||
static int test_snapshot_cmp(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int res;
|
||||
sqlite3_snapshot *p1;
|
||||
sqlite3_snapshot *p2;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
|
||||
res = sqlite3_snapshot_cmp(p1, p2);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -5188,7 +5213,9 @@ static int vfs_unregister_all(
|
||||
/*
|
||||
** tclcmd: vfs_reregister_all
|
||||
**
|
||||
** Restore all VFSes that were removed using vfs_unregister_all
|
||||
** Restore all VFSes that were removed using vfs_unregister_all. Taking
|
||||
** care to put the linked list back together in the same order as it was
|
||||
** in before vfs_unregister_all was invoked.
|
||||
*/
|
||||
static int vfs_reregister_all(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
@@ -5197,8 +5224,8 @@ static int vfs_reregister_all(
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int i;
|
||||
for(i=0; i<nVfs; i++){
|
||||
sqlite3_vfs_register(apVfs[i], i==0);
|
||||
for(i=nVfs-1; i>=0; i--){
|
||||
sqlite3_vfs_register(apVfs[i], 1);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -5455,6 +5482,38 @@ static int file_control_win32_av_retry(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_win32_get_handle DB
|
||||
**
|
||||
** This TCL command runs the sqlite3_file_control interface with
|
||||
** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
|
||||
*/
|
||||
static int file_control_win32_get_handle(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
HANDLE hFile = NULL;
|
||||
char z[100];
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
|
||||
(void*)&hFile);
|
||||
sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
|
||||
Tcl_AppendResult(interp, z, (char*)0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_win32_set_handle DB HANDLE
|
||||
**
|
||||
@@ -6673,8 +6732,8 @@ static int sorter_test_sort4_helper(
|
||||
const char *zSql2;
|
||||
int nStep;
|
||||
int iStep;
|
||||
int iCksum1 = 0;
|
||||
int iCksum2 = 0;
|
||||
unsigned int iCksum1 = 0;
|
||||
unsigned int iCksum2 = 0;
|
||||
int rc;
|
||||
int iB;
|
||||
sqlite3 *db;
|
||||
@@ -6701,7 +6760,7 @@ static int sorter_test_sort4_helper(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
iCksum1 += (iCksum1 << 3) + a;
|
||||
iCksum1 += (iCksum1 << 3) + (unsigned int)a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
@@ -6710,7 +6769,7 @@ static int sorter_test_sort4_helper(
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
||||
int a = sqlite3_column_int(pStmt, 0);
|
||||
iCksum2 += (iCksum2 << 3) + a;
|
||||
iCksum2 += (iCksum2 << 3) + (unsigned int)a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
@@ -6963,6 +7022,7 @@ static int test_sqlite3_db_config(
|
||||
{ "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY },
|
||||
{ "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
|
||||
{ "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
|
||||
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
|
||||
};
|
||||
int i;
|
||||
int v;
|
||||
@@ -7186,6 +7246,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
||||
#if SQLITE_OS_WIN
|
||||
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
|
||||
{ "file_control_win32_get_handle", file_control_win32_get_handle, 0 },
|
||||
{ "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
|
||||
#endif
|
||||
{ "file_control_persist_wal", file_control_persist_wal, 0 },
|
||||
@@ -7249,6 +7310,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_snapshot_get", test_snapshot_get, 0 },
|
||||
{ "sqlite3_snapshot_open", test_snapshot_open, 0 },
|
||||
{ "sqlite3_snapshot_free", test_snapshot_free, 0 },
|
||||
{ "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
|
||||
#endif
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
|
||||
+4
-2
@@ -547,7 +547,7 @@ static int btree_from_db(
|
||||
/*
|
||||
** Usage: btree_ismemdb ID
|
||||
**
|
||||
** Return true if the B-Tree is in-memory.
|
||||
** Return true if the B-Tree is currently stored entirely in memory.
|
||||
*/
|
||||
static int btree_ismemdb(
|
||||
void *NotUsed,
|
||||
@@ -557,6 +557,7 @@ static int btree_ismemdb(
|
||||
){
|
||||
Btree *pBt;
|
||||
int res;
|
||||
sqlite3_file *pFile;
|
||||
|
||||
if( argc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
@@ -566,7 +567,8 @@ static int btree_ismemdb(
|
||||
pBt = sqlite3TestTextToPtr(argv[1]);
|
||||
sqlite3_mutex_enter(pBt->db->mutex);
|
||||
sqlite3BtreeEnter(pBt);
|
||||
res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
|
||||
pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
|
||||
res = (pFile->pMethods==0);
|
||||
sqlite3BtreeLeave(pBt);
|
||||
sqlite3_mutex_leave(pBt->db->mutex);
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
|
||||
|
||||
+27
-1
@@ -701,6 +701,10 @@ static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xCurrentTime(pVfs, pTimeOut);
|
||||
}
|
||||
static int cfGetLastError(sqlite3_vfs *pCfVfs, int n, char *z){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xGetLastError(pVfs, n, z);
|
||||
}
|
||||
|
||||
static int processDevSymArgs(
|
||||
Tcl_Interp *interp,
|
||||
@@ -827,7 +831,7 @@ static int crashEnableCmd(
|
||||
cfRandomness, /* xRandomness */
|
||||
cfSleep, /* xSleep */
|
||||
cfCurrentTime, /* xCurrentTime */
|
||||
0, /* xGetlastError */
|
||||
cfGetLastError, /* xGetLastError */
|
||||
0, /* xCurrentTimeInt64 */
|
||||
};
|
||||
|
||||
@@ -940,6 +944,27 @@ static int devSymObjCmd(
|
||||
devsym_register(iDc, iSectorSize);
|
||||
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: unregister_devsim
|
||||
*/
|
||||
static int dsUnregisterObjCmd(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
void devsym_unregister(void);
|
||||
|
||||
if( objc!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
devsym_unregister();
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1010,6 +1035,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
|
||||
#endif
|
||||
|
||||
+9
-1
@@ -133,7 +133,8 @@ struct DevsymGlobal g = {0, 0, 512};
|
||||
*/
|
||||
static int devsymClose(sqlite3_file *pFile){
|
||||
devsym_file *p = (devsym_file *)pFile;
|
||||
return sqlite3OsClose(p->pReal);
|
||||
sqlite3OsClose(p->pReal);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -395,4 +396,11 @@ void devsym_register(int iDeviceChar, int iSectorSize){
|
||||
}
|
||||
}
|
||||
|
||||
void devsym_unregister(){
|
||||
sqlite3_vfs_unregister(&devsym_vfs);
|
||||
g.pVfs = 0;
|
||||
g.iDeviceChar = 0;
|
||||
g.iSectorSize = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+18
-12
@@ -160,6 +160,7 @@ static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||
static int jtSleep(sqlite3_vfs*, int microseconds);
|
||||
static int jtCurrentTime(sqlite3_vfs*, double*);
|
||||
static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||
static int jtGetLastError(sqlite3_vfs*, int, char*);
|
||||
|
||||
static sqlite3_vfs jt_vfs = {
|
||||
2, /* iVersion */
|
||||
@@ -179,7 +180,7 @@ static sqlite3_vfs jt_vfs = {
|
||||
jtRandomness, /* xRandomness */
|
||||
jtSleep, /* xSleep */
|
||||
jtCurrentTime, /* xCurrentTime */
|
||||
0, /* xGetLastError */
|
||||
jtGetLastError, /* xGetLastError */
|
||||
jtCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||
};
|
||||
|
||||
@@ -256,7 +257,8 @@ static int jtClose(sqlite3_file *pFile){
|
||||
*pp = p->pNext;
|
||||
}
|
||||
leaveJtMutex();
|
||||
return sqlite3OsClose(p->pReal);
|
||||
sqlite3OsClose(p->pReal);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -284,9 +286,10 @@ static int jtRead(
|
||||
** b) The file-name specified when the file was opened matches
|
||||
** all but the final 8 characters of the journal file name.
|
||||
**
|
||||
** c) There is currently a reserved lock on the file.
|
||||
** c) There is currently a reserved lock on the file. This
|
||||
** condition is waived if the noLock argument is non-zero.
|
||||
**/
|
||||
static jt_file *locateDatabaseHandle(const char *zJournal){
|
||||
static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){
|
||||
jt_file *pMain = 0;
|
||||
enterJtMutex();
|
||||
for(pMain=g.pList; pMain; pMain=pMain->pNext){
|
||||
@@ -294,7 +297,7 @@ static jt_file *locateDatabaseHandle(const char *zJournal){
|
||||
if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
|
||||
&& ((int)strlen(pMain->zName)==nName)
|
||||
&& 0==memcmp(pMain->zName, zJournal, nName)
|
||||
&& (pMain->eLock>=SQLITE_LOCK_RESERVED)
|
||||
&& ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock)
|
||||
){
|
||||
break;
|
||||
}
|
||||
@@ -516,7 +519,7 @@ static int jtWrite(
|
||||
jt_file *p = (jt_file *)pFile;
|
||||
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
if( iOfst==0 ){
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName);
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
|
||||
assert( pMain );
|
||||
|
||||
if( iAmt==28 ){
|
||||
@@ -561,7 +564,7 @@ static int jtWrite(
|
||||
|
||||
rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
|
||||
if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName);
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
|
||||
int rc2 = readJournalFile(p, pMain);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
@@ -575,7 +578,7 @@ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
jt_file *p = (jt_file *)pFile;
|
||||
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){
|
||||
/* Truncating a journal file. This is the end of a transaction. */
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName);
|
||||
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
|
||||
closeTransaction(pMain);
|
||||
}
|
||||
if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
|
||||
@@ -603,11 +606,10 @@ static int jtSync(sqlite3_file *pFile, int flags){
|
||||
** jt_file.pWritable bitvec of the main database file associated with
|
||||
** this journal file.
|
||||
*/
|
||||
pMain = locateDatabaseHandle(p->zName);
|
||||
assert(pMain);
|
||||
pMain = locateDatabaseHandle(p->zName, 0);
|
||||
|
||||
/* Set the bitvec values */
|
||||
if( pMain->pWritable ){
|
||||
if( pMain && pMain->pWritable ){
|
||||
pMain->nSync++;
|
||||
rc = readJournalFile(p, pMain);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -729,7 +731,7 @@ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
int nPath = (int)strlen(zPath);
|
||||
if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){
|
||||
/* Deleting a journal file. The end of a transaction. */
|
||||
jt_file *pMain = locateDatabaseHandle(zPath);
|
||||
jt_file *pMain = locateDatabaseHandle(zPath, 0);
|
||||
if( pMain ){
|
||||
closeTransaction(pMain);
|
||||
}
|
||||
@@ -824,6 +826,10 @@ static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
||||
return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut);
|
||||
}
|
||||
|
||||
static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){
|
||||
return g.pVfs->xGetLastError(g.pVfs, n, z);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
** Start of public API.
|
||||
*/
|
||||
|
||||
@@ -539,7 +539,7 @@ static int multiplexOpen(
|
||||
memset(pGroup, 0, sz);
|
||||
pMultiplexOpen->pGroup = pGroup;
|
||||
pGroup->bEnabled = (unsigned char)-1;
|
||||
pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate",
|
||||
pGroup->bTruncate = (unsigned char)sqlite3_uri_boolean(zUri, "truncate",
|
||||
(flags & SQLITE_OPEN_MAIN_DB)==0);
|
||||
pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize",
|
||||
SQLITE_MULTIPLEX_CHUNK_SIZE);
|
||||
@@ -978,7 +978,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
case MULTIPLEX_CTRL_ENABLE:
|
||||
if( pArg ) {
|
||||
int bEnabled = *(int *)pArg;
|
||||
pGroup->bEnabled = bEnabled;
|
||||
pGroup->bEnabled = (unsigned char)bEnabled;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
+1
-1
@@ -508,7 +508,7 @@ static int fsSync(sqlite3_file *pFile, int flags){
|
||||
if( p->eType==DATABASE_FILE ){
|
||||
unsigned char zSize[4];
|
||||
zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
|
||||
zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
|
||||
zSize[1] = (unsigned char)((pReal->nDatabase&0x00FF0000)>>16);
|
||||
zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
|
||||
zSize[3] = (pReal->nDatabase&0x000000FF);
|
||||
rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
|
||||
|
||||
+3
-3
@@ -644,9 +644,9 @@ static void vfslog_flush(VfslogVfs *p){
|
||||
|
||||
static void put32bits(unsigned char *p, unsigned int v){
|
||||
p[0] = v>>24;
|
||||
p[1] = v>>16;
|
||||
p[2] = v>>8;
|
||||
p[3] = v;
|
||||
p[1] = (unsigned char)(v>>16);
|
||||
p[2] = (unsigned char)(v>>8);
|
||||
p[3] = (unsigned char)v;
|
||||
}
|
||||
|
||||
static void vfslog_call(
|
||||
|
||||
+18
-9
@@ -108,10 +108,13 @@ static int ts_ftruncate(int fd, off_t n);
|
||||
static int ts_fcntl(int fd, int cmd, ... );
|
||||
static int ts_read(int fd, void *aBuf, size_t nBuf);
|
||||
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
|
||||
/* Note: pread64() and pwrite64() actually use off64_t as the type on their
|
||||
** last parameter. But that datatype is not defined on many systems
|
||||
** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
|
||||
static int ts_write(int fd, const void *aBuf, size_t nBuf);
|
||||
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
|
||||
static int ts_fchmod(int fd, mode_t mode);
|
||||
static int ts_fallocate(int fd, off_t off, off_t len);
|
||||
static void *ts_mmap(void *, size_t, int, int, int, off_t);
|
||||
@@ -155,11 +158,11 @@ struct TestSyscallArray {
|
||||
#define orig_fcntl ((int(*)(int,int,...))aSyscall[7].xOrig)
|
||||
#define orig_read ((ssize_t(*)(int,void*,size_t))aSyscall[8].xOrig)
|
||||
#define orig_pread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].xOrig)
|
||||
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].xOrig)
|
||||
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,sqlite3_uint64))aSyscall[10].xOrig)
|
||||
#define orig_write ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
|
||||
#define orig_pwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
aSyscall[12].xOrig)
|
||||
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,sqlite3_uint64))\
|
||||
aSyscall[13].xOrig)
|
||||
#define orig_fchmod ((int(*)(int,mode_t))aSyscall[14].xOrig)
|
||||
#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
|
||||
@@ -326,7 +329,7 @@ static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
|
||||
/*
|
||||
** A wrapper around pread64().
|
||||
*/
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
|
||||
if( tsIsFailErrno("pread64") ){
|
||||
return -1;
|
||||
}
|
||||
@@ -357,7 +360,7 @@ static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
|
||||
/*
|
||||
** A wrapper around pwrite64().
|
||||
*/
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
|
||||
if( tsIsFailErrno("pwrite64") ){
|
||||
return -1;
|
||||
}
|
||||
@@ -719,14 +722,20 @@ static int test_syscall(
|
||||
};
|
||||
int iCmd;
|
||||
int rc;
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
|
||||
if( objc<2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = Tcl_GetIndexFromObjStruct(interp,
|
||||
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
|
||||
);
|
||||
if( pVfs->iVersion<3 || pVfs->xSetSystemCall==0 ){
|
||||
Tcl_AppendResult(interp, "VFS does not support xSetSystemCall", 0);
|
||||
rc = TCL_ERROR;
|
||||
}else{
|
||||
rc = Tcl_GetIndexFromObjStruct(interp,
|
||||
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
|
||||
);
|
||||
}
|
||||
if( rc!=TCL_OK ) return rc;
|
||||
return aCmd[iCmd].xCmd(clientData, interp, objc, objv);
|
||||
}
|
||||
|
||||
+2
-3
@@ -306,7 +306,6 @@ static void tvfsExecTcl(
|
||||
** Close an tvfs-file.
|
||||
*/
|
||||
static int tvfsClose(sqlite3_file *pFile){
|
||||
int rc;
|
||||
TestvfsFile *pTestfile = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = pTestfile->pFd;
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
@@ -324,10 +323,10 @@ static int tvfsClose(sqlite3_file *pFile){
|
||||
if( pFile->pMethods ){
|
||||
ckfree((char *)pFile->pMethods);
|
||||
}
|
||||
rc = sqlite3OsClose(pFd->pReal);
|
||||
sqlite3OsClose(pFd->pReal);
|
||||
ckfree((char *)pFd);
|
||||
pTestfile->pFd = 0;
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -583,7 +583,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
sqlite3DeleteTable(db, pParse->pNewTable);
|
||||
}
|
||||
|
||||
sqlite3WithDelete(db, pParse->pWithToFree);
|
||||
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
|
||||
sqlite3DbFree(db, pParse->azVar);
|
||||
|
||||
+61
-50
@@ -355,7 +355,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
int eValid = 1; /* True exponent is either not used or is well-formed */
|
||||
double result;
|
||||
int nDigits = 0;
|
||||
int nonNum = 0;
|
||||
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
|
||||
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
*pResult = 0.0; /* Default return value, in case of an error */
|
||||
@@ -368,7 +368,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
for(i=3-enc; i<length && z[i]==0; i+=2){}
|
||||
nonNum = i<length;
|
||||
zEnd = z+i+enc-3;
|
||||
zEnd = &z[i^1];
|
||||
z += (enc&1);
|
||||
}
|
||||
|
||||
@@ -384,9 +384,6 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
z+=incr;
|
||||
}
|
||||
|
||||
/* skip leading zeroes */
|
||||
while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
|
||||
|
||||
/* copy max significant digits to significand */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
@@ -403,12 +400,13 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
z+=incr;
|
||||
/* copy digits from after decimal to significand
|
||||
** (decrease exponent by d to shift decimal right) */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
z+=incr, nDigits++, d--;
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
if( s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
d--;
|
||||
}
|
||||
z+=incr, nDigits++;
|
||||
}
|
||||
/* skip non-significant digits */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
|
||||
}
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
@@ -416,7 +414,12 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
if( *z=='e' || *z=='E' ){
|
||||
z+=incr;
|
||||
eValid = 0;
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
/* This branch is needed to avoid a (harmless) buffer overread. The
|
||||
** special comment alerts the mutation tester that the correct answer
|
||||
** is obtained even if the branch is omitted */
|
||||
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
|
||||
|
||||
/* get sign of exponent */
|
||||
if( *z=='-' ){
|
||||
esign = -1;
|
||||
@@ -433,9 +436,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
}
|
||||
|
||||
/* skip trailing spaces */
|
||||
if( nDigits && eValid ){
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
}
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
|
||||
do_atof_calc:
|
||||
/* adjust exponent by d, and update sign */
|
||||
@@ -447,41 +448,51 @@ do_atof_calc:
|
||||
esign = 1;
|
||||
}
|
||||
|
||||
/* if 0 significand */
|
||||
if( !s ) {
|
||||
/* In the IEEE 754 standard, zero is signed.
|
||||
** Add the sign if we've seen at least one digit */
|
||||
result = (sign<0 && nDigits) ? -(double)0 : (double)0;
|
||||
if( s==0 ) {
|
||||
/* In the IEEE 754 standard, zero is signed. */
|
||||
result = sign<0 ? -(double)0 : (double)0;
|
||||
} else {
|
||||
/* attempt to reduce exponent */
|
||||
if( esign>0 ){
|
||||
while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
|
||||
}else{
|
||||
while( !(s%10) && e>0 ) e--,s/=10;
|
||||
/* Attempt to reduce exponent.
|
||||
**
|
||||
** Branches that are not required for the correct answer but which only
|
||||
** help to obtain the correct answer faster are marked with special
|
||||
** comments, as a hint to the mutation tester.
|
||||
*/
|
||||
while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
if( esign>0 ){
|
||||
if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
|
||||
s *= 10;
|
||||
}else{
|
||||
if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
|
||||
s /= 10;
|
||||
}
|
||||
e--;
|
||||
}
|
||||
|
||||
/* adjust the sign of significand */
|
||||
s = sign<0 ? -s : s;
|
||||
|
||||
/* if exponent, scale significand as appropriate
|
||||
** and store in result. */
|
||||
if( e ){
|
||||
if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
result = (double)s;
|
||||
}else{
|
||||
LONGDOUBLE_TYPE scale = 1.0;
|
||||
/* attempt to handle extremely small/large numbers better */
|
||||
if( e>307 && e<342 ){
|
||||
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
|
||||
if( esign<0 ){
|
||||
result = s / scale;
|
||||
result /= 1.0e+308;
|
||||
}else{
|
||||
result = s * scale;
|
||||
result *= 1.0e+308;
|
||||
}
|
||||
}else if( e>=342 ){
|
||||
if( esign<0 ){
|
||||
result = 0.0*s;
|
||||
}else{
|
||||
result = 1e308*1e308*s; /* Infinity */
|
||||
if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
|
||||
if( esign<0 ){
|
||||
result = s / scale;
|
||||
result /= 1.0e+308;
|
||||
}else{
|
||||
result = s * scale;
|
||||
result *= 1.0e+308;
|
||||
}
|
||||
}else{ assert( e>=342 );
|
||||
if( esign<0 ){
|
||||
result = 0.0*s;
|
||||
}else{
|
||||
result = 1e308*1e308*s; /* Infinity */
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* 1.0e+22 is the largest power of 10 than can be
|
||||
@@ -494,8 +505,6 @@ do_atof_calc:
|
||||
result = s * scale;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = (double)s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +512,7 @@ do_atof_calc:
|
||||
*pResult = result;
|
||||
|
||||
/* return true if number and no extra non-whitespace chracters after */
|
||||
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
|
||||
return z==zEnd && nDigits>0 && eValid && nonNum==0;
|
||||
#else
|
||||
return !sqlite3Atoi64(z, pResult, length, enc);
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
@@ -565,7 +574,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
int neg = 0; /* assume positive */
|
||||
int i;
|
||||
int c = 0;
|
||||
int nonNum = 0;
|
||||
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
|
||||
const char *zStart;
|
||||
const char *zEnd = zNum + length;
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
@@ -576,7 +585,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
|
||||
nonNum = i<length;
|
||||
zEnd = zNum+i+enc-3;
|
||||
zEnd = &zNum[i^1];
|
||||
zNum += (enc&1);
|
||||
}
|
||||
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
|
||||
@@ -603,8 +612,11 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum)
|
||||
|| i>19*incr || nonNum ){
|
||||
if( &zNum[i]<zEnd /* Extra bytes at the end */
|
||||
|| (i==0 && zStart==zNum) /* No digits */
|
||||
|| i>19*incr /* Too many digits */
|
||||
|| nonNum /* UTF16 with high-order bytes non-zero */
|
||||
){
|
||||
/* zNum is empty or contains non-numeric text or is longer
|
||||
** than 19 digits (thus guaranteeing that it is too large) */
|
||||
return 1;
|
||||
@@ -646,7 +658,6 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
if( z[0]=='0'
|
||||
&& (z[1]=='x' || z[1]=='X')
|
||||
&& sqlite3Isxdigit(z[2])
|
||||
){
|
||||
u64 u = 0;
|
||||
int i, k;
|
||||
@@ -1408,7 +1419,7 @@ LogEst sqlite3LogEst(u64 x){
|
||||
if( x<2 ) return 0;
|
||||
while( x<8 ){ y -= 10; x <<= 1; }
|
||||
}else{
|
||||
while( x>255 ){ y += 40; x >>= 4; }
|
||||
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
|
||||
while( x>15 ){ y += 10; x >>= 1; }
|
||||
}
|
||||
return a[x&7] + y - 10;
|
||||
|
||||
+26
-46
@@ -215,7 +215,7 @@ static VdbeCursor *allocateCursor(
|
||||
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
|
||||
|
||||
assert( iCur>=0 && iCur<p->nCursor );
|
||||
if( p->apCsr[iCur] ){
|
||||
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
|
||||
p->apCsr[iCur] = 0;
|
||||
}
|
||||
@@ -292,7 +292,7 @@ static void applyAffinity(
|
||||
if( affinity>=SQLITE_AFF_NUMERIC ){
|
||||
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|
||||
|| affinity==SQLITE_AFF_NUMERIC );
|
||||
if( (pRec->flags & MEM_Int)==0 ){
|
||||
if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
if( (pRec->flags & MEM_Real)==0 ){
|
||||
if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
|
||||
}else{
|
||||
@@ -302,10 +302,13 @@ static void applyAffinity(
|
||||
}else if( affinity==SQLITE_AFF_TEXT ){
|
||||
/* Only attempt the conversion to TEXT if there is an integer or real
|
||||
** representation (blob and NULL do not get converted) but no string
|
||||
** representation.
|
||||
*/
|
||||
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
|
||||
sqlite3VdbeMemStringify(pRec, enc, 1);
|
||||
** representation. It would be harmless to repeat the conversion if
|
||||
** there is already a string rep, but it is pointless to waste those
|
||||
** CPU cycles. */
|
||||
if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
if( (pRec->flags&(MEM_Real|MEM_Int)) ){
|
||||
sqlite3VdbeMemStringify(pRec, enc, 1);
|
||||
}
|
||||
}
|
||||
pRec->flags &= ~(MEM_Real|MEM_Int);
|
||||
}
|
||||
@@ -542,7 +545,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
|
||||
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
memAboutToChange(p, pOut);
|
||||
if( VdbeMemDynamic(pOut) ){
|
||||
if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
return out2PrereleaseWithClear(pOut);
|
||||
}else{
|
||||
pOut->flags = MEM_Int;
|
||||
@@ -946,8 +949,6 @@ case OP_HaltIfNull: { /* in3 */
|
||||
** is the same as executing Halt.
|
||||
*/
|
||||
case OP_Halt: {
|
||||
const char *zType;
|
||||
const char *zLogFmt;
|
||||
VdbeFrame *pFrame;
|
||||
int pcx;
|
||||
|
||||
@@ -976,34 +977,28 @@ case OP_Halt: {
|
||||
p->rc = pOp->p1;
|
||||
p->errorAction = (u8)pOp->p2;
|
||||
p->pc = pcx;
|
||||
assert( pOp->p5>=0 && pOp->p5<=4 );
|
||||
if( p->rc ){
|
||||
if( pOp->p5 ){
|
||||
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
|
||||
"FOREIGN KEY" };
|
||||
assert( pOp->p5>=1 && pOp->p5<=4 );
|
||||
testcase( pOp->p5==1 );
|
||||
testcase( pOp->p5==2 );
|
||||
testcase( pOp->p5==3 );
|
||||
testcase( pOp->p5==4 );
|
||||
zType = azType[pOp->p5-1];
|
||||
sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
|
||||
if( pOp->p4.z ){
|
||||
p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
|
||||
}
|
||||
}else{
|
||||
zType = 0;
|
||||
}
|
||||
assert( zType!=0 || pOp->p4.z!=0 );
|
||||
zLogFmt = "abort at %d in [%s]: %s";
|
||||
if( zType && pOp->p4.z ){
|
||||
sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z);
|
||||
}else if( pOp->p4.z ){
|
||||
sqlite3VdbeError(p, "%s", pOp->p4.z);
|
||||
}else{
|
||||
sqlite3VdbeError(p, "%s constraint failed", zType);
|
||||
}
|
||||
sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
|
||||
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
|
||||
}
|
||||
rc = sqlite3VdbeHalt(p);
|
||||
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
|
||||
if( rc==SQLITE_BUSY ){
|
||||
p->rc = rc = SQLITE_BUSY;
|
||||
p->rc = SQLITE_BUSY;
|
||||
}else{
|
||||
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
|
||||
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
|
||||
@@ -1069,10 +1064,7 @@ case OP_String8: { /* same as TK_STRING, out2 */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( encoding!=SQLITE_UTF8 ){
|
||||
rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
|
||||
if( rc ){
|
||||
assert( rc==SQLITE_TOOBIG ); /* This is the only possible error here */
|
||||
goto too_big;
|
||||
}
|
||||
assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
|
||||
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
|
||||
assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
|
||||
assert( VdbeMemDynamic(pOut)==0 );
|
||||
@@ -1085,10 +1077,12 @@ case OP_String8: { /* same as TK_STRING, out2 */
|
||||
pOp->p4.z = pOut->z;
|
||||
pOp->p1 = pOut->n;
|
||||
}
|
||||
testcase( rc==SQLITE_TOOBIG );
|
||||
#endif
|
||||
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
assert( rc==SQLITE_OK );
|
||||
/* Fall through to the next case, OP_String */
|
||||
}
|
||||
|
||||
@@ -1097,10 +1091,12 @@ case OP_String8: { /* same as TK_STRING, out2 */
|
||||
**
|
||||
** The string value P4 of length P1 (bytes) is stored in register P2.
|
||||
**
|
||||
** If P5!=0 and the content of register P3 is greater than zero, then
|
||||
** If P3 is not zero and the content of register P3 is equal to P5, then
|
||||
** the datatype of the register P2 is converted to BLOB. The content is
|
||||
** the same sequence of bytes, it is merely interpreted as a BLOB instead
|
||||
** of a string, as if it had been CAST.
|
||||
** of a string, as if it had been CAST. In other words:
|
||||
**
|
||||
** if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB)
|
||||
*/
|
||||
case OP_String: { /* out2 */
|
||||
assert( pOp->p4.z!=0 );
|
||||
@@ -1111,12 +1107,11 @@ case OP_String: { /* out2 */
|
||||
pOut->enc = encoding;
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( pOp->p5 ){
|
||||
assert( pOp->p3>0 );
|
||||
if( pOp->p3>0 ){
|
||||
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
assert( pIn3->flags & MEM_Int );
|
||||
if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
|
||||
if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -5972,21 +5967,6 @@ case OP_DecrJumpZero: { /* jump, in1 */
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: JumpZeroIncr P1 P2 * * *
|
||||
** Synopsis: if (r[P1]++)==0 ) goto P2
|
||||
**
|
||||
** The register P1 must contain an integer. If register P1 is initially
|
||||
** zero, then jump to P2. Increment register P1 regardless of whether or
|
||||
** not the jump is taken.
|
||||
*/
|
||||
case OP_JumpZeroIncr: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
VdbeBranchTaken(pIn1->u.i==0, 2);
|
||||
if( (pIn1->u.i++)==0 ) goto jump_to_p2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: AggStep0 * P2 P3 P4 P5
|
||||
** Synopsis: accum=r[P3] step(r[P2@P5])
|
||||
**
|
||||
|
||||
+11
-3
@@ -931,7 +931,6 @@ int sqlite3VdbeSorterInit(
|
||||
){
|
||||
int pgsz; /* Page size of main database */
|
||||
int i; /* Used to iterate through aTask[] */
|
||||
int mxCache; /* Cache size */
|
||||
VdbeSorter *pSorter; /* The new sorter */
|
||||
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
|
||||
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
|
||||
@@ -988,11 +987,20 @@ int sqlite3VdbeSorterInit(
|
||||
}
|
||||
|
||||
if( !sqlite3TempInMemory(db) ){
|
||||
i64 mxCache; /* Cache size in bytes*/
|
||||
u32 szPma = sqlite3GlobalConfig.szPma;
|
||||
pSorter->mnPmaSize = szPma * pgsz;
|
||||
|
||||
mxCache = db->aDb[0].pSchema->cache_size;
|
||||
if( mxCache<(int)szPma ) mxCache = (int)szPma;
|
||||
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
|
||||
if( mxCache<0 ){
|
||||
/* A negative cache-size value C indicates that the cache is abs(C)
|
||||
** KiB in size. */
|
||||
mxCache = mxCache * -1024;
|
||||
}else{
|
||||
mxCache = mxCache * pgsz;
|
||||
}
|
||||
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
|
||||
|
||||
@@ -3399,6 +3399,23 @@ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
|
||||
void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
|
||||
** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
|
||||
*/
|
||||
int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
|
||||
WalIndexHdr *pHdr1 = (WalIndexHdr*)p1;
|
||||
WalIndexHdr *pHdr2 = (WalIndexHdr*)p2;
|
||||
|
||||
/* aSalt[0] is a copy of the value stored in the wal file header. It
|
||||
** is incremented each time the wal file is restarted. */
|
||||
if( pHdr1->aSalt[0]<pHdr2->aSalt[0] ) return -1;
|
||||
if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1;
|
||||
if( pHdr1->mxFrame<pHdr2->mxFrame ) return -1;
|
||||
if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1;
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
|
||||
+17
-22
@@ -3881,9 +3881,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
&& nRowEst
|
||||
){
|
||||
Bitmask notUsed;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
|
||||
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
|
||||
if( rc==pWInfo->pResultSet->nExpr ){
|
||||
if( rc==pWInfo->pDistinctSet->nExpr ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
|
||||
}
|
||||
}
|
||||
@@ -4098,14 +4098,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
** used.
|
||||
*/
|
||||
WhereInfo *sqlite3WhereBegin(
|
||||
Parse *pParse, /* The parser context */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
|
||||
ExprList *pResultSet, /* Result set of the query */
|
||||
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number,
|
||||
** If WHERE_USE_LIMIT, then the limit amount */
|
||||
Parse *pParse, /* The parser context */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
|
||||
ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
|
||||
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
|
||||
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number
|
||||
** If WHERE_USE_LIMIT, then the limit amount */
|
||||
){
|
||||
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
||||
int nTabList; /* Number of elements in pTabList */
|
||||
@@ -4180,7 +4180,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
pWInfo->pResultSet = pResultSet;
|
||||
pWInfo->pDistinctSet = pDistinctSet;
|
||||
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pWInfo->iLimit = iAuxArg;
|
||||
@@ -4253,13 +4253,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
|
||||
/* The DISTINCT marking is pointless. Ignore it. */
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}else if( pOrderBy==0 ){
|
||||
/* Try to ORDER BY the result set to make distinct processing easier */
|
||||
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
|
||||
pWInfo->pOrderBy = pResultSet;
|
||||
pWInfo->pOrderBy = pDistinctSet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4338,10 +4338,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
#endif
|
||||
/* Attempt to omit tables from the join that do not effect the result */
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0
|
||||
&& pDistinctSet!=0
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
){
|
||||
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
|
||||
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
|
||||
if( sWLB.pOrderBy ){
|
||||
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
|
||||
}
|
||||
@@ -4607,13 +4607,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( pLevel->addrLikeRep ){
|
||||
int op;
|
||||
if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
|
||||
op = OP_DecrJumpZero;
|
||||
}else{
|
||||
op = OP_JumpZeroIncr;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
|
||||
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1),
|
||||
pLevel->addrLikeRep);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
+10
-2
@@ -70,7 +70,7 @@ struct WhereLevel {
|
||||
int addrFirst; /* First instruction of interior of the loop */
|
||||
int addrBody; /* Beginning of the body of this loop */
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
int iLikeRepCntr; /* LIKE range processing counter register */
|
||||
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
|
||||
int addrLikeRep; /* LIKE range processing address */
|
||||
#endif
|
||||
u8 iFrom; /* Which entry in the FROM clause */
|
||||
@@ -408,7 +408,7 @@ struct WhereInfo {
|
||||
Parse *pParse; /* Parsing and code generating context */
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
|
||||
ExprList *pDistinctSet; /* DISTINCT over all these values */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
@@ -492,6 +492,14 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
||||
** operators that are of interest to the query planner. An
|
||||
** OR-ed combination of these values can be used when searching for
|
||||
** particular WhereTerms within a WhereClause.
|
||||
**
|
||||
** Value constraints:
|
||||
** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ
|
||||
** WO_LT == SQLITE_INDEX_CONSTRAINT_LT
|
||||
** 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
|
||||
|
||||
+23
-13
@@ -560,9 +560,10 @@ static int codeAllEqualityTerms(
|
||||
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
/*
|
||||
** If the most recently coded instruction is a constant range contraint
|
||||
** that originated from the LIKE optimization, then change the P3 to be
|
||||
** pLoop->iLikeRepCntr and set P5.
|
||||
** If the most recently coded instruction is a constant range constraint
|
||||
** (a string literal) that originated from the LIKE optimization, then
|
||||
** set P3 and P5 on the OP_String opcode so that the string will be cast
|
||||
** to a BLOB at appropriate times.
|
||||
**
|
||||
** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
|
||||
** expression: "x>='ABC' AND x<'abd'". But this requires that the range
|
||||
@@ -587,8 +588,8 @@ static void whereLikeOptimizationStringFixup(
|
||||
assert( pOp!=0 );
|
||||
assert( pOp->opcode==OP_String8
|
||||
|| pTerm->pWC->pWInfo->pParse->db->mallocFailed );
|
||||
pOp->p3 = pLevel->iLikeRepCntr;
|
||||
pOp->p5 = 1;
|
||||
pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */
|
||||
pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -1175,14 +1176,17 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
|
||||
assert( pRangeStart!=0 ); /* LIKE opt constraints */
|
||||
assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
|
||||
pLevel->iLikeRepCntr = ++pParse->nMem;
|
||||
testcase( bRev );
|
||||
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer,
|
||||
bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
|
||||
pLevel->iLikeRepCntr);
|
||||
pLevel->iLikeRepCntr = (u32)++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr);
|
||||
VdbeComment((v, "LIKE loop counter"));
|
||||
pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
|
||||
/* iLikeRepCntr actually stores 2x the counter register number. The
|
||||
** bottom bit indicates whether the search order is ASC or DESC. */
|
||||
testcase( bRev );
|
||||
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
|
||||
assert( (bRev & ~1)==0 );
|
||||
pLevel->iLikeRepCntr <<=1;
|
||||
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
|
||||
}
|
||||
#endif
|
||||
if( pRangeStart==0
|
||||
@@ -1696,11 +1700,17 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
continue;
|
||||
}
|
||||
if( pTerm->wtFlags & TERM_LIKECOND ){
|
||||
/* If the TERM_LIKECOND flag is set, that means that the range search
|
||||
** is sufficient to guarantee that the LIKE operator is true, so we
|
||||
** can skip the call to the like(A,B) function. But this only works
|
||||
** for strings. So do not skip the call to the function on the pass
|
||||
** that compares BLOBs. */
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
continue;
|
||||
#else
|
||||
assert( pLevel->iLikeRepCntr>0 );
|
||||
skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
|
||||
u32 x = pLevel->iLikeRepCntr;
|
||||
assert( x>0 );
|
||||
skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1));
|
||||
VdbeCoverage(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
+2
-2
@@ -1282,10 +1282,10 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
|
||||
return mask;
|
||||
}
|
||||
mask = sqlite3WhereExprUsage(pMaskSet, p->pRight);
|
||||
mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
|
||||
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
}else{
|
||||
}else if( p->x.pList ){
|
||||
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
|
||||
}
|
||||
return mask;
|
||||
|
||||
+10
-11
@@ -164,7 +164,7 @@ foreach zOpenScript [list {
|
||||
set file_dest temp
|
||||
}] {
|
||||
foreach rows_dest {0 3 10} {
|
||||
foreach pgsz_dest {512 1024 2048} {
|
||||
foreach pgsz_dest {512 1024 2048 4096} {
|
||||
foreach nPagePerStep {1 200} {
|
||||
|
||||
# Open the databases.
|
||||
@@ -176,17 +176,16 @@ foreach nPagePerStep {1 200} {
|
||||
# in-memory destination is only possible if the initial destination
|
||||
# page size is the same as the source page size (in this case 1024 bytes).
|
||||
#
|
||||
set isMemDest [expr {
|
||||
$zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
|
||||
}]
|
||||
set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
|
||||
|
||||
if { $isMemDest==0 || $pgsz_dest == 1024 } {
|
||||
if 0 {
|
||||
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
|
||||
puts -nonewline " (as $db_dest.$file_dest)"
|
||||
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
|
||||
puts ""
|
||||
}
|
||||
if 0 {
|
||||
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
|
||||
puts -nonewline " (as $db_dest.$file_dest)"
|
||||
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
|
||||
puts ""
|
||||
}
|
||||
|
||||
if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
|
||||
|
||||
# Set up the content of the source database.
|
||||
execsql {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cacheflush
|
||||
set testprefix cffault
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# Run the supplied SQL on a copy of the database currently stored on
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ do_test 2.3 { db_write db 1 } {0 4 0}
|
||||
do_test 2.4 { db_write db 0 } {0 0 0}
|
||||
do_test 2.5 { db_write db 1 } {0 0 0}
|
||||
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
do_test 2.6 {
|
||||
execsql { PRAGMA journal_mode = WAL }
|
||||
db_write db 1
|
||||
|
||||
@@ -161,4 +161,27 @@ do_execsql_test 5.0 {
|
||||
SELECT a FROM t1 WHERE b=2;
|
||||
} {}
|
||||
|
||||
# 2016-05-02
|
||||
# Ticket https://www.sqlite.org/src/tktview/dc6ebeda93960877
|
||||
# A subquery in the WHERE clause of a one-pass DELETE can cause an
|
||||
# incorrect answer.
|
||||
#
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t2(x INT);
|
||||
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
|
||||
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x-1);
|
||||
SELECT x FROM t2;
|
||||
} {1}
|
||||
do_execsql_test 6.1 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(x INT);
|
||||
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
|
||||
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x+1);
|
||||
SELECT x FROM t2;
|
||||
} {5}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ if {![nonzero_reserved_bytes]} {
|
||||
# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
|
||||
# auto_vacuum support property can be changed using VACUUM.
|
||||
#
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
do_test e_vacuum-1.3.3.1 {
|
||||
execsql { PRAGMA journal_mode = wal }
|
||||
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
|
||||
|
||||
@@ -19,6 +19,7 @@ source $testdir/lock_common.tcl
|
||||
|
||||
|
||||
foreach jm {rollback wal} {
|
||||
if {![wal_is_capable] && $jm=="wal"} continue
|
||||
|
||||
set testprefix exists-$jm
|
||||
|
||||
|
||||
@@ -43,4 +43,30 @@ do_test filectrl-1.6 {
|
||||
} {/etilqs_/}
|
||||
db close
|
||||
forcedelete .test_control_lockproxy.db-conch test.proxy
|
||||
forcedelete test.db test2.db
|
||||
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
do_test filectrl-2.1 {
|
||||
sqlite3 db test2.db
|
||||
set size [file size test2.db]
|
||||
set handle [file_control_win32_get_handle db]
|
||||
db close
|
||||
forcedelete test2.db
|
||||
list $size $handle [expr {$handle != 0}]
|
||||
} {/^0 \{0 \d+\} 1$/}
|
||||
|
||||
do_test filectrl-2.2 {
|
||||
sqlite3 db test2.db
|
||||
execsql {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 (x) VALUES(RANDOMBLOB(1048576));
|
||||
}
|
||||
set size [file size test2.db]
|
||||
set handle [file_control_win32_get_handle db]
|
||||
db close
|
||||
forcedelete test2.db
|
||||
list $size $handle [expr {$handle != 0}]
|
||||
} {/^1\d+ \{0 \d+\} 1$/}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -704,7 +704,7 @@ do_execsql_test 7.5.2.0 {
|
||||
ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
|
||||
}
|
||||
|
||||
ifcapable !session {
|
||||
if 0 {
|
||||
# At time of writing, these two are broken. They demonstrate that the
|
||||
# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
|
||||
# has been used to add a column with a default value other than NULL.
|
||||
|
||||
@@ -134,7 +134,7 @@ do_test incrvacuum2-3.2 {
|
||||
|
||||
integrity_check incrvacuum2-3.3
|
||||
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
# At one point, when a specific page was being extracted from the b-tree
|
||||
# free-list (e.g. during an incremental-vacuum), all trunk pages that
|
||||
# occurred before the specific page in the free-list trunk were being
|
||||
|
||||
@@ -604,5 +604,16 @@ do_test intpkey-15.7 {
|
||||
}
|
||||
} {}
|
||||
|
||||
# 2016-04-18 ticket https://www.sqlite.org/src/tktview/7d7525cb01b68712495d3a
|
||||
# Be sure to escape quoted typenames.
|
||||
#
|
||||
do_execsql_test intpkey-16.0 {
|
||||
CREATE TABLE t16a(id "INTEGER" PRIMARY KEY AUTOINCREMENT, b [TEXT], c `INT`);
|
||||
} {}
|
||||
do_execsql_test intpkey-16.1 {
|
||||
PRAGMA table_info=t16a;
|
||||
} {0 id INTEGER 0 {} 1 1 b TEXT 0 {} 0 2 c INT 0 {} 0}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ db close
|
||||
# delete the journal file when committing the transaction that switches
|
||||
# the system to WAL mode.
|
||||
#
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
do_test journal2-2.1 {
|
||||
faultsim_delete_and_reopen
|
||||
set ::oplog [list]
|
||||
|
||||
+11
-1
@@ -111,7 +111,7 @@ do_test loadext-1.2 {
|
||||
#
|
||||
do_test loadext-1.3 {
|
||||
sqlite3 db2 test.db
|
||||
sqlite3_enable_load_extension db2 1
|
||||
sqlite3_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
|
||||
catchsql {
|
||||
SELECT half(1.0);
|
||||
} db2
|
||||
@@ -256,6 +256,7 @@ do_test loadext-4.2 {
|
||||
}
|
||||
} {0 {{}}}
|
||||
|
||||
# disable all extension loading
|
||||
do_test loadext-4.3 {
|
||||
sqlite3_enable_load_extension db 0
|
||||
catchsql {
|
||||
@@ -263,6 +264,15 @@ do_test loadext-4.3 {
|
||||
}
|
||||
} {1 {not authorized}}
|
||||
|
||||
# enable C-api extension loading only. Show that the SQL function
|
||||
# still does not work.
|
||||
do_test loadext-4.4 {
|
||||
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
|
||||
catchsql {
|
||||
SELECT load_extension($::testextension,'testloadext_init')
|
||||
}
|
||||
} {1 {not authorized}}
|
||||
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -423,8 +423,9 @@ do_test lock-6.5 {
|
||||
# * there exists one or more active read-only statements, and
|
||||
# * a transaction that modified zero database pages is committed.
|
||||
#
|
||||
set temp_status unlocked
|
||||
if {$TEMP_STORE>=2} {set temp_status unknown}
|
||||
#set temp_status unlocked
|
||||
#if {$TEMP_STORE>=2} {set temp_status unknown}
|
||||
set temp_status unknown
|
||||
do_test lock-7.1 {
|
||||
set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
|
||||
sqlite3_step $STMT
|
||||
|
||||
+16
-14
@@ -684,22 +684,24 @@ do_faultsim_test pagerfault-14a -prep {
|
||||
# is not possible to change the page-size of an in-memory database. Even
|
||||
# using the backup API.
|
||||
#
|
||||
if {$TEMP_STORE<2} {
|
||||
do_faultsim_test pagerfault-14b -prep {
|
||||
catch { db2 close }
|
||||
faultsim_restore_and_reopen
|
||||
# Update: It is no longer possible to change the page size of any temp
|
||||
# database after it has been created.
|
||||
#
|
||||
do_faultsim_test pagerfault-14b -prep {
|
||||
catch { db2 close }
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3 db2 ""
|
||||
db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
|
||||
} -body {
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 200
|
||||
set rc [B finish]
|
||||
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
|
||||
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
|
||||
}
|
||||
} -body {
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 200
|
||||
set rc [B finish]
|
||||
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
|
||||
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {1 {attempt to write a readonly database}} \
|
||||
{1 {sqlite3_backup_init() failed}}
|
||||
}
|
||||
|
||||
do_faultsim_test pagerfault-14c -prep {
|
||||
|
||||
@@ -728,7 +728,7 @@ test_suite "inmemory_journal" -description {
|
||||
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
|
||||
vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
|
||||
e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
|
||||
fts3snippet.test mmapfault.test
|
||||
fts3snippet.test mmapfault.test sessionfault.test sessionfault2.test
|
||||
|
||||
# Exclude test scripts that use tcl IO to access journal files or count
|
||||
# the number of fsync() calls.
|
||||
@@ -942,7 +942,9 @@ test_suite "journaltest" -description {
|
||||
unregister_jt_vfs
|
||||
} -files [test_set $::allquicktests -exclude {
|
||||
wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test
|
||||
async4.test bigfile.test backcompat.test
|
||||
async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
|
||||
pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
|
||||
pager2.test *fault* rowal* snapshot* superlock* symlink.test
|
||||
}]
|
||||
|
||||
if {[info commands register_demovfs] != ""} {
|
||||
@@ -1050,15 +1052,13 @@ proc run_tests {name args} {
|
||||
set ::G(isquick) 1
|
||||
set ::G(perm:dbconfig) $options(-dbconfig)
|
||||
|
||||
uplevel $options(-initialize)
|
||||
|
||||
foreach file [lsort $options(-files)] {
|
||||
uplevel $options(-initialize)
|
||||
if {[file tail $file] == $file} { set file [file join $::testdir $file] }
|
||||
slave_test_file $file
|
||||
uplevel $options(-shutdown)
|
||||
}
|
||||
|
||||
uplevel $options(-shutdown)
|
||||
|
||||
unset ::G(perm:name)
|
||||
unset ::G(perm:prefix)
|
||||
unset ::G(perm:presql)
|
||||
|
||||
+16
-3
@@ -628,10 +628,10 @@ ifcapable tempdb&&attach {
|
||||
}
|
||||
do_test pragma-6.2 {
|
||||
execsql {
|
||||
CREATE TABLE t2(a,b,c);
|
||||
CREATE TABLE t2(a TYPE_X, b [TYPE_Y], c "TYPE_Z");
|
||||
pragma table_info(t2)
|
||||
}
|
||||
} {0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0}
|
||||
} {0 a TYPE_X 0 {} 0 1 b TYPE_Y 0 {} 0 2 c TYPE_Z 0 {} 0}
|
||||
do_test pragma-6.2.1 {
|
||||
execsql {
|
||||
pragma table_info;
|
||||
@@ -1083,7 +1083,20 @@ do_test pragma-8.2.15 {
|
||||
# "memory" or "disk" as appropriate.
|
||||
#
|
||||
proc check_temp_store {} {
|
||||
db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)}
|
||||
db eval {
|
||||
PRAGMA temp.cache_size = 1;
|
||||
CREATE TEMP TABLE IF NOT EXISTS a(b);
|
||||
DELETE FROM a;
|
||||
INSERT INTO a VALUES(randomblob(1000));
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
}
|
||||
db eval {PRAGMA database_list} {
|
||||
if {$name=="temp"} {
|
||||
set bt [btree_from_db db 1]
|
||||
|
||||
+1
-1
@@ -221,7 +221,7 @@ ifcapable shared_cache {
|
||||
# This will not work with the in-memory journal permutation, as opening
|
||||
# [db2] switches the journal mode back to "memory"
|
||||
#
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
if {[permutation]!="inmemory_journal"} {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
@@ -527,4 +527,6 @@ do_faultsim_test quota-5.6 -prep {
|
||||
}
|
||||
|
||||
catch { sqlite3_quota_shutdown }
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
finish_test
|
||||
|
||||
@@ -51,10 +51,12 @@ array set ::Configs [strip_comments {
|
||||
"Default" {
|
||||
-O2
|
||||
--disable-amalgamation --disable-shared
|
||||
--enable-session
|
||||
}
|
||||
"Sanitize" {
|
||||
CC=clang -fsanitize=undefined
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
--enable-session
|
||||
}
|
||||
"Have-Not" {
|
||||
# The "Have-Not" configuration sets all possible -UHAVE_feature options
|
||||
@@ -106,7 +108,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS
|
||||
--enable-json1 --enable-fts5
|
||||
--enable-json1 --enable-fts5 --enable-session
|
||||
}
|
||||
"Debug-One" {
|
||||
--disable-shared
|
||||
@@ -132,6 +134,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_RBU
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
-DLONGDOUBLE_TYPE=double
|
||||
--enable-session
|
||||
}
|
||||
"Device-One" {
|
||||
-O2
|
||||
@@ -168,7 +171,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_OMIT_TRACE=1
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
-DSQLITE_THREADSAFE=2
|
||||
--enable-json1 --enable-fts5
|
||||
--enable-json1 --enable-fts5 --enable-session
|
||||
}
|
||||
"Locking-Style" {
|
||||
-O2
|
||||
|
||||
@@ -968,6 +968,42 @@ do_execsql_test select4-16.3 {
|
||||
ORDER BY t3.a;
|
||||
} {95 96 97 98 99}
|
||||
|
||||
# Ticket https://www.sqlite.org/src/tktview/f7f8c97e975978d45 on 2016-04-25
|
||||
#
|
||||
# The where push-down optimization from 2015-06-02 is suppose to disable
|
||||
# on aggregate subqueries. But if the subquery is a compound where the
|
||||
# last SELECT is non-aggregate but some other SELECT is an aggregate, the
|
||||
# test is incomplete and the optimization is not properly disabled.
|
||||
#
|
||||
# The following test cases verify that the fix works.
|
||||
#
|
||||
do_execsql_test select4-17.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a int, b int);
|
||||
INSERT INTO t1 VALUES(1,2),(1,18),(2,19);
|
||||
SELECT x, y FROM (
|
||||
SELECT 98 AS x, 99 AS y
|
||||
UNION
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 20 98 99}
|
||||
do_execsql_test select4-17.2 {
|
||||
SELECT x, y FROM (
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
|
||||
UNION
|
||||
SELECT 98 AS x, 99 AS y
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 20 98 99}
|
||||
do_catchsql_test select4-17.3 {
|
||||
SELECT x, y FROM (
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3
|
||||
UNION
|
||||
SELECT 98 AS x, 99 AS y
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 {LIMIT clause should come after UNION not before}}
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -568,7 +568,7 @@ do_test shell1-3.21.2 {
|
||||
do_test shell1-3.21.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".schema FOO BAD"
|
||||
} {1 {Usage: .schema ?LIKE-PATTERN?}}
|
||||
} {1 {Usage: .schema ?--indent? ?LIKE-PATTERN?}}
|
||||
|
||||
do_test shell1-3.21.4 {
|
||||
catchcmd "test.db" {
|
||||
|
||||
@@ -365,4 +365,78 @@ do_test 6.5 {
|
||||
|
||||
sqlite3_snapshot_free $snapshot
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests investigate the sqlite3_snapshot_cmp() API.
|
||||
#
|
||||
|
||||
# Compare snapshots $p1 and $p2, checking that the result is $r.
|
||||
#
|
||||
proc do_snapshot_cmp_test {tn p1 p2 r} {
|
||||
uplevel [list do_test $tn.1 [list sqlite3_snapshot_cmp $p1 $p2] $r]
|
||||
uplevel [list do_test $tn.2 [list sqlite3_snapshot_cmp $p2 $p1] [expr $r*-1]]
|
||||
uplevel [list do_test $tn.3 [list sqlite3_snapshot_cmp $p1 $p1] 0]
|
||||
uplevel [list do_test $tn.4 [list sqlite3_snapshot_cmp $p2 $p2] 0]
|
||||
}
|
||||
|
||||
catch { db2 close }
|
||||
reset_db
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(x);
|
||||
} wal
|
||||
|
||||
do_test 7.1.2 {
|
||||
execsql { BEGIN ; PRAGMA application_id }
|
||||
set p1 [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(10);
|
||||
COMMIT;
|
||||
}
|
||||
execsql { BEGIN ; PRAGMA application_id }
|
||||
set p2 [sqlite3_snapshot_get db main]
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_snapshot_cmp_test 7.1.3 $p1 $p2 -1
|
||||
sqlite3_snapshot_free $p1
|
||||
sqlite3_snapshot_free $p2
|
||||
|
||||
do_execsql_test 7.2.1 {
|
||||
INSERT INTO t1 VALUES(11);
|
||||
INSERT INTO t1 VALUES(12);
|
||||
INSERT INTO t1 VALUES(13);
|
||||
BEGIN;
|
||||
PRAGMA application_id;
|
||||
} {0}
|
||||
do_test 7.2.2 {
|
||||
set p1 [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
COMMIT;
|
||||
INSERT INTO t1 VALUES(14);
|
||||
PRAGMA wal_checkpoint;
|
||||
BEGIN;
|
||||
PRAGMA application_id;
|
||||
}
|
||||
set p2 [sqlite3_snapshot_get db main]
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_snapshot_cmp_test 7.2.3 $p1 $p2 -1
|
||||
sqlite3_snapshot_free $p2
|
||||
|
||||
do_test 7.3.1 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(14);
|
||||
BEGIN;
|
||||
PRAGMA application_id;
|
||||
}
|
||||
set p2 [sqlite3_snapshot_get db main]
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_snapshot_cmp_test 7.3.2 $p1 $p2 -1
|
||||
sqlite3_snapshot_free $p1
|
||||
sqlite3_snapshot_free $p2
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -41,4 +41,76 @@ do_execsql_test 1.2 {
|
||||
|
||||
db close
|
||||
tvfs delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the PMA size is determined correctly. The PMA size should be
|
||||
# roughly the same amount of memory allocated to the main pager cache, or
|
||||
# 250 pages if this is larger.
|
||||
#
|
||||
testvfs tvfs
|
||||
tvfs script tv_callback
|
||||
tvfs filter {xOpen xWrite}
|
||||
|
||||
proc tv_callback {method args} {
|
||||
global iTemp
|
||||
global F
|
||||
switch $method {
|
||||
xOpen {
|
||||
if {[lindex $args 0]==""} { return "temp[incr iTemp]" }
|
||||
return "SQLITE_OK"
|
||||
}
|
||||
|
||||
xWrite {
|
||||
foreach {filename id off amt} $args {}
|
||||
if {[info exists F($id)]==0 || $F($id)<($off + $amt)} {
|
||||
set F($id) [expr $off+$amt]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
execsql { CREATE TABLE t1(x) }
|
||||
|
||||
# Each iteration of the following loop attempts to sort 10001 records
|
||||
# each a bit over 100 bytes in size. In total a little more than 1MiB
|
||||
# of data.
|
||||
#
|
||||
breakpoint
|
||||
foreach {tn pgsz cachesz bTemp} {
|
||||
2 1024 1000 1
|
||||
|
||||
1 4096 1000 0
|
||||
2 1024 1000 1
|
||||
|
||||
3 4096 -1000 1
|
||||
4 1024 -1000 1
|
||||
|
||||
5 4096 -9000 0
|
||||
6 1024 -9000 0
|
||||
} {
|
||||
do_execsql_test 2.$tn.0 "
|
||||
PRAGMA page_size = $pgsz;
|
||||
VACUUM;
|
||||
PRAGMA cache_size = $cachesz;
|
||||
"
|
||||
|
||||
do_test 2.$tn.1 {
|
||||
set ::iTemp 0
|
||||
catch { array unset F }
|
||||
execsql {
|
||||
WITH x(i, j) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT i+1, randomblob(100) FROM x WHERE i<10000
|
||||
)
|
||||
SELECT * FROM x ORDER BY j;
|
||||
}
|
||||
expr {[array names F]!=""}
|
||||
} $bTemp
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+27
-14
@@ -30,6 +30,7 @@ static const char zHelp[] =
|
||||
" --shrink-memory Invoke sqlite3_db_release_memory() frequently.\n"
|
||||
" --size N Relative test size. Default=100\n"
|
||||
" --stats Show statistics at the end\n"
|
||||
" --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n"
|
||||
" --testset T Run test-set T\n"
|
||||
" --trace Turn on SQL tracing\n"
|
||||
" --threads N Use up to N threads for sorting\n"
|
||||
@@ -69,6 +70,7 @@ static struct Global {
|
||||
int bExplain; /* Print SQL with EXPLAIN prefix */
|
||||
int bVerify; /* Try to verify that results are correct */
|
||||
int bMemShrink; /* Call sqlite3_db_release_memory() often */
|
||||
int eTemp; /* 0: no TEMP. 9: always TEMP. */
|
||||
int szTest; /* Scale factor for test iterations */
|
||||
const char *zWR; /* Might be WITHOUT ROWID */
|
||||
const char *zNN; /* Might be NOT NULL */
|
||||
@@ -78,6 +80,12 @@ static struct Global {
|
||||
char zResult[3000]; /* Text of the current result */
|
||||
} g;
|
||||
|
||||
/* Return " TEMP" or "", as appropriate for creating a table.
|
||||
*/
|
||||
static const char *isTemp(int N){
|
||||
return g.eTemp>=N ? " TEMP" : "";
|
||||
}
|
||||
|
||||
|
||||
/* Print an error message and exit */
|
||||
static void fatal_error(const char *zMsg, ...){
|
||||
@@ -459,8 +467,8 @@ void testset_main(void){
|
||||
maxb = roundup_allones(sz);
|
||||
speedtest1_begin_test(100, "%d INSERTs into table with no index", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_exec("CREATE TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
|
||||
g.zNN, g.zNN, g.zNN);
|
||||
speedtest1_exec("CREATE%s TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
|
||||
isTemp(9), g.zNN, g.zNN, g.zNN);
|
||||
speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n);
|
||||
for(i=1; i<=n; i++){
|
||||
x1 = swizzle(i,maxb);
|
||||
@@ -477,8 +485,9 @@ void testset_main(void){
|
||||
n = sz;
|
||||
speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_exec("CREATE TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
|
||||
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
speedtest1_exec(
|
||||
"CREATE%s TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
|
||||
isTemp(5), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n);
|
||||
for(i=1; i<=n; i++){
|
||||
x1 = swizzle(i,maxb);
|
||||
@@ -495,8 +504,9 @@ void testset_main(void){
|
||||
n = sz;
|
||||
speedtest1_begin_test(120, "%d unordered INSERTS with one index/PK", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_exec("CREATE TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
|
||||
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
speedtest1_exec(
|
||||
"CREATE%s TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
|
||||
isTemp(3), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
speedtest1_prepare("INSERT INTO t3 VALUES(?1,?2,?3); -- %d times", n);
|
||||
for(i=1; i<=n; i++){
|
||||
x1 = swizzle(i,maxb);
|
||||
@@ -654,12 +664,12 @@ void testset_main(void){
|
||||
speedtest1_begin_test(180, "%d INSERTS with three indexes", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_exec(
|
||||
"CREATE TABLE t4(\n"
|
||||
"CREATE%s TABLE t4(\n"
|
||||
" a INTEGER %s %s,\n"
|
||||
" b INTEGER %s,\n"
|
||||
" c TEXT %s\n"
|
||||
") %s",
|
||||
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
isTemp(1), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
|
||||
speedtest1_exec("CREATE INDEX t4b ON t4(b)");
|
||||
speedtest1_exec("CREATE INDEX t4c ON t4(c)");
|
||||
speedtest1_exec("INSERT INTO t4 SELECT * FROM t1");
|
||||
@@ -1047,7 +1057,7 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(101, "Copy from rtree to a regular table");
|
||||
speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
|
||||
speedtest1_exec(" TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
|
||||
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
|
||||
speedtest1_end_test();
|
||||
|
||||
@@ -1321,6 +1331,13 @@ int main(int argc, char **argv){
|
||||
g.szTest = integerValue(argv[++i]);
|
||||
}else if( strcmp(z,"stats")==0 ){
|
||||
showStats = 1;
|
||||
}else if( strcmp(z,"temp")==0 ){
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
i++;
|
||||
if( argv[i][0]<'0' || argv[i][0]>'9' || argv[i][1]!=0 ){
|
||||
fatal_error("argument to --temp should be integer between 0 and 9");
|
||||
}
|
||||
g.eTemp = argv[i][0] - '0';
|
||||
}else if( strcmp(z,"testset")==0 ){
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
zTSet = argv[++i];
|
||||
@@ -1352,11 +1369,7 @@ int main(int argc, char **argv){
|
||||
argv[i], argv[0]);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if( zDbName==0 ){
|
||||
fatal_error(zHelp, argv[0]);
|
||||
}
|
||||
#endif
|
||||
if( zDbName!=0 ) unlink(zDbName);
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( nHeap>0 ){
|
||||
pHeap = malloc( nHeap );
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ do_execsql_test stat-0.0 {
|
||||
SELECT * FROM stat;
|
||||
} {}
|
||||
|
||||
ifcapable wal {
|
||||
if {[wal_is_capable]} {
|
||||
do_execsql_test stat-0.1 {
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA journal_mode = delete;
|
||||
|
||||
@@ -81,6 +81,7 @@ do_test sync-1.3 {
|
||||
set sqlite_sync_count
|
||||
} 11
|
||||
ifcapable pager_pragmas {
|
||||
if {[permutation]!="journaltest"} {
|
||||
do_test sync-1.4 {
|
||||
set sqlite_sync_count 0
|
||||
execsql {
|
||||
@@ -94,6 +95,7 @@ ifcapable pager_pragmas {
|
||||
set sqlite_sync_count
|
||||
} 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
# 2016 April 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests for fault-injection when SQLite is used with
|
||||
# a temp file database.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix tempfault
|
||||
|
||||
# sqlite3_memdebug_vfs_oom_test 0
|
||||
|
||||
do_faultsim_test 1 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
} -body {
|
||||
execsql { INSERT INTO t1 VALUES(5, 6) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
set rc [catch { execsql { SELECT * FROM t1 } } msg]
|
||||
if {$rc==0 && $msg != "1 2 3 4 5 6" && $msg != "1 2 3 4"} {
|
||||
error "data mismatch 1: $msg"
|
||||
}
|
||||
if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
|
||||
error "data mismatch 2: $msg"
|
||||
}
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
do_faultsim_test 2 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE t1 SET a = randomblob(99) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
do_faultsim_test 2.1 -faults * -prep {
|
||||
if {[info commands db]==""} {
|
||||
sqlite3 db ""
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE t1 SET a = randomblob(99) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = randomblob(99);
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
|
||||
ROLLBACK TO abc;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
do_faultsim_test 4 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = randomblob(99);
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
|
||||
ROLLBACK TO abc;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
sqlite3_memdebug_vfs_oom_test 1
|
||||
finish_test
|
||||
@@ -0,0 +1,357 @@
|
||||
# 2016 March 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix temptable2
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100000 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM X;
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
PRAGMA temp.integrity_check;
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
SELECT * FROM t2;
|
||||
} {1 2 3 4}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
ROLLBACK;
|
||||
SELECT * FROM t2;
|
||||
} {1 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t1;
|
||||
} {1000}
|
||||
do_execsql_test 3.1.2 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
|
||||
ROLLBACK;
|
||||
}
|
||||
do_execsql_test 3.1.3 {
|
||||
SELECT count(*) FROM t1;
|
||||
} {1000}
|
||||
do_execsql_test 3.1.4 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==1;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==2;
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 3.2.2 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<10 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA temp.page_count;
|
||||
} {10 9}
|
||||
|
||||
do_execsql_test 4.1.2 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100);
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1.3 {
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t2;
|
||||
SELECT count(*) FROM t1;
|
||||
} {500 10}
|
||||
|
||||
do_test 4.1.4 {
|
||||
set n [db one { PRAGMA temp.page_count }]
|
||||
expr ($n >280 && $n < 300)
|
||||
} 1
|
||||
|
||||
do_execsql_test 4.1.4 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
|
||||
# Test that the temp database is now much bigger than the configured
|
||||
# cache size (10 pages).
|
||||
do_test 5.1.2 {
|
||||
set n [db one { PRAGMA temp.page_count }]
|
||||
expr ($n > 270 && $n < 290)
|
||||
} {1}
|
||||
|
||||
do_execsql_test 5.1.3 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a=2;
|
||||
UPDATE t2 SET a=randomblob(100);
|
||||
SELECT count(*) FROM t1;
|
||||
ROLLBACK;
|
||||
} {1}
|
||||
|
||||
do_execsql_test 5.1.4 {
|
||||
UPDATE t2 SET a=randomblob(100);
|
||||
|
||||
SELECT * FROM t1;
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 5.1.5 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test this:
|
||||
#
|
||||
# 1. Page is DIRTY at the start of a transaction.
|
||||
# 2. Page is written out as part of the transaction.
|
||||
# 3. Page is then read back in.
|
||||
# 4. Transaction is rolled back. Is the page now clean or dirty?
|
||||
#
|
||||
# This actually does work. Step 4 marks the page as clean. But it also
|
||||
# writes to the database file itself. So marking it clean is correct -
|
||||
# the page does match the contents of the db file.
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(x);
|
||||
INSERT INTO t1 VALUES('one');
|
||||
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
UPDATE t1 SET x='two'; -- step 1
|
||||
BEGIN;
|
||||
UPDATE t2 SET a=randomblob(100); -- step 2
|
||||
SELECT * FROM t1; -- step 3
|
||||
ROLLBACK; -- step 4
|
||||
|
||||
SELECT count(*) FROM t2;
|
||||
SELECT * FROM t1;
|
||||
} {two 500 two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
sqlite3 db ""
|
||||
do_execsql_test 7.1 {
|
||||
PRAGMA auto_vacuum=INCREMENTAL;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(zeroblob(900));
|
||||
INSERT INTO t1 VALUES(zeroblob(900));
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE rowid%2;
|
||||
PRAGMA incremental_vacuum(4);
|
||||
ROLLBACK;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try changing the page size using a backup operation when pages are
|
||||
# stored in main-memory only.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.1 {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<20 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x ORDER BY 1, 2;
|
||||
PRAGMA page_count;
|
||||
} {13}
|
||||
|
||||
do_test 8.2 {
|
||||
sqlite3 tmp ""
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
PRAGMA page_size = 8192;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x ORDER BY 1, 2;
|
||||
PRAGMA page_count;
|
||||
} tmp
|
||||
} {10}
|
||||
|
||||
do_test 8.3 {
|
||||
sqlite3_backup B tmp main db main
|
||||
B step 5
|
||||
B finish
|
||||
} {SQLITE_READONLY}
|
||||
|
||||
do_test 8.4 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
PRAGMA page_size;
|
||||
} tmp
|
||||
} {100 ok 8192}
|
||||
|
||||
do_test 8.5 {
|
||||
tmp eval { UPDATE t1 SET a=randomblob(100) }
|
||||
} {}
|
||||
|
||||
do_test 8.6 {
|
||||
sqlite3_backup B tmp main db main
|
||||
B step 1000
|
||||
B finish
|
||||
} {SQLITE_READONLY}
|
||||
|
||||
tmp close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try inserts and deletes with a large db in auto-vacuum mode. Check
|
||||
#
|
||||
foreach {tn mode} {
|
||||
1 delete
|
||||
2 wal
|
||||
} {
|
||||
reset_db
|
||||
sqlite3 db ""
|
||||
do_execsql_test 9.$tn.1.1 {
|
||||
PRAGMA cache_size = 15;
|
||||
PRAGMA auto_vacuum = 1;
|
||||
}
|
||||
execsql "PRAGMA journal_mode = $mode"
|
||||
|
||||
do_execsql_test 9.$tn.1.2 {
|
||||
CREATE TABLE tx(a, b);
|
||||
CREATE INDEX i1 ON tx(a);
|
||||
CREATE INDEX i2 ON tx(b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
for {set i 2} {$i<20} {incr i} {
|
||||
do_execsql_test 9.$tn.$i.1 { DELETE FROM tx WHERE (random()%3)==0 }
|
||||
|
||||
do_execsql_test 9.$tn.$i.2 { PRAGMA integrity_check } ok
|
||||
|
||||
do_execsql_test 9.$tn.$i.3 {
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<400 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.$i.4 { PRAGMA integrity_check } ok
|
||||
|
||||
do_execsql_test 9.$tn.$i.5 {
|
||||
BEGIN;
|
||||
DELETE FROM tx WHERE (random()%3)==0;
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.$i.6 { PRAGMA integrity_check } ok
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# When using mmap mode with a temp file, SQLite must search the cache
|
||||
# before using a mapped page even when there is no write transaction
|
||||
# open. For a temp file, the on-disk version may not be up to date.
|
||||
#
|
||||
sqlite3 db ""
|
||||
do_execsql_test 10.0 {
|
||||
PRAGMA cache_size = 50;
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
BEGIN;
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
COMMIT;
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
}
|
||||
|
||||
ifcapable mmap {
|
||||
if {[permutation]!="journaltest"} {
|
||||
# The journaltest permutation does not support mmap, so this part of
|
||||
# the test is omitted.
|
||||
do_execsql_test 10.2 { PRAGMA mmap_size = 512000 } 512000
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 10.3 { SELECT * FROM t2 } {1 2 3 4}
|
||||
do_execsql_test 10.4 { PRAGMA integrity_check } ok
|
||||
|
||||
finish_test
|
||||
+11
-1
@@ -521,7 +521,11 @@ if {[info exists cmdlinearg]==0} {
|
||||
}
|
||||
|
||||
default {
|
||||
lappend leftover [file normalize $a]
|
||||
if {[file tail $a]==$a} {
|
||||
lappend leftover $a
|
||||
} else {
|
||||
lappend leftover [file normalize $a]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1944,6 +1948,12 @@ proc wal_check_journal_mode {testname {db db}} {
|
||||
}
|
||||
}
|
||||
|
||||
proc wal_is_capable {} {
|
||||
ifcapable !wal { return 0 }
|
||||
if {[permutation]=="journaltest"} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
proc permutation {} {
|
||||
set perm ""
|
||||
catch {set perm $::G(perm:name)}
|
||||
|
||||
@@ -19,7 +19,8 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix tkt-2d1a5c67d
|
||||
|
||||
ifcapable {!wal || !vtab} {finish_test; return}
|
||||
ifcapable {!vtab} {finish_test; return}
|
||||
if {[wal_is_capable]==0} {finish_test; return}
|
||||
|
||||
for {set ii 1} {$ii<=10} {incr ii} {
|
||||
do_test tkt-2d1a5c67d.1.$ii {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user