/ 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 Unified Diffs Show Whitespace Changes Patch

Changes to src/main.c.

3887
3888
3889
3890
3891
3892
3893
3894
3895

3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
  }
#endif
  sqlite3_mutex_enter(db->mutex);

  iDb = sqlite3FindDbName(db, zDb);
  if( iDb==0 || iDb>1 ){
    Btree *pBt = db->aDb[iDb].pBt;
    if( 0!=sqlite3BtreeIsInReadTrans(pBt) 
     && 0==sqlite3BtreeIsInTrans(pBt)

    ){
      rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
    }
  }


  sqlite3_mutex_leave(db->mutex);
#endif   /* SQLITE_OMIT_WAL */
  return rc;
}

/*







<
|
>
|



>







3887
3888
3889
3890
3891
3892
3893

3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
  }
#endif
  sqlite3_mutex_enter(db->mutex);

  iDb = sqlite3FindDbName(db, zDb);
  if( iDb==0 || iDb>1 ){
    Btree *pBt = db->aDb[iDb].pBt;

    if( 0==sqlite3BtreeIsInTrans(pBt) ){
      rc = sqlite3BtreeBeginTrans(pBt, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
      }
    }
  }

  sqlite3_mutex_leave(db->mutex);
#endif   /* SQLITE_OMIT_WAL */
  return rc;
}

/*

Changes to src/sqlite.h.in.

7879
7880
7881
7882
7883
7884
7885
7886
7887


7888
7889
7890
7891
7892
7893
7894
int sqlite3_db_cacheflush(sqlite3*);

/*
** CAPI3REF: Open old database snapshots.
**
** The second argument passed to sqlite3_snapshot_get() must be the name
** of a database file attached to the database handle passed as the first.
** The database handle must have an open read transaction on the named 
** database, which must be in wal mode. 


**
** If successful, sqlite3_snapshot_get() sets *ppSnapshot to point to a new
** snapshot handle that may be used with sqlite3_snapshot_open() and returns
** SQLITE_OK.
**
** If the specified database does not exist, or is not a wal mode database, 
** or the database handle does not have an open read transaction on it,







|
|
>
>







7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
int sqlite3_db_cacheflush(sqlite3*);

/*
** CAPI3REF: Open old database snapshots.
**
** The second argument passed to sqlite3_snapshot_get() must be the name
** of a database file attached to the database handle passed as the first.
** The database handle must not have an open write transaction on the named 
** database, which must be in wal mode. If the database handle does not
** have an open read transaction on the named file, this function opens
** one.
**
** If successful, sqlite3_snapshot_get() sets *ppSnapshot to point to a new
** snapshot handle that may be used with sqlite3_snapshot_open() and returns
** SQLITE_OK.
**
** If the specified database does not exist, or is not a wal mode database, 
** or the database handle does not have an open read transaction on it,

Changes to test/snapshot.test.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
..
57
58
59
60
61
62
63

64
65
66
67
68
69
70
...
109
110
111
112
113
114
115

























116
117
118
119
120
121
122
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix snapshot

#-------------------------------------------------------------------------
# Check some error conditions in snapshot_get(). It is an error if:
#
#  1) snapshot_get() is called on a non-WAL database.
#  2) there is no open read transaction on the database, or
#  3) there is an open write transaction on the database.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
}

................................................................................
  execsql { BEGIN; SELECT * FROM t1; }
  list [catch { sqlite3_snapshot_get db main } msg] $msg
} {1 SQLITE_ERROR}
do_execsql_test 1.1.2 COMMIT

do_test 1.2.1 {
  execsql {
    PRAGMA journal_mode = wal;
    INSERT INTO t1 VALUES(5, 6);
  }
  list [catch { sqlite3_snapshot_get db main } msg] $msg
} {1 SQLITE_ERROR}

do_test 1.3.1 {
  execsql {
    BEGIN;

      INSERT INTO t1 VALUES(7, 8);
  }
  list [catch { sqlite3_snapshot_get db main } msg] $msg
} {1 SQLITE_ERROR}
do_execsql_test 1.3.2 COMMIT

#-------------------------------------------------------------------------
................................................................................
# block of tests above.
#
do_execsql_test 2.1.0 {
  BEGIN;
    SELECT * FROM t1;
} {1 2 3 4 5 6 7 8}


do_test 2.1.1 {
  set snapshot [sqlite3_snapshot_get db main]
  execsql {
    COMMIT;
    INSERT INTO t1 VALUES(9, 10);
    SELECT * FROM t1;
  }
................................................................................

do_test 2.2.3 {
  sqlite3_snapshot_free $snapshot
  execsql COMMIT
  execsql COMMIT db2
  db2 close
} {}


























#-------------------------------------------------------------------------
# Check some errors in sqlite3_snapshot_open(). It is an error if:
#
#   1) the db is in auto-commit mode,
#   2) the db has an open (read or write) transaction,
#   3) the db is not a wal database,







|
<
|







 







|
<
<
<
<
<
<
<

>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
..
32
33
34
35
36
37
38
39







40
41
42
43
44
45
46
47
48
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix snapshot

#-------------------------------------------------------------------------
# Check some error conditions in snapshot_get(). It is an error if:
#
#  1) snapshot_get() is called on a non-WAL database, or

#  2) there is an open write transaction on the database.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
}

................................................................................
  execsql { BEGIN; SELECT * FROM t1; }
  list [catch { sqlite3_snapshot_get db main } msg] $msg
} {1 SQLITE_ERROR}
do_execsql_test 1.1.2 COMMIT

do_test 1.2.1 {
  execsql {
    PRAGMA journal_mode = WAL;







    BEGIN;
      INSERT INTO t1 VALUES(5, 6);
      INSERT INTO t1 VALUES(7, 8);
  }
  list [catch { sqlite3_snapshot_get db main } msg] $msg
} {1 SQLITE_ERROR}
do_execsql_test 1.3.2 COMMIT

#-------------------------------------------------------------------------
................................................................................
# block of tests above.
#
do_execsql_test 2.1.0 {
  BEGIN;
    SELECT * FROM t1;
} {1 2 3 4 5 6 7 8}

breakpoint
do_test 2.1.1 {
  set snapshot [sqlite3_snapshot_get db main]
  execsql {
    COMMIT;
    INSERT INTO t1 VALUES(9, 10);
    SELECT * FROM t1;
  }
................................................................................

do_test 2.2.3 {
  sqlite3_snapshot_free $snapshot
  execsql COMMIT
  execsql COMMIT db2
  db2 close
} {}

do_test 2.3.1 {
  execsql { DELETE FROM t1 WHERE a>6 }
  set snapshot [sqlite3_snapshot_get db main]
  execsql {
    INSERT INTO t1 VALUES('a', 'b');
    INSERT INTO t1 VALUES('c', 'd');
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 a b c d}
do_test 2.3.2 {
  execsql BEGIN
  sqlite3_snapshot_open db main $snapshot
  execsql { SELECT * FROM t1 }
} {1 2 3 4 5 6}

do_test 2.3.3 {
  catchsql {
    INSERT INTO t1 VALUES('x','y')
  }
} {1 {database is locked}}
do_test 2.3.4 {
  execsql COMMIT
  sqlite3_snapshot_free $snapshot
} {}

#-------------------------------------------------------------------------
# Check some errors in sqlite3_snapshot_open(). It is an error if:
#
#   1) the db is in auto-commit mode,
#   2) the db has an open (read or write) transaction,
#   3) the db is not a wal database,