]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the testcase() macro. Additional CSE test coverage. (CVS 4951)
authordrh <drh@noemail.net>
Tue, 1 Apr 2008 15:06:33 +0000 (15:06 +0000)
committerdrh <drh@noemail.net>
Tue, 1 Apr 2008 15:06:33 +0000 (15:06 +0000)
FossilOrigin-Name: 492490f9c86e52c7a706d9e1bf0ba216d5bb8aba

manifest
manifest.uuid
src/expr.c
src/main.c
src/sqliteInt.h
test/cse.test

index 9bec6ebae7bf7fa6423fa9113abee264da66b4d2..33ab66fec15a241ebffbaf7800ea06ce02234ba5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\swith\sCASTs\sand\sthe\snew\sCSE\smechanism.\s(CVS\s4950)
-D 2008-04-01T12:24:11
+C Add\sthe\stestcase()\smacro.\s\sAdditional\sCSE\stest\scoverage.\s(CVS\s4951)
+D 2008-04-01T15:06:34
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in b861627d91df5ee422c54237aa38296954dc0151
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -95,7 +95,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
 F src/delete.c 74d5c9c824848a14d7dee37264ec302b168c4ddb
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 64843f848a36edf1fe4d95bfd3e7a9090580c4a3
+F src/expr.c bc7ab980abcc211083148eeaea571c4511f41238
 F src/fault.c 83057e86815d473e526f7df0b0108dfdd022ff23
 F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe
 F src/hash.c 53655c312280211444bfe23af6490a460aec2980
@@ -104,7 +104,7 @@ F src/insert.c 6974a1d02f2dcd616d00eef4996d4872495fad0f
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 8267890e6a0a71f13b680794520999c642299081
 F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc
-F src/main.c 7d22155e35094bc5d368202c3db8a3fc429548af
+F src/main.c b499fa9fa2551d0963404e1b582747ef92754dd0
 F src/malloc.c 12c1ae98ef1eff34b13c9eb526e0b7b479e1e820
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/mem1.c fc716ff521b6dd3e43eaa211967383308800e70a
@@ -140,7 +140,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
 F src/sqlite.h.in b1ac824d9fc163a5d2226ebf5990b09a02a11117
 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
-F src/sqliteInt.h 1b7ad8791bf441901914734fb1f9735b58adfb37
+F src/sqliteInt.h 3b9a1f2338d6b0d4361b1901543c830a45a45637
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
 F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
@@ -248,7 +248,7 @@ F test/crash5.test c7ddcf7ca83abc19901b977732144234ac72a938
 F test/crash6.test 873d851c5ba2a46e0f9974c54e1d4a77d9a587d5
 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
 F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
-F test/cse.test 36b0079f67f187e4dffe8f3047e04cf10f5f75f9
+F test/cse.test cb548fa3000a246c80fde7adaa0ee4bd85cbc5e9
 F test/date.test 8db95a0ba2c8f4c8762ce66859a036c51959a6be
 F test/default.test 252298e42a680146b1dd64f563b95bdf088d94fb
 F test/delete.test 57533e88e886608bf5ae0f394e14c2eb1b1f7754
@@ -621,7 +621,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 91cc646e2b0c1d62a1989405cc9384a2c22d98d0
-R 0b78187a1b465d3d8c93c57ba92e771e
+P e25939fb25ec8bde8500a672ca5be3cbb514ac3a
+R 739e5874578bdbb30904d6eb328630e7
 U drh
-Z ed15e3f8ef7420ee4fecf6ce237f8aee
+Z 3436b9a596d9596333afb3b553896141
index fb6db5fc8f5e8a33016da7c364ede8d327ac7e3a..66aa29daeaf6ed9b3d354d010a16a07592a61df9 100644 (file)
@@ -1 +1 @@
-e25939fb25ec8bde8500a672ca5be3cbb514ac3a
\ No newline at end of file
+492490f9c86e52c7a706d9e1bf0ba216d5bb8aba
\ No newline at end of file
index ec9f7d554a09600f1b9d16f9e7f7b3df8b4e6d60..aa01fb9a39c8d0bf8c94c08a4969d93f2b75fb56 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.363 2008/04/01 12:24:11 drh Exp $
+** $Id: expr.c,v 1.364 2008/04/01 15:06:34 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -428,6 +428,10 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
     ** use it as the variable number */
     int i;
     pExpr->iTable = i = atoi((char*)&pToken->z[1]);
+    testcase( i==0 );
+    testcase( i==1 );
+    testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
+    testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
     if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
       sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
           db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
@@ -727,6 +731,8 @@ void sqlite3ExprListCheckLength(
   const char *zObject
 ){
   int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+  testcase( pEList && pEList->nExpr==mx );
+  testcase( pEList && pEList->nExpr==mx+1 );
   if( pEList && pEList->nExpr>mx ){
     sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
   }
@@ -909,7 +915,14 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
 #ifndef SQLITE_OMIT_SUBQUERY
     case TK_SELECT:
     case TK_EXISTS:
+      testcase( pExpr->op==TK_SELECT );
+      testcase( pExpr->op==TK_EXISTS );
 #endif
+      testcase( pExpr->op==TK_ID );
+      testcase( pExpr->op==TK_COLUMN );
+      testcase( pExpr->op==TK_DOT );
+      testcase( pExpr->op==TK_AGG_FUNCTION );
+      testcase( pExpr->op==TK_AGG_COLUMN );
       *pN = 0;
       return 2;
     case TK_IN:
@@ -1165,6 +1178,8 @@ static int lookupName(
             }
             pExpr->pTab = pTab;
             if( iCol>=0 ){
+              testcase( iCol==31 );
+              testcase( iCol==32 );
               *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
             }
             break;
@@ -1274,6 +1289,7 @@ static int lookupName(
   */
   if( pExpr->iColumn>=0 && pMatch!=0 ){
     int n = pExpr->iColumn;
+    testcase( n==sizeof(Bitmask)*8-1 );
     if( n>=sizeof(Bitmask)*8 ){
       n = sizeof(Bitmask)*8-1;
     }
@@ -1809,6 +1825,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
           /* Evaluate the expression and insert it into the temp table */
           pParse->disableColCache++;
           sqlite3ExprCode(pParse, pE2, r1);
+          assert( pParse->disableColCache>0 );
           pParse->disableColCache--;
           sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
           sqlite3ExprCacheAffinityChange(pParse, r1, 1);
@@ -1982,6 +1999,7 @@ int sqlite3ExprCodeGetColumn(
     p->iTable = iTable;
     p->iColumn = iColumn;
     p->iReg = iReg;
+    p->affChange = 0;
     i++;
     if( i>=ArraySize(pParse->aColCache) ) i = 0;
     if( i>pParse->nColCache ) pParse->nColCache = i;
@@ -1990,15 +2008,6 @@ int sqlite3ExprCodeGetColumn(
   return iReg;
 }
 
-/*
-** Disable (+1) or enable (-1) the adding of new column cache entries.
-*/
-void sqlite3ExprColumnCacheDisable(Parse *pParse, int disable){
-  assert( disable==-1 || disable==+1 );
-  assert( pParse->disableColCache>0 || disable==1 );
-  pParse->disableColCache += disable;
-}
-
 /*
 ** Clear all column cache entries associated with the vdbe
 ** cursor with cursor number iTable.
@@ -2011,6 +2020,7 @@ void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){
     int i;
     for(i=0; i<pParse->nColCache; i++){
       if( pParse->aColCache[i].iTable==iTable ){
+        testcase( i==pParse->nColCache-1 );
         pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
         pParse->iColCache = pParse->nColCache;
       }
@@ -2140,6 +2150,7 @@ 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);
@@ -2203,7 +2214,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
       assert( to_op==OP_ToInt     || aff!=SQLITE_AFF_INTEGER );
       assert( to_op==OP_ToReal    || aff!=SQLITE_AFF_REAL    );
+      testcase( to_op==OP_ToText );
+      testcase( to_op==OP_ToBlob );
+      testcase( to_op==OP_ToNumeric );
+      testcase( to_op==OP_ToInt );
+      testcase( to_op==OP_ToReal );
       sqlite3VdbeAddOp1(v, to_op, inReg);
+      testcase( usedAsColumnCache(pParse, inReg, inReg) );
       sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
       break;
     }
@@ -2220,10 +2237,18 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       assert( TK_GE==OP_Ge );
       assert( TK_EQ==OP_Eq );
       assert( TK_NE==OP_Ne );
+      testcase( op==TK_LT );
+      testcase( op==TK_LE );
+      testcase( op==TK_GT );
+      testcase( op==TK_GE );
+      testcase( op==TK_EQ );
+      testcase( op==TK_NE );
       codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                   pExpr->pRight, &r2, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, inReg, SQLITE_STOREP2);
+      testcase( regFree1==0 );
+      testcase( regFree2==0 );
       break;
     }
     case TK_AND:
@@ -2249,9 +2274,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       assert( TK_LSHIFT==OP_ShiftLeft );
       assert( TK_RSHIFT==OP_ShiftRight );
       assert( TK_CONCAT==OP_Concat );
+      testcase( op==TK_AND );
+      testcase( op==TK_OR );
+      testcase( op==TK_PLUS );
+      testcase( op==TK_MINUS );
+      testcase( op==TK_REM );
+      testcase( op==TK_BITAND );
+      testcase( op==TK_BITOR );
+      testcase( op==TK_SLASH );
+      testcase( op==TK_LSHIFT );
+      testcase( op==TK_RSHIFT );
+      testcase( op==TK_CONCAT );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       sqlite3VdbeAddOp3(v, op, r2, r1, target);
+      testcase( regFree1==0 );
+      testcase( regFree2==0 );
       break;
     }
     case TK_UMINUS: {
@@ -2269,6 +2307,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
         sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
         r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
         sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
+        testcase( regFree2==0 );
       }
       inReg = target;
       break;
@@ -2277,7 +2316,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
     case TK_NOT: {
       assert( TK_BITNOT==OP_BitNot );
       assert( TK_NOT==OP_Not );
+      testcase( op==TK_BITNOT );
+      testcase( op==TK_NOT );
       inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+      testcase( inReg==target );
+      testcase( usedAsColumnCache(pParse, inReg, inReg) );
       inReg = sqlite3ExprWritableRegister(pParse, inReg, target);
       sqlite3VdbeAddOp1(v, op, inReg);
       break;
@@ -2287,8 +2330,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       int addr;
       assert( TK_ISNULL==OP_IsNull );
       assert( TK_NOTNULL==OP_NotNull );
+      testcase( op==TK_ISNULL );
+      testcase( op==TK_NOTNULL );
       sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      testcase( regFree1==0 );
       addr = sqlite3VdbeAddOp1(v, op, r1);
       sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
       sqlite3VdbeJumpHere(v, addr);
@@ -2317,6 +2363,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       u8 enc = ENC(db);
       CollSeq *pColl = 0;
 
+      testcase( op==TK_CONST_FUNC );
+      testcase( op==TK_FUNCTION );
       zId = (char*)pExpr->token.z;
       nId = pExpr->token.n;
       pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
@@ -2371,6 +2419,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
 #ifndef SQLITE_OMIT_SUBQUERY
     case TK_EXISTS:
     case TK_SELECT: {
+      testcase( op==TK_EXISTS );
+      testcase( op==TK_SELECT );
       if( pExpr->iColumn==0 ){
         sqlite3CodeSubselect(pParse, pExpr);
       }
@@ -2396,6 +2446,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       ** pExpr->iTable contains the values that make up the (...) set.
       */
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+      testcase( regFree1==0 );
       j1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1);
       sqlite3VdbeAddOp2(v, OP_Null, 0, target);
       j2  = sqlite3VdbeAddOp0(v, OP_Goto);
@@ -2436,6 +2487,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
 
       codeCompareOperands(pParse, pLeft, &r1, &regFree1,
                                   pRight, &r2, &regFree2);
+      testcase( regFree1==0 );
+      testcase( regFree2==0 );
       r3 = sqlite3GetTempReg(pParse);
       r4 = sqlite3GetTempReg(pParse);
       codeCompare(pParse, pLeft, pRight, OP_Ge,
@@ -2444,6 +2497,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       pRight = pLItem->pExpr;
       sqlite3ReleaseTempReg(pParse, regFree2);
       r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
+      testcase( regFree2==0 );
       codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
       sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
       sqlite3ReleaseTempReg(pParse, r3);
@@ -2497,14 +2551,16 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       endLabel = sqlite3VdbeMakeLabel(v);
       if( (pX = pExpr->pLeft)!=0 ){
         cacheX = *pX;
+        testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER );
         cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
+        testcase( regFree1==0 );
         cacheX.op = TK_REGISTER;
         cacheX.iColumn = 0;
         opCompare.op = TK_EQ;
         opCompare.pLeft = &cacheX;
         pTest = &opCompare;
       }
-      sqlite3ExprColumnCacheDisable(pParse, 1);
+      pParse->disableColCache++;
       for(i=0; i<nExpr; i=i+2){
         if( pX ){
           opCompare.pRight = aListelem[i].pExpr;
@@ -2512,7 +2568,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
           pTest = aListelem[i].pExpr;
         }
         nextCase = sqlite3VdbeMakeLabel(v);
+        testcase( pTest->op==TK_COLUMN || pTest->op==TK_REGISTER );
         sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
+        testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
+        testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
         sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
         sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
         sqlite3VdbeResolveLabel(v, nextCase);
@@ -2523,7 +2582,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
         sqlite3VdbeAddOp2(v, OP_Null, 0, target);
       }
       sqlite3VdbeResolveLabel(v, endLabel);
-      sqlite3ExprColumnCacheDisable(pParse, -1);
+      assert( pParse->disableColCache>0 );
+      pParse->disableColCache--;
       break;
     }
 #ifndef SQLITE_OMIT_TRIGGER
@@ -2635,7 +2695,7 @@ static int evalConstExpr(void *pArg, Expr *pExpr){
     int r1 = ++pParse->nMem;
     int r2;
     r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
-    if( r1!=r2 ) pParse->nMem--;
+    if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
     pExpr->iColumn = pExpr->op;
     pExpr->op = TK_REGISTER;
     pExpr->iTable = r2;
@@ -2707,21 +2767,28 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
   switch( op ){
     case TK_AND: {
       int d2 = sqlite3VdbeMakeLabel(v);
+      testcase( jumpIfNull==0 );
+      testcase( pParse->disableColCache==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
       pParse->disableColCache++;
       sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pParse->disableColCache>0 );
       pParse->disableColCache--;
       sqlite3VdbeResolveLabel(v, d2);
       break;
     }
     case TK_OR: {
+      testcase( jumpIfNull==0 );
+      testcase( pParse->disableColCache==0 );
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
       pParse->disableColCache++;
       sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pParse->disableColCache>0 );
       pParse->disableColCache--;
       break;
     }
     case TK_NOT: {
+      testcase( jumpIfNull==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
       break;
     }
@@ -2737,18 +2804,30 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       assert( TK_GE==OP_Ge );
       assert( TK_EQ==OP_Eq );
       assert( TK_NE==OP_Ne );
+      testcase( op==TK_LT );
+      testcase( op==TK_LE );
+      testcase( op==TK_GT );
+      testcase( op==TK_GE );
+      testcase( op==TK_EQ );
+      testcase( op==TK_NE );
+      testcase( jumpIfNull==0 );
       codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                   pExpr->pRight, &r2, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, jumpIfNull);
+      testcase( regFree1==0 );
+      testcase( regFree2==0 );
       break;
     }
     case TK_ISNULL:
     case TK_NOTNULL: {
       assert( TK_ISNULL==OP_IsNull );
       assert( TK_NOTNULL==OP_NotNull );
+      testcase( op==TK_ISNULL );
+      testcase( op==TK_NOTNULL );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       sqlite3VdbeAddOp2(v, op, r1, dest);
+      testcase( regFree1==0 );
       break;
     }
     case TK_BETWEEN: {
@@ -2777,13 +2856,17 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       compRight.pLeft = &exprX;
       compRight.pRight = pExpr->pList->a[1].pExpr;
       exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
+      testcase( regFree1==0 );
       exprX.op = TK_REGISTER;
+      testcase( jumpIfNull==0 );
       sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
       break;
     }
     default: {
       r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
       sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
+      testcase( regFree1==0 );
+      testcase( jumpIfNull==0 );
       break;
     }
   }
@@ -2843,17 +2926,23 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
 
   switch( pExpr->op ){
     case TK_AND: {
+      testcase( jumpIfNull==0 );
+      testcase( pParse->disableColCache==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
       pParse->disableColCache++;
       sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pParse->disableColCache>0 );
       pParse->disableColCache--;
       break;
     }
     case TK_OR: {
       int d2 = sqlite3VdbeMakeLabel(v);
+      testcase( jumpIfNull==0 );
+      testcase( pParse->disableColCache==0 );
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
       pParse->disableColCache++;
       sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pParse->disableColCache>0 );
       pParse->disableColCache--;
       sqlite3VdbeResolveLabel(v, d2);
       break;
@@ -2868,16 +2957,28 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
     case TK_GE:
     case TK_NE:
     case TK_EQ: {
+      testcase( op==TK_LT );
+      testcase( op==TK_LE );
+      testcase( op==TK_GT );
+      testcase( op==TK_GE );
+      testcase( op==TK_EQ );
+      testcase( op==TK_NE );
+      testcase( jumpIfNull==0 );
       codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                   pExpr->pRight, &r2, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, jumpIfNull);
+      testcase( regFree1==0 );
+      testcase( regFree2==0 );
       break;
     }
     case TK_ISNULL:
     case TK_NOTNULL: {
+      testcase( op==TK_ISNULL );
+      testcase( op==TK_NOTNULL );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       sqlite3VdbeAddOp2(v, op, r1, dest);
+      testcase( regFree1==0 );
       break;
     }
     case TK_BETWEEN: {
@@ -2906,13 +3007,17 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       compRight.pLeft = &exprX;
       compRight.pRight = pExpr->pList->a[1].pExpr;
       exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
+      testcase( regFree1==0 );
       exprX.op = TK_REGISTER;
+      testcase( jumpIfNull==0 );
       sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
       break;
     }
     default: {
       r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
       sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
+      testcase( regFree1==0 );
+      testcase( jumpIfNull==0 );
       break;
     }
   }
