mysql2 0.2.24 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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