|
1 # 2001 September 15 |
|
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 # This file implements regression tests for SQLite library. The |
|
12 # focus of this script is page cache subsystem. |
|
13 # |
|
14 # $Id: collate3.test,v 1.13 2008/08/20 16:35:10 drh Exp $ |
|
15 |
|
16 set testdir [file dirname $argv0] |
|
17 source $testdir/tester.tcl |
|
18 |
|
19 # |
|
20 # Tests are organised as follows: |
|
21 # |
|
22 # collate3.1.* - Errors related to unknown collation sequences. |
|
23 # collate3.2.* - Errors related to undefined collation sequences. |
|
24 # collate3.3.* - Writing to a table that has an index with an undefined c.s. |
|
25 # collate3.4.* - Misc errors. |
|
26 # collate3.5.* - Collation factory. |
|
27 # |
|
28 |
|
29 # |
|
30 # These tests ensure that when a user executes a statement with an |
|
31 # unknown collation sequence an error is returned. |
|
32 # |
|
33 do_test collate3-1.0 { |
|
34 execsql { |
|
35 CREATE TABLE collate3t1(c1); |
|
36 } |
|
37 } {} |
|
38 do_test collate3-1.1 { |
|
39 catchsql { |
|
40 SELECT * FROM collate3t1 ORDER BY 1 collate garbage; |
|
41 } |
|
42 } {1 {no such collation sequence: garbage}} |
|
43 do_test collate3-1.2 { |
|
44 catchsql { |
|
45 CREATE TABLE collate3t2(c1 collate garbage); |
|
46 } |
|
47 } {1 {no such collation sequence: garbage}} |
|
48 do_test collate3-1.3 { |
|
49 catchsql { |
|
50 CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage); |
|
51 } |
|
52 } {1 {no such collation sequence: garbage}} |
|
53 |
|
54 execsql { |
|
55 DROP TABLE collate3t1; |
|
56 } |
|
57 |
|
58 # |
|
59 # Create a table with a default collation sequence, then close |
|
60 # and re-open the database without re-registering the collation |
|
61 # sequence. Then make sure the library stops us from using |
|
62 # the collation sequence in: |
|
63 # * an explicitly collated ORDER BY |
|
64 # * an ORDER BY that uses the default collation sequence |
|
65 # * an expression (=) |
|
66 # * a CREATE TABLE statement |
|
67 # * a CREATE INDEX statement that uses a default collation sequence |
|
68 # * a GROUP BY that uses the default collation sequence |
|
69 # * a SELECT DISTINCT that uses the default collation sequence |
|
70 # * Compound SELECTs that uses the default collation sequence |
|
71 # * An ORDER BY on a compound SELECT with an explicit ORDER BY. |
|
72 # |
|
73 do_test collate3-2.0 { |
|
74 db collate string_compare {string compare} |
|
75 execsql { |
|
76 CREATE TABLE collate3t1(c1 COLLATE string_compare, c2); |
|
77 } |
|
78 db close |
|
79 sqlite3 db test.db |
|
80 expr 0 |
|
81 } 0 |
|
82 do_test collate3-2.1 { |
|
83 catchsql { |
|
84 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare; |
|
85 } |
|
86 } {1 {no such collation sequence: string_compare}} |
|
87 do_test collate3-2.2 { |
|
88 catchsql { |
|
89 SELECT * FROM collate3t1 ORDER BY c1; |
|
90 } |
|
91 } {1 {no such collation sequence: string_compare}} |
|
92 do_test collate3-2.3 { |
|
93 catchsql { |
|
94 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; |
|
95 } |
|
96 } {1 {no such collation sequence: string_compare}} |
|
97 do_test collate3-2.4 { |
|
98 catchsql { |
|
99 CREATE TABLE collate3t2(c1 COLLATE string_compare); |
|
100 } |
|
101 } {1 {no such collation sequence: string_compare}} |
|
102 do_test collate3-2.5 { |
|
103 catchsql { |
|
104 CREATE INDEX collate3t1_i1 ON collate3t1(c1); |
|
105 } |
|
106 } {1 {no such collation sequence: string_compare}} |
|
107 do_test collate3-2.6 { |
|
108 catchsql { |
|
109 SELECT * FROM collate3t1; |
|
110 } |
|
111 } {0 {}} |
|
112 do_test collate3-2.7.1 { |
|
113 catchsql { |
|
114 SELECT count(*) FROM collate3t1 GROUP BY c1; |
|
115 } |
|
116 } {1 {no such collation sequence: string_compare}} |
|
117 # do_test collate3-2.7.2 { |
|
118 # catchsql { |
|
119 # SELECT * FROM collate3t1 GROUP BY c1; |
|
120 # } |
|
121 # } {1 {GROUP BY may only be used on aggregate queries}} |
|
122 do_test collate3-2.7.2 { |
|
123 catchsql { |
|
124 SELECT * FROM collate3t1 GROUP BY c1; |
|
125 } |
|
126 } {1 {no such collation sequence: string_compare}} |
|
127 do_test collate3-2.8 { |
|
128 catchsql { |
|
129 SELECT DISTINCT c1 FROM collate3t1; |
|
130 } |
|
131 } {1 {no such collation sequence: string_compare}} |
|
132 |
|
133 ifcapable compound { |
|
134 do_test collate3-2.9 { |
|
135 catchsql { |
|
136 SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1; |
|
137 } |
|
138 } {1 {no such collation sequence: string_compare}} |
|
139 do_test collate3-2.10 { |
|
140 catchsql { |
|
141 SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1; |
|
142 } |
|
143 } {1 {no such collation sequence: string_compare}} |
|
144 do_test collate3-2.11 { |
|
145 catchsql { |
|
146 SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1; |
|
147 } |
|
148 } {1 {no such collation sequence: string_compare}} |
|
149 do_test collate3-2.12 { |
|
150 catchsql { |
|
151 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1; |
|
152 } |
|
153 } {0 {}} |
|
154 do_test collate3-2.13 { |
|
155 catchsql { |
|
156 SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare; |
|
157 } |
|
158 } {1 {no such collation sequence: string_compare}} |
|
159 do_test collate3-2.14 { |
|
160 catchsql { |
|
161 SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare; |
|
162 } |
|
163 } {1 {no such collation sequence: string_compare}} |
|
164 do_test collate3-2.15 { |
|
165 catchsql { |
|
166 SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare; |
|
167 } |
|
168 } {1 {no such collation sequence: string_compare}} |
|
169 do_test collate3-2.16 { |
|
170 catchsql { |
|
171 SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare; |
|
172 } |
|
173 } {1 {no such collation sequence: string_compare}} |
|
174 do_test collate3-2.17 { |
|
175 catchsql { |
|
176 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1; |
|
177 } |
|
178 } {1 {no such collation sequence: string_compare}} |
|
179 } ;# ifcapable compound |
|
180 |
|
181 # |
|
182 # Create an index that uses a collation sequence then close and |
|
183 # re-open the database without re-registering the collation |
|
184 # sequence. Then check that for the table with the index |
|
185 # * An INSERT fails, |
|
186 # * An UPDATE on the column with the index fails, |
|
187 # * An UPDATE on a different column succeeds. |
|
188 # * A DELETE with a WHERE clause fails |
|
189 # * A DELETE without a WHERE clause succeeds |
|
190 # |
|
191 # Also, ensure that the restrictions tested by collate3-2.* still |
|
192 # apply after the index has been created. |
|
193 # |
|
194 do_test collate3-3.0 { |
|
195 db collate string_compare {string compare} |
|
196 execsql { |
|
197 CREATE INDEX collate3t1_i1 ON collate3t1(c1); |
|
198 INSERT INTO collate3t1 VALUES('xxx', 'yyy'); |
|
199 } |
|
200 db close |
|
201 sqlite3 db test.db |
|
202 expr 0 |
|
203 } 0 |
|
204 db eval {select * from collate3t1} |
|
205 do_test collate3-3.1 { |
|
206 catchsql { |
|
207 INSERT INTO collate3t1 VALUES('xxx', 0); |
|
208 } |
|
209 } {1 {no such collation sequence: string_compare}} |
|
210 do_test collate3-3.2 { |
|
211 catchsql { |
|
212 UPDATE collate3t1 SET c1 = 'xxx'; |
|
213 } |
|
214 } {1 {no such collation sequence: string_compare}} |
|
215 do_test collate3-3.3 { |
|
216 catchsql { |
|
217 UPDATE collate3t1 SET c2 = 'xxx'; |
|
218 } |
|
219 } {0 {}} |
|
220 do_test collate3-3.4 { |
|
221 catchsql { |
|
222 DELETE FROM collate3t1 WHERE 1; |
|
223 } |
|
224 } {1 {no such collation sequence: string_compare}} |
|
225 do_test collate3-3.5 { |
|
226 catchsql { |
|
227 SELECT * FROM collate3t1; |
|
228 } |
|
229 } {0 {xxx xxx}} |
|
230 do_test collate3-3.6 { |
|
231 catchsql { |
|
232 DELETE FROM collate3t1; |
|
233 } |
|
234 } {0 {}} |
|
235 ifcapable {integrityck} { |
|
236 do_test collate3-3.8 { |
|
237 catchsql { |
|
238 PRAGMA integrity_check |
|
239 } |
|
240 } {1 {no such collation sequence: string_compare}} |
|
241 } |
|
242 do_test collate3-3.9 { |
|
243 catchsql { |
|
244 SELECT * FROM collate3t1; |
|
245 } |
|
246 } {0 {}} |
|
247 do_test collate3-3.10 { |
|
248 catchsql { |
|
249 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare; |
|
250 } |
|
251 } {1 {no such collation sequence: string_compare}} |
|
252 do_test collate3-3.11 { |
|
253 catchsql { |
|
254 SELECT * FROM collate3t1 ORDER BY c1; |
|
255 } |
|
256 } {1 {no such collation sequence: string_compare}} |
|
257 do_test collate3-3.12 { |
|
258 catchsql { |
|
259 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; |
|
260 } |
|
261 } {1 {no such collation sequence: string_compare}} |
|
262 do_test collate3-3.13 { |
|
263 catchsql { |
|
264 CREATE TABLE collate3t2(c1 COLLATE string_compare); |
|
265 } |
|
266 } {1 {no such collation sequence: string_compare}} |
|
267 do_test collate3-3.14 { |
|
268 catchsql { |
|
269 CREATE INDEX collate3t1_i2 ON collate3t1(c1); |
|
270 } |
|
271 } {1 {no such collation sequence: string_compare}} |
|
272 do_test collate3-3.15 { |
|
273 execsql { |
|
274 DROP TABLE collate3t1; |
|
275 } |
|
276 } {} |
|
277 |
|
278 # Check we can create an index that uses an explicit collation |
|
279 # sequence and then close and re-open the database. |
|
280 do_test collate3-4.6 { |
|
281 db collate user_defined "string compare" |
|
282 execsql { |
|
283 CREATE TABLE collate3t1(a, b); |
|
284 INSERT INTO collate3t1 VALUES('hello', NULL); |
|
285 CREATE INDEX collate3i1 ON collate3t1(a COLLATE user_defined); |
|
286 } |
|
287 } {} |
|
288 do_test collate3-4.7 { |
|
289 db close |
|
290 sqlite3 db test.db |
|
291 catchsql { |
|
292 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; |
|
293 } |
|
294 } {1 {no such collation sequence: user_defined}} |
|
295 do_test collate3-4.8.1 { |
|
296 db collate user_defined "string compare" |
|
297 catchsql { |
|
298 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; |
|
299 } |
|
300 } {0 {hello {}}} |
|
301 do_test collate3-4.8.2 { |
|
302 db close |
|
303 lindex [catch { |
|
304 sqlite3 db test.db |
|
305 }] 0 |
|
306 } {0} |
|
307 do_test collate3-4.8.3 { |
|
308 execsql { |
|
309 DROP TABLE collate3t1; |
|
310 } |
|
311 } {} |
|
312 |
|
313 # Compare strings as numbers. |
|
314 proc numeric_compare {lhs rhs} { |
|
315 if {$rhs > $lhs} { |
|
316 set res -1 |
|
317 } else { |
|
318 set res [expr ($lhs > $rhs)?1:0] |
|
319 } |
|
320 return $res |
|
321 } |
|
322 |
|
323 # Check we can create a view that uses an explicit collation |
|
324 # sequence and then close and re-open the database. |
|
325 ifcapable view { |
|
326 do_test collate3-4.9 { |
|
327 db collate user_defined numeric_compare |
|
328 execsql { |
|
329 CREATE TABLE collate3t1(a, b); |
|
330 INSERT INTO collate3t1 VALUES('2', NULL); |
|
331 INSERT INTO collate3t1 VALUES('101', NULL); |
|
332 INSERT INTO collate3t1 VALUES('12', NULL); |
|
333 CREATE VIEW collate3v1 AS SELECT * FROM collate3t1 |
|
334 ORDER BY 1 COLLATE user_defined; |
|
335 SELECT * FROM collate3v1; |
|
336 } |
|
337 } {2 {} 12 {} 101 {}} |
|
338 do_test collate3-4.10 { |
|
339 db close |
|
340 sqlite3 db test.db |
|
341 catchsql { |
|
342 SELECT * FROM collate3v1; |
|
343 } |
|
344 } {1 {no such collation sequence: user_defined}} |
|
345 do_test collate3-4.11 { |
|
346 db collate user_defined numeric_compare |
|
347 catchsql { |
|
348 SELECT * FROM collate3v1; |
|
349 } |
|
350 } {0 {2 {} 12 {} 101 {}}} |
|
351 do_test collate3-4.12 { |
|
352 execsql { |
|
353 DROP TABLE collate3t1; |
|
354 } |
|
355 } {} |
|
356 } ;# ifcapable view |
|
357 |
|
358 # |
|
359 # Test the collation factory. In the code, the "no such collation sequence" |
|
360 # message is only generated in two places. So these tests just test that |
|
361 # the collation factory can be called once from each of those points. |
|
362 # |
|
363 do_test collate3-5.0 { |
|
364 catchsql { |
|
365 CREATE TABLE collate3t1(a); |
|
366 INSERT INTO collate3t1 VALUES(10); |
|
367 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; |
|
368 } |
|
369 } {1 {no such collation sequence: unk}} |
|
370 do_test collate3-5.1 { |
|
371 set ::cfact_cnt 0 |
|
372 proc cfact {nm} { |
|
373 db collate $nm {string compare} |
|
374 incr ::cfact_cnt |
|
375 } |
|
376 db collation_needed cfact |
|
377 } {} |
|
378 do_test collate3-5.2 { |
|
379 catchsql { |
|
380 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; |
|
381 } |
|
382 } {0 10} |
|
383 do_test collate3-5.3 { |
|
384 set ::cfact_cnt |
|
385 } {1} |
|
386 do_test collate3-5.4 { |
|
387 catchsql { |
|
388 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; |
|
389 } |
|
390 } {0 10} |
|
391 do_test collate3-5.5 { |
|
392 set ::cfact_cnt |
|
393 } {1} |
|
394 do_test collate3-5.6 { |
|
395 catchsql { |
|
396 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; |
|
397 } |
|
398 } {0 10} |
|
399 do_test collate3-5.7 { |
|
400 execsql { |
|
401 DROP TABLE collate3t1; |
|
402 CREATE TABLE collate3t1(a COLLATE unk); |
|
403 } |
|
404 db close |
|
405 sqlite3 db test.db |
|
406 catchsql { |
|
407 SELECT a FROM collate3t1 ORDER BY 1; |
|
408 } |
|
409 } {1 {no such collation sequence: unk}} |
|
410 do_test collate3-5.8 { |
|
411 set ::cfact_cnt 0 |
|
412 proc cfact {nm} { |
|
413 db collate $nm {string compare} |
|
414 incr ::cfact_cnt |
|
415 } |
|
416 db collation_needed cfact |
|
417 catchsql { |
|
418 SELECT a FROM collate3t1 ORDER BY 1; |
|
419 } |
|
420 } {0 {}} |
|
421 |
|
422 do_test collate3-5.9 { |
|
423 execsql { |
|
424 DROP TABLE collate3t1; |
|
425 } |
|
426 } {} |
|
427 |
|
428 finish_test |