/ Check-in [b9c90f10]
Login

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

Overview
Comment:Update the sqlite3_snapshot_get() API so that if the caller does not have an open read transaction on the named database, one is automatically opened.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | snapshot-get
Files: files | file ages | folders
SHA1: b9c90f10297d8516a661449e8af898e682c930aa
User & Date: dan 2015-12-10 20:03:08
Context
2015-12-10
22:48
Snapshot documentation updates. Comment changes only - no changes to code. check-in: ef51a398 user: drh tags: snapshot-get
20:03
Update the sqlite3_snapshot_get() API so that if the caller does not have an open read transaction on the named database, one is automatically opened. check-in: b9c90f10 user: dan tags: snapshot-get
19:44
Add tests to snapshot.test. check-in: f3b74362 user: dan tags: snapshot-get
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

  3887   3887     }
  3888   3888   #endif
  3889   3889     sqlite3_mutex_enter(db->mutex);
  3890   3890   
  3891   3891     iDb = sqlite3FindDbName(db, zDb);
  3892   3892     if( iDb==0 || iDb>1 ){
  3893   3893       Btree *pBt = db->aDb[iDb].pBt;
  3894         -    if( 0!=sqlite3BtreeIsInReadTrans(pBt) 
  3895         -     && 0==sqlite3BtreeIsInTrans(pBt)
  3896         -    ){
  3897         -      rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
         3894  +    if( 0==sqlite3BtreeIsInTrans(pBt) ){
         3895  +      rc = sqlite3BtreeBeginTrans(pBt, 0);
         3896  +      if( rc==SQLITE_OK ){
         3897  +        rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
         3898  +      }
  3898   3899       }
  3899   3900     }
  3900   3901   
  3901   3902     sqlite3_mutex_leave(db->mutex);
  3902   3903   #endif   /* SQLITE_OMIT_WAL */
  3903   3904     return rc;
  3904   3905   }

Changes to src/sqlite.h.in.

  7879   7879   int sqlite3_db_cacheflush(sqlite3*);
  7880   7880   
  7881   7881   /*
  7882   7882   ** CAPI3REF: Open old database snapshots.
  7883   7883   **
  7884   7884   ** The second argument passed to sqlite3_snapshot_get() must be the name
  7885   7885   ** of a database file attached to the database handle passed as the first.
  7886         -** The database handle must have an open read transaction on the named 
  7887         -** database, which must be in wal mode. 
         7886  +** The database handle must not have an open write transaction on the named 
         7887  +** database, which must be in wal mode. If the database handle does not
         7888  +** have an open read transaction on the named file, this function opens
         7889  +** one.
  7888   7890   **
  7889   7891   ** If successful, sqlite3_snapshot_get() sets *ppSnapshot to point to a new
  7890   7892   ** snapshot handle that may be used with sqlite3_snapshot_open() and returns
  7891   7893   ** SQLITE_OK.
  7892   7894   **
  7893   7895   ** If the specified database does not exist, or is not a wal mode database, 
  7894   7896   ** or the database handle does not have an open read transaction on it,

Changes to test/snapshot.test.

    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   set testprefix snapshot
    18     18   
    19     19   #-------------------------------------------------------------------------
    20     20   # Check some error conditions in snapshot_get(). It is an error if:
    21     21   #
    22         -#  1) snapshot_get() is called on a non-WAL database.
    23         -#  2) there is no open read transaction on the database, or
    24         -#  3) there is an open write transaction on the database.
           22  +#  1) snapshot_get() is called on a non-WAL database, or
           23  +#  2) there is an open write transaction on the database.
    25     24   #
    26     25   do_execsql_test 1.0 {
    27     26     CREATE TABLE t1(a, b);
    28     27     INSERT INTO t1 VALUES(1, 2);
    29     28     INSERT INTO t1 VALUES(3, 4);
    30     29   }
    31     30   
................................................................................
    33     32     execsql { BEGIN; SELECT * FROM t1; }
    34     33     list [catch { sqlite3_snapshot_get db main } msg] $msg
    35     34   } {1 SQLITE_ERROR}
    36     35   do_execsql_test 1.1.2 COMMIT
    37     36   
    38     37   do_test 1.2.1 {
    39     38     execsql {
    40         -    PRAGMA journal_mode = wal;
    41         -    INSERT INTO t1 VALUES(5, 6);
    42         -  }
    43         -  list [catch { sqlite3_snapshot_get db main } msg] $msg
    44         -} {1 SQLITE_ERROR}
    45         -
    46         -do_test 1.3.1 {
    47         -  execsql {
           39  +    PRAGMA journal_mode = WAL;
    48     40       BEGIN;
           41  +      INSERT INTO t1 VALUES(5, 6);
    49     42         INSERT INTO t1 VALUES(7, 8);
    50     43     }
    51     44     list [catch { sqlite3_snapshot_get db main } msg] $msg
    52     45   } {1 SQLITE_ERROR}
    53     46   do_execsql_test 1.3.2 COMMIT
    54     47   
    55     48   #-------------------------------------------------------------------------
................................................................................
    57     50   # block of tests above.
    58     51   #
    59     52   do_execsql_test 2.1.0 {
    60     53     BEGIN;
    61     54       SELECT * FROM t1;
    62     55   } {1 2 3 4 5 6 7 8}
    63     56   
           57  +breakpoint
    64     58   do_test 2.1.1 {
    65     59     set snapshot [sqlite3_snapshot_get db main]
    66     60     execsql {
    67     61       COMMIT;
    68     62       INSERT INTO t1 VALUES(9, 10);
    69     63       SELECT * FROM t1;
    70     64     }
................................................................................
   109    103   
   110    104   do_test 2.2.3 {
   111    105     sqlite3_snapshot_free $snapshot
   112    106     execsql COMMIT
   113    107     execsql COMMIT db2
   114    108     db2 close
   115    109   } {}
          110  +
          111  +do_test 2.3.1 {
          112  +  execsql { DELETE FROM t1 WHERE a>6 }
          113  +  set snapshot [sqlite3_snapshot_get db main]
          114  +  execsql {
          115  +    INSERT INTO t1 VALUES('a', 'b');
          116  +    INSERT INTO t1 VALUES('c', 'd');
          117  +    SELECT * FROM t1;
          118  +  }
          119  +} {1 2 3 4 5 6 a b c d}
          120  +do_test 2.3.2 {
          121  +  execsql BEGIN
          122  +  sqlite3_snapshot_open db main $snapshot
          123  +  execsql { SELECT * FROM t1 }
          124  +} {1 2 3 4 5 6}
          125  +
          126  +do_test 2.3.3 {
          127  +  catchsql {
          128  +    INSERT INTO t1 VALUES('x','y')
          129  +  }
          130  +} {1 {database is locked}}
          131  +do_test 2.3.4 {
          132  +  execsql COMMIT
          133  +  sqlite3_snapshot_free $snapshot
          134  +} {}
   116    135   
   117    136   #-------------------------------------------------------------------------
   118    137   # Check some errors in sqlite3_snapshot_open(). It is an error if:
   119    138   #
   120    139   #   1) the db is in auto-commit mode,
   121    140   #   2) the db has an open (read or write) transaction,
   122    141   #   3) the db is not a wal database,