analyze9.test 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. # 2013 August 3
  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. #
  12. # This file contains automated tests used to verify that the sqlite_stat4
  13. # functionality is working.
  14. #
  15. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. set testprefix analyze9
  18. ifcapable !stat4 {
  19. finish_test
  20. return
  21. }
  22. proc s {blob} {
  23. set ret ""
  24. binary scan $blob c* bytes
  25. foreach b $bytes {
  26. set t [binary format c $b]
  27. if {[string is print $t]} {
  28. append ret $t
  29. } else {
  30. append ret .
  31. }
  32. }
  33. return $ret
  34. }
  35. db function s s
  36. do_execsql_test 1.0 {
  37. CREATE TABLE t1(a TEXT, b TEXT);
  38. INSERT INTO t1 VALUES('(0)', '(0)');
  39. INSERT INTO t1 VALUES('(1)', '(1)');
  40. INSERT INTO t1 VALUES('(2)', '(2)');
  41. INSERT INTO t1 VALUES('(3)', '(3)');
  42. INSERT INTO t1 VALUES('(4)', '(4)');
  43. CREATE INDEX i1 ON t1(a, b);
  44. } {}
  45. do_execsql_test 1.1 {
  46. ANALYZE;
  47. } {}
  48. do_execsql_test 1.2 {
  49. SELECT tbl,idx,nEq,nLt,nDLt,test_decode(sample) FROM sqlite_stat4;
  50. } {
  51. t1 i1 {1 1 1} {0 0 0} {0 0 0} {(0) (0) 1}
  52. t1 i1 {1 1 1} {1 1 1} {1 1 1} {(1) (1) 2}
  53. t1 i1 {1 1 1} {2 2 2} {2 2 2} {(2) (2) 3}
  54. t1 i1 {1 1 1} {3 3 3} {3 3 3} {(3) (3) 4}
  55. t1 i1 {1 1 1} {4 4 4} {4 4 4} {(4) (4) 5}
  56. }
  57. if {[permutation] != "utf16"} {
  58. do_execsql_test 1.3 {
  59. SELECT tbl,idx,nEq,nLt,nDLt,s(sample) FROM sqlite_stat4;
  60. } {
  61. t1 i1 {1 1 1} {0 0 0} {0 0 0} ....(0)(0)
  62. t1 i1 {1 1 1} {1 1 1} {1 1 1} ....(1)(1).
  63. t1 i1 {1 1 1} {2 2 2} {2 2 2} ....(2)(2).
  64. t1 i1 {1 1 1} {3 3 3} {3 3 3} ....(3)(3).
  65. t1 i1 {1 1 1} {4 4 4} {4 4 4} ....(4)(4).
  66. }
  67. }
  68. #-------------------------------------------------------------------------
  69. # This is really just to test SQL user function "test_decode".
  70. #
  71. reset_db
  72. do_execsql_test 2.1 {
  73. CREATE TABLE t1(a, b, c);
  74. INSERT INTO t1 VALUES('some text', 14, NULL);
  75. INSERT INTO t1 VALUES(22.0, NULL, x'656667');
  76. CREATE INDEX i1 ON t1(a, b, c);
  77. ANALYZE;
  78. SELECT test_decode(sample) FROM sqlite_stat4;
  79. } {
  80. {22.0 NULL x'656667' 2}
  81. {{some text} 14 NULL 1}
  82. }
  83. #-------------------------------------------------------------------------
  84. #
  85. reset_db
  86. do_execsql_test 3.1 {
  87. CREATE TABLE t2(a, b);
  88. CREATE INDEX i2 ON t2(a, b);
  89. BEGIN;
  90. }
  91. do_test 3.2 {
  92. for {set i 0} {$i < 1000} {incr i} {
  93. set a [expr $i / 10]
  94. set b [expr int(rand() * 15.0)]
  95. execsql { INSERT INTO t2 VALUES($a, $b) }
  96. }
  97. execsql COMMIT
  98. } {}
  99. db func lindex lindex
  100. # Each value of "a" occurs exactly 10 times in the table.
  101. #
  102. do_execsql_test 3.3.1 {
  103. SELECT count(*) FROM t2 GROUP BY a;
  104. } [lrange [string repeat "10 " 100] 0 99]
  105. # The first element in the "nEq" list of all samples should therefore be 10.
  106. #
  107. do_execsql_test 3.3.2 {
  108. ANALYZE;
  109. SELECT lindex(nEq, 0) FROM sqlite_stat4;
  110. } [lrange [string repeat "10 " 100] 0 23]
  111. #-------------------------------------------------------------------------
  112. #
  113. do_execsql_test 3.4 {
  114. DROP TABLE IF EXISTS t1;
  115. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  116. INSERT INTO t1 VALUES(1, 1, 'one-a');
  117. INSERT INTO t1 VALUES(11, 1, 'one-b');
  118. INSERT INTO t1 VALUES(21, 1, 'one-c');
  119. INSERT INTO t1 VALUES(31, 1, 'one-d');
  120. INSERT INTO t1 VALUES(41, 1, 'one-e');
  121. INSERT INTO t1 VALUES(51, 1, 'one-f');
  122. INSERT INTO t1 VALUES(61, 1, 'one-g');
  123. INSERT INTO t1 VALUES(71, 1, 'one-h');
  124. INSERT INTO t1 VALUES(81, 1, 'one-i');
  125. INSERT INTO t1 VALUES(91, 1, 'one-j');
  126. INSERT INTO t1 SELECT a+1,2,'two' || substr(c,4) FROM t1;
  127. INSERT INTO t1 SELECT a+2,3,'three'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  128. INSERT INTO t1 SELECT a+3,4,'four'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  129. INSERT INTO t1 SELECT a+4,5,'five'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  130. INSERT INTO t1 SELECT a+5,6,'six'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  131. CREATE INDEX t1b ON t1(b);
  132. ANALYZE;
  133. SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND 60;
  134. } {three-d three-e three-f}
  135. #-------------------------------------------------------------------------
  136. # These tests verify that the sample selection for stat4 appears to be
  137. # working as designed.
  138. #
  139. reset_db
  140. db func lindex lindex
  141. db func lrange lrange
  142. do_execsql_test 4.0 {
  143. DROP TABLE IF EXISTS t1;
  144. CREATE TABLE t1(a, b, c);
  145. CREATE INDEX i1 ON t1(c, b, a);
  146. }
  147. proc insert_filler_rows_n {iStart args} {
  148. set A(-ncopy) 1
  149. set A(-nval) 1
  150. foreach {k v} $args {
  151. if {[info exists A($k)]==0} { error "no such option: $k" }
  152. set A($k) $v
  153. }
  154. if {[llength $args] % 2} {
  155. error "option requires an argument: [lindex $args end]"
  156. }
  157. for {set i 0} {$i < $A(-nval)} {incr i} {
  158. set iVal [expr $iStart+$i]
  159. for {set j 0} {$j < $A(-ncopy)} {incr j} {
  160. execsql { INSERT INTO t1 VALUES($iVal, $iVal, $iVal) }
  161. }
  162. }
  163. }
  164. do_test 4.1 {
  165. execsql { BEGIN }
  166. insert_filler_rows_n 0 -ncopy 10 -nval 19
  167. insert_filler_rows_n 20 -ncopy 1 -nval 100
  168. execsql {
  169. INSERT INTO t1(c, b, a) VALUES(200, 1, 'a');
  170. INSERT INTO t1(c, b, a) VALUES(200, 1, 'b');
  171. INSERT INTO t1(c, b, a) VALUES(200, 1, 'c');
  172. INSERT INTO t1(c, b, a) VALUES(200, 2, 'e');
  173. INSERT INTO t1(c, b, a) VALUES(200, 2, 'f');
  174. INSERT INTO t1(c, b, a) VALUES(201, 3, 'g');
  175. INSERT INTO t1(c, b, a) VALUES(201, 4, 'h');
  176. ANALYZE;
  177. SELECT count(*) FROM sqlite_stat4;
  178. SELECT count(*) FROM t1;
  179. }
  180. } {24 297}
  181. do_execsql_test 4.2 {
  182. SELECT
  183. neq,
  184. lrange(nlt, 0, 2),
  185. lrange(ndlt, 0, 2),
  186. lrange(test_decode(sample), 0, 2)
  187. FROM sqlite_stat4
  188. ORDER BY rowid LIMIT 16;
  189. } {
  190. {10 10 10 1} {0 0 0} {0 0 0} {0 0 0}
  191. {10 10 10 1} {10 10 10} {1 1 1} {1 1 1}
  192. {10 10 10 1} {20 20 20} {2 2 2} {2 2 2}
  193. {10 10 10 1} {30 30 30} {3 3 3} {3 3 3}
  194. {10 10 10 1} {40 40 40} {4 4 4} {4 4 4}
  195. {10 10 10 1} {50 50 50} {5 5 5} {5 5 5}
  196. {10 10 10 1} {60 60 60} {6 6 6} {6 6 6}
  197. {10 10 10 1} {70 70 70} {7 7 7} {7 7 7}
  198. {10 10 10 1} {80 80 80} {8 8 8} {8 8 8}
  199. {10 10 10 1} {90 90 90} {9 9 9} {9 9 9}
  200. {10 10 10 1} {100 100 100} {10 10 10} {10 10 10}
  201. {10 10 10 1} {110 110 110} {11 11 11} {11 11 11}
  202. {10 10 10 1} {120 120 120} {12 12 12} {12 12 12}
  203. {10 10 10 1} {130 130 130} {13 13 13} {13 13 13}
  204. {10 10 10 1} {140 140 140} {14 14 14} {14 14 14}
  205. {10 10 10 1} {150 150 150} {15 15 15} {15 15 15}
  206. }
  207. do_execsql_test 4.3 {
  208. SELECT
  209. neq,
  210. lrange(nlt, 0, 2),
  211. lrange(ndlt, 0, 2),
  212. lrange(test_decode(sample), 0, 1)
  213. FROM sqlite_stat4
  214. ORDER BY rowid DESC LIMIT 2;
  215. } {
  216. {2 1 1 1} {295 296 296} {120 122 125} {201 4}
  217. {5 3 1 1} {290 290 290} {119 119 119} {200 1}
  218. }
  219. do_execsql_test 4.4 { SELECT count(DISTINCT c) FROM t1 WHERE c<201 } 120
  220. do_execsql_test 4.5 { SELECT count(DISTINCT c) FROM t1 WHERE c<200 } 119
  221. # Check that the perioidic samples are present.
  222. do_execsql_test 4.6 {
  223. SELECT count(*) FROM sqlite_stat4
  224. WHERE lindex(test_decode(sample), 3) IN
  225. ('34', '68', '102', '136', '170', '204', '238', '272')
  226. } {8}
  227. reset_db
  228. do_test 4.7 {
  229. execsql {
  230. BEGIN;
  231. CREATE TABLE t1(o,t INTEGER PRIMARY KEY);
  232. CREATE INDEX i1 ON t1(o);
  233. }
  234. for {set i 0} {$i<10000} {incr i [expr (($i<1000)?1:10)]} {
  235. execsql { INSERT INTO t1 VALUES('x', $i) }
  236. }
  237. execsql {
  238. COMMIT;
  239. ANALYZE;
  240. SELECT count(*) FROM sqlite_stat4;
  241. }
  242. } {8}
  243. do_execsql_test 4.8 {
  244. SELECT test_decode(sample) FROM sqlite_stat4;
  245. } {
  246. {x 211} {x 423} {x 635} {x 847}
  247. {x 1590} {x 3710} {x 5830} {x 7950}
  248. }
  249. #-------------------------------------------------------------------------
  250. # The following would cause a crash at one point.
  251. #
  252. reset_db
  253. do_execsql_test 5.1 {
  254. PRAGMA encoding = 'utf-16';
  255. CREATE TABLE t0(v);
  256. ANALYZE;
  257. }
  258. #-------------------------------------------------------------------------
  259. # This was also crashing (corrupt sqlite_stat4 table).
  260. #
  261. reset_db
  262. do_execsql_test 6.1 {
  263. CREATE TABLE t1(a, b);
  264. CREATE INDEX i1 ON t1(a);
  265. CREATE INDEX i2 ON t1(b);
  266. INSERT INTO t1 VALUES(1, 1);
  267. INSERT INTO t1 VALUES(2, 2);
  268. INSERT INTO t1 VALUES(3, 3);
  269. INSERT INTO t1 VALUES(4, 4);
  270. INSERT INTO t1 VALUES(5, 5);
  271. ANALYZE;
  272. PRAGMA writable_schema = 1;
  273. CREATE TEMP TABLE x1 AS
  274. SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat4
  275. ORDER BY (rowid%5), rowid;
  276. DELETE FROM sqlite_stat4;
  277. INSERT INTO sqlite_stat4 SELECT * FROM x1;
  278. PRAGMA writable_schema = 0;
  279. ANALYZE sqlite_master;
  280. }
  281. do_execsql_test 6.2 {
  282. SELECT * FROM t1 WHERE a = 'abc';
  283. }
  284. #-------------------------------------------------------------------------
  285. # The following tests experiment with adding corrupted records to the
  286. # 'sample' column of the sqlite_stat4 table.
  287. #
  288. reset_db
  289. sqlite3_db_config_lookaside db 0 0 0
  290. do_execsql_test 7.1 {
  291. CREATE TABLE t1(a, b);
  292. CREATE INDEX i1 ON t1(a, b);
  293. INSERT INTO t1 VALUES(1, 1);
  294. INSERT INTO t1 VALUES(2, 2);
  295. INSERT INTO t1 VALUES(3, 3);
  296. INSERT INTO t1 VALUES(4, 4);
  297. INSERT INTO t1 VALUES(5, 5);
  298. ANALYZE;
  299. UPDATE sqlite_stat4 SET sample = X'' WHERE rowid = 1;
  300. ANALYZE sqlite_master;
  301. }
  302. do_execsql_test 7.2 {
  303. UPDATE sqlite_stat4 SET sample = X'FFFF';
  304. ANALYZE sqlite_master;
  305. SELECT * FROM t1 WHERE a = 1;
  306. } {1 1}
  307. do_execsql_test 7.3 {
  308. ANALYZE;
  309. UPDATE sqlite_stat4 SET neq = '0 0 0';
  310. ANALYZE sqlite_master;
  311. SELECT * FROM t1 WHERE a = 1;
  312. } {1 1}
  313. do_execsql_test 7.4 {
  314. ANALYZE;
  315. UPDATE sqlite_stat4 SET ndlt = '0 0 0';
  316. ANALYZE sqlite_master;
  317. SELECT * FROM t1 WHERE a = 3;
  318. } {3 3}
  319. do_execsql_test 7.5 {
  320. ANALYZE;
  321. UPDATE sqlite_stat4 SET nlt = '0 0 0';
  322. ANALYZE sqlite_master;
  323. SELECT * FROM t1 WHERE a = 5;
  324. } {5 5}
  325. #-------------------------------------------------------------------------
  326. #
  327. reset_db
  328. do_execsql_test 8.1 {
  329. CREATE TABLE t1(x TEXT);
  330. CREATE INDEX i1 ON t1(x);
  331. INSERT INTO t1 VALUES('1');
  332. INSERT INTO t1 VALUES('2');
  333. INSERT INTO t1 VALUES('3');
  334. INSERT INTO t1 VALUES('4');
  335. ANALYZE;
  336. }
  337. do_execsql_test 8.2 {
  338. SELECT * FROM t1 WHERE x = 3;
  339. } {3}
  340. #-------------------------------------------------------------------------
  341. # Check that the bug fixed by [91733bc485] really is fixed.
  342. #
  343. reset_db
  344. do_execsql_test 9.1 {
  345. CREATE TABLE t1(a, b, c, d, e);
  346. CREATE INDEX i1 ON t1(a, b, c, d);
  347. CREATE INDEX i2 ON t1(e);
  348. }
  349. do_test 9.2 {
  350. execsql BEGIN;
  351. for {set i 0} {$i < 100} {incr i} {
  352. execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  353. }
  354. for {set i 0} {$i < 20} {incr i} {
  355. execsql "INSERT INTO t1 VALUES('x', 'y', 'z', 101, $i)"
  356. }
  357. for {set i 102} {$i < 200} {incr i} {
  358. execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  359. }
  360. execsql COMMIT
  361. execsql ANALYZE
  362. } {}
  363. do_eqp_test 9.3.1 {
  364. SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=101 AND e=5;
  365. } {/t1 USING INDEX i2/}
  366. do_eqp_test 9.3.2 {
  367. SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=99 AND e=5;
  368. } {/t1 USING INDEX i1/}
  369. set value_d [expr 101]
  370. do_eqp_test 9.4.1 {
  371. SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5
  372. } {/t1 USING INDEX i2/}
  373. set value_d [expr 99]
  374. do_eqp_test 9.4.2 {
  375. SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5
  376. } {/t1 USING INDEX i1/}
  377. #-------------------------------------------------------------------------
  378. # Check that the planner takes stat4 data into account when considering
  379. # "IS NULL" and "IS NOT NULL" constraints.
  380. #
  381. do_execsql_test 10.1.1 {
  382. DROP TABLE IF EXISTS t3;
  383. CREATE TABLE t3(a, b);
  384. CREATE INDEX t3a ON t3(a);
  385. CREATE INDEX t3b ON t3(b);
  386. }
  387. do_test 10.1.2 {
  388. for {set i 1} {$i < 100} {incr i} {
  389. if {$i>90} { set a $i } else { set a NULL }
  390. set b [expr $i % 5]
  391. execsql "INSERT INTO t3 VALUES($a, $b)"
  392. }
  393. execsql ANALYZE
  394. } {}
  395. do_eqp_test 10.1.3 {
  396. SELECT * FROM t3 WHERE a IS NULL AND b = 2
  397. } {/t3 USING INDEX t3b/}
  398. do_eqp_test 10.1.4 {
  399. SELECT * FROM t3 WHERE a IS NOT NULL AND b = 2
  400. } {/t3 USING INDEX t3a/}
  401. do_execsql_test 10.2.1 {
  402. DROP TABLE IF EXISTS t3;
  403. CREATE TABLE t3(x, a, b);
  404. CREATE INDEX t3a ON t3(x, a);
  405. CREATE INDEX t3b ON t3(x, b);
  406. }
  407. do_test 10.2.2 {
  408. for {set i 1} {$i < 100} {incr i} {
  409. if {$i>90} { set a $i } else { set a NULL }
  410. set b [expr $i % 5]
  411. execsql "INSERT INTO t3 VALUES('xyz', $a, $b)"
  412. }
  413. execsql ANALYZE
  414. } {}
  415. do_eqp_test 10.2.3 {
  416. SELECT * FROM t3 WHERE x = 'xyz' AND a IS NULL AND b = 2
  417. } {/t3 USING INDEX t3b/}
  418. do_eqp_test 10.2.4 {
  419. SELECT * FROM t3 WHERE x = 'xyz' AND a IS NOT NULL AND b = 2
  420. } {/t3 USING INDEX t3a/}
  421. #-------------------------------------------------------------------------
  422. # Check that stat4 data is used correctly with non-default collation
  423. # sequences.
  424. #
  425. foreach {tn schema} {
  426. 1 {
  427. CREATE TABLE t4(a COLLATE nocase, b);
  428. CREATE INDEX t4a ON t4(a);
  429. CREATE INDEX t4b ON t4(b);
  430. }
  431. 2 {
  432. CREATE TABLE t4(a, b);
  433. CREATE INDEX t4a ON t4(a COLLATE nocase);
  434. CREATE INDEX t4b ON t4(b);
  435. }
  436. } {
  437. drop_all_tables
  438. do_test 11.$tn.1 { execsql $schema } {}
  439. do_test 11.$tn.2 {
  440. for {set i 0} {$i < 100} {incr i} {
  441. if { ($i % 10)==0 } { set a ABC } else { set a DEF }
  442. set b [expr $i % 5]
  443. execsql { INSERT INTO t4 VALUES($a, $b) }
  444. }
  445. execsql ANALYZE
  446. } {}
  447. do_eqp_test 11.$tn.3 {
  448. SELECT * FROM t4 WHERE a = 'def' AND b = 3;
  449. } {/t4 USING INDEX t4b/}
  450. if {$tn==1} {
  451. set sql "SELECT * FROM t4 WHERE a = 'abc' AND b = 3;"
  452. do_eqp_test 11.$tn.4 $sql {/t4 USING INDEX t4a/}
  453. } else {
  454. set sql "SELECT * FROM t4 WHERE a = 'abc' COLLATE nocase AND b = 3;"
  455. do_eqp_test 11.$tn.5 $sql {/t4 USING INDEX t4a/}
  456. set sql "SELECT * FROM t4 WHERE a COLLATE nocase = 'abc' AND b = 3;"
  457. do_eqp_test 11.$tn.6 $sql {/t4 USING INDEX t4a/}
  458. }
  459. }
  460. foreach {tn schema} {
  461. 1 {
  462. CREATE TABLE t4(x, a COLLATE nocase, b);
  463. CREATE INDEX t4a ON t4(x, a);
  464. CREATE INDEX t4b ON t4(x, b);
  465. }
  466. 2 {
  467. CREATE TABLE t4(x, a, b);
  468. CREATE INDEX t4a ON t4(x, a COLLATE nocase);
  469. CREATE INDEX t4b ON t4(x, b);
  470. }
  471. } {
  472. drop_all_tables
  473. do_test 12.$tn.1 { execsql $schema } {}
  474. do_test 12.$tn.2 {
  475. for {set i 0} {$i < 100} {incr i} {
  476. if { ($i % 10)==0 } { set a ABC } else { set a DEF }
  477. set b [expr $i % 5]
  478. execsql { INSERT INTO t4 VALUES(X'abcdef', $a, $b) }
  479. }
  480. execsql ANALYZE
  481. } {}
  482. do_eqp_test 12.$tn.3 {
  483. SELECT * FROM t4 WHERE x=X'abcdef' AND a = 'def' AND b = 3;
  484. } {/t4 USING INDEX t4b/}
  485. if {$tn==1} {
  486. set sql "SELECT * FROM t4 WHERE x=X'abcdef' AND a = 'abc' AND b = 3;"
  487. do_eqp_test 12.$tn.4 $sql {/t4 USING INDEX t4a/}
  488. } else {
  489. set sql {
  490. SELECT * FROM t4 WHERE x=X'abcdef' AND a = 'abc' COLLATE nocase AND b = 3
  491. }
  492. do_eqp_test 12.$tn.5 $sql {/t4 USING INDEX t4a/}
  493. set sql {
  494. SELECT * FROM t4 WHERE x=X'abcdef' AND a COLLATE nocase = 'abc' AND b = 3
  495. }
  496. do_eqp_test 12.$tn.6 $sql {/t4 USING INDEX t4a/}
  497. }
  498. }
  499. #-------------------------------------------------------------------------
  500. # Check that affinities are taken into account when using stat4 data to
  501. # estimate the number of rows scanned by a rowid constraint.
  502. #
  503. drop_all_tables
  504. do_test 13.1 {
  505. execsql {
  506. CREATE TABLE t1(a, b, c);
  507. CREATE INDEX i1 ON t1(a);
  508. CREATE INDEX i2 ON t1(b, c);
  509. }
  510. for {set i 0} {$i<100} {incr i} {
  511. if {$i %2} {set a abc} else {set a def}
  512. execsql { INSERT INTO t1(rowid, a, b, c) VALUES($i, $a, $i, $i) }
  513. }
  514. execsql ANALYZE
  515. } {}
  516. do_eqp_test 13.2.1 {
  517. SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<20
  518. } {/SEARCH TABLE t1 USING INDEX i1/}
  519. do_eqp_test 13.2.2 {
  520. SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<20
  521. } {/SEARCH TABLE t1 USING INDEX i1/}
  522. do_eqp_test 13.3.1 {
  523. SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<20
  524. } {/SEARCH TABLE t1 USING INDEX i2/}
  525. do_eqp_test 13.3.2 {
  526. SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<20
  527. } {/SEARCH TABLE t1 USING INDEX i2/}
  528. #-------------------------------------------------------------------------
  529. # Check also that affinities are taken into account when using stat4 data
  530. # to estimate the number of rows scanned by any other constraint on a
  531. # column other than the leftmost.
  532. #
  533. drop_all_tables
  534. do_test 14.1 {
  535. execsql { CREATE TABLE t1(a, b INTEGER, c) }
  536. for {set i 0} {$i<100} {incr i} {
  537. set c [expr $i % 3]
  538. execsql { INSERT INTO t1 VALUES('ott', $i, $c) }
  539. }
  540. execsql {
  541. CREATE INDEX i1 ON t1(a, b);
  542. CREATE INDEX i2 ON t1(c);
  543. ANALYZE;
  544. }
  545. } {}
  546. do_eqp_test 13.2.1 {
  547. SELECT * FROM t1 WHERE a='ott' AND b<10 AND c=1
  548. } {/SEARCH TABLE t1 USING INDEX i1/}
  549. do_eqp_test 13.2.2 {
  550. SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
  551. } {/SEARCH TABLE t1 USING INDEX i1/}
  552. #-------------------------------------------------------------------------
  553. # By default, 16 non-periodic samples are collected for the stat4 table.
  554. # The following tests attempt to verify that the most common keys are
  555. # being collected.
  556. #
  557. proc check_stat4 {tn} {
  558. db eval ANALYZE
  559. db eval {SELECT a, b, c, d FROM t1} {
  560. incr k($a)
  561. incr k([list $a $b])
  562. incr k([list $a $b $c])
  563. if { [info exists k([list $a $b $c $d])]==0 } { incr nRow }
  564. incr k([list $a $b $c $d])
  565. }
  566. set L [list]
  567. foreach key [array names k] {
  568. lappend L [list $k($key) $key]
  569. }
  570. set nSample $nRow
  571. if {$nSample>16} {set nSample 16}
  572. set nThreshold [lindex [lsort -decr -integer -index 0 $L] [expr $nSample-1] 0]
  573. foreach key [array names k] {
  574. if {$k($key)>$nThreshold} {
  575. set expect($key) 1
  576. }
  577. if {$k($key)==$nThreshold} {
  578. set possible($key) 1
  579. }
  580. }
  581. set nPossible [expr $nSample - [llength [array names expect]]]
  582. #puts "EXPECT: [array names expect]"
  583. #puts "POSSIBLE($nPossible/[array size possible]): [array names possible]"
  584. #puts "HAVE: [db eval {SELECT test_decode(sample) FROM sqlite_stat4 WHERE idx='i1'}]"
  585. db eval {SELECT test_decode(sample) AS s FROM sqlite_stat4 WHERE idx='i1'} {
  586. set seen 0
  587. for {set i 0} {$i<4} {incr i} {
  588. unset -nocomplain expect([lrange $s 0 $i])
  589. if {[info exists possible([lrange $s 0 $i])]} {
  590. set seen 1
  591. unset -nocomplain possible([lrange $s 0 $i])
  592. }
  593. }
  594. if {$seen} {incr nPossible -1}
  595. }
  596. if {$nPossible<0} {set nPossible 0}
  597. set res [list [llength [array names expect]] $nPossible]
  598. uplevel [list do_test $tn [list set {} $res] {0 0}]
  599. }
  600. drop_all_tables
  601. do_test 14.1.1 {
  602. execsql {
  603. CREATE TABLE t1(a,b,c,d);
  604. CREATE INDEX i1 ON t1(a,b,c,d);
  605. }
  606. for {set i 0} {$i < 160} {incr i} {
  607. execsql { INSERT INTO t1 VALUES($i,$i,$i,$i) }
  608. if {($i % 10)==0} { execsql { INSERT INTO t1 VALUES($i,$i,$i,$i) } }
  609. }
  610. } {}
  611. check_stat4 14.1.2
  612. do_test 14.2.1 {
  613. execsql { DELETE FROM t1 }
  614. for {set i 0} {$i < 1600} {incr i} {
  615. execsql { INSERT INTO t1 VALUES($i/10,$i/17,$i/27,$i/37) }
  616. }
  617. } {}
  618. check_stat4 14.2.2
  619. do_test 14.3.1 {
  620. for {set i 0} {$i < 10} {incr i} {
  621. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  622. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  623. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  624. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  625. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  626. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  627. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  628. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  629. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  630. execsql { INSERT INTO t1 VALUES($i*50,$i*50,$i*50,$i*50) }
  631. }
  632. } {}
  633. check_stat4 14.3.2
  634. do_test 14.4.1 {
  635. execsql {DELETE FROM t1}
  636. for {set i 1} {$i < 160} {incr i} {
  637. set b [expr $i % 10]
  638. if {$b==0 || $b==2} {set b 1}
  639. execsql { INSERT INTO t1 VALUES($i/10,$b,$i,$i) }
  640. }
  641. } {}
  642. check_stat4 14.4.2
  643. db func lrange lrange
  644. db func lindex lindex
  645. do_execsql_test 14.4.3 {
  646. SELECT lrange(test_decode(sample), 0, 1) AS s FROM sqlite_stat4
  647. WHERE lindex(s, 1)=='1' ORDER BY rowid
  648. } {
  649. {0 1} {1 1} {2 1} {3 1}
  650. {4 1} {5 1} {6 1} {7 1}
  651. {8 1} {9 1} {10 1} {11 1}
  652. {12 1} {13 1} {14 1} {15 1}
  653. }
  654. #-------------------------------------------------------------------------
  655. # Test that nothing untoward happens if the stat4 table contains entries
  656. # for indexes that do not exist. Or NULL values in the idx column.
  657. # Or NULL values in any of the other columns.
  658. #
  659. drop_all_tables
  660. do_execsql_test 15.1 {
  661. CREATE TABLE x1(a, b, UNIQUE(a, b));
  662. INSERT INTO x1 VALUES(1, 2);
  663. INSERT INTO x1 VALUES(3, 4);
  664. INSERT INTO x1 VALUES(5, 6);
  665. ANALYZE;
  666. INSERT INTO sqlite_stat4 VALUES(NULL, NULL, NULL, NULL, NULL, NULL);
  667. }
  668. db close
  669. sqlite3 db test.db
  670. do_execsql_test 15.2 { SELECT * FROM x1 } {1 2 3 4 5 6}
  671. do_execsql_test 15.3 {
  672. INSERT INTO sqlite_stat4 VALUES(42, 42, 42, 42, 42, 42);
  673. }
  674. db close
  675. sqlite3 db test.db
  676. do_execsql_test 15.4 { SELECT * FROM x1 } {1 2 3 4 5 6}
  677. do_execsql_test 15.5 {
  678. UPDATE sqlite_stat1 SET stat = NULL;
  679. }
  680. db close
  681. sqlite3 db test.db
  682. do_execsql_test 15.6 { SELECT * FROM x1 } {1 2 3 4 5 6}
  683. do_execsql_test 15.7 {
  684. ANALYZE;
  685. UPDATE sqlite_stat1 SET tbl = 'no such tbl';
  686. }
  687. db close
  688. sqlite3 db test.db
  689. do_execsql_test 15.8 { SELECT * FROM x1 } {1 2 3 4 5 6}
  690. do_execsql_test 15.9 {
  691. ANALYZE;
  692. UPDATE sqlite_stat4 SET neq = NULL, nlt=NULL, ndlt=NULL;
  693. }
  694. db close
  695. sqlite3 db test.db
  696. do_execsql_test 15.10 { SELECT * FROM x1 } {1 2 3 4 5 6}
  697. # This is just for coverage....
  698. do_execsql_test 15.11 {
  699. ANALYZE;
  700. UPDATE sqlite_stat1 SET stat = stat || ' unordered';
  701. }
  702. db close
  703. sqlite3 db test.db
  704. do_execsql_test 15.12 { SELECT * FROM x1 } {1 2 3 4 5 6}
  705. #-------------------------------------------------------------------------
  706. # Test that allocations used for sqlite_stat4 samples are included in
  707. # the quantity returned by SQLITE_DBSTATUS_SCHEMA_USED.
  708. #
  709. set one [string repeat x 1000]
  710. set two [string repeat x 2000]
  711. do_test 16.1 {
  712. reset_db
  713. execsql {
  714. CREATE TABLE t1(a, UNIQUE(a));
  715. INSERT INTO t1 VALUES($one);
  716. ANALYZE;
  717. }
  718. set nByte [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
  719. reset_db
  720. execsql {
  721. CREATE TABLE t1(a, UNIQUE(a));
  722. INSERT INTO t1 VALUES($two);
  723. ANALYZE;
  724. }
  725. set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
  726. expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1050}
  727. } {1}
  728. #-------------------------------------------------------------------------
  729. # Test that stat4 data may be used with partial indexes.
  730. #
  731. do_test 17.1 {
  732. reset_db
  733. execsql {
  734. CREATE TABLE t1(a, b, c, d);
  735. CREATE INDEX i1 ON t1(a, b) WHERE d IS NOT NULL;
  736. INSERT INTO t1 VALUES(-1, -1, -1, NULL);
  737. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  738. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  739. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  740. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  741. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  742. INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  743. }
  744. for {set i 0} {$i < 32} {incr i} {
  745. if {$i<8} {set b 0} else { set b $i }
  746. execsql { INSERT INTO t1 VALUES($i%2, $b, $i/2, 'abc') }
  747. }
  748. execsql {ANALYZE main.t1}
  749. } {}
  750. do_catchsql_test 17.1.2 {
  751. ANALYZE temp.t1;
  752. } {1 {no such table: temp.t1}}
  753. do_eqp_test 17.2 {
  754. SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=10 AND c=10;
  755. } {/USING INDEX i1/}
  756. do_eqp_test 17.3 {
  757. SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=0 AND c=10;
  758. } {/USING INDEX i1/}
  759. do_execsql_test 17.4 {
  760. CREATE INDEX i2 ON t1(c, d);
  761. ANALYZE main.i2;
  762. }
  763. do_eqp_test 17.5 {
  764. SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=10 AND c=10;
  765. } {/USING INDEX i1/}
  766. do_eqp_test 17.6 {
  767. SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=0 AND c=10;
  768. } {/USING INDEX i2/}
  769. #-------------------------------------------------------------------------
  770. #
  771. do_test 18.1 {
  772. reset_db
  773. execsql {
  774. CREATE TABLE t1(a, b);
  775. CREATE INDEX i1 ON t1(a, b);
  776. }
  777. for {set i 0} {$i < 9} {incr i} {
  778. execsql {
  779. INSERT INTO t1 VALUES($i, 0);
  780. INSERT INTO t1 VALUES($i, 0);
  781. INSERT INTO t1 VALUES($i, 0);
  782. INSERT INTO t1 VALUES($i, 0);
  783. INSERT INTO t1 VALUES($i, 0);
  784. INSERT INTO t1 VALUES($i, 0);
  785. INSERT INTO t1 VALUES($i, 0);
  786. INSERT INTO t1 VALUES($i, 0);
  787. INSERT INTO t1 VALUES($i, 0);
  788. INSERT INTO t1 VALUES($i, 0);
  789. INSERT INTO t1 VALUES($i, 0);
  790. INSERT INTO t1 VALUES($i, 0);
  791. INSERT INTO t1 VALUES($i, 0);
  792. INSERT INTO t1 VALUES($i, 0);
  793. INSERT INTO t1 VALUES($i, 0);
  794. }
  795. }
  796. execsql ANALYZE
  797. execsql { SELECT count(*) FROM sqlite_stat4 }
  798. } {9}
  799. #-------------------------------------------------------------------------
  800. # For coverage.
  801. #
  802. ifcapable view {
  803. do_test 19.1 {
  804. reset_db
  805. execsql {
  806. CREATE TABLE t1(x, y);
  807. CREATE INDEX i1 ON t1(x, y);
  808. CREATE VIEW v1 AS SELECT * FROM t1;
  809. ANALYZE;
  810. }
  811. } {}
  812. }
  813. ifcapable auth {
  814. proc authproc {op args} {
  815. if {$op == "SQLITE_ANALYZE"} { return "SQLITE_DENY" }
  816. return "SQLITE_OK"
  817. }
  818. do_test 19.2 {
  819. reset_db
  820. db auth authproc
  821. execsql {
  822. CREATE TABLE t1(x, y);
  823. CREATE VIEW v1 AS SELECT * FROM t1;
  824. }
  825. catchsql ANALYZE
  826. } {1 {not authorized}}
  827. }
  828. #-------------------------------------------------------------------------
  829. #
  830. reset_db
  831. proc r {args} { expr rand() }
  832. db func r r
  833. db func lrange lrange
  834. do_test 20.1 {
  835. execsql {
  836. CREATE TABLE t1(a,b,c,d);
  837. CREATE INDEX i1 ON t1(a,b,c,d);
  838. }
  839. for {set i 0} {$i < 16} {incr i} {
  840. execsql {
  841. INSERT INTO t1 VALUES($i, r(), r(), r());
  842. INSERT INTO t1 VALUES($i, $i, r(), r());
  843. INSERT INTO t1 VALUES($i, $i, $i, r());
  844. INSERT INTO t1 VALUES($i, $i, $i, $i);
  845. INSERT INTO t1 VALUES($i, $i, $i, $i);
  846. INSERT INTO t1 VALUES($i, $i, $i, r());
  847. INSERT INTO t1 VALUES($i, $i, r(), r());
  848. INSERT INTO t1 VALUES($i, r(), r(), r());
  849. }
  850. }
  851. } {}
  852. do_execsql_test 20.2 { ANALYZE }
  853. for {set i 0} {$i<16} {incr i} {
  854. set val "$i $i $i $i"
  855. do_execsql_test 20.3.$i {
  856. SELECT count(*) FROM sqlite_stat4
  857. WHERE lrange(test_decode(sample), 0, 3)=$val
  858. } {1}
  859. }
  860. finish_test