mysql2 0.3.1 → 0.5.2

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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -151
  3. data/LICENSE +21 -0
  4. data/README.md +634 -0
  5. data/examples/eventmachine.rb +1 -3
  6. data/examples/threaded.rb +5 -9
  7. data/ext/mysql2/client.c +1154 -342
  8. data/ext/mysql2/client.h +20 -33
  9. data/ext/mysql2/extconf.rb +229 -37
  10. data/ext/mysql2/infile.c +122 -0
  11. data/ext/mysql2/infile.h +1 -0
  12. data/ext/mysql2/mysql2_ext.c +3 -1
  13. data/ext/mysql2/mysql2_ext.h +18 -16
  14. data/ext/mysql2/mysql_enc_name_to_ruby.h +168 -0
  15. data/ext/mysql2/mysql_enc_to_ruby.h +259 -0
  16. data/ext/mysql2/result.c +708 -191
  17. data/ext/mysql2/result.h +15 -6
  18. data/ext/mysql2/statement.c +602 -0
  19. data/ext/mysql2/statement.h +17 -0
  20. data/ext/mysql2/wait_for_single_fd.h +37 -0
  21. data/lib/mysql2.rb +69 -7
  22. data/lib/mysql2/client.rb +126 -211
  23. data/lib/mysql2/console.rb +5 -0
  24. data/lib/mysql2/em.rb +24 -8
  25. data/lib/mysql2/error.rb +93 -8
  26. data/lib/mysql2/field.rb +3 -0
  27. data/lib/mysql2/result.rb +2 -0
  28. data/lib/mysql2/statement.rb +11 -0
  29. data/lib/mysql2/version.rb +2 -2
  30. data/spec/configuration.yml.example +11 -0
  31. data/spec/em/em_spec.rb +101 -15
  32. data/spec/my.cnf.example +9 -0
  33. data/spec/mysql2/client_spec.rb +874 -232
  34. data/spec/mysql2/error_spec.rb +55 -46
  35. data/spec/mysql2/result_spec.rb +306 -154
  36. data/spec/mysql2/statement_spec.rb +712 -0
  37. data/spec/spec_helper.rb +103 -57
  38. data/spec/ssl/ca-cert.pem +17 -0
  39. data/spec/ssl/ca-key.pem +27 -0
  40. data/spec/ssl/ca.cnf +22 -0
  41. data/spec/ssl/cert.cnf +22 -0
  42. data/spec/ssl/client-cert.pem +17 -0
  43. data/spec/ssl/client-key.pem +27 -0
  44. data/spec/ssl/client-req.pem +15 -0
  45. data/spec/ssl/gen_certs.sh +48 -0
  46. data/spec/ssl/pkcs8-client-key.pem +28 -0
  47. data/spec/ssl/pkcs8-server-key.pem +28 -0
  48. data/spec/ssl/server-cert.pem +17 -0
  49. data/spec/ssl/server-key.pem +27 -0
  50. data/spec/ssl/server-req.pem +15 -0
  51. data/spec/test_data +1 -0
  52. data/support/5072E1F5.asc +432 -0
  53. data/support/libmysql.def +219 -0
  54. data/support/mysql_enc_to_ruby.rb +81 -0
  55. data/support/ruby_enc_to_mysql.rb +61 -0
  56. metadata +82 -188
  57. data/.gitignore +0 -12
  58. data/.rspec +0 -2
  59. data/.rvmrc +0 -1
  60. data/Gemfile +0 -3
  61. data/MIT-LICENSE +0 -20
  62. data/README.rdoc +0 -257
  63. data/Rakefile +0 -5
  64. data/benchmark/active_record.rb +0 -51
  65. data/benchmark/active_record_threaded.rb +0 -42
  66. data/benchmark/allocations.rb +0 -33
  67. data/benchmark/escape.rb +0 -36
  68. data/benchmark/query_with_mysql_casting.rb +0 -80
  69. data/benchmark/query_without_mysql_casting.rb +0 -47
  70. data/benchmark/sequel.rb +0 -37
  71. data/benchmark/setup_db.rb +0 -119
  72. data/benchmark/threaded.rb +0 -44
  73. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +0 -64
  74. data/lib/active_record/fiber_patches.rb +0 -104
  75. data/lib/mysql2/em_fiber.rb +0 -31
  76. data/mysql2.gemspec +0 -32
  77. data/spec/em/em_fiber_spec.rb +0 -22
  78. data/tasks/benchmarks.rake +0 -20
  79. data/tasks/compile.rake +0 -71
  80. data/tasks/rspec.rake +0 -16
  81. data/tasks/vendor_mysql.rake +0 -40
