diff --git a/Makefile.in b/Makefile.in index 043c5717a7..a1e2737f95 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1078,7 +1078,7 @@ fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) - valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA) + valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) # Minimal testing that runs in less than 3 minutes # diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 8626962067..83a71723ff 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -160,6 +160,7 @@ struct Fts5Config { int pgsz; /* Approximate page size used in %_data */ int nAutomerge; /* 'automerge' setting */ int nCrisisMerge; /* Maximum allowed segments per level */ + int nHashSize; /* Bytes of memory for in-memory hash */ char *zRank; /* Name of rank function */ char *zRankArgs; /* Arguments to rank function */ diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index 2d8f7ac1a7..4f6272dbe2 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -20,6 +20,7 @@ #define FTS5_DEFAULT_PAGE_SIZE 4050 #define FTS5_DEFAULT_AUTOMERGE 4 #define FTS5_DEFAULT_CRISISMERGE 16 +#define FTS5_DEFAULT_HASHSIZE (1024*1024) /* Maximum allowed page size */ #define FTS5_MAX_PAGE_SIZE (128*1024) @@ -706,33 +707,37 @@ int sqlite3Fts5ConfigParseRank( *pzRank = 0; *pzRankArgs = 0; - p = fts5ConfigSkipWhitespace(p); - pRank = p; - p = fts5ConfigSkipBareword(p); - - if( p ){ - zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank); - if( zRank ) memcpy(zRank, pRank, p-pRank); - }else{ + if( p==0 ){ rc = SQLITE_ERROR; - } + }else{ + p = fts5ConfigSkipWhitespace(p); + pRank = p; + p = fts5ConfigSkipBareword(p); - if( rc==SQLITE_OK ){ - p = fts5ConfigSkipWhitespace(p); - if( *p!='(' ) rc = SQLITE_ERROR; - p++; - } - if( rc==SQLITE_OK ){ - const char *pArgs; - p = fts5ConfigSkipWhitespace(p); - pArgs = p; - if( *p!=')' ){ - p = fts5ConfigSkipArgs(p); - if( p==0 ){ - rc = SQLITE_ERROR; - }else{ - zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs); - if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs); + if( p ){ + zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank); + if( zRank ) memcpy(zRank, pRank, p-pRank); + }else{ + rc = SQLITE_ERROR; + } + + if( rc==SQLITE_OK ){ + p = fts5ConfigSkipWhitespace(p); + if( *p!='(' ) rc = SQLITE_ERROR; + p++; + } + if( rc==SQLITE_OK ){ + const char *pArgs; + p = fts5ConfigSkipWhitespace(p); + pArgs = p; + if( *p!=')' ){ + p = fts5ConfigSkipArgs(p); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs); + if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs); + } } } } @@ -767,6 +772,18 @@ int sqlite3Fts5ConfigSetValue( } } + else if( 0==sqlite3_stricmp(zKey, "hashsize") ){ + int nHashSize = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nHashSize = sqlite3_value_int(pVal); + } + if( nHashSize<=0 ){ + *pbBadkey = 1; + }else{ + pConfig->nHashSize = nHashSize; + } + } + else if( 0==sqlite3_stricmp(zKey, "automerge") ){ int nAutomerge = -1; if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ @@ -827,6 +844,7 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE; pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE; pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; + pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE; zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName); if( zSql ){ diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index b3f4372965..b7374f9805 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -288,7 +288,6 @@ struct Fts5Index { ** in-memory hash tables before they are flushed to disk. */ Fts5Hash *pHash; /* Hash table for in-memory data */ - int nMaxPendingData; /* Max pending data before flush to disk */ int nPendingData; /* Current bytes of pending data */ i64 iWriteRowid; /* Rowid for current doc being written */ int bDelete; /* Current write is a delete */ @@ -4453,7 +4452,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){ /* Flush the hash table to disk if required */ if( iRowidiWriteRowid || (iRowid==p->iWriteRowid && p->bDelete==0) - || (p->nPendingData > p->nMaxPendingData) + || (p->nPendingData > p->pConfig->nHashSize) ){ fts5IndexFlush(p); } @@ -4519,7 +4518,6 @@ int sqlite3Fts5IndexOpen( if( rc==SQLITE_OK ){ p->pConfig = pConfig; p->nWorkUnit = FTS5_WORK_UNIT; - p->nMaxPendingData = 1024*1024; p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName); if( p->zDataTbl && bCreate ){ rc = sqlite3Fts5CreateTable( diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index bd004cf824..9390cb6cb2 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -395,6 +395,15 @@ static int fts5InitVtab( rc = sqlite3Fts5ConfigDeclareVtab(pConfig); } + /* Load the initial configuration */ + if( rc==SQLITE_OK ){ + assert( pConfig->pzErrmsg==0 ); + pConfig->pzErrmsg = pzErr; + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + sqlite3Fts5IndexRollback(pTab->pIndex); + pConfig->pzErrmsg = 0; + } + if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; @@ -829,13 +838,42 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ return rc; } + +static sqlite3_stmt *fts5PrepareStatement( + int *pRc, + Fts5Config *pConfig, + const char *zFmt, + ... +){ + sqlite3_stmt *pRet = 0; + va_list ap; + va_start(ap, zFmt); + + if( *pRc==SQLITE_OK ){ + int rc; + char *zSql = sqlite3_vmprintf(zFmt, ap); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0); + if( rc!=SQLITE_OK ){ + *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db)); + } + sqlite3_free(zSql); + } + *pRc = rc; + } + + va_end(ap); + return pRet; +} + static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ Fts5Config *pConfig = pTab->pConfig; Fts5Sorter *pSorter; int nPhrase; int nByte; int rc = SQLITE_OK; - char *zSql; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; @@ -853,17 +891,13 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ ** table, saving it creates a circular reference. ** ** If SQLite a built-in statement cache, this wouldn't be a problem. */ - zSql = sqlite3Fts5Mprintf(&rc, + pSorter->pStmt = fts5PrepareStatement(&rc, pConfig, "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), bDesc ? "DESC" : "ASC" ); - if( zSql ){ - rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pSorter->pStmt, 0); - sqlite3_free(zSql); - } pCsr->pSorter = pSorter; if( rc==SQLITE_OK ){ diff --git a/ext/fts5/test/fts5fault1.test b/ext/fts5/test/fts5fault1.test index 13f36803e1..429ea39af0 100644 --- a/ext/fts5/test/fts5fault1.test +++ b/ext/fts5/test/fts5fault1.test @@ -52,7 +52,7 @@ do_faultsim_test 2 -prep { INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} } reset_db @@ -66,7 +66,7 @@ do_faultsim_test 3 -prep { } -body { execsql { DELETE FROM t1 } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} } reset_db @@ -101,7 +101,7 @@ foreach {tn expr res} { } -body " execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' } " -test " - faultsim_test_result {[list 0 $res]} + faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}} " } diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index a392b238ee..989a372d49 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -107,7 +107,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}] do_faultsim_test 4 -faults oom-* -body { db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'} } -test { - faultsim_test_result {0 {0 {} 3}} + faultsim_test_result {0 {0 {} 4}} } #------------------------------------------------------------------------- diff --git a/ext/fts5/test/fts5rank.test b/ext/fts5/test/fts5rank.test index 2182ab3097..4961b42605 100644 --- a/ext/fts5/test/fts5rank.test +++ b/ext/fts5/test/fts5rank.test @@ -41,5 +41,60 @@ do_execsql_test 1.3 { WHERE xyz MATCH 'x AND y' ORDER BY rank } [list [string map {x [x] y [y]} $doc]] +#------------------------------------------------------------------------- +# Check that the 'rank' option really is persistent. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(a); + INSERT INTO tt VALUES('a x x x x'); + INSERT INTO tt VALUES('x x a a a'); + INSERT INTO tt VALUES('x a a x x'); +} + +proc firstinst {cmd} { + foreach {p c o} [$cmd xInst 0] {} + return $o +} +sqlite3_fts5_create_function db firstinst firstinst + +do_execsql_test 2.1 { + SELECT rowid FROM tt('a') ORDER BY rank; +} {2 3 1} + +do_execsql_test 2.2 { + SELECT rowid FROM tt('a', 'firstinst()') ORDER BY rank; +} {1 3 2} + +do_execsql_test 2.3 { + INSERT INTO tt(tt, rank) VALUES('rank', 'firstinst()'); + SELECT rowid FROM tt('a') ORDER BY rank; +} {1 3 2} + +do_test 2.4 { + sqlite3 db2 test.db + catchsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 {no such function: firstinst}} + +do_test 2.5 { + db2 close + sqlite3 db2 test.db + sqlite3_fts5_create_function db2 firstinst firstinst + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.6 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.7 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db +} {1 3 2} + + + + + + + finish_test diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 952464fc54..27a1aee08b 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -18,7 +18,7 @@ ifcapable !fts5 { finish_test return } - + #------------------------------------------------------------------------- # set doc "x x [string repeat {y } 50]z z" @@ -322,5 +322,34 @@ do_execsql_test 13.3 { INSERT INTO xy(xy) VALUES('integrity-check'); } +#------------------------------------------------------------------------- +# +do_execsql_test 14.1 { + CREATE VIRTUAL TABLE ttt USING fts5(x); + BEGIN; + INSERT INTO ttt(rowid, x) VALUES(1, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(2, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(3, 'a b c'); + COMMIT; +} +do_test 14.2 { + fts5_level_segs ttt +} {1} + +#------------------------------------------------------------------------- +db func rnddoc fts5_rnddoc +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + + WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 ) + INSERT INTO x1 SELECT rnddoc(5) FROM ii; +} + +do_execsql_test 4.1 { + SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads' +} {0 {} 4} + + finish_test diff --git a/ext/fts5/tool/loadfts5.tcl b/ext/fts5/tool/loadfts5.tcl index 4bf89d7817..4a5aa37250 100644 --- a/ext/fts5/tool/loadfts5.tcl +++ b/ext/fts5/tool/loadfts5.tcl @@ -48,6 +48,7 @@ proc usage {} { puts stderr " -crisismerge N (set the crisismerge parameter to N)" puts stderr " -prefix PREFIX (comma separated prefix= argument)" puts stderr " -trans N (commit after N inserts - 0 == never)" + puts stderr " -hashsize N (set the fts5 hashsize parameter to N)" exit 1 } @@ -59,6 +60,7 @@ set O(automerge) -1 set O(crisismerge) -1 set O(prefix) "" set O(trans) 0 +set O(hashsize) -1 if {[llength $argv]<2} usage set nOpt [expr {[llength $argv]-2}] @@ -106,6 +108,11 @@ for {set i 0} {$i < $nOpt} {incr i} { set O(prefix) [lindex $argv $i] } + -hashsize { + if { [incr i]>=$nOpt } usage + set O(hashsize) [lindex $argv $i] + } + default { usage } @@ -126,6 +133,14 @@ db eval BEGIN db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)" db eval "INSERT INTO t1(t1, rank) VALUES('pgsz', 4050);" } + + if {$O(hashsize)>=0} { + catch { + db eval "INSERT INTO t1(t1, rank) VALUES('hashsize', $O(hashsize));" + } + } + + if {$O(automerge)>=0} { if {$O(vtab) == "fts5"} { db eval { INSERT INTO t1(t1, rank) VALUES('automerge', $O(automerge)) } @@ -141,6 +156,7 @@ db eval BEGIN } load_hierachy [lindex $argv end] db eval COMMIT +puts "" diff --git a/ext/misc/ieee754.c b/ext/misc/ieee754.c index f143893885..20c5e61433 100644 --- a/ext/misc/ieee754.c +++ b/ext/misc/ieee754.c @@ -94,16 +94,16 @@ static void ieee754func( m >>= 1; e++; } - while( ((m>>32)&0xfff00000)==0 ){ + while( m!=0 && ((m>>32)&0xfff00000)==0 ){ m <<= 1; e--; } e += 1075; if( e<0 ) e = m = 0; - if( e>0x7ff ) m = 0; + if( e>0x7ff ) e = 0x7ff; a = m & ((((sqlite3_int64)1)<<52)-1); a |= e<<52; - if( isNeg ) a |= ((sqlite3_int64)1)<<63; + if( isNeg ) a |= ((sqlite3_uint64)1)<<63; memcpy(&r, &a, sizeof(r)); sqlite3_result_double(context, r); } diff --git a/main.mk b/main.mk index 91e8ccd1ae..dd74aecf77 100644 --- a/main.mk +++ b/main.mk @@ -768,7 +768,7 @@ fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) ./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) - valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA) + valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) # A very quick test using only testfixture and omitting all the slower # tests. Designed to run in under 3 minutes on a workstation. diff --git a/manifest b/manifest index 2d04d10a23..701f0d01fc 100644 --- a/manifest +++ b/manifest @@ -1,6 +1,6 @@ -C Merge\sall\srecent\senhancements\sand\sfixes\sfrom\strunk. -D 2015-11-02T18:57:26.691 -F Makefile.in 3229179cfbc7d1378aba248dcbdf5213fff6214a +C Merge\srecent\senhancements\sand\sbug\sfixes\sfrom\strunk. +D 2015-11-07T01:33:30.741 +F Makefile.in 7037017983949da7c736ca3de2c3d29611b77d1c F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 2ed14817d36a6c26cb146e53b9c8a7318ba5bdd4 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 @@ -103,14 +103,14 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9 -F ext/fts5/fts5Int.h 06594fd3e5a3c74da6df9141e165975dc0ea6ef4 +F ext/fts5/fts5Int.h acf968e43d57b6b1caf7554d34ec35d6ed3b4fe8 F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35 F ext/fts5/fts5_buffer.c 1e49512a535045e621246dc7f4f65f3593fa0fc2 -F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685 +F ext/fts5/fts5_config.c 6fc92c0b1bda5244c28a54c9ba740736bd5513d9 F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900 F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f -F ext/fts5/fts5_index.c 356481ce027cc2ede8e462c316b578260cda29d2 -F ext/fts5/fts5_main.c 39358d3d8f0d6ea3757c40e0ddcbb6bc435604c3 +F ext/fts5/fts5_index.c b622a0a70f57a96469e6828da2dd70e0872aeb37 +F ext/fts5/fts5_main.c 7581280ee242785477df67402f2853c66f77d45b F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf @@ -149,10 +149,10 @@ F ext/fts5/test/fts5dlidx.test ecba5e62ea8b26c33829961602069c546228046d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 F ext/fts5/test/fts5eb.test 3e5869af2008cbc4ad03a175a0b6f6e58134cd43 -F ext/fts5/test/fts5fault1.test 7a562367cb4a735b57b410dbdb62dcc8d971faec +F ext/fts5/test/fts5fault1.test 4b39c47ca3544615daa8a2f733b911fa08022c77 F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 -F ext/fts5/test/fts5fault4.test 762991d526ee67c2b374351a17248097ea38bee7 +F ext/fts5/test/fts5fault4.test 4864f2b5c2c083440dbe85aff60897bc1aa04603 F ext/fts5/test/fts5fault5.test f2b8645053d48982e8979749e93994c43011c118 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b @@ -170,11 +170,11 @@ F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1 F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487 F ext/fts5/test/fts5prefix.test 7ccbdf180ed561a912acef520519e85af8642239 F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40 -F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1 +F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821 -F ext/fts5/test/fts5simple.test 41333e267c6145efc3620342af53dfe65d5676b7 +F ext/fts5/test/fts5simple.test 9bded45827b4ab8933c87b7b3bcc3cd47f7378a4 F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671 F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89 F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841 @@ -184,7 +184,7 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5vocab.test c88a5554d0409494da95ba647bbdb4879b2624b0 F ext/fts5/tool/fts5txt2db.tcl c374c4c4797e8cdfadabdfaeeb5412dcd6686e84 -F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3 +F ext/fts5/tool/loadfts5.tcl 4cc2d6af43b58d4fac05bc4fdabd0e5862c3b2c1 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 @@ -196,7 +196,7 @@ F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83 F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 -F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e +F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 4f45afd9dbcd6feca8c528251efbb7fc09299a09 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 @@ -283,7 +283,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk ace127ebc8f73fbe37ecf9021385f9efdc4d595d +F main.mk 2e67604b0dbd7670230ed626b6a2947f05a35ba5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -299,18 +299,18 @@ F src/alter.c 9d649e46c780166e416fb11dbd23f8d49aab8267 F src/analyze.c 4c308880cf53c558070cb8513bdff4ffb1a38a77 F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 -F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c +F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 77343aac89c50bb5e06cbca3ace8c057c14de57c -F src/btree.h b512723e4f27d7ba16b4b985cdecdb82c0f6d0c0 -F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 +F src/btree.c 9e5d713bf54be8bfcae9b60210173dd53570f56d +F src/btree.h 1b8bf2818b5e256c25a5e09126720113b1d783da +F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38 F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 -F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7 +F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 F src/delete.c 9dddc4434aace0f42f1ed1c5224cdcfc2328ed67 F src/expr.c 0080c0f12806eca91e75a23a121a68918e9da357 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb @@ -347,8 +347,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c cf72e06e15839ebe7121e01d3eebf256c039b0ca F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 9c1eec0d88133484b165fa0b5284a411c24b964c -F src/pager.h 1c4fa826c330040c5659a384446c7cc6e8e4200c +F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e +F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 F src/parse.y 11078cd8e3af00f030505b6a86a06a4536cfdeaa F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 @@ -365,13 +365,13 @@ F src/shell.c 993863f82d764be0c00803056e56b9b744f86f02 F src/sqlite.h.in 45821b35edf55ac410c16a3e1de4d6d43aa7ee16 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 -F src/sqliteInt.h b2e72eaa886665d042908a736d98fadacab95ef6 +F src/sqliteInt.h a02b33a3b68913394c218ec27f24b8fa33518244 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc -F src/test1.c 9ac5cbfe3c859ab7518edc5109a2959d6bf7b059 -F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d +F src/test1.c a719afff3144f7f01c6dc3f7d118ac31d15e7527 +F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1 @@ -423,11 +423,11 @@ F src/update.c c2fff3b60bfcabcb0372acbe8cf6f77c2bb515bc F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 755ebcef6b85f4917b567401752aa39523cd06e5 +F src/vdbe.c 9539aa0ccf4844b8b59466ef3c15dbffb479a390 F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77 F src/vdbeInt.h d6ae6e64ad16e213f37306b1735ff72fb98bec69 F src/vdbeapi.c f5eda36a5c85ef578957ab4311e8d9b1f51a3552 -F src/vdbeaux.c 3c67cbdee0308a0e0a942e5edea95339e021ea5c +F src/vdbeaux.c 1c5969fa8b04e162a2e893ebb283071bec81a006 F src/vdbeblob.c b400c25ac822af3c507ef84b5cd93c1583a70321 F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0 F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68 @@ -473,7 +473,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 -F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7 +F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58 F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27 @@ -500,7 +500,7 @@ F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135 F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f -F test/bc_common.tcl 5c8689cc6d2fb44b7c0968ae4f85eb26d50022fa +F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191 F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -539,7 +539,7 @@ F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846 F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5 -F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177 +F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907 F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868 @@ -621,7 +621,7 @@ F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763 F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10 F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528 -F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585 +F test/e_uri.test eed3eb41b22d051a1164110dacdc778899126e14 F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567 @@ -785,6 +785,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67 F test/hook.test aa41c095d26822b8a51aa4c82904a14347961be6 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 +F test/ieee754.test 118b665a97a8df0e8f2fbdb07d113e596f4a6b53 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 @@ -922,6 +923,7 @@ F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 +F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823 F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6 @@ -948,7 +950,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test c57b8fa360f3b86385fc03f9b25160b5fdfbcb51 +F test/permutations.test 63cb93f915b4056463cef8ad035082e9f1cb524e F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772 F test/pragma2.test b5e2ce4c892afceb308c6ae6163a9099b2a0d8d7 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c @@ -968,7 +970,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 67a82199e6ddee609211488bc04ed3f9ea3aa28a +F test/releasetest.tcl 2d000ceded3115758be96abb9c10a5669fb27862 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14 @@ -1322,10 +1324,10 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e -F test/where.test 66d4c107e82dfe86c01a96277b77e7a8809aff0b +F test/where.test 9902a3d84e9bc80357a2c54ed0e76c0d6d04a867 F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23 F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e -F test/where4.test 44f506bf1737cf0fa4fc795e340208250f1fcd89 +F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8 @@ -1419,7 +1421,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 395a153ff7b3c7a72f3d02b6fe76d72383f4e480 6d5ce3ede4c7038c19a77268a5a7b9d5650933c2 -R 108cce56953c38f03dac9fc0349473c4 +P 0546d1cd1a3402890edade7970c269cc3f17bc98 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1 +R 65016c2c463ac04ecdb2d993caf6bb9d U drh -Z a9e0c02c1ba22a50e60adc1f82d63108 +Z 6ef4d8405632dbe4f4eb27a0771bc5f1 diff --git a/manifest.uuid b/manifest.uuid index 1c809979a9..5e3b708e1b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0546d1cd1a3402890edade7970c269cc3f17bc98 \ No newline at end of file +78bc42e664e9fa9ee21ad9762c369f291fcdf5db \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index 69e3c52822..1c282242d7 100644 --- a/src/backup.c +++ b/src/backup.c @@ -293,7 +293,7 @@ static int backupOnePage( DbPage *pDestPg = 0; Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; - if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg)) + if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0)) && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) ){ const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; @@ -419,8 +419,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ - rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg, - PAGER_GET_READONLY); + rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); if( rc==SQLITE_OK ){ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); sqlite3PagerUnref(pSrcPg); @@ -520,7 +519,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ DbPage *pPg; - rc = sqlite3PagerGet(pDestPager, iPg, &pPg); + rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg); sqlite3PagerUnref(pPg); @@ -540,7 +539,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ ){ PgHdr *pSrcPg = 0; const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); - rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); + rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0); if( rc==SQLITE_OK ){ u8 *zData = sqlite3PagerGetData(pSrcPg); rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); diff --git a/src/btree.c b/src/btree.c index 8d183efb31..a61a6edf2f 100644 --- a/src/btree.c +++ b/src/btree.c @@ -931,7 +931,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ return; } iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); if( rc!=SQLITE_OK ){ *pRC = rc; return; @@ -974,7 +974,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ assert( sqlite3_mutex_held(pBt->mutex) ); iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); if( rc!=0 ){ return rc; } @@ -1901,11 +1901,14 @@ static void zeroPage(MemPage *pPage, int flags){ */ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){ MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - pPage->aData = sqlite3PagerGetData(pDbPage); - pPage->pDbPage = pDbPage; - pPage->pBt = pBt; - pPage->pgno = pgno; - pPage->hdrOffset = pgno==1 ? 100 : 0; + if( pgno!=pPage->pgno ){ + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pgno==1 ? 100 : 0; + } + assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); return pPage; } @@ -1931,7 +1934,7 @@ static int btreeGetPage( assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY ); assert( sqlite3_mutex_held(pBt->mutex) ); - rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); + rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); if( rc ) return rc; *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); return SQLITE_OK; @@ -1996,24 +1999,25 @@ static int getAndInitPage( rc = SQLITE_CORRUPT_BKPT; goto getAndInitPage_error; } - rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); + rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); if( rc ){ goto getAndInitPage_error; } - *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); + *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); if( (*ppPage)->isInit==0 ){ + btreePageFromDbPage(pDbPage, pgno, pBt); rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); goto getAndInitPage_error; } } + assert( (*ppPage)->pgno==pgno ); + assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); /* If obtaining a child page for a cursor, we must verify that the page is ** compatible with the root page. */ - if( pCur - && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) - ){ + if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ rc = SQLITE_CORRUPT_BKPT; releasePage(*ppPage); goto getAndInitPage_error; @@ -4593,7 +4597,7 @@ static int accessPayload( { DbPage *pDbPage; - rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage, + rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage, ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ @@ -5037,6 +5041,8 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ ** *pRes>0 The cursor is left pointing at an entry that ** is larger than intKey/pIdxKey. ** +** For index tables, the pIdxKey->eqSeen field is set to 1 if there +** exists an entry in the table that exactly matches pIdxKey. */ int sqlite3BtreeMovetoUnpacked( BtCursor *pCur, /* The cursor to be moved */ @@ -6960,9 +6966,6 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ ** If aOvflSpace is set to a null pointer, this function returns ** SQLITE_NOMEM. */ -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#pragma optimize("", off) -#endif static int balance_nonroot( MemPage *pParent, /* Parent page of siblings being balanced */ int iParentIdx, /* Index of "the page" in pParent */ @@ -7708,9 +7711,6 @@ balance_cleanup: return rc; } -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#pragma optimize("", on) -#endif /* @@ -8909,7 +8909,7 @@ static void checkList( break; } if( checkRef(pCheck, iPage) ) break; - if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ checkAppendMsg(pCheck, "failed to get page %d", iPage); break; } @@ -9646,7 +9646,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ return rc; } -#ifdef SQLITE_DEBUG /* ** Return true if the cursor has a hint specified. This routine is ** only used from within assert() statements @@ -9654,7 +9653,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ return (pCsr->hints & mask)!=0; } -#endif /* ** Return true if the given Btree is read-only. diff --git a/src/btree.h b/src/btree.h index f37ec5e7fc..0c15a59c11 100644 --- a/src/btree.h +++ b/src/btree.h @@ -257,9 +257,7 @@ int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); -#ifdef SQLITE_DEBUG int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); -#endif int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3HeaderSizeBtree(void); diff --git a/src/btreeInt.h b/src/btreeInt.h index e52130cc39..e43ff1210a 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -517,7 +517,7 @@ struct BtCursor { int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ** Error code if eState==CURSOR_FAULT */ u8 curFlags; /* zero or more BTCF_* flags defined below */ - u8 curPagerFlags; /* Flags to send to sqlite3PagerAcquire() */ + u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ u8 hints; /* As configured by CursorSetHints() */ /* All fields above are zeroed when the cursor is allocated. See diff --git a/src/dbstat.c b/src/dbstat.c index f43b14881f..ae55d6b803 100644 --- a/src/dbstat.c +++ b/src/dbstat.c @@ -386,7 +386,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){ int rc; u32 iPrev = pCell->aOvfl[j-1]; DbPage *pPg = 0; - rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg); + rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0); if( rc!=SQLITE_OK ){ assert( pPg==0 ); return rc; @@ -454,7 +454,7 @@ statNextRestart: pCsr->isEof = 1; return sqlite3_reset(pCsr->pStmt); } - rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); + rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0); pCsr->aPage[0].iPgno = iRoot; pCsr->aPage[0].iCell = 0; pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); @@ -514,7 +514,7 @@ statNextRestart: }else{ p[1].iPgno = p->aCell[p->iCell].iChildPg; } - rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); + rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0); p[1].iCell = 0; p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); p->iCell++; diff --git a/src/pager.c b/src/pager.c index 314f792aa0..b537e9e931 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2333,7 +2333,7 @@ static int pager_playback_one_page( assert( isSavepnt ); assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 ); pPager->doNotSpill |= SPILLFLAG_ROLLBACK; - rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1); + rc = sqlite3PagerGet(pPager, pgno, &pPg, 1); assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; if( rc!=SQLITE_OK ) return rc; @@ -4969,7 +4969,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){ /* ** This function is called to obtain a shared lock on the database file. -** It is illegal to call sqlite3PagerAcquire() until after this function +** It is illegal to call sqlite3PagerGet() until after this function ** has been successfully called. If a shared-lock is already held when ** this function is called, it is a no-op. ** @@ -5272,7 +5272,7 @@ static void pagerUnlockIfUnused(Pager *pPager){ ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ -int sqlite3PagerAcquire( +int sqlite3PagerGet( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ @@ -5858,7 +5858,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ PgHdr *pPage; if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ if( pg!=PAGER_MJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage); + rc = sqlite3PagerGet(pPager, pg, &pPage, 0); if( rc==SQLITE_OK ){ rc = pager_write(pPage); if( pPage->flags&PGHDR_NEED_SYNC ){ @@ -6018,7 +6018,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ assert( !pPager->tempFile && isOpen(pPager->fd) ); /* Open page 1 of the file for writing. */ - rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0); assert( pPgHdr==0 || rc==SQLITE_OK ); /* If page one was fetched successfully, and this function is not @@ -6173,7 +6173,7 @@ int sqlite3PagerCommitPhaseOne( if( pList==0 ){ /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ - rc = sqlite3PagerGet(pPager, 1, &pPageOne); + rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0); pList = pPageOne; pList->pDirty = 0; } @@ -6878,7 +6878,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ ** the journal file twice, but that is not a problem. */ PgHdr *pPgHdr; - rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0); if( rc!=SQLITE_OK ){ if( needSyncPgno<=pPager->dbOrigSize ){ assert( pPager->pTmpSpace!=0 ); diff --git a/src/pager.h b/src/pager.h index 8e0e942efe..9d541dede9 100644 --- a/src/pager.h +++ b/src/pager.h @@ -79,7 +79,7 @@ typedef struct PgHdr DbPage; #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ /* -** Flags that make up the mask passed to sqlite3PagerAcquire(). +** Flags that make up the mask passed to sqlite3PagerGet(). */ #define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ #define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ @@ -135,8 +135,7 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager*); int sqlite3PagerFlush(Pager*); /* Functions used to obtain and release page references. */ -int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); -#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1ee31d0f39..3b86e49edb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1820,9 +1820,8 @@ struct KeyInfo { }; /* -** An instance of the following structure holds information about a -** single index record that has already been parsed out into individual -** values. +** This object holds a record which has been parsed out into individual +** fields, for the purposes of doing a comparison. ** ** A record is an object that contains one or more fields of data. ** Records are used to store the content of a table row and to store @@ -1830,20 +1829,40 @@ struct KeyInfo { ** the OP_MakeRecord opcode of the VDBE and is disassembled by the ** OP_Column opcode. ** -** This structure holds a record that has already been disassembled -** into its constituent fields. +** An instance of this object serves as a "key" for doing a search on +** an index b+tree. The goal of the search is to find the entry that +** is closed to the key described by this object. This object might hold +** just a prefix of the key. The number of fields is given by +** pKeyInfo->nField. ** -** The r1 and r2 member variables are only used by the optimized comparison -** functions vdbeRecordCompareInt() and vdbeRecordCompareString(). +** The r1 and r2 fields are the values to return if this key is less than +** or greater than a key in the btree, respectively. These are normally +** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree +** is in DESC order. +** +** The key comparison functions actually return default_rc when they find +** an equals comparison. default_rc can be -1, 0, or +1. If there are +** multiple entries in the b-tree with the same key (when only looking +** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to +** cause the search to find the last match, or +1 to cause the search to +** find the first match. +** +** The key comparison functions will set eqSeen to true if they ever +** get and equal results when comparing this structure to a b-tree record. +** When default_rc!=0, the search might end up on the record immediately +** before the first match or immediately after the last match. The +** eqSeen field will indicate whether or not an exact match exists in the +** b-tree. */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ + Mem *aMem; /* Values */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ - Mem *aMem; /* Values */ - int r1; /* Value to return if (lhs > rhs) */ - int r2; /* Value to return if (rhs < lhs) */ + i8 r1; /* Value to return if (lhs > rhs) */ + i8 r2; /* Value to return if (rhs < lhs) */ + u8 eqSeen; /* True if an equality comparison has been seen */ }; diff --git a/src/test1.c b/src/test1.c index dd190feebc..7ce4ed5a5a 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7039,6 +7039,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ }; static int bitmask_size = sizeof(Bitmask)*8; + static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; @@ -7139,6 +7140,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ (char*)&sqlite3_data_directory, TCL_LINK_STRING); Tcl_LinkVar(interp, "bitmask_size", (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "longdouble_size", + (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "sqlite_sync_count", (char*)&sqlite3_sync_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_fullsync_count", diff --git a/src/test2.c b/src/test2.c index 7192ddfffb..d16ba5016a 100644 --- a/src/test2.c +++ b/src/test2.c @@ -322,7 +322,7 @@ static int page_get( if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; rc = sqlite3PagerSharedLock(pPager); if( rc==SQLITE_OK ){ - rc = sqlite3PagerGet(pPager, pgno, &pPage); + rc = sqlite3PagerGet(pPager, pgno, &pPage, 0); } if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); diff --git a/src/vdbe.c b/src/vdbe.c index c1391427f2..5557db6d43 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3607,6 +3607,13 @@ case OP_ColumnsUsed: { ** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this +** opcode will always land on a record that equally equals the key, or +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this +** opcode must be followed by an IdxLE opcode with the same arguments. +** The IdxLE opcode will be skipped if this opcode succeeds, but the +** IdxLE opcode will be used on subsequent loop iterations. +** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. @@ -3665,18 +3672,26 @@ case OP_ColumnsUsed: { ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. ** +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this +** opcode will always land on a record that equally equals the key, or +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this +** opcode must be followed by an IdxGE opcode with the same arguments. +** The IdxGE opcode will be skipped if this opcode succeeds, but the +** IdxGE opcode will be used on subsequent loop iterations. +** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ case OP_SeekLT: /* jump, in3 */ case OP_SeekLE: /* jump, in3 */ case OP_SeekGE: /* jump, in3 */ case OP_SeekGT: { /* jump, in3 */ - int res; - int oc; - VdbeCursor *pC; - UnpackedRecord r; - int nField; - i64 iKey; /* The rowid we are to seek to */ + int res; /* Comparison result */ + int oc; /* Opcode */ + VdbeCursor *pC; /* The cursor to seek */ + UnpackedRecord r; /* The key to seek for */ + int nField; /* Number of columns or fields in the key */ + i64 iKey; /* The rowid we are to seek to */ + int eqOnly; /* Only interested in == results */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p2!=0 ); @@ -3689,27 +3704,16 @@ case OP_SeekGT: { /* jump, in3 */ assert( pC->isOrdered ); assert( pC->pCursor!=0 ); oc = pOp->opcode; + eqOnly = 0; pC->nullRow = 0; #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif - /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and - ** OP_SeekLE opcodes are allowed, and these must be immediately followed - ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. - */ -#ifdef SQLITE_DEBUG - if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){ - assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); - assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - assert( pOp[1].p1==pOp[0].p1 ); - assert( pOp[1].p2==pOp[0].p2 ); - assert( pOp[1].p3==pOp[0].p3 ); - assert( pOp[1].p4.i==pOp[0].p4.i ); - } -#endif - if( pC->isTable ){ + /* The BTREE_SEEK_EQ flag is only set on index cursors */ + assert( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ)==0 ); + /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so convert it. */ @@ -3758,6 +3762,20 @@ case OP_SeekGT: { /* jump, in3 */ goto abort_due_to_error; } }else{ + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and + ** OP_SeekLE opcodes are allowed, and these must be immediately followed + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. + */ + if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){ + eqOnly = 1; + assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); + assert( pOp[1].p1==pOp[0].p1 ); + assert( pOp[1].p2==pOp[0].p2 ); + assert( pOp[1].p3==pOp[0].p3 ); + assert( pOp[1].p4.i==pOp[0].p4.i ); + } + nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); assert( nField>0 ); @@ -3782,10 +3800,15 @@ case OP_SeekGT: { /* jump, in3 */ { int i; for(i=0; ipCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } + if( eqOnly && r.eqSeen==0 ){ + assert( res!=0 ); + goto seek_not_found; + } } pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -3813,10 +3836,14 @@ case OP_SeekGT: { /* jump, in3 */ res = sqlite3BtreeEof(pC->pCursor); } } +seek_not_found: assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ goto jump_to_p2; + }else if( eqOnly ){ + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); + pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ } break; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 750f5f64ae..7e89229be6 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3320,6 +3320,10 @@ u32 sqlite3VdbeSerialGet( /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit ** twos-complement integer. */ pMem->u.i = FOUR_BYTE_INT(buf); +#ifdef __HP_cc + /* Work around a sign-extension bug in the HP compiler for HP/UX */ + if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL; +#endif pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 4; @@ -3636,6 +3640,34 @@ static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ return pB1->n - pB2->n; } +/* +** Do a comparison between a 64-bit signed integer and a 64-bit floating-point +** number. Return negative, zero, or positive if the first (i64) is less than, +** equal to, or greater than the second (double). +*/ +static int sqlite3IntFloatCompare(i64 i, double r){ + if( sizeof(LONGDOUBLE_TYPE)>8 ){ + LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; + if( xr ) return +1; + return 0; + }else{ + i64 y; + double s; + if( r<-9223372036854775808.0 ) return +1; + if( r>9223372036854775807.0 ) return -1; + y = (i64)r; + if( iy ){ + if( y==SMALLEST_INT64 && r>0.0 ) return -1; + return +1; + } + s = (double)i; + if( sr ) return +1; + return 0; + } +} /* ** Compare the values contained by the two memory cells, returning @@ -3662,34 +3694,34 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ return (f2&MEM_Null) - (f1&MEM_Null); } - /* If one value is a number and the other is not, the number is less. - ** If both are numbers, compare as reals if one is a real, or as integers - ** if both values are integers. + /* At least one of the two values is a number */ if( combined_flags&(MEM_Int|MEM_Real) ){ - double r1, r2; if( (f1 & f2 & MEM_Int)!=0 ){ if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return 1; + if( pMem1->u.i > pMem2->u.i ) return +1; return 0; } + if( (f1 & f2 & MEM_Real)!=0 ){ + if( pMem1->u.r < pMem2->u.r ) return -1; + if( pMem1->u.r > pMem2->u.r ) return +1; + return 0; + } + if( (f1&MEM_Int)!=0 ){ + if( (f2&MEM_Real)!=0 ){ + return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r); + }else{ + return -1; + } + } if( (f1&MEM_Real)!=0 ){ - r1 = pMem1->u.r; - }else if( (f1&MEM_Int)!=0 ){ - r1 = (double)pMem1->u.i; - }else{ - return 1; + if( (f2&MEM_Int)!=0 ){ + return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r); + }else{ + return -1; + } } - if( (f2&MEM_Real)!=0 ){ - r2 = pMem2->u.r; - }else if( (f2&MEM_Int)!=0 ){ - r2 = (double)pMem2->u.i; - }else{ - return -1; - } - if( r1r2 ) return 1; - return 0; + return +1; } /* If one value is a string and the other is a blob, the string is less. @@ -3840,13 +3872,8 @@ int sqlite3VdbeRecordCompareWithSkip( }else if( serial_type==0 ){ rc = -1; }else if( serial_type==7 ){ - double rhs = (double)pRhs->u.i; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); - if( mem1.u.rrhs ){ - rc = +1; - } + rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); }else{ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); i64 rhs = pRhs->u.i; @@ -3870,18 +3897,15 @@ int sqlite3VdbeRecordCompareWithSkip( }else if( serial_type==0 ){ rc = -1; }else{ - double rhs = pRhs->u.r; - double lhs; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); if( serial_type==7 ){ - lhs = mem1.u.r; + if( mem1.u.ru.r ){ + rc = -1; + }else if( mem1.u.r>pRhs->u.r ){ + rc = +1; + } }else{ - lhs = (double)mem1.u.i; - } - if( lhsrhs ){ - rc = +1; + rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); } } } @@ -3971,6 +3995,7 @@ int sqlite3VdbeRecordCompareWithSkip( || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) || pKeyInfo->db->mallocFailed ); + pPKey2->eqSeen = 1; return pPKey2->default_rc; } int sqlite3VdbeRecordCompare( @@ -4070,6 +4095,7 @@ static int vdbeRecordCompareInt( /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ res = pPKey2->default_rc; + pPKey2->eqSeen = 1; } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) ); @@ -4090,6 +4116,7 @@ static int vdbeRecordCompareString( int serial_type; int res; + assert( pPKey2->aMem[0].flags & MEM_Str ); vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); getVarint32(&aKey1[1], serial_type); if( serial_type<12 ){ @@ -4116,6 +4143,7 @@ static int vdbeRecordCompareString( res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; + pPKey2->eqSeen = 1; } }else if( res>0 ){ res = pPKey2->r2; diff --git a/test/atof1.test b/test/atof1.test index 5c04d02290..55f5e44d96 100644 --- a/test/atof1.test +++ b/test/atof1.test @@ -15,7 +15,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -if {![info exists __GNUC__] || [regexp arm $tcl_platform(machine)]} { +if {$::longdouble_size<=8} { finish_test return } diff --git a/test/bc_common.tcl b/test/bc_common.tcl index eb9b6db9d3..78010dfa46 100644 --- a/test/bc_common.tcl +++ b/test/bc_common.tcl @@ -7,11 +7,13 @@ proc bc_find_binaries {zCaption} { # against. # set binaries [list] - set pattern "[file tail [info nameofexec]]?*" + set self [file tail [info nameofexec]] + set pattern "$self?*" if {$::tcl_platform(platform)=="windows"} { set pattern [string map {\.exe {}} $pattern] } foreach file [glob -nocomplain $pattern] { + if {$file==$self} continue if {[file executable $file] && [file isfile $file]} {lappend binaries $file} } diff --git a/test/collate4.test b/test/collate4.test index 2ddf53d58b..b8c1c573c3 100644 --- a/test/collate4.test +++ b/test/collate4.test @@ -352,7 +352,7 @@ do_test collate4-2.1.2 { count { SELECT * FROM collate4t2, collate4t1 WHERE a = b; } -} {A a A A 5} +} {A a A A 4} do_test collate4-2.1.3 { count { SELECT * FROM collate4t2, collate4t1 WHERE b = a; @@ -372,7 +372,7 @@ do_test collate4-2.1.5 { count { SELECT * FROM collate4t2, collate4t1 WHERE b = a; } -} {A A 4} +} {A A 3} ifcapable subquery { do_test collate4-2.1.6 { count { @@ -389,12 +389,12 @@ ifcapable subquery { SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2) ORDER BY rowid } - } {a A 6} + } {a A 5} do_test collate4-2.1.8 { count { SELECT a FROM collate4t1 WHERE a IN ('z', 'a'); } - } {a A 5} + } {a A 4} do_test collate4-2.1.9 { execsql { DROP INDEX collate4i1; diff --git a/test/e_uri.test b/test/e_uri.test index d1590e4108..7a7f2559ec 100644 --- a/test/e_uri.test +++ b/test/e_uri.test @@ -26,7 +26,9 @@ proc parse_uri {uri} { set DB [sqlite3_open_v2 $uri { SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL } tvfs] + set fileName [sqlite3_db_filename $DB main] sqlite3_close $DB + forcedelete $fileName tvfs delete tvfs2 delete diff --git a/test/ieee754.test b/test/ieee754.test new file mode 100644 index 0000000000..c0bf9d7995 --- /dev/null +++ b/test/ieee754.test @@ -0,0 +1,56 @@ +# 2015-11-06 +# +# 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. +# +#*********************************************************************** +# +# Tests of the iee754 extension +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +load_static_extension db ieee754 + +foreach {id float rep} { + 1 1.0 1,0 + 2 2.0 2,0 + 3 0.5 1,-1 + 4 1.5 3,-1 + 5 0.0 0,-1075 + 6 4.9406564584124654e-324 4503599627370497,-1075 + 7 2.2250738585072009e-308 9007199254740991,-1075 + 8 2.2250738585072014e-308 1,-1022 +} { + do_test ieee754-100-$id-1 { + db eval "SELECT ieee754($float);" + } "ieee754($rep)" + do_test ieee754-100-$id-2 { + db eval "SELECT ieee754($rep)==$float;" + } {1} + if {$float!=0.0} { + do_test ieee754-100-$id-3 { + db eval "SELECT ieee754(-$float);" + } "ieee754(-$rep)" + do_test ieee754-100-$id-4 { + db eval "SELECT ieee754(-$rep)==-$float;" + } {1} + } +} + +do_execsql_test ieee754-110 { + SELECT ieee754(1,1024), ieee754(4503599627370495,972); +} {Inf 1.79769313486232e+308} +do_execsql_test ieee754-111 { + SELECT ieee754(-1,1024), ieee754(-4503599627370495,972); +} {-Inf -1.79769313486232e+308} +do_execsql_test ieee754-112 { + SELECT ieee754(4503599627370495,973) is null; +} {1} + +finish_test diff --git a/test/numindex1.test b/test/numindex1.test new file mode 100644 index 0000000000..c647fc5401 --- /dev/null +++ b/test/numindex1.test @@ -0,0 +1,79 @@ +# 2015-11-05 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements tests for indexes on large numeric values. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + + +# Test cases from Zsbán Ambrus: +# +do_execsql_test numindex1-1.1 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE INDEX t1b ON t1(b); + INSERT INTO t1(a,b) VALUES(100, 356282677878746339); + INSERT INTO t1(a,b) VALUES(50, 356282677878746339.0); + INSERT INTO t1(a,b) VALUES(0, 356282677878746340); + DELETE FROM t1 WHERE a=50; + PRAGMA integrity_check; +} {ok} + +do_execsql_test numindex1-1.2 { + CREATE TABLE t2(a,b); + INSERT INTO t2(a,b) VALUES('b', 1<<58), + ('c', (1<<58)+1e-7), ('d', (1<<58)+1); + SELECT a, b, typeof(b), '|' FROM t2 ORDER BY +a; +} {b 288230376151711744 integer | c 2.88230376151712e+17 real | d 288230376151711745 integer |} + +do_execsql_test numindex1-1.3 { + SELECT x.a || CASE WHEN x.b==y.b THEN '==' ELSE '<>' END || y.a + FROM t2 AS x, t2 AS y + ORDER BY +x.a, +x.b; +} {b==b b==c b<>d c==b c==c c<>d d<>b d<>c d==d} + +# New test cases +# +do_execsql_test numindex1-2.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY,b); + CREATE INDEX t1b ON t1(b); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t1(a,b) SELECT x, 10000000000000004.0 FROM c + WHERE x NOT IN (23,37); + INSERT INTO t1(a,b) VALUES(23,10000000000000005); + INSERT INTO t1(a,b) VALUES(37,10000000000000003); + DELETE FROM t1 WHERE a NOT IN (23,37); + PRAGMA integrity_check; +} {ok} + +do_execsql_test numindex1-3.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY,b); + CREATE INDEX t1b ON t1(b); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20) + INSERT INTO t1(a,b) SELECT x, 100000000000000005.0 + FROM c WHERE x NOT IN (3,5,7,11,13,17,19); + INSERT INTO t1(a,b) VALUES(3,100000000000000005); + INSERT INTO t1(a,b) VALUES(5,100000000000000000); + INSERT INTO t1(a,b) VALUES(7,100000000000000008); + INSERT INTO t1(a,b) VALUES(11,100000000000000006); + INSERT INTO t1(a,b) VALUES(13,100000000000000001); + INSERT INTO t1(a,b) VALUES(17,100000000000000004); + INSERT INTO t1(a,b) VALUES(19,100000000000000003); + PRAGMA integrity_check; +} {ok} + +do_execsql_test numindex1-3.2 { + SELECT a FROM t1 ORDER BY b; +} {1 2 4 5 6 8 9 10 12 14 15 16 18 20 13 19 17 3 11 7} + +finish_test diff --git a/test/permutations.test b/test/permutations.test index b15f6d552e..5e7b00eff1 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -182,7 +182,7 @@ test_suite "valgrind" -prefix "" -description { } -files [ test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \ shell*.test crash8.test atof1.test selectG.test \ - tkt-fc62af4523.test + tkt-fc62af4523.test numindex1.test ] -initialize { set ::G(valgrind) 1 } -shutdown { @@ -711,7 +711,7 @@ test_suite "inmemory_journal" -description { pragma journal_mode = 'memory' } -files [test_set $::allquicktests -exclude { # Exclude all tests that simulate IO errors. - autovacuum_ioerr2.test incrvacuum_ioerr.test ioerr.test + autovacuum_ioerr2.test cffault.test incrvacuum_ioerr.test ioerr.test ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test @@ -727,7 +727,7 @@ test_suite "inmemory_journal" -description { corrupt5.test corruptA.test pageropt.test # Exclude stmt.test, which expects sub-journals to use temporary files. - stmt.test + stmt.test symlink.test zerodamage.test diff --git a/test/releasetest.tcl b/test/releasetest.tcl index 04c2419ace..2e67aabae2 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -19,6 +19,8 @@ optional) are: --dryrun (Print what would have happened) --info (Show diagnostic info) --with-tcl=DIR (Use TCL build at DIR) + --jobs N (Use N processes - default 1) + --progress (Show progress messages) The default value for --srcdir is the parent of the directory holding this script. @@ -32,6 +34,12 @@ Every test begins with a fresh run of the configure script at the top of the SQLite source tree. } +# Return a timestamp of the form HH:MM:SS +# +proc now {} { + return [clock format [clock seconds] -format %H:%M:%S] +} + # Omit comments (text between # and \n) in a long multi-line string. # proc strip_comments {in} { @@ -120,6 +128,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_RBU -DSQLITE_MAX_ATTACHED=125 + -DLONGDOUBLE_TYPE=double } "Device-One" { -O2 @@ -223,6 +232,7 @@ array set ::Configs [strip_comments { array set ::Platforms [strip_comments { Linux-x86_64 { "Check-Symbols" checksymbols + "Fast-One" fuzztest "Debug-One" "mptest test" "Have-Not" test "Secure-Delete" test @@ -233,10 +243,9 @@ array set ::Platforms [strip_comments { "No-lookaside" test "Devkit" test "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} - "Fast-One" fuzztest - "Valgrind" valgrindtest - "Default" "threadtest fulltest" "Device-One" fulltest + "Default" "threadtest fulltest" + "Valgrind" valgrindtest } Linux-i686 { "Devkit" test @@ -257,12 +266,12 @@ array set ::Platforms [strip_comments { "OS-X" "threadtest fulltest" } "Windows NT-intel" { - "Default" "mptest fulltestonly" "Have-Not" test + "Default" "mptest fulltestonly" } "Windows NT-amd64" { - "Default" "mptest fulltestonly" "Have-Not" test + "Default" "mptest fulltestonly" } # The Failure-Detection platform runs various tests that deliberately @@ -285,6 +294,9 @@ array set ::Platforms [strip_comments { ######################################################################### ######################################################################### +# Configuration verification: Check that each entry in the list of configs +# specified for each platforms exists. +# foreach {key value} [array get ::Platforms] { foreach {v t} $value { if {0==[info exists ::Configs($v)]} { @@ -372,9 +384,8 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} { } close $fd if {$::BUILDONLY} { - if {$rc==0} { - set errmsg "Build complete" - } else { + incr ::NTESTCASE + if {$rc!=0} { set errmsg "Build failed" } } elseif {!$seen} { @@ -386,12 +397,169 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} { } } -proc run_test_suite {name testtarget config} { +#-------------------------------------------------------------------------- +# This command is invoked as the [main] routine for scripts run with the +# "--slave" option. +# +# For each test (i.e. "configure && make test" execution), the master +# process spawns a process with the --slave option. It writes two lines +# to the slaves stdin. The first contains a single boolean value - the +# value of ::TRACE to use in the slave script. The second line contains a +# list in the same format as each element of the list passed to the +# [run_all_test_suites] command in the master process. +# +# The slave then runs the "configure && make test" commands specified. It +# exits successfully if the tests passes, or with a non-zero error code +# otherwise. +# +proc run_slave_test {} { + # Read global vars configuration from stdin. + set V [gets stdin] + foreach {::TRACE ::MSVC ::DRYRUN} $V {} + + # Read the test-suite configuration from stdin. + set T [gets stdin] + foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} + + # Create and switch to the test directory. + trace_cmd file mkdir $dir + trace_cmd cd $dir + catch {file delete core} + catch {file delete test.log} + + # Run the "./configure && make" commands. + set rc 0 + set rc [catch [configureCommand $configOpts]] + if {!$rc} { + if {[info exists ::env(TCLSH_CMD)]} { + set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD) + } else { + unset -nocomplain savedEnv(TCLSH_CMD) + } + set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]] + set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]] + if {[info exists savedEnv(TCLSH_CMD)]} { + set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD) + } else { + unset -nocomplain ::env(TCLSH_CMD) + } + } + + # Exis successfully if the test passed, or with a non-zero error code + # otherwise. + exit $rc +} + +# This command is invoked in the master process each time a slave +# file-descriptor is readable. +# +proc slave_fileevent {fd T tm1} { + global G + foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} + + if {[eof $fd]} { + fconfigure $fd -blocking 1 + set rc [catch { close $fd }] + + set errmsg {} + set logfile [file join $dir test.log] + if {[file exists $logfile]} { + count_tests_and_errors [file join $dir test.log] rc errmsg + } elseif {$rc==0 && !$::DRYRUN} { + set rc 1 + set errmsg "no test.log file..." + } + + if {!$::TRACE} { + set tm2 [clock seconds] + set hours [expr {($tm2-$tm1)/3600}] + set minutes [expr {(($tm2-$tm1)/60)%60}] + set seconds [expr {($tm2-$tm1)%60}] + set tm [format (%02d:%02d:%02d) $hours $minutes $seconds] + + if {$rc} { + set status FAIL + incr ::NERR + } else { + set status Ok + } + + set n [string length $title] + if {$::PROGRESS_MSGS} { + PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm" + } else { + PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm" + } + if {$errmsg!=""} {PUTS " $errmsg"} + flush stdout + } + + incr G(nJob) -1 + } else { + set line [gets $fd] + if {[string trim $line] != ""} { + puts "Trace : $title - \"$line\"" + } + } +} + +#-------------------------------------------------------------------------- +# The only argument passed to this function is a list of test-suites to +# run. Each "test-suite" is itself a list consisting of the following +# elements: +# +# * Test title (for display). +# * The name of the directory to run the test in. +# * The argument for [configureCommand] +# * The first argument for [makeCommand] +# * The second argument for [makeCommand] +# * The third argument for [makeCommand] +# +proc run_all_test_suites {alltests} { + global G + set tests $alltests + + set G(nJob) 0 + + while {[llength $tests]>0 || $G(nJob)>0} { + if {$G(nJob)>=$::JOBS || [llength $tests]==0} { + vwait G(nJob) + } + + if {[llength $tests]>0} { + set T [lindex $tests 0] + set tests [lrange $tests 1 end] + foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} + if {$::PROGRESS_MSGS && !$::TRACE} { + set n [string length $title] + PUTS "starting: ${title} at [now]" + flush stdout + } + + # Run the job. + # + set tm1 [clock seconds] + incr G(nJob) + set script [file normalize [info script]] + set fd [open "|[info nameofexecutable] $script --slave" r+] + fconfigure $fd -blocking 0 + fileevent $fd readable [list slave_fileevent $fd $T $tm1] + puts $fd [list $::TRACE $::MSVC $::DRYRUN] + puts $fd [list {*}$T] + flush $fd + } + } +} + +proc add_test_suite {listvar name testtarget config} { + upvar $listvar alltests + # Tcl variable $opts is used to build up the value used to set the # OPTS Makefile variable. Variable $cflags holds the value for # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but # CFLAGS is only passed to gcc. # + set makeOpts "" set cflags [expr {$::MSVC ? "-Zi" : "-g"}] set opts "" set title ${name}($testtarget) @@ -404,67 +572,74 @@ proc run_test_suite {name testtarget config} { } elseif {[regexp {^[A-Z]+=} $arg]} { lappend testtarget $arg } elseif {[regexp {^--(enable|disable)-} $arg]} { + if {$::MSVC} { + if {$arg eq "--disable-amalgamation"} { + lappend makeOpts USE_AMALGAMATION=0 + continue + } + if {$arg eq "--disable-shared"} { + lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 + continue + } + if {$arg eq "--enable-fts5"} { + lappend opts -DSQLITE_ENABLE_FTS5 + continue + } + if {$arg eq "--enable-json1"} { + lappend opts -DSQLITE_ENABLE_JSON1 + continue + } + if {$arg eq "--enable-shared"} { + lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 + continue + } + } lappend configOpts $arg } else { + if {$::MSVC} { + if {$arg eq "-g"} { + lappend cflags -Zi + continue + } + if {[regexp -- {^-O(\d+)$} $arg all level]} then { + lappend makeOpts OPTIMIZATIONS=$level + continue + } + } lappend cflags $arg } } - set cflags [join $cflags " "] - set opts [join $opts " "] - append opts " -DSQLITE_NO_SYNC=1" + # Disable sync to make testing faster. + # + lappend opts -DSQLITE_NO_SYNC=1 # Some configurations already set HAVE_USLEEP; in that case, skip it. # - if {![regexp { -DHAVE_USLEEP$} $opts] - && ![regexp { -DHAVE_USLEEP[ =]+} $opts]} { - append opts " -DHAVE_USLEEP=1" + if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} { + lappend opts -DHAVE_USLEEP=1 + } + + # Add the define for this platform. + # + if {$::tcl_platform(platform)=="windows"} { + lappend opts -DSQLITE_OS_WIN=1 + } else { + lappend opts -DSQLITE_OS_UNIX=1 } # Set the sub-directory to use. # set dir [string tolower [string map {- _ " " _} $name]] - if {$::tcl_platform(platform)=="windows"} { - append opts " -DSQLITE_OS_WIN=1" - } else { - append opts " -DSQLITE_OS_UNIX=1" - } + # Join option lists into strings, using space as delimiter. + # + set makeOpts [join $makeOpts " "] + set cflags [join $cflags " "] + set opts [join $opts " "] - if {!$::TRACE} { - set n [string length $title] - PUTS -nonewline "${title}[string repeat . [expr {63-$n}]]" - flush stdout - } - - set rc 0 - set tm1 [clock seconds] - set origdir [pwd] - trace_cmd file mkdir $dir - trace_cmd cd $dir - set errmsg {} - catch {file delete core} - set rc [catch [configureCommand $configOpts]] - if {!$rc} { - set rc [catch [makeCommand $testtarget $cflags $opts]] - count_tests_and_errors test.log rc errmsg - } - trace_cmd cd $origdir - set tm2 [clock seconds] - - if {!$::TRACE} { - set hours [expr {($tm2-$tm1)/3600}] - set minutes [expr {(($tm2-$tm1)/60)%60}] - set seconds [expr {($tm2-$tm1)%60}] - set tm [format (%02d:%02d:%02d) $hours $minutes $seconds] - if {$rc} { - PUTS " FAIL $tm" - incr ::NERR - } else { - PUTS " Ok $tm" - } - if {$errmsg!=""} {PUTS " $errmsg"} - } + lappend alltests [list \ + $title $dir $configOpts $testtarget $makeOpts $cflags $opts] } # The following procedure returns the "configure" command to be exectued for @@ -484,15 +659,19 @@ proc configureCommand {opts} { # The following procedure returns the "make" command to be executed for the # specified targets, compiler flags, and options. # -proc makeCommand { targets cflags opts } { +proc makeCommand { targets makeOpts cflags opts } { set result [list trace_cmd exec] if {$::MSVC} { set nmakeDir [file nativename $::SRCDIR] - set nmakeFile [file join $nmakeDir Makefile.msc] - lappend result nmake /f $nmakeFile TOP=$nmakeDir clean + set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]] + lappend result nmake /f $nmakeFile TOP=$nmakeDir } else { - lappend result make clean + lappend result make } + foreach makeOpt $makeOpts { + lappend result $makeOpt + } + lappend result clean foreach target $targets { lappend result $target } @@ -507,9 +686,11 @@ proc trace_cmd {args} { if {$::TRACE} { PUTS $args } + set res "" if {!$::DRYRUN} { - uplevel 1 $args + set res [uplevel 1 $args] } + return $res } @@ -520,13 +701,14 @@ proc trace_cmd {args} { # proc process_options {argv} { set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]] - set ::QUICK 0 - set ::MSVC 0 - set ::BUILDONLY 0 - set ::DRYRUN 0 - set ::EXEC exec - set ::TRACE 0 - set ::WITHTCL {} + set ::QUICK 0 + set ::MSVC 0 + set ::BUILDONLY 0 + set ::DRYRUN 0 + set ::TRACE 0 + set ::JOBS 1 + set ::PROGRESS_MSGS 0 + set ::WITHTCL {} set config {} set platform $::tcl_platform(os)-$::tcl_platform(machine) @@ -534,6 +716,11 @@ proc process_options {argv} { set x [lindex $argv $i] if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]} switch -glob -- $x { + -slave { + run_slave_test + exit + } + -srcdir { incr i set ::SRCDIR [file normalize [lindex $argv $i]] @@ -544,6 +731,15 @@ proc process_options {argv} { set platform [lindex $argv $i] } + -jobs { + incr i + set ::JOBS [lindex $argv $i] + } + + -progress { + set ::PROGRESS_MSGS 1 + } + -quick { set ::QUICK 1 } @@ -597,11 +793,7 @@ proc process_options {argv} { } -g { - if {$::MSVC} { - lappend ::EXTRACONFIG -Zi - } else { - lappend ::EXTRACONFIG [lindex $argv $i] - } + lappend ::EXTRACONFIG [lindex $argv $i] } -with-tcl=* { @@ -640,11 +832,20 @@ proc process_options {argv} { if {[llength $config]==1} {lappend config fulltest} set ::CONFIGLIST $config } else { - set ::CONFIGLIST $::Platforms($platform) + if {$::JOBS>1} { + set ::CONFIGLIST {} + foreach {target zConfig} [lreverse $::Platforms($platform)] { + append ::CONFIGLIST [format " %-25s %s\n" \ + [list $zConfig] [list $target]] + } + } else { + set ::CONFIGLIST $::Platforms($platform) + } } PUTS "Running the following test configurations for $platform:" PUTS " [string trim $::CONFIGLIST]" PUTS -nonewline "Flags:" + if {$::PROGRESS_MSGS} {PUTS -nonewline " --progress"} if {$::DRYRUN} {PUTS -nonewline " --dryrun"} if {$::BUILDONLY} {PUTS -nonewline " --buildonly"} if {$::MSVC} {PUTS -nonewline " --msvc"} @@ -652,6 +853,7 @@ proc process_options {argv} { 1 {PUTS -nonewline " --quick"} 2 {PUTS -nonewline " --veryquick"} } + if {$::JOBS>1} {PUTS -nonewline " --jobs $::JOBS"} PUTS "" } @@ -683,13 +885,15 @@ proc main {argv} { } if {$::BUILDONLY} { set target testfixture - if {$::MSVC} {append target .exe} + if {$::tcl_platform(platform)=="windows"} { + append target .exe + } } } set config_options [concat $::Configs($zConfig) $::EXTRACONFIG] incr NTEST - run_test_suite $zConfig $target $config_options + add_test_suite all $zConfig $target $config_options # If the configuration included the SQLITE_DEBUG option, then remove # it and run veryquick.test. If it did not include the SQLITE_DEBUG option @@ -703,16 +907,18 @@ proc main {argv} { if {$debug_idx < 0} { incr NTEST append config_options " -DSQLITE_DEBUG=1" - run_test_suite "${zConfig}_debug" $xtarget $config_options + add_test_suite all "${zConfig}_debug" $xtarget $config_options } else { incr NTEST regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options - run_test_suite "${zConfig}_ndebug" $xtarget $config_options + add_test_suite all "${zConfig}_ndebug" $xtarget $config_options } } } + run_all_test_suites $all + set elapsetime [expr {[clock seconds]-$STARTTIME}] set hr [expr {$elapsetime/3600}] set min [expr {($elapsetime/60)%60}] diff --git a/test/where.test b/test/where.test index e94047564c..0b5bb934d0 100644 --- a/test/where.test +++ b/test/where.test @@ -412,22 +412,22 @@ ifcapable subquery { count { SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1; } - } {1 0 4 2 1 9 3 1 16 13} + } {1 0 4 2 1 9 3 1 16 12} do_test where-5.3b { count { SELECT * FROM t1 WHERE w IN (3,-1,1,2) order by 1; } - } {1 0 4 2 1 9 3 1 16 13} + } {1 0 4 2 1 9 3 1 16 12} do_test where-5.3c { count { SELECT * FROM t1 WHERE w IN (3,2,-1,1,2) order by 1; } - } {1 0 4 2 1 9 3 1 16 13} + } {1 0 4 2 1 9 3 1 16 12} do_test where-5.3d { count { SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1 DESC; } - } {3 1 16 2 1 9 1 0 4 12} + } {3 1 16 2 1 9 1 0 4 11} do_test where-5.4 { count { SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1; @@ -465,7 +465,7 @@ ifcapable subquery { count { SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1; } - } {2 1 9 3 1 16 7} + } {2 1 9 3 1 16 6} do_test where-5.10 { count { SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1; @@ -485,17 +485,17 @@ ifcapable subquery { count { SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1; } - } {2 1 9 3 1 16 7} + } {2 1 9 3 1 16 6} do_test where-5.14 { count { SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1; } - } {2 1 9 8} + } {2 1 9 5} do_test where-5.15 { count { SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1; } - } {2 1 9 3 1 16 11} + } {2 1 9 3 1 16 9} do_test where-5.100 { db eval { SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969) diff --git a/test/where4.test b/test/where4.test index 3b24711514..bafc84faef 100644 --- a/test/where4.test +++ b/test/where4.test @@ -91,7 +91,7 @@ do_test where4-1.10 { } {6 2} do_test where4-1.11 { count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=123} -} {1} +} {0} do_test where4-1.12 { count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=x'7A'} } {6 2}