mysql2 0.2.24 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +148 -0
  5. data/Gemfile +3 -0
  6. data/README.rdoc +257 -0
  7. data/Rakefile +5 -0
  8. data/benchmark/active_record.rb +51 -0
  9. data/benchmark/active_record_threaded.rb +42 -0
  10. data/benchmark/allocations.rb +33 -0
  11. data/benchmark/escape.rb +36 -0
  12. data/benchmark/query_with_mysql_casting.rb +80 -0
  13. data/benchmark/query_without_mysql_casting.rb +47 -0
  14. data/benchmark/sequel.rb +37 -0
  15. data/benchmark/setup_db.rb +119 -0
  16. data/benchmark/threaded.rb +44 -0
  17. data/ext/mysql2/client.c +272 -849
  18. data/ext/mysql2/client.h +12 -27
  19. data/ext/mysql2/extconf.rb +14 -72
  20. data/ext/mysql2/mysql2_ext.h +4 -7
  21. data/ext/mysql2/result.c +123 -319
  22. data/ext/mysql2/result.h +1 -4
  23. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +64 -0
  24. data/lib/active_record/fiber_patches.rb +104 -0
  25. data/lib/mysql2.rb +5 -20
  26. data/lib/mysql2/client.rb +200 -50
  27. data/lib/mysql2/em.rb +3 -13
  28. data/lib/mysql2/em_fiber.rb +31 -0
  29. data/lib/mysql2/error.rb +6 -71
  30. data/lib/mysql2/version.rb +2 -2
  31. data/mysql2.gemspec +32 -0
  32. data/spec/em/em_fiber_spec.rb +22 -0
  33. data/spec/em/em_spec.rb +9 -74
  34. data/spec/mysql2/client_spec.rb +126 -593
  35. data/spec/mysql2/error_spec.rb +44 -58
  36. data/spec/mysql2/result_spec.rb +85 -257
  37. data/spec/spec_helper.rb +3 -24
  38. data/tasks/benchmarks.rake +20 -0
  39. data/tasks/compile.rake +71 -0
  40. data/tasks/rspec.rake +16 -0
  41. data/tasks/vendor_mysql.rake +40 -0
  42. metadata +179 -92
  43. checksums.yaml +0 -7
  44. data/README.md +0 -524
  45. data/ext/mysql2/infile.c +0 -122
  46. data/ext/mysql2/infile.h +0 -1
  47. data/ext/mysql2/mysql_enc_name_to_ruby.h +0 -168
  48. data/ext/mysql2/mysql_enc_to_ruby.h +0 -246
  49. data/ext/mysql2/wait_for_single_fd.h +0 -36
  50. data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -635
  51. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +0 -11
  52. data/lib/mysql2/console.rb +0 -5
  53. data/spec/configuration.yml.example +0 -17
  54. data/spec/my.cnf.example +0 -9
  55. data/spec/test_data +0 -1
  56. data/support/mysql_enc_to_ruby.rb +0 -82
  57. data/support/ruby_enc_to_mysql.rb +0 -61
data/ext/mysql2/result.h CHANGED
@@ -2,20 +2,17 @@
2
2
  #define MYSQL2_RESULT_H
3
3
 
4
4
  void init_mysql2_result();
5
- VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r);
5
+ VALUE rb_mysql_result_to_obj(MYSQL_RES * r);
6
6
 
7
7
  typedef struct {
8
8
  VALUE fields;
9
9
  VALUE rows;
10
- VALUE client;
11
10
  VALUE encoding;
12
11
  unsigned int numberOfFields;
13
12
  unsigned long numberOfRows;
14
13
  unsigned long lastRowProcessed;
15
- char streamingComplete;
16
14
  char resultFreed;
17
15
  MYSQL_RES *result;
18
- mysql_client_wrapper *client_wrapper;
19
16
  } mysql2_result_wrapper;
20
17
 
21
18
  #define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ # AR adapter for using a fibered mysql2 connection with EM
