blob: 99640d05b89bee6539e7fb8754639a28fcbcc880 [file] [log] [blame]
danielk1977dc1bdc42004-06-11 10:51:27 +00001# 2001 September 15
danielk1977d2b65b92004-06-10 10:51:47 +00002#
danielk1977dc1bdc42004-06-11 10:51:27 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
danielk1977d2b65b92004-06-10 10:51:47 +00005#
danielk1977dc1bdc42004-06-11 10:51:27 +00006# 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.
danielk1977d2b65b92004-06-10 10:51:47 +00009#
danielk1977dc1bdc42004-06-11 10:51:27 +000010#***********************************************************************
11# This file implements regression tests for SQLite library. The
12# focus of this script is page cache subsystem.
13#
drh7d10d5a2008-08-20 16:35:10 +000014# $Id: collate3.test,v 1.13 2008/08/20 16:35:10 drh Exp $
danielk1977d2b65b92004-06-10 10:51:47 +000015
16set testdir [file dirname $argv0]
17source $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#
33do_test collate3-1.0 {
34 execsql {
drh65df68e2015-04-15 05:31:02 +000035 CREATE TABLE collate3t1(c1 UNIQUE);
danielk1977d2b65b92004-06-10 10:51:47 +000036 }
37} {}
38do_test collate3-1.1 {
39 catchsql {
40 SELECT * FROM collate3t1 ORDER BY 1 collate garbage;
41 }
42} {1 {no such collation sequence: garbage}}
drh65df68e2015-04-15 05:31:02 +000043do_test collate3-1.1.2 {
44 catchsql {
45 SELECT DISTINCT c1 COLLATE garbage FROM collate3t1;
46 }
47} {1 {no such collation sequence: garbage}}
danielk1977d2b65b92004-06-10 10:51:47 +000048do_test collate3-1.2 {
49 catchsql {
50 CREATE TABLE collate3t2(c1 collate garbage);
51 }
52} {1 {no such collation sequence: garbage}}
53do_test collate3-1.3 {
54 catchsql {
55 CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage);
56 }
57} {1 {no such collation sequence: garbage}}
58
59execsql {
60 DROP TABLE collate3t1;
61}
62
dan911ce412013-05-15 15:16:50 +000063proc caseless {a b} { string compare -nocase $a $b }
64do_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
75do_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
81do_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
87do_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
93do_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
99do_test collate3-1.6.4 {
100 db close
101 sqlite3 db test.db
102 catchsql { REINDEX }
103} {1 {no such collation sequence: caseless}}
104
105do_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
118do_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
124do_test collate3-1.7.4 {
125 db close
126 sqlite3 db test.db
127 catchsql { REINDEX }
128} {1 {no such collation sequence: caseless}}
129
130do_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
136do_test collate3-1.7.4 {
137 db close
138 sqlite3 db test.db
139 catchsql { REINDEX }
140} {1 {no such collation sequence: caseless}}
141
142do_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
dand58792e2013-05-15 16:24:46 +0000149proc needed {nm} { db collate caseless caseless }
dan911ce412013-05-15 15:16:50 +0000150do_test collate3-1.7.6 {
dand58792e2013-05-15 16:24:46 +0000151 db close
152 sqlite3 db test.db
153 db collation_needed needed
154 catchsql { PRAGMA integrity_check }
155} {0 ok}
156
157do_test collate3-1.8 {
dan911ce412013-05-15 15:16:50 +0000158 execsql { DROP TABLE t1 }
159} {}
160
danielk1977d2b65b92004-06-10 10:51:47 +0000161#
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#
176do_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
drhef4ac8f2004-06-19 00:16:31 +0000182 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000183 expr 0
184} 0
185do_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}}
190do_test collate3-2.2 {
191 catchsql {
192 SELECT * FROM collate3t1 ORDER BY c1;
193 }
194} {1 {no such collation sequence: string_compare}}
195do_test collate3-2.3 {
196 catchsql {
197 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
198 }
199} {1 {no such collation sequence: string_compare}}
200do_test collate3-2.4 {
201 catchsql {
202 CREATE TABLE collate3t2(c1 COLLATE string_compare);
203 }
204} {1 {no such collation sequence: string_compare}}
205do_test collate3-2.5 {
206 catchsql {
207 CREATE INDEX collate3t1_i1 ON collate3t1(c1);
208 }
209} {1 {no such collation sequence: string_compare}}
210do_test collate3-2.6 {
211 catchsql {
212 SELECT * FROM collate3t1;
213 }
214} {0 {}}
drh49d642d2005-01-03 02:26:54 +0000215do_test collate3-2.7.1 {
216 catchsql {
217 SELECT count(*) FROM collate3t1 GROUP BY c1;
218 }
219} {1 {no such collation sequence: string_compare}}
danielk1977e2573002005-01-26 03:58:35 +0000220# 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}}
drh49d642d2005-01-03 02:26:54 +0000225do_test collate3-2.7.2 {
danielk1977d2b65b92004-06-10 10:51:47 +0000226 catchsql {
227 SELECT * FROM collate3t1 GROUP BY c1;
228 }
danielk1977e2573002005-01-26 03:58:35 +0000229} {1 {no such collation sequence: string_compare}}
danielk1977d2b65b92004-06-10 10:51:47 +0000230do_test collate3-2.8 {
231 catchsql {
232 SELECT DISTINCT c1 FROM collate3t1;
233 }
234} {1 {no such collation sequence: string_compare}}
danielk1977dc1bdc42004-06-11 10:51:27 +0000235
danielk197727c77432004-11-22 13:35:41 +0000236ifcapable compound {
danielk1977b3bce662005-01-29 08:32:43 +0000237 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}}
danielk197727c77432004-11-22 13:35:41 +0000282} ;# ifcapable compound
danielk1977d2b65b92004-06-10 10:51:47 +0000283
danielk1977d2b65b92004-06-10 10:51:47 +0000284#
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#
297do_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
drhef4ac8f2004-06-19 00:16:31 +0000304 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000305 expr 0
306} 0
307db eval {select * from collate3t1}
danielk1977d2b65b92004-06-10 10:51:47 +0000308do_test collate3-3.1 {
309 catchsql {
310 INSERT INTO collate3t1 VALUES('xxx', 0);
311 }
312} {1 {no such collation sequence: string_compare}}
313do_test collate3-3.2 {
314 catchsql {
315 UPDATE collate3t1 SET c1 = 'xxx';
316 }
317} {1 {no such collation sequence: string_compare}}
318do_test collate3-3.3 {
319 catchsql {
320 UPDATE collate3t1 SET c2 = 'xxx';
321 }
322} {0 {}}
323do_test collate3-3.4 {
324 catchsql {
325 DELETE FROM collate3t1 WHERE 1;
326 }
327} {1 {no such collation sequence: string_compare}}
328do_test collate3-3.5 {
329 catchsql {
330 SELECT * FROM collate3t1;
331 }
332} {0 {xxx xxx}}
333do_test collate3-3.6 {
334 catchsql {
335 DELETE FROM collate3t1;
336 }
337} {0 {}}
drh40e016e2004-11-04 14:47:11 +0000338ifcapable {integrityck} {
339 do_test collate3-3.8 {
340 catchsql {
341 PRAGMA integrity_check
342 }
343 } {1 {no such collation sequence: string_compare}}
344}
danielk1977d2b65b92004-06-10 10:51:47 +0000345do_test collate3-3.9 {
346 catchsql {
347 SELECT * FROM collate3t1;
348 }
349} {0 {}}
350do_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}}
355do_test collate3-3.11 {
356 catchsql {
357 SELECT * FROM collate3t1 ORDER BY c1;
358 }
359} {1 {no such collation sequence: string_compare}}
360do_test collate3-3.12 {
361 catchsql {
362 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
363 }
364} {1 {no such collation sequence: string_compare}}
365do_test collate3-3.13 {
366 catchsql {
367 CREATE TABLE collate3t2(c1 COLLATE string_compare);
368 }
369} {1 {no such collation sequence: string_compare}}
370do_test collate3-3.14 {
371 catchsql {
372 CREATE INDEX collate3t1_i2 ON collate3t1(c1);
373 }
374} {1 {no such collation sequence: string_compare}}
375do_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.
383do_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} {}
391do_test collate3-4.7 {
392 db close
drhef4ac8f2004-06-19 00:16:31 +0000393 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000394 catchsql {
395 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
396 }
397} {1 {no such collation sequence: user_defined}}
drh7d10d5a2008-08-20 16:35:10 +0000398do_test collate3-4.8.1 {
danielk1977d2b65b92004-06-10 10:51:47 +0000399 db collate user_defined "string compare"
400 catchsql {
401 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
402 }
403} {0 {hello {}}}
drh7d10d5a2008-08-20 16:35:10 +0000404do_test collate3-4.8.2 {
danielk1977d2b65b92004-06-10 10:51:47 +0000405 db close
406 lindex [catch {
drhef4ac8f2004-06-19 00:16:31 +0000407 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000408 }] 0
409} {0}
drh7d10d5a2008-08-20 16:35:10 +0000410do_test collate3-4.8.3 {
danielk1977d2b65b92004-06-10 10:51:47 +0000411 execsql {
412 DROP TABLE collate3t1;
413 }
414} {}
415
416# Compare strings as numbers.
417proc 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.
danielk19770fa8ddb2004-11-22 08:43:32 +0000428ifcapable view {
danielk1977d2b65b92004-06-10 10:51:47 +0000429do_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 {}}
441do_test collate3-4.10 {
442 db close
drhef4ac8f2004-06-19 00:16:31 +0000443 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000444 catchsql {
445 SELECT * FROM collate3v1;
446 }
447} {1 {no such collation sequence: user_defined}}
448do_test collate3-4.11 {
449 db collate user_defined numeric_compare
450 catchsql {
451 SELECT * FROM collate3v1;
452 }
453} {0 {2 {} 12 {} 101 {}}}
454do_test collate3-4.12 {
455 execsql {
456 DROP TABLE collate3t1;
457 }
458} {}
danielk19770fa8ddb2004-11-22 08:43:32 +0000459} ;# ifcapable view
danielk1977d2b65b92004-06-10 10:51:47 +0000460
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#
466do_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}}
473do_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} {}
481do_test collate3-5.2 {
482 catchsql {
483 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
484 }
485} {0 10}
486do_test collate3-5.3 {
487 set ::cfact_cnt
488} {1}
489do_test collate3-5.4 {
490 catchsql {
491 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
492 }
493} {0 10}
494do_test collate3-5.5 {
495 set ::cfact_cnt
496} {1}
497do_test collate3-5.6 {
498 catchsql {
499 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
500 }
501} {0 10}
502do_test collate3-5.7 {
503 execsql {
504 DROP TABLE collate3t1;
505 CREATE TABLE collate3t1(a COLLATE unk);
506 }
507 db close
drhef4ac8f2004-06-19 00:16:31 +0000508 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000509 catchsql {
510 SELECT a FROM collate3t1 ORDER BY 1;
511 }
512} {1 {no such collation sequence: unk}}
513do_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
525do_test collate3-5.9 {
526 execsql {
527 DROP TABLE collate3t1;
528 }
529} {}
530
531finish_test