Ошибка «Неверное смешение параметров сортировки» от MySql при запуске набора тестов rails - PullRequest
6 голосов
/ 10 октября 2010

Я недавно отряхнул свой старый проект Ruby on Rails. В прошлом у меня никогда не было проблем с выполнением всех тестов, но теперь есть один тест, который дает мне следующую ошибку:

ActiveRecord :: StatementInvalid: Mysql :: Ошибка: # HY000Неверное сочетание параметров сортировки (latin1_swedish_ci, IMPLICIT) и (utf8_general_ci, COERCIBLE) для операции '=': ВЫБРАТЬ * ИЗ карт, ГДЕ (cards.l1_description = '是' AND .l2_word = '')

Итак, я иду на свою тестовую базу данных и спрашиваю:

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)

И, как вы можете видеть, параметры сортировки - latin1_swedish_ci, и, вероятно, если бы это было "utf8_general_ci", мои проблемы были бы решены. К счастью, моя база данных разработки уже в порядке, поэтому я иду и

rake db:test:clone_structure

и вернитесь к MySql и проверьте снова в тесте db

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)

Ах, теперь все выглядит хорошо, поэтому я снова

rake test

Но я снова и снова сталкиваюсь с той же проблемой, и когда я проверяю свою тестовую базу данных, я обнаруживаю, что столбец сортировки сброшен в значение latin1_swedish_ci.

Я не очень хорошо понимаю, как работает тест рейка, но моя рабочая гипотеза заключается в том, что он воссоздает БД с использованием schema.rb. Теперь, в одной из моих миграций, у меня есть

 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

И это, видимо, решило проблему сортировки там. (У меня есть другая миграция, которая переименовывает english_word и chinese_description в l2_word и l1_description, соответственно.) Но эта информация не вошла в schema.rb. И как-то, судя по всему, MySql решил предположить, что я хочу latin1_swedish_ci.

Итак, чтобы подвести итог, я думаю, что мне нужно как-то отредактировать что-то, чтобы я использовал сортировку utf8_general_ci, и тогда мои проблемы исчезнут (верно?). Но я не могу понять, как заставить код, который запускается, когда вы выполняете тест rake, делать это. Кто-нибудь может помочь?

Для чего бы то ни было, базы данных для тестирования и разработки были созданы как

create database flashcard_test default character set utf8 default collate utf8_general_ci;

и

create database flashcard_development default character set utf8 default collate utf8_general_ci;

И мой database.yml имеет

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, похоже, предполагает, что эта проблема как-то связана с соединением между RoR и MySql, но мне не повезло с предложениями там.

1 Ответ

5 голосов
/ 11 июня 2011

Добавление параметров сортировки: utf8_general_ci в файл database.yml, как вы сделали, должно помочь. Попробуйте воссоздать тестовую базу данных, используя "rake RAILS_ENV = test db: migrate: reset db: fixtures load" - предупреждая, это очистит все данные, которые у вас есть, за исключением фикстур.

Это сработало для меня. Для проверки просмотра параметров сортировки в базе данных, таблицах и столбцах вы можете выполнить следующее:

-- 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;

Теперь все в вашей тестовой базе данных должно иметь параметры сортировки, указанные в database.yml.

...