4
+ # This adapter should be used within Thin or Unicorn with the rack-fiber_pool middleware.
5
+ # Just update your database.yml's adapter to be 'em_mysql2'
6
+
7
+ module ActiveRecord
8
+ class Base
9
+ def self.em_mysql2_connection(config)
10
+ client = ::Mysql2::Fibered::Client.new(config.symbolize_keys)
11
+ options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
12
+ ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
13
+ end
14
+ end
15
+ end
16
+
17
+ require 'fiber'
18
+ require 'eventmachine'
19
+ require 'mysql2'
20
+ require 'active_record/connection_adapters/mysql2_adapter'
21
+ require 'active_record/fiber_patches'
22
+
23
+ module Mysql2
24
+ module Fibered
25
+ class Client < ::Mysql2::Client
26
+ module Watcher
27
+ def initialize(client, deferable)
28
+ @client = client
29
+ @deferable = deferable
30
+ end
31
+
32
+ def notify_readable
33
+ begin
34
+ detach
35
+ results = @client.async_result
36
+ @deferable.succeed(results)
37
+ rescue Exception => e
38
+ @deferable.fail(e)
39
+ end
40
+ end
41
+ end
42
+
43
+ def query(sql, opts={})
44
+ if ::EM.reactor_running?
45
+ super(sql, opts.merge(:async => true))
46
+ deferrable = ::EM::DefaultDeferrable.new
47
+ ::EM.watch(self.socket, Watcher, self, deferrable).notify_readable = true
48
+ fiber = Fiber.current
49
+ deferrable.callback do |result|
50
+ fiber.resume(result)
51
+ end
52
+ deferrable.errback do |err|
53
+ fiber.resume(err)
54
+ end
55
+ Fiber.yield.tap do |result|
56
+ raise result if result.is_a?(Exception)
57
+ end
58
+ else
59
+ super(sql, opts)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,104 @@
1
+ # Necessary monkeypatching to make AR fiber-friendly.
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+
6
+ def self.fiber_pools
7
+ @fiber_pools ||= []
8
+ end
9
+ def self.register_fiber_pool(fp)
10
+ fiber_pools << fp
11
+ end
12
+
13
+ class FiberedMonitor
14
+ class Queue
15
+ def initialize
16
+ @queue = []
17
+ end
18
+
19
+ def wait(timeout)
20
+ t = timeout || 5
21
+ fiber = Fiber.current
22
+ x = EM::Timer.new(t) do
23
+ @queue.delete(fiber)
24
+ fiber.resume(false)
25
+ end
26
+ @queue << fiber
27
+ Fiber.yield.tap do
28
+ x.cancel
29
+ end
30
+ end
31
+
32
+ def signal
33
+ fiber = @queue.pop
34
+ fiber.resume(true) if fiber
35
+ end
36
+ end
37
+
38
+ def synchronize
39
+ yield
40
+ end
41
+
42
+ def new_cond
43
+ Queue.new
44
+ end
45
+ end
46
+
47
+ # ActiveRecord's connection pool is based on threads. Since we are working
48
+ # with EM and a single thread, multiple fiber design, we need to provide
49
+ # our own connection pool that keys off of Fiber.current so that different
50
+ # fibers running in the same thread don't try to use the same connection.
51
+ class ConnectionPool
52
+ def initialize(spec)
53
+ @spec = spec
54
+
55
+ # The cache of reserved connections mapped to threads
56
+ @reserved_connections = {}
57
+
58
+ # The mutex used to synchronize pool access
59
+ @connection_mutex = FiberedMonitor.new
60
+ @queue = @connection_mutex.new_cond
61
+
62
+ # default 5 second timeout unless on ruby 1.9
63
+ @timeout = spec.config[:wait_timeout] || 5
64
+
65
+ # default max pool size to 5
66
+ @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
67
+
68
+ @connections = []
69
+ @checked_out = []
70
+ end
71
+
72
+ def clear_stale_cached_connections!
73
+ cache = @reserved_connections
74
+ keys = Set.new(cache.keys)
75
+
76
+ ActiveRecord::ConnectionAdapters.fiber_pools.each do |pool|
77
+ pool.busy_fibers.each_pair do |object_id, fiber|
78
+ keys.delete(object_id)
79
+ end
80
+ end
81
+
82
+ keys.each do |key|
83
+ next unless cache.has_key?(key)
84
+ checkin cache[key]
85
+ cache.delete(key)
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def current_connection_id #:nodoc:
92
+ Fiber.current.object_id
93
+ end
94
+
95
+ def checkout_and_verify(c)
96
+ @checked_out << c
97
+ c.run_callbacks :checkout
98
+ c.verify!
99
+ c
100
+ end
101
+ end
102
+
103
+ end
104
+ end
data/lib/mysql2.rb CHANGED
@@ -6,8 +6,8 @@ require 'rational' unless RUBY_VERSION >= '1.9.2'
6
6
  require 'mysql2/version' unless defined? Mysql2::VERSION
