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.13 2008/08/20 16:35:10 drh Exp $ 15 16 set testdir [file dirname $argv0] 17 source $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 # 33 do_test collate3-1.0 { 34 execsql { 35 CREATE TABLE collate3t1(c1); 36 } 37 } {} 38 do_test collate3-1.1 { 39 catchsql { 40 SELECT * FROM collate3t1 ORDER BY 1 collate garbage; 41 } 42 } {1 {no such collation sequence: garbage}} 43 do_test collate3-1.2 { 44 catchsql { 45 CREATE TABLE collate3t2(c1 collate garbage); 46 } 47 } {1 {no such collation sequence: garbage}} 48 do_test collate3-1.3 { 49 catchsql { 50 CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage); 51 } 52 } {1 {no such collation sequence: garbage}} 53 54 execsql { 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 # 73 do_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 82 do_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}} 87 do_test collate3-2.2 { 88 catchsql { 89 SELECT * FROM collate3t1 ORDER BY c1; 90 } 91 } {1 {no such collation sequence: string_compare}} 92 do_test collate3-2.3 { 93 catchsql { 94 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; 95 } 96 } {1 {no such collation sequence: string_compare}} 97 do_test collate3-2.4 { 98 catchsql { 99 CREATE TABLE collate3t2(c1 COLLATE string_compare); 100 } 101 } {1 {no such collation sequence: string_compare}} 102 do_test collate3-2.5 { 103 catchsql { 104 CREATE INDEX collate3t1_i1 ON collate3t1(c1); 105 } 106 } {1 {no such collation sequence: string_compare}} 107 do_test collate3-2.6 { 108 catchsql { 109 SELECT * FROM collate3t1; 110 } 111 } {0 {}} 112 do_test collate3-2.7.1 { 113 catchsql { 114 SELECT count(*) FROM collate3t1 GROUP BY c1; 115 } 116 } {1 {no such collation sequence: string_compare}} 117 # 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}} 122 do_test collate3-2.7.2 { 123 catchsql { 124 SELECT * FROM collate3t1 GROUP BY c1; 125 } 126 } {1 {no such collation sequence: string_compare}} 127 do_test collate3-2.8 { 128 catchsql { 129 SELECT DISTINCT c1 FROM collate3t1; 130 } 131 } {1 {no such collation sequence: string_compare}} 132 133 ifcapable compound { 134 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}} 179 } ;# ifcapable compound 180 181 # 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 # 194 do_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 201 sqlite3 db test.db 202 expr 0 203 } 0 204 db eval {select * from collate3t1} 205 do_test collate3-3.1 { 206 catchsql { 207 INSERT INTO collate3t1 VALUES('xxx', 0); 208 } 209 } {1 {no such collation sequence: string_compare}} 210 do_test collate3-3.2 { 211 catchsql { 212 UPDATE collate3t1 SET c1 = 'xxx'; 213 } 214 } {1 {no such collation sequence: string_compare}} 215 do_test collate3-3.3 { 216 catchsql { 217 UPDATE collate3t1 SET c2 = 'xxx'; 218 } 219 } {0 {}} 220 do_test collate3-3.4 { 221 catchsql { 222 DELETE FROM collate3t1 WHERE 1; 223 } 224 } {1 {no such collation sequence: string_compare}} 225 do_test collate3-3.5 { 226 catchsql { 227 SELECT * FROM collate3t1; 228 } 229 } {0 {xxx xxx}} 230 do_test collate3-3.6 { 231 catchsql { 232 DELETE FROM collate3t1; 233 } 234 } {0 {}} 235 ifcapable {integrityck} { 236 do_test collate3-3.8 { 237 catchsql { 238 PRAGMA integrity_check 239 } 240 } {1 {no such collation sequence: string_compare}} 241 } 242 do_test collate3-3.9 { 243 catchsql { 244 SELECT * FROM collate3t1; 245 } 246 } {0 {}} 247 do_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}} 252 do_test collate3-3.11 { 253 catchsql { 254 SELECT * FROM collate3t1 ORDER BY c1; 255 } 256 } {1 {no such collation sequence: string_compare}} 257 do_test collate3-3.12 { 258 catchsql { 259 SELECT * FROM collate3t1 WHERE c1 = 'xxx'; 260 } 261 } {1 {no such collation sequence: string_compare}} 262 do_test collate3-3.13 { 263 catchsql { 264 CREATE TABLE collate3t2(c1 COLLATE string_compare); 265 } 266 } {1 {no such collation sequence: string_compare}} 267 do_test collate3-3.14 { 268 catchsql { 269 CREATE INDEX collate3t1_i2 ON collate3t1(c1); 270 } 271 } {1 {no such collation sequence: string_compare}} 272 do_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. 280 do_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 } {} 288 do_test collate3-4.7 { 289 db close 290 sqlite3 db test.db 291 catchsql { 292 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; 293 } 294 } {1 {no such collation sequence: user_defined}} 295 do_test collate3-4.8.1 { 296 db collate user_defined "string compare" 297 catchsql { 298 SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined; 299 } 300 } {0 {hello {}}} 301 do_test collate3-4.8.2 { 302 db close 303 lindex [catch { 304 sqlite3 db test.db 305 }] 0 306 } {0} 307 do_test collate3-4.8.3 { 308 execsql { 309 DROP TABLE collate3t1; 310 } 311 } {} 312 313 # Compare strings as numbers. 314 proc 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. 325 ifcapable view { 326 do_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 {}} 338 do_test collate3-4.10 { 339 db close 340 sqlite3 db test.db 341 catchsql { 342 SELECT * FROM collate3v1; 343 } 344 } {1 {no such collation sequence: user_defined}} 345 do_test collate3-4.11 { 346 db collate user_defined numeric_compare 347 catchsql { 348 SELECT * FROM collate3v1; 349 } 350 } {0 {2 {} 12 {} 101 {}}} 351 do_test collate3-4.12 { 352 execsql { 353 DROP TABLE collate3t1; 354 } 355 } {} 356 } ;# ifcapable view 357 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 # 363 do_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}} 370 do_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 } {} 378 do_test collate3-5.2 { 379 catchsql { 380 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; 381 } 382 } {0 10} 383 do_test collate3-5.3 { 384 set ::cfact_cnt 385 } {1} 386 do_test collate3-5.4 { 387 catchsql { 388 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; 389 } 390 } {0 10} 391 do_test collate3-5.5 { 392 set ::cfact_cnt 393 } {1} 394 do_test collate3-5.6 { 395 catchsql { 396 SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk; 397 } 398 } {0 10} 399 do_test collate3-5.7 { 400 execsql { 401 DROP TABLE collate3t1; 402 CREATE TABLE collate3t1(a COLLATE unk); 403 } 404 db close 405 sqlite3 db test.db 406 catchsql { 407 SELECT a FROM collate3t1 ORDER BY 1; 408 } 409 } {1 {no such collation sequence: unk}} 410 do_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 422 do_test collate3-5.9 { 423 execsql { 424 DROP TABLE collate3t1; 425 } 426 } {} 427 428 finish_test 429