/ Check-in [15368a9f]
Login
Overview
Comment:Merge trunk changes into experimental branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:15368a9f8523d5fb611cd576080daed2cf2f1500
User & Date: dan 2010-08-03 18:29:05
Context
2010-08-04
19:14
Fix some problems with error recovery introduced while reworking pager state. check-in: 77eaab6f user: dan tags: experimental
2010-08-03
18:29
Merge trunk changes into experimental branch. check-in: 15368a9f user: dan tags: experimental
18:18
Set the Pager.eState variable to PAGER_ERROR whenever the pager enters the error state. check-in: 4d384761 user: dan tags: experimental
18:06
Fix disabled implementation-mark comments in func.c. check-in: 57c09600 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  7843   7843   /*
  7844   7844   ** Return non-zero if a transaction is active.
  7845   7845   */
  7846   7846   int sqlite3BtreeIsInTrans(Btree *p){
  7847   7847     assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
  7848   7848     return (p && (p->inTrans==TRANS_WRITE));
  7849   7849   }
         7850  +
         7851  +#ifndef SQLITE_OMIT_WAL
         7852  +/*
         7853  +** Run a checkpoint on the Btree passed as the first argument.
         7854  +**
         7855  +** Return SQLITE_LOCKED if this or any other connection has an open 
         7856  +** transaction on the shared-cache the argument Btree is connected to.
         7857  +*/
         7858  +int sqlite3BtreeCheckpoint(Btree *p){
         7859  +  int rc = SQLITE_OK;
         7860  +  if( p ){
         7861  +    BtShared *pBt = p->pBt;
         7862  +    sqlite3BtreeEnter(p);
         7863  +    if( pBt->inTransaction!=TRANS_NONE ){
         7864  +      rc = SQLITE_LOCKED;
         7865  +    }else{
         7866  +      rc = sqlite3PagerCheckpoint(pBt->pPager);
         7867  +    }
         7868  +    sqlite3BtreeLeave(p);
         7869  +  }
         7870  +  return rc;
         7871  +}
         7872  +#endif
  7850   7873   
  7851   7874   /*
  7852   7875   ** Return non-zero if a read (or write) transaction is active.
  7853   7876   */
  7854   7877   int sqlite3BtreeIsInReadTrans(Btree *p){
  7855   7878     assert( p );
  7856   7879     assert( sqlite3_mutex_held(p->db->mutex) );

Changes to src/btree.h.

   196    196   int sqlite3BtreeCount(BtCursor *, i64 *);
   197    197   #endif
   198    198   
   199    199   #ifdef SQLITE_TEST
   200    200   int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
   201    201   void sqlite3BtreeCursorList(Btree*);
   202    202   #endif
          203  +
          204  +#ifndef SQLITE_OMIT_WAL
          205  +  int sqlite3BtreeCheckpoint(Btree*);
          206  +#endif
   203    207   
   204    208   /*
   205    209   ** If we are not using shared cache, then there is no need to
   206    210   ** use mutexes to access the BtShared structures.  So make the
   207    211   ** Enter and Leave procedures no-ops.
   208    212   */
   209    213   #ifndef SQLITE_OMIT_SHARED_CACHE

Changes to src/func.c.

   784    784     sqlite3_context *context,
   785    785     int argc,
   786    786     sqlite3_value **argv
   787    787   ){
   788    788     const char *zOptName;
   789    789     assert( argc==1 );
   790    790     UNUSED_PARAMETER(argc);
   791         -  /* IMP: R-xxxx This function is an SQL wrapper around the
   792         -  ** sqlite3_compileoption_used() C interface. */
          791  +  /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL
          792  +  ** function is a wrapper around the sqlite3_compileoption_used() C/C++
          793  +  ** function.
          794  +  */
   793    795     if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
   794    796       sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
   795    797     }
   796    798   }
   797    799   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
   798    800   
   799    801   /*
................................................................................
   806    808     sqlite3_context *context,
   807    809     int argc,
   808    810     sqlite3_value **argv
   809    811   ){
   810    812     int n;
   811    813     assert( argc==1 );
   812    814     UNUSED_PARAMETER(argc);
   813         -  /* IMP: R-xxxx This function is an SQL wrapper around the
   814         -  ** sqlite3_compileoption_get() C interface. */
          815  +  /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
          816  +  ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
          817  +  */
   815    818     n = sqlite3_value_int(argv[0]);
   816    819     sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
   817    820   }
   818    821   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
   819    822   
   820    823   /* Array for converting from half-bytes (nybbles) into ASCII hex
   821    824   ** digits. */

