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