1# 2013-07-31 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# Test cases for partial indices 13# 14 15 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18 19ifcapable !vtab { 20 finish_test 21 return 22} 23 24load_static_extension db wholenumber; 25do_test index6-1.1 { 26 # Able to parse and manage partial indices 27 execsql { 28 CREATE TABLE t1(a,b,c); 29 CREATE INDEX t1a ON t1(a) WHERE a IS NOT NULL; 30 CREATE INDEX t1b ON t1(b) WHERE b>10; 31 CREATE VIRTUAL TABLE nums USING wholenumber; 32 INSERT INTO t1(a,b,c) 33 SELECT CASE WHEN value%3!=0 THEN value END, value, value 34 FROM nums WHERE value<=20; 35 SELECT count(a), count(b) FROM t1; 36 PRAGMA integrity_check; 37 } 38} {14 20 ok} 39 40# Make sure the count(*) optimization works correctly with 41# partial indices. Ticket [a5c8ed66cae16243be6] 2013-10-03. 42# 43do_execsql_test index6-1.1.1 { 44 SELECT count(*) FROM t1; 45} {20} 46 47# Error conditions during parsing... 48# 49do_test index6-1.2 { 50 catchsql { 51 CREATE INDEX bad1 ON t1(a,b) WHERE x IS NOT NULL; 52 } 53} {1 {no such column: x}} 54do_test index6-1.3 { 55 catchsql { 56 CREATE INDEX bad1 ON t1(a,b) WHERE EXISTS(SELECT * FROM t1); 57 } 58} {1 {subqueries prohibited in partial index WHERE clauses}} 59do_test index6-1.4 { 60 catchsql { 61 CREATE INDEX bad1 ON t1(a,b) WHERE a!=?1; 62 } 63} {1 {parameters prohibited in partial index WHERE clauses}} 64do_test index6-1.5 { 65 catchsql { 66 CREATE INDEX bad1 ON t1(a,b) WHERE a!=random(); 67 } 68} {1 {functions prohibited in partial index WHERE clauses}} 69do_test index6-1.6 { 70 catchsql { 71 CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%'; 72 } 73} {1 {functions prohibited in partial index WHERE clauses}} 74 75do_test index6-1.10 { 76 execsql { 77 ANALYZE; 78 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 79 PRAGMA integrity_check; 80 } 81} {{} 20 t1a {14 1} t1b {10 1} ok} 82 83# STAT1 shows the partial indices have a reduced number of 84# rows. 85# 86do_test index6-1.11 { 87 execsql { 88 UPDATE t1 SET a=b; 89 ANALYZE; 90 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 91 PRAGMA integrity_check; 92 } 93} {{} 20 t1a {20 1} t1b {10 1} ok} 94 95do_test index6-1.11 { 96 execsql { 97 UPDATE t1 SET a=NULL WHERE b%3!=0; 98 UPDATE t1 SET b=b+100; 99 ANALYZE; 100 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 101 PRAGMA integrity_check; 102 } 103} {{} 20 t1a {6 1} t1b {20 1} ok} 104 105do_test index6-1.12 { 106 execsql { 107 UPDATE t1 SET a=CASE WHEN b%3!=0 THEN b END; 108 UPDATE t1 SET b=b-100; 109 ANALYZE; 110 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 111 PRAGMA integrity_check; 112 } 113} {{} 20 t1a {13 1} t1b {10 1} ok} 114 115do_test index6-1.13 { 116 execsql { 117 DELETE FROM t1 WHERE b BETWEEN 8 AND 12; 118 ANALYZE; 119 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 120 PRAGMA integrity_check; 121 } 122} {{} 15 t1a {10 1} t1b {8 1} ok} 123 124do_test index6-1.14 { 125 execsql { 126 REINDEX; 127 ANALYZE; 128 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 129 PRAGMA integrity_check; 130 } 131} {{} 15 t1a {10 1} t1b {8 1} ok} 132 133do_test index6-1.15 { 134 execsql { 135 CREATE INDEX t1c ON t1(c); 136 ANALYZE; 137 SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 138 PRAGMA integrity_check; 139 } 140} {t1a {10 1} t1b {8 1} t1c {15 1} ok} 141 142# Queries use partial indices as appropriate times. 143# 144do_test index6-2.1 { 145 execsql { 146 CREATE TABLE t2(a,b); 147 INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000; 148 UPDATE t2 SET a=NULL WHERE b%2==0; 149 CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL; 150 SELECT count(*) FROM t2 WHERE a IS NOT NULL; 151 } 152} {500} 153do_test index6-2.2 { 154 execsql { 155 EXPLAIN QUERY PLAN 156 SELECT * FROM t2 WHERE a=5; 157 } 158} {/.* TABLE t2 USING INDEX t2a1 .*/} 159ifcapable stat4||stat3 { 160 execsql ANALYZE 161 do_test index6-2.3stat4 { 162 execsql { 163 EXPLAIN QUERY PLAN 164 SELECT * FROM t2 WHERE a IS NOT NULL; 165 } 166 } {/.* TABLE t2 USING INDEX t2a1 .*/} 167} else { 168 do_test index6-2.3stat4 { 169 execsql { 170 EXPLAIN QUERY PLAN 171 SELECT * FROM t2 WHERE a IS NOT NULL AND a>0; 172 } 173 } {/.* TABLE t2 USING INDEX t2a1 .*/} 174} 175do_test index6-2.4 { 176 execsql { 177 EXPLAIN QUERY PLAN 178 SELECT * FROM t2 WHERE a IS NULL; 179 } 180} {~/.*INDEX t2a1.*/} 181 182do_execsql_test index6-2.101 { 183 DROP INDEX t2a1; 184 UPDATE t2 SET a=b, b=b+10000; 185 SELECT b FROM t2 WHERE a=15; 186} {10015} 187do_execsql_test index6-2.102 { 188 CREATE INDEX t2a2 ON t2(a) WHERE a<100 OR a>200; 189 SELECT b FROM t2 WHERE a=15; 190 PRAGMA integrity_check; 191} {10015 ok} 192do_execsql_test index6-2.102eqp { 193 EXPLAIN QUERY PLAN 194 SELECT b FROM t2 WHERE a=15; 195} {~/.*INDEX t2a2.*/} 196do_execsql_test index6-2.103 { 197 SELECT b FROM t2 WHERE a=15 AND a<100; 198} {10015} 199do_execsql_test index6-2.103eqp { 200 EXPLAIN QUERY PLAN 201 SELECT b FROM t2 WHERE a=15 AND a<100; 202} {/.*INDEX t2a2.*/} 203do_execsql_test index6-2.104 { 204 SELECT b FROM t2 WHERE a=515 AND a>200; 205} {10515} 206do_execsql_test index6-2.104eqp { 207 EXPLAIN QUERY PLAN 208 SELECT b FROM t2 WHERE a=515 AND a>200; 209} {/.*INDEX t2a2.*/} 210 211# Partial UNIQUE indices 212# 213do_execsql_test index6-3.1 { 214 CREATE TABLE t3(a,b); 215 INSERT INTO t3 SELECT value, value FROM nums WHERE value<200; 216 UPDATE t3 SET a=999 WHERE b%5!=0; 217 CREATE UNIQUE INDEX t3a ON t3(a) WHERE a<>999; 218} {} 219do_test index6-3.2 { 220 # unable to insert a duplicate row a-value that is not 999. 221 catchsql { 222 INSERT INTO t3(a,b) VALUES(150, 'test1'); 223 } 224} {1 {UNIQUE constraint failed: t3.a}} 225do_test index6-3.3 { 226 # can insert multiple rows with a==999 because such rows are not 227 # part of the unique index. 228 catchsql { 229 INSERT INTO t3(a,b) VALUES(999, 'test1'), (999, 'test2'); 230 } 231} {0 {}} 232do_execsql_test index6-3.4 { 233 SELECT count(*) FROM t3 WHERE a=999; 234} {162} 235integrity_check index6-3.5 236 237do_execsql_test index6-4.0 { 238 VACUUM; 239 PRAGMA integrity_check; 240} {ok} 241 242# Silently ignore database name qualifiers in partial indices. 243# 244do_execsql_test index6-5.0 { 245 CREATE INDEX t3b ON t3(b) WHERE xyzzy.t3.b BETWEEN 5 AND 10; 246 /* ^^^^^-- ignored */ 247 ANALYZE; 248 SELECT count(*) FROM t3 WHERE t3.b BETWEEN 5 AND 10; 249 SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b'; 250} {6 6} 251 252# Test case for ticket [2ea3e9fe6379fc3f6ce7e090ce483c1a3a80d6c9] from 253# 2014-04-13: Partial index causes assertion fault on UPDATE OR REPLACE. 254# 255do_execsql_test index6-6.0 { 256 CREATE TABLE t6(a,b); 257 CREATE UNIQUE INDEX t6ab ON t1(a,b); 258 CREATE INDEX t6b ON t6(b) WHERE b=1; 259 INSERT INTO t6(a,b) VALUES(123,456); 260 SELECT * FROM t6; 261} {123 456} 262do_execsql_test index6-6.1 { 263 UPDATE OR REPLACE t6 SET b=789; 264 SELECT * FROM t6; 265} {123 789} 266do_execsql_test index6-6.2 { 267 PRAGMA integrity_check; 268} {ok} 269 270# Test case for ticket [2326c258d02ead33d69faa63de8f4686b9b1b9d9] on 271# 2015-02-24. Any use of a partial index qualifying constraint inside 272# the ON clause of a LEFT JOIN was causing incorrect results for all 273# versions of SQLite 3.8.0 through 3.8.8. 274# 275do_execsql_test index6-7.0 { 276 CREATE TABLE t7a(x); 277 CREATE TABLE t7b(y); 278 INSERT INTO t7a(x) VALUES(1); 279 CREATE INDEX t7ax ON t7a(x) WHERE x=99; 280 PRAGMA automatic_index=OFF; 281 SELECT * FROM t7a LEFT JOIN t7b ON (x=99) ORDER BY x; 282} {1 {}} 283do_execsql_test index6-7.1 { 284 INSERT INTO t7b(y) VALUES(2); 285 SELECT * FROM t7a JOIN t7b ON (x=99) ORDER BY x; 286} {} 287do_execsql_test index6-7.2 { 288 INSERT INTO t7a(x) VALUES(99); 289 SELECT * FROM t7a LEFT JOIN t7b ON (x=99) ORDER BY x; 290} {1 {} 99 2} 291do_execsql_test index6-7.3 { 292 SELECT * FROM t7a JOIN t7b ON (x=99) ORDER BY x; 293} {99 2} 294do_execsql_test index6-7.4 { 295 EXPLAIN QUERY PLAN 296 SELECT * FROM t7a JOIN t7b ON (x=99) ORDER BY x; 297} {/USING COVERING INDEX t7ax/} 298 299 300do_execsql_test index6-8.0 { 301 CREATE TABLE t8a(a,b); 302 CREATE TABLE t8b(x,y); 303 CREATE INDEX i8c ON t8b(y) WHERE x = 'value'; 304 305 INSERT INTO t8a VALUES(1, 'one'); 306 INSERT INTO t8a VALUES(2, 'two'); 307 INSERT INTO t8a VALUES(3, 'three'); 308 309 INSERT INTO t8b VALUES('value', 1); 310 INSERT INTO t8b VALUES('dummy', 2); 311 INSERT INTO t8b VALUES('value', 3); 312 INSERT INTO t8b VALUES('dummy', 4); 313} {} 314 315do_eqp_test index6-8.1 { 316 SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a) 317} { 318 0 0 0 {SCAN TABLE t8a} 319 0 1 1 {SEARCH TABLE t8b USING INDEX i8c (y=?)} 320} 321 322do_execsql_test index6-8.2 { 323 SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a) 324} { 325 1 one value 1 326 2 two {} {} 327 3 three value 3 328} 329 330# 2015-06-11. Assertion fault found by AFL 331# 332do_execsql_test index6-9.1 { 333 CREATE TABLE t9(a int, b int, c int); 334 CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20); 335 INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5),(NULL,7,3); 336 UPDATE t9 SET b=c WHERE a in (10,12,20); 337 SELECT a,b,c,'|' FROM t9 ORDER BY a; 338} {{} 7 3 | 1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |} 339do_execsql_test index6-9.2 { 340 DROP TABLE t9; 341 CREATE TABLE t9(a int, b int, c int, PRIMARY KEY(a)) WITHOUT ROWID; 342 CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20); 343 INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5); 344 UPDATE t9 SET b=c WHERE a in (10,12,20); 345 SELECT a,b,c,'|' FROM t9 ORDER BY a; 346} {1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |} 347 348# AND-connected terms in the WHERE clause of a partial index 349# 350do_execsql_test index6-10.1 { 351 CREATE TABLE t10(a,b,c,d,e INTEGER PRIMARY KEY); 352 INSERT INTO t10 VALUES 353 (1,2,3,4,5), 354 (2,3,4,5,6), 355 (3,4,5,6,7), 356 (1,2,3,8,9); 357 CREATE INDEX t10x ON t10(d) WHERE a=1 AND b=2 AND c=3; 358 SELECT e FROM t10 WHERE a=1 AND b=2 AND c=3 ORDER BY d; 359} {5 9} 360do_execsql_test index6-10.1eqp { 361 EXPLAIN QUERY PLAN 362 SELECT e FROM t10 WHERE a=1 AND b=2 AND c=3 ORDER BY d; 363} {/USING INDEX t10x/} 364do_execsql_test index6-10.2 { 365 SELECT e FROM t10 WHERE c=3 AND 2=b AND a=1 ORDER BY d DESC; 366} {9 5} 367do_execsql_test index6-10.2eqp { 368 EXPLAIN QUERY PLAN 369 SELECT e FROM t10 WHERE c=3 AND 2=b AND a=1 ORDER BY d DESC; 370} {/USING INDEX t10x/} 371do_execsql_test index6-10.3 { 372 SELECT e FROM t10 WHERE a=1 AND b=2 ORDER BY d DESC; 373} {9 5} 374do_execsql_test index6-10.3eqp { 375 EXPLAIN QUERY PLAN 376 SELECT e FROM t10 WHERE a=1 AND b=2 ORDER BY d DESC; 377} {~/USING INDEX t10x/} 378 379finish_test 380