Changes to src/insert.c.

  1216   1216       int allOk = sqlite3VdbeMakeLabel(v);
  1217   1217       pParse->ckBase = regData;
  1218   1218       sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);
  1219   1219       onError = overrideError!=OE_Default ? overrideError : OE_Abort;
  1220   1220       if( onError==OE_Ignore ){
  1221   1221         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
  1222   1222       }else{
         1223  +      if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
  1223   1224         sqlite3HaltConstraint(pParse, onError, 0, 0);
  1224   1225       }
  1225   1226       sqlite3VdbeResolveLabel(v, allOk);
  1226   1227     }
  1227   1228   #endif /* !defined(SQLITE_OMIT_CHECK) */
  1228   1229   
  1229   1230     /* If we have an INTEGER PRIMARY KEY, make sure the primary key

Changes to src/main.c.

  1304   1304     int rc = SQLITE_OK;             /* Return code */
  1305   1305     int i;                          /* Used to iterate through attached dbs */
  1306   1306   
  1307   1307     assert( sqlite3_mutex_held(db->mutex) );
  1308   1308   
  1309   1309     for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
  1310   1310       if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
  1311         -      Btree *pBt = db->aDb[i].pBt;
  1312         -      if( pBt ){
  1313         -        if( sqlite3BtreeIsInReadTrans(pBt) ){
  1314         -          rc = SQLITE_LOCKED;
  1315         -        }else{
  1316         -          sqlite3BtreeEnter(pBt);
  1317         -          rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
  1318         -          sqlite3BtreeLeave(pBt);
  1319         -        }
  1320         -      }
         1311  +      rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt);
  1321   1312       }
  1322   1313     }
  1323   1314   
  1324   1315     return rc;
  1325   1316   }
  1326   1317   #endif /* SQLITE_OMIT_WAL */
  1327   1318   

Changes to src/pager.c.

  5557   5557         ** journal requires a sync here. However, in locking_mode=exclusive
  5558   5558         ** on a system under memory pressure it is just possible that this is 
  5559   5559         ** not the case. In this case it is likely enough that the redundant
  5560   5560         ** xSync() call will be changed to a no-op by the OS anyhow. 
  5561   5561         */
  5562   5562         rc = syncJournal(pPager, 0);
  5563   5563         if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
  5564         -
         5564  +  
  5565   5565         rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
  5566   5566         if( rc!=SQLITE_OK ){
  5567   5567           assert( rc!=SQLITE_IOERR_BLOCKED );
  5568   5568           goto commit_phase_one_exit;
  5569   5569         }
  5570   5570         sqlite3PcacheCleanAll(pPager->pPCache);
  5571   5571     

