xref: /sqlite-3.40.0/test/analyze.test (revision 175b8f06)
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