blob: c4dbfbe4cf344c7e1c3abb0cf57453b5ab0d7713 [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 {
35 CREATE TABLE collate3t1(c1);
36 }
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}}
43do_test collate3-1.2 {
44 catchsql {
45 CREATE TABLE collate3t2(c1 collate garbage);
46 }
47} {1 {no such collation sequence: garbage}}
48do_test collate3-1.3 {
49 catchsql {
50 CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage);
51 }
52} {1 {no such collation sequence: garbage}}
53
54execsql {
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#
73do_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
drhef4ac8f2004-06-19 00:16:31 +000079 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +000080 expr 0
81} 0
82do_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}}
87do_test collate3-2.2 {
88 catchsql {
89 SELECT * FROM collate3t1 ORDER BY c1;
90 }
91} {1 {no such collation sequence: string_compare}}
92do_test collate3-2.3 {
93 catchsql {
94 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
95 }
96} {1 {no such collation sequence: string_compare}}
97do_test collate3-2.4 {
98 catchsql {
99 CREATE TABLE collate3t2(c1 COLLATE string_compare);
100 }
101} {1 {no such collation sequence: string_compare}}
102do_test collate3-2.5 {
103 catchsql {
104 CREATE INDEX collate3t1_i1 ON collate3t1(c1);
105 }
106} {1 {no such collation sequence: string_compare}}
107do_test collate3-2.6 {
108 catchsql {
109 SELECT * FROM collate3t1;
110 }
111} {0 {}}
drh49d642d2005-01-03 02:26:54 +0000112do_test collate3-2.7.1 {
113 catchsql {
114 SELECT count(*) FROM collate3t1 GROUP BY c1;
115 }
116} {1 {no such collation sequence: string_compare}}
danielk1977e2573002005-01-26 03:58:35 +0000117# 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}}
drh49d642d2005-01-03 02:26:54 +0000122do_test collate3-2.7.2 {
danielk1977d2b65b92004-06-10 10:51:47 +0000123 catchsql {
124 SELECT * FROM collate3t1 GROUP BY c1;
125 }
danielk1977e2573002005-01-26 03:58:35 +0000126} {1 {no such collation sequence: string_compare}}
danielk1977d2b65b92004-06-10 10:51:47 +0000127do_test collate3-2.8 {
128 catchsql {
129 SELECT DISTINCT c1 FROM collate3t1;
130 }
131} {1 {no such collation sequence: string_compare}}
danielk1977dc1bdc42004-06-11 10:51:27 +0000132
danielk197727c77432004-11-22 13:35:41 +0000133ifcapable compound {
danielk1977b3bce662005-01-29 08:32:43 +0000134 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}}
danielk197727c77432004-11-22 13:35:41 +0000179} ;# ifcapable compound
danielk1977d2b65b92004-06-10 10:51:47 +0000180
danielk1977d2b65b92004-06-10 10:51:47 +0000181#
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#
194do_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
drhef4ac8f2004-06-19 00:16:31 +0000201 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000202 expr 0
203} 0
204db eval {select * from collate3t1}
danielk1977d2b65b92004-06-10 10:51:47 +0000205do_test collate3-3.1 {
206 catchsql {
207 INSERT INTO collate3t1 VALUES('xxx', 0);
208 }
209} {1 {no such collation sequence: string_compare}}
210do_test collate3-3.2 {
211 catchsql {
212 UPDATE collate3t1 SET c1 = 'xxx';
213 }
214} {1 {no such collation sequence: string_compare}}
215do_test collate3-3.3 {
216 catchsql {
217 UPDATE collate3t1 SET c2 = 'xxx';
218 }
219} {0 {}}
220do_test collate3-3.4 {
221 catchsql {
222 DELETE FROM collate3t1 WHERE 1;
223 }
224} {1 {no such collation sequence: string_compare}}
225do_test collate3-3.5 {
226 catchsql {
227 SELECT * FROM collate3t1;
228 }
229} {0 {xxx xxx}}
230do_test collate3-3.6 {
231 catchsql {
232 DELETE FROM collate3t1;
233 }
234} {0 {}}
drh40e016e2004-11-04 14:47:11 +0000235ifcapable {integrityck} {
236 do_test collate3-3.8 {
237 catchsql {
238 PRAGMA integrity_check
239 }
240 } {1 {no such collation sequence: string_compare}}
241}
danielk1977d2b65b92004-06-10 10:51:47 +0000242do_test collate3-3.9 {
243 catchsql {
244 SELECT * FROM collate3t1;
245 }
246} {0 {}}
247do_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}}
252do_test collate3-3.11 {
253 catchsql {
254 SELECT * FROM collate3t1 ORDER BY c1;
255 }
256} {1 {no such collation sequence: string_compare}}
257do_test collate3-3.12 {
258 catchsql {
259 SELECT * FROM collate3t1 WHERE c1 = 'xxx';
260 }
261} {1 {no such collation sequence: string_compare}}
262do_test collate3-3.13 {
263 catchsql {
264 CREATE TABLE collate3t2(c1 COLLATE string_compare);
265 }
266} {1 {no such collation sequence: string_compare}}
267do_test collate3-3.14 {
268 catchsql {
269 CREATE INDEX collate3t1_i2 ON collate3t1(c1);
270 }
271} {1 {no such collation sequence: string_compare}}
272do_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.
280do_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} {}
288do_test collate3-4.7 {
289 db close
drhef4ac8f2004-06-19 00:16:31 +0000290 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000291 catchsql {
292 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
293 }
294} {1 {no such collation sequence: user_defined}}
drh7d10d5a2008-08-20 16:35:10 +0000295do_test collate3-4.8.1 {
danielk1977d2b65b92004-06-10 10:51:47 +0000296 db collate user_defined "string compare"
297 catchsql {
298 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
299 }
300} {0 {hello {}}}
drh7d10d5a2008-08-20 16:35:10 +0000301do_test collate3-4.8.2 {
danielk1977d2b65b92004-06-10 10:51:47 +0000302 db close
303 lindex [catch {
drhef4ac8f2004-06-19 00:16:31 +0000304 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000305 }] 0
306} {0}
drh7d10d5a2008-08-20 16:35:10 +0000307do_test collate3-4.8.3 {
danielk1977d2b65b92004-06-10 10:51:47 +0000308 execsql {
309 DROP TABLE collate3t1;
310 }
311} {}
312
313# Compare strings as numbers.
314proc 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.
danielk19770fa8ddb2004-11-22 08:43:32 +0000325ifcapable view {
danielk1977d2b65b92004-06-10 10:51:47 +0000326do_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 {}}
338do_test collate3-4.10 {
339 db close
drhef4ac8f2004-06-19 00:16:31 +0000340 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000341 catchsql {
342 SELECT * FROM collate3v1;
343 }
344} {1 {no such collation sequence: user_defined}}
345do_test collate3-4.11 {
346 db collate user_defined numeric_compare
347 catchsql {
348 SELECT * FROM collate3v1;
349 }
350} {0 {2 {} 12 {} 101 {}}}
351do_test collate3-4.12 {
352 execsql {
353 DROP TABLE collate3t1;
354 }
355} {}
danielk19770fa8ddb2004-11-22 08:43:32 +0000356} ;# ifcapable view
danielk1977d2b65b92004-06-10 10:51:47 +0000357
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#
363do_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}}
370do_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} {}
378do_test collate3-5.2 {
379 catchsql {
380 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
381 }
382} {0 10}
383do_test collate3-5.3 {
384 set ::cfact_cnt
385} {1}
386do_test collate3-5.4 {
387 catchsql {
388 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
389 }
390} {0 10}
391do_test collate3-5.5 {
392 set ::cfact_cnt
393} {1}
394do_test collate3-5.6 {
395 catchsql {
396 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
397 }
398} {0 10}
399do_test collate3-5.7 {
400 execsql {
401 DROP TABLE collate3t1;
402 CREATE TABLE collate3t1(a COLLATE unk);
403 }
404 db close
drhef4ac8f2004-06-19 00:16:31 +0000405 sqlite3 db test.db
danielk1977d2b65b92004-06-10 10:51:47 +0000406 catchsql {
407 SELECT a FROM collate3t1 ORDER BY 1;
408 }
409} {1 {no such collation sequence: unk}}
410do_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
422do_test collate3-5.9 {
423 execsql {
424 DROP TABLE collate3t1;
425 }
426} {}
427
428finish_test