3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this script is page cache subsystem.
14 # $Id: collate3.test,v 1.13 2008/08/20 16:35:10 drh Exp $
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
20 # Tests are organised as follows:
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.
30 # These tests ensure that when a user executes a statement with an
31 # unknown collation sequence an error is returned.
33 do_test collate3-1.0 {
35 CREATE TABLE collate3t1(c1);
38 do_test collate3-1.1 {
40 SELECT * FROM collate3t1 ORDER BY 1 collate garbage;
42 } {1 {no such collation sequence: garbage}}
43 do_test collate3-1.2 {
45 CREATE TABLE collate3t2(c1 collate garbage);
47 } {1 {no such collation sequence: garbage}}
48 do_test collate3-1.3 {
50 CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage);
52 } {1 {no such collation sequence: garbage}}
55 DROP TABLE collate3t1;
58 proc caseless {a b} { string compare -nocase $a $b }
59 do_test collate3-1.4 {
60 db collate caseless caseless
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');
67 execsql { SELECT * FROM t1 ORDER BY a }
70 do_test collate3-1.5 {
73 catchsql { SELECT * FROM t1 ORDER BY a }
74 } {1 {no such collation sequence: caseless}}
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 }
82 do_test collate3-1.6.2 {
85 catchsql { SELECT * FROM t1 ORDER BY a }
86 } {1 {no such collation sequence: caseless}}
88 do_test collate3-1.6.3 {
91 catchsql { PRAGMA integrity_check }
92 } {1 {no such collation sequence: caseless}}
94 do_test collate3-1.6.4 {
98 } {1 {no such collation sequence: caseless}}
100 do_test collate3-1.7.1 {
101 db collate caseless caseless
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;
113 do_test collate3-1.7.2 {
116 catchsql { SELECT * FROM t1 ORDER BY a COLLATE caseless}
117 } {1 {no such collation sequence: caseless}}
119 do_test collate3-1.7.4 {
123 } {1 {no such collation sequence: caseless}}
125 do_test collate3-1.7.3 {
128 catchsql { PRAGMA integrity_check }
129 } {1 {no such collation sequence: caseless}}
131 do_test collate3-1.7.4 {
135 } {1 {no such collation sequence: caseless}}
137 do_test collate3-1.7.5 {
140 db collate caseless caseless
141 catchsql { PRAGMA integrity_check }
144 proc needed {nm} { db collate caseless caseless }
145 do_test collate3-1.7.6 {
148 db collation_needed needed
149 catchsql { PRAGMA integrity_check }
152 do_test collate3-1.8 {
153 execsql { DROP TABLE t1 }
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.
171 do_test collate3-2.0 {
172 db collate string_compare {string compare}
174 CREATE TABLE collate3t1(c1 COLLATE string_compare, c2);
180 do_test collate3-2.1 {
182 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare;
184 } {1 {no such collation sequence: string_compare}}
185 do_test collate3-2.2 {
187 SELECT * FROM collate3t1 ORDER BY c1;
189 } {1 {no such collation sequence: string_compare}}
190 do_test collate3-2.3 {
192 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
194 } {1 {no such collation sequence: string_compare}}
195 do_test collate3-2.4 {
197 CREATE TABLE collate3t2(c1 COLLATE string_compare);
199 } {1 {no such collation sequence: string_compare}}
200 do_test collate3-2.5 {
202 CREATE INDEX collate3t1_i1 ON collate3t1(c1);
204 } {1 {no such collation sequence: string_compare}}
205 do_test collate3-2.6 {
207 SELECT * FROM collate3t1;
210 do_test collate3-2.7.1 {
212 SELECT count(*) FROM collate3t1 GROUP BY c1;
214 } {1 {no such collation sequence: string_compare}}
215 # do_test collate3-2.7.2 {
217 # SELECT * FROM collate3t1 GROUP BY c1;
219 # } {1 {GROUP BY may only be used on aggregate queries}}
220 do_test collate3-2.7.2 {
222 SELECT * FROM collate3t1 GROUP BY c1;
224 } {1 {no such collation sequence: string_compare}}
225 do_test collate3-2.8 {
227 SELECT DISTINCT c1 FROM collate3t1;
229 } {1 {no such collation sequence: string_compare}}
232 do_test collate3-2.9 {
234 SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1;
236 } {1 {no such collation sequence: string_compare}}
237 do_test collate3-2.10 {
239 SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1;
241 } {1 {no such collation sequence: string_compare}}
242 do_test collate3-2.11 {
244 SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1;
246 } {1 {no such collation sequence: string_compare}}
247 do_test collate3-2.12 {
249 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1;
252 do_test collate3-2.13 {
254 SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare;
256 } {1 {no such collation sequence: string_compare}}
257 do_test collate3-2.14 {
259 SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare;
261 } {1 {no such collation sequence: string_compare}}
262 do_test collate3-2.15 {
264 SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare;
266 } {1 {no such collation sequence: string_compare}}
267 do_test collate3-2.16 {
269 SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare;
271 } {1 {no such collation sequence: string_compare}}
272 do_test collate3-2.17 {
274 SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1;
276 } {1 {no such collation sequence: string_compare}}
277 } ;# ifcapable compound
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
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
289 # Also, ensure that the restrictions tested by collate3-2.* still
290 # apply after the index has been created.
292 do_test collate3-3.0 {
293 db collate string_compare {string compare}
295 CREATE INDEX collate3t1_i1 ON collate3t1(c1);
296 INSERT INTO collate3t1 VALUES('xxx', 'yyy');
302 db eval {select * from collate3t1}
303 do_test collate3-3.1 {
305 INSERT INTO collate3t1 VALUES('xxx', 0);
307 } {1 {no such collation sequence: string_compare}}
308 do_test collate3-3.2 {
310 UPDATE collate3t1 SET c1 = 'xxx';
312 } {1 {no such collation sequence: string_compare}}
313 do_test collate3-3.3 {
315 UPDATE collate3t1 SET c2 = 'xxx';
318 do_test collate3-3.4 {
320 DELETE FROM collate3t1 WHERE 1;
322 } {1 {no such collation sequence: string_compare}}
323 do_test collate3-3.5 {
325 SELECT * FROM collate3t1;
328 do_test collate3-3.6 {
330 DELETE FROM collate3t1;
333 ifcapable {integrityck} {
334 do_test collate3-3.8 {
336 PRAGMA integrity_check
338 } {1 {no such collation sequence: string_compare}}
340 do_test collate3-3.9 {
342 SELECT * FROM collate3t1;
345 do_test collate3-3.10 {
347 SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare;
349 } {1 {no such collation sequence: string_compare}}
350 do_test collate3-3.11 {
352 SELECT * FROM collate3t1 ORDER BY c1;
354 } {1 {no such collation sequence: string_compare}}
355 do_test collate3-3.12 {
357 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
359 } {1 {no such collation sequence: string_compare}}
360 do_test collate3-3.13 {
362 CREATE TABLE collate3t2(c1 COLLATE string_compare);
364 } {1 {no such collation sequence: string_compare}}
365 do_test collate3-3.14 {
367 CREATE INDEX collate3t1_i2 ON collate3t1(c1);
369 } {1 {no such collation sequence: string_compare}}
370 do_test collate3-3.15 {
372 DROP TABLE collate3t1;
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"
381 CREATE TABLE collate3t1(a, b);
382 INSERT INTO collate3t1 VALUES('hello', NULL);
383 CREATE INDEX collate3i1 ON collate3t1(a COLLATE user_defined);
386 do_test collate3-4.7 {
390 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
392 } {1 {no such collation sequence: user_defined}}
393 do_test collate3-4.8.1 {
394 db collate user_defined "string compare"
396 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
399 do_test collate3-4.8.2 {
405 do_test collate3-4.8.3 {
407 DROP TABLE collate3t1;
411 # Compare strings as numbers.
412 proc numeric_compare {lhs rhs} {
416 set res [expr ($lhs > $rhs)?1:0]
421 # Check we can create a view that uses an explicit collation
422 # sequence and then close and re-open the database.
424 do_test collate3-4.9 {
425 db collate user_defined numeric_compare
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;
435 } {2 {} 12 {} 101 {}}
436 do_test collate3-4.10 {
440 SELECT * FROM collate3v1;
442 } {1 {no such collation sequence: user_defined}}
443 do_test collate3-4.11 {
444 db collate user_defined numeric_compare
446 SELECT * FROM collate3v1;
448 } {0 {2 {} 12 {} 101 {}}}
449 do_test collate3-4.12 {
451 DROP TABLE collate3t1;
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.
461 do_test collate3-5.0 {
463 CREATE TABLE collate3t1(a);
464 INSERT INTO collate3t1 VALUES(10);
465 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
467 } {1 {no such collation sequence: unk}}
468 do_test collate3-5.1 {
471 db collate $nm {string compare}
474 db collation_needed cfact
476 do_test collate3-5.2 {
478 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
481 do_test collate3-5.3 {
484 do_test collate3-5.4 {
486 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
489 do_test collate3-5.5 {
492 do_test collate3-5.6 {
494 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
497 do_test collate3-5.7 {
499 DROP TABLE collate3t1;
500 CREATE TABLE collate3t1(a COLLATE unk);
505 SELECT a FROM collate3t1 ORDER BY 1;
507 } {1 {no such collation sequence: unk}}
508 do_test collate3-5.8 {
511 db collate $nm {string compare}
514 db collation_needed cfact
516 SELECT a FROM collate3t1 ORDER BY 1;
520 do_test collate3-5.9 {
522 DROP TABLE collate3t1;