7
7
  require 'mysql2/error'
8
8
  require 'mysql2/mysql2'
9
- require 'mysql2/result'
10
9
  require 'mysql2/client'
10
+ require 'mysql2/result'
11
11
 
12
12
  # = Mysql2
13
13
  #
@@ -15,22 +15,7 @@ require 'mysql2/client'
15
15
  module Mysql2
16
16
  end
17
17
 
18
- if defined?(ActiveRecord::VERSION::STRING) && ActiveRecord::VERSION::STRING >= "3.1"
19
- warn "============= WARNING FROM mysql2 ============="
20
- warn "This version of mysql2 (#{Mysql2::VERSION}) isn't compatible with Rails 3.1 as the ActiveRecord adapter was pulled into Rails itself."
21
- warn "Please use the 0.3.x (or greater) releases if you plan on using it in Rails >= 3.1.x"
22
- warn "============= END WARNING FROM mysql2 ============="
23
- end
24
-
25
- # For holding utility methods
26
- module Mysql2::Util
27
-
28
- #
29
- # Rekey a string-keyed hash with equivalent symbols.
30
- #
31
- def self.key_hash_as_symbols(hash)
32
- return nil unless hash
33
- Hash[hash.map { |k,v| [k.to_sym, v] }]
34
- end
35
-
36
- end
18
+ if defined?(ActiveRecord) && ActiveRecord::VERSION::STRING < "3.1"
19
+ puts "WARNING: This version of mysql2 (#{Mysql2::VERSION}) doesn't ship with the ActiveRecord adapter bundled anymore as it's now part of Rails 3.1"
20
+ puts "WARNING: Please use the 0.2.x releases if you plan on using it in Rails <= 3.0.x"
21
+ end
data/lib/mysql2/client.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Mysql2
2
2
  class Client
3
- attr_reader :query_options, :read_timeout
3
+ attr_reader :query_options
4
4
  @@default_query_options = {
5
5
  :as => :hash, # the type of object you want each row back as; also supports :array (an array of values)
6
6
  :async => false, # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result
@@ -9,63 +9,35 @@ module Mysql2
9
9
  :database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
10
10
  :application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
11
11
  :cache_rows => true, # tells Mysql2 to use it's internal row cache for results
12
- :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION,
13
- :cast => true,
14
- :default_file => nil,
15
- :default_group => nil
12
+ :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION
16
13
  }
17
14
 
18
15
  def initialize(opts = {})
19
- opts = Mysql2::Util.key_hash_as_symbols( opts )
20
- @read_timeout = nil
21
16
  @query_options = @@default_query_options.dup
22
- @query_options.merge! opts
23
17
 
24
- initialize_ext
18
+ init_connection
25
19
 
26
- # Set default connect_timeout to avoid unlimited retries from signal interruption
27
- opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
28
-
29
- [:reconnect, :connect_timeout, :local_infile, :read_timeout, :write_timeout, :default_file, :default_group, :secure_auth, :init_command].each do |key|
20
+ [:reconnect, :connect_timeout].each do |key|
30
21
  next unless opts.key?(key)
