xref: /sqlite-3.40.0/test/index6.test (revision c3c16cbd)
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