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