31
- case key
32
- when :reconnect, :local_infile, :secure_auth
33
- send(:"#{key}=", !!opts[key])
34
- when :connect_timeout, :read_timeout, :write_timeout
35
- send(:"#{key}=", opts[key].to_i)
36
- else
37
- send(:"#{key}=", opts[key])
38
- end
22
+ send(:"#{key}=", opts[key])
39
23
  end
40
-
41
24
  # force the encoding to utf8
42
25
  self.charset_name = opts[:encoding] || 'utf8'
43
26
 
44
- ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
45
- ssl_set(*ssl_options) if ssl_options.any?
46
-
47
- if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| @query_options.has_key?(k) }
48
- warn "============= WARNING FROM mysql2 ============="
49
- warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be deprecated at some point in the future."
50
- warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
51
- warn "============= END WARNING FROM mysql2 ========="
27
+ @read_timeout = opts[:read_timeout]
28
+ if @read_timeout and @read_timeout < 0
29
+ raise Mysql2::Error, "read_timeout must be a positive integer, you passed #{@read_timeout}"
52
30
  end
53
31
 
54
- user = opts[:username] || opts[:user]
55
- pass = opts[:password] || opts[:pass]
56
- host = opts[:host] || opts[:hostname]
57
- port = opts[:port]
58
- database = opts[:database] || opts[:dbname] || opts[:db]
59
- socket = opts[:socket] || opts[:sock]
60
- flags = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]
32
+ ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
61
33
 
62
- # Correct the data types before passing these values down to the C level
63
- user = user.to_s unless user.nil?
64
- pass = pass.to_s unless pass.nil?
65
- host = host.to_s unless host.nil?
66
- port = port.to_i unless port.nil?
67
- database = database.to_s unless database.nil?
68
- socket = socket.to_s unless socket.nil?
34
+ user = opts[:username]
35
+ pass = opts[:password]
36
+ host = opts[:host] || 'localhost'
37
+ port = opts[:port] || 3306
38
+ database = opts[:database]
39
+ socket = opts[:socket]
40
+ flags = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]
69
41
 
70
42
  connect user, pass, host, port, database, socket, flags
71
43
  end
@@ -74,12 +46,190 @@ module Mysql2
74
46
  @@default_query_options
75
47
  end
76
48
 
