xref: /sqlite-3.40.0/test/cacheflush.test (revision a23bc8a3)
16fa255fdSdan# 2011 November 16
26fa255fdSdan#
36fa255fdSdan# The author disclaims copyright to this source code.  In place of
46fa255fdSdan# a legal notice, here is a blessing:
56fa255fdSdan#
66fa255fdSdan#    May you do good and not evil.
76fa255fdSdan#    May you find forgiveness for yourself and forgive others.
86fa255fdSdan#    May you share freely, never taking more than you give.
96fa255fdSdan#
106fa255fdSdan#***********************************************************************
116fa255fdSdan#
126fa255fdSdan# This file contains test cases for sqlite3_db_cacheflush API.
136fa255fdSdan#
146fa255fdSdan
156fa255fdSdanset testdir [file dirname $argv0]
166fa255fdSdansource $testdir/tester.tcl
176fa255fdSdanset testprefix cacheflush
186fa255fdSdantest_set_config_pagecache 0 0
196fa255fdSdan
206fa255fdSdan# Run the supplied SQL on a copy of the database currently stored on
216fa255fdSdan# disk in file $dbfile.
226fa255fdSdanproc diskquery {dbfile sql} {
236fa255fdSdan  forcecopy $dbfile dq.db
246fa255fdSdan  sqlite3 dq dq.db
256fa255fdSdan  set res [execsql $sql dq]
266fa255fdSdan  dq close
276fa255fdSdan  set res
286fa255fdSdan}
296fa255fdSdan
306fa255fdSdan# Simplest possible test.
316fa255fdSdan#
326fa255fdSdando_execsql_test 1.1.0 {
336fa255fdSdan  CREATE TABLE t1(a, b);
346fa255fdSdan  INSERT INTO t1 VALUES(1, 2);
356fa255fdSdan  BEGIN;
366fa255fdSdan    INSERT INTO t1 VALUES(3, 4);
376fa255fdSdan}
386fa255fdSdando_test 1.1.1 {
396fa255fdSdan  diskquery test.db { SELECT * FROM t1 }
406fa255fdSdan} {1 2}
416fa255fdSdando_test 1.1.2 {
426fa255fdSdan  sqlite3_db_cacheflush db
436fa255fdSdan  diskquery test.db { SELECT * FROM t1 }
446fa255fdSdan} {1 2 3 4}
456fa255fdSdan
466fa255fdSdan# Test that multiple pages may be flushed to disk.
476fa255fdSdan#
486fa255fdSdando_execsql_test 1.2.0 {
496fa255fdSdan  COMMIT;
506fa255fdSdan  CREATE TABLE t2(a, b);
516fa255fdSdan  BEGIN;
526fa255fdSdan    INSERT INTO t1 VALUES(5, 6);
536fa255fdSdan    INSERT INTO t2 VALUES('a', 'b');
546fa255fdSdan}
556fa255fdSdando_test 1.2.1 {
566fa255fdSdan  diskquery test.db {
576fa255fdSdan    SELECT * FROM t1;
586fa255fdSdan    SELECT * FROM t2;
596fa255fdSdan  }
606fa255fdSdan} {1 2 3 4}
616fa255fdSdando_test 1.2.2 {
626fa255fdSdan  sqlite3_db_cacheflush db
636fa255fdSdan  diskquery test.db {
646fa255fdSdan    SELECT * FROM t1;
656fa255fdSdan    SELECT * FROM t2;
666fa255fdSdan  }
676fa255fdSdan} {1 2 3 4 5 6 a b}
686fa255fdSdan
696fa255fdSdan# Test that pages with nRef!=0 are not flushed to disk.
706fa255fdSdan#
716fa255fdSdando_execsql_test 1.3.0 {
726fa255fdSdan  COMMIT;
736fa255fdSdan  CREATE TABLE t3(a, b);
746fa255fdSdan  BEGIN;
756fa255fdSdan    INSERT INTO t1 VALUES(7, 8);
766fa255fdSdan    INSERT INTO t2 VALUES('c', 'd');
776fa255fdSdan    INSERT INTO t3 VALUES('i', 'ii');
786fa255fdSdan}
796fa255fdSdando_test 1.3.1 {
806fa255fdSdan  diskquery test.db {
816fa255fdSdan    SELECT * FROM t1;
826fa255fdSdan    SELECT * FROM t2;
836fa255fdSdan    SELECT * FROM t3;
846fa255fdSdan  }
856fa255fdSdan} {1 2 3 4 5 6 a b}
866fa255fdSdando_test 1.3.2 {
876fa255fdSdan  db eval { SELECT a FROM t1 } {
886fa255fdSdan    if {$a==3} {
896fa255fdSdan      sqlite3_db_cacheflush db
906fa255fdSdan    }
916fa255fdSdan  }
926fa255fdSdan  diskquery test.db {
936fa255fdSdan    SELECT * FROM t1;
946fa255fdSdan    SELECT * FROM t2;
956fa255fdSdan    SELECT * FROM t3;
966fa255fdSdan  }
976fa255fdSdan} {1 2 3 4 5 6 a b c d i ii}
986fa255fdSdando_test 1.3.2 {
996fa255fdSdan  sqlite3_db_cacheflush db
1006fa255fdSdan  diskquery test.db {
1016fa255fdSdan    SELECT * FROM t1;
1026fa255fdSdan    SELECT * FROM t2;
1036fa255fdSdan    SELECT * FROM t3;
1046fa255fdSdan  }
1056fa255fdSdan} {1 2 3 4 5 6 7 8 a b c d i ii}
1066fa255fdSdan
1076fa255fdSdan# Check that SQLITE_BUSY is returned if pages cannot be flushed due to
1086fa255fdSdan# conflicting read locks.
1096fa255fdSdan#
1106fa255fdSdando_execsql_test 1.4.0 {
1116fa255fdSdan  COMMIT;
1126fa255fdSdan  BEGIN;
1136fa255fdSdan    INSERT INTO t1 VALUES(9, 10);
1146fa255fdSdan}
1156fa255fdSdando_test 1.4.1 {
1166fa255fdSdan  sqlite3 db2 test.db
1176fa255fdSdan  db2 eval {
1186fa255fdSdan    BEGIN;
1196fa255fdSdan      SELECT * FROM t1;
1206fa255fdSdan  }
1216fa255fdSdan  diskquery test.db {
1226fa255fdSdan    SELECT * FROM t1;
1236fa255fdSdan  }
1246fa255fdSdan} {1 2 3 4 5 6 7 8}
1256fa255fdSdando_test 1.4.2 {
1266fa255fdSdan  list [catch { sqlite3_db_cacheflush db } msg] $msg
1276fa255fdSdan} {1 {database is locked}}
1286fa255fdSdando_test 1.4.3 {
1296fa255fdSdan  diskquery test.db {
1306fa255fdSdan    SELECT * FROM t1;
1316fa255fdSdan  }
1326fa255fdSdan} {1 2 3 4 5 6 7 8}
1336fa255fdSdando_test 1.4.4 {
1346fa255fdSdan  db2 close
1356fa255fdSdan  sqlite3_db_cacheflush db
1366fa255fdSdan  diskquery test.db {
1376fa255fdSdan    SELECT * FROM t1;
1386fa255fdSdan  }
1396fa255fdSdan} {1 2 3 4 5 6 7 8 9 10}
1406fa255fdSdando_execsql_test 1.4.5 { COMMIT }
1416fa255fdSdan
1426fa255fdSdan#-------------------------------------------------------------------------
1436fa255fdSdan# Test that ATTACHed database caches are also flushed.
1446fa255fdSdan#
1456fa255fdSdanforcedelete test.db2
1466fa255fdSdando_execsql_test 2.1.0 {
1476fa255fdSdan  ATTACH 'test.db2' AS aux;
1486fa255fdSdan  CREATE TABLE aux.t4(x, y);
1496fa255fdSdan  INSERT INTO t4 VALUES('A', 'B');
1506fa255fdSdan  BEGIN;
1516fa255fdSdan    INSERT INTO t1 VALUES(11, 12);
1526fa255fdSdan    INSERT INTO t4 VALUES('C', 'D');
1536fa255fdSdan}
1546fa255fdSdando_test 2.1.1 {
1556fa255fdSdan  diskquery test.db { SELECT * FROM t1; }
1566fa255fdSdan} {1 2 3 4 5 6 7 8 9 10}
1576fa255fdSdando_test 2.1.2 {
1586fa255fdSdan  diskquery test.db2 { SELECT * FROM t4; }
1596fa255fdSdan} {A B}
1606fa255fdSdando_test 2.1.3 {
1616fa255fdSdan  sqlite3_db_cacheflush db
1626fa255fdSdan  diskquery test.db { SELECT * FROM t1; }
1636fa255fdSdan} {1 2 3 4 5 6 7 8 9 10 11 12}
1646fa255fdSdando_test 2.1.4 {
1656fa255fdSdan  sqlite3_db_cacheflush db
1666fa255fdSdan  diskquery test.db2 { SELECT * FROM t4; }
1676fa255fdSdan} {A B C D}
1686fa255fdSdando_execsql_test 2.1.5 { COMMIT }
1696fa255fdSdan
1706fa255fdSdan# And that hitting an SQLITE_BUSY when flushing "main" does not stop
1716fa255fdSdan# SQLite from going on to flush "aux".
1726fa255fdSdan#
1736fa255fdSdando_execsql_test 2.2.0 {
1746fa255fdSdan  BEGIN;
1756fa255fdSdan    INSERT INTO t1 VALUES(13, 14);
1766fa255fdSdan    INSERT INTO t4 VALUES('E', 'F');
1776fa255fdSdan}
1786fa255fdSdando_test 2.2.1 {
1796fa255fdSdan  diskquery test.db { SELECT * FROM t1; }
1806fa255fdSdan} {1 2 3 4 5 6 7 8 9 10 11 12}
1816fa255fdSdando_test 2.2.2 {
1826fa255fdSdan  diskquery test.db2 { SELECT * FROM t4; }
1836fa255fdSdan} {A B C D}
1846fa255fdSdando_test 2.2.3 {
1856fa255fdSdan  sqlite3 db2 test.db
1866fa255fdSdan  execsql {
1876fa255fdSdan    BEGIN;
1886fa255fdSdan      SELECT * FROM t1;
1896fa255fdSdan  } db2
1906fa255fdSdan  list [catch { sqlite3_db_cacheflush db } msg] $msg
1916fa255fdSdan} {1 {database is locked}}
1926fa255fdSdando_test 2.2.4 {
1936fa255fdSdan  diskquery test.db { SELECT * FROM t1; }
1946fa255fdSdan} {1 2 3 4 5 6 7 8 9 10 11 12}
1956fa255fdSdando_test 2.2.5 {
1966fa255fdSdan  diskquery test.db2 { SELECT * FROM t4; }
1976fa255fdSdan} {A B C D E F}
1986fa255fdSdando_test 2.2.6 {
1996fa255fdSdan  db2 close
2006fa255fdSdan  sqlite3_db_cacheflush db
2016fa255fdSdan  diskquery test.db { SELECT * FROM t1; }
2026fa255fdSdan} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
2036fa255fdSdando_execsql_test 2.2.7 { COMMIT }
2046fa255fdSdan
2054a6beac2Sdan#-------------------------------------------------------------------------
2064a6beac2Sdan# Test that nothing terrible happens if sqlite3_db_cacheflush() is
2074a6beac2Sdan# called on an in-memory database.
2084a6beac2Sdan#
2094a6beac2Sdando_test 3.0 {
2104a6beac2Sdan  db close
2114a6beac2Sdan  sqlite3 db :memory:
2124a6beac2Sdan  db eval {
2134a6beac2Sdan    CREATE TABLE t1(x PRIMARY KEY);
2144a6beac2Sdan    CREATE TABLE t2(y PRIMARY KEY);
2154a6beac2Sdan    BEGIN;
2164a6beac2Sdan      INSERT INTO t1 VALUES(randomblob(100));
2174a6beac2Sdan      INSERT INTO t2 VALUES(randomblob(100));
2184a6beac2Sdan      INSERT INTO t1 VALUES(randomblob(100));
2194a6beac2Sdan      INSERT INTO t2 VALUES(randomblob(100));
2204a6beac2Sdan  }
2214a6beac2Sdan  sqlite3_db_cacheflush db
2224a6beac2Sdan} {}
2234a6beac2Sdan
2244a6beac2Sdando_execsql_test 3.1 { PRAGMA integrity_check } ok
2254a6beac2Sdando_execsql_test 3.2 { COMMIT }
2264a6beac2Sdando_execsql_test 3.3 { PRAGMA integrity_check } ok
2274a6beac2Sdando_execsql_test 3.4 {
2284a6beac2Sdan  SELECT count(*) FROM t1;
2294a6beac2Sdan  SELECT count(*) FROM t2;
2304a6beac2Sdan} {2 2}
2314a6beac2Sdan
232*e8e6657fSdan#-------------------------------------------------------------------------
233*e8e6657fSdan# Test that calling sqlite3_db_cacheflush() does not interfere with
234*e8e6657fSdan# savepoint transactions.
235*e8e6657fSdan#
236*e8e6657fSdando_test 4.0 {
237*e8e6657fSdan  reset_db
238*e8e6657fSdan  execsql {
239*e8e6657fSdan    CREATE TABLE ta(a, aa);
240*e8e6657fSdan    CREATE TABLE tb(b, bb);
241*e8e6657fSdan    INSERT INTO ta VALUES('a', randomblob(500));
242*e8e6657fSdan    INSERT INTO tb VALUES('b', randomblob(500));
243*e8e6657fSdan    BEGIN;
244*e8e6657fSdan      UPDATE ta SET a = 'A';
245*e8e6657fSdan      SAVEPOINT one;
246*e8e6657fSdan        UPDATE tb SET b = 'B';
247*e8e6657fSdan  }
248*e8e6657fSdan
249*e8e6657fSdan  sqlite3_db_cacheflush db
250*e8e6657fSdan  diskquery test.db {
251*e8e6657fSdan    SELECT a FROM ta;
252*e8e6657fSdan    SELECT b FROM tb;
253*e8e6657fSdan  }
254*e8e6657fSdan} {A B}
255*e8e6657fSdan
256*e8e6657fSdando_test 4.1 {
257*e8e6657fSdan  execsql {
258*e8e6657fSdan    ROLLBACK TO one;
259*e8e6657fSdan  }
260*e8e6657fSdan  sqlite3_db_cacheflush db
261*e8e6657fSdan  diskquery test.db {
262*e8e6657fSdan    SELECT a FROM ta;
263*e8e6657fSdan    SELECT b FROM tb;
264*e8e6657fSdan  }
265*e8e6657fSdan} {A b}
266*e8e6657fSdan
267*e8e6657fSdando_test 4.2 {
268*e8e6657fSdan  execsql {
269*e8e6657fSdan    INSERT INTO tb VALUES('c', randomblob(10));
270*e8e6657fSdan    INSERT INTO tb VALUES('d', randomblob(10));
271*e8e6657fSdan    INSERT INTO tb VALUES('e', randomblob(10));
272*e8e6657fSdan  }
273*e8e6657fSdan  sqlite3_db_cacheflush db
274*e8e6657fSdan  diskquery test.db {
275*e8e6657fSdan    SELECT a FROM ta;
276*e8e6657fSdan    SELECT b FROM tb;
277*e8e6657fSdan  }
278*e8e6657fSdan} {A b c d e}
279*e8e6657fSdan
280*e8e6657fSdando_test 4.3 {
281*e8e6657fSdan  execsql {
282*e8e6657fSdan    SAVEPOINT two;
283*e8e6657fSdan    UPDATE tb SET b = upper(b);
284*e8e6657fSdan  }
285*e8e6657fSdan  sqlite3_db_cacheflush db
286*e8e6657fSdan  diskquery test.db {
287*e8e6657fSdan    SELECT a FROM ta;
288*e8e6657fSdan    SELECT b FROM tb;
289*e8e6657fSdan  }
290*e8e6657fSdan} {A B C D E}
291*e8e6657fSdan
292*e8e6657fSdando_test 4.4 {
293*e8e6657fSdan  execsql {
294*e8e6657fSdan    ROLLBACK TO two;
295*e8e6657fSdan  }
296*e8e6657fSdan  sqlite3_db_cacheflush db
297*e8e6657fSdan  diskquery test.db {
298*e8e6657fSdan    SELECT a FROM ta;
299*e8e6657fSdan    SELECT b FROM tb;
300*e8e6657fSdan  }
301*e8e6657fSdan} {A b c d e}
302*e8e6657fSdan
303*e8e6657fSdando_test 4.4 {
304*e8e6657fSdan  execsql {
305*e8e6657fSdan    ROLLBACK TO one;
306*e8e6657fSdan  }
307*e8e6657fSdan  sqlite3_db_cacheflush db
308*e8e6657fSdan  diskquery test.db {
309*e8e6657fSdan    SELECT a FROM ta;
310*e8e6657fSdan    SELECT b FROM tb;
311*e8e6657fSdan  }
312*e8e6657fSdan} {A b}
313*e8e6657fSdan
314*e8e6657fSdando_test 4.5 {
315*e8e6657fSdan  execsql {
316*e8e6657fSdan    ROLLBACK;
317*e8e6657fSdan    SELECT a FROM ta;
318*e8e6657fSdan    SELECT b FROM tb;
319*e8e6657fSdan  }
320*e8e6657fSdan} {a b}
3214a6beac2Sdan
3226fa255fdSdantest_restore_config_pagecache
3236fa255fdSdanfinish_test
324