Index: ext/fts5/fts5_expr.c ================================================================== --- ext/fts5/fts5_expr.c +++ ext/fts5/fts5_expr.c @@ -2498,11 +2498,11 @@ if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; for(i=0; inPhrase; i++){ Fts5ExprTerm *pTerm; if( p->aPopulator[i].bOk==0 ) continue; for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ - int nTerm = strlen(pTerm->zTerm); + int nTerm = (int)strlen(pTerm->zTerm); if( (nTerm==nToken || (nTermbPrefix)) && memcmp(pTerm->zTerm, pToken, nTerm)==0 ){ int rc = sqlite3Fts5PoslistWriterAppend( &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff Index: ext/fts5/fts5_storage.c ================================================================== --- ext/fts5/fts5_storage.c +++ ext/fts5/fts5_storage.c @@ -143,10 +143,11 @@ } } } *ppStmt = p->aStmt[eStmt]; + sqlite3_reset(*ppStmt); return rc; } static int fts5ExecPrintf( @@ -1119,7 +1120,5 @@ p->pConfig->iCookie = iNew; } } return rc; } - - Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -1281,11 +1281,12 @@ int i; u32 m = 0; if( pList ){ for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; - if( ALWAYS(pExpr) ) m |= pExpr->flags; + assert( pExpr!=0 ); + m |= pExpr->flags; } } return m; } @@ -3546,10 +3547,17 @@ case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_IS: + case TK_ISNOT: + testcase( op==TK_IS ); + testcase( op==TK_ISNOT ); + op = (op==TK_IS) ? TK_EQ : TK_NE; + jumpIfNull = SQLITE_NULLEQ; + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: @@ -3561,27 +3569,16 @@ r1, r2, dest, jumpIfNull); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: @@ -3702,10 +3699,17 @@ case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_IS: + case TK_ISNOT: + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; + jumpIfNull = SQLITE_NULLEQ; + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: @@ -3717,27 +3721,16 @@ r1, r2, dest, jumpIfNull); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); + VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -1654,10 +1654,14 @@ ** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right. */ static void verifyDbFile(unixFile *pFile){ struct stat buf; int rc; + + /* These verifications occurs for the main database only */ + if( pFile->ctrlFlags & UNIXFILE_NOLOCK ) return; + rc = osFstat(pFile->h, &buf); if( rc!=0 ){ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); return; } @@ -6991,13 +6995,10 @@ #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) else{ p->openFlags = openFlags; } #endif - - noLock = eType!=SQLITE_OPEN_MAIN_DB; - #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ storeLastErrno(p, errno); robust_close(p, fd, __LINE__); @@ -7012,10 +7013,11 @@ #endif /* Set up appropriate ctrlFlags */ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; + noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; #if defined(SQLITE_ENABLE_PERSIST_WAL) if( eType==SQLITE_OPEN_MAIN_DB ) { Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1704,11 +1704,13 @@ ** PRAGMA [schema.]schema_version = ** ** PRAGMA [schema.]user_version ** PRAGMA [schema.]user_version = ** - ** PRAGMA [schema.]freelist_count = + ** PRAGMA [schema.]freelist_count + ** + ** PRAGMA [schema.]data_version ** ** PRAGMA [schema.]application_id ** PRAGMA [schema.]application_id = ** ** The pragma's schema_version and user_version are used to set or get @@ -1760,10 +1762,11 @@ aOp[0].p1 = iDb; aOp[1].p1 = iDb; aOp[1].p3 = iCookie; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); + sqlite3VdbeReusable(v); } } break; #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ @@ -1781,10 +1784,11 @@ setOneColumnName(v, "compile_option"); while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ sqlite3VdbeLoadString(v, 1, zOpt); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } + sqlite3VdbeReusable(v); } break; #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ #ifndef SQLITE_OMIT_WAL Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -1900,27 +1900,23 @@ ){ Tcl_CmdInfo cmdInfo; sqlite3 *db; int rc; char *zDb; -#ifndef SQLITE_OMIT_LOAD_EXTENSION char *zFile; char *zProc = 0; -#endif char *zErr = 0; if( objc!=4 && objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); return TCL_ERROR; } zDb = Tcl_GetString(objv[1]); -#ifndef SQLITE_OMIT_LOAD_EXTENSION zFile = Tcl_GetString(objv[2]); if( objc==4 ){ zProc = Tcl_GetString(objv[3]); } -#endif /* Extract the C database handle from the Tcl command name */ if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); return TCL_ERROR; @@ -1933,10 +1929,12 @@ ** error occurs, set rc to TCL_OK. */ #ifdef SQLITE_OMIT_LOAD_EXTENSION rc = SQLITE_ERROR; zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); + (void)zProc; + (void)zFile; #else rc = sqlite3_load_extension(db, zFile, zProc, &zErr); #endif if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); Index: src/test_config.c ================================================================== --- src/test_config.c +++ src/test_config.c @@ -76,10 +76,17 @@ #ifdef SQLITE_DEBUG Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY); #endif + +#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC + Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync", + SQLITE_DEFAULT_CKPTFULLFSYNC ? "1" : "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "default_ckptfullfsync", "0", TCL_GLOBAL_ONLY); +#endif #ifdef SQLITE_DIRECT_OVERFLOW_READ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "direct_read", "0", TCL_GLOBAL_ONLY); @@ -94,10 +101,16 @@ #ifdef SQLITE_DISABLE_LFS Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY); #endif + +#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS + Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","0",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "pagecache_overflow_stats","1",TCL_GLOBAL_ONLY); +#endif #if SQLITE_MAX_MMAP_SIZE>0 Tcl_SetVar2(interp, "sqlite_options", "mmap", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "mmap", "0", TCL_GLOBAL_ONLY); @@ -588,11 +601,15 @@ #else Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY); #endif Tcl_SetVar2(interp, "sqlite_options", "threadsafe", - STRINGVALUE(SQLITE_THREADSAFE), TCL_GLOBAL_ONLY); + SQLITE_THREADSAFE ? "1" : "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "threadsafe1", + SQLITE_THREADSAFE==1 ? "1" : "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "threadsafe2", + SQLITE_THREADSAFE==2 ? "1" : "0", TCL_GLOBAL_ONLY); assert( sqlite3_threadsafe()==SQLITE_THREADSAFE ); #ifdef SQLITE_OMIT_TEMPDB Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY); #else Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -200,10 +200,11 @@ void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeRunOnlyOnce(Vdbe*); +void sqlite3VdbeReusable(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeClearObject(sqlite3*,Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,Parse*); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -388,10 +388,17 @@ ** Mark the VDBE as one that can only be run one time. */ void sqlite3VdbeRunOnlyOnce(Vdbe *p){ p->runOnlyOnce = 1; } + +/* +** Mark the VDBE as one that can only be run multiple times. +*/ +void sqlite3VdbeReusable(Vdbe *p){ + p->runOnlyOnce = 0; +} #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ /* ** The following type and function are used to iterate through all opcodes Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -287,10 +287,11 @@ pScan->pIdxExpr = 0; if( pIdx ){ j = iColumn; iColumn = pIdx->aiColumn[j]; if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; } if( pIdx && iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; }else{ @@ -3927,11 +3928,11 @@ WhereLoop *pLoop; int iCur; int j; Table *pTab; Index *pIdx; - + pWInfo = pBuilder->pWInfo; if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; assert( pWInfo->pTabList->nSrc>=1 ); pItem = pWInfo->pTabList->a; pTab = pItem->pTab; Index: test/capi3.test ================================================================== --- test/capi3.test +++ test/capi3.test @@ -923,23 +923,24 @@ sqlite3_get_autocommit $DB } 1 do_test capi3-11.10 { sqlite3_step $STMT } {SQLITE_ROW} -ifcapable !autoreset { - # If SQLITE_OMIT_AUTORESET is defined, then the statement must be - # reset() before it can be passed to step() again. - do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} - do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} -} do_test capi3-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -do_test capi3-11.12 { - sqlite3_step $STMT - sqlite3_step $STMT -} {SQLITE_ROW} +ifcapable api_armor { + do_test capi3-11.12armor { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_MISUSE} +} else { + do_test capi3-11.12 { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_ROW} +} do_test capi3-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} do_test capi3-11.14 { execsql { Index: test/capi3c.test ================================================================== --- test/capi3c.test +++ test/capi3c.test @@ -863,23 +863,24 @@ sqlite3_get_autocommit $DB } 1 do_test capi3c-11.10 { sqlite3_step $STMT } {SQLITE_ROW} -ifcapable !autoreset { - # If SQLITE_OMIT_AUTORESET is defined, then the statement must be - # reset() before it can be passed to step() again. - do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} - do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} -} do_test capi3c-11.11 { sqlite3_step $STMT } {SQLITE_DONE} -do_test capi3c-11.12 { - sqlite3_step $STMT - sqlite3_step $STMT -} {SQLITE_ROW} +ifcapable api_armor { + do_test capi3c-11.12armor { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_MISUSE} +} else { + do_test capi3c-11.12 { + sqlite3_step $STMT + sqlite3_step $STMT + } {SQLITE_ROW} +} do_test capi3c-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} do_test capi3c-11.14 { execsql { Index: test/intpkey.test ================================================================== --- test/intpkey.test +++ test/intpkey.test @@ -294,11 +294,11 @@ } {5 hello world 11 hello world 5} do_test intpkey-3.8 { count { SELECT * FROM t1 WHERE c=='world' AND a>7; } -} {11 hello world 4} +} {11 hello world 3} do_test intpkey-3.9 { count { SELECT * FROM t1 WHERE 71 || $MEMORY_MANAGEMENT==0)*1024] } } Index: test/mutex1.test ================================================================== --- test/mutex1.test +++ test/mutex1.test @@ -95,11 +95,11 @@ # # * Serialized mode, # * Multi-threaded mode, # * Single-threaded mode. # -ifcapable threadsafe&&shared_cache { +ifcapable threadsafe1&&shared_cache { set enable_shared_cache [sqlite3_enable_shared_cache 1] foreach {mode mutexes} { singlethread {} multithread { fast static_app1 static_app2 static_app3 Index: test/releasetest.tcl ================================================================== --- test/releasetest.tcl +++ test/releasetest.tcl @@ -172,28 +172,51 @@ } "Locking-Style" { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } - "OS-X" { + "Apple" { -O1 # Avoid a compiler bug in gcc 4.2.1 build 5658 - -DSQLITE_OMIT_LOAD_EXTENSION=1 - -DSQLITE_DEFAULT_MEMSTATUS=0 - -DSQLITE_THREADSAFE=2 - -DSQLITE_OS_UNIX=1 - -DSQLITE_ENABLE_JSON1=1 - -DSQLITE_ENABLE_LOCKING_STYLE=1 - -DUSE_PREAD=1 - -DSQLITE_ENABLE_RTREE=1 + -DHAVE_GMTIME_R=1 + -DHAVE_ISNAN=1 + -DHAVE_LOCALTIME_R=1 + -DHAVE_PREAD=1 + -DHAVE_PWRITE=1 + -DHAVE_USLEEP=1 + -DHAVE_USLEEP=1 + -DHAVE_UTIME=1 + -DSQLITE_DEFAULT_CACHE_SIZE=1000 + -DSQLITE_DEFAULT_CKPTFULLFSYNC=1 + -DSQLITE_DEFAULT_MEMSTATUS=1 + -DSQLITE_DEFAULT_PAGE_SIZE=1024 + -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1 + -DSQLITE_ENABLE_API_ARMOR=1 + -DSQLITE_ENABLE_AUTO_PROFILE=1 + -DSQLITE_ENABLE_FLOCKTIMEOUT=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 - -DSQLITE_DEFAULT_CACHE_SIZE=1000 + -DSQLITE_ENABLE_FTS3_TOKENIZER=1 + if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1 + -DSQLITE_ENABLE_PERSIST_WAL=1 + -DSQLITE_ENABLE_PURGEABLE_PCACHE=1 + -DSQLITE_ENABLE_RTREE=1 + -DSQLITE_ENABLE_SNAPSHOT=1 + # -DSQLITE_ENABLE_SQLLOG=1 + -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 -DSQLITE_MAX_LENGTH=2147483645 -DSQLITE_MAX_VARIABLE_NUMBER=500000 - -DSQLITE_DEBUG=1 + # -DSQLITE_MEMDEBUG=1 + -DSQLITE_NO_SYNC=1 + -DSQLITE_OMIT_AUTORESET=1 + -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_PREFER_PROXY_LOCKING=1 - -DSQLITE_ENABLE_API_ARMOR=1 + -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 + -DSQLITE_THREADSAFE=2 + -DSQLITE_USE_URI=1 + -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1 + -DUSE_GUARDED_FD=1 + -DUSE_PREAD=1 --enable-json1 --enable-fts5 } "Extra-Robustness" { -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1 -DSQLITE_MAX_ATTACHED=62 @@ -246,10 +269,11 @@ "Update-Delete-Limit" test "Extra-Robustness" test "Device-Two" test "No-lookaside" test "Devkit" test + "Apple" test "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} "Device-One" fulltest "Default" "threadtest fulltest" "Valgrind" valgrindtest } @@ -262,16 +286,16 @@ "Default" "threadtest fulltest" } Darwin-i386 { "Locking-Style" "mptest test" "Have-Not" test - "OS-X" "threadtest fulltest" + "Apple" "threadtest fulltest" } Darwin-x86_64 { "Locking-Style" "mptest test" "Have-Not" test - "OS-X" "threadtest fulltest" + "Apple" "threadtest fulltest" } "Windows NT-intel" { "Have-Not" test "Default" "mptest fulltestonly" } @@ -586,17 +610,27 @@ set makeOpts "" set cflags [expr {$::MSVC ? "-Zi" : "-g"}] set opts "" set title ${name}($testtarget) set configOpts $::WITHTCL + set skip 0 regsub -all {#[^\n]*\n} $config \n config foreach arg $config { + if {$skip} { + set skip 0 + continue + } if {[regexp {^-[UD]} $arg]} { lappend opts $arg } elseif {[regexp {^[A-Z]+=} $arg]} { lappend testtarget $arg + } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} { + # Arguments of the form 'if:os=="Linux"' will cause the subsequent + # argument to be skipped if the $tcl_platform(os) is not "Linux", for + # example... + set skip [expr !(\$::tcl_platform($key)$tail)] } elseif {[regexp {^--(enable|disable)-} $arg]} { if {$::MSVC} { if {$arg eq "--disable-amalgamation"} { lappend makeOpts USE_AMALGAMATION=0 continue Index: test/wal2.test ================================================================== --- test/wal2.test +++ test/wal2.test @@ -1229,10 +1229,13 @@ foreach {tn sql reslist} { 1 { } {10 0 4 0 6 0} 2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2} 3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0} } { + ifcapable default_ckptfullfsync { + if {[string trim $sql]==""} continue + } faultsim_delete_and_reopen execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} execsql $sql do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {} Index: test/wal3.test ================================================================== --- test/wal3.test +++ test/wal3.test @@ -221,10 +221,11 @@ T filter {} T script sync_counter sqlite3 db test.db -vfs T execsql "PRAGMA synchronous = $syncmode" + execsql "PRAGMA checkpoint_fullfsync = 0" execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE filler(a,b,c); } set ::syncs [list] T filter xSync Index: tool/lemon.c ================================================================== --- tool/lemon.c +++ tool/lemon.c @@ -288,10 +288,11 @@ const char *code; /* The code executed when this rule is reduced */ const char *codePrefix; /* Setup code before code[] above */ const char *codeSuffix; /* Breakdown code after code[] above */ struct symbol *precsym; /* Precedence symbol for this rule */ int index; /* An index number for this rule */ + int iRule; /* Rule number as used in the generated tables */ Boolean canReduce; /* True if this rule is ever reduced */ struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *next; /* Next rule in the global list */ }; @@ -370,10 +371,11 @@ ** static variables. Fields in the following structure can be thought ** of as begin global variables in the program.) */ struct lemon { struct state **sorted; /* Table of states sorted by state number */ struct rule *rule; /* List of all rules */ + struct rule *startRule; /* First rule */ int nstate; /* Number of states */ int nxstate; /* nstate with tail degenerate states removed */ int nrule; /* Number of rules */ int nsymbol; /* Number of terminal and nonterminal symbols */ int nterminal; /* Number of terminal symbols */ @@ -856,16 +858,16 @@ sp = Symbol_find(lemp->start); if( sp==0 ){ ErrorMsg(lemp->filename,0, "The specified start symbol \"%s\" is not \ in a nonterminal of the grammar. \"%s\" will be used as the start \ -symbol instead.",lemp->start,lemp->rule->lhs->name); +symbol instead.",lemp->start,lemp->startRule->lhs->name); lemp->errorcnt++; - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } }else{ - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } /* Make sure the start symbol doesn't occur on the right-hand side of ** any rule. Report an error if it does. (YACC would generate a new ** start symbol in this case.) */ @@ -1115,13 +1117,13 @@ } /* Add the accepting token */ if( lemp->start ){ sp = Symbol_find(lemp->start); - if( sp==0 ) sp = lemp->rule->lhs; + if( sp==0 ) sp = lemp->startRule->lhs; }else{ - sp = lemp->rule->lhs; + sp = lemp->startRule->lhs; } /* Add to the first state (which is always the starting state of the ** finite state machine) an action to ACCEPT if the lookahead is the ** start nonterminal. */ Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); @@ -1494,10 +1496,58 @@ if( user_templatename==0 ){ memory_error(); } lemon_strcpy(user_templatename, z); } + +/* Merge together to lists of rules order by rule.iRule */ +static struct rule *Rule_merge(struct rule *pA, struct rule *pB){ + struct rule *pFirst = 0; + struct rule **ppPrev = &pFirst; + while( pA && pB ){ + if( pA->iRuleiRule ){ + *ppPrev = pA; + ppPrev = &pA->next; + pA = pA->next; + }else{ + *ppPrev = pB; + ppPrev = &pB->next; + pB = pB->next; + } + } + if( pA ){ + *ppPrev = pA; + }else{ + *ppPrev = pB; + } + return pFirst; +} + +/* +** Sort a list of rules in order of increasing iRule value +*/ +static struct rule *Rule_sort(struct rule *rp){ + int i; + struct rule *pNext; + struct rule *x[32]; + memset(x, 0, sizeof(x)); + while( rp ){ + pNext = rp->next; + rp->next = 0; + for(i=0; itype==MULTITERMINAL ){ i--; } assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); lem.nsymbol = i - 1; for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); lem.nterminal = i; + + /* Assign sequential rule numbers */ + for(i=0, rp=lem.rule; rp; rp=rp->next){ + rp->iRule = rp->code ? i++ : -1; + } + for(rp=lem.rule; rp; rp=rp->next){ + if( rp->iRule<0 ) rp->iRule = i++; + } + lem.startRule = lem.rule; + lem.rule = Rule_sort(lem.rule); /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); }else{ @@ -3052,17 +3113,17 @@ fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum); break; } case REDUCE: { struct rule *rp = ap->x.rp; - fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index); + fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->iRule); RulePrint(fp, rp, -1); break; } case SHIFTREDUCE: { struct rule *rp = ap->x.rp; - fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index); + fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule); RulePrint(fp, rp, -1); break; } case ACCEPT: fprintf(fp,"%*s accept",indent,ap->sp->name); @@ -3071,11 +3132,11 @@ fprintf(fp,"%*s error",indent,ap->sp->name); break; case SRCONFLICT: case RRCONFLICT: fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", - indent,ap->sp->name,ap->x.rp->index); + indent,ap->sp->name,ap->x.rp->iRule); break; case SSCONFLICT: fprintf(fp,"%*s shift %-7d ** Parsing conflict **", indent,ap->sp->name,ap->x.stp->statenum); break; @@ -3088,11 +3149,11 @@ } break; case RD_RESOLVED: if( showPrecedenceConflict ){ fprintf(fp,"%*s reduce %-7d -- dropped by precedence", - indent,ap->sp->name,ap->x.rp->index); + indent,ap->sp->name,ap->x.rp->iRule); }else{ result = 0; } break; case NOT_USED: @@ -3119,11 +3180,11 @@ if( lemp->basisflag ) cfp=stp->bp; else cfp=stp->cfp; while( cfp ){ char buf[20]; if( cfp->dot==cfp->rp->nrhs ){ - lemon_sprintf(buf,"(%d)",cfp->rp->index); + lemon_sprintf(buf,"(%d)",cfp->rp->iRule); fprintf(fp," %5s ",buf); }else{ fprintf(fp," "); } ConfigPrint(fp,cfp); @@ -3220,12 +3281,12 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap) { int act; switch( ap->type ){ case SHIFT: act = ap->x.stp->statenum; break; - case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break; - case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break; + case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate; break; + case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break; case ERROR: act = lemp->nstate + lemp->nrule*2; break; case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; default: act = -1; break; } return act; @@ -4239,11 +4300,11 @@ /* Generate a table containing a text string that describes every ** rule in the rule set of the grammar. This information is used ** when tracing REDUCE actions. */ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ - assert( rp->index==i ); + assert( rp->iRule==i ); fprintf(out," /* %3d */ \"", i); writeRuleText(out, rp); fprintf(out,"\",\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); @@ -4335,18 +4396,18 @@ /* First output rules other than the default: rule */ for(rp=lemp->rule; rp; rp=rp->next){ struct rule *rp2; /* Other rules with the same action */ if( rp->code==0 ) continue; if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ - fprintf(out," case %d: /* ", rp->index); + fprintf(out," case %d: /* ", rp->iRule); writeRuleText(out, rp); fprintf(out, " */\n"); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next){ if( rp2->code==rp->code ){ - fprintf(out," case %d: /* ", rp2->index); + fprintf(out," case %d: /* ", rp2->iRule); writeRuleText(out, rp2); - fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++; + fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; rp2->code = 0; } } emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; @@ -4356,13 +4417,13 @@ ** empty actions. */ fprintf(out," default:\n"); lineno++; for(rp=lemp->rule; rp; rp=rp->next){ if( rp->code==0 ) continue; assert( rp->code[0]=='\n' && rp->code[1]==0 ); - fprintf(out," /* (%d) ", rp->index); + fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); - fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++; + fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; } fprintf(out," break;\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes if a parse fails */ Index: tool/lempar.c ================================================================== --- tool/lempar.c +++ tool/lempar.c @@ -416,11 +416,11 @@ /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ -static int yy_find_shift_action( +static unsigned int yy_find_shift_action( yyParser *pParser, /* The parser */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; @@ -604,21 +604,20 @@ ** Perform a reduce action and the shift that must immediately ** follow the reduce. */ static void yy_reduce( yyParser *yypParser, /* The parser */ - int yyruleno /* Number of the rule by which to reduce */ + unsigned int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 - && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, yyRuleName[yyruleno], yymsp[-yysize].stateno); } #endif /* NDEBUG */ @@ -659,11 +658,11 @@ */ /********** Begin reduce actions **********************************************/ %% /********** End reduce actions ************************************************/ }; - assert( yyruleno>=0 && yyrulenoYY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; @@ -763,11 +762,11 @@ int yymajor, /* The major token code number */ ParseTOKENTYPE yyminor /* The value for the token */ ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - int yyact; /* The parser action. */ + unsigned int yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ Index: tool/sqldiff.c ================================================================== --- tool/sqldiff.c +++ tool/sqldiff.c @@ -1755,12 +1755,14 @@ char *zSql; sqlite3_stmt *pStmt; char *zTab = 0; FILE *out = stdout; void (*xDiff)(const char*,FILE*) = diff_one_table; +#ifndef SQLITE_OMIT_LOAD_EXTENSION int nExt = 0; char **azExt = 0; +#endif int useTransaction = 0; int neverUseTransaction = 0; g.zArgv0 = argv[0]; sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); @@ -1839,12 +1841,12 @@ rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg); if( rc || zErrMsg ){ cmdlineError("error loading %s: %s", azExt[i], zErrMsg); } } -#endif free(azExt); +#endif zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2); rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); if( rc || zErrMsg ){ cmdlineError("cannot attach database \"%s\"", zDb2); }