77
- def query_info
78
- info = query_info_string
79
- return {} unless info
80
- info_hash = {}
81
- info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
82
- info_hash
49
+ # NOTE: from ruby-mysql
50
+ if defined? Encoding
51
+ CHARSET_MAP = {
52
+ "armscii8" => nil,
53
+ "ascii" => Encoding::US_ASCII,
54
+ "big5" => Encoding::Big5,
55
+ "binary" => Encoding::ASCII_8BIT,
56
+ "cp1250" => Encoding::Windows_1250,
57
+ "cp1251" => Encoding::Windows_1251,
58
+ "cp1256" => Encoding::Windows_1256,
59
+ "cp1257" => Encoding::Windows_1257,
60
+ "cp850" => Encoding::CP850,
61
+ "cp852" => Encoding::CP852,
62
+ "cp866" => Encoding::IBM866,
63
+ "cp932" => Encoding::Windows_31J,
64
+ "dec8" => nil,
65
+ "eucjpms" => Encoding::EucJP_ms,
66
+ "euckr" => Encoding::EUC_KR,
67
+ "gb2312" => Encoding::EUC_CN,
68
+ "gbk" => Encoding::GBK,
69
+ "geostd8" => nil,
70
+ "greek" => Encoding::ISO_8859_7,
71
+ "hebrew" => Encoding::ISO_8859_8,
72
+ "hp8" => nil,
73
+ "keybcs2" => nil,
74
+ "koi8r" => Encoding::KOI8_R,
75
+ "koi8u" => Encoding::KOI8_U,
76
+ "latin1" => Encoding::ISO_8859_1,
77
+ "latin2" => Encoding::ISO_8859_2,
78
+ "latin5" => Encoding::ISO_8859_9,
79
+ "latin7" => Encoding::ISO_8859_13,
80
+ "macce" => Encoding::MacCentEuro,
81
+ "macroman" => Encoding::MacRoman,
82
+ "sjis" => Encoding::SHIFT_JIS,
83
+ "swe7" => nil,
84
+ "tis620" => Encoding::TIS_620,
85
+ "ucs2" => Encoding::UTF_16BE,
86
+ "ujis" => Encoding::EucJP_ms,
87
+ "utf8" => Encoding::UTF_8,
88
+ }
89
+
90
+ MYSQL_CHARSET_MAP = {
91
+ 1 => {:name => "big5", :collation => "big5_chinese_ci"},
92
+ 2 => {:name => "latin2", :collation => "latin2_czech_cs"},
93
+ 3 => {:name => "dec8", :collation => "dec8_swedish_ci"},
94
+ 4 => {:name => "cp850", :collation => "cp850_general_ci"},
95
+ 5 => {:name => "latin1", :collation => "latin1_german1_ci"},
96
+ 6 => {:name => "hp8", :collation => "hp8_english_ci"},
97
+ 7 => {:name => "koi8r", :collation => "koi8r_general_ci"},
98
+ 8 => {:name => "latin1", :collation => "latin1_swedish_ci"},
99
+ 9 => {:name => "latin2", :collation => "latin2_general_ci"},
100
+ 10 => {:name => "swe7", :collation => "swe7_swedish_ci"},
101
+ 11 => {:name => "ascii", :collation => "ascii_general_ci"},
102
+ 12 => {:name => "ujis", :collation => "ujis_japanese_ci"},
103
+ 13 => {:name => "sjis", :collation => "sjis_japanese_ci"},
104
+ 14 => {:name => "cp1251", :collation => "cp1251_bulgarian_ci"},
105
+ 15 => {:name => "latin1", :collation => "latin1_danish_ci"},
106
+ 16 => {:name => "hebrew", :collation => "hebrew_general_ci"},
107
+ 17 => {:name => "filename", :collation => "filename"},
108
+ 18 => {:name => "tis620", :collation => "tis620_thai_ci"},
109
+ 19 => {:name => "euckr", :collation => "euckr_korean_ci"},
110
+ 20 => {:name => "latin7", :collation => "latin7_estonian_cs"},
111
+ 21 => {:name => "latin2", :collation => "latin2_hungarian_ci"},
112
+ 22 => {:name => "koi8u", :collation => "koi8u_general_ci"},
113
+ 23 => {:name => "cp1251", :collation => "cp1251_ukrainian_ci"},
114
+ 24 => {:name => "gb2312", :collation => "gb2312_chinese_ci"},
115
+ 25 => {:name => "greek", :collation => "greek_general_ci"},
116
+ 26 => {:name => "cp1250", :collation => "cp1250_general_ci"},
117
+ 27 => {:name => "latin2", :collation => "latin2_croatian_ci"},
118
+ 28 => {:name => "gbk", :collation => "gbk_chinese_ci"},
119
+ 29 => {:name => "cp1257", :collation => "cp1257_lithuanian_ci"},
120
+ 30 => {:name => "latin5", :collation => "latin5_turkish_ci"},
121
+ 31 => {:name => "latin1", :collation => "latin1_german2_ci"},
122
+ 32 => {:name => "armscii8", :collation => "armscii8_general_ci"},
123
+ 33 => {:name => "utf8", :collation => "utf8_general_ci"},
124
+ 34 => {:name => "cp1250", :collation => "cp1250_czech_cs"},
125
+ 35 => {:name => "ucs2", :collation => "ucs2_general_ci"},
126
+ 36 => {:name => "cp866", :collation => "cp866_general_ci"},
127
+ 37 => {:name => "keybcs2", :collation => "keybcs2_general_ci"},
128
+ 38 => {:name => "macce", :collation => "macce_general_ci"},
129
+ 39 => {:name => "macroman", :collation => "macroman_general_ci"},
130
+ 40 => {:name => "cp852", :collation => "cp852_general_ci"},
131
+ 41 => {:name => "latin7", :collation => "latin7_general_ci"},
132
+ 42 => {:name => "latin7", :collation => "latin7_general_cs"},
133
+ 43 => {:name => "macce", :collation => "macce_bin"},
134
+ 44 => {:name => "cp1250", :collation => "cp1250_croatian_ci"},
135
+ 47 => {:name => "latin1", :collation => "latin1_bin"},
136
+ 48 => {:name => "latin1", :collation => "latin1_general_ci"},
137
+ 49 => {:name => "latin1", :collation => "latin1_general_cs"},
138
+ 50 => {:name => "cp1251", :collation => "cp1251_bin"},
139
+ 51 => {:name => "cp1251", :collation => "cp1251_general_ci"},
140
+ 52 => {:name => "cp1251", :collation => "cp1251_general_cs"},
141
+ 53 => {:name => "macroman", :collation => "macroman_bin"},
142
+ 57 => {:name => "cp1256", :collation => "cp1256_general_ci"},
143
+ 58 => {:name => "cp1257", :collation => "cp1257_bin"},
144
+ 59 => {:name => "cp1257", :collation => "cp1257_general_ci"},
145
+ 63 => {:name => "binary", :collation => "binary"},
146
+ 64 => {:name => "armscii8", :collation => "armscii8_bin"},
147
+ 65 => {:name => "ascii", :collation => "ascii_bin"},
148
+ 66 => {:name => "cp1250", :collation => "cp1250_bin"},
149
+ 67 => {:name => "cp1256", :collation => "cp1256_bin"},
150
+ 68 => {:name => "cp866", :collation => "cp866_bin"},
151
+ 69 => {:name => "dec8", :collation => "dec8_bin"},
152
+ 70 => {:name => "greek", :collation => "greek_bin"},
153
+ 71 => {:name => "hebrew", :collation => "hebrew_bin"},
154
+ 72 => {:name => "hp8", :collation => "hp8_bin"},
155
+ 73 => {:name => "keybcs2", :collation => "keybcs2_bin"},
156
+ 74 => {:name => "koi8r", :collation => "koi8r_bin"},
157
+ 75 => {:name => "koi8u", :collation => "koi8u_bin"},
158
+ 77 => {:name => "latin2", :collation => "latin2_bin"},
159
+ 78 => {:name => "latin5", :collation => "latin5_bin"},
160
+ 79 => {:name => "latin7", :collation => "latin7_bin"},
161
+ 80 => {:name => "cp850", :collation => "cp850_bin"},
162
+ 81 => {:name => "cp852", :collation => "cp852_bin"},
163
+ 82 => {:name => "swe7", :collation => "swe7_bin"},
164
+ 83 => {:name => "utf8", :collation => "utf8_bin"},
165
+ 84 => {:name => "big5", :collation => "big5_bin"},
166
+ 85 => {:name => "euckr", :collation => "euckr_bin"},
167
+ 86 => {:name => "gb2312", :collation => "gb2312_bin"},
168
+ 87 => {:name => "gbk", :collation => "gbk_bin"},
169
+ 88 => {:name => "sjis", :collation => "sjis_bin"},
170
+ 89 => {:name => "tis620", :collation => "tis620_bin"},
171
+ 90 => {:name => "ucs2", :collation => "ucs2_bin"},
172
+ 91 => {:name => "ujis", :collation => "ujis_bin"},
173
+ 92 => {:name => "geostd8", :collation => "geostd8_general_ci"},
174
+ 93 => {:name => "geostd8", :collation => "geostd8_bin"},
175
+ 94 => {:name => "latin1", :collation => "latin1_spanish_ci"},
176
+ 95 => {:name => "cp932", :collation => "cp932_japanese_ci"},
177
+ 96 => {:name => "cp932", :collation => "cp932_bin"},
178
+ 97 => {:name => "eucjpms", :collation => "eucjpms_japanese_ci"},
179
+ 98 => {:name => "eucjpms", :collation => "eucjpms_bin"},
180
+ 99 => {:name => "cp1250", :collation => "cp1250_polish_ci"},
181
+ 128 => {:name => "ucs2", :collation => "ucs2_unicode_ci"},
182
+ 129 => {:name => "ucs2", :collation => "ucs2_icelandic_ci"},
183
+ 130 => {:name => "ucs2", :collation => "ucs2_latvian_ci"},
184
+ 131 => {:name => "ucs2", :collation => "ucs2_romanian_ci"},
185
+ 132 => {:name => "ucs2", :collation => "ucs2_slovenian_ci"},
186
+ 133 => {:name => "ucs2", :collation => "ucs2_polish_ci"},
187
+ 134 => {:name => "ucs2", :collation => "ucs2_estonian_ci"},
188
+ 135 => {:name => "ucs2", :collation => "ucs2_spanish_ci"},
189
+ 136 => {:name => "ucs2", :collation => "ucs2_swedish_ci"},
190
+ 137 => {:name => "ucs2", :collation => "ucs2_turkish_ci"},
191
+ 138 => {:name => "ucs2", :collation => "ucs2_czech_ci"},
192
+ 139 => {:name => "ucs2", :collation => "ucs2_danish_ci"},
193
+ 140 => {:name => "ucs2", :collation => "ucs2_lithuanian_ci"},
194
+ 141 => {:name => "ucs2", :collation => "ucs2_slovak_ci"},
195
+ 142 => {:name => "ucs2", :collation => "ucs2_spanish2_ci"},
196
+ 143 => {:name => "ucs2", :collation => "ucs2_roman_ci"},
197
+ 144 => {:name => "ucs2", :collation => "ucs2_persian_ci"},
198
+ 145 => {:name => "ucs2", :collation => "ucs2_esperanto_ci"},
199
+ 146 => {:name => "ucs2", :collation => "ucs2_hungarian_ci"},
200
+ 192 => {:name => "utf8", :collation => "utf8_unicode_ci"},
201
+ 193 => {:name => "utf8", :collation => "utf8_icelandic_ci"},
202
+ 194 => {:name => "utf8", :collation => "utf8_latvian_ci"},
203
+ 195 => {:name => "utf8", :collation => "utf8_romanian_ci"},
204
+ 196 => {:name => "utf8", :collation => "utf8_slovenian_ci"},
205
+ 197 => {:name => "utf8", :collation => "utf8_polish_ci"},
206
+ 198 => {:name => "utf8", :collation => "utf8_estonian_ci"},
207
+ 199 => {:name => "utf8", :collation => "utf8_spanish_ci"},
208
+ 200 => {:name => "utf8", :collation => "utf8_swedish_ci"},
209
+ 201 => {:name => "utf8", :collation => "utf8_turkish_ci"},
210
+ 202 => {:name => "utf8", :collation => "utf8_czech_ci"},
211
+ 203 => {:name => "utf8", :collation => "utf8_danish_ci"},
212
+ 204 => {:name => "utf8", :collation => "utf8_lithuanian_ci"},
213
+ 205 => {:name => "utf8", :collation => "utf8_slovak_ci"},
214
+ 206 => {:name => "utf8", :collation => "utf8_spanish2_ci"},
215
+ 207 => {:name => "utf8", :collation => "utf8_roman_ci"},
216
+ 208 => {:name => "utf8", :collation => "utf8_persian_ci"},
217
+ 209 => {:name => "utf8", :collation => "utf8_esperanto_ci"},
218
+ 210 => {:name => "utf8", :collation => "utf8_hungarian_ci"},
219
+ 254 => {:name => "utf8", :collation => "utf8_general_cs"}
220
+ }
221
+
222
+ def self.encoding_from_charset(charset)
223
+ CHARSET_MAP[charset.to_s.downcase]
224
+ end
225
+
226
+ def self.encoding_from_charset_code(code)
227
+ if mapping = MYSQL_CHARSET_MAP[code]
228
+ encoding_from_charset(mapping[:name])
229
+ else
230
+ nil
231
+ end
232
+ end
83
233
  end
84
234
 
85
235
  private