]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Immediately purge entries from the column cache when the associated register
authordrh <drh@noemail.net>
Thu, 24 Dec 2009 16:00:28 +0000 (16:00 +0000)
committerdrh <drh@noemail.net>
Thu, 24 Dec 2009 16:00:28 +0000 (16:00 +0000)
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

manifest
manifest.uuid
src/delete.c
src/expr.c
src/select.c
src/sqliteInt.h
src/where.c

index 67dd5b96ecbbfe494f7919550a525b72a201de6e..fb26745d40a545c1998a6fcf869dad9af7cb727d 100644 (file)
--- 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-----
index 7ea3abbb9771680076086a7804ecdbdd3f7c959c..ea9a2ea53ee70c7e7a52af90d99023cb187eb525 100644 (file)
@@ -1 +1 @@
-4a97c623f4e190134de4b2ca406e311034a74797
\ No newline at end of file
+ea4e57e1c1b6663ceb12872e31a8503f6c14e3d8
\ No newline at end of file
index 5b30888280d3fb77cbd68e157761fe1050f2f50e..18ed22418f659c3ae5851eae95581f61b978ac54 100644 (file)
@@ -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);
index aee2b740913492696fdda164ceb50091759cd7e4..7e9eb41706257e2ca82304ee58c8c3b3e618c449 100644 (file)
@@ -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; i<SQLITE_N_COLCACHE; i++, p++){
     if( p->iReg && 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; i<SQLITE_N_COLCACHE; i++, p++){
-    if( p->iReg>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; i<SQLITE_N_COLCACHE; i++, p++){
     int r = p->iReg;
     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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       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, &regFree1,
-                                  pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
       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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       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, &regFree1,
-                                  pExpr->pRight, &r2, &regFree2);
+      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, SQLITE_NULLEQ);
index 2e07213f93734fed680775b3f7e8332eb338a56a..0ba56a8ae029a91e2dd297f432044f1d4303cc3d 100644 (file)
@@ -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);
             }
index 6bbae1aa1ba4ad31bfc031b760f21da78f8ae8ac..9ca2a55e5bb252678b20c49252b5e8069790c1cd 100644 (file)
@@ -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);
index f6d9ab296ed0bf36465da9240c80b12c99e00bc9..0f47d18af45d9d3323e7d881e4041e3a85b28328 100644 (file)
@@ -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);
           }