2010-10-10 9 views
6

Niedawno odkurzyłem stary projekt Ruby on Rails. W przeszłości, nigdy nie miałem żadnych problemów z dostaniem wszystkie testy do przekazania, ale teraz jest jeden test, który daje mi następujący błąd:Błąd "Nielegalna mieszanka kolizji" z MySql podczas uruchamiania zestawu testów szyn

ActiveRecord::StatementInvalid: Mysql::Error: #HY000Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=': SELECT * FROM cards WHERE (cards.l1_description = '是' AND cards.l2_word = '')

Więc idę do mojego testu db i zapytać:

mysql> use flashcard_test 
Reading table information for completion of table and column names 
You can turn off this feature to get a quicker startup with -A 

Database changed 
mysql> show full columns from cards; 
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+ 
| Field   | Type   | Collation   | Null | Key | Default | Extra   | Privileges      | Comment | 
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+ 
| id    | int(11)  | NULL    | NO | PRI | NULL | auto_increment | select,insert,update,references |   | 
| l2_word  | varchar(255) | latin1_swedish_ci | YES |  | NULL |    | select,insert,update,references |   | 
| l1_description | text   | latin1_swedish_ci | YES |  | NULL |    | select,insert,update,references |   | 
| l1_id   | int(11)  | NULL    | YES |  | NULL |    | select,insert,update,references |   | 
| l2_id   | int(11)  | NULL    | YES |  | NULL |    | select,insert,update,references |   | 
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+ 
5 rows in set (0.01 sec) 

Jak widać, zestawienie to latin1_swedish_ci, i prawdopodobnie jeśli byłby "utf8_general_ci", moje problemy zostaną rozwiązane. Na szczęście, moja baza rozwój jest już w porządku, więc pójdę i

rake db:test:clone_structure 

iz powrotem do MySQL i sprawdź ponownie w db testu

mysql> show full columns from cards; 
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+ 
| Field   | Type   | Collation  | Null | Key | Default | Extra   | Privileges      | Comment | 
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+ 
| id    | int(11)  | NULL   | NO | PRI | NULL | auto_increment | select,insert,update,references |   | 
| l2_word  | varchar(255) | utf8_general_ci | YES |  | NULL |    | select,insert,update,references |   | 
| l1_description | text   | utf8_general_ci | YES |  | NULL |    | select,insert,update,references |   | 
| l1_id   | int(11)  | NULL   | YES |  | NULL |    | select,insert,update,references |   | 
| l2_id   | int(11)  | NULL   | YES |  | NULL |    | select,insert,update,references |   | 
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+ 
5 rows in set (0.00 sec) 

Ah, więc teraz wszystko wygląda dobrze, więc po raz kolejny i

rake test 

Ale mam ten sam problem na nowo, a kiedy sprawdzić mój test db, uważam, że kolumna sortowania został zresetowany do latin1_swedish_ci.

Nie bardzo rozumiem, jak działa test rake, ale moja robocza hipoteza polega na tym, że odtwarza DB za pomocą schema.rb. Teraz, w jednej z moich migracji, mam teraz

class CreateCards < ActiveRecord::Migration 
    def self.up 
    create_table :cards, :options => "DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci" do |t| 
     t.column :english_word, :string 
     t.column :chinese_description, :text 
    end 
    end 

    def self.down 
    drop_table :cards 
    end 
end 

A to najwyraźniej zajęło się problemem sortowania. (Mam inną migrację, która odpowiednio zmienia nazwę English_word i Chinese_description na l2_word i l1_description). Jednak ta informacja nie dotarła do schematu.rb. I jakoś, widocznie, MySql zdecydował się założyć, że chcę latin1_swedish_ci.

Podsumowując, myślę, że muszę coś zmodyfikować, żeby użyć zestawu utf8_general_ci, a wtedy moje problemy znikną (prawda?). Ale nie mogę wymyślić, jak zrobić kod, który uruchamia się, gdy "rake test" to zrobić. Czy ktokolwiek może pomóc?

Na co warto, zarówno bazy testowe i rozwojowe zostały stworzone jako

create database flashcard_test default character set utf8 default collate utf8_general_ci; 

i

create database flashcard_development default character set utf8 default collate utf8_general_ci; 

A moja database.yml ma

development: 
    adapter: mysql 
    database: flashcard_development 
    username: root 
    password: 
    encoding: utf8 

test: 
    adapter: mysql 
    database: flashcard_test 
    username: root 
    password: 
    encoding: utf8 
    collation: utf8_general_ci 

http://nhw.pl/wp/2008/09/16/mysql-collate-setting-in-rails-application zdaje się sugerować że ten problem ma coś wspólnego z połączeniem RoR i MySql, ale nie miałem szczęścia z sugestiami tam.

Odpowiedz

5

Dodanie sortowania: utf8_general_ci do pliku database.yml, tak jak zrobiliście, powinno załatwić sprawę. Spróbuj odtworzyć testową bazę danych za pomocą polecenia "rake RAILS_ENV = testowy db: migrate: reset db: fixtures load" - ostrzeżenie spowoduje wyczyszczenie wszystkich danych poza urządzeniami.

To zadziałało dla mnie.Aby zweryfikować zobaczyć sortowania na bazie danych, tabel i kolumn można wykonać następujące czynności:

-- Database Collations: 
SELECT schema_name,default_character_set_name,default_collation_name 
FROM information_schema.SCHEMATA 
WHERE schema_name not IN ('mysql'); 

-- Table Collations: 
SELECT T.table_schema, T.table_name, T.TABLE_COLLATION, CCSA.CHARACTER_SET_NAME 
FROM information_schema.`TABLES` T, 
information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA 
WHERE CCSA.collation_name = T.table_collation 
AND T.table_schema not IN ('mysql'); 

-- Column Collations: 
SELECT table_schema, table_name, column_name, collation_name, character_set_name 
FROM information_schema.`COLUMNS` C 
WHERE C.table_schema not IN ('mysql') 
ORDER BY 1,2,4; 

wszystko w swojej bazie testowej powinna mieć sortowania określonego w database.yml.

Powiązane problemy