mysql2 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +90 -52
- data/examples/eventmachine.rb +0 -2
- data/examples/threaded.rb +2 -4
- data/ext/mysql2/client.c +260 -76
- data/ext/mysql2/client.h +2 -47
- data/ext/mysql2/extconf.rb +44 -18
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -8
- data/ext/mysql2/result.c +23 -74
- data/ext/mysql2/statement.c +139 -63
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2/client.rb +50 -31
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +49 -20
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +14 -15
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +6 -6
- data/spec/mysql2/client_spec.rb +318 -237
- data/spec/mysql2/error_spec.rb +4 -10
- data/spec/mysql2/result_spec.rb +124 -158
- data/spec/mysql2/statement_spec.rb +185 -180
- data/spec/spec_helper.rb +79 -61
- data/spec/ssl/gen_certs.sh +1 -1
- data/support/5072E1F5.asc +432 -0
- data/support/mysql_enc_to_ruby.rb +2 -2
- data/support/ruby_enc_to_mysql.rb +5 -5
- metadata +16 -14
data/lib/mysql2/error.rb
CHANGED
@@ -1,32 +1,65 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module Mysql2
|
4
2
|
class Error < StandardError
|
5
3
|
ENCODE_OPTS = {
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:
|
4
|
+
undef: :replace,
|
5
|
+
invalid: :replace,
|
6
|
+
replace: '?'.freeze,
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
ConnectionError = Class.new(Error)
|
10
|
+
TimeoutError = Class.new(Error)
|
11
|
+
|
12
|
+
CODES = {
|
13
|
+
1205 => TimeoutError, # ER_LOCK_WAIT_TIMEOUT
|
14
|
+
|
15
|
+
1044 => ConnectionError, # ER_DBACCESS_DENIED_ERROR
|
16
|
+
1045 => ConnectionError, # ER_ACCESS_DENIED_ERROR
|
17
|
+
1152 => ConnectionError, # ER_ABORTING_CONNECTION
|
18
|
+
1153 => ConnectionError, # ER_NET_PACKET_TOO_LARGE
|
19
|
+
1154 => ConnectionError, # ER_NET_READ_ERROR_FROM_PIPE
|
20
|
+
1155 => ConnectionError, # ER_NET_FCNTL_ERROR
|
21
|
+
1156 => ConnectionError, # ER_NET_PACKETS_OUT_OF_ORDER
|
22
|
+
1157 => ConnectionError, # ER_NET_UNCOMPRESS_ERROR
|
23
|
+
1158 => ConnectionError, # ER_NET_READ_ERROR
|
24
|
+
1159 => ConnectionError, # ER_NET_READ_INTERRUPTED
|
25
|
+
1160 => ConnectionError, # ER_NET_ERROR_ON_WRITE
|
26
|
+
1161 => ConnectionError, # ER_NET_WRITE_INTERRUPTED
|
27
|
+
|
28
|
+
2001 => ConnectionError, # CR_SOCKET_CREATE_ERROR
|
29
|
+
2002 => ConnectionError, # CR_CONNECTION_ERROR
|
30
|
+
2003 => ConnectionError, # CR_CONN_HOST_ERROR
|
31
|
+
2004 => ConnectionError, # CR_IPSOCK_ERROR
|
32
|
+
2005 => ConnectionError, # CR_UNKNOWN_HOST
|
33
|
+
2006 => ConnectionError, # CR_SERVER_GONE_ERROR
|
34
|
+
2007 => ConnectionError, # CR_VERSION_ERROR
|
35
|
+
2009 => ConnectionError, # CR_WRONG_HOST_INFO
|
36
|
+
2012 => ConnectionError, # CR_SERVER_HANDSHAKE_ERR
|
37
|
+
2013 => ConnectionError, # CR_SERVER_LOST
|
38
|
+
2020 => ConnectionError, # CR_NET_PACKET_TOO_LARGE
|
39
|
+
2026 => ConnectionError, # CR_SSL_CONNECTION_ERROR
|
40
|
+
2027 => ConnectionError, # CR_MALFORMED_PACKET
|
41
|
+
2047 => ConnectionError, # CR_CONN_UNKNOW_PROTOCOL
|
42
|
+
2048 => ConnectionError, # CR_INVALID_CONN_HANDLE
|
43
|
+
2049 => ConnectionError, # CR_UNUSED_1
|
9
44
|
}.freeze
|
10
45
|
|
11
46
|
attr_reader :error_number, :sql_state
|
12
47
|
|
13
48
|
# Mysql gem compatibility
|
14
|
-
|
15
|
-
|
49
|
+
alias errno error_number
|
50
|
+
alias error message
|
16
51
|
|
17
|
-
def initialize(msg)
|
18
|
-
@server_version
|
52
|
+
def initialize(msg, server_version = nil, error_number = nil, sql_state = nil)
|
53
|
+
@server_version = server_version
|
54
|
+
@error_number = error_number
|
55
|
+
@sql_state = sql_state ? sql_state.encode(ENCODE_OPTS) : nil
|
19
56
|
|
20
57
|
super(clean_message(msg))
|
21
58
|
end
|
22
59
|
|
23
60
|
def self.new_with_args(msg, server_version, error_number, sql_state)
|
24
|
-
|
25
|
-
|
26
|
-
err.instance_variable_set('@error_number', error_number)
|
27
|
-
err.instance_variable_set('@sql_state', sql_state.respond_to?(:encode) ? sql_state.encode(ENCODE_OPTS) : sql_state)
|
28
|
-
err.send(:initialize, msg)
|
29
|
-
err
|
61
|
+
error_class = CODES.fetch(error_number, self)
|
62
|
+
error_class.new(msg, server_version, error_number, sql_state)
|
30
63
|
end
|
31
64
|
|
32
65
|
private
|
@@ -55,12 +88,8 @@ module Mysql2
|
|
55
88
|
# encoding, we'll assume UTF-8 and clean the string of anything that's not a
|
56
89
|
# valid UTF-8 character.
|
57
90
|
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# Returns a valid UTF-8 string in Ruby 1.9+, the original string on Ruby 1.8
|
91
|
+
# Returns a valid UTF-8 string.
|
61
92
|
def clean_message(message)
|
62
|
-
return message unless message.respond_to?(:encode)
|
63
|
-
|
64
93
|
if @server_version && @server_version > 50500
|
65
94
|
message.encode(ENCODE_OPTS)
|
66
95
|
else
|
data/lib/mysql2/result.rb
CHANGED
data/lib/mysql2/statement.rb
CHANGED
@@ -2,15 +2,9 @@ module Mysql2
|
|
2
2
|
class Statement
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
_execute(*args)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
else
|
12
|
-
def execute(*args)
|
13
|
-
_execute(*args)
|
5
|
+
def execute(*args, **kwargs)
|
6
|
+
Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_CLASS => :never) do
|
7
|
+
_execute(*args, **kwargs)
|
14
8
|
end
|
15
9
|
end
|
16
10
|
end
|
data/lib/mysql2/version.rb
CHANGED
data/lib/mysql2.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'date'
|
3
2
|
require 'bigdecimal'
|
4
|
-
require 'rational' unless RUBY_VERSION >= '1.9.2'
|
5
3
|
|
6
4
|
# Load libmysql.dll before requiring mysql2/mysql2.so
|
7
5
|
# This gives a chance to be flexible about the load path
|
@@ -13,16 +11,20 @@ if RUBY_PLATFORM =~ /mswin|mingw/
|
|
13
11
|
ENV['RUBY_MYSQL2_LIBMYSQL_DLL']
|
14
12
|
elsif File.exist?(File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__)))
|
15
13
|
# Use vendor/libmysql.dll if it exists, convert slashes for Win32 LoadLibrary
|
16
|
-
File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__))
|
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
17
|
else
|
18
18
|
# This will use default / system library paths
|
19
19
|
'libmysql.dll'
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -71,14 +73,11 @@ module Mysql2
|
|
71
73
|
# Timeout::ExitException was removed in Ruby 2.3.0, 2.2.3, and 2.1.8,
|
72
74
|
# but is present in earlier 2.1.x and 2.2.x, so we provide a shim.
|
73
75
|
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
else
|
80
|
-
::Timeout::Error
|
81
|
-
end
|
76
|
+
require 'timeout'
|
77
|
+
TIMEOUT_ERROR_CLASS = if defined?(::Timeout::ExitException)
|
78
|
+
::Timeout::ExitException
|
79
|
+
else
|
80
|
+
::Timeout::Error
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
data/spec/em/em_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'spec_helper'
|
3
2
|
begin
|
4
3
|
require 'eventmachine'
|
@@ -49,13 +48,13 @@ begin
|
|
49
48
|
end
|
50
49
|
|
51
50
|
it "should not swallow exceptions raised in callbacks" do
|
52
|
-
expect
|
51
|
+
expect do
|
53
52
|
EM.run do
|
54
53
|
client = Mysql2::EM::Client.new DatabaseCredentials['root']
|
55
54
|
defer = client.query "SELECT sleep(0.1) as first_query"
|
56
55
|
defer.callback do
|
57
56
|
client.close
|
58
|
-
|
57
|
+
raise 'some error'
|
59
58
|
end
|
60
59
|
defer.errback do
|
61
60
|
# This _shouldn't_ be run, but it needed to prevent the specs from
|
@@ -63,13 +62,14 @@ begin
|
|
63
62
|
EM.stop_event_loop
|
64
63
|
end
|
65
64
|
end
|
66
|
-
|
65
|
+
end.to raise_error('some error')
|
67
66
|
end
|
68
67
|
|
69
68
|
context 'when an exception is raised by the client' do
|
70
69
|
let(:client) { Mysql2::EM::Client.new DatabaseCredentials['root'] }
|
71
70
|
let(:error) { StandardError.new('some error') }
|
72
71
|
before { allow(client).to receive(:async_result).and_raise(error) }
|
72
|
+
after { client.close }
|
73
73
|
|
74
74
|
it "should swallow exceptions raised in by the client" do
|
75
75
|
errors = []
|
@@ -122,9 +122,9 @@ begin
|
|
122
122
|
end
|
123
123
|
EM.add_timer(0.1) do
|
124
124
|
expect(callbacks_run).to eq([:callback])
|
125
|
-
expect
|
125
|
+
expect do
|
126
126
|
client.close
|
127
|
-
|
127
|
+
end.not_to raise_error
|
128
128
|
EM.stop_event_loop
|
129
129
|
end
|
130
130
|
end
|