1# 2002 March 6 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. 12# 13# This file implements tests for the PRAGMA command. 14# 15# $Id: pragma.test,v 1.36 2005/05/22 20:30:39 drh Exp $ 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20# Test organization: 21# 22# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db. 23# pragma-2.*: Test synchronous on attached db. 24# pragma-3.*: Test detection of table/index inconsistency by integrity_check. 25# pragma-4.*: Test cache_size and default_cache_size on attached db. 26# pragma-5.*: Test that pragma synchronous may not be used inside of a 27# transaction. 28# pragma-6.*: Test schema-query pragmas. 29# pragma-7.*: Miscellaneous tests. 30# pragma-8.*: Test user_version and schema_version pragmas. 31# pragma-9.*: Test temp_store and temp_store_directory. 32# pragma-10.*: Test the count_changes pragma in the presence of triggers. 33# pragma-11.*: Test the collation_list pragma. 34# 35 36# Delete the preexisting database to avoid the special setup 37# that the "all.test" script does. 38# 39db close 40file delete test.db 41set DB [sqlite3 db test.db] 42 43ifcapable pager_pragmas { 44do_test pragma-1.1 { 45 execsql { 46 PRAGMA cache_size; 47 PRAGMA default_cache_size; 48 PRAGMA synchronous; 49 } 50} {2000 2000 2} 51do_test pragma-1.2 { 52 execsql { 53 PRAGMA synchronous=OFF; 54 PRAGMA cache_size=1234; 55 PRAGMA cache_size; 56 PRAGMA default_cache_size; 57 PRAGMA synchronous; 58 } 59} {1234 2000 0} 60do_test pragma-1.3 { 61 db close 62 sqlite3 db test.db 63 execsql { 64 PRAGMA cache_size; 65 PRAGMA default_cache_size; 66 PRAGMA synchronous; 67 } 68} {2000 2000 2} 69do_test pragma-1.4 { 70 execsql { 71 PRAGMA synchronous=OFF; 72 PRAGMA cache_size; 73 PRAGMA default_cache_size; 74 PRAGMA synchronous; 75 } 76} {2000 2000 0} 77do_test pragma-1.5 { 78 execsql { 79 PRAGMA cache_size=4321; 80 PRAGMA cache_size; 81 PRAGMA default_cache_size; 82 PRAGMA synchronous; 83 } 84} {4321 2000 0} 85do_test pragma-1.6 { 86 execsql { 87 PRAGMA synchronous=ON; 88 PRAGMA cache_size; 89 PRAGMA default_cache_size; 90 PRAGMA synchronous; 91 } 92} {4321 2000 1} 93do_test pragma-1.7 { 94 db close 95 sqlite3 db test.db 96 execsql { 97 PRAGMA cache_size; 98 PRAGMA default_cache_size; 99 PRAGMA synchronous; 100 } 101} {2000 2000 2} 102do_test pragma-1.8 { 103 execsql { 104 PRAGMA default_cache_size=123; 105 PRAGMA cache_size; 106 PRAGMA default_cache_size; 107 PRAGMA synchronous; 108 } 109} {123 123 2} 110do_test pragma-1.9.1 { 111 db close 112 set ::DB [sqlite3 db test.db] 113 execsql { 114 PRAGMA cache_size; 115 PRAGMA default_cache_size; 116 PRAGMA synchronous; 117 } 118} {123 123 2} 119ifcapable vacuum { 120 do_test pragma-1.9.2 { 121 execsql { 122 VACUUM; 123 PRAGMA cache_size; 124 PRAGMA default_cache_size; 125 PRAGMA synchronous; 126 } 127 } {123 123 2} 128} 129do_test pragma-1.10 { 130 execsql { 131 PRAGMA synchronous=NORMAL; 132 PRAGMA cache_size; 133 PRAGMA default_cache_size; 134 PRAGMA synchronous; 135 } 136} {123 123 1} 137do_test pragma-1.11 { 138 execsql { 139 PRAGMA synchronous=FULL; 140 PRAGMA cache_size; 141 PRAGMA default_cache_size; 142 PRAGMA synchronous; 143 } 144} {123 123 2} 145do_test pragma-1.12 { 146 db close 147 set ::DB [sqlite3 db test.db] 148 execsql { 149 PRAGMA cache_size; 150 PRAGMA default_cache_size; 151 PRAGMA synchronous; 152 } 153} {123 123 2} 154 155# Make sure the pragma handler understands numeric values in addition 156# to keywords like "off" and "full". 157# 158do_test pragma-1.13 { 159 execsql { 160 PRAGMA synchronous=0; 161 PRAGMA synchronous; 162 } 163} {0} 164do_test pragma-1.14 { 165 execsql { 166 PRAGMA synchronous=2; 167 PRAGMA synchronous; 168 } 169} {2} 170} ;# ifcapable pager_pragmas 171 172# Test turning "flag" pragmas on and off. 173# 174do_test pragma-1.15 { 175 execsql { 176 PRAGMA vdbe_listing=YES; 177 PRAGMA vdbe_listing; 178 } 179} {1} 180do_test pragma-1.16 { 181 execsql { 182 PRAGMA vdbe_listing=NO; 183 PRAGMA vdbe_listing; 184 } 185} {0} 186do_test pragma-1.17 { 187 execsql { 188 PRAGMA parser_trace=ON; 189 PRAGMA parser_trace=OFF; 190 } 191} {} 192do_test pragma-1.18 { 193 execsql { 194 PRAGMA bogus = -1234; -- Parsing of negative values 195 } 196} {} 197 198# Test modifying the safety_level of an attached database. 199do_test pragma-2.1 { 200 file delete -force test2.db 201 file delete -force test2.db-journal 202 execsql { 203 ATTACH 'test2.db' AS aux; 204 } 205} {} 206ifcapable pager_pragmas { 207do_test pragma-2.2 { 208 execsql { 209 pragma aux.synchronous; 210 } 211} {2} 212do_test pragma-2.3 { 213 execsql { 214 pragma aux.synchronous = OFF; 215 pragma aux.synchronous; 216 pragma synchronous; 217 } 218} {0 2} 219do_test pragma-2.4 { 220 execsql { 221 pragma aux.synchronous = ON; 222 pragma synchronous; 223 pragma aux.synchronous; 224 } 225} {2 1} 226} ;# ifcapable pager_pragmas 227 228# Construct a corrupted index and make sure the integrity_check 229# pragma finds it. 230# 231# These tests won't work if the database is encrypted 232# 233do_test pragma-3.1 { 234 execsql { 235 BEGIN; 236 CREATE TABLE t2(a,b,c); 237 CREATE INDEX i2 ON t2(a); 238 INSERT INTO t2 VALUES(11,2,3); 239 INSERT INTO t2 VALUES(22,3,4); 240 COMMIT; 241 SELECT rowid, * from t2; 242 } 243} {1 11 2 3 2 22 3 4} 244if {![sqlite3 -has-codec] && $sqlite_options(integrityck)} { 245 do_test pragma-3.2 { 246 set rootpage [execsql {SELECT rootpage FROM sqlite_master WHERE name='i2'}] 247 set db [btree_open test.db 100 0] 248 btree_begin_transaction $db 249 set c [btree_cursor $db $rootpage 1] 250 btree_first $c 251 btree_delete $c 252 btree_commit $db 253 btree_close $db 254 execsql {PRAGMA integrity_check} 255 } {{rowid 1 missing from index i2} {wrong # of entries in index i2}} 256} 257do_test pragma-3.3 { 258 execsql { 259 DROP INDEX i2; 260 } 261} {} 262 263# Test modifying the cache_size of an attached database. 264ifcapable pager_pragmas { 265do_test pragma-4.1 { 266 execsql { 267 pragma aux.cache_size; 268 pragma aux.default_cache_size; 269 } 270} {2000 2000} 271do_test pragma-4.2 { 272 execsql { 273 pragma aux.cache_size = 50; 274 pragma aux.cache_size; 275 pragma aux.default_cache_size; 276 } 277} {50 2000} 278do_test pragma-4.3 { 279 execsql { 280 pragma aux.default_cache_size = 456; 281 pragma aux.cache_size; 282 pragma aux.default_cache_size; 283 } 284} {456 456} 285do_test pragma-4.4 { 286 execsql { 287 pragma cache_size; 288 pragma default_cache_size; 289 } 290} {123 123} 291do_test pragma-4.5 { 292 execsql { 293 DETACH aux; 294 ATTACH 'test3.db' AS aux; 295 pragma aux.cache_size; 296 pragma aux.default_cache_size; 297 } 298} {2000 2000} 299do_test pragma-4.6 { 300 execsql { 301 DETACH aux; 302 ATTACH 'test2.db' AS aux; 303 pragma aux.cache_size; 304 pragma aux.default_cache_size; 305 } 306} {456 456} 307} ;# ifcapable pager_pragmas 308 309# Test that modifying the sync-level in the middle of a transaction is 310# disallowed. 311ifcapable pager_pragmas { 312do_test pragma-5.0 { 313 execsql { 314 pragma synchronous; 315 } 316} {2} 317do_test pragma-5.1 { 318 catchsql { 319 BEGIN; 320 pragma synchronous = OFF; 321 } 322} {1 {Safety level may not be changed inside a transaction}} 323do_test pragma-5.2 { 324 execsql { 325 pragma synchronous; 326 } 327} {2} 328catchsql {COMMIT;} 329} ;# ifcapable pager_pragmas 330 331# Test schema-query pragmas 332# 333ifcapable schema_pragmas { 334ifcapable tempdb { 335 do_test pragma-6.1 { 336 set res {} 337 execsql {SELECT * FROM sqlite_temp_master} 338 foreach {idx name file} [execsql {pragma database_list}] { 339 lappend res $idx $name 340 } 341 set res 342 } {0 main 1 temp 2 aux} 343} 344do_test pragma-6.2 { 345 execsql { 346 pragma table_info(t2) 347 } 348} {0 a numeric 0 {} 0 1 b numeric 0 {} 0 2 c numeric 0 {} 0} 349ifcapable {foreignkey} { 350 do_test pragma-6.3 { 351 execsql { 352 CREATE TABLE t3(a int references t2(b), b UNIQUE); 353 pragma foreign_key_list(t3); 354 } 355 } {0 0 t2 a b} 356 do_test pragma-6.4 { 357 execsql { 358 pragma index_list(t3); 359 } 360 } {0 sqlite_autoindex_t3_1 1} 361} 362ifcapable {!foreignkey} { 363 execsql {CREATE TABLE t3(a,b UNIQUE)} 364} 365do_test pragma-6.5 { 366 execsql { 367 CREATE INDEX t3i1 ON t3(a,b); 368 pragma index_info(t3i1); 369 } 370} {0 0 a 1 1 b} 371} ;# ifcapable schema_pragmas 372# Miscellaneous tests 373# 374ifcapable schema_pragmas { 375do_test pragma-7.1 { 376 # Make sure a pragma knows to read the schema if it needs to 377 db close 378 sqlite3 db test.db 379 execsql { 380 pragma index_list(t3); 381 } 382} {0 t3i1 0 1 sqlite_autoindex_t3_1 1} 383} ;# ifcapable schema_pragmas 384ifcapable {utf16} { 385 do_test pragma-7.2 { 386 db close 387 sqlite3 db test.db 388 catchsql { 389 pragma encoding=bogus; 390 } 391 } {1 {unsupported encoding: bogus}} 392} 393ifcapable tempdb { 394 do_test pragma-7.3 { 395 db close 396 sqlite3 db test.db 397 execsql { 398 pragma lock_status; 399 } 400 } {main unlocked temp closed} 401} else { 402 do_test pragma-7.3 { 403 db close 404 sqlite3 db test.db 405 execsql { 406 pragma lock_status; 407 } 408 } {main unlocked} 409} 410 411 412#---------------------------------------------------------------------- 413# Test cases pragma-8.* test the "PRAGMA schema_version" and "PRAGMA 414# user_version" statements. 415# 416# pragma-8.1: PRAGMA schema_version 417# pragma-8.2: PRAGMA user_version 418# 419 420ifcapable schema_version { 421 422# First check that we can set the schema version and then retrieve the 423# same value. 424do_test pragma-8.1.1 { 425 execsql { 426 PRAGMA schema_version = 105; 427 } 428} {} 429do_test pragma-8.1.2 { 430 execsql { 431 PRAGMA schema_version; 432 } 433} 105 434do_test pragma-8.1.3 { 435 execsql { 436 PRAGMA schema_version = 106; 437 } 438} {} 439do_test pragma-8.1.4 { 440 execsql { 441 PRAGMA schema_version; 442 } 443} 106 444 445# Check that creating a table modifies the schema-version (this is really 446# to verify that the value being read is in fact the schema version). 447do_test pragma-8.1.5 { 448 execsql { 449 CREATE TABLE t4(a, b, c); 450 INSERT INTO t4 VALUES(1, 2, 3); 451 SELECT * FROM t4; 452 } 453} {1 2 3} 454do_test pragma-8.1.6 { 455 execsql { 456 PRAGMA schema_version; 457 } 458} 107 459 460# Now open a second connection to the database. Ensure that changing the 461# schema-version using the first connection forces the second connection 462# to reload the schema. This has to be done using the C-API test functions, 463# because the TCL API accounts for SCHEMA_ERROR and retries the query. 464do_test pragma-8.1.7 { 465 set ::DB2 [sqlite3 db2 test.db] 466 execsql { 467 SELECT * FROM t4; 468 } db2 469} {1 2 3} 470do_test pragma-8.1.8 { 471 execsql { 472 PRAGMA schema_version = 108; 473 } 474} {} 475do_test pragma-8.1.9 { 476 set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM t4" -1 DUMMY] 477 sqlite3_step $::STMT 478} SQLITE_ERROR 479do_test pragma-8.1.10 { 480 sqlite3_finalize $::STMT 481} SQLITE_SCHEMA 482 483# Make sure the schema-version can be manipulated in an attached database. 484file delete -force test2.db 485file delete -force test2.db-journal 486do_test pragma-8.1.11 { 487 execsql { 488 ATTACH 'test2.db' AS aux; 489 CREATE TABLE aux.t1(a, b, c); 490 PRAGMA aux.schema_version = 205; 491 } 492} {} 493do_test pragma-8.1.12 { 494 execsql { 495 PRAGMA aux.schema_version; 496 } 497} 205 498do_test pragma-8.1.13 { 499 execsql { 500 PRAGMA schema_version; 501 } 502} 108 503 504# And check that modifying the schema-version in an attached database 505# forces the second connection to reload the schema. 506do_test pragma-8.1.14 { 507 set ::DB2 [sqlite3 db2 test.db] 508 execsql { 509 ATTACH 'test2.db' AS aux; 510 SELECT * FROM aux.t1; 511 } db2 512} {} 513do_test pragma-8.1.15 { 514 execsql { 515 PRAGMA aux.schema_version = 206; 516 } 517} {} 518do_test pragma-8.1.16 { 519 set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM aux.t1" -1 DUMMY] 520 sqlite3_step $::STMT 521} SQLITE_ERROR 522do_test pragma-8.1.17 { 523 sqlite3_finalize $::STMT 524} SQLITE_SCHEMA 525do_test pragma-8.1.18 { 526 db2 close 527} {} 528 529# Now test that the user-version can be read and written (and that we aren't 530# accidentally manipulating the schema-version instead). 531do_test pragma-8.2.1 { 532 execsql { 533 PRAGMA user_version; 534 } 535} {0} 536do_test pragma-8.2.2 { 537 execsql { 538 PRAGMA user_version = 2; 539 } 540} {} 541do_test pragma-8.2.3.1 { 542 execsql { 543 PRAGMA user_version; 544 } 545} {2} 546do_test pragma-8.2.3.2 { 547 db close 548 sqlite3 db test.db 549 execsql { 550 PRAGMA user_version; 551 } 552} {2} 553do_test pragma-8.2.4.1 { 554 execsql { 555 PRAGMA schema_version; 556 } 557} {108} 558ifcapable vacuum { 559 do_test pragma-8.2.4.2 { 560 execsql { 561 VACUUM; 562 PRAGMA user_version; 563 } 564 } {2} 565 do_test pragma-8.2.4.3 { 566 execsql { 567 PRAGMA schema_version; 568 } 569 } {109} 570} 571db eval {ATTACH 'test2.db' AS aux} 572 573# Check that the user-version in the auxilary database can be manipulated ( 574# and that we aren't accidentally manipulating the same in the main db). 575do_test pragma-8.2.5 { 576 execsql { 577 PRAGMA aux.user_version; 578 } 579} {0} 580do_test pragma-8.2.6 { 581 execsql { 582 PRAGMA aux.user_version = 3; 583 } 584} {} 585do_test pragma-8.2.7 { 586 execsql { 587 PRAGMA aux.user_version; 588 } 589} {3} 590do_test pragma-8.2.8 { 591 execsql { 592 PRAGMA main.user_version; 593 } 594} {2} 595 596# Now check that a ROLLBACK resets the user-version if it has been modified 597# within a transaction. 598do_test pragma-8.2.9 { 599 execsql { 600 BEGIN; 601 PRAGMA aux.user_version = 10; 602 PRAGMA user_version = 11; 603 } 604} {} 605do_test pragma-8.2.10 { 606 execsql { 607 PRAGMA aux.user_version; 608 } 609} {10} 610do_test pragma-8.2.11 { 611 execsql { 612 PRAGMA main.user_version; 613 } 614} {11} 615do_test pragma-8.2.12 { 616 execsql { 617 ROLLBACK; 618 PRAGMA aux.user_version; 619 } 620} {3} 621do_test pragma-8.2.13 { 622 execsql { 623 PRAGMA main.user_version; 624 } 625} {2} 626 627# Try a negative value for the user-version 628do_test pragma-8.2.14 { 629 execsql { 630 PRAGMA user_version = -450; 631 } 632} {} 633do_test pragma-8.2.15 { 634 execsql { 635 PRAGMA user_version; 636 } 637} {-450} 638} ; # ifcapable schema_version 639 640 641# Test temp_store and temp_store_directory pragmas 642# 643ifcapable pager_pragmas { 644do_test pragma-9.1 { 645 db close 646 sqlite3 db test.db 647 execsql { 648 PRAGMA temp_store; 649 } 650} {0} 651do_test pragma-9.2 { 652 execsql { 653 PRAGMA temp_store=file; 654 PRAGMA temp_store; 655 } 656} {1} 657do_test pragma-9.3 { 658 execsql { 659 PRAGMA temp_store=memory; 660 PRAGMA temp_store; 661 } 662} {2} 663do_test pragma-9.4 { 664 execsql { 665 PRAGMA temp_store_directory; 666 } 667} {} 668do_test pragma-9.5 { 669 set pwd [string map {' ''} [pwd]] 670 execsql " 671 PRAGMA temp_store_directory='$pwd'; 672 " 673} {} 674do_test pragma-9.6 { 675 execsql { 676 PRAGMA temp_store_directory; 677 } 678} [pwd] 679do_test pragma-9.7 { 680 catchsql { 681 PRAGMA temp_store_directory='/NON/EXISTENT/PATH/FOOBAR'; 682 } 683} {1 {not a writable directory}} 684do_test pragma-9.8 { 685 execsql { 686 PRAGMA temp_store_directory=''; 687 } 688} {} 689ifcapable tempdb { 690 do_test pragma-9.9 { 691 execsql { 692 PRAGMA temp_store_directory; 693 PRAGMA temp_store=FILE; 694 CREATE TEMP TABLE temp_store_directory_test(a integer); 695 INSERT INTO temp_store_directory_test values (2); 696 SELECT * FROM temp_store_directory_test; 697 } 698 } {2} 699} 700do_test pragma-9.10 { 701 catchsql " 702 PRAGMA temp_store_directory='$pwd'; 703 SELECT * FROM temp_store_directory_test; 704 " 705} {1 {no such table: temp_store_directory_test}} 706} ;# ifcapable pager_pragmas 707 708ifcapable trigger { 709 710do_test pragma-10.0 { 711 catchsql { 712 DROP TABLE main.t1; 713 } 714 execsql { 715 PRAGMA count_changes = 1; 716 717 CREATE TABLE t1(a PRIMARY KEY); 718 CREATE TABLE t1_mirror(a); 719 CREATE TABLE t1_mirror2(a); 720 CREATE TRIGGER t1_bi BEFORE INSERT ON t1 BEGIN 721 INSERT INTO t1_mirror VALUES(new.a); 722 END; 723 CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN 724 INSERT INTO t1_mirror2 VALUES(new.a); 725 END; 726 CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN 727 UPDATE t1_mirror SET a = new.a WHERE a = old.a; 728 END; 729 CREATE TRIGGER t1_au AFTER UPDATE ON t1 BEGIN 730 UPDATE t1_mirror2 SET a = new.a WHERE a = old.a; 731 END; 732 CREATE TRIGGER t1_bd BEFORE DELETE ON t1 BEGIN 733 DELETE FROM t1_mirror WHERE a = old.a; 734 END; 735 CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN 736 DELETE FROM t1_mirror2 WHERE a = old.a; 737 END; 738 } 739} {} 740 741do_test pragma-10.1 { 742 execsql { 743 INSERT INTO t1 VALUES(randstr(10,10)); 744 } 745} {1} 746do_test pragma-10.2 { 747 execsql { 748 UPDATE t1 SET a = randstr(10,10); 749 } 750} {1} 751do_test pragma-10.3 { 752 execsql { 753 DELETE FROM t1; 754 } 755} {1} 756 757} ;# ifcapable trigger 758 759ifcapable schema_pragmas { 760 do_test pragma-11.1 { 761 execsql2 { 762 pragma collation_list; 763 } 764 } {seq 0 name NOCASE seq 1 name BINARY} 765 do_test pragma-11.2 { 766 db collate New_Collation blah... 767 execsql { 768 pragma collation_list; 769 } 770 } {0 New_Collation 1 NOCASE 2 BINARY} 771} 772 773# Reset the sqlite3_temp_directory variable for the next run of tests: 774sqlite3 dbX :memory: 775dbX eval {PRAGMA temp_store_directory = ""} 776dbX close 777 778finish_test 779