OLD | NEW |
1 # 2008 October 4 | 1 # 2008 October 4 |
2 # | 2 # |
3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
5 # | 5 # |
6 # May you do good and not evil. | 6 # May you do good and not evil. |
7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
9 # | 9 # |
10 #*********************************************************************** | 10 #*********************************************************************** |
(...skipping 22 matching lines...) Expand all Loading... |
33 } {} | 33 } {} |
34 | 34 |
35 # Explain Query Plan | 35 # Explain Query Plan |
36 # | 36 # |
37 proc EQP {sql} { | 37 proc EQP {sql} { |
38 uplevel "execsql {EXPLAIN QUERY PLAN $sql}" | 38 uplevel "execsql {EXPLAIN QUERY PLAN $sql}" |
39 } | 39 } |
40 | 40 |
41 # These tests are to check that "EXPLAIN QUERY PLAN" is working as expected. | 41 # These tests are to check that "EXPLAIN QUERY PLAN" is working as expected. |
42 # | 42 # |
43 do_test indexedby-1.2 { | 43 do_execsql_test indexedby-1.2 { |
44 EQP { select * from t1 WHERE a = 10; } | 44 EXPLAIN QUERY PLAN select * from t1 WHERE a = 10; |
45 } {0 0 {TABLE t1 WITH INDEX i1}} | 45 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}} |
46 do_test indexedby-1.3 { | 46 do_execsql_test indexedby-1.3 { |
47 EQP { select * from t1 ; } | 47 EXPLAIN QUERY PLAN select * from t1 ; |
48 } {0 0 {TABLE t1}} | 48 } {0 0 0 {SCAN TABLE t1 (~1000000 rows)}} |
49 do_test indexedby-1.4 { | 49 do_execsql_test indexedby-1.4 { |
50 EQP { select * from t1, t2 WHERE c = 10; } | 50 EXPLAIN QUERY PLAN select * from t1, t2 WHERE c = 10; |
51 } {0 1 {TABLE t2 WITH INDEX i3} 1 0 {TABLE t1}} | 51 } { |
| 52 0 0 1 {SEARCH TABLE t2 USING INDEX i3 (c=?) (~10 rows)} |
| 53 0 1 0 {SCAN TABLE t1 (~1000000 rows)} |
| 54 } |
52 | 55 |
53 # Parser tests. Test that an INDEXED BY or NOT INDEX clause can be | 56 # Parser tests. Test that an INDEXED BY or NOT INDEX clause can be |
54 # attached to a table in the FROM clause, but not to a sub-select or | 57 # attached to a table in the FROM clause, but not to a sub-select or |
55 # SQL view. Also test that specifying an index that does not exist or | 58 # SQL view. Also test that specifying an index that does not exist or |
56 # is attached to a different table is detected as an error. | 59 # is attached to a different table is detected as an error. |
57 # | 60 # |
58 do_test indexedby-2.1 { | 61 do_test indexedby-2.1 { |
59 execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'} | 62 execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'} |
60 } {} | 63 } {} |
61 do_test indexedby-2.2 { | 64 do_test indexedby-2.2 { |
(...skipping 11 matching lines...) Expand all Loading... |
73 } {1 {no such index: i5}} | 76 } {1 {no such index: i5}} |
74 do_test indexedby-2.6 { | 77 do_test indexedby-2.6 { |
75 catchsql { SELECT * FROM t1 INDEXED BY WHERE a = 'one' AND b = 'two'} | 78 catchsql { SELECT * FROM t1 INDEXED BY WHERE a = 'one' AND b = 'two'} |
76 } {1 {near "WHERE": syntax error}} | 79 } {1 {near "WHERE": syntax error}} |
77 do_test indexedby-2.7 { | 80 do_test indexedby-2.7 { |
78 catchsql { SELECT * FROM v1 INDEXED BY i1 WHERE a = 'one' } | 81 catchsql { SELECT * FROM v1 INDEXED BY i1 WHERE a = 'one' } |
79 } {1 {no such index: i1}} | 82 } {1 {no such index: i1}} |
80 | 83 |
81 # Tests for single table cases. | 84 # Tests for single table cases. |
82 # | 85 # |
83 do_test indexedby-3.1 { | 86 do_execsql_test indexedby-3.1 { |
84 EQP { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'} | 87 EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two' |
85 } {0 0 {TABLE t1}} | 88 } {0 0 0 {SCAN TABLE t1 (~10000 rows)}} |
86 do_test indexedby-3.2 { | 89 do_execsql_test indexedby-3.2 { |
87 EQP { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'} | 90 EXPLAIN QUERY PLAN |
88 } {0 0 {TABLE t1 WITH INDEX i1}} | 91 SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two' |
89 do_test indexedby-3.3 { | 92 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}} |
90 EQP { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'} | 93 do_execsql_test indexedby-3.3 { |
91 } {0 0 {TABLE t1 WITH INDEX i2}} | 94 EXPLAIN QUERY PLAN |
| 95 SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two' |
| 96 } {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}} |
92 do_test indexedby-3.4 { | 97 do_test indexedby-3.4 { |
93 catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' } | 98 catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' } |
94 } {1 {cannot use index: i2}} | 99 } {1 {cannot use index: i2}} |
95 do_test indexedby-3.5 { | 100 do_test indexedby-3.5 { |
96 catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a } | 101 catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a } |
97 } {1 {cannot use index: i2}} | 102 } {1 {cannot use index: i2}} |
98 do_test indexedby-3.6 { | 103 do_test indexedby-3.6 { |
99 catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' } | 104 catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' } |
100 } {0 {}} | 105 } {0 {}} |
101 do_test indexedby-3.7 { | 106 do_test indexedby-3.7 { |
102 catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a } | 107 catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a } |
103 } {0 {}} | 108 } {0 {}} |
104 | 109 |
105 do_test indexedby-3.8 { | 110 do_execsql_test indexedby-3.8 { |
106 EQP { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e } | 111 EXPLAIN QUERY PLAN |
107 } {0 0 {TABLE t3 WITH INDEX sqlite_autoindex_t3_1 ORDER BY}} | 112 SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e |
108 do_test indexedby-3.9 { | 113 } {0 0 0 {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1 (~1000000 rows)}} |
109 EQP { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 } | 114 do_execsql_test indexedby-3.9 { |
110 } {0 0 {TABLE t3 WITH INDEX sqlite_autoindex_t3_1}} | 115 EXPLAIN QUERY PLAN |
| 116 SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 |
| 117 } {0 0 0 {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?) (~1 rows)}} |
111 do_test indexedby-3.10 { | 118 do_test indexedby-3.10 { |
112 catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 } | 119 catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 } |
113 } {1 {cannot use index: sqlite_autoindex_t3_1}} | 120 } {1 {cannot use index: sqlite_autoindex_t3_1}} |
114 do_test indexedby-3.11 { | 121 do_test indexedby-3.11 { |
115 catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 } | 122 catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 } |
116 } {1 {no such index: sqlite_autoindex_t3_2}} | 123 } {1 {no such index: sqlite_autoindex_t3_2}} |
117 | 124 |
118 # Tests for multiple table cases. | 125 # Tests for multiple table cases. |
119 # | 126 # |
120 do_test indexedby-4.1 { | 127 do_execsql_test indexedby-4.1 { |
121 EQP { SELECT * FROM t1, t2 WHERE a = c } | 128 EXPLAIN QUERY PLAN SELECT * FROM t1, t2 WHERE a = c |
122 } {0 0 {TABLE t1} 1 1 {TABLE t2 WITH INDEX i3}} | 129 } { |
123 do_test indexedby-4.2 { | 130 0 0 0 {SCAN TABLE t1 (~1000000 rows)} |
124 EQP { SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c } | 131 0 1 1 {SEARCH TABLE t2 USING INDEX i3 (c=?) (~10 rows)} |
125 } {0 1 {TABLE t2} 1 0 {TABLE t1 WITH INDEX i1}} | 132 } |
| 133 do_execsql_test indexedby-4.2 { |
| 134 EXPLAIN QUERY PLAN SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c |
| 135 } { |
| 136 0 0 1 {SCAN TABLE t2 (~1000000 rows)} |
| 137 0 1 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)} |
| 138 } |
| 139 do_test indexedby-4.3 { |
| 140 catchsql { |
| 141 SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c |
| 142 } |
| 143 } {1 {cannot use index: i1}} |
| 144 do_test indexedby-4.4 { |
| 145 catchsql { |
| 146 SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c |
| 147 } |
| 148 } {1 {cannot use index: i3}} |
126 | 149 |
127 # Test embedding an INDEXED BY in a CREATE VIEW statement. This block | 150 # Test embedding an INDEXED BY in a CREATE VIEW statement. This block |
128 # also tests that nothing bad happens if an index refered to by | 151 # also tests that nothing bad happens if an index refered to by |
129 # a CREATE VIEW statement is dropped and recreated. | 152 # a CREATE VIEW statement is dropped and recreated. |
130 # | 153 # |
131 do_test indexedby-5.1 { | 154 do_execsql_test indexedby-5.1 { |
132 execsql { | 155 CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5; |
133 CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5; | 156 EXPLAIN QUERY PLAN SELECT * FROM v2 |
134 } | 157 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?) (~250000 rows)}} |
135 EQP { SELECT * FROM v2 } | 158 do_execsql_test indexedby-5.2 { |
136 } {0 0 {TABLE t1 WITH INDEX i1}} | 159 EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 |
137 do_test indexedby-5.2 { | 160 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?) (~25000 rows)}} |
138 EQP { SELECT * FROM v2 WHERE b = 10 } | |
139 } {0 0 {TABLE t1 WITH INDEX i1}} | |
140 do_test indexedby-5.3 { | 161 do_test indexedby-5.3 { |
141 execsql { DROP INDEX i1 } | 162 execsql { DROP INDEX i1 } |
142 catchsql { SELECT * FROM v2 } | 163 catchsql { SELECT * FROM v2 } |
143 } {1 {no such index: i1}} | 164 } {1 {no such index: i1}} |
144 do_test indexedby-5.4 { | 165 do_test indexedby-5.4 { |
145 # Recreate index i1 in such a way as it cannot be used by the view query. | 166 # Recreate index i1 in such a way as it cannot be used by the view query. |
146 execsql { CREATE INDEX i1 ON t1(b) } | 167 execsql { CREATE INDEX i1 ON t1(b) } |
147 catchsql { SELECT * FROM v2 } | 168 catchsql { SELECT * FROM v2 } |
148 } {1 {cannot use index: i1}} | 169 } {1 {cannot use index: i1}} |
149 do_test indexedby-5.5 { | 170 do_test indexedby-5.5 { |
150 # Drop and recreate index i1 again. This time, create it so that it can | 171 # Drop and recreate index i1 again. This time, create it so that it can |
151 # be used by the query. | 172 # be used by the query. |
152 execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) } | 173 execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) } |
153 catchsql { SELECT * FROM v2 } | 174 catchsql { SELECT * FROM v2 } |
154 } {0 {}} | 175 } {0 {}} |
155 | 176 |
156 # Test that "NOT INDEXED" may use the rowid index, but not others. | 177 # Test that "NOT INDEXED" may use the rowid index, but not others. |
157 # | 178 # |
158 do_test indexedby-6.1 { | 179 do_execsql_test indexedby-6.1 { |
159 EQP { SELECT * FROM t1 WHERE b = 10 ORDER BY rowid } | 180 EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 10 ORDER BY rowid |
160 } {0 0 {TABLE t1 WITH INDEX i2 ORDER BY}} | 181 } {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~10 rows)}} |
161 do_test indexedby-6.2 { | 182 do_execsql_test indexedby-6.2 { |
162 EQP { SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid } | 183 EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid |
163 } {0 0 {TABLE t1 USING PRIMARY KEY ORDER BY}} | 184 } {0 0 0 {SCAN TABLE t1 USING INTEGER PRIMARY KEY (~100000 rows)}} |
164 | 185 |
165 # Test that "INDEXED BY" can be used in a DELETE statement. | 186 # Test that "INDEXED BY" can be used in a DELETE statement. |
166 # | 187 # |
167 do_test indexedby-7.1 { | 188 do_execsql_test indexedby-7.1 { |
168 EQP { DELETE FROM t1 WHERE a = 5 } | 189 EXPLAIN QUERY PLAN DELETE FROM t1 WHERE a = 5 |
169 } {0 0 {TABLE t1 WITH INDEX i1}} | 190 } {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}} |
170 do_test indexedby-7.2 { | 191 do_execsql_test indexedby-7.2 { |
171 EQP { DELETE FROM t1 NOT INDEXED WHERE a = 5 } | 192 EXPLAIN QUERY PLAN DELETE FROM t1 NOT INDEXED WHERE a = 5 |
172 } {0 0 {TABLE t1}} | 193 } {0 0 0 {SCAN TABLE t1 (~100000 rows)}} |
173 do_test indexedby-7.3 { | 194 do_execsql_test indexedby-7.3 { |
174 EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 } | 195 EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 |
175 } {0 0 {TABLE t1 WITH INDEX i1}} | 196 } {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}} |
176 do_test indexedby-7.4 { | 197 do_execsql_test indexedby-7.4 { |
177 EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10} | 198 EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10 |
178 } {0 0 {TABLE t1 WITH INDEX i1}} | 199 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}} |
179 do_test indexedby-7.5 { | 200 do_execsql_test indexedby-7.5 { |
180 EQP { DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10} | 201 EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10 |
181 } {0 0 {TABLE t1 WITH INDEX i2}} | 202 } {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}} |
182 do_test indexedby-7.6 { | 203 do_test indexedby-7.6 { |
183 catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5} | 204 catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5} |
184 } {1 {cannot use index: i2}} | 205 } {1 {cannot use index: i2}} |
185 | 206 |
186 # Test that "INDEXED BY" can be used in an UPDATE statement. | 207 # Test that "INDEXED BY" can be used in an UPDATE statement. |
187 # | 208 # |
188 do_test indexedby-8.1 { | 209 do_execsql_test indexedby-8.1 { |
189 EQP { UPDATE t1 SET rowid=rowid+1 WHERE a = 5 } | 210 EXPLAIN QUERY PLAN UPDATE t1 SET rowid=rowid+1 WHERE a = 5 |
190 } {0 0 {TABLE t1 WITH INDEX i1}} | 211 } {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}} |
191 do_test indexedby-8.2 { | 212 do_execsql_test indexedby-8.2 { |
192 EQP { UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 } | 213 EXPLAIN QUERY PLAN UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 |
193 } {0 0 {TABLE t1}} | 214 } {0 0 0 {SCAN TABLE t1 (~100000 rows)}} |
194 do_test indexedby-8.3 { | 215 do_execsql_test indexedby-8.3 { |
195 EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 } | 216 EXPLAIN QUERY PLAN UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 |
196 } {0 0 {TABLE t1 WITH INDEX i1}} | 217 } {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}} |
197 do_test indexedby-8.4 { | 218 do_execsql_test indexedby-8.4 { |
198 EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10} | 219 EXPLAIN QUERY PLAN |
199 } {0 0 {TABLE t1 WITH INDEX i1}} | 220 UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10 |
200 do_test indexedby-8.5 { | 221 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}} |
201 EQP { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10} | 222 do_execsql_test indexedby-8.5 { |
202 } {0 0 {TABLE t1 WITH INDEX i2}} | 223 EXPLAIN QUERY PLAN |
| 224 UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10 |
| 225 } {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}} |
203 do_test indexedby-8.6 { | 226 do_test indexedby-8.6 { |
204 catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5} | 227 catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5} |
205 } {1 {cannot use index: i2}} | 228 } {1 {cannot use index: i2}} |
206 | 229 |
207 # Test that bug #3560 is fixed. | 230 # Test that bug #3560 is fixed. |
208 # | 231 # |
209 do_test indexedby-9.1 { | 232 do_test indexedby-9.1 { |
210 execsql { | 233 execsql { |
211 CREATE TABLE maintable( id integer); | 234 CREATE TABLE maintable( id integer); |
212 CREATE TABLE joinme(id_int integer, id_text text); | 235 CREATE TABLE joinme(id_int integer, id_text text); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 execsql { | 268 execsql { |
246 DROP TABLE indexed; | 269 DROP TABLE indexed; |
247 CREATE TABLE t10(indexed INTEGER); | 270 CREATE TABLE t10(indexed INTEGER); |
248 INSERT INTO t10 VALUES(1); | 271 INSERT INTO t10 VALUES(1); |
249 CREATE INDEX indexed ON t10(indexed); | 272 CREATE INDEX indexed ON t10(indexed); |
250 SELECT * FROM t10 indexed by indexed WHERE indexed>0 | 273 SELECT * FROM t10 indexed by indexed WHERE indexed>0 |
251 } | 274 } |
252 } {1} | 275 } {1} |
253 | 276 |
254 finish_test | 277 finish_test |
OLD | NEW |