1e6e04969Sdrh# 2005 July 22 2e6e04969Sdrh# 3e6e04969Sdrh# The author disclaims copyright to this source code. In place of 4e6e04969Sdrh# a legal notice, here is a blessing: 5e6e04969Sdrh# 6e6e04969Sdrh# May you do good and not evil. 7e6e04969Sdrh# May you find forgiveness for yourself and forgive others. 8e6e04969Sdrh# May you share freely, never taking more than you give. 9e6e04969Sdrh# 10e6e04969Sdrh#*********************************************************************** 11e6e04969Sdrh# This file implements regression tests for SQLite library. 12e6e04969Sdrh# This file implements tests for the ANALYZE command. 13e6e04969Sdrh# 14c456e57aSdrh# $Id: analyze.test,v 1.9 2008/08/11 18:44:58 drh Exp $ 15e6e04969Sdrh 16e6e04969Sdrhset testdir [file dirname $argv0] 17e6e04969Sdrhsource $testdir/tester.tcl 18e6e04969Sdrh 19e6e04969Sdrh# There is nothing to test if ANALYZE is disable for this build. 20e6e04969Sdrh# 21e6e04969Sdrhifcapable {!analyze} { 22e6e04969Sdrh finish_test 23e6e04969Sdrh return 24e6e04969Sdrh} 25e6e04969Sdrh 26e6e04969Sdrh# Basic sanity checks. 27e6e04969Sdrh# 28e6e04969Sdrhdo_test analyze-1.1 { 29e6e04969Sdrh catchsql { 30e6e04969Sdrh ANALYZE no_such_table 31e6e04969Sdrh } 32e6e04969Sdrh} {1 {no such table: no_such_table}} 33e6e04969Sdrhdo_test analyze-1.2 { 34e6e04969Sdrh execsql { 35e6e04969Sdrh SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1' 36e6e04969Sdrh } 37e6e04969Sdrh} {0} 38e6e04969Sdrhdo_test analyze-1.3 { 39e6e04969Sdrh catchsql { 40e6e04969Sdrh ANALYZE no_such_db.no_such_table 41e6e04969Sdrh } 42e6e04969Sdrh} {1 {unknown database no_such_db}} 43e6e04969Sdrhdo_test analyze-1.4 { 44e6e04969Sdrh execsql { 45e6e04969Sdrh SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1' 46e6e04969Sdrh } 47e6e04969Sdrh} {0} 481ec43c9aSdrhdo_test analyze-1.5.1 { 49e6e04969Sdrh catchsql { 50e6e04969Sdrh ANALYZE 51e6e04969Sdrh } 52e6e04969Sdrh} {0 {}} 531ec43c9aSdrhdo_test analyze-1.5.2 { 541ec43c9aSdrh catchsql { 551ec43c9aSdrh PRAGMA empty_result_callbacks=1; 561ec43c9aSdrh ANALYZE 571ec43c9aSdrh } 581ec43c9aSdrh} {0 {}} 59e6e04969Sdrhdo_test analyze-1.6 { 60e6e04969Sdrh execsql { 61e6e04969Sdrh SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1' 62e6e04969Sdrh } 63e6e04969Sdrh} {1} 64c456e57aSdrhdo_test analyze-1.6.2 { 65c456e57aSdrh catchsql { 66c456e57aSdrh CREATE INDEX stat1idx ON sqlite_stat1(idx); 67c456e57aSdrh } 68c456e57aSdrh} {1 {table sqlite_stat1 may not be indexed}} 69c456e57aSdrhdo_test analyze-1.6.3 { 70c456e57aSdrh catchsql { 71c456e57aSdrh CREATE INDEX main.stat1idx ON SQLite_stat1(idx); 72c456e57aSdrh } 73c456e57aSdrh} {1 {table sqlite_stat1 may not be indexed}} 74e6e04969Sdrhdo_test analyze-1.7 { 75e6e04969Sdrh execsql { 7615564055Sdrh SELECT * FROM sqlite_stat1 WHERE idx NOT NULL 77e6e04969Sdrh } 78e6e04969Sdrh} {} 79e6e04969Sdrhdo_test analyze-1.8 { 80e6e04969Sdrh catchsql { 81e6e04969Sdrh ANALYZE main 82e6e04969Sdrh } 83e6e04969Sdrh} {0 {}} 84e6e04969Sdrhdo_test analyze-1.9 { 85e6e04969Sdrh execsql { 8615564055Sdrh SELECT * FROM sqlite_stat1 WHERE idx NOT NULL 87e6e04969Sdrh } 88e6e04969Sdrh} {} 89e6e04969Sdrhdo_test analyze-1.10 { 90e6e04969Sdrh catchsql { 91e6e04969Sdrh CREATE TABLE t1(a,b); 92e6e04969Sdrh ANALYZE main.t1; 93e6e04969Sdrh } 94e6e04969Sdrh} {0 {}} 95e6e04969Sdrhdo_test analyze-1.11 { 96e6e04969Sdrh execsql { 97e6e04969Sdrh SELECT * FROM sqlite_stat1 98e6e04969Sdrh } 99f6cf1ffbSdrh} {} 100e6e04969Sdrhdo_test analyze-1.12 { 101e6e04969Sdrh catchsql { 102e6e04969Sdrh ANALYZE t1; 103e6e04969Sdrh } 104e6e04969Sdrh} {0 {}} 105e6e04969Sdrhdo_test analyze-1.13 { 106e6e04969Sdrh execsql { 107e6e04969Sdrh SELECT * FROM sqlite_stat1 108e6e04969Sdrh } 109f6cf1ffbSdrh} {} 110e6e04969Sdrh 111e6e04969Sdrh# Create some indices that can be analyzed. But do not yet add 112e6e04969Sdrh# data. Without data in the tables, no analysis is done. 113e6e04969Sdrh# 114e6e04969Sdrhdo_test analyze-2.1 { 115e6e04969Sdrh execsql { 116e6e04969Sdrh CREATE INDEX t1i1 ON t1(a); 117e6e04969Sdrh ANALYZE main.t1; 118e6e04969Sdrh SELECT * FROM sqlite_stat1 ORDER BY idx; 119e6e04969Sdrh } 120f6cf1ffbSdrh} {} 121e6e04969Sdrhdo_test analyze-2.2 { 122e6e04969Sdrh execsql { 123e6e04969Sdrh CREATE INDEX t1i2 ON t1(b); 124e6e04969Sdrh ANALYZE t1; 125e6e04969Sdrh SELECT * FROM sqlite_stat1 ORDER BY idx; 126e6e04969Sdrh } 127f6cf1ffbSdrh} {} 128e6e04969Sdrhdo_test analyze-2.3 { 129e6e04969Sdrh execsql { 130e6e04969Sdrh CREATE INDEX t1i3 ON t1(a,b); 131e6e04969Sdrh ANALYZE main; 132e6e04969Sdrh SELECT * FROM sqlite_stat1 ORDER BY idx; 133e6e04969Sdrh } 134f6cf1ffbSdrh} {} 135e6e04969Sdrh 136e6e04969Sdrh# Start adding data to the table. Verify that the analysis 137e6e04969Sdrh# is done correctly. 138e6e04969Sdrh# 139e6e04969Sdrhdo_test analyze-3.1 { 140e6e04969Sdrh execsql { 141e6e04969Sdrh INSERT INTO t1 VALUES(1,2); 142e6e04969Sdrh INSERT INTO t1 VALUES(1,3); 143e6e04969Sdrh ANALYZE main.t1; 144e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 145e6e04969Sdrh } 14617a18f2fSdrh} {t1i1 {2 2} t1i2 {2 1} t1i3 {2 2 1}} 147e6e04969Sdrhdo_test analyze-3.2 { 148e6e04969Sdrh execsql { 149e6e04969Sdrh INSERT INTO t1 VALUES(1,4); 150e6e04969Sdrh INSERT INTO t1 VALUES(1,5); 151e6e04969Sdrh ANALYZE t1; 152e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 153e6e04969Sdrh } 15417a18f2fSdrh} {t1i1 {4 4} t1i2 {4 1} t1i3 {4 4 1}} 155e6e04969Sdrhdo_test analyze-3.3 { 156e6e04969Sdrh execsql { 157e6e04969Sdrh INSERT INTO t1 VALUES(2,5); 158e6e04969Sdrh ANALYZE main; 159e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 160e6e04969Sdrh } 16117a18f2fSdrh} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1}} 162e6e04969Sdrhdo_test analyze-3.4 { 163e6e04969Sdrh execsql { 164e6e04969Sdrh CREATE TABLE t2 AS SELECT * FROM t1; 165e6e04969Sdrh CREATE INDEX t2i1 ON t2(a); 166e6e04969Sdrh CREATE INDEX t2i2 ON t2(b); 167e6e04969Sdrh CREATE INDEX t2i3 ON t2(a,b); 168e6e04969Sdrh ANALYZE; 169e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 170e6e04969Sdrh } 17117a18f2fSdrh} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2} t2i3 {5 3 1}} 172e6e04969Sdrhdo_test analyze-3.5 { 173e6e04969Sdrh execsql { 174e6e04969Sdrh DROP INDEX t2i3; 175e6e04969Sdrh ANALYZE t1; 176e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 177e6e04969Sdrh } 178006015d8Sdanielk1977} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2}} 179e6e04969Sdrhdo_test analyze-3.6 { 180e6e04969Sdrh execsql { 181e6e04969Sdrh ANALYZE t2; 182e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 183e6e04969Sdrh } 18417a18f2fSdrh} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2}} 185e6e04969Sdrhdo_test analyze-3.7 { 186e6e04969Sdrh execsql { 187e6e04969Sdrh DROP INDEX t2i2; 188e6e04969Sdrh ANALYZE t2; 189e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 190e6e04969Sdrh } 1910c35667bSdrh} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3}} 192e6e04969Sdrhdo_test analyze-3.8 { 193e6e04969Sdrh execsql { 194e6e04969Sdrh CREATE TABLE t3 AS SELECT a, b, rowid AS c, 'hi' AS d FROM t1; 195e6e04969Sdrh CREATE INDEX t3i1 ON t3(a); 196e6e04969Sdrh CREATE INDEX t3i2 ON t3(a,b,c,d); 197e6e04969Sdrh CREATE INDEX t3i3 ON t3(d,b,c,a); 198e6e04969Sdrh DROP TABLE t1; 199e6e04969Sdrh DROP TABLE t2; 200006015d8Sdanielk1977 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 201006015d8Sdanielk1977 } 202006015d8Sdanielk1977} {} 203006015d8Sdanielk1977do_test analyze-3.9 { 204006015d8Sdanielk1977 execsql { 205e6e04969Sdrh ANALYZE; 206e6e04969Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 207e6e04969Sdrh } 20817a18f2fSdrh} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}} 209e6e04969Sdrh 210006015d8Sdanielk1977do_test analyze-3.10 { 211006015d8Sdanielk1977 execsql { 212006015d8Sdanielk1977 CREATE TABLE [silly " name](a, b, c); 213006015d8Sdanielk1977 CREATE INDEX 'foolish '' name' ON [silly " name](a, b); 214006015d8Sdanielk1977 CREATE INDEX 'another foolish '' name' ON [silly " name](c); 215006015d8Sdanielk1977 INSERT INTO [silly " name] VALUES(1, 2, 3); 216006015d8Sdanielk1977 INSERT INTO [silly " name] VALUES(4, 5, 6); 217006015d8Sdanielk1977 ANALYZE; 218006015d8Sdanielk1977 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 219006015d8Sdanielk1977 } 220006015d8Sdanielk1977} {{another foolish ' name} {2 1} {foolish ' name} {2 1 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}} 221006015d8Sdanielk1977do_test analyze-3.11 { 222006015d8Sdanielk1977 execsql { 223006015d8Sdanielk1977 DROP INDEX "foolish ' name"; 224006015d8Sdanielk1977 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 225006015d8Sdanielk1977 } 226006015d8Sdanielk1977} {{another foolish ' name} {2 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}} 227006015d8Sdanielk1977do_test analyze-3.11 { 228006015d8Sdanielk1977 execsql { 229006015d8Sdanielk1977 DROP TABLE "silly "" name"; 230006015d8Sdanielk1977 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 231006015d8Sdanielk1977 } 232006015d8Sdanielk1977} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}} 233006015d8Sdanielk1977 2348b3d990bSdrh# Try corrupting the sqlite_stat1 table and make sure the 2358b3d990bSdrh# database is still able to function. 2368b3d990bSdrh# 2378b3d990bSdrhdo_test analyze-4.0 { 2388b3d990bSdrh sqlite3 db2 test.db 2398b3d990bSdrh db2 eval { 2408b3d990bSdrh CREATE TABLE t4(x,y,z); 2418b3d990bSdrh CREATE INDEX t4i1 ON t4(x); 2428b3d990bSdrh CREATE INDEX t4i2 ON t4(y); 2438b3d990bSdrh INSERT INTO t4 SELECT a,b,c FROM t3; 2448b3d990bSdrh } 2458b3d990bSdrh db2 close 2468b3d990bSdrh db close 2478b3d990bSdrh sqlite3 db test.db 2488b3d990bSdrh execsql { 2498b3d990bSdrh ANALYZE; 2508b3d990bSdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 2518b3d990bSdrh } 2528b3d990bSdrh} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1} t4i1 {5 3} t4i2 {5 2}} 2538b3d990bSdrhdo_test analyze-4.1 { 2548b3d990bSdrh execsql { 2558b3d990bSdrh PRAGMA writable_schema=on; 2568b3d990bSdrh INSERT INTO sqlite_stat1 VALUES(null,null,null); 2578b3d990bSdrh PRAGMA writable_schema=off; 2588b3d990bSdrh } 2598b3d990bSdrh db close 2608b3d990bSdrh sqlite3 db test.db 2618b3d990bSdrh execsql { 2628b3d990bSdrh SELECT * FROM t4 WHERE x=1234; 2638b3d990bSdrh } 2648b3d990bSdrh} {} 2658b3d990bSdrhdo_test analyze-4.2 { 2668b3d990bSdrh execsql { 2678b3d990bSdrh PRAGMA writable_schema=on; 2688b3d990bSdrh DELETE FROM sqlite_stat1; 2698b3d990bSdrh INSERT INTO sqlite_stat1 VALUES('t4','t4i1','nonsense'); 2708b3d990bSdrh INSERT INTO sqlite_stat1 VALUES('t4','t4i2','120897349817238741092873198273409187234918720394817209384710928374109827172901827349871928741910'); 2718b3d990bSdrh PRAGMA writable_schema=off; 2728b3d990bSdrh } 2738b3d990bSdrh db close 2748b3d990bSdrh sqlite3 db test.db 2758b3d990bSdrh execsql { 2768b3d990bSdrh SELECT * FROM t4 WHERE x=1234; 2778b3d990bSdrh } 2788b3d990bSdrh} {} 2794cfb22f7Sdrhdo_test analyze-4.3 { 2804cfb22f7Sdrh execsql { 2814cfb22f7Sdrh INSERT INTO sqlite_stat1 VALUES('t4','xyzzy','0 1 2 3'); 2824cfb22f7Sdrh } 2834cfb22f7Sdrh db close 2844cfb22f7Sdrh sqlite3 db test.db 2854cfb22f7Sdrh execsql { 2864cfb22f7Sdrh SELECT * FROM t4 WHERE x=1234; 2874cfb22f7Sdrh } 2884cfb22f7Sdrh} {} 2898b3d990bSdrh 290a5ae4c33Sdrh# Verify that DROP TABLE and DROP INDEX remove entries from the 291*175b8f06Sdrh# sqlite_stat1 and sqlite_stat4 tables. 292a5ae4c33Sdrh# 293a5ae4c33Sdrhdo_test analyze-5.0 { 294a5ae4c33Sdrh execsql { 295a5ae4c33Sdrh DELETE FROM t3; 296a5ae4c33Sdrh DELETE FROM t4; 297a5ae4c33Sdrh INSERT INTO t3 VALUES(1,2,3,4); 298a5ae4c33Sdrh INSERT INTO t3 VALUES(5,6,7,8); 299a5ae4c33Sdrh INSERT INTO t3 SELECT a+8, b+8, c+8, d+8 FROM t3; 300a5ae4c33Sdrh INSERT INTO t3 SELECT a+16, b+16, c+16, d+16 FROM t3; 301a5ae4c33Sdrh INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3; 302a5ae4c33Sdrh INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3; 303a5ae4c33Sdrh INSERT INTO t4 SELECT a, b, c FROM t3; 304a5ae4c33Sdrh ANALYZE; 305a5ae4c33Sdrh SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; 306a5ae4c33Sdrh SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; 307a5ae4c33Sdrh } 308a5ae4c33Sdrh} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} 309*175b8f06Sdrhifcapable stat4 { 310a5ae4c33Sdrh do_test analyze-5.1 { 311*175b8f06Sdrh execsql { 312*175b8f06Sdrh SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; 313*175b8f06Sdrh SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; 314*175b8f06Sdrh } 315a5ae4c33Sdrh } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} 316a5ae4c33Sdrh} 317a5ae4c33Sdrhdo_test analyze-5.2 { 318a5ae4c33Sdrh execsql { 319a5ae4c33Sdrh DROP INDEX t3i2; 320a5ae4c33Sdrh SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; 321a5ae4c33Sdrh SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; 322a5ae4c33Sdrh } 323a5ae4c33Sdrh} {t3i1 t3i3 t4i1 t4i2 t3 t4} 324*175b8f06Sdrhifcapable stat4 { 325a5ae4c33Sdrh do_test analyze-5.3 { 326*175b8f06Sdrh execsql { 327*175b8f06Sdrh SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; 328*175b8f06Sdrh SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; 329*175b8f06Sdrh } 330a5ae4c33Sdrh } {t3i1 t3i3 t4i1 t4i2 t3 t4} 331a5ae4c33Sdrh} 332a5ae4c33Sdrhdo_test analyze-5.4 { 333a5ae4c33Sdrh execsql { 334a5ae4c33Sdrh DROP TABLE t3; 335a5ae4c33Sdrh SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; 336a5ae4c33Sdrh SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; 337a5ae4c33Sdrh } 338a5ae4c33Sdrh} {t4i1 t4i2 t4} 339*175b8f06Sdrhifcapable stat4 { 340a5ae4c33Sdrh do_test analyze-5.5 { 341*175b8f06Sdrh execsql { 342*175b8f06Sdrh SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; 343*175b8f06Sdrh SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; 344*175b8f06Sdrh } 345a5ae4c33Sdrh } {t4i1 t4i2 t4} 346a5ae4c33Sdrh} 347a5ae4c33Sdrh 3488b3d990bSdrh# This test corrupts the database file so it must be the last test 3498b3d990bSdrh# in the series. 3508b3d990bSdrh# 351cedfecf9Sdrhdo_test analyze-5.99 { 3526ab91a7aSdrh sqlite3_db_config db DEFENSIVE 0 3538b3d990bSdrh execsql { 3548b3d990bSdrh PRAGMA writable_schema=on; 355c456e57aSdrh UPDATE sqlite_master SET sql='nonsense' WHERE name='sqlite_stat1'; 3568b3d990bSdrh } 3578b3d990bSdrh db close 358cb354603Sdan catch { sqlite3 db test.db } 3598b3d990bSdrh catchsql { 3608b3d990bSdrh ANALYZE 3618b3d990bSdrh } 36222ecef5cSdrh} {1 {malformed database schema (sqlite_stat1)}} 3638b3d990bSdrh 364cedfecf9Sdrh# Verify that tables whose names begin with "sqlite" but not 365cedfecf9Sdrh# "sqlite_" are analyzed. 366cedfecf9Sdrh# 367cedfecf9Sdrhdb close 368cedfecf9Sdrhsqlite3 db :memory: 369cedfecf9Sdrhdo_execsql_test analyze-6.1 { 370cedfecf9Sdrh CREATE TABLE sqliteDemo(a); 371cedfecf9Sdrh INSERT INTO sqliteDemo(a) VALUES(1),(2),(3),(4),(5); 372cedfecf9Sdrh CREATE TABLE SQLiteDemo2(a INTEGER PRIMARY KEY AUTOINCREMENT); 373cedfecf9Sdrh INSERT INTO SQLiteDemo2 SELECT * FROM sqliteDemo; 374cedfecf9Sdrh CREATE TABLE t1(b); 375cedfecf9Sdrh INSERT INTO t1(b) SELECT a FROM sqliteDemo; 376cedfecf9Sdrh ANALYZE; 377cedfecf9Sdrh SELECT tbl FROM sqlite_stat1 WHERE idx IS NULL ORDER BY tbl; 378cedfecf9Sdrh} {SQLiteDemo2 sqliteDemo t1} 379cedfecf9Sdrh 380e6e04969Sdrhfinish_test 381