From a9115795dbae1c7d518ebd4341e6d674b97a8780 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Mon, 7 Jun 2010 10:38:22 -0700 Subject: [PATCH] Make :encoding option work on MySQL even if config file specifies different encoding (Fixes #300, again) After discussions with tmm1, this seems like the best way to work around the bug in libmysqlclient, which makes configuration file settings taken from READ_DEFAULT_GROUP override an explicitly given SET_CHARSET_NAME option. It uses a "SET NAMES" SQL query after connection to attempt to ensure the connection will use the correct encoding. This is not safe across implicit reconnects, but Sequel hasn't used those for some time. --- CHANGELOG | 2 ++ lib/sequel/adapters/mysql.rb | 15 ++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index effc797950..daf1e6e8b1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === HEAD +* Make :encoding option work on MySQL even if config file specifies different encoding (jeremyevans) (#300) + * Don't attempt to use class polymorphism in the class_table_inheritance plugin if no cti_key is defined (jeremyevans) * Add a XmlSerializer plugin for serializing/deserializing model objects to/from XML (jeremyevans) diff --git a/lib/sequel/adapters/mysql.rb b/lib/sequel/adapters/mysql.rb index 26c6a40c09..51476d273a 100644 --- a/lib/sequel/adapters/mysql.rb +++ b/lib/sequel/adapters/mysql.rb @@ -99,6 +99,11 @@ def connect(server) conn = Mysql.init conn.options(Mysql::READ_DEFAULT_GROUP, opts[:config_default_group] || "client") conn.options(Mysql::OPT_LOCAL_INFILE, opts[:config_local_infile]) if opts.has_key?(:config_local_infile) + if encoding = opts[:encoding] || opts[:charset] + # Set encoding before connecting so that the mysql driver knows what + # encoding we want to use, but this can be overridden by READ_DEFAULT_GROUP. + conn.options(Mysql::SET_CHARSET_NAME, encoding) + end conn.real_connect( opts[:host] || 'localhost', opts[:user], @@ -110,11 +115,11 @@ def connect(server) Mysql::CLIENT_MULTI_STATEMENTS + (opts[:compress] == false ? 0 : Mysql::CLIENT_COMPRESS) ) - if encoding = opts[:encoding] || opts[:charset] - # Setting encoding before the connect appears not to work - # with READ_DEFAULT_GROUP, so set it afterwards. - conn.options(Mysql::SET_CHARSET_NAME, encoding) - end + # Set encoding a slightly different way after connecting, + # in case the READ_DEFAULT_GROUP overrode the provided encoding. + # Doesn't work across implicit reconnects, but Sequel doesn't turn on + # that feature. + conn.query("set names #{literal(encoding.to_s)}") if encoding # increase timeout so mysql server doesn't disconnect us conn.query("set @@wait_timeout = #{opts[:timeout] || 2592000}")