Changes to src/tclsqlite.c.

  2567   2567     ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or 
  2568   2568     ** SQLITE_STMTSTATUS_SORT for the most recent eval.
  2569   2569     */
  2570   2570     case DB_STATUS: {
  2571   2571       int v;
  2572   2572       const char *zOp;
  2573   2573       if( objc!=3 ){
  2574         -      Tcl_WrongNumArgs(interp, 2, objv, "(step|sort)");
         2574  +      Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)");
  2575   2575         return TCL_ERROR;
  2576   2576       }
  2577   2577       zOp = Tcl_GetString(objv[2]);
  2578   2578       if( strcmp(zOp, "step")==0 ){
  2579   2579         v = pDb->nStep;
  2580   2580       }else if( strcmp(zOp, "sort")==0 ){
  2581   2581         v = pDb->nSort;

Changes to src/update.c.

     4      4   ** The author disclaims copyright to this source code.  In place of
     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11         -sqlite*************************************************************************
           11  +*************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle UPDATE statements.
    14     14   */
    15     15   #include "sqliteInt.h"
    16     16   
    17     17   #ifndef SQLITE_OMIT_VIRTUALTABLE
    18     18   /* Forward declaration */

Changes to src/vdbeaux.c.

  2396   2396   #ifdef SQLITE_TEST
  2397   2397       extern int sqlite3_search_count;
  2398   2398   #endif
  2399   2399       assert( p->isTable );
  2400   2400       rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
  2401   2401       if( rc ) return rc;
  2402   2402       p->lastRowid = p->movetoTarget;
  2403         -    p->rowidIsValid = ALWAYS(res==0) ?1:0;
  2404         -    if( NEVER(res<0) ){
  2405         -      rc = sqlite3BtreeNext(p->pCursor, &res);
  2406         -      if( rc ) return rc;
  2407         -    }
         2403  +    if( res!=0 ) return SQLITE_CORRUPT_BKPT;
         2404  +    p->rowidIsValid = 1;
  2408   2405   #ifdef SQLITE_TEST
  2409   2406       sqlite3_search_count++;
  2410   2407   #endif
  2411   2408       p->deferredMoveto = 0;
  2412   2409       p->cacheStatus = CACHE_STALE;
  2413   2410     }else if( ALWAYS(p->pCursor) ){
  2414   2411       int hasMoved;

Changes to src/vdbemem.c.

  1012   1012   
  1013   1013     if( !pExpr ){
  1014   1014       *ppVal = 0;
  1015   1015       return SQLITE_OK;
  1016   1016     }
  1017   1017     op = pExpr->op;
  1018   1018   
  1019         -  /* op can only be TK_REGISTER is we have compiled with SQLITE_ENABLE_STAT2.
         1019  +  /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT2.
  1020   1020     ** The ifdef here is to enable us to achieve 100% branch test coverage even
  1021   1021     ** when SQLITE_ENABLE_STAT2 is omitted.
  1022   1022     */
  1023   1023   #ifdef SQLITE_ENABLE_STAT2
  1024   1024     if( op==TK_REGISTER ) op = pExpr->op2;
  1025   1025   #else
  1026   1026     if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;

Changes to test/conflict.test.

   784    784   do_test conflict-12.4 {
   785    785     execsql {
   786    786       UPDATE OR REPLACE t5 SET a=a+1 WHERE a=1;
   787    787       SELECT * FROM t5;
   788    788     }
   789    789   } {2 one}
   790    790   
          791  +
          792  +# Ticket [c38baa3d969eab7946dc50ba9d9b4f0057a19437]
          793  +# REPLACE works like ABORT on a CHECK constraint.
          794  +#
          795  +do_test conflict-13.1 {
          796  +  execsql {
          797  +    CREATE TABLE t13(a CHECK(a!=2));
          798  +    BEGIN;
          799  +    REPLACE INTO t13 VALUES(1);
          800  +  }
          801  +  catchsql {
          802  +    REPLACE INTO t13 VALUES(2);
          803  +  }
          804  +} {1 {constraint failed}}
          805  +do_test conflict-13.2 {
          806  +  execsql {
          807  +    REPLACE INTO t13 VALUES(3);
          808  +    COMMIT;
          809  +    SELECT * FROM t13;
          810  +  }
          811  +} {1 3}
          812  +
   791    813   
   792    814   finish_test

Changes to test/wal2.test.

   976    976   } {wal 1 2 3 4 5 6 7 8 9}
   977    977   
   978    978   do_test wal2-11.1.1 {
   979    979     sqlite3 db2 test.db
   980    980     execsql { SELECT name FROM sqlite_master } db2
   981    981   } {t1}
   982    982   
   983         -# Set all zeroed slots in the first hash table to invalid values.
   984         -#
   985         -set blob [string range [tvfs shm $::filename] 0 16383]
   986         -set I [string range [tvfs shm $::filename] 16384 end]
   987         -binary scan $I t* L
   988         -set I [list]
   989         -foreach p $L {
   990         -  lappend I [expr $p ? $p : 400]
   991         -}
   992         -append blob [binary format t* $I]
   993         -tvfs shm $::filename $blob
   994         -do_test wal2-11.2 {
   995         -  catchsql { INSERT INTO t1 VALUES(10, 11, 12) }
   996         -} {1 {database disk image is malformed}}
   997         -
   998         -# Fill up the hash table on the first page of shared memory with 0x55 bytes.
   999         -#
  1000         -set blob [string range [tvfs shm $::filename] 0 16383]
  1001         -append blob [string repeat [binary format c 55] 16384]
  1002         -tvfs shm $::filename $blob
  1003         -do_test wal2-11.3 {
  1004         -  catchsql { SELECT * FROM t1 } db2
  1005         -} {1 {database disk image is malformed}}
          983  +if {$::tcl_version>=8.5} {
          984  +  # Set all zeroed slots in the first hash table to invalid values.
          985  +  #
          986  +  set blob [string range [tvfs shm $::filename] 0 16383]
          987  +  set I [string range [tvfs shm $::filename] 16384 end]
          988  +  binary scan $I t* L
          989  +  set I [list]
          990  +  foreach p $L {
          991  +    lappend I [expr $p ? $p : 400]
          992  +  }
          993  +  append blob [binary format t* $I]
          994  +  tvfs shm $::filename $blob
          995  +  do_test wal2-11.2 {
          996  +    catchsql { INSERT INTO t1 VALUES(10, 11, 12) }
          997  +  } {1 {database disk image is malformed}}
          998  +  
          999  +  # Fill up the hash table on the first page of shared memory with 0x55 bytes.
         1000  +  #
         1001  +  set blob [string range [tvfs shm $::filename] 0 16383]
         1002  +  append blob [string repeat [binary format c 55] 16384]
         1003  +  tvfs shm $::filename $blob
         1004  +  do_test wal2-11.3 {
         1005  +    catchsql { SELECT * FROM t1 } db2
         1006  +  } {1 {database disk image is malformed}}
         1007  +}
  1006   1008   
  1007   1009   db close
  1008   1010   db2 close
  1009   1011   tvfs delete
  1010   1012   
  1011   1013   #-------------------------------------------------------------------------
  1012   1014   # If a connection is required to create a WAL or SHM file, it creates 
