xref: /sqlite-3.40.0/test/collate3.test (revision 0fa8ddbd)
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.5 2004/11/22 08:43:32 danielk1977 Exp $
15
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
79  sqlite3 db test.db
80  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 {}}
112do_test collate3-2.7 {
113  catchsql {
114    SELECT * FROM collate3t1 GROUP BY c1;
115  }
116} {1 {no such collation sequence: string_compare}}
117do_test collate3-2.8 {
118  catchsql {
119    SELECT DISTINCT c1 FROM collate3t1;
120  }
121} {1 {no such collation sequence: string_compare}}
122
123do_test collate3-2.9 {
124  catchsql {
125    SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1;
126  }
127} {1 {no such collation sequence: string_compare}}
128do_test collate3-2.10 {
129  catchsql {
130    SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1;
131  }
132} {1 {no such collation sequence: string_compare}}
133do_test collate3-2.11 {
134  catchsql {
135    SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1;
136  }
137} {1 {no such collation sequence: string_compare}}
138do_test collate3-2.12 {
139  catchsql {
140    SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1;
141  }
142} {0 {}}
143do_test collate3-2.13 {
144  catchsql {
145    SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare;
146  }
147} {1 {no such collation sequence: string_compare}}
148do_test collate3-2.14 {
149  catchsql {
150    SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare;
151  }
152} {1 {no such collation sequence: string_compare}}
153do_test collate3-2.15 {
154  catchsql {
155    SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare;
156  }
157} {1 {no such collation sequence: string_compare}}
158do_test collate3-2.16 {
159  catchsql {
160    SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare;
161  }
162} {1 {no such collation sequence: string_compare}}
163do_test collate3-2.17 {
164  catchsql {
165    SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1;
166  }
167} {1 {no such collation sequence: string_compare}}
168
169#
170# Create an index that uses a collation sequence then close and
171# re-open the database without re-registering the collation
172# sequence. Then check that for the table with the index
173# * An INSERT fails,
174# * An UPDATE on the column with the index fails,
175# * An UPDATE on a different column succeeds.
176# * A DELETE with a WHERE clause fails
177# * A DELETE without a WHERE clause succeeds
178#
179# Also, ensure that the restrictions tested by collate3-2.* still
180# apply after the index has been created.
181#
182do_test collate3-3.0 {
183  db collate string_compare {string compare}
184  execsql {
185    CREATE INDEX collate3t1_i1 ON collate3t1(c1);
186    INSERT INTO collate3t1 VALUES('xxx', 'yyy');
187  }
188  db close
189  sqlite3 db test.db
190  expr 0
191} 0
192db eval {select * from collate3t1}
193breakpoint
194do_test collate3-3.1 {
195  catchsql {
196    INSERT INTO collate3t1 VALUES('xxx', 0);
197  }
198} {1 {no such collation sequence: string_compare}}
199do_test collate3-3.2 {
200  catchsql {
201    UPDATE collate3t1 SET c1 = 'xxx';
202  }
203} {1 {no such collation sequence: string_compare}}
204do_test collate3-3.3 {
205  catchsql {
206    UPDATE collate3t1 SET c2 = 'xxx';
207  }
208} {0 {}}
209do_test collate3-3.4 {
210  catchsql {
211    DELETE FROM collate3t1 WHERE 1;
212  }
213} {1 {no such collation sequence: string_compare}}
214do_test collate3-3.5 {
215  catchsql {
216    SELECT * FROM collate3t1;
217  }
218} {0 {xxx xxx}}
219do_test collate3-3.6 {
220  catchsql {
221    DELETE FROM collate3t1;
222  }
223} {0 {}}
224ifcapable {integrityck} {
225  do_test collate3-3.8 {
226    catchsql {
227      PRAGMA integrity_check
228    }
229  } {1 {no such collation sequence: string_compare}}
230}
231do_test collate3-3.9 {
232  catchsql {
233    SELECT * FROM collate3t1;
234  }
235} {0 {}}
236do_test collate3-3.10 {
237  catchsql {
238    SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare;
239  }
240} {1 {no such collation sequence: string_compare}}
241do_test collate3-3.11 {
242  catchsql {
243    SELECT * FROM collate3t1 ORDER BY c1;
244  }
245} {1 {no such collation sequence: string_compare}}
246do_test collate3-3.12 {
247  catchsql {
248    SELECT * FROM collate3t1 WHERE c1 = 'xxx';
249  }
250} {1 {no such collation sequence: string_compare}}
251do_test collate3-3.13 {
252  catchsql {
253    CREATE TABLE collate3t2(c1 COLLATE string_compare);
254  }
255} {1 {no such collation sequence: string_compare}}
256do_test collate3-3.14 {
257  catchsql {
258    CREATE INDEX collate3t1_i2 ON collate3t1(c1);
259  }
260} {1 {no such collation sequence: string_compare}}
261do_test collate3-3.15 {
262  execsql {
263    DROP TABLE collate3t1;
264  }
265} {}
266
267# Check we can create an index that uses an explicit collation
268# sequence and then close and re-open the database.
269do_test collate3-4.6 {
270  db collate user_defined "string compare"
271  execsql {
272    CREATE TABLE collate3t1(a, b);
273    INSERT INTO collate3t1 VALUES('hello', NULL);
274    CREATE INDEX collate3i1 ON collate3t1(a COLLATE user_defined);
275  }
276} {}
277do_test collate3-4.7 {
278  db close
279  sqlite3 db test.db
280  catchsql {
281    SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
282  }
283} {1 {no such collation sequence: user_defined}}
284do_test collate3-4.8 {
285  db collate user_defined "string compare"
286  catchsql {
287    SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
288  }
289} {0 {hello {}}}
290do_test collate3-4.8 {
291  db close
292  lindex [catch {
293    sqlite3 db test.db
294  }] 0
295} {0}
296do_test collate3-4.8 {
297  execsql {
298    DROP TABLE collate3t1;
299  }
300} {}
301
302# Compare strings as numbers.
303proc numeric_compare {lhs rhs} {
304  if {$rhs > $lhs} {
305    set res -1
306  } else {
307    set res [expr ($lhs > $rhs)?1:0]
308  }
309  return $res
310}
311
312# Check we can create a view that uses an explicit collation
313# sequence and then close and re-open the database.
314ifcapable view {
315do_test collate3-4.9 {
316  db collate user_defined numeric_compare
317  execsql {
318    CREATE TABLE collate3t1(a, b);
319    INSERT INTO collate3t1 VALUES('2', NULL);
320    INSERT INTO collate3t1 VALUES('101', NULL);
321    INSERT INTO collate3t1 VALUES('12', NULL);
322    CREATE VIEW collate3v1 AS SELECT * FROM collate3t1
323        ORDER BY 1 COLLATE user_defined;
324    SELECT * FROM collate3v1;
325  }
326} {2 {} 12 {} 101 {}}
327do_test collate3-4.10 {
328  db close
329  sqlite3 db test.db
330  catchsql {
331    SELECT * FROM collate3v1;
332  }
333} {1 {no such collation sequence: user_defined}}
334do_test collate3-4.11 {
335  db collate user_defined numeric_compare
336  catchsql {
337    SELECT * FROM collate3v1;
338  }
339} {0 {2 {} 12 {} 101 {}}}
340do_test collate3-4.12 {
341  execsql {
342    DROP TABLE collate3t1;
343  }
344} {}
345} ;# ifcapable view
346
347#
348# Test the collation factory. In the code, the "no such collation sequence"
349# message is only generated in two places. So these tests just test that
350# the collation factory can be called once from each of those points.
351#
352do_test collate3-5.0 {
353  catchsql {
354    CREATE TABLE collate3t1(a);
355    INSERT INTO collate3t1 VALUES(10);
356    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
357  }
358} {1 {no such collation sequence: unk}}
359do_test collate3-5.1 {
360  set ::cfact_cnt 0
361  proc cfact {nm} {
362    db collate $nm {string compare}
363    incr ::cfact_cnt
364  }
365  db collation_needed cfact
366} {}
367do_test collate3-5.2 {
368  catchsql {
369    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
370  }
371} {0 10}
372do_test collate3-5.3 {
373  set ::cfact_cnt
374} {1}
375do_test collate3-5.4 {
376  catchsql {
377    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
378  }
379} {0 10}
380do_test collate3-5.5 {
381  set ::cfact_cnt
382} {1}
383do_test collate3-5.6 {
384  catchsql {
385    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
386  }
387} {0 10}
388do_test collate3-5.7 {
389  execsql {
390    DROP TABLE collate3t1;
391    CREATE TABLE collate3t1(a COLLATE unk);
392  }
393  db close
394  sqlite3 db test.db
395  catchsql {
396    SELECT a FROM collate3t1 ORDER BY 1;
397  }
398} {1 {no such collation sequence: unk}}
399do_test collate3-5.8 {
400  set ::cfact_cnt 0
401  proc cfact {nm} {
402    db collate $nm {string compare}
403    incr ::cfact_cnt
404  }
405  db collation_needed cfact
406  catchsql {
407    SELECT a FROM collate3t1 ORDER BY 1;
408  }
409} {0 {}}
410
411do_test collate3-5.9 {
412  execsql {
413    DROP TABLE collate3t1;
414  }
415} {}
416
417finish_test
418