diff --git a/Makefile.in b/Makefile.in index 469f144e6c..6da7bff345 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1050,15 +1050,18 @@ soaktest: $(TESTPROGS) ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS) # Do extra testing but not everything. -fulltestonly: $(TESTPROGS) +fulltestonly: $(TESTPROGS) fuzztest ./testfixture$(TEXE) $(TOP)/test/full.test # Fuzz testing fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) ./fuzzcheck$(TEXE) $(FUZZDATA) +fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) + ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) + valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) - valgrind ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA) + valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA) # Minimal testing that runs in less than 3 minutes # @@ -1068,7 +1071,7 @@ quicktest: ./testfixture$(TEXE) # This is the common case. Run many tests that do not take too long, # including fuzzcheck, sqlite3_analyzer, and sqldiff tests. # -test: $(TESTPROGS) fuzztest +test: $(TESTPROGS) fastfuzztest ./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS) # Run a test using valgrind. This can take a really long time diff --git a/Makefile.msc b/Makefile.msc index cd5010b2c1..64e2d26e07 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1766,6 +1766,9 @@ queryplantest: testfixture.exe sqlite3.exe fuzztest: fuzzcheck.exe .\fuzzcheck.exe $(FUZZDATA) +fastfuzztest: fuzzcheck.exe + .\fuzzcheck.exe --limit-mem 100M $(FUZZDATA) + # Minimal testing that runs in less than 3 minutes (on a fast machine) # quicktest: testfixture.exe @@ -1774,7 +1777,7 @@ quicktest: testfixture.exe # This is the common case. Run many tests that do not take too long, # including fuzzcheck, sqlite3_analyzer, and sqldiff tests. # -test: $(TESTPROGS) fuzztest +test: $(TESTPROGS) fastfuzztest .\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS) smoketest: $(TESTPROGS) diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 97ff3c72a0..861b20863a 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -60,7 +60,7 @@ struct Fts5ExprNode { /* Child nodes. For a NOT node, this array always contains 2 entries. For ** AND or OR nodes, it contains 2 or more entries. */ int nChild; /* Number of child nodes */ - Fts5ExprNode *apChild[0]; /* Array of child nodes */ + Fts5ExprNode *apChild[1]; /* Array of child nodes */ }; #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) @@ -1619,7 +1619,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode( if( pRight->eType==eType ) nChild += pRight->nChild-1; } - nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*nChild; + nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1); pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); if( pRet ){ diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 4229573391..2d23607d3f 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -3754,13 +3754,13 @@ static void fts5IndexMergeLevel( fts5MultiIterEof(p, pIter)==0; fts5MultiIterNext(p, pIter, 0, 0) ){ - Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; int nPos; /* position-list size field value */ int nTerm; const u8 *pTerm; /* Check for key annihilation. */ - if( pSeg->nPos==0 && (bOldest || pSeg->bDel==0) ) continue; + if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue; pTerm = fts5MultiIterTerm(pIter, &nTerm); if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){ @@ -3779,11 +3779,11 @@ static void fts5IndexMergeLevel( /* Append the rowid to the output */ /* WRITEPOSLISTSIZE */ - nPos = pSeg->nPos*2 + pSeg->bDel; + nPos = pSegIter->nPos*2 + pSegIter->bDel; fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter), nPos); /* Append the position-list data to the output */ - fts5ChunkIterate(p, pSeg, (void*)&writer, fts5MergeChunkCallback); + fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback); } /* Flush the last leaf page to disk. Set the output segment b-tree height diff --git a/ext/rbu/rbu.c b/ext/rbu/rbu.c index 6e84bbdebe..dd46743def 100644 --- a/ext/rbu/rbu.c +++ b/ext/rbu/rbu.c @@ -65,6 +65,7 @@ int main(int argc, char **argv){ int i; const char *zTarget; /* Target database to apply RBU to */ const char *zRbu; /* Database containing RBU */ + char zBuf[200]; /* Buffer for printf() */ char *zErrmsg; /* Error message, if any */ sqlite3rbu *pRbu; /* RBU handle */ int nStep = 0; /* Maximum number of step() calls */ @@ -98,17 +99,19 @@ int main(int argc, char **argv){ /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: - fprintf(stdout, + sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_OK: rbu update incomplete (%lld operations so far)\n", nProgress ); + fprintf(stdout, zBuf); break; case SQLITE_DONE: - fprintf(stdout, + sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_DONE: rbu update completed (%lld operations)\n", nProgress ); + fprintf(stdout, zBuf); break; default: diff --git a/ext/rbu/rbu14.test b/ext/rbu/rbu14.test new file mode 100644 index 0000000000..d4f97ac32c --- /dev/null +++ b/ext/rbu/rbu14.test @@ -0,0 +1,95 @@ +# 2015 July 25 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test that an RBU data_xxx table may be a view instead of a regular +# table. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source $testdir/tester.tcl +source $testdir/lock_common.tcl +set ::testprefix rbu14 + + +foreach {tn schema} { + 1 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b, c); + } + 2 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b, c); + CREATE INDEX i2 ON t2(b, c); + } + 3 { + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; + } + 4 { + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; + CREATE INDEX i1 ON t1(b, c); + CREATE INDEX i2 ON t2(b, c); + } +} { + reset_db + + execsql $schema + execsql { + INSERT INTO t1 VALUES(50, 50, 50); + INSERT INTO t1 VALUES(51, 51, 51); + INSERT INTO t2 VALUES(50, 50, 50); + INSERT INTO t2 VALUES(51, 51, 51); + } + + forcedelete rbu.db + do_execsql_test $tn.1 { + ATTACH 'rbu.db' AS rbu; + CREATE TABLE rbu.stuff(tbl, a, b, c, rbu_control); + INSERT INTO stuff VALUES + ('t1', 1, 2, 3, 0), -- insert into t1 + ('t2', 4, 5, 6, 0), -- insert into t2 + ('t1', 50, NULL, NULL, 1), -- delete from t1 + ('t2', 51, NULL, NULL, 1); -- delete from t2 + + CREATE VIEW rbu.data_t1 AS + SELECT a, b, c, rbu_control FROM stuff WHERE tbl='t1'; + CREATE VIEW rbu.data_t2 AS + SELECT a, b, c, rbu_control FROM stuff WHERE tbl='t2'; + } + + do_test $tn.2 { + while 1 { + sqlite3rbu rbu test.db rbu.db + set rc [rbu step] + rbu close + if {$rc != "SQLITE_OK"} break + } + set rc + } {SQLITE_DONE} + + do_execsql_test $tn.3.1 { + SELECT * FROM t1 ORDER BY a; + } {1 2 3 51 51 51} + + do_execsql_test $tn.3.2 { + SELECT * FROM t2 ORDER BY a; + } {4 5 6 50 50 50} + + integrity_check $tn.4 +} + + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 11090d0821..491313ad9a 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -83,7 +83,10 @@ #include #include #include -#include + +#if !defined(_WIN32) +# include +#endif #include "sqlite3.h" @@ -568,7 +571,7 @@ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ rc = prepareAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, "SELECT substr(name, 6) FROM sqlite_master " - "WHERE type='table' AND name LIKE 'data_%'" + "WHERE type IN ('table', 'view') AND name LIKE 'data_%'" ); if( rc==SQLITE_OK ){ @@ -620,8 +623,9 @@ static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ */ static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ va_list ap; + char *zSql; va_start(ap, zFmt); - char *zSql = sqlite3_vmprintf(zFmt, ap); + zSql = sqlite3_vmprintf(zFmt, ap); if( p->rc==SQLITE_OK ){ if( zSql==0 ){ p->rc = SQLITE_NOMEM; @@ -2640,7 +2644,7 @@ static void rbuCreateVfs(sqlite3rbu *p){ assert( p->rc==SQLITE_OK ); sqlite3_randomness(sizeof(int), (void*)&rnd); - sprintf(zRnd, "rbu_vfs_%d", rnd); + sqlite3_snprintf(sizeof(zRnd), zRnd, "rbu_vfs_%d", rnd); p->rc = sqlite3rbu_create_vfs(zRnd, 0); if( p->rc==SQLITE_OK ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); @@ -3525,7 +3529,7 @@ static void (*rbuVfsDlSym( */ static void rbuVfsDlClose(sqlite3_vfs *pVfs, void *pHandle){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; - return pRealVfs->xDlClose(pRealVfs, pHandle); + pRealVfs->xDlClose(pRealVfs, pHandle); } #endif /* SQLITE_OMIT_LOAD_EXTENSION */ diff --git a/ext/rbu/sqlite3rbu.h b/ext/rbu/sqlite3rbu.h index bc1f74fb24..c3e32f9410 100644 --- a/ext/rbu/sqlite3rbu.h +++ b/ext/rbu/sqlite3rbu.h @@ -47,7 +47,7 @@ ** to read from the original database snapshot. In other words, partially ** applied transactions are not visible to other clients. ** -** "RBU" stands for "Over The Air" update. As in a large database update +** "RBU" stands for "Resumable Bulk Update". As in a large database update ** transmitted via a wireless network to a mobile device. A transaction ** applied using this extension is hence refered to as an "RBU update". ** diff --git a/main.mk b/main.mk index a06c22dfb4..e8c1cdd34a 100644 --- a/main.mk +++ b/main.mk @@ -455,11 +455,12 @@ sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB) fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h - $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\ + $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB) fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h - $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\ + $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ + -DSQLITE_ENABLE_MEMSYS5 \ $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB) mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c @@ -738,8 +739,11 @@ queryplantest: testfixture$(EXE) sqlite3$(EXE) fuzztest: fuzzcheck$(EXE) $(FUZZDATA) ./fuzzcheck$(EXE) $(FUZZDATA) +fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) + ./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA) + valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) - valgrind ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA) + valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA) # A very quick test using only testfixture and omitting all the slower # tests. Designed to run in under 3 minutes on a workstation. @@ -750,7 +754,7 @@ quicktest: ./testfixture$(EXE) # The default test case. Runs most of the faster standard TCL tests, # and fuzz tests, and sqlite3_analyzer and sqldiff tests. # -test: $(TESTPROGS) fuzztest +test: $(TESTPROGS) fastfuzztest ./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS) # Run a test using valgrind. This can take a really long time diff --git a/manifest b/manifest index 797c3a0098..f8c7b41f33 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Merge\sall\schanges\sin\sthe\slatest\s3.8.11\sbeta\sinto\sthe\ssessions\sbranch.\nChanges\sinclude\sthe\srename\sof\sOTA\sto\sRBU,\sthe\sWITHOUT-ROWID-OR-Skipscan\sfix,\nand\simprovements\sto\spcache1. -D 2015-07-23T21:59:58.899 +C Merge\stest\simprovements\sand\sminor\sfixes\sfrom\strunk. +D 2015-07-24T22:21:01.450 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in e4e700c7c1764b1e731e2747dc9121e63eb951fc +F Makefile.in bb0577f51dd8eda80a4d14bcf830f9696e31dcce F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc bbb9d41e71f6b32ea5eb12dfec06302f7f6de70a +F Makefile.msc 60f6a05fe6da8ec23596df656b3fa6c2e052cc20 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db @@ -110,9 +110,9 @@ F ext/fts5/fts5Int.h 8d9bce1847a10df2e4ed9492ea4f3868276748fb F ext/fts5/fts5_aux.c 044cb176a815f4388308738437f6e130aa384fb0 F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015 F ext/fts5/fts5_config.c b2456e9625bca41c51d54c363e369c6356895c90 -F ext/fts5/fts5_expr.c ac0614f843cf5c80a85c4c6aa44bbede62a51bb2 +F ext/fts5/fts5_expr.c 56dcbcbdc9029dd76a31360de664559839f4be41 F ext/fts5/fts5_hash.c ff07722c73587c12781213133edbdb22cd156378 -F ext/fts5/fts5_index.c d6ad9293280f39c56343ef5035b0475ff2a6be12 +F ext/fts5/fts5_index.c 892c13a7f44b68e962a91af62f2078f23fabb241 F ext/fts5/fts5_main.c 0de7ba81488d2c502c8e794eaf7983d468e4c6e9 F ext/fts5/fts5_storage.c 1c35a38a564ee9cadcbd7ae0b13a806bdda722bd F ext/fts5/fts5_tcl.c 85eb4e0d0fefa9420b78151496ad4599a1783e20 @@ -200,25 +200,26 @@ 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 e04e7baea76b6dd719a4f290f8a58166efc8d234 w ext/ota/ota.c -F ext/rbu/rbu1.test 57601977588603e82700a43c279bd55282ffa482 w ext/ota/ota1.test -F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d w ext/ota/ota10.test -F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 w ext/ota/ota11.test -F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 w ext/ota/ota12.test -F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2 w ext/ota/ota13.test -F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90 w ext/ota/ota3.test -F ext/rbu/rbu5.test 2e24fee3e615aecd99bbdd46967935a641e866f7 w ext/ota/ota5.test -F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb w ext/ota/ota6.test -F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1 w ext/ota/ota7.test -F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0 w ext/ota/ota8.test -F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af w ext/ota/ota9.test -F ext/rbu/rbuA.test c1a7b3e2d926b8f8448bb3b4ae787e314ee4b2b3 w ext/ota/otaA.test -F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 w ext/ota/otacrash.test -F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 w ext/ota/otafault.test -F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 w ext/ota/otafault2.test -F ext/rbu/sqlite3rbu.c d37e1ca2d13e439cb3df7cd9d98db90458f21433 w ext/ota/sqlite3ota.c -F ext/rbu/sqlite3rbu.h 27dc1bdc18df6c9bfa3bd7d7b011699ed619d6f6 w ext/ota/sqlite3ota.h -F ext/rbu/test_rbu.c f99698956cc9158d6bf865e461e2d15876538ac1 w ext/ota/test_ota.c +F ext/rbu/rbu.c e572f7ddef2ef3a73d03e7b44d36448e466772b7 +F ext/rbu/rbu1.test 57601977588603e82700a43c279bd55282ffa482 +F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d +F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 +F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 +F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2 +F ext/rbu/rbu14.test 01f5dcba904aecadbaea69d4ccdc2ea43dd30560 +F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90 +F ext/rbu/rbu5.test 2e24fee3e615aecd99bbdd46967935a641e866f7 +F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb +F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1 +F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0 +F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af +F ext/rbu/rbuA.test c1a7b3e2d926b8f8448bb3b4ae787e314ee4b2b3 +F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 +F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 +F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 +F ext/rbu/sqlite3rbu.c dbd7e4b31821398dcdeb21492970401ff1027881 +F ext/rbu/sqlite3rbu.h 6a280298e9eeb8ef59841a620f07f4f844651545 +F ext/rbu/test_rbu.c f99698956cc9158d6bf865e461e2d15876538ac1 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e @@ -267,7 +268,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 7e9671e3b41d23a454398e8ab5b1fa5a05bd6df6 +F main.mk 0918e34121c7d5120d34a27653cb4bcd16d532fe F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -301,7 +302,7 @@ F src/delete.c b998fbc3c55e8331a5f40aa7ff80972254de8de1 F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c9b63a217d86582c22121699a47f22f524608869 -F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1 +F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 @@ -310,7 +311,7 @@ F src/insert.c a81d4454051c92d058d79cd77099e700e36a74f6 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712 -F src/loadext.c e722f4b832f923744788365df5fb8515c0bc8a47 +F src/loadext.c dfcee8c7c032cd0fd55af3e0fc1fcfb01e426df2 F src/main.c 6dd8bf94f181925a50a1f494042e50a64d5ecaca F src/malloc.c 19461e159bccf0e2cf06a50e867963d0a7b124a8 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 @@ -348,15 +349,15 @@ F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 57ef3d98c4400b93eea318813be41b2af2da2217 F src/shell.c e4ad9031072a6d679b2c69a780014d30db62dc7f -F src/sqlite.h.in 814992bc580544d632965a5480f8dc76eee331ed +F src/sqlite.h.in 52dce8a4cf52ae3201507a8f0f0c68603fc925fc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad -F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066 -F src/sqliteInt.h cdc9b0c2dc12273c60603eb6c4157dd998603039 +F src/sqlite3ext.h a0b948ebc89bac13941254641326a6aa248c2cc4 +F src/sqliteInt.h d6389d1902f97533210c443f1cc77f83bd4bb73e F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc -F src/test1.c 375d7bd56d9f806095deb91a3dafe61bd0e367c8 +F src/test1.c ab312f4160fdd9c82e65e8b123e35ef17e879c07 F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e @@ -381,7 +382,7 @@ F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5 F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4 -F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112 +F src/test_malloc.c 27d9e11b6e9d30267465d41ad81edbe24256408b F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3 F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c @@ -409,10 +410,10 @@ F src/update.c 24dd6a45b8b3470e62702128ebf11be1f2693145 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 46358a204b35971a839341cf64599d65b151ba88 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 195b32310c7062847a45fda214b32ceb8f8f6ab2 +F src/vdbe.c 8dbffc354f8b8bfb388d56c2e470a589fba0543c F src/vdbe.h d0f8ab919146109d080cde4b0840af9b5fafad4b F src/vdbeInt.h 963c87c4bf8040c0a316ca3e58f8a4888e1fa3c4 -F src/vdbeapi.c 86f01f72f8341c0394ff745e68962b17bfb0974e +F src/vdbeapi.c 7813b9725069c8b32e6da727bcf3e73f321384a4 F src/vdbeaux.c 2d86fc5411e4e659c9181ef642c63dff602b3684 F src/vdbeblob.c ab33f9b57cfce7dddb23853090186da614be4846 F src/vdbemem.c 6c9e261d135fc175da2f34e46d60243a19fffb9f @@ -751,10 +752,10 @@ F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74 F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 -F test/fuzz3.test 0d13010d1c13003a3aa57dda2f69b6b71ccac46e +F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c b973b06b500e6fc052d7059257cdf70df1f3a986 +F test/fuzzcheck.c 79980bbc00e19ad44c3ba6699e643348572757a2 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd @@ -836,13 +837,13 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38 F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5 F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431 F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035 -F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2 +F test/lookaside.test 90052e87282de256d613fcf8c9cbb845e4001d2f F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8 F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a F test/malloc4.test 957337613002b7058a85116493a262f679f3a261 -F test/malloc5.test 4e87e596a28908c034eb5777fc33dd921bb44fc3 +F test/malloc5.test 02ed7c5313f0a68d95f2dfca8c8962132bd1f04b F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d @@ -865,7 +866,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 -F test/memsubsys1.test 1733c617e246642db5bf3b9f78c18e2b14fac96c +F test/memsubsys1.test d2b2d6ca37890b26703a2258df8fd66f9869da02 F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9 F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc @@ -919,11 +920,11 @@ F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b -F test/pcache2.test c70d92547550136ba6f818e6a44fe246d2738604 +F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test dacb0a4094fbf20fc8b5c0e6d40fb5a985836b19 +F test/permutations.test c57b8fa360f3b86385fc03f9b25160b5fdfbcb51 F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2 -F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028 +F test/pragma2.test 8e72df3a16c0fda748ad52abf79cb8256b04a6fe F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 @@ -937,7 +938,7 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df -F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 w test/ota.test +F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 @@ -1048,7 +1049,7 @@ F test/tclsqlite.test 7179b4e0bf236ddf0bfa6bfaefa76fbe0a23c28a F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl d3f3d3e46f0bc852a395fa1d6469b75582708ff7 +F test/tester.tcl b1f0870442ca012effbf8659e34f9be428990696 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1327,7 +1328,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862 F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda -F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d +F test/zeroblob.test c54bc7a95df5fb2d463e00822e1377384954c161 F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/build-all-msvc.bat 9058bd90a3c078a3d8c17d40e853aaa0f47885f4 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 @@ -1385,7 +1386,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 db4cbefb8674c6cfff27c1e918741de1885c845c 017c5019e1ce042025d4f327e50ec50af49f9fa4 -R 9260e9fdfb3bce3b7e0f7ced18f40623 +P 7f0ee77062d2fcb014942c7c62c163ccc801f21b cca79fdc3dff65907c2a59369057265b4512058f +R afa7eed8a3a47b08d78c1d46aa2aac25 U drh -Z 699bda1d1e2b37f0ec4352c1a5a3ac67 +Z d3e71694cf71fedeea79c377e4fa2c08 diff --git a/manifest.uuid b/manifest.uuid index ffc2052adb..6be0992b22 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7f0ee77062d2fcb014942c7c62c163ccc801f21b \ No newline at end of file +0298a9a780695b666e7c683700d9f2f889d6f826 \ No newline at end of file diff --git a/src/func.c b/src/func.c index d0565357d5..6ecd743969 100644 --- a/src/func.c +++ b/src/func.c @@ -1122,16 +1122,14 @@ static void zeroblobFunc( sqlite3_value **argv ){ i64 n; - sqlite3 *db = sqlite3_context_db_handle(context); + int rc; assert( argc==1 ); UNUSED_PARAMETER(argc); n = sqlite3_value_int64(argv[0]); - testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); - if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - }else{ - sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ + if( n<0 ) n = 0; + rc = sqlite3_result_zeroblob64(context, n); /* IMP: R-00293-64994 */ + if( rc ){ + sqlite3_result_error_code(context, rc); } } diff --git a/src/loadext.c b/src/loadext.c index dcdbb28126..1d398c54ce 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -405,7 +405,9 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_strglob, /* Version 3.8.11 and later */ (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, - sqlite3_value_free + sqlite3_value_free, + sqlite3_result_zeroblob64, + sqlite3_bind_zeroblob64 }; /* diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3ddd8ece58..85fe1abaf8 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -3562,6 +3562,7 @@ int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -4534,8 +4535,8 @@ typedef void (*sqlite3_destructor_type)(void*); ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** -** ^The sqlite3_result_zeroblob() interfaces set the result of -** the application-defined function to be a BLOB containing all zero +** ^The sqlite3_result_zeroblob() and zeroblob64() interfaces set the result +** of the application-defined function to be a BLOB containing all zero ** bytes and N bytes in size, where N is the value of the 2nd parameter. ** ** ^The sqlite3_result_double() interface sets the result from @@ -4651,6 +4652,7 @@ void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_value(sqlite3_context*, sqlite3_value*); void sqlite3_result_zeroblob(sqlite3_context*, int n); +int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Define New Collating Sequences diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index b56cc4e54c..48a5bf744b 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -270,6 +270,8 @@ struct sqlite3_api_routines { /* Version 3.8.11 and later */ sqlite3_value *(*value_dup)(const sqlite3_value*); void (*value_free)(sqlite3_value*); + int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); + int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); }; /* @@ -503,6 +505,8 @@ struct sqlite3_api_routines { /* Version 3.8.11 and later */ #define sqlite3_value_dup sqlite3_api->value_dup #define sqlite3_value_free sqlite3_api->value_free +#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 +#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7d99d772fa..aa6b63bffe 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -189,10 +189,14 @@ ** 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 && !defined(_WIN32_WCE) -# include -# pragma intrinsic(_byteswap_ushort) -# pragma intrinsic(_byteswap_ulong) +#if defined(_MSC_VER) && _MSC_VER>=1300 +# if !defined(_WIN32_WCE) +# include +# pragma intrinsic(_byteswap_ushort) +# pragma intrinsic(_byteswap_ulong) +# else +# include +# endif #endif /* diff --git a/src/test1.c b/src/test1.c index 15fd8c7f7d..ceccf10db8 100644 --- a/src/test1.c +++ b/src/test1.c @@ -3008,6 +3008,43 @@ static int test_bind_zeroblob( return TCL_OK; } +/* +** Usage: sqlite3_bind_zeroblob64 STMT IDX N +** +** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement. +** IDX is the index of a wildcard in the prepared statement. This command +** binds a N-byte zero-filled BLOB to the wildcard. +*/ +static int test_bind_zeroblob64( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + i64 n; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; + + rc = sqlite3_bind_zeroblob64(pStmt, idx, n); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); + return TCL_ERROR; + } + + return TCL_OK; +} + /* ** Usage: sqlite3_bind_int STMT N VALUE ** @@ -6796,6 +6833,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, { "sqlite3_bind_int", test_bind_int, 0 }, { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, + { "sqlite3_bind_zeroblob64", test_bind_zeroblob64, 0 }, { "sqlite3_bind_int64", test_bind_int64, 0 }, { "sqlite3_bind_double", test_bind_double, 0 }, { "sqlite3_bind_null", test_bind_null ,0 }, diff --git a/src/test_malloc.c b/src/test_malloc.c index 94a2282923..3ab177dcb7 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -938,8 +938,8 @@ static int test_config_pagecache( int objc, Tcl_Obj *CONST objv[] ){ - int sz, N, rc; - Tcl_Obj *pResult; + int sz, N; + Tcl_Obj *pRes; static char *buf = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); @@ -948,17 +948,20 @@ static int test_config_pagecache( if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; free(buf); + buf = 0; + + /* Set the return value */ + pRes = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage)); + Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage)); + Tcl_SetObjResult(interp, pRes); + if( sz<0 ){ - buf = 0; - rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0); + sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0); }else{ buf = malloc( sz*N ); - rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N); + sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N); } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N)); - Tcl_SetObjResult(interp, pResult); return TCL_OK; } diff --git a/src/vdbe.c b/src/vdbe.c index 0fbe96e425..3a960ccf5c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2712,7 +2712,7 @@ case OP_MakeRecord: { len = sqlite3VdbeSerialTypeLen(serial_type); if( pRec->flags & MEM_Zero ){ if( nData ){ - sqlite3VdbeMemExpandBlob(pRec); + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ nZero += pRec->u.nZero; len -= pRec->u.nZero; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index a35225732a..2c75bbf2ab 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -162,7 +162,10 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - sqlite3VdbeMemExpandBlob(p); + if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ + assert( p->flags==MEM_Null && p->z==0 ); + return 0; + } p->flags |= MEM_Blob; return p->n ? p->z : 0; }else{ @@ -424,6 +427,15 @@ void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } +int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ + Mem *pOut = pCtx->pOut; + assert( sqlite3_mutex_held(pOut->db->mutex) ); + if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ + return SQLITE_TOOBIG; + } + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); + return SQLITE_OK; +} void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; @@ -1403,6 +1415,20 @@ int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ } return rc; } +int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ + rc = SQLITE_TOOBIG; + }else{ + assert( (n & 0x7FFFFFFF)==n ); + rc = sqlite3_bind_zeroblob(pStmt, i, n); + } + rc = sqlite3ApiExit(p->db, rc); + sqlite3_mutex_leave(p->db->mutex); + return rc; +} /* ** Return the number of wildcards that can be potentially bound to. diff --git a/test/fuzz3.test b/test/fuzz3.test index e54b811142..b432671822 100644 --- a/test/fuzz3.test +++ b/test/fuzz3.test @@ -21,12 +21,7 @@ source $testdir/tester.tcl # These tests deal with corrupt database files # database_may_be_corrupt -db close -sqlite3_shutdown -sqlite3_config_pagecache 0 0 -sqlite3_initialize -autoinstall_test_functions -sqlite3 db test.db +test_set_config_pagecache 0 0 expr srand(123) @@ -176,4 +171,6 @@ for {set ii 0} {$ii < 5000} {incr ii} { } $::cksum } +test_restore_config_pagecache finish_test + diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index d17a9a1289..c678e2af7a 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -682,6 +682,64 @@ static void rebuild_database(sqlite3 *db){ if( rc ) fatalError("cannot rebuild: %s", sqlite3_errmsg(db)); } +/* +** Return the value of a hexadecimal digit. Return -1 if the input +** is not a hex digit. +*/ +static int hexDigitValue(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; +} + +/* +** Interpret zArg as an integer value, possibly with suffixes. +*/ +static int integerValue(const char *zArg){ + sqlite3_int64 v = 0; + static const struct { char *zSuffix; int iMult; } aMult[] = { + { "KiB", 1024 }, + { "MiB", 1024*1024 }, + { "GiB", 1024*1024*1024 }, + { "KB", 1000 }, + { "MB", 1000000 }, + { "GB", 1000000000 }, + { "K", 1000 }, + { "M", 1000000 }, + { "G", 1000000000 }, + }; + int i; + int isNeg = 0; + if( zArg[0]=='-' ){ + isNeg = 1; + zArg++; + }else if( zArg[0]=='+' ){ + zArg++; + } + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( isdigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } + } + for(i=0; i0x7fffffff ) fatalError("parameter too large - max 2147483648"); + return (int)(isNeg? -v : v); +} + /* ** Print sketchy documentation for this utility program */ @@ -696,6 +754,7 @@ static void showHelp(void){ " --help Show this help text\n" " -q Reduced output\n" " --quiet Reduced output\n" +" --limit-mem N Limit memory used by test SQLite instance to N bytes\n" " --limit-vdbe Panic if an sync SQL runs for more than 100,000 cycles\n" " --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" " --load-db ARGS... Load template databases from files into SOURCE_DB\n" @@ -739,6 +798,7 @@ int main(int argc, char **argv){ int cellSzCkFlag = 0; /* --cell-size-check */ int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ int iTimeout = 120; /* Default 120-second timeout */ + int nMem = 0; /* Memory limit */ iBegin = timeOfDay(); #ifdef __unix__ @@ -756,12 +816,16 @@ int main(int argc, char **argv){ }else if( strcmp(z,"dbid")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - onlyDbid = atoi(argv[++i]); + onlyDbid = integerValue(argv[++i]); }else if( strcmp(z,"help")==0 ){ showHelp(); return 0; }else + if( strcmp(z,"limit-mem")==0 ){ + if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); + nMem = integerValue(argv[++i]); + }else if( strcmp(z,"limit-vdbe")==0 ){ vdbeLimitFlag = 1; }else @@ -794,11 +858,11 @@ int main(int argc, char **argv){ }else if( strcmp(z,"sqlid")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - onlySqlid = atoi(argv[++i]); + onlySqlid = integerValue(argv[++i]); }else if( strcmp(z,"timeout")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - iTimeout = atoi(argv[++i]); + iTimeout = integerValue(argv[++i]); }else if( strcmp(z,"timeout-test")==0 ){ timeoutTest = 1; @@ -928,6 +992,17 @@ int main(int argc, char **argv){ if( sqlite3_memory_used()>0 ){ fatalError("SQLite has memory in use before the start of testing"); } + + /* Limit available memory, if requested */ + if( nMem>0 ){ + void *pHeap; + sqlite3_shutdown(); + pHeap = malloc(nMem); + if( pHeap==0 ){ + fatalError("failed to allocate %d bytes of heap memory", nMem); + } + sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMem, 128); + } /* Register the in-memory virtual filesystem */ diff --git a/test/lookaside.test b/test/lookaside.test index 0b239a04d5..a89110ee1d 100644 --- a/test/lookaside.test +++ b/test/lookaside.test @@ -29,9 +29,10 @@ if {[info exists ::G(perm:presql)]} { return } +test_set_config_pagecache 0 0 + catch {db close} sqlite3_shutdown -sqlite3_config_pagecache 0 0 sqlite3_config_scratch 0 0 sqlite3_initialize autoinstall_test_functions @@ -129,4 +130,5 @@ do_test lookaside-4.1 { sqlite3_initialize autoinstall_test_functions +test_restore_config_pagecache finish_test diff --git a/test/malloc5.test b/test/malloc5.test index 3f5208accd..8f0db04c2a 100644 --- a/test/malloc5.test +++ b/test/malloc5.test @@ -20,11 +20,6 @@ # # $Id: malloc5.test,v 1.22 2009/04/11 19:09:54 drh Exp $ -sqlite3_shutdown -sqlite3_config_pagecache 0 100 -sqlite3_initialize -autoinstall_test_functions - set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl @@ -44,6 +39,8 @@ ifcapable !memorymanage { return } +test_set_config_pagecache 0 100 + sqlite3_soft_heap_limit 0 sqlite3 db test.db db eval {PRAGMA cache_size=1} @@ -415,5 +412,6 @@ do_test malloc5-6.3.6 { db2 close sqlite3_soft_heap_limit $::soft_limit +test_restore_config_pagecache finish_test catch {db close} diff --git a/test/memsubsys1.test b/test/memsubsys1.test index 3eb3cd4a95..8265ce6317 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -25,6 +25,8 @@ if {[permutation] == "memsubsys1"} { return } +test_set_config_pagecache 0 0 + # This procedure constructs a new database in test.db. It fills # this database with many small records (enough to force multiple # rebalance operations in the btree-layer and to require a large @@ -310,10 +312,11 @@ do_test memsubsys1-8.4 { db close sqlite3_shutdown sqlite3_config_memstatus 1 -sqlite3_config_pagecache 0 0 sqlite3_config_scratch 0 0 sqlite3_config_lookaside 100 500 sqlite3_config serialized sqlite3_initialize autoinstall_test_functions + +test_restore_config_pagecache finish_test diff --git a/test/pcache2.test b/test/pcache2.test index c59dfb25d4..a0d7496c86 100644 --- a/test/pcache2.test +++ b/test/pcache2.test @@ -16,6 +16,8 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +test_set_config_pagecache 0 0 + # Set up a pcache memory pool so that we can easily track how many # pages are being used for cache. # @@ -78,4 +80,5 @@ sqlite3_config serialized sqlite3_initialize autoinstall_test_functions +test_restore_config_pagecache finish_test diff --git a/test/permutations.test b/test/permutations.test index 747b663d39..b15f6d552e 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -421,16 +421,16 @@ test_suite "memsubsys1" -description { } -files [ test_set $::allquicktests -exclude ioerr5.test malloc5.test mmap1.test ] -initialize { + test_set_config_pagecache 4096 24 catch {db close} sqlite3_shutdown - sqlite3_config_pagecache 4096 24 sqlite3_config_scratch 25000 1 sqlite3_initialize autoinstall_test_functions } -shutdown { + test_restore_config_pagecache catch {db close} sqlite3_shutdown - sqlite3_config_pagecache 0 0 sqlite3_config_scratch 0 0 sqlite3_initialize autoinstall_test_functions @@ -448,16 +448,16 @@ test_suite "memsubsys2" -description { } -files [ test_set $::allquicktests -exclude ioerr5.test malloc5.test ] -initialize { + test_set_config_pagecache 512 5 catch {db close} sqlite3_shutdown - sqlite3_config_pagecache 512 5 sqlite3_config_scratch 1000 1 sqlite3_initialize autoinstall_test_functions } -shutdown { + test_restore_config_pagecache catch {db close} sqlite3_shutdown - sqlite3_config_pagecache 0 0 sqlite3_config_scratch 0 0 sqlite3_initialize autoinstall_test_functions diff --git a/test/pragma2.test b/test/pragma2.test index 3ade8c1a07..12d5cce5f7 100644 --- a/test/pragma2.test +++ b/test/pragma2.test @@ -30,6 +30,8 @@ ifcapable !pragma||!schema_pragmas { return } +test_set_config_pagecache 0 0 + # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # @@ -208,5 +210,5 @@ do_execsql_test pragma2-4.8 { PRAGMA lock_status; } {main unlocked temp unknown aux1 exclusive} - +test_restore_config_pagecache finish_test diff --git a/test/tester.tcl b/test/tester.tcl index ed8d5c712e..4f6c1d9b73 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -2047,6 +2047,45 @@ proc db_delete_and_reopen {{file test.db}} { sqlite3 db $file } +# Close any connections named [db], [db2] or [db3]. Then use sqlite3_config +# to configure the size of the PAGECACHE allocation using the parameters +# provided to this command. Save the old PAGECACHE parameters in a global +# variable so that [test_restore_config_pagecache] can restore the previous +# configuration. +# +# Before returning, reopen connection [db] on file test.db. +# +proc test_set_config_pagecache {sz nPg} { + catch {db close} + catch {db2 close} + catch {db3 close} + + sqlite3_shutdown + set ::old_pagecache_config [sqlite3_config_pagecache $sz $nPg] + sqlite3_initialize + autoinstall_test_functions + reset_db +} + +# Close any connections named [db], [db2] or [db3]. Then use sqlite3_config +# to configure the size of the PAGECACHE allocation to the size saved in +# the global variable by an earlier call to [test_set_config_pagecache]. +# +# Before returning, reopen connection [db] on file test.db. +# +proc test_restore_config_pagecache {} { + catch {db close} + catch {db2 close} + catch {db3 close} + + sqlite3_shutdown + eval sqlite3_config_pagecache $::old_pagecache_config + unset ::old_pagecache_config + sqlite3_initialize + autoinstall_test_functions + sqlite3 db test.db +} + # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) diff --git a/test/zeroblob.test b/test/zeroblob.test index e70fd0b748..c45be2b09c 100644 --- a/test/zeroblob.test +++ b/test/zeroblob.test @@ -17,12 +17,15 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix zeroblob ifcapable !incrblob { finish_test return } +test_set_config_pagecache 0 0 + # When zeroblob() is used for the last field of a column, then the # content of the zeroblob is never instantiated on the VDBE stack. # But it does get inserted into the database correctly. @@ -41,8 +44,9 @@ do_test zeroblob-1.1 { } set ::sqlite3_max_blobsize } {10} + do_test zeroblob-1.1.1 { - expr {[sqlite3_memory_highwater]<$::memused+25000} + expr {[sqlite3_memory_highwater]<$::memused+35000} } {1} do_test zeroblob-1.2 { execsql { @@ -264,5 +268,53 @@ do_test zeroblob-10.1 { catchsql {INSERT INTO t10 VALUES(zeroblob(1e9),zeroblob(1e9),zeroblob(1e9))} } {1 {string or blob too big}} +#------------------------------------------------------------------------- +# Test the zeroblob() function on its own with negative or oversized +# arguments. +# +do_execsql_test 11.0 { + SELECT length(zeroblob(-1444444444444444)); +} {0} +do_catchsql_test 11.1 { + SELECT zeroblob(1025 * 1024 * 1024); +} {1 {string or blob too big}} +do_catchsql_test 11.2 { + SELECT quote(zeroblob(1025 * 1024 * 1024)); +} {1 {string or blob too big}} +do_catchsql_test 11.3 { + SELECT quote(zeroblob(-1444444444444444)); +} {0 X''} +do_catchsql_test 11.4 { + SELECT quote(test_zeroblob(-1)); +} {0 X''} +#------------------------------------------------------------------------- +# Test the sqlite3_bind_zeroblob64() API. +# +proc bind_and_run {stmt nZero} { + sqlite3_bind_zeroblob64 $stmt 1 $nZero + sqlite3_step $stmt + set ret [sqlite3_column_int $stmt 0] + sqlite3_reset $stmt + set ret +} +set stmt [sqlite3_prepare db "SELECT length(?)" -1 dummy] + +do_test 12.1 { bind_and_run $stmt 40 } 40 +do_test 12.2 { bind_and_run $stmt 0 } 0 +do_test 12.3 { bind_and_run $stmt 1000 } 1000 + +do_test 12.4 { + list [catch { bind_and_run $stmt [expr 1500 * 1024 * 1024] } msg] $msg +} {1 SQLITE_TOOBIG} +do_test 12.5 { + sqlite3_step $stmt + set ret [sqlite3_column_int $stmt 0] + sqlite3_reset $stmt + set ret +} {1000} + +sqlite3_finalize $stmt + +test_restore_config_pagecache finish_test