................................................................................
  1144   1146         } $b($can_read,$can_write)
  1145   1147       }
  1146   1148       catch { db close }
  1147   1149     }
  1148   1150   }
  1149   1151   
  1150   1152   finish_test
  1151         -

Added test/walshared.test.

            1  +# 2010 August 2
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is testing the operation of the library in
           13  +# "PRAGMA journal_mode=WAL" mode with shared-cache turned on.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +db close
           19  +set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
           20  +
           21  +sqlite3 db  test.db
           22  +sqlite3 db2 test.db
           23  +
           24  +do_test walshared-1.0 {
           25  +  execsql {
           26  +    PRAGMA cache_size = 10;
           27  +    PRAGMA journal_mode = WAL;
           28  +    CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
           29  +    INSERT INTO t1 VALUES(randomblob(100), randomblob(200));
           30  +  }
           31  +} {wal}
           32  +
           33  +do_test walshared-1.1 {
           34  +  execsql {
           35  +    BEGIN;
           36  +      INSERT INTO t1 VALUES(randomblob(100), randomblob(200));
           37  +      INSERT INTO t1 SELECT randomblob(100), randomblob(200) FROM t1;
           38  +      INSERT INTO t1 SELECT randomblob(100), randomblob(200) FROM t1;
           39  +      INSERT INTO t1 SELECT randomblob(100), randomblob(200) FROM t1;
           40  +  }
           41  +} {}
           42  +
           43  +do_test walshared-1.2 {
           44  +  catchsql { PRAGMA wal_checkpoint }
           45  +} {1 {database table is locked}}
           46  +
           47  +do_test walshared-1.3 {
           48  +  catchsql { PRAGMA wal_checkpoint } db2
           49  +} {1 {database table is locked}}
           50  +
           51  +do_test walshared-1.4 {
           52  +  execsql { COMMIT }
           53  +  execsql { PRAGMA integrity_check } db2
           54  +} {ok}
           55  +
           56  +
           57  +
           58  +sqlite3_enable_shared_cache $::enable_shared_cache
           59  +finish_test
           60  +