Created
May 15, 2014 10:57
-
-
Save stevehodgkiss/e4ca45b2bf2570ddb135 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
require 'active_record' | |
ActiveRecord::Base.establish_connection( | |
:adapter => 'mysql2', | |
:host => '127.0.0.1', | |
:port => 13306, | |
:username => 'root', | |
:database => 'encoding_test', | |
:encoding => 'latin1') | |
conn = ActiveRecord::Base.connection | |
conn.execute('set sql_mode="STRICT_TRANS_TABLES"') | |
def create_table(name, charset) | |
ActiveRecord::Base.connection.create_table :test, :options => "ENGINE=InnoDB DEFAULT CHARSET=#{charset}" do |t| | |
yield t | |
end | |
end | |
def recreate_test_table(encoding) | |
conn.drop_table('test') if conn.table_exists?('test') | |
create_table('test', encoding) do |t| | |
t.string :name | |
end | |
end | |
def set_client_encoding(encoding) | |
conn.execute("set names #{encoding}") | |
end | |
def insert_name | |
conn.execute("insert into test (`name`) values ('#{utf8_name}')") | |
end | |
describe 'mysql encoding' do | |
let(:utf8_name) { 'testş' } | |
let(:conn) { ActiveRecord::Base.connection } | |
subject(:name) { conn.select_value('select name from test limit 1') } | |
before { conn.execute('truncate table test') } | |
context 'latin1 table' do | |
before do | |
recreate_test_table('latin1') | |
end | |
context 'latin1 client' do | |
before { set_client_encoding('latin1') } | |
it 'stores utf8 data unchanged' do | |
insert_name | |
name.bytes.should eq utf8_name.bytes | |
name.should_not eq utf8_name | |
end | |
it 'comes back marked as latin1' do | |
insert_name | |
name.encoding.should eq Encoding::ISO_8859_1 | |
end | |
context 'when marked as utf8' do | |
before do | |
insert_name | |
name.force_encoding('utf-8') | |
end | |
it { should eq utf8_name } | |
end | |
context 'when client connection changes to utf8 client' do | |
before do | |
insert_name | |
set_client_encoding('utf8') | |
end | |
it 'comes back double encoded' do | |
name.should eq "testÅŸ" | |
name.should eq conn.select_value("SELECT CAST(_latin1'testş' AS CHAR CHARACTER SET utf8)") | |
end | |
it 'can be recovered' do | |
recovered = conn.select_value("SELECT CONVERT(CAST(CONVERT('#{name}' USING latin1) AS BINARY) USING utf8)") | |
recovered.should eq utf8_name | |
end | |
end | |
context 'after a mysqldump and restore' do | |
# its the same | |
before do | |
insert_name | |
`mysqldump -u root --default-character-set=latin1 encoding_test > /tmp/encoding_test.sql` | |
`mysql -u root encoding_test < /tmp/encoding_test.sql` | |
end | |
it 'stores utf8 data unchanged' do | |
name.bytes.should eq utf8_name.bytes | |
name.should_not eq utf8_name | |
end | |
context 'and utf8 client' do | |
before { set_client_encoding('utf8') } | |
it 'is double encoded' do | |
name.should eq "testÅŸ" | |
end | |
end | |
context 'when marked as utf8' do | |
before do | |
name.force_encoding('utf-8') | |
end | |
it { should eq utf8_name } | |
end | |
end | |
end | |
context 'utf8 client' do | |
before { set_client_encoding('utf8') } | |
context 'with strict_trans_tables' do | |
before do | |
conn.execute('set sql_mode="STRICT_TRANS_TABLES"') | |
end | |
it 'comes back double encoded' do | |
expect { | |
insert_name | |
}.to raise_error(ActiveRecord::StatementInvalid) | |
end | |
end | |
context 'without strict_trans_tables' do | |
before do | |
conn.execute('set sql_mode=""') | |
insert_name | |
end | |
it 'replaces unknown chars with ?' do | |
name.should eq "test?" | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment