/ Check-in [af129b6d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Miscellaneous code simplifications and cleanup and test coverage enhancements. (CVS 4730)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: af129b6d158cc90ce9752dd6383c1de47f7b3e43
User & Date: drh 2008-01-19 20:11:26
Context
2008-01-19
23:50
Additional test coverage improvements. Test coverage now stands at 98.73%. (CVS 4731) check-in: 010f7b78 user: drh tags: trunk
20:11
Miscellaneous code simplifications and cleanup and test coverage enhancements. (CVS 4730) check-in: af129b6d user: drh tags: trunk
03:35
Cleanup and simplification of constraint processing. Simplifications to the VM for better test coverage. (CVS 4729) check-in: d9ebe9d7 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to mkopcodeh.awk.

    84     84   
    85     85   # Assign numbers to all opcodes and output the result.
    86     86   END {
    87     87     cnt = 0
    88     88     max = 0
    89     89     print "/* Automatically generated.  Do not edit */"
    90     90     print "/* See the mkopcodeh.awk script for details */"
           91  +  op["OP_Noop"] = -1;
           92  +  op["OP_Explain"] = -1;
    91     93     for(name in op){
    92     94       if( op[name]<0 ){
    93     95         cnt++
    94     96         while( used[cnt] ) cnt++
    95     97         op[name] = cnt
    96     98       }
    97     99       used[op[name]] = 1;

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing all sorts of SQLite interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test1.c,v 1.282 2008/01/16 17:46:38 drh Exp $
           16  +** $Id: test1.c,v 1.283 2008/01/19 20:11:26 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   
    23     23   /*
................................................................................
  4216   4216   static int vfs_unlink_test(
  4217   4217     ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  4218   4218     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  4219   4219     int objc,              /* Number of arguments */
  4220   4220     Tcl_Obj *CONST objv[]  /* Command arguments */
  4221   4221   ){
  4222   4222     int i;
         4223  +  sqlite3_vfs *pMain;
  4223   4224     sqlite3_vfs *apVfs[20];
         4225  +  sqlite3_vfs one, two;
  4224   4226   
         4227  +  sqlite3_vfs_unregister(0);   /* Unregister of NULL is harmless */
         4228  +  one.zName = "__one";
         4229  +  two.zName = "__two";
         4230  +
         4231  +  /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
         4232  +  ** change the default VFS
         4233  +  */
         4234  +  pMain = sqlite3_vfs_find(0);
         4235  +  sqlite3_vfs_register(&one, 0);
         4236  +  assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
         4237  +  sqlite3_vfs_register(&two, 0);
         4238  +  assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
         4239  +
         4240  +  /* We can find a VFS by its name */
         4241  +  assert( sqlite3_vfs_find("__one")==&one );
         4242  +  assert( sqlite3_vfs_find("__two")==&two );
         4243  +
         4244  +  /* Calling sqlite_vfs_register with non-zero second parameter changes the
         4245  +  ** default VFS, even if the 1st parameter is an existig VFS that is
         4246  +  ** previously registered as the non-default.
         4247  +  */
         4248  +  sqlite3_vfs_register(&one, 1);
         4249  +  assert( sqlite3_vfs_find("__one")==&one );
         4250  +  assert( sqlite3_vfs_find("__two")==&two );
         4251  +  assert( sqlite3_vfs_find(0)==&one );
         4252  +  sqlite3_vfs_register(&two, 1);
         4253  +  assert( sqlite3_vfs_find("__one")==&one );
         4254  +  assert( sqlite3_vfs_find("__two")==&two );
         4255  +  assert( sqlite3_vfs_find(0)==&two );
         4256  +  if( pMain ){
         4257  +    sqlite3_vfs_register(pMain, 1);
         4258  +    assert( sqlite3_vfs_find("__one")==&one );
         4259  +    assert( sqlite3_vfs_find("__two")==&two );
         4260  +    assert( sqlite3_vfs_find(0)==pMain );
         4261  +  }
         4262  +  
         4263  +  /* Unlink the default VFS.  Repeat until there are no more VFSes
         4264  +  ** registered.
         4265  +  */
  4225   4266     for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
  4226   4267       apVfs[i] = sqlite3_vfs_find(0);
  4227   4268       if( apVfs[i] ){
  4228   4269         assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
  4229   4270         sqlite3_vfs_unregister(apVfs[i]);
  4230   4271         assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
  4231   4272       }
  4232   4273     }
  4233   4274     assert( 0==sqlite3_vfs_find(0) );
         4275  +
         4276  +  /* Relink all VFSes in reverse order. */  
  4234   4277     for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
  4235   4278       if( apVfs[i] ){
  4236   4279         sqlite3_vfs_register(apVfs[i], 1);
  4237   4280         assert( apVfs[i]==sqlite3_vfs_find(0) );
  4238   4281         assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
  4239   4282       }
  4240   4283     }
         4284  +
         4285  +  /* Unregister out sample VFSes. */
         4286  +  sqlite3_vfs_unregister(&one);
         4287  +  sqlite3_vfs_unregister(&two);
         4288  +
         4289  +  /* Unregistering a VFS that is not currently registered is harmless */
         4290  +  sqlite3_vfs_unregister(&one);
         4291  +  sqlite3_vfs_unregister(&two);
         4292  +  assert( sqlite3_vfs_find("__one")==0 );
         4293  +  assert( sqlite3_vfs_find("__two")==0 );
         4294  +
         4295  +  /* We should be left with the original default VFS back as the
         4296  +  ** original */
         4297  +  assert( sqlite3_vfs_find(0)==pMain );
         4298  +
  4241   4299     return TCL_OK;
  4242   4300   }
  4243   4301   
  4244   4302   /*
  4245   4303   ** tclcmd:  save_prng_state
  4246   4304   */
  4247   4305   static int save_prng_state(

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.700 2008/01/19 03:35:59 drh Exp $
           46  +** $Id: vdbe.c,v 1.701 2008/01/19 20:11:26 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
  2692   2692   /* Opcode: MoveGe P1 P2 P3 * *
  2693   2693   **
  2694   2694   ** Use the value in register P3 as a key.  Reposition
  2695   2695   ** cursor P1 so that it points to the smallest entry that is greater
  2696   2696   ** than or equal to the key in register P3.
  2697   2697   ** If there are no records greater than or equal to the key and P2 
  2698   2698   ** is not zero, then jump to P2.
         2699  +**
         2700  +** A special feature of this opcode (and different from the
         2701  +** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is
         2702  +** zero and P1 is an SQL table (a b-tree with integer keys) then
         2703  +** the seek is deferred until it is actually needed.  It might be
         2704  +** the case that the cursor is never accessed.  By deferring the
         2705  +** seek, we avoid unnecessary seeks.
  2699   2706   **
  2700   2707   ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
  2701   2708   */
  2702   2709   /* Opcode: MoveGt P1 P2 P3 * *
  2703   2710   **
  2704   2711   ** Use the value in register P3 as a key.  Reposition
  2705   2712   ** cursor P1 so that it points to the smallest entry that is greater
  2706   2713   ** than the key in register P3.
  2707         -** If there are no records greater than the key and P2 is not zero,
         2714  +** If there are no records greater than the key 
  2708   2715   ** then jump to P2.
  2709   2716   **
  2710   2717   ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
  2711   2718   */
  2712   2719   /* Opcode: MoveLt P1 P2 P3 * * 
  2713   2720   **
  2714   2721   ** Use the value in register P3 as a key.  Reposition
  2715   2722   ** cursor P1 so that it points to the largest entry that is less
  2716   2723   ** than the key in register P3.
  2717         -** If there are no records less than the key and P2 is not zero,
         2724  +** If there are no records less than the key
  2718   2725   ** then jump to P2.
  2719   2726   **
  2720   2727   ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
  2721   2728   */
  2722   2729   /* Opcode: MoveLe P1 P2 P3 * *
  2723   2730   **
  2724   2731   ** Use the value in register P3 as a key.  Reposition
  2725   2732   ** cursor P1 so that it points to the largest entry that is less than
  2726   2733   ** or equal to the key.
  2727         -** If there are no records less than or eqal to the key and P2 is not zero,
         2734  +** If there are no records less than or eqal to the key
  2728   2735   ** then jump to P2.
  2729   2736   **
  2730   2737   ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
  2731   2738   */
  2732   2739   case OP_MoveLt:         /* jump, in3 */
  2733   2740   case OP_MoveLe:         /* jump, in3 */
  2734   2741   case OP_MoveGe:         /* jump, in3 */
................................................................................
  2742   2749     if( pC->pCursor!=0 ){
  2743   2750       int res, oc;
  2744   2751       oc = pOp->opcode;
  2745   2752       pC->nullRow = 0;
  2746   2753       *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
  2747   2754       if( pC->isTable ){
  2748   2755         i64 iKey = sqlite3VdbeIntValue(pIn3);
  2749         -      if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
         2756  +      if( pOp->p2==0 ){
         2757  +        assert( pOp->opcode==OP_MoveGe );
  2750   2758           pC->movetoTarget = iKey;
         2759  +        pC->rowidIsValid = 0;
  2751   2760           pC->deferredMoveto = 1;
  2752   2761           break;
  2753   2762         }
  2754   2763         rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
  2755   2764         if( rc!=SQLITE_OK ){
  2756   2765           goto abort_due_to_error;
  2757   2766         }
................................................................................
  2789   2798         }else{
  2790   2799           /* res might be negative because the table is empty.  Check to
  2791   2800           ** see if this is the case.
  2792   2801           */
  2793   2802           res = sqlite3BtreeEof(pC->pCursor);
  2794   2803         }
  2795   2804       }
         2805  +    assert( pOp->p2>0 );
  2796   2806       if( res ){
  2797         -      if( pOp->p2>0 ){
  2798         -        pc = pOp->p2 - 1;
  2799         -      }else{
  2800         -        pC->nullRow = 1;
  2801         -      }
         2807  +      pc = pOp->p2 - 1;
  2802   2808       }
  2803   2809     }
  2804   2810     break;
  2805   2811   }
  2806   2812   
  2807   2813   /* Opcode: Found P1 P2 P3 * *
  2808   2814   **
................................................................................
  3002   3008       /* res might be uninitialized if rc!=SQLITE_OK.  But if rc!=SQLITE_OK
  3003   3009       ** processing is about to abort so we really do not care whether or not
  3004   3010       ** the following jump is taken.  (In other words, do not stress over
  3005   3011       ** the error that valgrind sometimes shows on the next statement when
  3006   3012       ** running ioerr.test and similar failure-recovery test scripts.) */
  3007   3013       if( res!=0 ){
  3008   3014         pc = pOp->p2 - 1;
  3009         -      pC->rowidIsValid = 0;
         3015  +      assert( pC->rowidIsValid==0 );
  3010   3016       }
  3011   3017     }
  3012   3018     break;
  3013   3019   }
  3014   3020   
  3015   3021   /* Opcode: Sequence P1 P2 * * *
  3016   3022   **
................................................................................
  3152   3158         }
  3153   3159       }
  3154   3160       if( pC->useRandomRowid ){
  3155   3161         assert( pOp->p3==0 );  /* SQLITE_FULL must have occurred prior to this */
  3156   3162         v = db->priorNewRowid;
  3157   3163         cnt = 0;
  3158   3164         do{
  3159         -        if( v==0 || cnt>2 ){
         3165  +        if( cnt==0 && (v&0xffffff)==v ){
         3166  +          v++;
         3167  +        }else{
  3160   3168             sqlite3Randomness(sizeof(v), &v);
  3161   3169             if( cnt<5 ) v &= 0xffffff;
  3162         -        }else{
  3163         -          unsigned char r;
  3164         -          sqlite3Randomness(1, &r);
  3165         -          v += r + 1;
  3166   3170           }
  3167   3171           if( v==0 ) continue;
  3168   3172           x = intToKey(v);
  3169   3173           rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res);
  3170   3174           cnt++;
  3171         -      }while( cnt<1000 && rx==SQLITE_OK && res==0 );
         3175  +      }while( cnt<100 && rx==SQLITE_OK && res==0 );
  3172   3176         db->priorNewRowid = v;
  3173   3177         if( rx==SQLITE_OK && res==0 ){
  3174   3178           rc = SQLITE_FULL;
  3175   3179           goto abort_due_to_error;
  3176   3180         }
  3177   3181       }
  3178   3182       pC->rowidIsValid = 0;
................................................................................
  3290   3294   ** record in the table. If it is left pointing at the next record, then
  3291   3295   ** the next Next instruction will be a no-op.  Hence it is OK to delete
  3292   3296   ** a record from within an Next loop.
  3293   3297   **
  3294   3298   ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
  3295   3299   ** incremented (otherwise not).
  3296   3300   **
  3297         -** If P1 is a pseudo-table, then this instruction is a no-op.
         3301  +** P1 must not be pseudo-table.  It has to be a real table with
         3302  +** multiple rows.
         3303  +**
         3304  +** If P4 is not NULL, then it is the name of the table that P1 is
         3305  +** pointing to.  The update hook will be invoked, if it exists.
         3306  +** If P4 is not NULL then the P1 cursor must have been positioned
         3307  +** using OP_NotFound prior to invoking this opcode.
  3298   3308   */
  3299   3309   case OP_Delete: {
  3300   3310     int i = pOp->p1;
         3311  +  i64 iKey;
  3301   3312     Cursor *pC;
         3313  +
  3302   3314     assert( i>=0 && i<p->nCursor );
  3303   3315     pC = p->apCsr[i];
  3304   3316     assert( pC!=0 );
  3305         -  if( pC->pCursor!=0 ){
  3306         -    i64 iKey;
  3307         -
  3308         -    /* If the update-hook will be invoked, set iKey to the rowid of the
  3309         -    ** row being deleted.
  3310         -    */
  3311         -    if( db->xUpdateCallback && pOp->p4.z ){
  3312         -      assert( pC->isTable );
  3313         -      if( pC->rowidIsValid ){
  3314         -        iKey = pC->lastRowid;
  3315         -      }else{
  3316         -        rc = sqlite3BtreeKeySize(pC->pCursor, &iKey);
  3317         -        if( rc ){
  3318         -          goto abort_due_to_error;
  3319         -        }
  3320         -        iKey = keyToInt(iKey);
  3321         -      }
  3322         -    }
  3323         -
  3324         -    rc = sqlite3VdbeCursorMoveto(pC);
  3325         -    if( rc ) goto abort_due_to_error;
  3326         -    rc = sqlite3BtreeDelete(pC->pCursor);
  3327         -    pC->nextRowidValid = 0;
  3328         -    pC->cacheStatus = CACHE_STALE;
  3329         -
  3330         -    /* Invoke the update-hook if required. */
  3331         -    if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
  3332         -      const char *zDb = db->aDb[pC->iDb].zName;
  3333         -      const char *zTbl = pOp->p4.z;
  3334         -      db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
  3335         -      assert( pC->iDb>=0 );
  3336         -    }
         3317  +  assert( pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
         3318  +
         3319  +  /* If the update-hook will be invoked, set iKey to the rowid of the
         3320  +  ** row being deleted.
         3321  +  */
         3322  +  if( db->xUpdateCallback && pOp->p4.z ){
         3323  +    assert( pC->isTable );
         3324  +    assert( pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
         3325  +    iKey = pC->lastRowid;
         3326  +  }
         3327  +
         3328  +  rc = sqlite3VdbeCursorMoveto(pC);
         3329  +  if( rc ) goto abort_due_to_error;
         3330  +  rc = sqlite3BtreeDelete(pC->pCursor);
         3331  +  pC->nextRowidValid = 0;
         3332  +  pC->cacheStatus = CACHE_STALE;
         3333  +
         3334  +  /* Invoke the update-hook if required. */
         3335  +  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
         3336  +    const char *zDb = db->aDb[pC->iDb].zName;
         3337  +    const char *zTbl = pOp->p4.z;
         3338  +    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
         3339  +    assert( pC->iDb>=0 );
  3337   3340     }
  3338   3341     if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  3339   3342     break;
  3340   3343   }
  3341   3344   
  3342   3345   /* Opcode: ResetCount P1 * *
  3343   3346   **
................................................................................
  4709   4712       }
  4710   4713   #endif /* SQLITE_DEBUG */
  4711   4714     }
  4712   4715     break;
  4713   4716   }
  4714   4717   #endif
  4715   4718   
  4716         -/* An other opcode is illegal...
         4719  +
         4720  +/* Opcode: Noop * * * * *
         4721  +**
         4722  +** Do nothing.  This instruction is often useful as a jump
         4723  +** destination.
         4724  +*/
         4725  +/*
         4726  +** The magic Explain opcode are only inserted when explain==2 (which
         4727  +** is to say when the EXPLAIN QUERY PLAN syntax is used.)
         4728  +** This opcode records information from the optimizer.  It is the
         4729  +** the same as a no-op.  This opcodesnever appears in a real VM program.
  4717   4730   */
  4718         -default: {
  4719         -  assert( 0 );
         4731  +default: {          /* This is really OP_Noop and OP_Explain */
  4720   4732     break;
  4721   4733   }
  4722   4734   
  4723   4735   /*****************************************************************************
  4724   4736   ** The cases of the switch statement above this line should all be indented
  4725   4737   ** by 6 spaces.  But the left-most 6 spaces have been removed to improve the
  4726   4738   ** readability.  From this point on down, the normal indentation rules are

Changes to src/vdbeaux.c.

   507    507   ** to a string or structure that is guaranteed to exist for the lifetime of
   508    508   ** the Vdbe. In these cases we can just copy the pointer.
   509    509   **
   510    510   ** If addr<0 then change P4 on the most recently inserted instruction.
   511    511   */
   512    512   void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
   513    513     Op *pOp;
   514         -  assert( p==0 || p->magic==VDBE_MAGIC_INIT );
   515         -  if( p==0 || p->aOp==0 || p->db->mallocFailed ){
          514  +  assert( p!=0 );
          515  +  assert( p->magic==VDBE_MAGIC_INIT );
          516  +  if( p->aOp==0 || p->db->mallocFailed ){
   516    517       if (n != P4_KEYINFO) {
   517    518         freeP4(n, (void*)*(char**)&zP4);
   518    519       }
   519    520       return;
   520    521     }
   521         -  if( addr<0 || addr>=p->nOp ){
          522  +  assert( addr<p->nOp );
          523  +  if( addr<0 ){
   522    524       addr = p->nOp - 1;
   523    525       if( addr<0 ) return;
   524    526     }
   525    527     pOp = &p->aOp[addr];
   526    528     freeP4(pOp->p4type, pOp->p4.p);
   527    529     pOp->p4.p = 0;
   528    530     if( n==P4_INT32 ){
................................................................................
   536    538       int nField, nByte;
   537    539   
   538    540       nField = ((KeyInfo*)zP4)->nField;
   539    541       nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
   540    542       pKeyInfo = sqlite3_malloc( nByte );
   541    543       pOp->p4.pKeyInfo = pKeyInfo;
   542    544       if( pKeyInfo ){
   543         -      unsigned char *aSortOrder;
   544    545         memcpy(pKeyInfo, zP4, nByte);
          546  +      /* In the current implementation, P4_KEYINFO is only ever used on
          547  +      ** KeyInfo structures that have no aSortOrder component.  Elements
          548  +      ** with an aSortOrder always use P4_KEYINFO_HANDOFF.  So we do not
          549  +      ** need to bother with duplicating the aSortOrder. */
          550  +      assert( pKeyInfo->aSortOrder==0 );
          551  +#if 0
   545    552         aSortOrder = pKeyInfo->aSortOrder;
   546    553         if( aSortOrder ){
   547    554           pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
   548    555           memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
   549    556         }
          557  +#endif
   550    558         pOp->p4type = P4_KEYINFO;
   551    559       }else{
   552    560         p->db->mallocFailed = 1;
   553    561         pOp->p4type = P4_NOTUSED;
   554    562       }
   555    563     }else if( n==P4_KEYINFO_HANDOFF ){
   556    564       pOp->p4.p = (void*)zP4;

Changes to src/where.c.

    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  This module is reponsible for
    14     14   ** generating the code that loops through a table looking for applicable
    15     15   ** rows.  Indices are selected and used to speed the search when doing
    16     16   ** so is applicable.  Because this module is responsible for selecting
    17     17   ** indices, you might also think of this module as the "query optimizer".
    18     18   **
    19         -** $Id: where.c,v 1.283 2008/01/17 16:22:15 drh Exp $
           19  +** $Id: where.c,v 1.284 2008/01/19 20:11:26 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   
    23     23   /*
    24     24   ** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
    25     25   */
    26     26   #define BMS  (sizeof(Bitmask)*8)
................................................................................
  2552   2552         r1 = sqlite3GetTempReg(pParse);
  2553   2553         if( topLimit | btmLimit ){
  2554   2554           sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
  2555   2555           sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
  2556   2556         }
  2557   2557         if( !omitTable ){
  2558   2558           sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
  2559         -        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
         2559  +        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);  /* Deferred seek */
  2560   2560         }
  2561   2561         sqlite3ReleaseTempReg(pParse, r1);
  2562   2562   
  2563   2563         /* Record the instruction used to terminate the loop.
  2564   2564         */
  2565   2565         pLevel->op = bRev ? OP_Prev : OP_Next;
  2566   2566         pLevel->p1 = iIdxCur;
................................................................................
  2627   2627           start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem);
  2628   2628           sqlite3VdbeChangeP5(v, 1);
  2629   2629           pLevel->op = OP_Next;
  2630   2630         }
  2631   2631         if( !omitTable ){
  2632   2632           r1 = sqlite3GetTempReg(pParse);
  2633   2633           sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
  2634         -        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
         2634  +        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);  /* Deferred seek */
  2635   2635           sqlite3ReleaseTempReg(pParse, r1);
  2636   2636         }
  2637   2637         pLevel->p1 = iIdxCur;
  2638   2638         pLevel->p2 = start;
  2639   2639       }else{
  2640   2640         /* Case 5:  There is no usable index.  We must do a complete
  2641   2641         **          scan of the entire table.

Changes to test/all.test.

     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file runs all tests.
    12     12   #
    13         -# $Id: all.test,v 1.52 2007/11/27 14:46:42 drh Exp $
           13  +# $Id: all.test,v 1.53 2008/01/19 20:11:26 drh Exp $
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   rename finish_test really_finish_test
    18     18   proc finish_test {} {
    19     19     # no-op
    20     20   }
................................................................................
    88     88     } else {
    89     89       catch {unset ::SETUP_SQL}
    90     90     }
    91     91     foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
    92     92       set tail [file tail $testfile]
    93     93       if {[lsearch -exact $EXCLUDE $tail]>=0} continue
    94     94       if {[llength $INCLUDE]>0 && [lsearch -exact $INCLUDE $tail]<0} continue
           95  +    reset_prng_state
    95     96       source $testfile
    96     97       catch {db close}
    97     98       if {$sqlite_open_file_count>0} {
    98     99         puts "$tail did not close all files: $sqlite_open_file_count"
    99    100         incr nErr
   100    101         lappend ::failList $tail
   101    102         set sqlite_open_file_count 0

Changes to test/cast.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the CAST operator.
    13     13   #
    14         -# $Id: cast.test,v 1.8 2007/08/13 15:18:28 drh Exp $
           14  +# $Id: cast.test,v 1.9 2008/01/19 20:11:26 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Only run these tests if the build includes the CAST operator
    20     20   ifcapable !cast {
    21     21     finish_test
................................................................................
   178    178   } integer
   179    179   do_test cast-1.51 {
   180    180     execsql {SELECT CAST('123.5abc' AS numeric)}
   181    181   } 123.5
   182    182   do_test cast-1.53 {
   183    183     execsql {SELECT CAST('123.5abc' AS integer)}
   184    184   } 123
          185  +
          186  +do_test case-1.60 {
          187  +  execsql {SELECT CAST(null AS REAL)}
          188  +} {{}}
          189  +do_test case-1.61 {
          190  +  execsql {SELECT typeof(CAST(null AS REAL))}
          191  +} {null}
          192  +do_test case-1.62 {
          193  +  execsql {SELECT CAST(1 AS REAL)}
          194  +} {1.0}
          195  +do_test case-1.63 {
          196  +  execsql {SELECT typeof(CAST(1 AS REAL))}
          197  +} {real}
          198  +do_test case-1.64 {
          199  +  execsql {SELECT CAST('1' AS REAL)}
          200  +} {1.0}
          201  +do_test case-1.65 {
          202  +  execsql {SELECT typeof(CAST('1' AS REAL))}
          203  +} {real}
          204  +do_test case-1.66 {
          205  +  execsql {SELECT CAST('abc' AS REAL)}
          206  +} {0.0}
          207  +do_test case-1.67 {
          208  +  execsql {SELECT typeof(CAST('abc' AS REAL))}
          209  +} {real}
          210  +do_test case-1.68 {
          211  +  execsql {SELECT CAST(x'31' AS REAL)}
          212  +} {1.0}
          213  +do_test case-1.69 {
          214  +  execsql {SELECT typeof(CAST(x'31' AS REAL))}
          215  +} {real}
          216  +
   185    217   
   186    218   # Ticket #1662.  Ignore leading spaces in numbers when casting.
   187    219   #
   188    220   do_test cast-2.1 {
   189    221     execsql {SELECT CAST('   123' AS integer)}
   190    222   } 123
   191    223   do_test cast-2.2 {

Changes to test/expr.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing expressions.
    13     13   #
    14         -# $Id: expr.test,v 1.60 2008/01/16 18:20:42 danielk1977 Exp $
           14  +# $Id: expr.test,v 1.61 2008/01/19 20:11:26 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
................................................................................
    68     68   test_expr expr-1.40 {i1=1, i2=2} {+(i2+i1)} {3}
    69     69   test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3}
    70     70   test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3}
    71     71   test_expr expr-1.42b {i1=1, i2=2} {4|2} {6}
    72     72   test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
    73     73   test_expr expr-1.43b {i1=1, i2=2} {4&5} {4}
    74     74   test_expr expr-1.44 {i1=1} {~i1} {-2}
           75  +test_expr expr-1.44b {i1=NULL} {~i1} {{}}
    75     76   test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
    76     77   test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
    77     78   test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1<i2} 0
    78     79   test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0
    79     80   test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1
    80     81   test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1<i2} 0
    81     82   test_expr expr-1.51 {i1=99999999999, i2=99999999998} {i1=i2} 0
................................................................................
   137    138   
   138    139   test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
   139    140   test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
   140    141   test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
   141    142   
   142    143   test_expr expr-1.106 {i1=0} {(1<<63)/-1} -9223372036854775808
   143    144   test_expr expr-1.107 {i1=0} {(1<<63)%-1} 0
          145  +test_expr expr-1.108 {i1=0} {1%0} {{}}
          146  +test_expr expr-1.109 {i1=0} {1/0} {{}}
   144    147   
   145    148   test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
   146    149   test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
   147    150   test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
   148    151   set tcl_precision 15
   149    152   test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
   150    153   test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024
................................................................................
   165    168   test_expr expr-2.20 {r1=2.34, r2=2.34} {r2<>r1} 0
   166    169   test_expr expr-2.21 {r1=2.34, r2=2.34} {r2==r1} 1
   167    170   test_expr expr-2.22 {r1=1.23, r2=2.34} {min(r1,r2,r1+r2,r1-r2)} {-1.11}
   168    171   test_expr expr-2.23 {r1=1.23, r2=2.34} {max(r1,r2,r1+r2,r1-r2)} {3.57}
   169    172   test_expr expr-2.24 {r1=25.0, r2=11.0} {r1%r2} 3.0
   170    173   test_expr expr-2.25 {r1=1.23, r2=NULL} {coalesce(r1+r2,99.0)} 99.0
   171    174   test_expr expr-2.26 {r1=1e300, r2=1e300} {coalesce((r1*r2)*0.0,99.0)} 99.0
          175  +test_expr expr-2.27 {r1=1.1, r2=0.0} {r1/r2} {{}}
          176  +test_expr expr-2.28 {r1=1.1, r2=0.0} {r1%r2} {{}}
   172    177   
   173    178   test_expr expr-3.1 {t1='abc', t2='xyz'} {t1<t2} 1
   174    179   test_expr expr-3.2 {t1='xyz', t2='abc'} {t1<t2} 0
   175    180   test_expr expr-3.3 {t1='abc', t2='abc'} {t1<t2} 0
   176    181   test_expr expr-3.4 {t1='abc', t2='xyz'} {t1<=t2} 1
   177    182   test_expr expr-3.5 {t1='xyz', t2='abc'} {t1<=t2} 0
   178    183   test_expr expr-3.6 {t1='abc', t2='abc'} {t1<=t2} 1

Changes to test/hook.test.

    13     13   #
    14     14   # The focus of the tests in this file is the  following interface:
    15     15   #
    16     16   #      sqlite_commit_hook    (tests hook-1..hook-3 inclusive)
    17     17   #      sqlite_update_hook    (tests hook-4-*)
    18     18   #      sqlite_rollback_hook  (tests hook-5.*)
    19     19   #
    20         -# $Id: hook.test,v 1.12 2007/10/09 08:29:32 danielk1977 Exp $
           20  +# $Id: hook.test,v 1.13 2008/01/19 20:11:26 drh Exp $
    21     21   
    22     22   set testdir [file dirname $argv0]
    23     23   source $testdir/tester.tcl
    24     24   
    25     25   do_test hook-1.2 {
    26     26     db commit_hook
    27     27   } {}
................................................................................
   132    132       DELETE main t1 2 \
   133    133       UPDATE main t1 1 \
   134    134       UPDATE main t1 3 \
   135    135       DELETE main t1 1 \
   136    136       DELETE main t1 3 \
   137    137       DELETE main t1 4 \
   138    138   ]
          139  +
          140  +# Update hook is not invoked for changes to sqlite_master
          141  +#
          142  +do_test hook-4.1.3 {
          143  +  set ::update_hook {}
          144  +  execsql {
          145  +    CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT RAISE(IGNORE); END;
          146  +  }
          147  +  set ::update_hook
          148  +} {}
          149  +do_test hook-4.1.4 {
          150  +  set ::update_hook {}
          151  +  execsql {
          152  +    DROP TRIGGER r1;
          153  +  }
          154  +  set ::update_hook
          155  +} {}
          156  +
   139    157   
   140    158   set ::update_hook {}
   141    159   ifcapable trigger {
   142    160     do_test hook-4.2.1 {
   143    161       catchsql {
   144    162         DROP TABLE t2;
   145    163       }

Changes to test/incrvacuum.test.

    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the incremental vacuum feature.
    13     13   #
    14     14   # Note: There are also some tests for incremental vacuum and IO 
    15     15   # errors in incrvacuum_ioerr.test.
    16     16   #
    17         -# $Id: incrvacuum.test,v 1.16 2007/12/13 21:54:11 drh Exp $
           17  +# $Id: incrvacuum.test,v 1.17 2008/01/19 20:11:26 drh Exp $
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22     22   # If this build of the library does not support auto-vacuum, omit this
    23     23   # whole file.
    24     24   ifcapable {!autovacuum || !pragma} {
................................................................................
   545    545     execsql {
   546    546       PRAGMA incremental_vacuum('1');
   547    547     }
   548    548     expr [file size test.db] / 1024
   549    549   } {22}
   550    550   
   551    551   do_test incrvacuum-10.5 {
   552         -breakpoint
   553    552     execsql {
   554    553       PRAGMA incremental_vacuum("+3");
   555    554     }
   556    555     expr [file size test.db] / 1024
   557    556   } {19}
   558    557   
   559    558   do_test incrvacuum-10.6 {
................................................................................
   564    563   } {18}
   565    564   
   566    565   do_test incrvacuum-10.7 {
   567    566     # Use a really big number as an argument to incremetal_vacuum. Should
   568    567     # be interpreted as "free all possible space".
   569    568     execsql {
   570    569       PRAGMA incremental_vacuum(2147483649);
          570  +  }
          571  +  expr [file size test.db] / 1024
          572  +} {1}
          573  +
          574  +do_test incrvacuum-10.8 {
          575  +  execsql {
          576  +    CREATE TABLE t1(x);
          577  +    INSERT INTO t1 VALUES(hex(randomblob(1000)));
          578  +    DROP TABLE t1;
          579  +  }
          580  +  # A negative number means free all possible space.
          581  +  execsql {
          582  +    PRAGMA incremental_vacuum=-1;
   571    583     }
   572    584     expr [file size test.db] / 1024
   573    585   } {1}
   574    586   
   575    587   #----------------------------------------------------------------
   576    588   # Test that if we set the auto_vacuum mode to 'incremental', then
   577    589   # create a database, thereafter that database defaults to incremental 

Changes to test/misc3.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for miscellanous features that were
    14     14   # left out of other test files.
    15     15   #
    16         -# $Id: misc3.test,v 1.16 2005/01/21 03:12:16 danielk1977 Exp $
           16  +# $Id: misc3.test,v 1.17 2008/01/19 20:11:26 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   ifcapable {integrityck} {
    22     22     # Ticket #529.  Make sure an ABORT does not damage the in-memory cache
    23     23     # that will be used by subsequent statements in the same transaction.
................................................................................
   254    254       execsql {EXPLAIN COMMIT}
   255    255       catchsql {COMMIT}
   256    256     } {0 {}}
   257    257     do_test misc3-6.3 {
   258    258       execsql {BEGIN; EXPLAIN ROLLBACK}
   259    259       catchsql {ROLLBACK}
   260    260     } {0 {}}
          261  +
          262  +  # Do some additional EXPLAIN operations to exercise the displayP4 logic.
          263  +  do_test misc3-6.10 {
          264  +    set x [execsql {
          265  +      CREATE TABLE ex1(a INTEGER, b TEXT DEFAULT "hello", c);
          266  +      CREATE UNIQUE INDEX ex1i1 ON ex1(a);
          267  +      EXPLAIN REINDEX;
          268  +    }]
          269  +    regexp { IsUnique \d+ \d+ \d+ \d+ } $x
          270  +  } {1}
          271  +  do_test misc3-6.11 {
          272  +    set x [execsql {
          273  +      EXPLAIN SELECT a+123456789012, b*4.5678, c FROM ex1 ORDER BY a, b DESC
          274  +    }]
          275  +    set y [regexp { 123456789012 } $x]
          276  +    lappend y [regexp { 4.5678 } $x]
          277  +    lappend y [regexp { hello } $x]
          278  +    lappend y [regexp {,-BINARY} $x]
          279  +  } {1 1 1 1}
          280  +
   261    281   }
   262    282   
   263    283   ifcapable {trigger} {
   264    284   # Ticket #640:  vdbe stack overflow with a LIMIT clause on a SELECT inside
   265    285   # of a trigger.
   266    286   #
   267    287   do_test misc3-7.1 {

Changes to test/rowid.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the magic ROWID column that is
    13     13   # found on all tables.
    14     14   #
    15         -# $Id: rowid.test,v 1.19 2007/04/25 11:32:30 drh Exp $
           15  +# $Id: rowid.test,v 1.20 2008/01/19 20:11:26 drh Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Basic ROWID functionality tests.
    21     21   #
    22     22   do_test rowid-1.1 {
................................................................................
   653    653   do_test rowid-11.4 {
   654    654     execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc'}
   655    655   } {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
   656    656   
   657    657   # Test the automatic generation of rowids when the table already contains
   658    658   # a rowid with the maximum value.
   659    659   #
          660  +# Once the the maximum rowid is taken, rowids are normally chosen at
          661  +# random.  By by reseting the random number generator, we can cause
          662  +# the rowid guessing loop to collide with prior rowids, and test the
          663  +# loop out to its limit of 100 iterations.  After 100 collisions, the
          664  +# rowid guesser gives up and reports SQLITE_FULL.
          665  +#
   660    666   do_test rowid-12.1 {
   661    667     execsql {
   662    668       CREATE TABLE t7(x INTEGER PRIMARY KEY, y);
   663    669       INSERT INTO t7 VALUES(9223372036854775807,'a');
   664    670       SELECT y FROM t7;
   665    671     }
   666    672   } {a}
   667    673   do_test rowid-12.2 {
          674  +  db close
          675  +  sqlite3 db test.db
          676  +  save_prng_state
   668    677     execsql {
   669    678       INSERT INTO t7 VALUES(NULL,'b');
   670         -    SELECT y FROM t7;
          679  +    SELECT x, y FROM t7;
          680  +  }
          681  +} {1 b 9223372036854775807 a}
          682  +execsql {INSERT INTO t7 VALUES(2,'y');}
          683  +for {set i 1} {$i<=101} {incr i} {
          684  +  do_test rowid-12.3.$i {
          685  +    restore_prng_state
          686  +    execsql {
          687  +      INSERT INTO t7 VALUES(NULL,'x');
          688  +      INSERT OR IGNORE INTO t7 VALUES(last_insert_rowid()+1,'y');
          689  +      SELECT count(*) FROM t7 WHERE y=='x';
          690  +    }
          691  +  } $i
          692  +}
          693  +do_test rowid-12.4 {
          694  +  restore_prng_state
          695  +  catchsql {
          696  +    INSERT INTO t7 VALUES(NULL,'x');
   671    697     }
   672         -} {b a}
          698  +} {1 {database or disk is full}}
          699  +
   673    700   
   674    701   finish_test

Changes to test/softheap1.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # 
    12     12   # This test script reproduces the problem reported by ticket #2565,
    13     13   # A database corruption bug that occurs in auto_vacuum mode when
    14     14   # the soft_heap_limit is set low enough to be triggered.
    15     15   #
    16         -# $Id: softheap1.test,v 1.3 2007/09/12 17:01:45 danielk1977 Exp $
           16  +# $Id: softheap1.test,v 1.4 2008/01/19 20:11:26 drh Exp $
    17     17   
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22     22   ifcapable !integrityck {
    23     23     finish_test
    24     24     return
    25     25   }
    26     26   
           27  +sqlite3_soft_heap_limit -1
           28  +sqlite3_soft_heap_limit 0
    27     29   sqlite3_soft_heap_limit 5000
    28     30   do_test softheap1-1.1 {
    29     31     execsql {
    30     32       PRAGMA auto_vacuum=1;
    31     33       CREATE TABLE t1(x);
    32     34       INSERT INTO t1 VALUES(hex(randomblob(1000)));
    33     35       BEGIN;

Changes to test/tester.tcl.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements some common TCL routines used for regression
    12     12   # testing the SQLite library
    13     13   #
    14         -# $Id: tester.tcl,v 1.101 2008/01/17 02:36:28 drh Exp $
           14  +# $Id: tester.tcl,v 1.102 2008/01/19 20:11:26 drh Exp $
    15     15   
    16     16   
    17     17   set tcl_precision 15
    18     18   set sqlite_pending_byte 0x0010000
    19     19   
    20     20   # 
    21     21   # Check the command-line arguments for a default soft-heap-limit.
................................................................................
   217    217       }
   218    218     } else {
   219    219       puts "All memory allocations freed - no leaks"
   220    220       ifcapable memdebug {
   221    221         sqlite3_memdebug_dump ./memusage.txt
   222    222       }
   223    223     }
   224         -  puts "Maximum memory usage: [sqlite3_memory_highwater] bytes"
          224  +  puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
          225  +  puts "Current memory usage: [sqlite3_memory_highwater] bytes"
   225    226     foreach f [glob -nocomplain test.db-*-journal] {
   226    227       file delete -force $f
   227    228     }
   228    229     foreach f [glob -nocomplain test.db-mj*] {
   229    230       file delete -force $f
   230    231     }
   231    232     exit [expr {$nErr>0}]