From: drh Date: Thu, 24 Dec 2009 16:00:28 +0000 (+0000) Subject: Immediately purge entries from the column cache when the associated register X-Git-Tag: version-3.7.2~684 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b6da74ebd5140fac15bb007ce21e3b79b981f98e;p=thirdparty%2Fsqlite.git Immediately purge entries from the column cache when the associated register undergoes an affinity change. Ticket [eb5548a849]. Enhance the SQLITE_TESTCTRL_OPTIMIZATIONS setting of sqlite3_test_control so that it can disable the column cache for testing purposes, in an effort to prevent future problems of a similar nature to this one. FossilOrigin-Name: ea4e57e1c1b6663ceb12872e31a8503f6c14e3d8 --- diff --git a/manifest b/manifest index 67dd5b96ec..fb26745d40 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Move\sthe\squery\sflattener\sturn-off\sfrom\sa\spragma\sto\san\ssqlite3_test_control()\ncall.\s\sMake\sprovisions\s(not\syet\simplemented)\sto\sturn\soff\sother\soptimizers\nusing\sthe\ssame\scall. -D 2009-12-22T23:52:32 +C Immediately\spurge\sentries\sfrom\sthe\scolumn\scache\swhen\sthe\sassociated\sregister\nundergoes\san\saffinity\schange.\s\sTicket\s[eb5548a849].\s\sEnhance\sthe\nSQLITE_TESTCTRL_OPTIMIZATIONS\ssetting\sof\ssqlite3_test_control\sso\sthat\sit\ncan\sdisable\sthe\scolumn\scache\sfor\stesting\spurposes,\sin\san\seffort\sto\sprevent\nfuture\sproblems\sof\sa\ssimilar\snature\sto\sthis\sone. +D 2009-12-24T16:00:29 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -118,8 +118,8 @@ F src/build.c 6ab7f8d8fa5b0ac6bfdce359e85f580b7a9b2e86 F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f F src/complete.c 4c8a742c4a4a6d9c835912648f5c8f032ea36c7b F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f -F src/delete.c 8b8afb9cd7783d573eae55a3f4208bc0637a2bb8 -F src/expr.c 50385ed51f1cd7f1ab289629cd0f87d5b2fcca52 +F src/delete.c 1425b44a1a8127ada4c909e8b71439354e523c24 +F src/expr.c 6d138c36168ca68d37a19a375af10f5b806214fc F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0 F src/func.c 69906340991919b4933dd8630774ad069e4d582e @@ -165,11 +165,11 @@ F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c 7e424c8fea32725dec2d86d06d98ffedd7fa5023 +F src/select.c 71511cdee4393c4dbaaa6feeff6c860b3f7e4f5f F src/shell.c b9fae60b0f2ce306c20fa99e83c75023bf35f15b F src/sqlite.h.in 60cbf318765de59bb454e229bd2d5ec065dd686a F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 -F src/sqliteInt.h 2612705b54169e0cd82740f4bf93d7284fe2536a +F src/sqliteInt.h 3b9eba31a66b2bcc7c0f51cbcf92ae273c883d73 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -222,7 +222,7 @@ F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2 F src/vtab.c 7c7713d66cda699f16bf1cc601d8d4f5070ab935 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f -F src/where.c f20ee9a15c1ccb8b94cd31e3f8c6868e1358fc07 +F src/where.c 5bf4b84dbd7b0129203562906340dded3de46543 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45 @@ -785,14 +785,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 37a1de02d1d8a34604f1bee896eaf579d4ba149a -R c2d4c8288e84ae9afb7a643682bb92e8 +P 4a97c623f4e190134de4b2ca406e311034a74797 +R becfd603a317957c894c09ed10d1cf47 U drh -Z 6449324b3eb75888a0748fac4f5b69aa +Z 823ba23042dadaf02b5d95ffa78418d3 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFLMVvDoxKgR168RlERArP6AJ9MsqPf1HHWZPNd9R2EyQa4uKZbCgCcCRSF -ZONbln7b9xypgxaX8ksQh18= -=pFNF +iD8DBQFLM5AgoxKgR168RlERArV4AJ9/5N6dJdz2JusC+5zWn7ZEq+ZJdQCdFCUl +ifDSVjdF1pkT8+LtcL0nAJ8= +=ip6B -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 7ea3abbb97..ea9a2ea53e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4a97c623f4e190134de4b2ca406e311034a74797 \ No newline at end of file +ea4e57e1c1b6663ceb12872e31a8503f6c14e3d8 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 5b30888280..18ed22418f 100644 --- a/src/delete.c +++ b/src/delete.c @@ -364,7 +364,7 @@ void sqlite3DeleteFrom( sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK); if( pWInfo==0 ) goto delete_from_cleanup; - regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0); + regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid); sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); diff --git a/src/expr.c b/src/expr.c index aee2b74091..7e9eb41706 100644 --- a/src/expr.c +++ b/src/expr.c @@ -227,30 +227,6 @@ CollSeq *sqlite3BinaryCompareCollSeq( return pColl; } -/* -** Generate the operands for a comparison operation. Before -** generating the code for each operand, set the EP_AnyAff -** flag on the expression so that it will be able to used a -** cached column value that has previously undergone an -** affinity change. -*/ -static void codeCompareOperands( - Parse *pParse, /* Parsing and code generating context */ - Expr *pLeft, /* The left operand */ - int *pRegLeft, /* Register where left operand is stored */ - int *pFreeLeft, /* Free this register when done */ - Expr *pRight, /* The right operand */ - int *pRegRight, /* Register where right operand is stored */ - int *pFreeRight /* Write temp register for right operand there */ -){ - while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft; - pLeft->flags |= EP_AnyAff; - *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft); - while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft; - pRight->flags |= EP_AnyAff; - *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight); -} - /* ** Generate code for a comparison operator. */ @@ -1982,13 +1958,18 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ + /* The SQLITE_ColumnCache flag disables the column cache. This is used + ** for testing only - to verify that SQLite always gets the same answer + ** with and without the column cache. + */ + if( pParse->db->flags & SQLITE_ColumnCache ) return; + /* First replace any existing entry */ for(i=0, p=pParse->aColCache; iiReg && p->iTable==iTab && p->iColumn==iCol ){ cacheEntryClear(pParse, p); p->iLevel = pParse->iCacheLevel; p->iReg = iReg; - p->affChange = 0; p->lru = pParse->iCacheCnt++; return; } @@ -2001,7 +1982,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; - p->affChange = 0; p->tempReg = 0; p->lru = pParse->iCacheCnt++; return; @@ -2023,7 +2003,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; - p->affChange = 0; p->tempReg = 0; p->lru = pParse->iCacheCnt++; return; @@ -2109,16 +2088,14 @@ int sqlite3ExprCodeGetColumn( Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ - int iReg, /* Store results here */ - int allowAffChng /* True if prior affinity changes are OK */ + int iReg /* Store results here */ ){ Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; iiReg>0 && p->iTable==iTable && p->iColumn==iColumn - && (!p->affChange || allowAffChng) ){ + if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; @@ -2162,7 +2139,8 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ for(i=0, p=pParse->aColCache; iiReg; if( r>=iStart && r<=iEnd ){ - p->affChange = 1; + cacheEntryClear(pParse, p); + p->iReg = 0; } } } @@ -2329,10 +2307,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ - testcase( (pExpr->flags & EP_AnyAff)!=0 ); inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, - pExpr->iColumn, pExpr->iTable, target, - pExpr->flags & EP_AnyAff); + pExpr->iColumn, pExpr->iTable, target); } break; } @@ -2449,8 +2425,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2); testcase( regFree1==0 ); @@ -2461,8 +2437,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); @@ -2702,8 +2678,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ struct ExprList_item *pLItem = pExpr->x.pList->a; Expr *pRight = pLItem->pExpr; - codeCompareOperands(pParse, pLeft, &r1, ®Free1, - pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); testcase( regFree1==0 ); testcase( regFree2==0 ); r3 = sqlite3GetTempReg(pParse); @@ -3238,8 +3214,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); testcase( regFree1==0 ); @@ -3250,8 +3226,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); @@ -3381,8 +3357,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); testcase( regFree1==0 ); @@ -3393,8 +3369,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_ISNOT: { testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); - codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, - pExpr->pRight, &r2, ®Free2); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); diff --git a/src/select.c b/src/select.c index 2e07213f93..0ba56a8ae0 100644 --- a/src/select.c +++ b/src/select.c @@ -3917,7 +3917,7 @@ int sqlite3Select( int r2; r2 = sqlite3ExprCodeGetColumn(pParse, - pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); + pCol->pTab, pCol->iColumn, pCol->iTable, r1); if( r1!=r2 ){ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6bbae1aa1b..9ca2a55e5b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -930,10 +930,10 @@ struct sqlite3 { ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ -#define SQLITE_IndexSort 0x02 /* Disable indexes for sorting */ -#define SQLITE_IndexSearch 0x04 /* Disable indexes for searching */ -#define SQLITE_IndexCover 0x08 /* Disable index covering table */ -#define SQLITE_RegisterReuse 0x10 /* Disable register reuse */ +#define SQLITE_ColumnCache 0x02 /* Disable the column cache */ +#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */ +#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */ +#define SQLITE_IndexCover 0x10 /* Disable index covering table */ #define SQLITE_OptMask 0x1f /* Mask of all disablable opts */ /* @@ -1648,14 +1648,13 @@ struct Expr { #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ -#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ -#define EP_FixedDest 0x0400 /* Result needed in a specific register */ -#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */ +#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_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() */ +#define EP_Reduced 0x1000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ +#define EP_TokenOnly 0x2000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ +#define EP_Static 0x4000 /* Held in memory not obtained from malloc() */ /* ** The following are the meanings of bits in the Expr.flags2 field. @@ -2133,7 +2132,6 @@ struct Parse { struct yColCache { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ - u8 affChange; /* True if this register has had an affinity change */ u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ @@ -2652,7 +2650,7 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16); void sqlite3WhereEnd(WhereInfo*); -int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); +int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeCopy(Parse*, int, int, int); void sqlite3ExprCacheStore(Parse*, int, int, int); diff --git a/src/where.c b/src/where.c index f6d9ab296e..0f47d18af4 100644 --- a/src/where.c +++ b/src/where.c @@ -3336,7 +3336,7 @@ static Bitmask codeOneLoopStart( int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int r; r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, - regRowid, 0); + regRowid); sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeCurrentAddr(v)+2, r, iSet); }