11fe0537eSdrh# 2013-07-31 21fe0537eSdrh# 31fe0537eSdrh# The author disclaims copyright to this source code. In place of 41fe0537eSdrh# a legal notice, here is a blessing: 51fe0537eSdrh# 61fe0537eSdrh# May you do good and not evil. 71fe0537eSdrh# May you find forgiveness for yourself and forgive others. 81fe0537eSdrh# May you share freely, never taking more than you give. 91fe0537eSdrh# 101fe0537eSdrh#*********************************************************************** 111fe0537eSdrh# 121fe0537eSdrh# Test cases for partial indices 131fe0537eSdrh# 141fe0537eSdrh 151fe0537eSdrh 161fe0537eSdrhset testdir [file dirname $argv0] 171fe0537eSdrhsource $testdir/tester.tcl 181fe0537eSdrh 19*c3c16cbdSdanifcapable !vtab { 20*c3c16cbdSdan finish_test 21*c3c16cbdSdan return 22*c3c16cbdSdan} 23*c3c16cbdSdan 241fe0537eSdrhload_static_extension db wholenumber; 251fe0537eSdrhdo_test index6-1.1 { 2666518ca7Sdrh # Able to parse and manage partial indices 271fe0537eSdrh execsql { 28721dfcf5Sdrh CREATE TABLE t1(a,b,c); 291fe0537eSdrh CREATE INDEX t1a ON t1(a) WHERE a IS NOT NULL; 301fe0537eSdrh CREATE INDEX t1b ON t1(b) WHERE b>10; 311fe0537eSdrh CREATE VIRTUAL TABLE nums USING wholenumber; 32721dfcf5Sdrh INSERT INTO t1(a,b,c) 33721dfcf5Sdrh SELECT CASE WHEN value%3!=0 THEN value END, value, value 341fe0537eSdrh FROM nums WHERE value<=20; 351fe0537eSdrh SELECT count(a), count(b) FROM t1; 3666518ca7Sdrh PRAGMA integrity_check; 371fe0537eSdrh } 3866518ca7Sdrh} {14 20 ok} 391fe0537eSdrh 4066518ca7Sdrh# Error conditions during parsing... 4166518ca7Sdrh# 423780be11Sdrhdo_test index6-1.2 { 433780be11Sdrh catchsql { 44721dfcf5Sdrh CREATE INDEX bad1 ON t1(a,b) WHERE x IS NOT NULL; 453780be11Sdrh } 46721dfcf5Sdrh} {1 {no such column: x}} 473780be11Sdrhdo_test index6-1.3 { 483780be11Sdrh catchsql { 493780be11Sdrh CREATE INDEX bad1 ON t1(a,b) WHERE EXISTS(SELECT * FROM t1); 503780be11Sdrh } 513780be11Sdrh} {1 {subqueries prohibited in partial index WHERE clauses}} 523780be11Sdrhdo_test index6-1.4 { 533780be11Sdrh catchsql { 543780be11Sdrh CREATE INDEX bad1 ON t1(a,b) WHERE a!=?1; 553780be11Sdrh } 563780be11Sdrh} {1 {parameters prohibited in partial index WHERE clauses}} 573780be11Sdrhdo_test index6-1.5 { 583780be11Sdrh catchsql { 593780be11Sdrh CREATE INDEX bad1 ON t1(a,b) WHERE a!=random(); 603780be11Sdrh } 613780be11Sdrh} {1 {functions prohibited in partial index WHERE clauses}} 623780be11Sdrhdo_test index6-1.6 { 633780be11Sdrh catchsql { 643780be11Sdrh CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%'; 653780be11Sdrh } 663780be11Sdrh} {1 {functions prohibited in partial index WHERE clauses}} 673780be11Sdrh 688a9789b6Sdrhdo_test index6-1.10 { 698a9789b6Sdrh execsql { 708a9789b6Sdrh ANALYZE; 718a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 728a9789b6Sdrh PRAGMA integrity_check; 738a9789b6Sdrh } 74721dfcf5Sdrh} {{} 20 t1a {14 1} t1b {10 1} ok} 758a9789b6Sdrh 7666518ca7Sdrh# STAT1 shows the partial indices have a reduced number of 7766518ca7Sdrh# rows. 7866518ca7Sdrh# 798a9789b6Sdrhdo_test index6-1.11 { 808a9789b6Sdrh execsql { 818a9789b6Sdrh UPDATE t1 SET a=b; 828a9789b6Sdrh ANALYZE; 838a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 848a9789b6Sdrh PRAGMA integrity_check; 858a9789b6Sdrh } 86721dfcf5Sdrh} {{} 20 t1a {20 1} t1b {10 1} ok} 878a9789b6Sdrh 888a9789b6Sdrhdo_test index6-1.11 { 898a9789b6Sdrh execsql { 908a9789b6Sdrh UPDATE t1 SET a=NULL WHERE b%3!=0; 918a9789b6Sdrh UPDATE t1 SET b=b+100; 928a9789b6Sdrh ANALYZE; 938a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 948a9789b6Sdrh PRAGMA integrity_check; 958a9789b6Sdrh } 96721dfcf5Sdrh} {{} 20 t1a {6 1} t1b {20 1} ok} 978a9789b6Sdrh 988a9789b6Sdrhdo_test index6-1.12 { 998a9789b6Sdrh execsql { 1008a9789b6Sdrh UPDATE t1 SET a=CASE WHEN b%3!=0 THEN b END; 1018a9789b6Sdrh UPDATE t1 SET b=b-100; 1028a9789b6Sdrh ANALYZE; 1038a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 1048a9789b6Sdrh PRAGMA integrity_check; 1058a9789b6Sdrh } 106721dfcf5Sdrh} {{} 20 t1a {13 1} t1b {10 1} ok} 1078a9789b6Sdrh 1088a9789b6Sdrhdo_test index6-1.13 { 1098a9789b6Sdrh execsql { 1108a9789b6Sdrh DELETE FROM t1 WHERE b BETWEEN 8 AND 12; 1118a9789b6Sdrh ANALYZE; 1128a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 1138a9789b6Sdrh PRAGMA integrity_check; 1148a9789b6Sdrh } 115721dfcf5Sdrh} {{} 15 t1a {10 1} t1b {8 1} ok} 1168a9789b6Sdrh 1178a9789b6Sdrhdo_test index6-1.14 { 1188a9789b6Sdrh execsql { 1198a9789b6Sdrh REINDEX; 1208a9789b6Sdrh ANALYZE; 1218a9789b6Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 1228a9789b6Sdrh PRAGMA integrity_check; 1238a9789b6Sdrh } 124721dfcf5Sdrh} {{} 15 t1a {10 1} t1b {8 1} ok} 125721dfcf5Sdrh 126721dfcf5Sdrhdo_test index6-1.15 { 127721dfcf5Sdrh execsql { 128721dfcf5Sdrh CREATE INDEX t1c ON t1(c); 129721dfcf5Sdrh ANALYZE; 130721dfcf5Sdrh SELECT idx, stat FROM sqlite_stat1 ORDER BY idx; 131721dfcf5Sdrh PRAGMA integrity_check; 132721dfcf5Sdrh } 133721dfcf5Sdrh} {t1a {10 1} t1b {8 1} t1c {15 1} ok} 1343780be11Sdrh 13566518ca7Sdrh# Queries use partial indices as appropriate times. 13666518ca7Sdrh# 13766518ca7Sdrhdo_test index6-2.1 { 13866518ca7Sdrh execsql { 13966518ca7Sdrh CREATE TABLE t2(a,b); 14066518ca7Sdrh INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000; 14166518ca7Sdrh UPDATE t2 SET a=NULL WHERE b%5==0; 14266518ca7Sdrh CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL; 14366518ca7Sdrh SELECT count(*) FROM t2 WHERE a IS NOT NULL; 14466518ca7Sdrh } 14566518ca7Sdrh} {800} 14666518ca7Sdrhdo_test index6-2.2 { 14766518ca7Sdrh execsql { 14866518ca7Sdrh EXPLAIN QUERY PLAN 14966518ca7Sdrh SELECT * FROM t2 WHERE a=5; 15066518ca7Sdrh } 15166518ca7Sdrh} {/.* TABLE t2 USING INDEX t2a1 .*/} 1529fe809c5Sdrhifcapable stat3 { 1539fe809c5Sdrh do_test index6-2.3stat3 { 15466518ca7Sdrh execsql { 15566518ca7Sdrh EXPLAIN QUERY PLAN 15666518ca7Sdrh SELECT * FROM t2 WHERE a IS NOT NULL; 15766518ca7Sdrh } 15866518ca7Sdrh } {/.* TABLE t2 USING INDEX t2a1 .*/} 1599fe809c5Sdrh} else { 1609fe809c5Sdrh do_test index6-2.3stat3 { 1619fe809c5Sdrh execsql { 1629fe809c5Sdrh EXPLAIN QUERY PLAN 1639fe809c5Sdrh SELECT * FROM t2 WHERE a IS NOT NULL AND a>0; 1649fe809c5Sdrh } 1659fe809c5Sdrh } {/.* TABLE t2 USING INDEX t2a1 .*/} 1669fe809c5Sdrh} 16766518ca7Sdrhdo_test index6-2.4 { 16866518ca7Sdrh execsql { 16966518ca7Sdrh EXPLAIN QUERY PLAN 17066518ca7Sdrh SELECT * FROM t2 WHERE a IS NULL; 17166518ca7Sdrh } 17266518ca7Sdrh} {~/.*INDEX t2a1.*/} 17366518ca7Sdrh 17466518ca7Sdrhdo_execsql_test index6-2.101 { 17566518ca7Sdrh DROP INDEX t2a1; 17666518ca7Sdrh UPDATE t2 SET a=b, b=b+10000; 17766518ca7Sdrh SELECT b FROM t2 WHERE a=15; 17866518ca7Sdrh} {10015} 17966518ca7Sdrhdo_execsql_test index6-2.102 { 18066518ca7Sdrh CREATE INDEX t2a2 ON t2(a) WHERE a<100 OR a>200; 18166518ca7Sdrh SELECT b FROM t2 WHERE a=15; 18266518ca7Sdrh PRAGMA integrity_check; 18366518ca7Sdrh} {10015 ok} 18466518ca7Sdrhdo_execsql_test index6-2.102eqp { 18566518ca7Sdrh EXPLAIN QUERY PLAN 18666518ca7Sdrh SELECT b FROM t2 WHERE a=15; 18766518ca7Sdrh} {~/.*INDEX t2a2.*/} 18866518ca7Sdrhdo_execsql_test index6-2.103 { 18966518ca7Sdrh SELECT b FROM t2 WHERE a=15 AND a<100; 19066518ca7Sdrh} {10015} 19166518ca7Sdrhdo_execsql_test index6-2.103eqp { 19266518ca7Sdrh EXPLAIN QUERY PLAN 19366518ca7Sdrh SELECT b FROM t2 WHERE a=15 AND a<100; 19466518ca7Sdrh} {/.*INDEX t2a2.*/} 19566518ca7Sdrhdo_execsql_test index6-2.104 { 19666518ca7Sdrh SELECT b FROM t2 WHERE a=515 AND a>200; 19766518ca7Sdrh} {10515} 19866518ca7Sdrhdo_execsql_test index6-2.104eqp { 19966518ca7Sdrh EXPLAIN QUERY PLAN 20066518ca7Sdrh SELECT b FROM t2 WHERE a=515 AND a>200; 20166518ca7Sdrh} {/.*INDEX t2a2.*/} 20266518ca7Sdrh 20366518ca7Sdrh# Partial UNIQUE indices 20466518ca7Sdrh# 20566518ca7Sdrhdo_execsql_test index6-3.1 { 20666518ca7Sdrh CREATE TABLE t3(a,b); 20766518ca7Sdrh INSERT INTO t3 SELECT value, value FROM nums WHERE value<200; 20866518ca7Sdrh UPDATE t3 SET a=999 WHERE b%5!=0; 20966518ca7Sdrh CREATE UNIQUE INDEX t3a ON t3(a) WHERE a<>999; 21066518ca7Sdrh} {} 21166518ca7Sdrhdo_test index6-3.2 { 21266518ca7Sdrh # unable to insert a duplicate row a-value that is not 999. 21366518ca7Sdrh catchsql { 21466518ca7Sdrh INSERT INTO t3(a,b) VALUES(150, 'test1'); 21566518ca7Sdrh } 21666518ca7Sdrh} {1 {column a is not unique}} 21766518ca7Sdrhdo_test index6-3.3 { 21866518ca7Sdrh # can insert multiple rows with a==999 because such rows are not 21966518ca7Sdrh # part of the unique index. 22066518ca7Sdrh catchsql { 22166518ca7Sdrh INSERT INTO t3(a,b) VALUES(999, 'test1'), (999, 'test2'); 22266518ca7Sdrh } 22366518ca7Sdrh} {0 {}} 22466518ca7Sdrhdo_execsql_test index6-3.4 { 22566518ca7Sdrh SELECT count(*) FROM t3 WHERE a=999; 22666518ca7Sdrh} {162} 22766518ca7Sdrhintegrity_check index6-3.5 22866518ca7Sdrh 2293bf0ac17Sdrhdo_execsql_test index6-4.0 { 2303bf0ac17Sdrh VACUUM; 2313bf0ac17Sdrh PRAGMA integrity_check; 2323bf0ac17Sdrh} {ok} 2333bf0ac17Sdrh 2341e7d43c9Sdrh# Silently ignore database name qualifiers in partial indices. 2351e7d43c9Sdrh# 2361e7d43c9Sdrhdo_execsql_test index6-5.0 { 2371e7d43c9Sdrh CREATE INDEX t3b ON t3(b) WHERE xyzzy.t3.b BETWEEN 5 AND 10; 2381e7d43c9Sdrh /* ^^^^^-- ignored */ 2391e7d43c9Sdrh ANALYZE; 2401e7d43c9Sdrh SELECT count(*) FROM t3 WHERE t3.b BETWEEN 5 AND 10; 2411e7d43c9Sdrh SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b'; 2421e7d43c9Sdrh} {6 6} 2431e7d43c9Sdrh 2441fe0537eSdrhfinish_test 245