@@ -0,0 +1,17 @@
1
+ #ifndef MYSQL2_STATEMENT_H
2
+ #define MYSQL2_STATEMENT_H
3
+
4
+ typedef struct {
5
+ VALUE client;
6
+ MYSQL_STMT *stmt;
7
+ int refcount;
8
+ int closed;
9
+ } mysql_stmt_wrapper;
10
+
11
+ void init_mysql2_statement(void);
12
+ void decr_mysql2_stmt(mysql_stmt_wrapper *stmt_wrapper);
13
+
14
+ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql);
15
+ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) RB_MYSQL_NORETURN;
16
+
17
+ #endif
@@ -0,0 +1,37 @@
1
+ /*
2
+ * backwards compatibility for Rubinius. See
3
+ * https://github.com/rubinius/rubinius/issues/3771.
4
+ *
5
+ * Ruby 1.9.3 provides this API which allows the use of ppoll() on Linux
6
+ * to minimize select() and malloc() overhead on high-numbered FDs.
7
+ */
8
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
9
+ # include <ruby/io.h>
10
+ #else
11
+ # define RB_WAITFD_IN 0x001
12
+ # define RB_WAITFD_PRI 0x002
13
+ # define RB_WAITFD_OUT 0x004
14
+
15
+ static int my_wait_for_single_fd(int fd, int events, struct timeval *tvp)
16
+ {
17
+ fd_set fdset;
18
+ fd_set *rfds = NULL;
19
+ fd_set *wfds = NULL;
20
+ fd_set *efds = NULL;
21
+
22
+ FD_ZERO(&fdset);
23
+ FD_SET(fd, &fdset);
24
+
25
+ if (events & RB_WAITFD_IN)
26
+ rfds = &fdset;
27
+ if (events & RB_WAITFD_OUT)
28
+ wfds = &fdset;
29
+ if (events & RB_WAITFD_PRI)
30
+ efds = &fdset;
31
+
32
+ return rb_thread_select(fd + 1, rfds, wfds, efds, tvp);
33
+ }
34
+
35
+ #define rb_wait_for_single_fd(fd,events,tvp) \
36
+ my_wait_for_single_fd((fd),(events),(tvp))
37
+ #endif
data/lib/mysql2.rb CHANGED
@@ -1,13 +1,40 @@
1
- # encoding: UTF-8
2
1
  require 'date'
3
2
  require 'bigdecimal'
4
- require 'rational' unless RUBY_VERSION >= '1.9.2'
3
+
4
+ # Load libmysql.dll before requiring mysql2/mysql2.so
5
+ # This gives a chance to be flexible about the load path
6
+ # Or to bomb out with a clear error message instead of a linker crash
7
+ if RUBY_PLATFORM =~ /mswin|mingw/
8
+ dll_path = if ENV['RUBY_MYSQL2_LIBMYSQL_DLL']
9
+ # If this environment variable is set, it overrides any other paths
10
+ # The user is advised to use backslashes not forward slashes
11
+ ENV['RUBY_MYSQL2_LIBMYSQL_DLL']
12
+ elsif File.exist?(File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__)))
13
+ # Use vendor/libmysql.dll if it exists, convert slashes for Win32 LoadLibrary
14
+ File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__))
15
+ elsif defined?(RubyInstaller)
16
+ # RubyInstaller-2.4+ native build doesn't need DLL preloading
17
+ else
18
+ # This will use default / system library paths
19
+ 'libmysql.dll'
20
+ end
21
+
22
+ if dll_path
23
+ require 'Win32API'
24
+ LoadLibrary = Win32API.new('Kernel32', 'LoadLibrary', ['P'], 'I')
25
+ if LoadLibrary.call(dll_path).zero?
26
+ abort "Failed to load libmysql.dll from #{dll_path}"
27
+ end
28
+ end
29
+ end
5
30
 
6
31
  require 'mysql2/version' unless defined? Mysql2::VERSION
7
32
  require 'mysql2/error'
8
33
  require 'mysql2/mysql2'
9
- require 'mysql2/client'
10
34
  require 'mysql2/result'
35
+ require 'mysql2/client'
36
+ require 'mysql2/field'
37
+ require 'mysql2/statement'
11
38
 
12
39
  # = Mysql2
13
40
  #
@@ -15,7 +42,42 @@ require 'mysql2/result'
15
42
  module Mysql2
16
43
  end
17
44
 
