Merge in the latest enhancements from trunks, especially the use of
_byteswap_ulong() and similar intrinsics on MSVC. FossilOrigin-Name: 85ca4409bdca7aee801e9fba1c49a87fabbf2064
This commit is contained in:
commit
bed6de557a
@ -1011,10 +1011,8 @@ fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
rm -f fts5parse.h
|
||||
./lemon $(OPTS) fts5parse.y
|
||||
mv fts5parse.c fts5parse.c.orig
|
||||
echo "#ifdef SQLITE_ENABLE_FTS5" > fts5parse.c
|
||||
cat fts5parse.c.orig | sed 's/yy/fts5yy/g' | sed 's/YY/fts5YY/g' \
|
||||
| sed 's/TOKEN/FTS5TOKEN/g' >> fts5parse.c
|
||||
echo "#endif /* SQLITE_ENABLE_FTS5 */" >> fts5parse.c
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
|
@ -1708,12 +1708,10 @@ fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
|
||||
del /Q fts5parse.h 2>NUL
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) fts5parse.y
|
||||
move fts5parse.c fts5parse.c.orig
|
||||
echo #ifdef SQLITE_ENABLE_FTS5 > $@
|
||||
type fts5parse.c.orig \
|
||||
| $(NAWK) "/.*/ { gsub(/yy/,\"fts5yy\");print }" \
|
||||
| $(NAWK) "/.*/ { gsub(/YY/,\"fts5YY\");print }" \
|
||||
| $(NAWK) "/.*/ { gsub(/TOKEN/,\"FTS5TOKEN\");print }" >> $@
|
||||
echo #endif /* SQLITE_ENABLE_FTS5 */ >> $@
|
||||
| $(NAWK) "/.*/ { gsub(/TOKEN/,\"FTS5TOKEN\");print }" > $@
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
@ -1724,7 +1722,7 @@ fts5.lo: fts5.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
|
||||
|
||||
fts5_ext.lo: fts5.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(NO_WARN) -DSQLITE_ENABLE_FTS5 -c fts5.c
|
||||
$(LTCOMPILE) $(NO_WARN) -c fts5.c
|
||||
|
||||
fts5.dll: fts5_ext.lo
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ fts5_ext.lo
|
||||
|
@ -590,7 +590,7 @@ proc print_fileheader {} {
|
||||
}]
|
||||
puts ""
|
||||
if {$::generate_fts5_code} {
|
||||
puts "#if defined(SQLITE_ENABLE_FTS5)"
|
||||
# no-op
|
||||
} else {
|
||||
puts "#ifndef SQLITE_DISABLE_FTS3_UNICODE"
|
||||
puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)"
|
||||
@ -687,7 +687,7 @@ if {$::generate_test_code} {
|
||||
}
|
||||
|
||||
if {$generate_fts5_code} {
|
||||
puts "#endif /* defined(SQLITE_ENABLE_FTS5) */"
|
||||
# no-op
|
||||
} else {
|
||||
puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */"
|
||||
puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */"
|
||||
|
@ -14,8 +14,6 @@
|
||||
#ifndef _FTS5INT_H
|
||||
#define _FTS5INT_H
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
#include "fts5.h"
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
@ -693,4 +691,3 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
|
||||
**************************************************************************/
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -11,7 +11,6 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
#include "fts5Int.h"
|
||||
#include <math.h>
|
||||
@ -552,6 +551,5 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -305,5 +304,4 @@ int sqlite3Fts5IsBareword(char t){
|
||||
return (t & 0x80) || aBareword[(int)t];
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
** This is an SQLite module implementing full-text search.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
|
||||
#include "fts5Int.h"
|
||||
@ -861,4 +860,3 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -12,7 +12,6 @@
|
||||
**
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
|
||||
#include "fts5Int.h"
|
||||
@ -2033,4 +2032,3 @@ int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
|
||||
return nRet;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -12,7 +12,6 @@
|
||||
**
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
|
||||
#include "fts5Int.h"
|
||||
@ -463,4 +462,3 @@ void sqlite3Fts5HashScanEntry(
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -16,7 +16,6 @@
|
||||
** the interface defined in fts5Int.h.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -5408,4 +5407,3 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -13,7 +13,6 @@
|
||||
** This is an SQLite module implementing full-text search.
|
||||
*/
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -2288,6 +2287,16 @@ int sqlite3_fts5_init(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_FTS5) */
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_fts_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
return sqlite3_fts5_init(db, pzErrMsg, pApi);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
**
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
|
||||
#include "fts5Int.h"
|
||||
@ -1092,4 +1091,3 @@ int sqlite3Fts5StorageConfigValue(
|
||||
}
|
||||
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -417,14 +417,14 @@ static int xF5tApi(
|
||||
CASE(14, "xSetAuxdataInt") {
|
||||
int iVal;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR;
|
||||
rc = p->pApi->xSetAuxdata(p->pFts, (void*)iVal, 0);
|
||||
rc = p->pApi->xSetAuxdata(p->pFts, (void*)((char*)0 + iVal), 0);
|
||||
break;
|
||||
}
|
||||
CASE(15, "xGetAuxdataInt") {
|
||||
int iVal;
|
||||
int bClear;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR;
|
||||
iVal = (int)p->pApi->xGetAuxdata(p->pFts, bClear);
|
||||
iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
|
||||
break;
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -1226,6 +1225,5 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_FTS5) */
|
||||
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
** DO NOT EDIT THIS MACHINE GENERATED FILE.
|
||||
*/
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@ -359,4 +358,3 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_FTS5) */
|
||||
|
@ -13,7 +13,6 @@
|
||||
** Routines for varint serialization and deserialization.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -341,4 +340,3 @@ int sqlite3Fts5GetVarintLen(u32 iVal){
|
||||
return 5;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
@ -31,7 +31,6 @@
|
||||
** $term in the database.
|
||||
*/
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
@ -486,6 +485,5 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
|
||||
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_FTS5) */
|
||||
|
||||
|
||||
|
@ -24,6 +24,8 @@ set G(src) [string map [list %dir% $srcdir] {
|
||||
|
||||
set G(hdr) {
|
||||
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
@ -33,6 +35,11 @@ set G(hdr) {
|
||||
|
||||
}
|
||||
|
||||
set G(footer) {
|
||||
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
|
||||
}
|
||||
|
||||
proc readfile {zFile} {
|
||||
set fd [open $zFile]
|
||||
set data [read $fd]
|
||||
@ -63,6 +70,7 @@ proc fts5c_printfile {zIn} {
|
||||
|
||||
proc fts5c_close {} {
|
||||
global G
|
||||
puts -nonewline $G(fd) $G(footer)
|
||||
if {$G(fd)!="stdout"} {
|
||||
close $G(fd)
|
||||
}
|
||||
|
2
main.mk
2
main.mk
@ -667,10 +667,8 @@ fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
rm -f fts5parse.h
|
||||
./lemon $(OPTS) fts5parse.y
|
||||
mv fts5parse.c fts5parse.c.orig
|
||||
echo "#ifdef SQLITE_ENABLE_FTS5" > fts5parse.c
|
||||
cat fts5parse.c.orig | sed 's/yy/fts5yy/g' | sed 's/YY/fts5YY/g' \
|
||||
| sed 's/TOKEN/FTS5TOKEN/g' >> fts5parse.c
|
||||
echo "#endif /* SQLITE_ENABLE_FTS5 */" >> fts5parse.c
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
|
72
manifest
72
manifest
@ -1,9 +1,9 @@
|
||||
C Merge\sall\sthe\slatest\senhancements\sfrom\strunk.\s\sThis\smerge\sinclude\sFTS5\nand\sa\snumber\sof\snotable\sperformance\senhancements.
|
||||
D 2015-06-30T16:29:59.664
|
||||
C Merge\sin\sthe\slatest\senhancements\sfrom\strunks,\sespecially\sthe\suse\sof\n_byteswap_ulong()\sand\ssimilar\sintrinsics\son\sMSVC.
|
||||
D 2015-07-02T18:47:12.801
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in c7566d9d9892f855145cbd28bf176fddf44a98b4
|
||||
F Makefile.in 5f96aa7b5ea06cbc72500e85d64f75f4ecd5ed52
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 1c184a23e55ed4b1781dfa127df295615a6eba0f
|
||||
F Makefile.msc 0600e09c21aeb7bff79e6badff56a406f68ced22
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
|
||||
@ -102,24 +102,24 @@ F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl ed0534dd51efce39878bce33944c6073d37a1e20
|
||||
F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
|
||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
|
||||
F ext/fts5/fts5.h 81d1a92fc2b4bd477af7e4e0b38b456f3e199fba
|
||||
F ext/fts5/fts5Int.h 918e947c0c20122ed5eb9ea695d83c6c8cf7239a
|
||||
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
|
||||
F ext/fts5/fts5_buffer.c 7428b0bcb257641cbecc3bacce7f40686cf99f36
|
||||
F ext/fts5/fts5_config.c 7d19f4516cd79f1f8b58d38aa051b70195404422
|
||||
F ext/fts5/fts5_expr.c 3386ab0a71dbab7e1259c3b16d6113c97d14123e
|
||||
F ext/fts5/fts5_hash.c c1cfdb2cae0fad00b06fae38a40eaf9261563ccc
|
||||
F ext/fts5/fts5_index.c ad32235180757f182050b8d24c9dbe61056385d2
|
||||
F ext/fts5/fts5_main.c c5b2a219d65967c07fd1bc8fd45206863a2fe360
|
||||
F ext/fts5/fts5_storage.c 3e672a0d35f63979556903861b324e7b8932cecc
|
||||
F ext/fts5/fts5_tcl.c b82f13f73a30f0959f539743f8818bece994a970
|
||||
F ext/fts5/fts5_tokenize.c 97251d68d7a6a9415bde1203f9382864dfc1f989
|
||||
F ext/fts5/fts5_unicode2.c da3cf712f05cd8347c8c5bc00964cc0361c88da9
|
||||
F ext/fts5/fts5_varint.c 366452037bf9a000c351374b489badc1b3541796
|
||||
F ext/fts5/fts5_vocab.c e454fa58c6d591024659a9b61eece0d708e8b575
|
||||
F ext/fts5/fts5Int.h c91773920639c01571d6870ac0c20e960798f79c
|
||||
F ext/fts5/fts5_aux.c 7cd0e2858171dacf505fea4e2e84ee6126854c3d
|
||||
F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015
|
||||
F ext/fts5/fts5_config.c b2456e9625bca41c51d54c363e369c6356895c90
|
||||
F ext/fts5/fts5_expr.c d2e148345639c5a5583e0daa39a639bf298ae6a7
|
||||
F ext/fts5/fts5_hash.c 219f4edd72e5cf95b19c33f1058809a18fad5229
|
||||
F ext/fts5/fts5_index.c fb1f0de6b4cd02a212c0c9c5580daa64a5634035
|
||||
F ext/fts5/fts5_main.c c24ee96e7b97178d02e66e1fe1d43f6145aab8f8
|
||||
F ext/fts5/fts5_storage.c 4cae85b5287b159d9d98174a4e70adf872b0930a
|
||||
F ext/fts5/fts5_tcl.c 85eb4e0d0fefa9420b78151496ad4599a1783e20
|
||||
F ext/fts5/fts5_tokenize.c 30f97a8c74683797b4cd233790444fbefb3b0708
|
||||
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
||||
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
||||
F ext/fts5/fts5_vocab.c 4e268a3fcbc099e50e335a1135be985a41ff6f7f
|
||||
F ext/fts5/fts5parse.y 833db1101b78c0c47686ab1b84918e38c36e9452
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl 9553cce0757092d194307c2168d4edd100eab578
|
||||
@ -178,7 +178,7 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
|
||||
F ext/fts5/test/fts5version.test bed59038e937c40d3c0056d08076db7874c6cd4a
|
||||
F ext/fts5/test/fts5vocab.test cdf97b9678484e9bad5062edf9c9106e5c3b0c5c
|
||||
F ext/fts5/tool/loadfts5.tcl 7ef3e62131f0434a78e4f5c5b056b09d221710a8
|
||||
F ext/fts5/tool/mkfts5c.tcl fdb449263837a18d9131bc2f61b256fd77e64361
|
||||
F ext/fts5/tool/mkfts5c.tcl 7174fce13c9d4b11c702eef3767344066cffe87e
|
||||
F ext/fts5/tool/showfts5.tcl 921f33b30c3189deefd2b2cc81f951638544aaf1
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
|
||||
@ -267,7 +267,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk eedc2e607f56729cdcc4b90d8654dfd472bc5bee
|
||||
F main.mk 574470491635f477235a16df7bd80e1a22a9a282
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@ -285,12 +285,12 @@ F src/alter.c 48e14b8aea28dc58baafe3cfcb8889c086b7744a
|
||||
F src/analyze.c f89727c36f997bd2bf6c5e546c2f51dc94e6f2a4
|
||||
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||
F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
|
||||
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 3a535c0118872c3ee4e198b80a62d09315381dab
|
||||
F src/btree.c cf3375bf706d15d3b8b7ac1fc86b0bf5603324d5
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 64b5723d8410a1f02c94d99c46b1b74cd547e6ef
|
||||
F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
|
||||
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
@ -333,8 +333,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
|
||||
F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 922d8ea28387b79a117488da06ee84f77d50d71e
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f
|
||||
F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
|
||||
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
|
||||
F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
@ -346,12 +346,12 @@ F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 009c6138be8788449d4f911f380d99e8608040e2
|
||||
F src/select.c 7003fe663bc0636b656874440845a85dcbad4ba7
|
||||
F src/shell.c e4ad9031072a6d679b2c69a780014d30db62dc7f
|
||||
F src/sqlite.h.in 876ad21b9a6bb5034db7c44cdebd5df2292a5336
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
|
||||
F src/sqliteInt.h 2c8f1aad45b003a5efd615ac1d12aca83cc8d364
|
||||
F src/sqliteInt.h b408931086cdcebb6d70c3561b7fe18efb2d48c9
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
@ -407,7 +407,7 @@ F src/treeview.c c84b1a8ebc7f1d00cd76ce4958eeb3ae1021beed
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 24dd6a45b8b3470e62702128ebf11be1f2693145
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 89bfe78b4610d456ba431a0865309a20acc115f3
|
||||
F src/util.c 075c2878fb698bd387164047ecdf76f6cbacf402
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 195b32310c7062847a45fda214b32ceb8f8f6ab2
|
||||
F src/vdbe.h d0f8ab919146109d080cde4b0840af9b5fafad4b
|
||||
@ -537,19 +537,19 @@ F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
|
||||
F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b
|
||||
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
|
||||
F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
|
||||
F test/corrupt2.test f2064e0bf934124cc38868fd8badb8f0dd67b552
|
||||
F test/corrupt2.test 08cec1e5ffa68a3610306d6068f112d08bc9f090
|
||||
F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18
|
||||
F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80
|
||||
F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
|
||||
F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80
|
||||
F test/corrupt7.test 22cc644c2e76c9804bc844121267aa6f8f7c0ded
|
||||
F test/corrupt7.test e4fa6d6584276679cc1d20c4e58beb9559a4eb85
|
||||
F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
|
||||
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2
|
||||
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
@ -1025,7 +1025,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c f42fd04a34a0c1dc289cbe536ef62d706227a736
|
||||
F test/speedtest1.c a2834483e435cf6017b0fead53c5a68c6efc67e8
|
||||
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
@ -1384,7 +1384,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 924f471291dfd458307a11819aa640cc1a02ac63 8bfcda3d10aec864d71d12a1248c37e4db6f8899
|
||||
R 16211acde3caeef0e3b8268914f32a0d
|
||||
P 39936b33b0668aad81aa574d4d74c92b0ddd218a bcc8a75509aafda61feb6dcc074668c79611a662
|
||||
R e09654bed267c32e59df855cf5a22b97
|
||||
U drh
|
||||
Z 476ef58b2bdb077bbb18b26bb89bdae6
|
||||
Z 52c48858632936f2e97d9ccb5e52e5d7
|
||||
|
@ -1 +1 @@
|
||||
39936b33b0668aad81aa574d4d74c92b0ddd218a
|
||||
85ca4409bdca7aee801e9fba1c49a87fabbf2064
|
15
src/backup.c
15
src/backup.c
@ -685,9 +685,13 @@ int sqlite3_backup_pagecount(sqlite3_backup *p){
|
||||
** corresponding to the source database is held when this function is
|
||||
** called.
|
||||
*/
|
||||
void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
|
||||
sqlite3_backup *p; /* Iterator variable */
|
||||
for(p=pBackup; p; p=p->pNext){
|
||||
static SQLITE_NOINLINE void backupUpdate(
|
||||
sqlite3_backup *p,
|
||||
Pgno iPage,
|
||||
const u8 *aData
|
||||
){
|
||||
assert( p!=0 );
|
||||
do{
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
|
||||
if( !isFatalError(p->rc) && iPage<p->iNext ){
|
||||
/* The backup process p has already copied page iPage. But now it
|
||||
@ -704,7 +708,10 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
|
||||
p->rc = rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}while( (p = p->pNext)!=0 );
|
||||
}
|
||||
void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
|
||||
if( pBackup ) backupUpdate(pBackup, iPage, aData);
|
||||
}
|
||||
|
||||
/*
|
||||
|
340
src/btree.c
340
src/btree.c
@ -1037,6 +1037,9 @@ static void btreeParseCellPtrNoPayload(
|
||||
assert( pPage->leaf==0 );
|
||||
assert( pPage->noPayload );
|
||||
assert( pPage->childPtrSize==4 );
|
||||
#ifndef SQLITE_DEBUG
|
||||
UNUSED_PARAMETER(pPage);
|
||||
#endif
|
||||
pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
|
||||
pInfo->nPayload = 0;
|
||||
pInfo->nLocal = 0;
|
||||
@ -1234,6 +1237,8 @@ static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
|
||||
** this function verifies that this invariant is not violated. */
|
||||
CellInfo debuginfo;
|
||||
pPage->xParseCell(pPage, pCell, &debuginfo);
|
||||
#else
|
||||
UNUSED_PARAMETER(pPage);
|
||||
#endif
|
||||
|
||||
assert( pPage->childPtrSize==4 );
|
||||
@ -3584,7 +3589,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){
|
||||
static int autoVacuumCommit(BtShared *pBt){
|
||||
int rc = SQLITE_OK;
|
||||
Pager *pPager = pBt->pPager;
|
||||
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) );
|
||||
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
invalidateAllOverflowCache(pBt);
|
||||
@ -8919,32 +8924,38 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
|
||||
**
|
||||
** 1. Make sure that cells and freeblocks do not overlap
|
||||
** but combine to completely cover the page.
|
||||
** NO 2. Make sure cell keys are in order.
|
||||
** NO 3. Make sure no key is less than or equal to zLowerBound.
|
||||
** NO 4. Make sure no key is greater than or equal to zUpperBound.
|
||||
** 5. Check the integrity of overflow pages.
|
||||
** 6. Recursively call checkTreePage on all children.
|
||||
** 7. Verify that the depth of all children is the same.
|
||||
** 8. Make sure this page is at least 33% full or else it is
|
||||
** the root of the tree.
|
||||
** 2. Make sure integer cell keys are in order.
|
||||
** 3. Check the integrity of overflow pages.
|
||||
** 4. Recursively call checkTreePage on all children.
|
||||
** 5. Verify that the depth of all children is the same.
|
||||
*/
|
||||
static int checkTreePage(
|
||||
IntegrityCk *pCheck, /* Context for the sanity check */
|
||||
int iPage, /* Page number of the page to check */
|
||||
i64 *pnParentMinKey,
|
||||
i64 *pnParentMaxKey
|
||||
i64 *piMinKey, /* Write minimum integer primary key here */
|
||||
i64 maxKey /* Error if integer primary key greater than this */
|
||||
){
|
||||
MemPage *pPage;
|
||||
int i, rc, depth, d2, pgno, cnt;
|
||||
int hdr, cellStart;
|
||||
int nCell;
|
||||
u8 *data;
|
||||
BtShared *pBt;
|
||||
int usableSize;
|
||||
u32 *heap = 0;
|
||||
MemPage *pPage = 0; /* The page being analyzed */
|
||||
int i; /* Loop counter */
|
||||
int rc; /* Result code from subroutine call */
|
||||
int depth = -1, d2; /* Depth of a subtree */
|
||||
int pgno; /* Page number */
|
||||
int nFrag; /* Number of fragmented bytes on the page */
|
||||
int hdr; /* Offset to the page header */
|
||||
int cellStart; /* Offset to the start of the cell pointer array */
|
||||
int nCell; /* Number of cells */
|
||||
int doCoverageCheck = 1; /* True if cell coverage checking should be done */
|
||||
int keyCanBeEqual = 1; /* True if IPK can be equal to maxKey
|
||||
** False if IPK must be strictly less than maxKey */
|
||||
u8 *data; /* Page content */
|
||||
u8 *pCell; /* Cell content */
|
||||
u8 *pCellIdx; /* Next element of the cell pointer array */
|
||||
BtShared *pBt; /* The BtShared object that owns pPage */
|
||||
u32 pc; /* Address of a cell */
|
||||
u32 usableSize; /* Usable size of the page */
|
||||
u32 contentOffset; /* Offset to the start of the cell content area */
|
||||
u32 *heap = 0; /* Min-heap used for checking cell coverage */
|
||||
u32 x, prev = 0;
|
||||
i64 nMinKey = 0;
|
||||
i64 nMaxKey = 0;
|
||||
const char *saved_zPfx = pCheck->zPfx;
|
||||
int saved_v1 = pCheck->v1;
|
||||
int saved_v2 = pCheck->v2;
|
||||
@ -8960,7 +8971,6 @@ static int checkTreePage(
|
||||
if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
|
||||
checkAppendMsg(pCheck,
|
||||
"unable to get the page. error code=%d", rc);
|
||||
depth = -1;
|
||||
goto end_of_check;
|
||||
}
|
||||
|
||||
@ -8971,43 +8981,85 @@ static int checkTreePage(
|
||||
assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
|
||||
checkAppendMsg(pCheck,
|
||||
"btreeInitPage() returns error code %d", rc);
|
||||
releasePage(pPage);
|
||||
depth = -1;
|
||||
goto end_of_check;
|
||||
}
|
||||
data = pPage->aData;
|
||||
hdr = pPage->hdrOffset;
|
||||
|
||||
/* Check out all the cells.
|
||||
*/
|
||||
depth = 0;
|
||||
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
|
||||
u8 *pCell;
|
||||
u32 sz;
|
||||
/* Set up for cell analysis */
|
||||
pCheck->zPfx = "On tree page %d cell %d: ";
|
||||
contentOffset = get2byteNotZero(&data[hdr+5]);
|
||||
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
assert( pPage->nCell==nCell );
|
||||
|
||||
/* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
|
||||
** immediately follows the b-tree page header. */
|
||||
cellStart = hdr + 12 - 4*pPage->leaf;
|
||||
assert( pPage->aCellIdx==&data[cellStart] );
|
||||
pCellIdx = &data[cellStart + 2*(nCell-1)];
|
||||
|
||||
if( !pPage->leaf ){
|
||||
/* Analyze the right-child page of internal pages */
|
||||
pgno = get4byte(&data[hdr+8]);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
pCheck->zPfx = "On page %d at right child: ";
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
|
||||
}
|
||||
#endif
|
||||
depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
|
||||
keyCanBeEqual = 0;
|
||||
}else{
|
||||
/* For leaf pages, the coverage check will occur in the same loop
|
||||
** as the other cell checks, so initialize the heap. */
|
||||
heap = pCheck->heap;
|
||||
heap[0] = 0;
|
||||
btreeHeapInsert(heap, contentOffset-1);
|
||||
}
|
||||
|
||||
/* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte
|
||||
** integer offsets to the cell contents. */
|
||||
for(i=nCell-1; i>=0 && pCheck->mxErr; i--){
|
||||
CellInfo info;
|
||||
|
||||
/* Check payload overflow pages
|
||||
*/
|
||||
pCheck->zPfx = "On tree page %d cell %d: ";
|
||||
pCheck->v1 = iPage;
|
||||
/* Check cell size */
|
||||
pCheck->v2 = i;
|
||||
pCell = findCell(pPage,i);
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
sz = info.nPayload;
|
||||
/* For intKey pages, check that the keys are in order.
|
||||
*/
|
||||
if( pPage->intKey ){
|
||||
if( i==0 ){
|
||||
nMinKey = nMaxKey = info.nKey;
|
||||
}else if( info.nKey <= nMaxKey ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
|
||||
}
|
||||
nMaxKey = info.nKey;
|
||||
assert( pCellIdx==&data[cellStart + i*2] );
|
||||
pc = get2byteAligned(pCellIdx);
|
||||
pCellIdx -= 2;
|
||||
if( pc<contentOffset || pc>usableSize-4 ){
|
||||
checkAppendMsg(pCheck, "Offset %d out of range %d..%d",
|
||||
pc, contentOffset, usableSize-4);
|
||||
doCoverageCheck = 0;
|
||||
continue;
|
||||
}
|
||||
if( (sz>info.nLocal)
|
||||
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
|
||||
){
|
||||
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
|
||||
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
|
||||
pCell = &data[pc];
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
if( pc+info.nSize>usableSize ){
|
||||
checkAppendMsg(pCheck, "Extends off end of page");
|
||||
doCoverageCheck = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for integer primary key out of range */
|
||||
if( pPage->intKey ){
|
||||
if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
|
||||
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
|
||||
}
|
||||
maxKey = info.nKey;
|
||||
}
|
||||
|
||||
/* Check the content overflow list */
|
||||
if( info.nPayload>info.nLocal ){
|
||||
int nPage; /* Number of pages on the overflow chain */
|
||||
Pgno pgnoOvfl; /* First page of the overflow chain */
|
||||
assert( pc + info.iOverflow <= usableSize );
|
||||
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
|
||||
pgnoOvfl = get4byte(&pCell[info.iOverflow]);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
|
||||
@ -9016,117 +9068,57 @@ static int checkTreePage(
|
||||
checkList(pCheck, 0, pgnoOvfl, nPage);
|
||||
}
|
||||
|
||||
/* Check sanity of left child page.
|
||||
*/
|
||||
if( !pPage->leaf ){
|
||||
/* Check sanity of left child page for internal pages */
|
||||
pgno = get4byte(pCell);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
|
||||
}
|
||||
#endif
|
||||
d2 = checkTreePage(pCheck, pgno, &nMinKey, i==0?NULL:&nMaxKey);
|
||||
if( i>0 && d2!=depth ){
|
||||
d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey);
|
||||
keyCanBeEqual = 0;
|
||||
if( d2!=depth ){
|
||||
checkAppendMsg(pCheck, "Child page depth differs");
|
||||
depth = d2;
|
||||
}
|
||||
depth = d2;
|
||||
}
|
||||
}
|
||||
|
||||
if( !pPage->leaf ){
|
||||
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
pCheck->zPfx = "On page %d at right child: ";
|
||||
pCheck->v1 = iPage;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
|
||||
}
|
||||
#endif
|
||||
checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
|
||||
}
|
||||
|
||||
/* For intKey leaf pages, check that the min/max keys are in order
|
||||
** with any left/parent/right pages.
|
||||
*/
|
||||
pCheck->zPfx = "Page %d: ";
|
||||
pCheck->v1 = iPage;
|
||||
if( pPage->leaf && pPage->intKey ){
|
||||
/* if we are a left child page */
|
||||
if( pnParentMinKey ){
|
||||
/* if we are the left most child page */
|
||||
if( !pnParentMaxKey ){
|
||||
if( nMaxKey > *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Rowid %lld out of order (max larger than parent min of %lld)",
|
||||
nMaxKey, *pnParentMinKey);
|
||||
}
|
||||
}else{
|
||||
if( nMinKey <= *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Rowid %lld out of order (min less than parent min of %lld)",
|
||||
nMinKey, *pnParentMinKey);
|
||||
}
|
||||
if( nMaxKey > *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Rowid %lld out of order (max larger than parent max of %lld)",
|
||||
nMaxKey, *pnParentMaxKey);
|
||||
}
|
||||
*pnParentMinKey = nMaxKey;
|
||||
}
|
||||
/* else if we're a right child page */
|
||||
} else if( pnParentMaxKey ){
|
||||
if( nMinKey <= *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Rowid %lld out of order (min less than parent max of %lld)",
|
||||
nMinKey, *pnParentMaxKey);
|
||||
}
|
||||
}else{
|
||||
/* Populate the coverage-checking heap for leaf pages */
|
||||
btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
|
||||
}
|
||||
}
|
||||
*piMinKey = maxKey;
|
||||
|
||||
/* Check for complete coverage of the page
|
||||
*/
|
||||
data = pPage->aData;
|
||||
hdr = pPage->hdrOffset;
|
||||
heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||
pCheck->zPfx = 0;
|
||||
if( heap==0 ){
|
||||
pCheck->mallocFailed = 1;
|
||||
}else{
|
||||
int contentOffset = get2byteNotZero(&data[hdr+5]);
|
||||
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
heap[0] = 0;
|
||||
btreeHeapInsert(heap, contentOffset-1);
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
/* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
|
||||
** immediately follows the b-tree page header. */
|
||||
cellStart = hdr + 12 - 4*pPage->leaf;
|
||||
/* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte
|
||||
** integer offsets to the cell contents. */
|
||||
for(i=0; i<nCell; i++){
|
||||
int pc = get2byteAligned(&data[cellStart+i*2]);
|
||||
u32 size = 65536;
|
||||
if( pc<=usableSize-4 ){
|
||||
if( doCoverageCheck && pCheck->mxErr>0 ){
|
||||
/* For leaf pages, the min-heap has already been initialized and the
|
||||
** cells have already been inserted. But for internal pages, that has
|
||||
** not yet been done, so do it now */
|
||||
if( !pPage->leaf ){
|
||||
heap = pCheck->heap;
|
||||
heap[0] = 0;
|
||||
btreeHeapInsert(heap, contentOffset-1);
|
||||
for(i=nCell-1; i>=0; i--){
|
||||
u32 size;
|
||||
pc = get2byteAligned(&data[cellStart+i*2]);
|
||||
size = pPage->xCellSize(pPage, &data[pc]);
|
||||
}
|
||||
if( (int)(pc+size-1)>=usableSize ){
|
||||
pCheck->zPfx = 0;
|
||||
checkAppendMsg(pCheck,
|
||||
"Corruption detected in cell %d on page %d",i,iPage);
|
||||
}else{
|
||||
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
|
||||
}
|
||||
}
|
||||
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
||||
/* Add the freeblocks to the min-heap
|
||||
**
|
||||
** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
||||
** is the offset of the first freeblock, or zero if there are no
|
||||
** freeblocks on the page. */
|
||||
** freeblocks on the page.
|
||||
*/
|
||||
i = get2byte(&data[hdr+1]);
|
||||
while( i>0 ){
|
||||
int size, j;
|
||||
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
size = get2byte(&data[i+2]);
|
||||
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
btreeHeapInsert(heap, (i<<16)|(i+size-1));
|
||||
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
||||
** big-endian integer which is the offset in the b-tree page of the next
|
||||
@ -9136,10 +9128,13 @@ static int checkTreePage(
|
||||
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
|
||||
** increasing offset. */
|
||||
assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */
|
||||
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
i = j;
|
||||
}
|
||||
cnt = 0;
|
||||
/* Analyze the min-heap looking for overlap between cells and/or
|
||||
** freeblocks, and counting the number of untracked bytes in nFrag.
|
||||
*/
|
||||
nFrag = 0;
|
||||
assert( heap[0]>0 );
|
||||
assert( (heap[1]>>16)==0 );
|
||||
btreeHeapPull(heap,&prev);
|
||||
@ -9149,26 +9144,25 @@ static int checkTreePage(
|
||||
"Multiple uses for byte %u of page %d", x>>16, iPage);
|
||||
break;
|
||||
}else{
|
||||
cnt += (x>>16) - (prev&0xffff) - 1;
|
||||
nFrag += (x>>16) - (prev&0xffff) - 1;
|
||||
prev = x;
|
||||
}
|
||||
}
|
||||
cnt += usableSize - (prev&0xffff) - 1;
|
||||
nFrag += usableSize - (prev&0xffff) - 1;
|
||||
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
|
||||
** is stored in the fifth field of the b-tree page header.
|
||||
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
|
||||
** number of fragmented free bytes within the cell content area.
|
||||
*/
|
||||
if( heap[0]==0 && cnt!=data[hdr+7] ){
|
||||
if( heap[0]==0 && nFrag!=data[hdr+7] ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Fragmentation of %d bytes reported as %d on page %d",
|
||||
cnt, data[hdr+7], iPage);
|
||||
nFrag, data[hdr+7], iPage);
|
||||
}
|
||||
}
|
||||
sqlite3PageFree(heap);
|
||||
releasePage(pPage);
|
||||
|
||||
end_of_check:
|
||||
releasePage(pPage);
|
||||
pCheck->zPfx = saved_zPfx;
|
||||
pCheck->v1 = saved_v1;
|
||||
pCheck->v2 = saved_v2;
|
||||
@ -9198,14 +9192,15 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
int *pnErr /* Write number of errors seen to this variable */
|
||||
){
|
||||
Pgno i;
|
||||
int nRef;
|
||||
IntegrityCk sCheck;
|
||||
BtShared *pBt = p->pBt;
|
||||
int savedDbFlags = pBt->db->flags;
|
||||
char zErr[100];
|
||||
VVA_ONLY( int nRef );
|
||||
|
||||
sqlite3BtreeEnter(p);
|
||||
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
|
||||
nRef = sqlite3PagerRefcount(pBt->pPager);
|
||||
assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 );
|
||||
sCheck.pBt = pBt;
|
||||
sCheck.pPager = pBt->pPager;
|
||||
sCheck.nPage = btreePagecount(sCheck.pBt);
|
||||
@ -9215,21 +9210,26 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
sCheck.zPfx = 0;
|
||||
sCheck.v1 = 0;
|
||||
sCheck.v2 = 0;
|
||||
*pnErr = 0;
|
||||
sCheck.aPgRef = 0;
|
||||
sCheck.heap = 0;
|
||||
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
|
||||
if( sCheck.nPage==0 ){
|
||||
sqlite3BtreeLeave(p);
|
||||
return 0;
|
||||
goto integrity_ck_cleanup;
|
||||
}
|
||||
|
||||
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
|
||||
if( !sCheck.aPgRef ){
|
||||
*pnErr = 1;
|
||||
sqlite3BtreeLeave(p);
|
||||
return 0;
|
||||
sCheck.mallocFailed = 1;
|
||||
goto integrity_ck_cleanup;
|
||||
}
|
||||
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||
if( sCheck.heap==0 ){
|
||||
sCheck.mallocFailed = 1;
|
||||
goto integrity_ck_cleanup;
|
||||
}
|
||||
|
||||
i = PENDING_BYTE_PAGE(pBt);
|
||||
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
|
||||
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
|
||||
|
||||
/* Check the integrity of the freelist
|
||||
*/
|
||||
@ -9240,17 +9240,19 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
|
||||
/* Check all the tables.
|
||||
*/
|
||||
testcase( pBt->db->flags & SQLITE_CellSizeCk );
|
||||
pBt->db->flags &= ~SQLITE_CellSizeCk;
|
||||
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
|
||||
i64 notUsed;
|
||||
if( aRoot[i]==0 ) continue;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum && aRoot[i]>1 ){
|
||||
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
|
||||
}
|
||||
#endif
|
||||
sCheck.zPfx = "List of tree roots: ";
|
||||
checkTreePage(&sCheck, aRoot[i], NULL, NULL);
|
||||
sCheck.zPfx = 0;
|
||||
checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
|
||||
}
|
||||
pBt->db->flags = savedDbFlags;
|
||||
|
||||
/* Make sure every page in the file is referenced
|
||||
*/
|
||||
@ -9274,28 +9276,20 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make sure this analysis did not leave any unref() pages.
|
||||
** This is an internal consistency check; an integrity check
|
||||
** of the integrity check.
|
||||
*/
|
||||
if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
|
||||
checkAppendMsg(&sCheck,
|
||||
"Outstanding page count goes from %d to %d during this analysis",
|
||||
nRef, sqlite3PagerRefcount(pBt->pPager)
|
||||
);
|
||||
}
|
||||
|
||||
/* Clean up and report errors.
|
||||
*/
|
||||
sqlite3BtreeLeave(p);
|
||||
integrity_ck_cleanup:
|
||||
sqlite3PageFree(sCheck.heap);
|
||||
sqlite3_free(sCheck.aPgRef);
|
||||
if( sCheck.mallocFailed ){
|
||||
sqlite3StrAccumReset(&sCheck.errMsg);
|
||||
*pnErr = sCheck.nErr+1;
|
||||
return 0;
|
||||
sCheck.nErr++;
|
||||
}
|
||||
*pnErr = sCheck.nErr;
|
||||
if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
|
||||
/* Make sure this analysis did not leave any unref() pages. */
|
||||
assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
|
||||
sqlite3BtreeLeave(p);
|
||||
return sqlite3StrAccumFinish(&sCheck.errMsg);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
@ -682,6 +682,7 @@ struct IntegrityCk {
|
||||
const char *zPfx; /* Error message prefix */
|
||||
int v1, v2; /* Values for up to two %d fields in zPfx */
|
||||
StrAccum errMsg; /* Accumulate the error message text here */
|
||||
u32 *heap; /* Min-heap used for analyzing cell coverage */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -701,6 +702,8 @@ struct IntegrityCk {
|
||||
# define get2byteAligned(x) (*(u16*)(x))
|
||||
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
|
||||
# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
|
||||
#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300
|
||||
# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
|
||||
#else
|
||||
# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
|
||||
#endif
|
||||
|
@ -6387,12 +6387,14 @@ u8 sqlite3PagerIsreadonly(Pager *pPager){
|
||||
return pPager->readOnly;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return the number of references to the pager.
|
||||
*/
|
||||
int sqlite3PagerRefcount(Pager *pPager){
|
||||
return sqlite3PcacheRefCount(pPager->pPCache);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the approximate number of bytes of memory currently
|
||||
|
@ -173,7 +173,9 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
/* Functions used to query pager state and configuration. */
|
||||
u8 sqlite3PagerIsreadonly(Pager*);
|
||||
u32 sqlite3PagerDataVersion(Pager*);
|
||||
int sqlite3PagerRefcount(Pager*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3PagerRefcount(Pager*);
|
||||
#endif
|
||||
int sqlite3PagerMemUsed(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*, int);
|
||||
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
||||
|
@ -4769,7 +4769,7 @@ int sqlite3Select(
|
||||
WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
|
||||
Vdbe *v; /* The virtual machine under construction */
|
||||
int isAgg; /* True for select lists like "count(*)" */
|
||||
ExprList *pEList; /* List of columns to extract. */
|
||||
ExprList *pEList = 0; /* List of columns to extract. */
|
||||
SrcList *pTabList; /* List of tables to select from */
|
||||
Expr *pWhere; /* The WHERE clause. May be NULL */
|
||||
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
|
||||
|
@ -185,6 +185,16 @@
|
||||
# define SQLITE_NOINLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make sure that the compiler intrinsics we desire are enabled when
|
||||
** compiling with an appropriate version of MSVC.
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER>=1300
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_byteswap_ushort)
|
||||
# pragma intrinsic(_byteswap_ulong)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
|
||||
** 0 means mutexes are permanently disable and the library is never
|
||||
|
@ -1086,6 +1086,10 @@ u32 sqlite3Get4byte(const u8 *p){
|
||||
u32 x;
|
||||
memcpy(&x,p,4);
|
||||
return __builtin_bswap32(x);
|
||||
#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300
|
||||
u32 x;
|
||||
memcpy(&x,p,4);
|
||||
return _byteswap_ulong(x);
|
||||
#else
|
||||
testcase( p[0]&0x80 );
|
||||
return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
||||
@ -1097,6 +1101,9 @@ void sqlite3Put4byte(unsigned char *p, u32 v){
|
||||
#elif SQLITE_BYTEORDER==1234 && defined(__GNUC__)
|
||||
u32 x = __builtin_bswap32(v);
|
||||
memcpy(p,&x,4);
|
||||
#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300
|
||||
u32 x = _byteswap_ulong(v);
|
||||
memcpy(p,&x,4);
|
||||
#else
|
||||
p[0] = (u8)(v>>24);
|
||||
p[1] = (u8)(v>>16);
|
||||
|
@ -249,7 +249,6 @@ do_test corrupt2-5.1 {
|
||||
set result
|
||||
} {{*** in database main ***
|
||||
On tree page 2 cell 0: 2nd reference to page 10
|
||||
On tree page 2 cell 1: Child page depth differs
|
||||
Page 4 is never used}}
|
||||
|
||||
db2 close
|
||||
|
@ -65,41 +65,20 @@ integrity_check corrupt7-1.4
|
||||
|
||||
# Deliberately corrupt some of the cell offsets in the btree page
|
||||
# on page 2 of the database.
|
||||
#
|
||||
# The error message is different depending on whether or not the
|
||||
# SQLITE_ENABLE_OVERSIZE_CELL_CHECK compile-time option is engaged.
|
||||
#
|
||||
ifcapable oversize_cell_check {
|
||||
do_test corrupt7-2.1 {
|
||||
db close
|
||||
hexio_write test.db 1062 FF
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
Page 2: btreeInitPage() returns error code 11}}
|
||||
do_test corrupt7-2.2 {
|
||||
db close
|
||||
hexio_write test.db 1062 04
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
Page 2: btreeInitPage() returns error code 11}}
|
||||
} else {
|
||||
do_test corrupt7-2.1 {
|
||||
db close
|
||||
hexio_write test.db 1062 FF
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
Corruption detected in cell 15 on page 2}}
|
||||
do_test corrupt7-2.2 {
|
||||
db close
|
||||
hexio_write test.db 1062 04
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
|
||||
}
|
||||
do_test corrupt7-2.1 {
|
||||
db close
|
||||
hexio_write test.db 1062 FF
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
On tree page 2 cell 15: Offset 65457 out of range 945..1020}}
|
||||
do_test corrupt7-2.2 {
|
||||
db close
|
||||
hexio_write test.db 1062 04
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
On tree page 2 cell 15: Offset 1201 out of range 945..1020}}
|
||||
|
||||
# The code path that was causing the buffer overrun that this test
|
||||
# case was checking for was removed.
|
||||
|
@ -14,7 +14,6 @@
|
||||
# segfault if it sees a corrupt database file. It specifcally
|
||||
# focuses on rowid order corruption.
|
||||
#
|
||||
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -79,12 +78,8 @@ do_test corruptE-2.1 {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*previous was} $ans] \
|
||||
[regexp {out of order.*max larger than parent max} $ans]
|
||||
} {1 1}
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {/ out of order/}
|
||||
|
||||
do_test corruptE-2.2 {
|
||||
db close
|
||||
@ -95,12 +90,8 @@ do_test corruptE-2.2 {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*previous was} $ans] \
|
||||
[regexp {out of order.*min less than parent min} $ans]
|
||||
} {1 1}
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {/ Extends off end of page/}
|
||||
|
||||
do_test corruptE-2.3 {
|
||||
db close
|
||||
@ -112,11 +103,8 @@ do_test corruptE-2.3 {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*max larger than parent min} $ans]
|
||||
} {1}
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {/out of order/}
|
||||
|
||||
do_test corruptE-2.4 {
|
||||
db close
|
||||
@ -127,33 +115,22 @@ do_test corruptE-2.4 {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*min less than parent max} $ans]
|
||||
} {1}
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {/out of order/}
|
||||
|
||||
|
||||
set tests [list {10233 0xd0} \
|
||||
{941 0x42} \
|
||||
{1028 0x53} \
|
||||
{2041 0xd0} \
|
||||
{2042 0x1f} \
|
||||
{2047 0xaa} \
|
||||
{2263 0x29} \
|
||||
{2274 0x75} \
|
||||
{3267 0xf2} \
|
||||
{4104 0x2c} \
|
||||
{5113 0x36} \
|
||||
{10233 0x84} \
|
||||
{10234 0x74} \
|
||||
{10239 0x41} \
|
||||
{10453 0x11} \
|
||||
{11273 0x28} \
|
||||
{11455 0x11} \
|
||||
{11461 0xe6} \
|
||||
{12281 0x99} \
|
||||
{12296 0x9e} \
|
||||
{12297 0xd7} \
|
||||
{13303 0x53} ]
|
||||
|
||||
@ -168,11 +145,8 @@ foreach test $tests {
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order} $ans]
|
||||
} {1}
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {/out of order/}
|
||||
incr tc 1
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ static const char zHelp[] =
|
||||
" --reprepare Reprepare each statement upon every invocation\n"
|
||||
" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
|
||||
" --sqlonly No-op. Only show the SQL that would have been run.\n"
|
||||
" --shrink-memory Invoke sqlite3_db_release_memory() frequently.\n"
|
||||
" --size N Relative test size. Default=100\n"
|
||||
" --stats Show statistics at the end\n"
|
||||
" --testset T Run test-set T\n"
|
||||
@ -61,6 +62,7 @@ static struct Global {
|
||||
int bSqlOnly; /* True to print the SQL once only */
|
||||
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 szTest; /* Scale factor for test iterations */
|
||||
const char *zWR; /* Might be WITHOUT ROWID */
|
||||
const char *zNN; /* Might be NOT NULL */
|
||||
@ -324,6 +326,15 @@ static void printSql(const char *zSql){
|
||||
}
|
||||
}
|
||||
|
||||
/* Shrink memory used, if appropriate and if the SQLite version is capable
|
||||
** of doing so.
|
||||
*/
|
||||
void speedtest1_shrink_memory(void){
|
||||
#if SQLITE_VERSION_NUMBER>=3007010
|
||||
if( g.bMemShrink ) sqlite3_db_release_memory(g.db);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Run SQL */
|
||||
void speedtest1_exec(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
@ -340,6 +351,7 @@ void speedtest1_exec(const char *zFormat, ...){
|
||||
if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
speedtest1_shrink_memory();
|
||||
}
|
||||
|
||||
/* Prepare an SQL statement */
|
||||
@ -392,6 +404,7 @@ void speedtest1_run(void){
|
||||
{
|
||||
sqlite3_reset(g.pStmt);
|
||||
}
|
||||
speedtest1_shrink_memory();
|
||||
}
|
||||
|
||||
/* The sqlite3_trace() callback function */
|
||||
@ -1242,6 +1255,8 @@ int main(int argc, char **argv){
|
||||
i += 2;
|
||||
}else if( strcmp(z,"sqlonly")==0 ){
|
||||
g.bSqlOnly = 1;
|
||||
}else if( strcmp(z,"shrink-memory")==0 ){
|
||||
g.bMemShrink = 1;
|
||||
}else if( strcmp(z,"size")==0 ){
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
g.szTest = integerValue(argv[++i]);
|
||||
|
Loading…
Reference in New Issue
Block a user