Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -1317,10 +1317,13 @@ $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ -DBUILD_sqlite -I$(TCLINCDIR) \ $(TESTFIXTURE_SRC) \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +extensiontest: testfixture.exe testloadext.dll + .\testfixture.exe $(TOP)\test\loadext.test + fulltest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test soaktest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test -soak=1 @@ -1343,10 +1346,16 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +testloadext.lo: $(TOP)\src\test_loadext.c + $(LTCOMPILE) -c $(TOP)\src\test_loadext.c + +testloadext.dll: testloadext.lo + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo + showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showdb.c $(SQLITE3C) wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) @@ -1361,18 +1370,20 @@ del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib del /Q *.cod *.da *.bb *.bbg gmon.out del /Q sqlite3.h opcodes.c opcodes.h del /Q lemon.exe lempar.c parse.* del /Q mkkeywordhash.exe keywordhash.h + del /Q notasharedlib.* -rmdir /Q/S .deps -rmdir /Q/S .libs -rmdir /Q/S quota2a -rmdir /Q/S quota2b -rmdir /Q/S quota2c -rmdir /Q/S tsrc del /Q .target_source del /Q tclsqlite3.exe tclsqlite3.exp + del /Q testloadext.dll testloadext.exp del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c sqlite3-*.c del /Q sqlite3rc.h del /Q shell.c sqlite3ext.h Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -75,12 +75,12 @@ len = sqlite3GetToken(zCsr, &token); } while( token==TK_SPACE ); assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } /* @@ -128,11 +128,11 @@ zParent = sqlite3DbStrNDup(db, (const char *)z, n); if( zParent==0 ) break; sqlite3Dequote(zParent); if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", - (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew ); sqlite3DbFree(db, zOutput); zOutput = zOut; zInput = &z[n]; } @@ -214,12 +214,12 @@ } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } #endif /* !SQLITE_OMIT_TRIGGER */ @@ -602,11 +602,12 @@ int r2 = sqlite3GetTempReg(pParse); int j1; sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -611,11 +611,12 @@ ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; if( !bNoSeek ){ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); - VdbeCoverage(v); + VdbeCoverageIf(v, opSeek==OP_NotExists); + VdbeCoverageIf(v, opSeek==OP_NotFound); } /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){ @@ -654,11 +655,12 @@ ** the cursor or of already deleted the row that the cursor was ** pointing to. */ if( addrStartpFrom && nIncr==1 ){ sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); } sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -302,29 +302,20 @@ sqlite3 *db = pParse->db; assert( v ); for(p = pParse->pAinc; p; p = p->pNext){ Db *pDb = &db->aDb[p->iDb]; - int j1, j2, j3, j4, j5; + int j1; int iRec; int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); - j2 = sqlite3VdbeAddOp0(v, OP_Rewind); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); - j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Next, 0, j3); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j2); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - j5 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, j4); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeJumpHere(v, j5); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); sqlite3ReleaseTempReg(pParse, iRec); @@ -684,22 +675,22 @@ ** goto L ** M: ... */ int regRec; /* Register to hold packed record */ int regTempRowid; /* Register to hold temp table ROWID */ - int addrTop; /* Label "L" */ + int addrL; /* Label "L" */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); + addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - sqlite3VdbeJumpHere(v, addrTop); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL); + sqlite3VdbeJumpHere(v, addrL); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ /* This is the case if the data for the INSERT is coming from a VALUES @@ -1273,10 +1264,11 @@ if( isUpdate ){ /* pkChng!=0 does not mean that the rowid has change, only that ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } /* If the response to a rowid conflict is REPLACE but the response ** to some other UNIQUE constraint is FAIL or IGNORE, then we need @@ -1444,10 +1436,11 @@ sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); /* Conflict only if the rowid of the existing index entry ** is different from old-rowid */ if( isUpdate ){ sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } }else{ int x; /* Extract the PRIMARY KEY from the end of the index entry and @@ -1479,11 +1472,14 @@ addrJump = addrUniqueOk; op = OP_Eq; } sqlite3VdbeAddOp4(v, op, regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ - ); VdbeCoverage(v); + ); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + VdbeCoverageIf(v, op==OP_Eq); + VdbeCoverageIf(v, op==OP_Ne); } } } } Index: src/mem5.c ================================================================== --- src/mem5.c +++ src/mem5.c @@ -272,10 +272,16 @@ mem5.totalExcess += iFullSz - nByte; mem5.currentCount++; mem5.currentOut += iFullSz; if( mem5.maxCountop = (u8)Y; - Z->pPrior = X; + Select *pRhs = Z; + if( pRhs && pRhs->pPrior ){ + SrcList *pFrom; + Token x; + x.n = 0; + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); + } + if( pRhs ){ + pRhs->op = (u8)Y; + pRhs->pPrior = X; if( Y!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, X); } - A = Z; + A = pRhs; } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP;} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1940,10 +1940,11 @@ addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); } Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -816,18 +816,20 @@ assert( pSO ); nKey = pSO->nExpr; r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempRange(pParse, nKey+2); r3 = r2+nKey+1; - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); if( eDest==SRT_DistQueue ){ /* If the destination is DistQueue, then cursor (iParm+1) is open ** on a second ephemeral index that holds all values every previously - ** added to the queue. Only add this new value if it has never before - ** been added */ - addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0); + ** added to the queue. */ + addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, + regResult, nResultCol); VdbeCoverage(v); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); + if( eDest==SRT_DistQueue ){ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } for(i=0; iin); } if( c=='\n' ){ p->nLine++; - if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; + if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; } p->cTerm = c; } if( p->z ) p->z[p->n] = 0; return p->z; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -10,11 +10,10 @@ ** ************************************************************************* ** Internal interface definitions for SQLite. ** */ -#include "sqlite3.h" #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on POSIX if the @@ -45,10 +44,15 @@ # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif + +/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear +** first in QNX. +*/ +#include "sqlite3.h" /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ @@ -1312,14 +1316,20 @@ #define SQLITE_AFF_MASK 0x67 /* ** Additional bit values that can be ORed with an affinity without ** changing the affinity. +** +** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. +** It causes an assert() to fire if either operand to a comparison +** operator is NULL. It is added to certain comparison operators to +** prove that the operands are always NOT NULL. */ #define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ +#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in ** the database schema. ** @@ -2346,11 +2356,10 @@ int rc; /* Return code from execution */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ - u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ Index: src/test_loadext.c ================================================================== --- src/test_loadext.c +++ src/test_loadext.c @@ -89,10 +89,13 @@ } /* ** Extension load function. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif int testloadext_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ @@ -107,10 +110,13 @@ } /* ** Another extension entry point. This one always fails. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif int testbrokenext_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -432,11 +432,11 @@ /* Top of the update loop */ if( okOnePass ){ if( aToOpen[iDataCur-iBaseCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); - VdbeCoverage(v); + VdbeCoverageNeverTaken(v); } labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); VdbeCoverage(v); }else if( pPk ){ @@ -575,15 +575,14 @@ /* Delete the index entries associated with the current record. */ if( bReplace || chngKey ){ if( pPk ){ j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); - VdbeCoverage(v); }else{ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); - VdbeCoverage(v); } + VdbeCoverageNeverTaken(v); } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); /* If changing the record number, delete the old record. */ if( hasFK || chngKey || pPk!=0 ){ Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -106,19 +106,35 @@ #else # define UPDATE_MAX_BLOBSIZE(P) #endif /* -** Invoke the VDBE coverage callback, if defined +** Invoke the VDBE coverage callback, if that callback is defined. This +** feature is used for test suite validation only and does not appear an +** production builds. +** +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. */ #if !defined(SQLITE_VDBE_COVERAGE) # define VdbeBranchTaken(I,M) #else -# define VdbeBranchTaken(I,M) \ - if( sqlite3GlobalConfig.xVdbeBranch!=0 ){ \ - sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, \ - pOp->iSrcLine,(I),(M)); } +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } + } #endif /* ** Convert the given register into a string if it isn't one ** already. Return non-zero if a malloc() fails. @@ -474,11 +490,10 @@ Mem *pOut = 0; /* Output operand */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ - int origPc; /* Program counter at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); @@ -536,11 +551,10 @@ #endif for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pcnOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE - origPc = pc; start = sqlite3Hwtime(); #endif nVmStep++; pOp = &aOp[pc]; @@ -1157,11 +1171,11 @@ ** Synopsis: output=r[P1@P2] ** ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the r[P1]..r[P1+P2-1] values as +** structure to provide access to the r(P1)..r(P1+P2-1) values as ** the result row. */ case OP_ResultRow: { Mem *pMem; int i; @@ -1889,10 +1903,11 @@ ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); if( (flags1&MEM_Null)!=0 && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ res = 0; /* Results are equal */ @@ -1907,11 +1922,11 @@ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); }else{ - VdbeBranchTaken((pOp->p5 & SQLITE_JUMPIFNULL)?2:3,4); + VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ pc = pOp->p2-1; } } break; @@ -1944,11 +1959,11 @@ memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else{ - VdbeBranchTaken(res!=0, 4); + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res ){ pc = pOp->p2-1; } } /* Undo any changes made by applyAffinity() to the input registers. */ @@ -4831,11 +4846,10 @@ case OP_Clear: { int nChange; nChange = 0; assert( p->readOnly==0 ); - assert( pOp->p1!=1 ); assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); if( pOp->p3 ){ @@ -6257,14 +6271,10 @@ #ifdef VDBE_PROFILE { u64 elapsed = sqlite3Hwtime() - start; pOp->cycles += elapsed; pOp->cnt++; -#if 0 - fprintf(stdout, "%10llu ", elapsed); - sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]); -#endif } #endif /* The following code adds nothing to the actual functionality ** of the program. It is only here for testing and debugging. Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -63,11 +63,11 @@ } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE - int cnt; /* Number of times this instruction was executed */ + u32 cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif #ifdef SQLITE_VDBE_COVERAGE int iSrcLine; /* Source-code line that generated this opcode */ #endif @@ -239,16 +239,41 @@ # define VdbeComment(X) # define VdbeNoopComment(X) # define VdbeModuleComment(X) #endif -/* Set the Opcode.iSrcline field of the previous opcode */ +/* +** The VdbeCoverage macros are used to set a coverage testing point +** for VDBE branch instructions. The coverage testing points are line +** numbers in the sqlite3.c source file. VDBE branch coverage testing +** only works with an amalagmation build. That's ok since a VDBE branch +** coverage build designed for testing the test suite only. No application +** should ever ship with VDBE branch coverage measuring turned on. +** +** VdbeCoverage(v) // Mark the previously coded instruction +** // as a branch +** +** VdbeCoverageIf(v, conditional) // Mark previous if conditional true +** +** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken +** +** VdbeCoverageNeverTaken(v) // Previous branch is never taken +** +** Every VDBE branch operation must be tagged with one of the macros above. +** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and +** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() +** routine in vdbe.c, alerting the developer to the missed tag. +*/ #ifdef SQLITE_VDBE_COVERAGE void sqlite3VdbeSetLineNumber(Vdbe*,int); # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) +# define VdbeCoverageAlwaysTaken(v) +# define VdbeCoverageNeverTaken(v) #endif #endif Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -2578,15 +2578,17 @@ pc = c; } if( pc!='\n' ) fprintf(out, "\n"); } for(i=0; inOp; i++){ - fprintf(out, "%6d %10lld %8lld ", + char zHdr[100]; + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", p->aOp[i].cnt, p->aOp[i].cycles, p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 ); + fprintf(out, "%s", zHdr); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); } } Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -2851,17 +2851,18 @@ ** equality comparison against the ROWID field. Or ** we reference multiple rows using a "rowid IN (...)" ** construct. */ assert( pLoop->u.btree.nEq==1 ); - iReleaseReg = sqlite3GetTempReg(pParse); pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); + iReleaseReg = ++pParse->nMem; iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); + if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); @@ -2946,11 +2947,11 @@ pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Lt); @@ -3179,11 +3180,11 @@ disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ }else{ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); @@ -3527,11 +3528,10 @@ assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } - sqlite3ReleaseTempReg(pParse, iReleaseReg); return pLevel->notReady; } #if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN) @@ -4899,13 +4899,16 @@ /* Mark off any other ORDER BY terms that reference pLoop */ if( isOrderDistinct ){ orderDistinctMask |= pLoop->maskSelf; for(i=0; ia[i].pExpr; - if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){ + mTerm = exprTableUsage(&pWInfo->sMaskSet,p); + if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; + if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } } } /* End the loop over all WhereLoops from outer-most down to inner-most */ @@ -5524,26 +5527,10 @@ exprAnalyzeAll(pTabList, &pWInfo->sWC); if( db->mallocFailed ){ goto whereBeginError; } - /* If the ORDER BY (or GROUP BY) clause contains references to general - ** expressions, then we won't be able to satisfy it using indices, so - ** go ahead and disable it now. - */ - if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ){ - pWInfo->pOrderBy = pOrderBy = 0; - break; - }else if( pExpr->iColumn<0 ){ - break; - } - } - } - if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ Index: test/loadext.test ================================================================== --- test/loadext.test +++ test/loadext.test @@ -63,10 +63,16 @@ if {$::tcl_platform(os) eq "Darwin"} { set dlerror_nosuchfile {dlopen(%s, 10): image not found} set dlerror_notadll {dlopen(%1$s, 10): no suitable image found.*} set dlerror_nosymbol {dlsym(XXX, %2$s): symbol not found} } + +if {$::tcl_platform(platform) eq "windows"} { + set dlerror_nosuchfile {The specified module could not be found.*} + set dlerror_notadll {%%1 is not a valid Win32 application.*} + set dlerror_nosymbol {The specified procedure could not be found.*} +} # Make sure the test extension actually exists. If it does not # exist, try to create it. If unable to create it, then skip this # test file. # @@ -165,11 +171,11 @@ } msg] if {$::tcl_platform(os) eq "Darwin"} { regsub {0x[1234567890abcdefABCDEF]*} $msg XXX msg } list $rc $msg -} [list 1 [format $dlerror_nosymbol $testextension icecream]] +} /[list 1 [format $dlerror_nosymbol $testextension icecream]]/ # Try to load an extension for which the entry point fails (returns non-zero) # do_test loadext-2.4 { set rc [catch { @@ -265,12 +271,19 @@ do_malloc_test loadext-5 -tclprep { sqlite3_reset_auto_extension } -tclbody { if {[autoinstall_test_functions]==7} {error "out of memory"} } -do_malloc_test loadext-6 -tclbody { - db enable_load_extension 1 - sqlite3_load_extension db $::testextension testloadext_init + +# On Windows, this malloc test must be skipped because the winDlOpen +# function itself can fail due to "out of memory" conditions. +# +if {$::tcl_platform(platform) ne "windows"} { + do_malloc_test loadext-6 -tclbody { + db enable_load_extension 1 + sqlite3_load_extension db $::testextension testloadext_init + } } + autoinstall_test_functions finish_test Index: test/select4.test ================================================================== --- test/select4.test +++ test/select4.test @@ -821,7 +821,43 @@ INSERT INTO t13 VALUES(4,2); CREATE INDEX t13ab ON t13(a,b); SELECT DISTINCT b from t13 WHERE a IN (1,2,3); } } {1 2} + +# 2014-02-18: Make sure compound SELECTs work with VALUES clauses +# +do_execsql_test select4-14.1 { + CREATE TABLE t14(a,b,c); + INSERT INTO t14 VALUES(1,2,3),(4,5,6); + SELECT * FROM t14 INTERSECT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3} +do_execsql_test select4-14.2 { + SELECT * FROM t14 INTERSECT VALUES(1,2,3); +} {1 2 3} +do_execsql_test select4-14.3 { + SELECT * FROM t14 + UNION VALUES(3,2,1),(2,3,1),(1,2,3),(7,8,9),(4,5,6) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 2 3 1 3 2 1 4 5 6 7 8 9} +do_execsql_test select4-14.4 { + SELECT * FROM t14 + UNION VALUES(3,2,1) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 3 2 1 4 5 6} +do_execsql_test select4-14.5 { + SELECT * FROM t14 EXCEPT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {4 5 6} +do_execsql_test select4-14.6 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) +} {4 5 6} +do_execsql_test select4-14.7 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) EXCEPT VALUES(4,5,6) +} {} +do_execsql_test select4-14.8 { + SELECT * FROM t14 EXCEPT VALUES('a','b','c') EXCEPT VALUES(4,5,6) +} {1 2 3} +do_execsql_test select4-14.9 { + SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3} finish_test Index: test/shell5.test ================================================================== --- test/shell5.test +++ test/shell5.test @@ -282,9 +282,28 @@ .import shell5.csv t1 } sqlite3 db test.db db eval {SELECT hex(c) FROM t1 ORDER BY rowid} } {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033} + +# Blank last column with \r\n line endings. +do_test shell5-1.11 { + set out [open shell5.csv w] + fconfigure $out -translation binary + puts $out "column1,column2,column3\r" + puts $out "a,b, \r" + puts $out "x,y,\r" + puts $out "p,q,r\r" + close $out + catch {db close} + forcedelete test.db + catchcmd test.db {.mode csv +.import shell5.csv t1 + } + sqlite3 db test.db + db eval {SELECT *, '|' FROM t1} +} {a b { } | x y {} | p q r |} + db close finish_test ADDED test/tkt-8c63ff0ec.test Index: test/tkt-8c63ff0ec.test ================================================================== --- /dev/null +++ test/tkt-8c63ff0ec.test @@ -0,0 +1,48 @@ +# 2014-02-25 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases to show that ticket [8c63ff0eca81a9132d8d67b31cd6ae9712a2cc6f] +# "Incorrect query result on a UNION ALL" which was caused by using the same +# temporary register in concurrent co-routines, as been fixed. +# + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix tkt-8c63ff0ec + +do_execsql_test 1.1 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e); + INSERT INTO t1 VALUES(1,20,30,40,50),(3,60,70,80,90); + CREATE TABLE t2(x INTEGER PRIMARY KEY); + INSERT INTO t2 VALUES(2); + CREATE TABLE t3(z); + INSERT INTO t3 VALUES(2),(2),(2),(2); + + SELECT a, b+c FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 50 2 5 2 5 2 5 2 5 3 130} +do_execsql_test 1.2 { + SELECT a, b+c+d FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 90 2 5 2 5 2 5 2 5 3 210} +do_execsql_test 1.3 { + SELECT a, b+c+d+e FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 140 2 5 2 5 2 5 2 5 3 300} + +finish_test Index: test/walro.test ================================================================== --- test/walro.test +++ test/walro.test @@ -30,21 +30,22 @@ finish_test return } do_multiclient_test tn { - # Do not run tests with the connections in the same process. - # - if {$tn==2} continue # Close all connections and delete the database. # code1 { db close } code2 { db2 close } code3 { db3 close } forcedelete test.db forcedelete walro + + # Do not run tests with the connections in the same process. + # + if {$tn==2} continue foreach c {code1 code2 code3} { $c { sqlite3_shutdown sqlite3_config_uri 1 @@ -230,21 +231,22 @@ #----------------------------------------------------------------------- # Test cases 2.* check that a read-only connection may read the # database file while a checkpoint operation is ongoing. # do_multiclient_test tn { - # Do not run tests with the connections in the same process. - # - if {$tn==2} continue # Close all connections and delete the database. # code1 { db close } code2 { db2 close } code3 { db3 close } forcedelete test.db forcedelete walro + + # Do not run tests with the connections in the same process. + # + if {$tn==2} continue foreach c {code1 code2 code3} { $c { sqlite3_shutdown sqlite3_config_uri 1 Index: test/where2.test ================================================================== --- test/where2.test +++ test/where2.test @@ -118,10 +118,46 @@ do_test where2-2.3 { queryplan { SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(); } } {85 6 7396 7402 nosort t1 *} + +# Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26 +# Make sure "ORDER BY random" does not gets optimized out. +# +do_test where2-2.4 { + db eval { + CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1); + WITH RECURSIVE + cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50) + INSERT INTO x1 SELECT x, 1 FROM cnt; + CREATE TABLE x2(x INTEGER PRIMARY KEY); + INSERT INTO x2 VALUES(1); + } + set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()} + set out1 [db eval $sql] + set out2 [db eval $sql] + set out3 [db eval $sql] + expr {$out1!=$out2 && $out2!=$out3} +} {1} +do_execsql_test where2-2.5 { + -- random() is not optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); +} {/ random/} +do_execsql_test where2-2.5b { + -- random() is not optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); +} {/ SorterOpen /} +do_execsql_test where2-2.6 { + -- other constant functions are optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); +} {~/ abs/} +do_execsql_test where2-2.6b { + -- other constant functions are optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); +} {~/ SorterOpen /} + # Efficient handling of forward and reverse table scans. # do_test where2-3.1 { Index: tool/mksqlite3c.tcl ================================================================== --- tool/mksqlite3c.tcl +++ tool/mksqlite3c.tcl @@ -119,11 +119,10 @@ whereInt.h } { set available_hdr($hdr) 1 } set available_hdr(sqliteInt.h) 0 -set available_hdr(sqlite3.h) 0 # 78 stars used for comment formatting. set s78 \ {*****************************************************************************} @@ -227,11 +226,10 @@ # Process the source files. Process files containing commonly # used subroutines first in order to help the compiler find # inlining opportunities. # foreach file { - sqlite3.h sqliteInt.h global.c ctime.c status.c