Home | History | Annotate | Download | only in test
      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