sl@0: # 2002 March 6 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # This file implements regression tests for SQLite library. sl@0: # sl@0: # This file implements tests for the PRAGMA command. sl@0: # sl@0: # $Id: pragma.test,v 1.66 2008/09/02 00:52:52 drh Exp $ sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: # Test organization: sl@0: # sl@0: # pragma-1.*: Test cache_size, default_cache_size and synchronous on main db. sl@0: # pragma-2.*: Test synchronous on attached db. sl@0: # pragma-3.*: Test detection of table/index inconsistency by integrity_check. sl@0: # pragma-4.*: Test cache_size and default_cache_size on attached db. sl@0: # pragma-5.*: Test that pragma synchronous may not be used inside of a sl@0: # transaction. sl@0: # pragma-6.*: Test schema-query pragmas. sl@0: # pragma-7.*: Miscellaneous tests. sl@0: # pragma-8.*: Test user_version and schema_version pragmas. sl@0: # pragma-9.*: Test temp_store and temp_store_directory. sl@0: # pragma-10.*: Test the count_changes pragma in the presence of triggers. sl@0: # pragma-11.*: Test the collation_list pragma. sl@0: # pragma-14.*: Test the page_count pragma. sl@0: # pragma-15.*: Test that the value set using the cache_size pragma is not sl@0: # reset when the schema is reloaded. sl@0: # sl@0: sl@0: ifcapable !pragma { sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: # Delete the preexisting database to avoid the special setup sl@0: # that the "all.test" script does. sl@0: # sl@0: db close sl@0: file delete test.db test.db-journal sl@0: file delete test3.db test3.db-journal sl@0: sqlite3 db test.db; set DB [sqlite3_connection_pointer db] sl@0: sl@0: sl@0: ifcapable pager_pragmas { sl@0: set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}] sl@0: set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}] sl@0: do_test pragma-1.1 { sl@0: execsql { sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2] sl@0: do_test pragma-1.2 { sl@0: execsql { sl@0: PRAGMA synchronous=OFF; sl@0: PRAGMA cache_size=1234; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list 1234 $DFLT_CACHE_SZ 0] sl@0: do_test pragma-1.3 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2] sl@0: do_test pragma-1.4 { sl@0: execsql { sl@0: PRAGMA synchronous=OFF; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 0] sl@0: do_test pragma-1.5 { sl@0: execsql { sl@0: PRAGMA cache_size=4321; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list 4321 $DFLT_CACHE_SZ 0] sl@0: do_test pragma-1.6 { sl@0: execsql { sl@0: PRAGMA synchronous=ON; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list 4321 $DFLT_CACHE_SZ 1] sl@0: do_test pragma-1.7 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2] sl@0: do_test pragma-1.8 { sl@0: execsql { sl@0: PRAGMA default_cache_size=123; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 2} sl@0: do_test pragma-1.9.1 { sl@0: db close sl@0: sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db] sl@0: execsql { sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 2} sl@0: ifcapable vacuum { sl@0: do_test pragma-1.9.2 { sl@0: execsql { sl@0: VACUUM; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 2} sl@0: } sl@0: do_test pragma-1.10 { sl@0: execsql { sl@0: PRAGMA synchronous=NORMAL; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 1} sl@0: do_test pragma-1.11 { sl@0: execsql { sl@0: PRAGMA synchronous=FULL; sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 2} sl@0: do_test pragma-1.12 { sl@0: db close sl@0: sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db] sl@0: execsql { sl@0: PRAGMA cache_size; sl@0: PRAGMA default_cache_size; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {123 123 2} sl@0: sl@0: # Make sure the pragma handler understands numeric values in addition sl@0: # to keywords like "off" and "full". sl@0: # sl@0: do_test pragma-1.13 { sl@0: execsql { sl@0: PRAGMA synchronous=0; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {0} sl@0: do_test pragma-1.14 { sl@0: execsql { sl@0: PRAGMA synchronous=2; sl@0: PRAGMA synchronous; sl@0: } sl@0: } {2} sl@0: } ;# ifcapable pager_pragmas sl@0: sl@0: # Test turning "flag" pragmas on and off. sl@0: # sl@0: ifcapable debug { sl@0: # Pragma "vdbe_listing" is only available if compiled with SQLITE_DEBUG sl@0: # sl@0: do_test pragma-1.15 { sl@0: execsql { sl@0: PRAGMA vdbe_listing=YES; sl@0: PRAGMA vdbe_listing; sl@0: } sl@0: } {1} sl@0: do_test pragma-1.16 { sl@0: execsql { sl@0: PRAGMA vdbe_listing=NO; sl@0: PRAGMA vdbe_listing; sl@0: } sl@0: } {0} sl@0: } sl@0: sl@0: do_test pragma-1.17 { sl@0: execsql { sl@0: PRAGMA parser_trace=ON; sl@0: PRAGMA parser_trace=OFF; sl@0: } sl@0: } {} sl@0: do_test pragma-1.18 { sl@0: execsql { sl@0: PRAGMA bogus = -1234; -- Parsing of negative values sl@0: } sl@0: } {} sl@0: sl@0: # Test modifying the safety_level of an attached database. sl@0: ifcapable pager_pragmas&&attach { sl@0: do_test pragma-2.1 { sl@0: file delete -force test2.db sl@0: file delete -force test2.db-journal sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: } sl@0: } {} sl@0: do_test pragma-2.2 { sl@0: execsql { sl@0: pragma aux.synchronous; sl@0: } sl@0: } {2} sl@0: do_test pragma-2.3 { sl@0: execsql { sl@0: pragma aux.synchronous = OFF; sl@0: pragma aux.synchronous; sl@0: pragma synchronous; sl@0: } sl@0: } {0 2} sl@0: do_test pragma-2.4 { sl@0: execsql { sl@0: pragma aux.synchronous = ON; sl@0: pragma synchronous; sl@0: pragma aux.synchronous; sl@0: } sl@0: } {2 1} sl@0: } ;# ifcapable pager_pragmas sl@0: sl@0: # Construct a corrupted index and make sure the integrity_check sl@0: # pragma finds it. sl@0: # sl@0: # These tests won't work if the database is encrypted sl@0: # sl@0: do_test pragma-3.1 { sl@0: db close sl@0: file delete -force test.db test.db-journal sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA auto_vacuum=OFF; sl@0: BEGIN; sl@0: CREATE TABLE t2(a,b,c); sl@0: CREATE INDEX i2 ON t2(a); sl@0: INSERT INTO t2 VALUES(11,2,3); sl@0: INSERT INTO t2 VALUES(22,3,4); sl@0: COMMIT; sl@0: SELECT rowid, * from t2; sl@0: } sl@0: } {1 11 2 3 2 22 3 4} sl@0: ifcapable attach { sl@0: if {![sqlite3 -has-codec] && $sqlite_options(integrityck)} { sl@0: do_test pragma-3.2 { sl@0: db eval {SELECT rootpage FROM sqlite_master WHERE name='i2'} break sl@0: set pgsz [db eval {PRAGMA page_size}] sl@0: # overwrite the header on the rootpage of the index in order to sl@0: # make the index appear to be empty. sl@0: # sl@0: set offset [expr {$pgsz*($rootpage-1)}] sl@0: hexio_write test.db $offset 0a00000000040000000000 sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql {PRAGMA integrity_check} sl@0: } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: do_test pragma-3.3 { sl@0: execsql {PRAGMA integrity_check=1} sl@0: } {{rowid 1 missing from index i2}} sl@0: do_test pragma-3.4 { sl@0: execsql { sl@0: ATTACH DATABASE 'test.db' AS t2; sl@0: PRAGMA integrity_check sl@0: } sl@0: } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: do_test pragma-3.5 { sl@0: execsql { sl@0: PRAGMA integrity_check=4 sl@0: } sl@0: } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2}} sl@0: do_test pragma-3.6 { sl@0: execsql { sl@0: PRAGMA integrity_check=xyz sl@0: } sl@0: } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: do_test pragma-3.7 { sl@0: execsql { sl@0: PRAGMA integrity_check=0 sl@0: } sl@0: } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: sl@0: # Add additional corruption by appending unused pages to the end of sl@0: # the database file testerr.db sl@0: # sl@0: do_test pragma-3.8 { sl@0: execsql {DETACH t2} sl@0: file delete -force testerr.db testerr.db-journal sl@0: set out [open testerr.db w] sl@0: fconfigure $out -translation binary sl@0: set in [open test.db r] sl@0: fconfigure $in -translation binary sl@0: puts -nonewline $out [read $in] sl@0: seek $in 0 sl@0: puts -nonewline $out [read $in] sl@0: close $in sl@0: close $out sl@0: execsql {REINDEX t2} sl@0: execsql {PRAGMA integrity_check} sl@0: } {ok} sl@0: do_test pragma-3.8.1 { sl@0: execsql {PRAGMA quick_check} sl@0: } {ok} sl@0: do_test pragma-3.9 { sl@0: execsql { sl@0: ATTACH 'testerr.db' AS t2; sl@0: PRAGMA integrity_check sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: do_test pragma-3.10 { sl@0: execsql { sl@0: PRAGMA integrity_check=1 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used}} sl@0: do_test pragma-3.11 { sl@0: execsql { sl@0: PRAGMA integrity_check=5 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2}} sl@0: do_test pragma-3.12 { sl@0: execsql { sl@0: PRAGMA integrity_check=4 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2}} sl@0: do_test pragma-3.13 { sl@0: execsql { sl@0: PRAGMA integrity_check=3 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used}} sl@0: do_test pragma-3.14 { sl@0: execsql { sl@0: PRAGMA integrity_check(2) sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used}} sl@0: do_test pragma-3.15 { sl@0: execsql { sl@0: ATTACH 'testerr.db' AS t3; sl@0: PRAGMA integrity_check sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} sl@0: do_test pragma-3.16 { sl@0: execsql { sl@0: PRAGMA integrity_check(10) sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2}} sl@0: do_test pragma-3.17 { sl@0: execsql { sl@0: PRAGMA integrity_check=8 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** sl@0: Page 4 is never used sl@0: Page 5 is never used}} sl@0: do_test pragma-3.18 { sl@0: execsql { sl@0: PRAGMA integrity_check=4 sl@0: } sl@0: } {{*** in database t2 *** sl@0: Page 4 is never used sl@0: Page 5 is never used sl@0: Page 6 is never used} {rowid 1 missing from index i2}} sl@0: } sl@0: do_test pragma-3.99 { sl@0: catchsql {DETACH t3} sl@0: catchsql {DETACH t2} sl@0: file delete -force testerr.db testerr.db-journal sl@0: catchsql {DROP INDEX i2} sl@0: } {0 {}} sl@0: } sl@0: sl@0: # Test modifying the cache_size of an attached database. sl@0: ifcapable pager_pragmas&&attach { sl@0: do_test pragma-4.1 { sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: pragma aux.cache_size; sl@0: pragma aux.default_cache_size; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ] sl@0: do_test pragma-4.2 { sl@0: execsql { sl@0: pragma aux.cache_size = 50; sl@0: pragma aux.cache_size; sl@0: pragma aux.default_cache_size; sl@0: } sl@0: } [list 50 $DFLT_CACHE_SZ] sl@0: do_test pragma-4.3 { sl@0: execsql { sl@0: pragma aux.default_cache_size = 456; sl@0: pragma aux.cache_size; sl@0: pragma aux.default_cache_size; sl@0: } sl@0: } {456 456} sl@0: do_test pragma-4.4 { sl@0: execsql { sl@0: pragma cache_size; sl@0: pragma default_cache_size; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ] sl@0: do_test pragma-4.5 { sl@0: execsql { sl@0: DETACH aux; sl@0: ATTACH 'test3.db' AS aux; sl@0: pragma aux.cache_size; sl@0: pragma aux.default_cache_size; sl@0: } sl@0: } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ] sl@0: do_test pragma-4.6 { sl@0: execsql { sl@0: DETACH aux; sl@0: ATTACH 'test2.db' AS aux; sl@0: pragma aux.cache_size; sl@0: pragma aux.default_cache_size; sl@0: } sl@0: } {456 456} sl@0: } ;# ifcapable pager_pragmas sl@0: sl@0: # Test that modifying the sync-level in the middle of a transaction is sl@0: # disallowed. sl@0: ifcapable pager_pragmas { sl@0: do_test pragma-5.0 { sl@0: execsql { sl@0: pragma synchronous; sl@0: } sl@0: } {2} sl@0: do_test pragma-5.1 { sl@0: catchsql { sl@0: BEGIN; sl@0: pragma synchronous = OFF; sl@0: } sl@0: } {1 {Safety level may not be changed inside a transaction}} sl@0: do_test pragma-5.2 { sl@0: execsql { sl@0: pragma synchronous; sl@0: } sl@0: } {2} sl@0: catchsql {COMMIT;} sl@0: } ;# ifcapable pager_pragmas sl@0: sl@0: # Test schema-query pragmas sl@0: # sl@0: ifcapable schema_pragmas { sl@0: ifcapable tempdb&&attach { sl@0: do_test pragma-6.1 { sl@0: set res {} sl@0: execsql {SELECT * FROM sqlite_temp_master} sl@0: foreach {idx name file} [execsql {pragma database_list}] { sl@0: lappend res $idx $name sl@0: } sl@0: set res sl@0: } {0 main 1 temp 2 aux} sl@0: } sl@0: do_test pragma-6.2 { sl@0: execsql { sl@0: pragma table_info(t2) sl@0: } sl@0: } {0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0} sl@0: db nullvalue <> sl@0: do_test pragma-6.2.2 { sl@0: execsql { sl@0: CREATE TABLE t5( sl@0: a TEXT DEFAULT CURRENT_TIMESTAMP, sl@0: b DEFAULT (5+3), sl@0: c TEXT, sl@0: d INTEGER DEFAULT NULL, sl@0: e TEXT DEFAULT '' sl@0: ); sl@0: PRAGMA table_info(t5); sl@0: } sl@0: } {0 a TEXT 0 CURRENT_TIMESTAMP 0 1 b {} 0 5+3 0 2 c TEXT 0 <> 0 3 d INTEGER 0 NULL 0 4 e TEXT 0 '' 0} sl@0: db nullvalue {} sl@0: ifcapable {foreignkey} { sl@0: do_test pragma-6.3 { sl@0: execsql { sl@0: CREATE TABLE t3(a int references t2(b), b UNIQUE); sl@0: pragma foreign_key_list(t3); sl@0: } sl@0: } {0 0 t2 a b} sl@0: do_test pragma-6.4 { sl@0: execsql { sl@0: pragma index_list(t3); sl@0: } sl@0: } {0 sqlite_autoindex_t3_1 1} sl@0: } sl@0: ifcapable {!foreignkey} { sl@0: execsql {CREATE TABLE t3(a,b UNIQUE)} sl@0: } sl@0: do_test pragma-6.5 { sl@0: execsql { sl@0: CREATE INDEX t3i1 ON t3(a,b); sl@0: pragma index_info(t3i1); sl@0: } sl@0: } {0 0 a 1 1 b} sl@0: sl@0: ifcapable tempdb { sl@0: # Test for ticket #3320. When a temp table of the same name exists, make sl@0: # sure the schema of the main table can still be queried using sl@0: # "pragma table_info": sl@0: do_test pragma-6.6.1 { sl@0: execsql { sl@0: CREATE TABLE trial(col_main); sl@0: CREATE TEMP TABLE trial(col_temp); sl@0: } sl@0: } {} sl@0: do_test pragma-6.6.2 { sl@0: execsql { sl@0: PRAGMA table_info(trial); sl@0: } sl@0: } {0 col_temp {} 0 {} 0} sl@0: do_test pragma-6.6.3 { sl@0: execsql { sl@0: PRAGMA temp.table_info(trial); sl@0: } sl@0: } {0 col_temp {} 0 {} 0} sl@0: do_test pragma-6.6.4 { sl@0: execsql { sl@0: PRAGMA main.table_info(trial); sl@0: } sl@0: } {0 col_main {} 0 {} 0} sl@0: } sl@0: } ;# ifcapable schema_pragmas sl@0: # Miscellaneous tests sl@0: # sl@0: ifcapable schema_pragmas { sl@0: do_test pragma-7.1 { sl@0: # Make sure a pragma knows to read the schema if it needs to sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: pragma index_list(t3); sl@0: } sl@0: } {0 t3i1 0 1 sqlite_autoindex_t3_1 1} sl@0: } ;# ifcapable schema_pragmas sl@0: ifcapable {utf16} { sl@0: do_test pragma-7.2 { sl@0: db close sl@0: sqlite3 db test.db sl@0: catchsql { sl@0: pragma encoding=bogus; sl@0: } sl@0: } {1 {unsupported encoding: bogus}} sl@0: } sl@0: ifcapable tempdb { sl@0: do_test pragma-7.3 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: pragma lock_status; sl@0: } sl@0: } {main unlocked temp closed} sl@0: } else { sl@0: do_test pragma-7.3 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: pragma lock_status; sl@0: } sl@0: } {main unlocked} sl@0: } sl@0: sl@0: sl@0: #---------------------------------------------------------------------- sl@0: # Test cases pragma-8.* test the "PRAGMA schema_version" and "PRAGMA sl@0: # user_version" statements. sl@0: # sl@0: # pragma-8.1: PRAGMA schema_version sl@0: # pragma-8.2: PRAGMA user_version sl@0: # sl@0: sl@0: ifcapable schema_version { sl@0: sl@0: # First check that we can set the schema version and then retrieve the sl@0: # same value. sl@0: do_test pragma-8.1.1 { sl@0: execsql { sl@0: PRAGMA schema_version = 105; sl@0: } sl@0: } {} sl@0: do_test pragma-8.1.2 { sl@0: execsql2 { sl@0: PRAGMA schema_version; sl@0: } sl@0: } {schema_version 105} sl@0: do_test pragma-8.1.3 { sl@0: execsql { sl@0: PRAGMA schema_version = 106; sl@0: } sl@0: } {} sl@0: do_test pragma-8.1.4 { sl@0: execsql { sl@0: PRAGMA schema_version; sl@0: } sl@0: } 106 sl@0: sl@0: # Check that creating a table modifies the schema-version (this is really sl@0: # to verify that the value being read is in fact the schema version). sl@0: do_test pragma-8.1.5 { sl@0: execsql { sl@0: CREATE TABLE t4(a, b, c); sl@0: INSERT INTO t4 VALUES(1, 2, 3); sl@0: SELECT * FROM t4; sl@0: } sl@0: } {1 2 3} sl@0: do_test pragma-8.1.6 { sl@0: execsql { sl@0: PRAGMA schema_version; sl@0: } sl@0: } 107 sl@0: sl@0: # Now open a second connection to the database. Ensure that changing the sl@0: # schema-version using the first connection forces the second connection sl@0: # to reload the schema. This has to be done using the C-API test functions, sl@0: # because the TCL API accounts for SCHEMA_ERROR and retries the query. sl@0: do_test pragma-8.1.7 { sl@0: sqlite3 db2 test.db; set ::DB2 [sqlite3_connection_pointer db2] sl@0: execsql { sl@0: SELECT * FROM t4; sl@0: } db2 sl@0: } {1 2 3} sl@0: do_test pragma-8.1.8 { sl@0: execsql { sl@0: PRAGMA schema_version = 108; sl@0: } sl@0: } {} sl@0: do_test pragma-8.1.9 { sl@0: set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM t4" -1 DUMMY] sl@0: sqlite3_step $::STMT sl@0: } SQLITE_ERROR sl@0: do_test pragma-8.1.10 { sl@0: sqlite3_finalize $::STMT sl@0: } SQLITE_SCHEMA sl@0: sl@0: # Make sure the schema-version can be manipulated in an attached database. sl@0: file delete -force test2.db sl@0: file delete -force test2.db-journal sl@0: ifcapable attach { sl@0: do_test pragma-8.1.11 { sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: CREATE TABLE aux.t1(a, b, c); sl@0: PRAGMA aux.schema_version = 205; sl@0: } sl@0: } {} sl@0: do_test pragma-8.1.12 { sl@0: execsql { sl@0: PRAGMA aux.schema_version; sl@0: } sl@0: } 205 sl@0: } sl@0: do_test pragma-8.1.13 { sl@0: execsql { sl@0: PRAGMA schema_version; sl@0: } sl@0: } 108 sl@0: sl@0: # And check that modifying the schema-version in an attached database sl@0: # forces the second connection to reload the schema. sl@0: ifcapable attach { sl@0: do_test pragma-8.1.14 { sl@0: sqlite3 db2 test.db; set ::DB2 [sqlite3_connection_pointer db2] sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: SELECT * FROM aux.t1; sl@0: } db2 sl@0: } {} sl@0: do_test pragma-8.1.15 { sl@0: execsql { sl@0: PRAGMA aux.schema_version = 206; sl@0: } sl@0: } {} sl@0: do_test pragma-8.1.16 { sl@0: set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM aux.t1" -1 DUMMY] sl@0: sqlite3_step $::STMT sl@0: } SQLITE_ERROR sl@0: do_test pragma-8.1.17 { sl@0: sqlite3_finalize $::STMT sl@0: } SQLITE_SCHEMA sl@0: do_test pragma-8.1.18 { sl@0: db2 close sl@0: } {} sl@0: } sl@0: sl@0: # Now test that the user-version can be read and written (and that we aren't sl@0: # accidentally manipulating the schema-version instead). sl@0: do_test pragma-8.2.1 { sl@0: execsql2 { sl@0: PRAGMA user_version; sl@0: } sl@0: } {user_version 0} sl@0: do_test pragma-8.2.2 { sl@0: execsql { sl@0: PRAGMA user_version = 2; sl@0: } sl@0: } {} sl@0: do_test pragma-8.2.3.1 { sl@0: execsql2 { sl@0: PRAGMA user_version; sl@0: } sl@0: } {user_version 2} sl@0: do_test pragma-8.2.3.2 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA user_version; sl@0: } sl@0: } {2} sl@0: do_test pragma-8.2.4.1 { sl@0: execsql { sl@0: PRAGMA schema_version; sl@0: } sl@0: } {108} sl@0: ifcapable vacuum { sl@0: do_test pragma-8.2.4.2 { sl@0: execsql { sl@0: VACUUM; sl@0: PRAGMA user_version; sl@0: } sl@0: } {2} sl@0: do_test pragma-8.2.4.3 { sl@0: execsql { sl@0: PRAGMA schema_version; sl@0: } sl@0: } {109} sl@0: } sl@0: sl@0: ifcapable attach { sl@0: db eval {ATTACH 'test2.db' AS aux} sl@0: sl@0: # Check that the user-version in the auxilary database can be manipulated ( sl@0: # and that we aren't accidentally manipulating the same in the main db). sl@0: do_test pragma-8.2.5 { sl@0: execsql { sl@0: PRAGMA aux.user_version; sl@0: } sl@0: } {0} sl@0: do_test pragma-8.2.6 { sl@0: execsql { sl@0: PRAGMA aux.user_version = 3; sl@0: } sl@0: } {} sl@0: do_test pragma-8.2.7 { sl@0: execsql { sl@0: PRAGMA aux.user_version; sl@0: } sl@0: } {3} sl@0: do_test pragma-8.2.8 { sl@0: execsql { sl@0: PRAGMA main.user_version; sl@0: } sl@0: } {2} sl@0: sl@0: # Now check that a ROLLBACK resets the user-version if it has been modified sl@0: # within a transaction. sl@0: do_test pragma-8.2.9 { sl@0: execsql { sl@0: BEGIN; sl@0: PRAGMA aux.user_version = 10; sl@0: PRAGMA user_version = 11; sl@0: } sl@0: } {} sl@0: do_test pragma-8.2.10 { sl@0: execsql { sl@0: PRAGMA aux.user_version; sl@0: } sl@0: } {10} sl@0: do_test pragma-8.2.11 { sl@0: execsql { sl@0: PRAGMA main.user_version; sl@0: } sl@0: } {11} sl@0: do_test pragma-8.2.12 { sl@0: execsql { sl@0: ROLLBACK; sl@0: PRAGMA aux.user_version; sl@0: } sl@0: } {3} sl@0: do_test pragma-8.2.13 { sl@0: execsql { sl@0: PRAGMA main.user_version; sl@0: } sl@0: } {2} sl@0: } sl@0: sl@0: # Try a negative value for the user-version sl@0: do_test pragma-8.2.14 { sl@0: execsql { sl@0: PRAGMA user_version = -450; sl@0: } sl@0: } {} sl@0: do_test pragma-8.2.15 { sl@0: execsql { sl@0: PRAGMA user_version; sl@0: } sl@0: } {-450} sl@0: } ; # ifcapable schema_version sl@0: sl@0: # Check to see if TEMP_STORE is memory or disk. Return strings sl@0: # "memory" or "disk" as appropriate. sl@0: # sl@0: proc check_temp_store {} { sl@0: db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)} sl@0: db eval {PRAGMA database_list} { sl@0: if {$name=="temp"} { sl@0: set bt [btree_from_db db 1] sl@0: if {[btree_ismemdb $bt]} { sl@0: return "memory" sl@0: } sl@0: return "disk" sl@0: } sl@0: } sl@0: return "unknown" sl@0: } sl@0: sl@0: sl@0: # Test temp_store and temp_store_directory pragmas sl@0: # sl@0: ifcapable pager_pragmas { sl@0: do_test pragma-9.1 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA temp_store; sl@0: } sl@0: } {0} sl@0: if {$TEMP_STORE<=1} { sl@0: do_test pragma-9.1.1 { sl@0: check_temp_store sl@0: } {disk} sl@0: } else { sl@0: do_test pragma-9.1.1 { sl@0: check_temp_store sl@0: } {memory} sl@0: } sl@0: sl@0: do_test pragma-9.2 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA temp_store=file; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {1} sl@0: if {$TEMP_STORE==3} { sl@0: # When TEMP_STORE is 3, always use memory regardless of pragma settings. sl@0: do_test pragma-9.2.1 { sl@0: check_temp_store sl@0: } {memory} sl@0: } else { sl@0: do_test pragma-9.2.1 { sl@0: check_temp_store sl@0: } {disk} sl@0: } sl@0: sl@0: do_test pragma-9.3 { sl@0: db close sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA temp_store=memory; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {2} sl@0: if {$TEMP_STORE==0} { sl@0: # When TEMP_STORE is 0, always use the disk regardless of pragma settings. sl@0: do_test pragma-9.3.1 { sl@0: check_temp_store sl@0: } {disk} sl@0: } else { sl@0: do_test pragma-9.3.1 { sl@0: check_temp_store sl@0: } {memory} sl@0: } sl@0: sl@0: do_test pragma-9.4 { sl@0: execsql { sl@0: PRAGMA temp_store_directory; sl@0: } sl@0: } {} sl@0: ifcapable wsd { sl@0: do_test pragma-9.5 { sl@0: set pwd [string map {' ''} [file nativename [pwd]]] sl@0: execsql " sl@0: PRAGMA temp_store_directory='$pwd'; sl@0: " sl@0: } {} sl@0: do_test pragma-9.6 { sl@0: execsql { sl@0: PRAGMA temp_store_directory; sl@0: } sl@0: } [list [file nativename [pwd]]] sl@0: do_test pragma-9.7 { sl@0: catchsql { sl@0: PRAGMA temp_store_directory='/NON/EXISTENT/PATH/FOOBAR'; sl@0: } sl@0: } {1 {not a writable directory}} sl@0: do_test pragma-9.8 { sl@0: execsql { sl@0: PRAGMA temp_store_directory=''; sl@0: } sl@0: } {} sl@0: if {![info exists TEMP_STORE] || $TEMP_STORE<=1} { sl@0: ifcapable tempdb { sl@0: do_test pragma-9.9 { sl@0: execsql { sl@0: PRAGMA temp_store_directory; sl@0: PRAGMA temp_store=FILE; sl@0: CREATE TEMP TABLE temp_store_directory_test(a integer); sl@0: INSERT INTO temp_store_directory_test values (2); sl@0: SELECT * FROM temp_store_directory_test; sl@0: } sl@0: } {2} sl@0: do_test pragma-9.10 { sl@0: catchsql " sl@0: PRAGMA temp_store_directory='$pwd'; sl@0: SELECT * FROM temp_store_directory_test; sl@0: " sl@0: } {1 {no such table: temp_store_directory_test}} sl@0: } sl@0: } sl@0: } sl@0: do_test pragma-9.11 { sl@0: execsql { sl@0: PRAGMA temp_store = 0; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {0} sl@0: do_test pragma-9.12 { sl@0: execsql { sl@0: PRAGMA temp_store = 1; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {1} sl@0: do_test pragma-9.13 { sl@0: execsql { sl@0: PRAGMA temp_store = 2; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {2} sl@0: do_test pragma-9.14 { sl@0: execsql { sl@0: PRAGMA temp_store = 3; sl@0: PRAGMA temp_store; sl@0: } sl@0: } {0} sl@0: do_test pragma-9.15 { sl@0: catchsql { sl@0: BEGIN EXCLUSIVE; sl@0: CREATE TEMP TABLE temp_table(t); sl@0: INSERT INTO temp_table VALUES('valuable data'); sl@0: PRAGMA temp_store = 1; sl@0: } sl@0: } {1 {temporary storage cannot be changed from within a transaction}} sl@0: do_test pragma-9.16 { sl@0: execsql { sl@0: SELECT * FROM temp_table; sl@0: COMMIT; sl@0: } sl@0: } {{valuable data}} sl@0: sl@0: do_test pragma-9.17 { sl@0: execsql { sl@0: INSERT INTO temp_table VALUES('valuable data II'); sl@0: SELECT * FROM temp_table; sl@0: } sl@0: } {{valuable data} {valuable data II}} sl@0: sl@0: do_test pragma-9.18 { sl@0: set rc [catch { sl@0: db eval {SELECT t FROM temp_table} { sl@0: execsql {pragma temp_store = 1} sl@0: } sl@0: } msg] sl@0: list $rc $msg sl@0: } {1 {temporary storage cannot be changed from within a transaction}} sl@0: sl@0: } ;# ifcapable pager_pragmas sl@0: sl@0: ifcapable trigger { sl@0: sl@0: do_test pragma-10.0 { sl@0: catchsql { sl@0: DROP TABLE main.t1; sl@0: } sl@0: execsql { sl@0: PRAGMA count_changes = 1; sl@0: sl@0: CREATE TABLE t1(a PRIMARY KEY); sl@0: CREATE TABLE t1_mirror(a); sl@0: CREATE TABLE t1_mirror2(a); sl@0: CREATE TRIGGER t1_bi BEFORE INSERT ON t1 BEGIN sl@0: INSERT INTO t1_mirror VALUES(new.a); sl@0: END; sl@0: CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN sl@0: INSERT INTO t1_mirror2 VALUES(new.a); sl@0: END; sl@0: CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN sl@0: UPDATE t1_mirror SET a = new.a WHERE a = old.a; sl@0: END; sl@0: CREATE TRIGGER t1_au AFTER UPDATE ON t1 BEGIN sl@0: UPDATE t1_mirror2 SET a = new.a WHERE a = old.a; sl@0: END; sl@0: CREATE TRIGGER t1_bd BEFORE DELETE ON t1 BEGIN sl@0: DELETE FROM t1_mirror WHERE a = old.a; sl@0: END; sl@0: CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN sl@0: DELETE FROM t1_mirror2 WHERE a = old.a; sl@0: END; sl@0: } sl@0: } {} sl@0: sl@0: do_test pragma-10.1 { sl@0: execsql { sl@0: INSERT INTO t1 VALUES(randstr(10,10)); sl@0: } sl@0: } {1} sl@0: do_test pragma-10.2 { sl@0: execsql { sl@0: UPDATE t1 SET a = randstr(10,10); sl@0: } sl@0: } {1} sl@0: do_test pragma-10.3 { sl@0: execsql { sl@0: DELETE FROM t1; sl@0: } sl@0: } {1} sl@0: sl@0: } ;# ifcapable trigger sl@0: sl@0: ifcapable schema_pragmas { sl@0: do_test pragma-11.1 { sl@0: execsql2 { sl@0: pragma collation_list; sl@0: } sl@0: } {seq 0 name NOCASE seq 1 name RTRIM seq 2 name BINARY} sl@0: do_test pragma-11.2 { sl@0: db collate New_Collation blah... sl@0: execsql { sl@0: pragma collation_list; sl@0: } sl@0: } {0 New_Collation 1 NOCASE 2 RTRIM 3 BINARY} sl@0: } sl@0: sl@0: ifcapable schema_pragmas&&tempdb { sl@0: do_test pragma-12.1 { sl@0: sqlite3 db2 test.db sl@0: execsql { sl@0: PRAGMA temp.table_info('abc'); sl@0: } db2 sl@0: } {} sl@0: db2 close sl@0: sl@0: do_test pragma-12.2 { sl@0: sqlite3 db2 test.db sl@0: execsql { sl@0: PRAGMA temp.default_cache_size = 200; sl@0: PRAGMA temp.default_cache_size; sl@0: } db2 sl@0: } {200} sl@0: db2 close sl@0: sl@0: do_test pragma-12.3 { sl@0: sqlite3 db2 test.db sl@0: execsql { sl@0: PRAGMA temp.cache_size = 400; sl@0: PRAGMA temp.cache_size; sl@0: } db2 sl@0: } {400} sl@0: db2 close sl@0: } sl@0: sl@0: ifcapable bloblit { sl@0: sl@0: do_test pragma-13.1 { sl@0: execsql { sl@0: DROP TABLE IF EXISTS t4; sl@0: PRAGMA vdbe_trace=on; sl@0: PRAGMA vdbe_listing=on; sl@0: PRAGMA sql_trace=on; sl@0: CREATE TABLE t4(a INTEGER PRIMARY KEY,b); sl@0: INSERT INTO t4(b) VALUES(x'0123456789abcdef0123456789abcdef0123456789'); sl@0: INSERT INTO t4(b) VALUES(randstr(30,30)); sl@0: INSERT INTO t4(b) VALUES(1.23456); sl@0: INSERT INTO t4(b) VALUES(NULL); sl@0: INSERT INTO t4(b) VALUES(0); sl@0: INSERT INTO t4(b) SELECT b||b||b||b FROM t4; sl@0: SELECT * FROM t4; sl@0: } sl@0: execsql { sl@0: PRAGMA vdbe_trace=off; sl@0: PRAGMA vdbe_listing=off; sl@0: PRAGMA sql_trace=off; sl@0: } sl@0: } {} sl@0: sl@0: } ;# ifcapable bloblit sl@0: sl@0: ifcapable pager_pragmas { sl@0: db close sl@0: file delete -force test.db sl@0: sqlite3 db test.db sl@0: sl@0: do_test pragma-14.1 { sl@0: execsql { pragma auto_vacuum = 0 } sl@0: execsql { pragma page_count } sl@0: } {0} sl@0: sl@0: do_test pragma-14.2 { sl@0: execsql { sl@0: CREATE TABLE abc(a, b, c); sl@0: PRAGMA page_count; sl@0: } sl@0: } {2} sl@0: sl@0: do_test pragma-14.3 { sl@0: execsql { sl@0: BEGIN; sl@0: CREATE TABLE def(a, b, c); sl@0: PRAGMA page_count; sl@0: } sl@0: } {3} sl@0: sl@0: do_test pragma-14.4 { sl@0: set page_size [db one {pragma page_size}] sl@0: expr [file size test.db] / $page_size sl@0: } {2} sl@0: sl@0: do_test pragma-14.5 { sl@0: execsql { sl@0: ROLLBACK; sl@0: PRAGMA page_count; sl@0: } sl@0: } {2} sl@0: sl@0: do_test pragma-14.6 { sl@0: file delete -force test2.db sl@0: sqlite3 db2 test2.db sl@0: execsql { sl@0: PRAGMA auto_vacuum = 0; sl@0: CREATE TABLE t1(a, b, c); sl@0: CREATE TABLE t2(a, b, c); sl@0: CREATE TABLE t3(a, b, c); sl@0: CREATE TABLE t4(a, b, c); sl@0: } db2 sl@0: db2 close sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: PRAGMA aux.page_count; sl@0: } sl@0: } {5} sl@0: } sl@0: sl@0: # Test that the value set using the cache_size pragma is not reset when the sl@0: # schema is reloaded. sl@0: # sl@0: ifcapable pager_pragmas { sl@0: db close sl@0: sqlite3 db test.db sl@0: do_test pragma-15.1 { sl@0: execsql { sl@0: PRAGMA cache_size=59; sl@0: PRAGMA cache_size; sl@0: } sl@0: } {59} sl@0: do_test pragma-15.2 { sl@0: sqlite3 db2 test.db sl@0: execsql { sl@0: CREATE TABLE newtable(a, b, c); sl@0: } db2 sl@0: db2 close sl@0: } {} sl@0: do_test pragma-15.3 { sl@0: # Evaluating this statement will cause the schema to be reloaded (because sl@0: # the schema was changed by another connection in pragma-15.2). At one sl@0: # point there was a bug that reset the cache_size to its default value sl@0: # when this happened. sl@0: execsql { SELECT * FROM sqlite_master } sl@0: execsql { PRAGMA cache_size } sl@0: } {59} sl@0: } sl@0: sl@0: # Reset the sqlite3_temp_directory variable for the next run of tests: sl@0: sqlite3 dbX :memory: sl@0: dbX eval {PRAGMA temp_store_directory = ""} sl@0: dbX close sl@0: sl@0: finish_test