OLD | NEW |
| (Empty) |
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 proc caseless {a b} { string compare -nocase $a $b } | |
59 do_test collate3-1.4 { | |
60 db collate caseless caseless | |
61 execsql { | |
62 CREATE TABLE t1(a COLLATE caseless); | |
63 INSERT INTO t1 VALUES('Abc2'); | |
64 INSERT INTO t1 VALUES('abc1'); | |
65 INSERT INTO t1 VALUES('aBc3'); | |
66 } | |
67 execsql { SELECT * FROM t1 ORDER BY a } | |
68 } {abc1 Abc2 aBc3} | |
69 | |
70 do_test collate3-1.5 { | |
71 db close | |
72 sqlite3 db test.db | |
73 catchsql { SELECT * FROM t1 ORDER BY a } | |
74 } {1 {no such collation sequence: caseless}} | |
75 | |
76 do_test collate3-1.6.1 { | |
77 db collate caseless caseless | |
78 execsql { CREATE INDEX i1 ON t1(a) } | |
79 execsql { SELECT * FROM t1 ORDER BY a } | |
80 } {abc1 Abc2 aBc3} | |
81 | |
82 do_test collate3-1.6.2 { | |
83 db close | |
84 sqlite3 db test.db | |
85 catchsql { SELECT * FROM t1 ORDER BY a } | |
86 } {1 {no such collation sequence: caseless}} | |
87 | |
88 do_test collate3-1.6.3 { | |
89 db close | |
90 sqlite3 db test.db | |
91 catchsql { PRAGMA integrity_check } | |
92 } {1 {no such collation sequence: caseless}} | |
93 | |
94 do_test collate3-1.6.4 { | |
95 db close | |
96 sqlite3 db test.db | |
97 catchsql { REINDEX } | |
98 } {1 {no such collation sequence: caseless}} | |
99 | |
100 do_test collate3-1.7.1 { | |
101 db collate caseless caseless | |
102 execsql { | |
103 DROP TABLE t1; | |
104 CREATE TABLE t1(a); | |
105 CREATE INDEX i1 ON t1(a COLLATE caseless); | |
106 INSERT INTO t1 VALUES('Abc2'); | |
107 INSERT INTO t1 VALUES('abc1'); | |
108 INSERT INTO t1 VALUES('aBc3'); | |
109 SELECT * FROM t1 ORDER BY a COLLATE caseless; | |
110 } | |
111 } {abc1 Abc2 aBc3} | |
112 | |
113 do_test collate3-1.7.2 { | |
114 db close | |
115 sqlite3 db test.db | |
116 catchsql { SELECT * FROM t1 ORDER BY a COLLATE caseless} | |
117 } {1 {no such collation sequence: caseless}} | |
118 | |
119 do_test collate3-1.7.4 { | |
120 db close | |
121 sqlite3 db test.db | |
122 catchsql { REINDEX } | |
123 } {1 {no such collation sequence: caseless}} | |
124 | |
125 do_test collate3-1.7.3 { | |
126 db close | |
127 sqlite3 db test.db | |
128 catchsql { PRAGMA integrity_check } | |
129 } {1 {no such collation sequence: caseless}} | |
130 | |
131 do_test collate3-1.7.4 { | |
132 db close | |
133 sqlite3 db test.db | |
134 catchsql { REINDEX } | |
135 } {1 {no such collation sequence: caseless}} | |
136 | |
137 do_test collate3-1.7.5 { | |
138 db close | |
139 sqlite3 db test.db | |
140 db collate caseless caseless | |
141 catchsql { PRAGMA integrity_check } | |
142 } {0 ok} | |
143 | |
144 proc needed {nm} { db collate caseless caseless } | |
145 do_test collate3-1.7.6 { | |
146 db close | |
147 sqlite3 db test.db | |
148 db collation_needed needed | |
149 catchsql { PRAGMA integrity_check } | |
150 } {0 ok} | |
151 | |
152 do_test collate3-1.8 { | |
153 execsql { DROP TABLE t1 } | |
154 } {} | |
155 | |
156 # | |
157 # Create a table with a default collation sequence, then close | |
158 # and re-open the database without re-registering the collation | |
159 # sequence. Then make sure the library stops us from using | |
160 # the collation sequence in: | |
161 # * an explicitly collated ORDER BY | |
162 # * an ORDER BY that uses the default collation sequence | |
163 # * an expression (=) | |
164 # * a CREATE TABLE statement | |
165 # * a CREATE INDEX statement that uses a default collation sequence | |
166 # * a GROUP BY that uses the default collation sequence | |
167 # * a SELECT DISTINCT that uses the default collation sequence | |
168 # * Compound SELECTs that uses the default collation sequence | |
169 # * An ORDER BY on a compound SELECT with an explicit ORDER BY. | |
170 # | |
171 do_test collate3-2.0 { | |
172 db collate string_compare {string compare} | |
173 execsql { | |
174 CREATE TABLE collate3t1(c1 COLLATE string_compare, c2); | |
175 } | |
176 db close | |
177 sqlite3 db test.db | |
178 expr 0 | |
179 } 0 | |
180 do_test collate3-2.1 { | |
181 catchsql { | |
182 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare; | |
183 } | |
184 } {1 {no such collation sequence: string_compare}} | |
185 do_test collate3-2.2 { | |
186 catchsql { | |
187 SELECT * FROM collate3t1 ORDER BY c1; | |
188 } | |
189 } {1 {no such collation sequence: string_compare}} | |
190 do_test collate3-2.3 { | |
191 catchsql { | |
192 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; | |
193 } | |
194 } {1 {no such collation sequence: string_compare}} | |
195 do_test collate3-2.4 { | |
196 catchsql { | |
197 CREATE TABLE collate3t2(c1 COLLATE string_compare); | |
198 } | |
199 } {1 {no such collation sequence: string_compare}} | |
200 do_test collate3-2.5 { | |
201 catchsql { | |
202 CREATE INDEX collate3t1_i1 ON collate3t1(c1); | |
203 } | |
204 } {1 {no such collation sequence: string_compare}} | |
205 do_test collate3-2.6 { | |
206 catchsql { | |
207 SELECT * FROM collate3t1; | |
208 } | |
209 } {0 {}} | |
210 do_test collate3-2.7.1 { | |
211 catchsql { | |
212 SELECT count(*) FROM collate3t1 GROUP BY c1; | |
213 } | |
214 } {1 {no such collation sequence: string_compare}} | |
215 # do_test collate3-2.7.2 { | |
216 # catchsql { | |
217 # SELECT * FROM collate3t1 GROUP BY c1; | |
218 # } | |
219 # } {1 {GROUP BY may only be used on aggregate queries}} | |
220 do_test collate3-2.7.2 { | |
221 catchsql { | |
222 SELECT * FROM collate3t1 GROUP BY c1; | |
223 } | |
224 } {1 {no such collation sequence: string_compare}} | |
225 do_test collate3-2.8 { | |
226 catchsql { | |
227 SELECT DISTINCT c1 FROM collate3t1; | |
228 } | |
229 } {1 {no such collation sequence: string_compare}} | |
230 | |
231 ifcapable compound { | |
232 do_test collate3-2.9 { | |
233 catchsql { | |
234 SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1; | |
235 } | |
236 } {1 {no such collation sequence: string_compare}} | |
237 do_test collate3-2.10 { | |
238 catchsql { | |
239 SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1; | |
240 } | |
241 } {1 {no such collation sequence: string_compare}} | |
242 do_test collate3-2.11 { | |
243 catchsql { | |
244 SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1; | |
245 } | |
246 } {1 {no such collation sequence: string_compare}} | |
247 do_test collate3-2.12 { | |
248 catchsql { | |
249 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1; | |
250 } | |
251 } {0 {}} | |
252 do_test collate3-2.13 { | |
253 catchsql { | |
254 SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare; | |
255 } | |
256 } {1 {no such collation sequence: string_compare}} | |
257 do_test collate3-2.14 { | |
258 catchsql { | |
259 SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare; | |
260 } | |
261 } {1 {no such collation sequence: string_compare}} | |
262 do_test collate3-2.15 { | |
263 catchsql { | |
264 SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare; | |
265 } | |
266 } {1 {no such collation sequence: string_compare}} | |
267 do_test collate3-2.16 { | |
268 catchsql { | |
269 SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare; | |
270 } | |
271 } {1 {no such collation sequence: string_compare}} | |
272 do_test collate3-2.17 { | |
273 catchsql { | |
274 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1; | |
275 } | |
276 } {1 {no such collation sequence: string_compare}} | |
277 } ;# ifcapable compound | |
278 | |
279 # | |
280 # Create an index that uses a collation sequence then close and | |
281 # re-open the database without re-registering the collation | |
282 # sequence. Then check that for the table with the index | |
283 # * An INSERT fails, | |
284 # * An UPDATE on the column with the index fails, | |
285 # * An UPDATE on a different column succeeds. | |
286 # * A DELETE with a WHERE clause fails | |
287 # * A DELETE without a WHERE clause succeeds | |
288 # | |
289 # Also, ensure that the restrictions tested by collate3-2.* still | |
290 # apply after the index has been created. | |
291 # | |
292 do_test collate3-3.0 { | |
293 db collate string_compare {string compare} | |
294 execsql { | |
295 CREATE INDEX collate3t1_i1 ON collate3t1(c1); | |
296 INSERT INTO collate3t1 VALUES('xxx', 'yyy'); | |
297 } | |
298 db close | |
299 sqlite3 db test.db | |
300 expr 0 | |
301 } 0 | |
302 db eval {select * from collate3t1} | |
303 do_test collate3-3.1 { | |
304 catchsql { | |
305 INSERT INTO collate3t1 VALUES('xxx', 0); | |
306 } | |
307 } {1 {no such collation sequence: string_compare}} | |
308 do_test collate3-3.2 { | |
309 catchsql { | |
310 UPDATE collate3t1 SET c1 = 'xxx'; | |
311 } | |
312 } {1 {no such collation sequence: string_compare}} | |
313 do_test collate3-3.3 { | |
314 catchsql { | |
315 UPDATE collate3t1 SET c2 = 'xxx'; | |
316 } | |
317 } {0 {}} | |
318 do_test collate3-3.4 { | |
319 catchsql { | |
320 DELETE FROM collate3t1 WHERE 1; | |
321 } | |
322 } {1 {no such collation sequence: string_compare}} | |
323 do_test collate3-3.5 { | |
324 catchsql { | |
325 SELECT * FROM collate3t1; | |
326 } | |
327 } {0 {xxx xxx}} | |
328 do_test collate3-3.6 { | |
329 catchsql { | |
330 DELETE FROM collate3t1; | |
331 } | |
332 } {0 {}} | |
333 ifcapable {integrityck} { | |
334 do_test collate3-3.8 { | |
335 catchsql { | |
336 PRAGMA integrity_check | |
337 } | |
338 } {1 {no such collation sequence: string_compare}} | |
339 } | |
340 do_test collate3-3.9 { | |
341 catchsql { | |
342 SELECT * FROM collate3t1; | |
343 } | |
344 } {0 {}} | |
345 do_test collate3-3.10 { | |
346 catchsql { | |
347 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare; | |
348 } | |
349 } {1 {no such collation sequence: string_compare}} | |
350 do_test collate3-3.11 { | |
351 catchsql { | |
352 SELECT * FROM collate3t1 ORDER BY c1; | |
353 } | |
354 } {1 {no such collation sequence: string_compare}} | |
355 do_test collate3-3.12 { | |
356 catchsql { | |
357 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; | |
358 } | |
359 } {1 {no such collation sequence: string_compare}} | |
360 do_test collate3-3.13 { | |
361 catchsql { | |
362 CREATE TABLE collate3t2(c1 COLLATE string_compare); | |
363 } | |
364 } {1 {no such collation sequence: string_compare}} | |
365 do_test collate3-3.14 { | |
366 catchsql { | |
367 CREATE INDEX collate3t1_i2 ON collate3t1(c1); | |
368 } | |
369 } {1 {no such collation sequence: string_compare}} | |
370 do_test collate3-3.15 { | |
371 execsql { | |
372 DROP TABLE collate3t1; | |
373 } | |
374 } {} | |
375 | |
376 # Check we can create an index that uses an explicit collation | |
377 # sequence and then close and re-open the database. | |
378 do_test collate3-4.6 { | |
379 db collate user_defined "string compare" | |
380 execsql { | |
381 CREATE TABLE collate3t1(a, b); | |
382 INSERT INTO collate3t1 VALUES('hello', NULL); | |
383 CREATE INDEX collate3i1 ON collate3t1(a COLLATE user_defined); | |
384 } | |
385 } {} | |
386 do_test collate3-4.7 { | |
387 db close | |
388 sqlite3 db test.db | |
389 catchsql { | |
390 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; | |
391 } | |
392 } {1 {no such collation sequence: user_defined}} | |
393 do_test collate3-4.8.1 { | |
394 db collate user_defined "string compare" | |
395 catchsql { | |
396 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; | |
397 } | |
398 } {0 {hello {}}} | |
399 do_test collate3-4.8.2 { | |
400 db close | |
401 lindex [catch { | |
402 sqlite3 db test.db | |
403 }] 0 | |
404 } {0} | |
405 do_test collate3-4.8.3 { | |
406 execsql { | |
407 DROP TABLE collate3t1; | |
408 } | |
409 } {} | |
410 | |
411 # Compare strings as numbers. | |
412 proc numeric_compare {lhs rhs} { | |
413 if {$rhs > $lhs} { | |
414 set res -1 | |
415 } else { | |
416 set res [expr ($lhs > $rhs)?1:0] | |
417 } | |
418 return $res | |
419 } | |
420 | |
421 # Check we can create a view that uses an explicit collation | |
422 # sequence and then close and re-open the database. | |
423 ifcapable view { | |
424 do_test collate3-4.9 { | |
425 db collate user_defined numeric_compare | |
426 execsql { | |
427 CREATE TABLE collate3t1(a, b); | |
428 INSERT INTO collate3t1 VALUES('2', NULL); | |
429 INSERT INTO collate3t1 VALUES('101', NULL); | |
430 INSERT INTO collate3t1 VALUES('12', NULL); | |
431 CREATE VIEW collate3v1 AS SELECT * FROM collate3t1 | |
432 ORDER BY 1 COLLATE user_defined; | |
433 SELECT * FROM collate3v1; | |
434 } | |
435 } {2 {} 12 {} 101 {}} | |
436 do_test collate3-4.10 { | |
437 db close | |
438 sqlite3 db test.db | |
439 catchsql { | |
440 SELECT * FROM collate3v1; | |
441 } | |
442 } {1 {no such collation sequence: user_defined}} | |
443 do_test collate3-4.11 { | |
444 db collate user_defined numeric_compare | |
445 catchsql { | |
446 SELECT * FROM collate3v1; | |
447 } | |
448 } {0 {2 {} 12 {} 101 {}}} | |
449 do_test collate3-4.12 { | |
450 execsql { | |
451 DROP TABLE collate3t1; | |
452 } | |
453 } {} | |
454 } ;# ifcapable view | |
455 | |
456 # | |
457 # Test the collation factory. In the code, the "no such collation sequence" | |
458 # message is only generated in two places. So these tests just test that | |
459 # the collation factory can be called once from each of those points. | |
460 # | |
461 do_test collate3-5.0 { | |
462 catchsql { | |
463 CREATE TABLE collate3t1(a); | |
464 INSERT INTO collate3t1 VALUES(10); | |
465 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; | |
466 } | |
467 } {1 {no such collation sequence: unk}} | |
468 do_test collate3-5.1 { | |
469 set ::cfact_cnt 0 | |
470 proc cfact {nm} { | |
471 db collate $nm {string compare} | |
472 incr ::cfact_cnt | |
473 } | |
474 db collation_needed cfact | |
475 } {} | |
476 do_test collate3-5.2 { | |
477 catchsql { | |
478 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; | |
479 } | |
480 } {0 10} | |
481 do_test collate3-5.3 { | |
482 set ::cfact_cnt | |
483 } {1} | |
484 do_test collate3-5.4 { | |
485 catchsql { | |
486 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; | |
487 } | |
488 } {0 10} | |
489 do_test collate3-5.5 { | |
490 set ::cfact_cnt | |
491 } {1} | |
492 do_test collate3-5.6 { | |
493 catchsql { | |
494 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; | |
495 } | |
496 } {0 10} | |
497 do_test collate3-5.7 { | |
498 execsql { | |
499 DROP TABLE collate3t1; | |
500 CREATE TABLE collate3t1(a COLLATE unk); | |
501 } | |
502 db close | |
503 sqlite3 db test.db | |
504 catchsql { | |
505 SELECT a FROM collate3t1 ORDER BY 1; | |
506 } | |
507 } {1 {no such collation sequence: unk}} | |
508 do_test collate3-5.8 { | |
509 set ::cfact_cnt 0 | |
510 proc cfact {nm} { | |
511 db collate $nm {string compare} | |
512 incr ::cfact_cnt | |
513 } | |
514 db collation_needed cfact | |
515 catchsql { | |
516 SELECT a FROM collate3t1 ORDER BY 1; | |
517 } | |
518 } {0 {}} | |
519 | |
520 do_test collate3-5.9 { | |
521 execsql { | |
522 DROP TABLE collate3t1; | |
523 } | |
524 } {} | |
525 | |
526 finish_test | |
OLD | NEW |