sl@0: # sl@0: # 2001 September 15 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #************************************************************************* sl@0: # This file implements regression tests for SQLite library. The sl@0: # focus of this file is testing DISTINCT, UNION, INTERSECT and EXCEPT sl@0: # SELECT statements that use user-defined collation sequences. Also sl@0: # GROUP BY clauses that use user-defined collation sequences. sl@0: # sl@0: # $Id: collate5.test,v 1.6 2007/11/12 15:29:19 danielk1977 Exp $ sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: sl@0: # sl@0: # Tests are organised as follows: sl@0: # collate5-1.* - DISTINCT sl@0: # collate5-2.* - Compound SELECT sl@0: # collate5-3.* - ORDER BY on compound SELECT sl@0: # collate5-4.* - GROUP BY sl@0: sl@0: # Create the collation sequence 'TEXT', purely for asthetic reasons. The sl@0: # test cases in this script could just as easily use BINARY. sl@0: db collate TEXT [list string compare] sl@0: sl@0: # Mimic the SQLite 2 collation type NUMERIC. sl@0: db collate numeric numeric_collate sl@0: proc numeric_collate {lhs rhs} { sl@0: if {$lhs == $rhs} {return 0} sl@0: return [expr ($lhs>$rhs)?1:-1] sl@0: } sl@0: sl@0: # sl@0: # These tests - collate5-1.* - focus on the DISTINCT keyword. sl@0: # sl@0: do_test collate5-1.0 { sl@0: execsql { sl@0: CREATE TABLE collate5t1(a COLLATE nocase, b COLLATE text); sl@0: sl@0: INSERT INTO collate5t1 VALUES('a', 'apple'); sl@0: INSERT INTO collate5t1 VALUES('A', 'Apple'); sl@0: INSERT INTO collate5t1 VALUES('b', 'banana'); sl@0: INSERT INTO collate5t1 VALUES('B', 'banana'); sl@0: INSERT INTO collate5t1 VALUES('n', NULL); sl@0: INSERT INTO collate5t1 VALUES('N', NULL); sl@0: } sl@0: } {} sl@0: do_test collate5-1.1 { sl@0: execsql { sl@0: SELECT DISTINCT a FROM collate5t1; sl@0: } sl@0: } {A B N} sl@0: do_test collate5-1.2 { sl@0: execsql { sl@0: SELECT DISTINCT b FROM collate5t1; sl@0: } sl@0: } {{} Apple apple banana} sl@0: do_test collate5-1.3 { sl@0: execsql { sl@0: SELECT DISTINCT a, b FROM collate5t1; sl@0: } sl@0: } {A Apple a apple B banana N {}} sl@0: sl@0: # The remainder of this file tests compound SELECT statements. sl@0: # Omit it if the library is compiled such that they are omitted. sl@0: # sl@0: ifcapable !compound { sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: # sl@0: # Tests named collate5-2.* focus on UNION, EXCEPT and INTERSECT sl@0: # queries that use user-defined collation sequences. sl@0: # sl@0: # collate5-2.1.* - UNION sl@0: # collate5-2.2.* - INTERSECT sl@0: # collate5-2.3.* - EXCEPT sl@0: # sl@0: do_test collate5-2.0 { sl@0: execsql { sl@0: CREATE TABLE collate5t2(a COLLATE text, b COLLATE nocase); sl@0: sl@0: INSERT INTO collate5t2 VALUES('a', 'apple'); sl@0: INSERT INTO collate5t2 VALUES('A', 'apple'); sl@0: INSERT INTO collate5t2 VALUES('b', 'banana'); sl@0: INSERT INTO collate5t2 VALUES('B', 'Banana'); sl@0: } sl@0: } {} sl@0: sl@0: do_test collate5-2.1.1 { sl@0: execsql { sl@0: SELECT a FROM collate5t1 UNION select a FROM collate5t2; sl@0: } sl@0: } {A B N} sl@0: do_test collate5-2.1.2 { sl@0: execsql { sl@0: SELECT a FROM collate5t2 UNION select a FROM collate5t1; sl@0: } sl@0: } {A B N a b n} sl@0: do_test collate5-2.1.3 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t1 UNION select a, b FROM collate5t2; sl@0: } sl@0: } {A Apple A apple B Banana b banana N {}} sl@0: do_test collate5-2.1.4 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t2 UNION select a, b FROM collate5t1; sl@0: } sl@0: } {A Apple B banana N {} a apple b banana n {}} sl@0: sl@0: do_test collate5-2.2.1 { sl@0: execsql { sl@0: SELECT a FROM collate5t1 EXCEPT select a FROM collate5t2; sl@0: } sl@0: } {N} sl@0: do_test collate5-2.2.2 { sl@0: execsql { sl@0: SELECT a FROM collate5t2 EXCEPT select a FROM collate5t1 WHERE a != 'a'; sl@0: } sl@0: } {A a} sl@0: do_test collate5-2.2.3 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t1 EXCEPT select a, b FROM collate5t2; sl@0: } sl@0: } {A Apple N {}} sl@0: do_test collate5-2.2.4 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t2 EXCEPT select a, b FROM collate5t1 sl@0: where a != 'a'; sl@0: } sl@0: } {A apple a apple} sl@0: sl@0: do_test collate5-2.3.1 { sl@0: execsql { sl@0: SELECT a FROM collate5t1 INTERSECT select a FROM collate5t2; sl@0: } sl@0: } {A B} sl@0: do_test collate5-2.3.2 { sl@0: execsql { sl@0: SELECT a FROM collate5t2 INTERSECT select a FROM collate5t1 WHERE a != 'a'; sl@0: } sl@0: } {B b} sl@0: do_test collate5-2.3.3 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t1 INTERSECT select a, b FROM collate5t2; sl@0: } sl@0: } {a apple B banana} sl@0: do_test collate5-2.3.4 { sl@0: execsql { sl@0: SELECT a, b FROM collate5t2 INTERSECT select a, b FROM collate5t1; sl@0: } sl@0: } {A apple B Banana a apple b banana} sl@0: sl@0: # sl@0: # This test ensures performs a UNION operation with a bunch of different sl@0: # length records. The goal is to test that the logic that compares records sl@0: # for the compound SELECT operators works with record lengths that lie sl@0: # either side of the troublesome 256 and 65536 byte marks. sl@0: # sl@0: set ::lens [list \ sl@0: 0 1 2 3 4 5 6 7 8 9 \ sl@0: 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 \ sl@0: 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 \ sl@0: 65520 65521 65522 65523 65524 65525 65526 65527 65528 65529 65530 \ sl@0: 65531 65532 65533 65534 65535 65536 65537 65538 65539 65540 65541 \ sl@0: 65542 65543 65544 65545 65546 65547 65548 65549 65550 65551 ] sl@0: do_test collate5-2.4.0 { sl@0: execsql { sl@0: BEGIN; sl@0: CREATE TABLE collate5t3(a, b); sl@0: } sl@0: foreach ii $::lens { sl@0: execsql "INSERT INTO collate5t3 VALUES($ii, '[string repeat a $ii]');" sl@0: } sl@0: expr [llength [execsql { sl@0: COMMIT; sl@0: SELECT * FROM collate5t3 UNION SELECT * FROM collate5t3; sl@0: }]] / 2 sl@0: } [llength $::lens] sl@0: do_test collate5-2.4.1 { sl@0: execsql {DROP TABLE collate5t3;} sl@0: } {} sl@0: unset ::lens sl@0: sl@0: # sl@0: # These tests - collate5-3.* - focus on compound SELECT queries that sl@0: # feature ORDER BY clauses. sl@0: # sl@0: do_test collate5-3.0 { sl@0: execsql { sl@0: SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 ORDER BY 1; sl@0: } sl@0: } {a A a A b B b B n N} sl@0: do_test collate5-3.1 { sl@0: execsql { sl@0: SELECT a FROM collate5t2 UNION ALL SELECT a FROM collate5t1 ORDER BY 1; sl@0: } sl@0: } {A A B B N a a b b n} sl@0: do_test collate5-3.2 { sl@0: execsql { sl@0: SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 sl@0: ORDER BY 1 COLLATE TEXT; sl@0: } sl@0: } {A A B B N a a b b n} sl@0: sl@0: do_test collate5-3.3 { sl@0: execsql { sl@0: CREATE TABLE collate5t_cn(a COLLATE NUMERIC); sl@0: CREATE TABLE collate5t_ct(a COLLATE TEXT); sl@0: INSERT INTO collate5t_cn VALUES('1'); sl@0: INSERT INTO collate5t_cn VALUES('11'); sl@0: INSERT INTO collate5t_cn VALUES('101'); sl@0: INSERT INTO collate5t_ct SELECT * FROM collate5t_cn; sl@0: } sl@0: } {} sl@0: do_test collate5-3.4 { sl@0: execsql { sl@0: SELECT a FROM collate5t_cn INTERSECT SELECT a FROM collate5t_ct ORDER BY 1; sl@0: } sl@0: } {1 11 101} sl@0: do_test collate5-3.5 { sl@0: execsql { sl@0: SELECT a FROM collate5t_ct INTERSECT SELECT a FROM collate5t_cn ORDER BY 1; sl@0: } sl@0: } {1 101 11} sl@0: sl@0: do_test collate5-3.20 { sl@0: execsql { sl@0: DROP TABLE collate5t_cn; sl@0: DROP TABLE collate5t_ct; sl@0: DROP TABLE collate5t1; sl@0: DROP TABLE collate5t2; sl@0: } sl@0: } {} sl@0: sl@0: do_test collate5-4.0 { sl@0: execsql { sl@0: CREATE TABLE collate5t1(a COLLATE NOCASE, b COLLATE NUMERIC); sl@0: INSERT INTO collate5t1 VALUES('a', '1'); sl@0: INSERT INTO collate5t1 VALUES('A', '1.0'); sl@0: INSERT INTO collate5t1 VALUES('b', '2'); sl@0: INSERT INTO collate5t1 VALUES('B', '3'); sl@0: } sl@0: } {} sl@0: do_test collate5-4.1 { sl@0: string tolower [execsql { sl@0: SELECT a, count(*) FROM collate5t1 GROUP BY a; sl@0: }] sl@0: } {a 2 b 2} sl@0: do_test collate5-4.2 { sl@0: execsql { sl@0: SELECT a, b, count(*) FROM collate5t1 GROUP BY a, b ORDER BY a, b; sl@0: } sl@0: } {A 1.0 2 b 2 1 B 3 1} sl@0: do_test collate5-4.3 { sl@0: execsql { sl@0: DROP TABLE collate5t1; sl@0: } sl@0: } {} sl@0: sl@0: finish_test