18
- if defined?(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
45
+ if defined?(ActiveRecord::VERSION::STRING) && ActiveRecord::VERSION::STRING < "3.1"
46
+ begin
47
+ require 'active_record/connection_adapters/mysql2_adapter'
48
+ rescue LoadError
49
+ warn "============= WARNING FROM mysql2 ============="
50
+ warn "This version of mysql2 (#{Mysql2::VERSION}) doesn't ship with the ActiveRecord adapter."
51
+ warn "In Rails version 3.1.0 and up, the mysql2 ActiveRecord adapter is included with rails."
52
+ warn "If you want to use the mysql2 gem with Rails <= 3.0.x, please use the latest mysql2 in the 0.2.x series."
53
+ warn "============= END WARNING FROM mysql2 ============="
54
+ end
55
+ end
56
+
57
+ # For holding utility methods
58
+ module Mysql2
59
+ module Util
60
+ #
61
+ # Rekey a string-keyed hash with equivalent symbols.
62
+ #
63
+ def self.key_hash_as_symbols(hash)
64
+ return nil unless hash
65
+ Hash[hash.map { |k, v| [k.to_sym, v] }]
66
+ end
67
+
68
+ #
69
+ # In Mysql2::Client#query and Mysql2::Statement#execute,
70
+ # Thread#handle_interrupt is used to prevent Timeout#timeout
71
+ # from interrupting query execution.
72
+ #
73
+ # Timeout::ExitException was removed in Ruby 2.3.0, 2.2.3, and 2.1.8,
74
+ # but is present in earlier 2.1.x and 2.2.x, so we provide a shim.
75
+ #
76
+ require 'timeout'
77
+ TIMEOUT_ERROR_CLASS = if defined?(::Timeout::ExitException)
78
+ ::Timeout::ExitException
79
+ else
80
+ ::Timeout::Error
81
+ end
82
+ end
83
+ end
data/lib/mysql2/client.rb CHANGED
@@ -1,240 +1,155 @@
1
1
  module Mysql2
2
2
  class Client
3
- attr_reader :query_options
4
- @@default_query_options = {
5
- :as => :hash, # the type of object you want each row back as; also supports :array (an array of values)
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
7
- :cast_booleans => false, # cast tinyint(1) fields as true/false in ruby
8
- :symbolize_keys => false, # return field names as symbols instead of strings
9
- :database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
10
- :application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
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
- }
3
+ attr_reader :query_options, :read_timeout
4
+
5
+ def self.default_query_options
6
+ @default_query_options ||= {
7
+ as: :hash, # the type of object you want each row back as; also supports :array (an array of values)
8
+ 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
+ cast_booleans: false, # cast tinyint(1) fields as true/false in ruby
10
+ symbolize_keys: false, # return field names as symbols instead of strings
11
+ database_timezone: :local, # timezone Mysql2 will assume datetime objects are stored in
12
+ application_timezone: nil, # timezone Mysql2 will convert to before handing the object back to the caller
13
+ cache_rows: true, # tells Mysql2 to use its internal row cache for results
14
+ connect_flags: REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | CONNECT_ATTRS,
15
+ cast: true,
16
+ default_file: nil,
17
+ default_group: nil,
18
+ }
19
+ end
14
20
 
15
21
  def initialize(opts = {})
16
- @query_options = @@default_query_options.dup
22
+ raise Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash
23
+ opts = Mysql2::Util.key_hash_as_symbols(opts)
24
+ @read_timeout = nil
25
+ @query_options = self.class.default_query_options.dup
26
+ @query_options.merge! opts
17
27
 
18
- init_connection
28
+ initialize_ext
19
29
 
20
- [:reconnect, :connect_timeout].each do |key|
30
+ # Set default connect_timeout to avoid unlimited retries from signal interruption
31
+ opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
32
+
33
+ # TODO: stricter validation rather than silent massaging
34
+ %i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin].each do |key|
21
35
  next unless opts.key?(key)
22
- send(:"#{key}=", opts[key])
36
+ case key
37
+ when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin
38
+ send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation
39
+ when :connect_timeout, :read_timeout, :write_timeout
40
+ send(:"#{key}=", Integer(opts[key])) unless opts[key].nil?
41
+ else
42
+ send(:"#{key}=", opts[key])
43
+ end
23
44
  end
45
+
24
46
  # force the encoding to utf8
25
47
  self.charset_name = opts[:encoding] || 'utf8'
26
48
 
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}"
49
+ ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
50
+ ssl_set(*ssl_options) if ssl_options.any? || opts.key?(:sslverify)
51
+ self.ssl_mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode]
52
+
53
+ flags = case opts[:flags]
54
+ when Array
55
+ parse_flags_array(opts[:flags], @query_options[:connect_flags])
56
+ when String
57
+ parse_flags_array(opts[:flags].split(' '), @query_options[:connect_flags])
58
+ when Integer
59
+ @query_options[:connect_flags] | opts[:flags]
60
+ else
61
+ @query_options[:connect_flags]
30
62
  end
