Merge updates from trunk.

FossilOrigin-Name: 435ce3b3fc0cffb4d7e6f2694c3100066e19f9ed
This commit is contained in:
mistachkin
2013-09-24 19:07:48 +00:00
40 changed files with 1802 additions and 518 deletions
+1 -1
View File
@@ -347,7 +347,7 @@ static void statInit(
p->mxSample = mxSample;
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1);
p->current.anLt = &p->current.anEq[nColUp];
sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565;
/* Set up the Stat4Accum.a[] and aBest[] arrays */
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
+1 -1
View File
@@ -509,7 +509,7 @@ int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{
+4 -4
View File
@@ -294,8 +294,8 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
** Return the number of errors.
*/
static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
sqlite3 *db = sqlite3_context_db_handle(context);
if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
p->iJD = sqlite3StmtCurrentTime(context);
if( p->iJD>0 ){
p->validJD = 1;
return 0;
}else{
@@ -1078,8 +1078,8 @@ static void currentTimeFunc(
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
db = sqlite3_context_db_handle(context);
if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
iT = sqlite3StmtCurrentTime(context);
if( iT<=0 ) return;
t = iT/1000 - 10000*(sqlite3_int64)21086676;
#ifdef HAVE_GMTIME_R
pTm = gmtime_r(&t, &sNow);
+69 -49
View File
@@ -70,7 +70,7 @@ Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
if( pNew ){
pNew->pLeft = pExpr;
pNew->flags |= EP_Collate;
pNew->flags |= EP_Collate|EP_Skip;
pExpr = pNew;
}
}
@@ -85,13 +85,21 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
}
/*
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
** an expression.
** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
** or likelihood() function at the root of an expression.
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
pExpr = pExpr->pLeft;
}
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
pExpr = pExpr->pLeft;
}
}
return pExpr;
}
@@ -596,7 +604,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
const char *z;
if( pExpr==0 ) return;
assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
z = pExpr->u.zToken;
assert( z!=0 );
assert( z[0]!=0 );
@@ -666,12 +674,12 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
if( !ExprHasProperty(p, EP_TokenOnly) ){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( p->x.pList==0 || p->pRight==0 );
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
sqlite3DbFree(db, p->u.zToken);
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
@@ -731,16 +739,19 @@ static int exprStructSize(Expr *p){
static int dupedExprStructSize(Expr *p, int flags){
int nSize;
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==(flags&EXPRDUP_REDUCE) ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_FromJoin) );
assert( (p->flags2 & EP2_MallocedToken)==0 );
assert( (p->flags2 & EP2_Irreducible)==0 );
if( p->pLeft || p->pRight || p->x.pList ){
assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
assert( p->pRight==0 );
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
}
}
@@ -834,7 +845,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
@@ -854,7 +865,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, flags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
@@ -864,8 +875,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
*pzBuffer = zAlloc;
}
}else{
pNew->flags2 = 0;
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
if( !ExprHasProperty(p, EP_TokenOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
@@ -1175,7 +1185,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->u.i is 3 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->u.i = 0;
return WRC_Abort;
}
@@ -1606,7 +1616,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
}else{
testcase( pParse->nQueryLoop>0 );
pParse->nQueryLoop = 0;
if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
}
@@ -1675,7 +1685,7 @@ int sqlite3CodeSubselect(
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
testAddr = sqlite3CodeOnce(pParse);
}
@@ -1844,7 +1854,7 @@ int sqlite3CodeSubselect(
return 0;
}
rReg = dest.iSDParm;
ExprSetIrreducible(pExpr);
ExprSetVVAProperty(pExpr, EP_NoReduce);
break;
}
}
@@ -2316,6 +2326,16 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
}
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
/*
** Convert an expression node to a TK_REGISTER
*/
static void exprToRegister(Expr *p, int iReg){
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
ExprClearProperty(p, EP_Skip);
}
/*
** Generate code into the current Vdbe to evaluate the given
** expression. Attempt to store the results in register "target".
@@ -2615,7 +2635,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
testcase( op==TK_CONST_FUNC );
testcase( op==TK_FUNCTION );
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
@@ -2649,6 +2669,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
/* The UNLIKELY() function is a no-op. The result is the value
** of the first argument.
*/
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
assert( nFarg>=1 );
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
break;
}
if( pFarg ){
r1 = sqlite3GetTempRange(pParse, nFarg);
@@ -2846,9 +2874,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
** WHEN x=eN THEN rN ELSE y END
**
** X (if it exists) is in pExpr->pLeft.
** Y is in pExpr->pRight. The Y is also optional. If there is no
** ELSE clause and no other term matches, then the result of the
** exprssion is NULL.
** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
** odd. The Y is also optional. If the number of elements in x.pList
** is even, then Y is omitted and the "otherwise" result is NULL.
** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
**
** The result of the expression is the Ri for the first matching Ei,
@@ -2869,7 +2897,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert((pExpr->x.pList->nExpr % 2) == 0);
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
@@ -2879,9 +2906,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
cacheX = *pX;
testcase( pX->op==TK_COLUMN );
testcase( pX->op==TK_REGISTER );
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
exprToRegister(&cacheX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( regFree1==0 );
cacheX.op = TK_REGISTER;
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
@@ -2891,7 +2917,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
** purposes and possibly overwritten. */
regFree1 = 0;
}
for(i=0; i<nExpr; i=i+2){
for(i=0; i<nExpr-1; i=i+2){
sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
@@ -2909,9 +2935,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCachePop(pParse, 1);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( pExpr->pRight ){
if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pExpr->pRight, target);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse, 1);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
@@ -3023,9 +3049,7 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
pExpr->iTable = iMem;
pExpr->op2 = pExpr->op;
pExpr->op = TK_REGISTER;
exprToRegister(pExpr, iMem);
}
return inReg;
}
@@ -3155,7 +3179,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
@@ -3404,9 +3428,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
** but suboptimal, so we want to know about the situation to fix it.
** Hence the following assert: */
assert( r2==r1 );
pExpr->op2 = pExpr->op;
pExpr->op = TK_REGISTER;
pExpr->iTable = r2;
exprToRegister(pExpr, r2);
return WRC_Prune;
}
return WRC_Continue;
@@ -3504,9 +3526,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
exprX.op2 = exprX.op;
exprX.op = TK_REGISTER;
exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, &regFree1));
if( jumpIfTrue ){
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
}else{
@@ -3821,8 +3841,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( pA==0||pB==0 ){
return pB==pA ? 0 : 2;
}
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 2;
}
@@ -4036,7 +4056,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
struct SrcList_item *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
** that is in the FROM clause of the aggregate query.
@@ -4085,7 +4105,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** Convert the pExpr to be a TK_AGG_COLUMN referring to that
** pAggInfo->aCol[] entry.
*/
ExprSetIrreducible(pExpr);
ExprSetVVAProperty(pExpr, EP_NoReduce);
pExpr->pAggInfo = pAggInfo;
pExpr->op = TK_AGG_COLUMN;
pExpr->iAgg = (i16)k;
@@ -4131,8 +4151,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
*/
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(pExpr);
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pExpr, EP_NoReduce);
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
+18 -16
View File
@@ -418,14 +418,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
/*
** The COALESCE() and IFNULL() functions are implemented as VDBE code so
** that unused argument values do not have to be computed. However, we
** still need some kind of function implementation for this routines in
** the function table. That function implementation will never be called
** so it doesn't matter what the implementation is. We might as well use
** the "version()" function as a substitute.
** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
** as VDBE code so that unused argument values do not have to be computed.
** However, we still need some kind of function implementation for this
** routines in the function table. The noopFunc macro provides this.
** noopFunc will never be called so it doesn't matter what the implementation
** is. We might as well use the "version()" function as a substitute.
*/
#define ifnullFunc versionFunc /* Substitute function - never called */
#define noopFunc versionFunc /* Substitute function - never called */
/*
** Implementation of random(). Return a random integer.
@@ -544,9 +544,9 @@ struct compareInfo {
*/
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A) (*((*A)++))
# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
#else
# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
# define GlobUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
#endif
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
@@ -625,11 +625,11 @@ static int patternCompare(
}
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
if( noCase ){
GlogUpperToLower(c2);
GlogUpperToLower(c);
GlobUpperToLower(c2);
GlobUpperToLower(c);
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(&zString);
GlogUpperToLower(c2);
GlobUpperToLower(c2);
}
}else{
while( c2 != 0 && c2 != c ){
@@ -681,8 +681,8 @@ static int patternCompare(
}else{
c2 = sqlite3Utf8Read(&zString);
if( noCase ){
GlogUpperToLower(c);
GlogUpperToLower(c2);
GlobUpperToLower(c);
GlobUpperToLower(c2);
}
if( c!=c2 ){
return 0;
@@ -1798,9 +1798,11 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+1
View File
@@ -484,6 +484,7 @@ void sqlite3_free(void *p){
*/
void sqlite3DbFree(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( p==0 ) return;
if( db ){
if( db->pnBytesFreed ){
*db->pnBytesFreed += sqlite3DbMallocSize(db, p);
+81 -50
View File
@@ -108,6 +108,14 @@
# define winIsDirSep(a) (((a) == '/') || ((a) == '\\'))
#endif
/*
** This macro is used when a local variable is set to a value that is
** [sometimes] not used by the code (e.g. via conditional compilation).
*/
#ifndef UNUSED_VARIABLE_VALUE
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
#endif
/*
** Returns the string that should be used as the directory separator.
*/
@@ -358,7 +366,8 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void);
*/
#ifdef SQLITE_TEST
int sqlite3_os_type = 0;
#else
#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE)
static int sqlite3_os_type = 0;
#endif
@@ -673,10 +682,19 @@ static struct win_syscall {
#define osGetVersionExA ((BOOL(WINAPI*)( \
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
#else
{ "GetVersionExW", (SYSCALL)0, 0 },
#endif
#define osGetVersionExW ((BOOL(WINAPI*)( \
LPOSVERSIONINFOW))aSyscall[35].pCurrent)
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
SIZE_T))aSyscall[35].pCurrent)
SIZE_T))aSyscall[36].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
@@ -685,7 +703,7 @@ static struct win_syscall {
#endif
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
SIZE_T))aSyscall[36].pCurrent)
SIZE_T))aSyscall[37].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
@@ -693,21 +711,21 @@ static struct win_syscall {
{ "HeapDestroy", (SYSCALL)0, 0 },
#endif
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
{ "HeapFree", (SYSCALL)HeapFree, 0 },
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
SIZE_T))aSyscall[39].pCurrent)
SIZE_T))aSyscall[40].pCurrent)
{ "HeapSize", (SYSCALL)HeapSize, 0 },
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[40].pCurrent)
LPCVOID))aSyscall[41].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
@@ -716,7 +734,7 @@ static struct win_syscall {
#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[41].pCurrent)
LPCVOID))aSyscall[42].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
@@ -724,7 +742,7 @@ static struct win_syscall {
{ "LoadLibraryA", (SYSCALL)0, 0 },
#endif
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[43].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
!defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -733,7 +751,7 @@ static struct win_syscall {
{ "LoadLibraryW", (SYSCALL)0, 0 },
#endif
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[44].pCurrent)
#if !SQLITE_OS_WINRT
{ "LocalFree", (SYSCALL)LocalFree, 0 },
@@ -741,7 +759,7 @@ static struct win_syscall {
{ "LocalFree", (SYSCALL)0, 0 },
#endif
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[45].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "LockFile", (SYSCALL)LockFile, 0 },
@@ -751,7 +769,7 @@ static struct win_syscall {
#ifndef osLockFile
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[45].pCurrent)
DWORD))aSyscall[46].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -762,7 +780,7 @@ static struct win_syscall {
#ifndef osLockFileEx
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
LPOVERLAPPED))aSyscall[46].pCurrent)
LPOVERLAPPED))aSyscall[47].pCurrent)
#endif
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -772,26 +790,26 @@ static struct win_syscall {
#endif
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
SIZE_T))aSyscall[47].pCurrent)
SIZE_T))aSyscall[48].pCurrent)
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
int))aSyscall[48].pCurrent)
int))aSyscall[49].pCurrent)
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
LARGE_INTEGER*))aSyscall[49].pCurrent)
LARGE_INTEGER*))aSyscall[50].pCurrent)
{ "ReadFile", (SYSCALL)ReadFile, 0 },
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
LPOVERLAPPED))aSyscall[50].pCurrent)
LPOVERLAPPED))aSyscall[51].pCurrent)
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[52].pCurrent)
#if !SQLITE_OS_WINRT
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
@@ -800,7 +818,7 @@ static struct win_syscall {
#endif
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
DWORD))aSyscall[52].pCurrent)
DWORD))aSyscall[53].pCurrent)
#if !SQLITE_OS_WINRT
{ "Sleep", (SYSCALL)Sleep, 0 },
@@ -808,12 +826,12 @@ static struct win_syscall {
{ "Sleep", (SYSCALL)0, 0 },
#endif
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[54].pCurrent)
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
LPFILETIME))aSyscall[54].pCurrent)
LPFILETIME))aSyscall[55].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
@@ -823,7 +841,7 @@ static struct win_syscall {
#ifndef osUnlockFile
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[55].pCurrent)
DWORD))aSyscall[56].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -833,7 +851,7 @@ static struct win_syscall {
#endif
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
LPOVERLAPPED))aSyscall[56].pCurrent)
LPOVERLAPPED))aSyscall[57].pCurrent)
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
@@ -841,17 +859,17 @@ static struct win_syscall {
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
#endif
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[58].pCurrent)
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
LPCSTR,LPBOOL))aSyscall[58].pCurrent)
LPCSTR,LPBOOL))aSyscall[59].pCurrent)
{ "WriteFile", (SYSCALL)WriteFile, 0 },
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
LPOVERLAPPED))aSyscall[59].pCurrent)
LPOVERLAPPED))aSyscall[60].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
@@ -860,7 +878,7 @@ static struct win_syscall {
#endif
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
DWORD,DWORD))aSyscall[60].pCurrent)
DWORD,DWORD))aSyscall[61].pCurrent)
#if !SQLITE_OS_WINRT
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
@@ -869,7 +887,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[61].pCurrent)
DWORD))aSyscall[62].pCurrent)
#if SQLITE_OS_WINRT
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
@@ -878,7 +896,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
BOOL))aSyscall[62].pCurrent)
BOOL))aSyscall[63].pCurrent)
#if SQLITE_OS_WINRT
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
@@ -887,7 +905,7 @@ static struct win_syscall {
#endif
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
PLARGE_INTEGER,DWORD))aSyscall[64].pCurrent)
#if SQLITE_OS_WINRT
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -896,7 +914,7 @@ static struct win_syscall {
#endif
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[65].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
@@ -905,7 +923,7 @@ static struct win_syscall {
#endif
#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
SIZE_T))aSyscall[65].pCurrent)
SIZE_T))aSyscall[66].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateFile2", (SYSCALL)CreateFile2, 0 },
@@ -914,7 +932,7 @@ static struct win_syscall {
#endif
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[67].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
@@ -923,7 +941,7 @@ static struct win_syscall {
#endif
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
DWORD))aSyscall[67].pCurrent)
DWORD))aSyscall[68].pCurrent)
#if SQLITE_OS_WINRT
{ "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
@@ -931,7 +949,7 @@ static struct win_syscall {
{ "GetTickCount64", (SYSCALL)0, 0 },
#endif
#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[69].pCurrent)
#if SQLITE_OS_WINRT
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
@@ -940,7 +958,7 @@ static struct win_syscall {
#endif
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
LPSYSTEM_INFO))aSyscall[69].pCurrent)
LPSYSTEM_INFO))aSyscall[70].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
@@ -948,7 +966,7 @@ static struct win_syscall {
{ "OutputDebugStringA", (SYSCALL)0, 0 },
#endif
#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[71].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
@@ -956,11 +974,11 @@ static struct win_syscall {
{ "OutputDebugStringW", (SYSCALL)0, 0 },
#endif
#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[72].pCurrent)
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[73].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -969,7 +987,7 @@ static struct win_syscall {
#endif
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[74].pCurrent)
}; /* End of the overrideable system calls */
@@ -1125,6 +1143,10 @@ void sqlite3_win32_sleep(DWORD milliseconds){
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
#ifndef NTDDI_WIN8
# define NTDDI_WIN8 0x06020000
#endif
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
# define osIsNT() (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
@@ -1132,9 +1154,15 @@ void sqlite3_win32_sleep(DWORD milliseconds){
#else
static int osIsNT(void){
if( sqlite3_os_type==0 ){
#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
OSVERSIONINFOW sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExW(&sInfo);
#else
OSVERSIONINFOA sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExA(&sInfo);
#endif
sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return sqlite3_os_type==2;
@@ -1159,7 +1187,7 @@ static void *winMemMalloc(int nBytes){
assert( nBytes>=0 );
p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
if( !p ){
sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
nBytes, osGetLastError(), (void*)hHeap);
}
return p;
@@ -1180,7 +1208,7 @@ static void winMemFree(void *pPrior){
#endif
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
pPrior, osGetLastError(), (void*)hHeap);
}
}
@@ -1206,7 +1234,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
}
if( !p ){
sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
(void*)hHeap);
}
@@ -1230,7 +1258,7 @@ static int winMemSize(void *p){
if( !p ) return 0;
n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
if( n==(SIZE_T)-1 ){
sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
p, osGetLastError(), (void*)hHeap);
return 0;
}
@@ -1260,7 +1288,7 @@ static int winMemInit(void *pAppData){
SQLITE_WIN32_HEAP_MAX_SIZE);
if( !pWinMemData->hHeap ){
sqlite3_log(SQLITE_NOMEM,
"failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
"failed to HeapCreate (%lu), flags=%u, initSize=%u, maxSize=%u",
osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
return SQLITE_NOMEM;
@@ -1272,7 +1300,7 @@ static int winMemInit(void *pAppData){
pWinMemData->hHeap = osGetProcessHeap();
if( !pWinMemData->hHeap ){
sqlite3_log(SQLITE_NOMEM,
"failed to GetProcessHeap (%d)", osGetLastError());
"failed to GetProcessHeap (%lu)", osGetLastError());
return SQLITE_NOMEM;
}
pWinMemData->bOwned = FALSE;
@@ -1300,7 +1328,7 @@ static void winMemShutdown(void *pAppData){
#endif
if( pWinMemData->bOwned ){
if( !osHeapDestroy(pWinMemData->hHeap) ){
sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
osGetLastError(), (void*)pWinMemData->hHeap);
}
pWinMemData->bOwned = FALSE;
@@ -3185,7 +3213,6 @@ static int winDelete(sqlite3_vfs *,const char*,int);
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
winShmNode **pp;
winShmNode *p;
BOOL bRc;
assert( winShmMutexHeld() );
OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
osGetCurrentProcessId(), deleteFlag));
@@ -3195,12 +3222,14 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
int i;
if( p->mutex ) sqlite3_mutex_free(p->mutex);
for(i=0; i<p->nRegion; i++){
bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
bRc = osCloseHandle(p->aRegion[i].hMap);
OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
}
if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
SimulateIOErrorBenign(1);
@@ -3919,6 +3948,7 @@ static const sqlite3_io_methods winIoMethod = {
** sqlite3_vfs object.
*/
#if 0
/*
** Convert a filename from whatever the underlying operating system
** supports for filenames into UTF-8. Space to hold the result is
@@ -3937,6 +3967,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){
/* caller will handle out of memory */
return zConverted;
}
#endif
/*
** Convert a UTF-8 filename into whatever form the underlying
@@ -5154,7 +5185,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==74 );
assert( ArraySize(aSyscall)==75 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
+3 -2
View File
@@ -1081,12 +1081,13 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
/* CASE expressions */
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, Z, 0);
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0);
if( A.pExpr ){
A.pExpr->x.pList = Y;
A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
sqlite3ExprSetHeight(pParse, A.pExpr);
}else{
sqlite3ExprListDelete(pParse->db, Y);
sqlite3ExprDelete(pParse->db, Z);
}
A.zStart = C.z;
A.zEnd = &E.z[E.n];
+439 -215
View File
File diff suppressed because it is too large Load Diff
+31 -4
View File
@@ -107,6 +107,7 @@ static void resolveAlias(
incrAggFunctionDepth(pDup, nSubquery);
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
ExprSetProperty(pDup, EP_Skip);
if( pEList->a[iCol].iAlias==0 ){
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
}
@@ -129,7 +130,7 @@ static void resolveAlias(
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags2 |= EP2_MallocedToken;
pExpr->flags |= EP_MemToken;
}
sqlite3DbFree(db, pDup);
}
@@ -229,12 +230,12 @@ static int lookupName(
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetIrreducible(pExpr);
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
** schema. If not found, pSchema will remain NULL and nothing will match
@@ -570,6 +571,19 @@ static void notValidCheckConstraint(
# define notValidCheckConstraint(P,N,M)
#endif
/*
** Expression p should encode a floating point value between 1.0 and 0.0.
** Return 1024 times this value. Or return -1 if p is not a floating point
** value between 1.0 and 0.0.
*/
static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*1000.0);
}
/*
** This routine is callback for sqlite3WalkExpr().
@@ -591,7 +605,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pParse = pNC->pParse;
assert( pParse==pWalker->pParse );
if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
@@ -683,6 +697,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}else{
is_agg = pDef->xFunc==0;
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
if( n==2 ){
pExpr->iTable = exprProbability(pList->a[1].pExpr);
if( pExpr->iTable<0 ){
sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
"constant between 0.0 and 1.0");
pNC->nErr++;
}
}else{
pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
}
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pDef ){
+4 -4
View File
@@ -264,8 +264,8 @@ static void addWhereTerm(
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
if( pEq && isOuterJoin ){
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(pEq);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
pEq->iRightJoinTable = (i16)pE2->iTable;
}
*ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
@@ -300,8 +300,8 @@ static void addWhereTerm(
static void setJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(p);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = (i16)iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
+13 -9
View File
@@ -17,7 +17,11 @@
#include "winresrc.h"
#else
#include "windows.h"
#endif
#endif /* !defined(_WIN32_WCE) */
#if !defined(VS_FF_NONE)
# define VS_FF_NONE 0x00000000L
#endif /* !defined(VS_FF_NONE) */
#include "sqlite3.h"
#include "sqlite3rc.h"
@@ -26,10 +30,10 @@
* English (U.S.) resources
*/
#ifdef _WIN32
#if defined(_WIN32)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif /* _WIN32 */
#endif /* defined(_WIN32) */
/*
* Version
@@ -38,14 +42,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION SQLITE_RESOURCE_VERSION
PRODUCTVERSION SQLITE_RESOURCE_VERSION
FILEFLAGSMASK 0x3F
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#if defined(_DEBUG)
FILEFLAGS 0x1L
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEFLAGS VS_FF_NONE
#endif /* defined(_DEBUG) */
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
@@ -64,6 +68,6 @@ BEGIN
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
VALUE "Translation", 0x409, 0x4b0
END
END
+38 -43
View File
@@ -921,8 +921,6 @@ struct sqlite3 {
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
sqlite3_value *pErr; /* Most recent error message */
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
union {
volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
@@ -1032,6 +1030,7 @@ struct sqlite3 {
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -1724,7 +1723,7 @@ typedef int ynVar;
struct Expr {
u8 op; /* Operation performed by this node */
char affinity; /* The affinity of the column or 0 if not a column */
u16 flags; /* Various flags. EP_* See below */
u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
int iValue; /* Non-negative integer value if EP_IntValue */
@@ -1738,8 +1737,8 @@ struct Expr {
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
} x;
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
@@ -1752,12 +1751,12 @@ struct Expr {
#endif
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old */
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 1000 times likelihood */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1). */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
u8 flags2; /* Second set of flags. EP2_... */
u8 op2; /* TK_REGISTER: original value of Expr.op
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
@@ -1768,50 +1767,45 @@ struct Expr {
/*
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x0008 /* Expression contains one or more errors */
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Hint 0x1000 /* Not used */
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
/*
** The following are the meanings of bits in the Expr.flags2 field.
*/
#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
/*
** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
** flag on an expression structure. This flag is used for VV&A only. The
** routine is implemented as a macro that only works when in debugging mode,
** so as not to burden production code.
*/
#ifdef SQLITE_DEBUG
# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
#else
# define ExprSetIrreducible(X)
#endif
#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x000008 /* Expression contains one or more errors */
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
#define EP_FixedDest 0x000200 /* Result needed in a specific register */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
/*
** These macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
#define ExprSetProperty(E,P) (E)->flags|=(P)
#define ExprClearProperty(E,P) (E)->flags&=~(P)
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
** and Accreditation only. It works like ExprSetProperty() during VVA
** processes but is a no-op for delivery.
*/
#ifdef SQLITE_DEBUG
# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
#else
# define ExprSetVVAProperty(E,P)
#endif
/*
** Macros to determine the number of bytes required by a normal Expr
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
@@ -3190,6 +3184,7 @@ int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, VTable *);
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
int sqlite3Reprepare(Vdbe*);
+2 -1
View File
@@ -193,7 +193,8 @@ int sqlite3Dequote(char *z){
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
default: return -1;
}
for(i=1, j=0; ALWAYS(z[i]); i++){
for(i=1, j=0;; i++){
assert( z[i] );
if( z[i]==quote ){
if( z[i+1]==quote ){
z[j++] = quote;
+1
View File
@@ -567,6 +567,7 @@ int sqlite3VdbeExec(
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
+1
View File
@@ -350,6 +350,7 @@ struct Vdbe {
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
+14
View File
@@ -510,6 +510,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
return rc;
}
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
@@ -534,6 +535,19 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
return p->s.db;
}
/*
** Return the current time for a statement
*/
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
Vdbe *v = p->pVdbe;
int rc;
if( v->iCurrentTime==0 ){
rc = sqlite3OsCurrentTimeInt64(p->s.db->pVfs, &v->iCurrentTime);
if( rc ) v->iCurrentTime = 0;
}
return v->iCurrentTime;
}
/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
+1
View File
@@ -2436,6 +2436,7 @@ int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
p->iCurrentTime = 0;
p->magic = VDBE_MAGIC_INIT;
return p->rc & db->errMask;
}
+1 -1
View File
@@ -43,7 +43,7 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
testcase( ExprHasProperty(pExpr, EP_Reduced) );
rc = pWalker->xExprCallback(pWalker, pExpr);
if( rc==WRC_Continue
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
&& !ExprHasProperty(pExpr,EP_TokenOnly) ){
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+104 -42
View File
@@ -52,12 +52,13 @@ typedef struct WhereOrSet WhereOrSet;
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
** (Virtual tables can return a larger cost, but let's assume they do not.)
** So all costs can be stored in a 16-bit unsigned integer without risk
** So all costs can be stored in a 16-bit integer without risk
** of overflow.
**
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
** Instead, a close estimate is used. Any value of X<=1 is stored as 0.
** X=2 is 10. X=3 is 16. X=1000 is 99. etc.
** Instead, a close estimate is used. Any value of X=1 is stored as 0.
** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
**
** The tool/wherecosttest.c source file implements a command-line program
** that will convert WhereCosts to integers, convert integers to WhereCosts
@@ -65,7 +66,7 @@ typedef struct WhereOrSet WhereOrSet;
** command-line program is a useful utility to have around when working with
** this module.
*/
typedef unsigned short int WhereCost;
typedef short int WhereCost;
/*
** This object contains information needed to implement a single nested
@@ -106,6 +107,7 @@ struct WhereLevel {
Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
} u;
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
Bitmask notReady; /* FROM entries not usable at this level */
};
/*
@@ -268,6 +270,7 @@ struct WhereTerm {
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
WhereCost truthProb; /* Probability of truth for this expression */
u16 eOperator; /* A WO_xx value describing <op> */
u8 wtFlags; /* TERM_xxx bit flags. See below */
u8 nChild; /* Number of children that must disable us */
@@ -642,6 +645,9 @@ static void whereClauseClear(WhereClause *pWC){
}
}
/* Forward declaration */
static WhereCost whereCost(tRowcnt x);
/*
** Add a single new WhereTerm entry to the WhereClause object pWC.
** The new WhereTerm object is constructed from Expr p and with wtFlags.
@@ -683,6 +689,11 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = whereCost(p->iTable) - 99;
}else{
pTerm->truthProb = -1;
}
pTerm->pExpr = sqlite3ExprSkipCollate(p);
pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC;
@@ -2544,6 +2555,7 @@ static int whereRangeScanEst(
){
int rc = SQLITE_OK;
int nOut = (int)*pnOut;
WhereCost nNew;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
Index *p = pBuilder->pNew->u.btree.pIndex;
@@ -2606,6 +2618,7 @@ static int whereRangeScanEst(
whereKeyStats(pParse, p, pRec, 0, a);
iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
if( iNew>iLower ) iLower = iNew;
nOut--;
}
}
@@ -2620,12 +2633,12 @@ static int whereRangeScanEst(
whereKeyStats(pParse, p, pRec, 1, a);
iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
if( iNew<iUpper ) iUpper = iNew;
nOut--;
}
}
pBuilder->pRec = pRec;
if( rc==SQLITE_OK ){
WhereCost nNew;
if( iUpper>iLower ){
nNew = whereCost(iUpper - iLower);
}else{
@@ -2647,13 +2660,17 @@ static int whereRangeScanEst(
assert( pLower || pUpper );
/* TUNING: Each inequality constraint reduces the search space 4-fold.
** A BETWEEN operator, therefore, reduces the search space 16-fold */
nNew = nOut;
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
nOut -= 20; assert( 20==whereCost(4) );
nNew -= 20; assert( 20==whereCost(4) );
nOut--;
}
if( pUpper ){
nOut -= 20; assert( 20==whereCost(4) );
nNew -= 20; assert( 20==whereCost(4) );
nOut--;
}
if( nOut<10 ) nOut = 10;
if( nNew<10 ) nNew = 10;
if( nNew<nOut ) nOut = nNew;
*pnOut = (WhereCost)nOut;
return rc;
}
@@ -2799,6 +2816,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
if( pTerm
&& (pTerm->wtFlags & TERM_CODED)==0
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
&& (pLevel->notReady & pTerm->prereqAll)==0
){
pTerm->wtFlags |= TERM_CODED;
if( pTerm->iParent>=0 ){
@@ -3224,7 +3242,6 @@ static Bitmask codeOneLoopStart(
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
Bitmask newNotReady; /* Return value */
pParse = pWInfo->pParse;
v = pParse->pVdbe;
@@ -3234,6 +3251,7 @@ static Bitmask codeOneLoopStart(
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
@@ -3886,7 +3904,6 @@ static Bitmask codeOneLoopStart(
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
@@ -3896,7 +3913,7 @@ static Bitmask codeOneLoopStart(
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & newNotReady)!=0 ){
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
pWInfo->untestedTerms = 1;
@@ -3928,7 +3945,7 @@ static Bitmask codeOneLoopStart(
if( pLevel->iLeftJoin ) continue;
pE = pTerm->pExpr;
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & newNotReady)!=0 );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
@@ -3956,7 +3973,7 @@ static Bitmask codeOneLoopStart(
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & newNotReady)!=0 ){
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
@@ -3967,7 +3984,7 @@ static Bitmask codeOneLoopStart(
}
sqlite3ReleaseTempReg(pParse, iReleaseReg);
return newNotReady;
return pLevel->notReady;
}
#ifdef WHERETRACE_ENABLED
@@ -4188,9 +4205,9 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
assert( p->rSetup==pTemplate->rSetup );
if( p->prereq==pTemplate->prereq
&& p->nLTerm<pTemplate->nLTerm
&& (p->wsFlags & WHERE_INDEXED)!=0
&& (pTemplate->wsFlags & WHERE_INDEXED)!=0
&& p->u.btree.pIndex==pTemplate->u.btree.pIndex
&& (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0
&& (p->u.btree.pIndex==pTemplate->u.btree.pIndex
|| pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm)
){
/* Overwrite an existing WhereLoop with an similar one that uses
** more terms of the index */
@@ -4205,12 +4222,12 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
&& p->rRun>=pTemplate->rRun
&& p->nOut>=pTemplate->nOut
&& ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */
){
/* Overwrite an existing WhereLoop with a better one: one that is
** better at one of (1) dependencies, (2) setup-cost, (3) run-cost
** or (4) number of output rows, and is no worse in any of those
** categories. */
assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
pNext = p->pNextLoop;
break;
}
@@ -4257,6 +4274,36 @@ whereLoopInsert_noop:
return SQLITE_OK;
}
/*
** Adjust the WhereLoop.nOut value downward to account for terms of the
** WHERE clause that reference the loop but which are not used by an
** index.
**
** In the current implementation, the first extra WHERE clause term reduces
** the number of output rows by a factor of 10 and each additional term
** reduces the number of output rows by sqrt(2).
*/
static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j;
if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
return;
}
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
for(j=pLoop->nLTerm-1; j>=0; j--){
pX = pLoop->aLTerm[j];
if( pX==pTerm ) break;
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ) pLoop->nOut += pTerm->truthProb;
}
}
/*
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
** Try to match one more.
@@ -4423,7 +4470,7 @@ static int whereLoopAddBtreeIndex(
}
/* Step cost for each output row */
pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
/* TBD: Adjust nOut for additional constraints */
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
rc = whereLoopInsert(pBuilder, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
@@ -4627,7 +4674,9 @@ static int whereLoopAddBtree(
** index scans so that a covering index scan will be favored over
** a table scan. */
pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
}else{
Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
@@ -4659,7 +4708,9 @@ static int whereLoopAddBtree(
** which we will simplify to just N*log2(N) */
pNew->rRun = rSize + rLogSize;
}
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
}
}
@@ -5266,9 +5317,12 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
sqlite3 *db; /* The database connection */
int iLoop; /* Loop counter over the terms of the join */
int ii, jj; /* Loop counters */
WhereCost rCost; /* Cost of a path */
WhereCost mxCost = 0; /* Maximum cost of a set of paths */
WhereCost rSortCost; /* Cost to do a sort */
int mxI = 0; /* Index of next entry to replace */
WhereCost rCost; /* Cost of a path */
WhereCost nOut; /* Number of outputs */
WhereCost mxCost = 0; /* Maximum cost of a set of paths */
WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
WhereCost rSortCost; /* Cost to do a sort */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */
WherePath *aTo; /* The nTo best paths at the current level */
@@ -5337,6 +5391,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
** Compute its cost */
rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
rCost = whereCostAdd(rCost, pFrom->rCost);
nOut = pFrom->nRow + pWLoop->nOut;
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
if( !isOrderedValid ){
switch( wherePathSatisfiesOrderBy(pWInfo,
@@ -5359,7 +5414,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
}
/* Check to see if pWLoop should be added to the mxChoice best so far */
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
if( pTo->maskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){
if( pTo->maskLoop==maskNew
&& pTo->isOrderedValid==isOrderedValid
&& ((pTo->rCost<=rCost && pTo->nRow<=nOut) ||
(pTo->rCost>=rCost && pTo->nRow>=nOut))
){
testcase( jj==nTo-1 );
break;
}
@@ -5368,8 +5427,8 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
if( nTo>=mxChoice && rCost>=mxCost ){
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost,
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
}
#endif
@@ -5381,26 +5440,26 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
jj = nTo++;
}else{
/* New path replaces the prior worst to keep count below mxChoice */
for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); }
jj = mxI;
}
pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("New %s cost=%-3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost,
sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
}
#endif
}else{
if( pTo->rCost<=rCost ){
if( pTo->rCost<=rCost && pTo->nRow<=nOut ){
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Skip %s cost=%-3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost,
"Skip %s cost=%-3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
sqlite3DebugPrintf(" vs %s cost=%-3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost,
sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
}
#endif
@@ -5412,11 +5471,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Update %s cost=%-3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost,
"Update %s cost=%-3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
sqlite3DebugPrintf(" was %s cost=%-3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost,
sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
}
#endif
@@ -5424,16 +5483,22 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
/* pWLoop is a winner. Add it to the set of best so far */
pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
pTo->revLoop = revMask;
pTo->nRow = pFrom->nRow + pWLoop->nOut;
pTo->nRow = nOut;
pTo->rCost = rCost;
pTo->isOrderedValid = isOrderedValid;
pTo->isOrdered = isOrdered;
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
pTo->aLoop[iLoop] = pWLoop;
if( nTo>=mxChoice ){
mxI = 0;
mxCost = aTo[0].rCost;
mxOut = aTo[0].nRow;
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
if( pTo->rCost>mxCost ) mxCost = pTo->rCost;
if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
mxCost = pTo->rCost;
mxOut = pTo->nRow;
mxI = jj;
}
}
}
}
@@ -5470,12 +5535,9 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
/* Find the lowest cost path. pFrom will be left pointing to that path */
pFrom = aFrom;
assert( nFrom==1 );
#if 0 /* The following is needed if nFrom is ever more than 1 */
for(ii=1; ii<nFrom; ii++){
if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
}
#endif
assert( pWInfo->nLevel==nLoop );
/* Load the lowest cost path into pWInfo */
for(iLoop=0; iLoop<nLoop; iLoop++){