@@ -3187,7 +3292,6 @@ int sqlite3GetTempReg(Parse *pParse){
 }
 void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
   if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
-    assert( iReg>0 );
     pParse->aTempReg[pParse->nTempReg++] = iReg;
   }
 }
index 41b84c0948d823c2ec35676e648d664f4e7e8602..68eb1c05057b4de86ce961c173c2db89aa256397 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.429 2008/03/21 16:45:47 drh Exp $
+** $Id: main.c,v 1.430 2008/04/01 15:06:34 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -47,6 +47,16 @@ void (*sqlite3IoTrace)(const char*, ...) = 0;
 */
 char *sqlite3_temp_directory = 0;
 
+/*
+** Routine needed to support the testcase() macro.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+void sqlite3Coverage(int x){
+  static int dummy = 0;
+  dummy += x;
+}
+#endif
+
 
 /*
 ** Return true if the buffer z[0..n-1] contains all spaces.
index b6bb4415138cfa9d7fe1c9f26bcafea60e10ead1..de3a46a231edd8bd078b87cac5d1fce9e9e21ffa 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.686 2008/04/01 05:07:15 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.687 2008/04/01 15:06:34 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
   typedef int sqlite3_intptr_t;
 #endif
 
+/*
+** A macro used to aid in coverage testing.  When doing coverage
+** testing, the condition inside the argument must be evaluated 
+** both true and false in order to get full branch coverage.
+** This macro can be inserted to ensure adequate test coverage
+** in places where simple condition/decision coverage is inadequate.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+  void sqlite3Coverage(int);
+# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
+#else
+# define testcase(X)
+#endif
+
 
 /*
 ** The macro unlikely() is a hint that surrounds a boolean
@@ -1841,7 +1855,6 @@ void sqlite3WhereEnd(WhereInfo*);
 int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
 void sqlite3ExprCodeMove(Parse*, int, int);
 void sqlite3ExprClearColumnCache(Parse*, int);
-void sqlite3ExprColumnCacheDisable(Parse*, int);
 void sqlite3ExprCacheAffinityChange(Parse*, int, int);
 int sqlite3ExprWritableRegister(Parse*,int,int);
 int sqlite3ExprCode(Parse*, Expr*, int);
index ce16d791ca5de71cd1b8131ca65b33edc66e359b..836e15aba983660d7bf93eb6be9385481351c1b9 100644 (file)
@@ -13,7 +13,7 @@
 # factoring constant expressions out of loops and for
 # common subexpression eliminations.
 #
-# $Id: cse.test,v 1.3 2008/04/01 12:24:11 drh Exp $
+# $Id: cse.test,v 1.4 2008/04/01 15:06:34 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -70,13 +70,40 @@ do_test cse-1.9 {
   }
 } {0 -12 1 11 0 -22 1 21}
 do_test cse-1.10 {
-  explain {
-    SELECT CAST(b AS integer), typeof(b), CAST(b AS text), typeof(b) FROM t1
-  }
   execsql {
     SELECT CAST(b AS integer), typeof(b), CAST(b AS text), typeof(b) FROM t1
   }
 } {11 integer 11 integer 21 integer 21 integer}
+do_test cse-1.11 { 
+  execsql {
+    SELECT *,* FROM t1 WHERE a=2
+    UNION ALL
+    SELECT *,* FROM t1 WHERE a=1
+  }
+} {2 21 22 23 24 25 2 21 22 23 24 25 1 11 12 13 14 15 1 11 12 13 14 15}
+do_test cse-1.12 { 
+  execsql {
+    SELECT coalesce(b,c,d,e), a, b, c, d, e FROM t1 WHERE a=2
+    UNION ALL
+    SELECT coalesce(e,d,c,b), e, d, c, b, a FROM t1 WHERE a=1
+  }
+} {21 2 21 22 23 24 14 14 13 12 11 1}
+do_test cse-1.13 {
+  explain {
+     SELECT upper(b), typeof(b), b FROM t1
+  }
+  execsql {
+     SELECT upper(b), typeof(b), b FROM t1
+  }
+} {11 integer 11 21 integer 21}
+do_test cse-1.14 {
+  explain {
+     SELECT b, typeof(b), upper(b), typeof(b), b FROM t1
+  }
+  execsql {
+     SELECT b, typeof(b), upper(b), typeof(b), b FROM t1
+  }
+} {11 integer 11 integer 11 21 integer 21 integer 21}
 
 # Overflow the column cache.  Create queries involving more and more
 # columns until the cache overflows.  Verify correct operation throughout.