31
63
 
32
- ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
64
+ # SSL verify is a connection flag rather than a mysql_ssl_set option
65
+ flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify]
33
66
 
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]
67
+ if %i[user pass hostname dbname db sock].any? { |k| @query_options.key?(k) }
68
+ warn "============= WARNING FROM mysql2 ============="
69
+ warn "The options :user, :pass, :hostname, :dbname, :db, and :sock are deprecated and will be removed at some point in the future."
70
+ warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
71
+ warn "============= END WARNING FROM mysql2 ========="
72
+ end
41
73
 
42
- connect user, pass, host, port, database, socket, flags
43
- end
74
+ user = opts[:username] || opts[:user]
75
+ pass = opts[:password] || opts[:pass]
76
+ host = opts[:host] || opts[:hostname]
77
+ port = opts[:port]
78
+ database = opts[:database] || opts[:dbname] || opts[:db]
79
+ socket = opts[:socket] || opts[:sock]
44
80
 
45
- def self.default_query_options
46
- @@default_query_options
47
- end
48
-
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
- }
81
+ # Correct the data types before passing these values down to the C level
82
+ user = user.to_s unless user.nil?
83
+ pass = pass.to_s unless pass.nil?
84
+ host = host.to_s unless host.nil?
85
+ port = port.to_i unless port.nil?
86
+ database = database.to_s unless database.nil?
87
+ socket = socket.to_s unless socket.nil?
88
+ conn_attrs = parse_connect_attrs(opts[:connect_attrs])
89
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
- }
90
+ connect user, pass, host, port, database, socket, flags, conn_attrs
91
+ end
221
92
 
222
- def self.encoding_from_charset(charset)
223
- CHARSET_MAP[charset.to_s.downcase]
93
+ def parse_ssl_mode(mode)
94
+ m = mode.to_s.upcase
95
+ if m.start_with?('SSL_MODE_')
96
+ return Mysql2::Client.const_get(m) if Mysql2::Client.const_defined?(m)
97
+ else
98
+ x = 'SSL_MODE_' + m
99
+ return Mysql2::Client.const_get(x) if Mysql2::Client.const_defined?(x)
224
100
  end
101
+ warn "Unknown MySQL ssl_mode flag: #{mode}"
102
+ end
225
103
 
226
- def self.encoding_from_charset_code(code)
227
- if mapping = MYSQL_CHARSET_MAP[code]
228
- encoding_from_charset(mapping[:name])
104
+ def parse_flags_array(flags, initial = 0)
105
+ flags.reduce(initial) do |memo, f|
106
+ fneg = f.start_with?('-') ? f[1..-1] : nil
107
+ if fneg && fneg =~ /^\w+$/ && Mysql2::Client.const_defined?(fneg)
108
+ memo & ~ Mysql2::Client.const_get(fneg)
109
+ elsif f && f =~ /^\w+$/ && Mysql2::Client.const_defined?(f)
110
+ memo | Mysql2::Client.const_get(f)
229
111
  else
230
- nil
112
+ warn "Unknown MySQL connection flag: '#{f}'"
113
+ memo
231
114
  end
232
115
  end
233
116
  end
234
117
 
235
- private
236
- def self.local_offset
118
+ # Set default program_name in performance_schema.session_connect_attrs
119
+ # and performance_schema.session_account_connect_attrs
120
+ def parse_connect_attrs(conn_attrs)
121
+ return {} if Mysql2::Client::CONNECT_ATTRS.zero?
122
+ conn_attrs ||= {}
123
+ conn_attrs[:program_name] ||= $PROGRAM_NAME
124
+ conn_attrs.each_with_object({}) do |(key, value), hash|
125
+ hash[key.to_s] = value.to_s
126
+ end
127
+ end
128
+
129
+ def query(sql, options = {})
130
+ Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_CLASS => :never) do
131
+ _query(sql, @query_options.merge(options))
132
+ end
133
+ end
134
+
135
+ def query_info
136
+ info = query_info_string
137
+ return {} unless info
138
+ info_hash = {}
139
+ info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
140
+ info_hash
141
+ end
142
+
143
+ def info
144
+ self.class.info
145
+ end
146
+
147
+ class << self
148
+ private
149
+
150
+ def local_offset
237
151
  ::Time.local(2010).utc_offset.to_r / 86400
238
152
  end
153
+ end
239
154
  end
240
155
  end