activerecord-pedantmysql2-adapter 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +15 -2
- data/lib/active_record/connection_adapters/pedant_mysql2_adapter.rb +1 -1
- data/lib/pedant_mysql2.rb +45 -16
- data/lib/pedant_mysql2/version.rb +1 -1
- data/spec/adapter_spec.rb +73 -14
- data/spec/support/database.rb +1 -0
- metadata +25 -3
- metadata.gz.sig +2 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3edf754b2a2095a7149077c7307326fb63e58851
|
4
|
+
data.tar.gz: e65305e4b6c3f8fb0c682cc890ee010b88405b93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0788ea3fa24672a2b31723dab2fc19cb2b768008515be1d978d19cffa7562d8c988a693770219a64f1380b77a434d22650fda77bb5ec25f3ff9dc0caa1b6f9c2
|
7
|
+
data.tar.gz: b2a18d31f2345eab76fc0f8373a721dd43b81b3c116ca120b9eb52c167330f674babd3d3820875b040fc814bb0f6af096401f4c2effc85a651186b2942406e16
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/README.md
CHANGED
@@ -40,10 +40,14 @@ You can report them to your exception tracker:
|
|
40
40
|
or totally silence them:
|
41
41
|
|
42
42
|
```ruby
|
43
|
-
PedantMysql2.
|
43
|
+
PedantMysql2.silence_warnings!
|
44
44
|
```
|
45
45
|
|
46
|
-
|
46
|
+
and to restore it to raising warnings as errors:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
PedantMysql2.raise_warnings!
|
50
|
+
```
|
47
51
|
|
48
52
|
You can easilly whitelist some types of warnings:
|
49
53
|
|
@@ -59,6 +63,15 @@ warnings = PedantMysql2.capture_warnings do
|
|
59
63
|
end
|
60
64
|
```
|
61
65
|
|
66
|
+
## Thread-safe
|
67
|
+
|
68
|
+
This gem is tested to be thread safe with a couple known exceptions.
|
69
|
+
|
70
|
+
`PedantMysql2.ignore` is not thread safe and should only be called during initialization of your app. Changing this within a thread while another is updating it could be problematic.
|
71
|
+
`PedantMysql2.on_warning=` is not thread safe, this should also be called only during initialization.
|
72
|
+
|
73
|
+
If you find any other parts that are not thread-safe, please create an issue or PR.
|
74
|
+
|
62
75
|
## Development
|
63
76
|
|
64
77
|
Setting up the development environment is very straightforward. In order to keep the test
|
@@ -63,7 +63,7 @@ class ActiveRecord::ConnectionAdapters::PedantMysql2Adapter < ActiveRecord::Conn
|
|
63
63
|
result = @connection.query('SHOW WARNINGS')
|
64
64
|
result.each do |level, code, message|
|
65
65
|
warning = MysqlWarning.new(message, code, level, sql)
|
66
|
-
::PedantMysql2.
|
66
|
+
::PedantMysql2.warn(warning)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
data/lib/pedant_mysql2.rb
CHANGED
@@ -1,34 +1,42 @@
|
|
1
1
|
module PedantMysql2
|
2
2
|
class << self
|
3
|
-
attr_accessor :on_warning
|
4
|
-
|
5
3
|
def capture_warnings
|
6
|
-
|
7
|
-
|
8
|
-
Thread.current[:mysql_warnings] = []
|
9
|
-
self.on_warning = lambda { |warning| Thread.current[:mysql_warnings] << warning }
|
4
|
+
warnings = backup_warnings
|
5
|
+
setup_capture
|
10
6
|
yield
|
11
|
-
|
12
|
-
warnings
|
7
|
+
captured_warnings
|
13
8
|
ensure
|
14
|
-
|
15
|
-
self.on_warning = previous_callback
|
9
|
+
restore_warnings(warnings)
|
16
10
|
end
|
17
11
|
|
18
12
|
def raise_warnings!
|
19
|
-
self.on_warning =
|
13
|
+
self.on_warning = nil
|
20
14
|
end
|
21
15
|
|
22
16
|
def silence_warnings!
|
23
|
-
self.on_warning =
|
17
|
+
self.on_warning = lambda{ |warning| }
|
24
18
|
end
|
25
19
|
|
26
20
|
def ignore(*matchers)
|
27
21
|
self.whitelist.concat(matchers.flatten)
|
28
22
|
end
|
29
23
|
|
30
|
-
def
|
31
|
-
|
24
|
+
def warn(warning)
|
25
|
+
return if ignored?(warning)
|
26
|
+
|
27
|
+
if on_warning
|
28
|
+
on_warning.call(warning)
|
29
|
+
else
|
30
|
+
raise warning
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_warning
|
35
|
+
Thread.current[:__pedant_mysql2_on_warning] || @_on_warning
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_warning=(new_proc)
|
39
|
+
@_on_warning = new_proc
|
32
40
|
end
|
33
41
|
|
34
42
|
protected
|
@@ -37,8 +45,29 @@ module PedantMysql2
|
|
37
45
|
@whitelist ||= []
|
38
46
|
end
|
39
47
|
|
40
|
-
|
48
|
+
def ignored?(warning)
|
49
|
+
whitelist.any? { |matcher| matcher =~ warning.message }
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup_capture
|
53
|
+
Thread.current[:__pedant_mysql2_warnings] = []
|
54
|
+
self.thread_on_warning = lambda { |warning| Thread.current[:__pedant_mysql2_warnings] << warning }
|
55
|
+
end
|
56
|
+
|
57
|
+
def captured_warnings
|
58
|
+
Thread.current[:__pedant_mysql2_warnings]
|
59
|
+
end
|
41
60
|
|
42
|
-
|
61
|
+
def backup_warnings
|
62
|
+
[captured_warnings, Thread.current[:__pedant_mysql2_on_warning]]
|
63
|
+
end
|
64
|
+
|
65
|
+
def restore_warnings(warnings)
|
66
|
+
Thread.current[:__pedant_mysql2_warnings], self.thread_on_warning = *warnings
|
67
|
+
end
|
43
68
|
|
69
|
+
def thread_on_warning=(new_proc)
|
70
|
+
Thread.current[:__pedant_mysql2_on_warning] = new_proc
|
71
|
+
end
|
72
|
+
end
|
44
73
|
end
|
data/spec/adapter_spec.rb
CHANGED
@@ -19,39 +19,56 @@ describe PedantMysql2 do
|
|
19
19
|
PedantMysql2.on_warning = @original_callback
|
20
20
|
end
|
21
21
|
|
22
|
+
def execute_with_warning
|
23
|
+
ActiveRecord::Base.connection.execute('SELECT 1 + "foo"')
|
24
|
+
end
|
25
|
+
|
26
|
+
def wait_for(thread)
|
27
|
+
sleep 0.1 until thread.stop?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Used by the thread-safe testing
|
31
|
+
def method_missing(method_name,*args)
|
32
|
+
if PedantMysql2.respond_to?(method_name, true)
|
33
|
+
PedantMysql2.send(method_name,*args)
|
34
|
+
else
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
22
39
|
it 'raises warnings by default' do
|
23
40
|
expect {
|
24
|
-
|
41
|
+
execute_with_warning
|
25
42
|
}.to raise_error(MysqlWarning, "Truncated incorrect DOUBLE value: 'foo'")
|
26
43
|
end
|
27
44
|
|
28
45
|
it 'can have a whitelist of warnings' do
|
29
46
|
PedantMysql2.ignore(/Truncated incorrect DOUBLE value/i)
|
30
47
|
expect {
|
31
|
-
|
48
|
+
execute_with_warning
|
32
49
|
}.to_not raise_error
|
33
50
|
end
|
34
51
|
|
35
52
|
it 'do not change the returned value' do
|
36
53
|
PedantMysql2.silence_warnings!
|
37
|
-
result =
|
54
|
+
result = execute_with_warning
|
38
55
|
expect(result.to_a).to be == [[1.0]]
|
39
56
|
end
|
40
57
|
|
41
58
|
it 'do not change the returned value of exec_update' do
|
42
|
-
result = connection.update('UPDATE comment SET id = 1 LIMIT 1')
|
59
|
+
result = connection.update('UPDATE comment SET id = 1 ORDER BY id LIMIT 1')
|
43
60
|
expect(result).to be_zero
|
44
61
|
end
|
45
62
|
|
46
63
|
it 'do not change the returned value of exec_delete' do
|
47
|
-
result = connection.delete('DELETE FROM comment LIMIT 1')
|
64
|
+
result = connection.delete('DELETE FROM comment ORDER BY id LIMIT 1')
|
48
65
|
expect(result).to be_zero
|
49
66
|
end
|
50
67
|
|
51
68
|
it 'can easily be raised' do
|
52
69
|
PedantMysql2.on_warning = lambda { |warning| raise warning }
|
53
70
|
expect {
|
54
|
-
|
71
|
+
execute_with_warning
|
55
72
|
}.to raise_error(MysqlWarning)
|
56
73
|
end
|
57
74
|
|
@@ -59,22 +76,64 @@ describe PedantMysql2 do
|
|
59
76
|
warnings = nil
|
60
77
|
expect {
|
61
78
|
warnings = PedantMysql2.capture_warnings do
|
62
|
-
|
79
|
+
execute_with_warning
|
63
80
|
end
|
64
81
|
}.to_not raise_error
|
65
|
-
|
82
|
+
|
66
83
|
expect(warnings.size).to be == 1
|
67
84
|
expect(warnings.first).to be_a MysqlWarning
|
68
85
|
expect(warnings.first.message).to be == "Truncated incorrect DOUBLE value: 'foo'"
|
69
86
|
end
|
70
87
|
|
71
88
|
it 'restores the old value that was stored in the thread_local capture_warnings' do
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
89
|
+
warnings1 = nil
|
90
|
+
warnings2 = nil
|
91
|
+
|
92
|
+
warnings1 = PedantMysql2.capture_warnings do
|
93
|
+
execute_with_warning
|
94
|
+
warnings2 = PedantMysql2.capture_warnings do
|
95
|
+
execute_with_warning
|
96
|
+
execute_with_warning
|
97
|
+
end
|
76
98
|
end
|
77
|
-
|
99
|
+
|
100
|
+
expect(warnings1.size).to be == 1
|
101
|
+
expect(warnings2.size).to be == 2
|
102
|
+
expect(warnings2).to_not include(warnings1)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should be thread-safe to capture_warnings (when class instance variables were used this did not pass)' do
|
106
|
+
thread = Thread.new do
|
107
|
+
warnings = backup_warnings
|
108
|
+
Thread.stop
|
109
|
+
setup_capture
|
110
|
+
Thread.stop
|
111
|
+
execute_with_warning
|
112
|
+
expect(captured_warnings.size).to be == 1
|
113
|
+
restore_warnings(warnings)
|
114
|
+
end
|
115
|
+
|
116
|
+
wait_for(thread)
|
117
|
+
warnings = backup_warnings
|
118
|
+
thread.run
|
119
|
+
wait_for(thread)
|
120
|
+
setup_capture
|
121
|
+
execute_with_warning
|
122
|
+
expect(captured_warnings.size).to be == 1
|
123
|
+
restore_warnings(warnings)
|
124
|
+
thread.run
|
125
|
+
thread.join
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should inherit on_warning from parent thread' do
|
129
|
+
PedantMysql2.silence_warnings!
|
130
|
+
thread = Thread.new do
|
131
|
+
expect {
|
132
|
+
execute_with_warning
|
133
|
+
}.to_not raise_error
|
134
|
+
end
|
135
|
+
|
136
|
+
thread.join
|
78
137
|
end
|
79
138
|
|
80
139
|
describe MysqlWarning do
|
@@ -82,7 +141,7 @@ describe PedantMysql2 do
|
|
82
141
|
subject do
|
83
142
|
begin
|
84
143
|
PedantMysql2.on_warning = lambda { |warning| raise warning }
|
85
|
-
|
144
|
+
execute_with_warning
|
86
145
|
rescue MysqlWarning => exception
|
87
146
|
exception
|
88
147
|
end
|
data/spec/support/database.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-pedantmysql2-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZhZG1p
|
14
|
+
bnMxFzAVBgoJkiaJk/IsZAEZFgdzaG9waWZ5MRMwEQYKCZImiZPyLGQBGRYDY29t
|
15
|
+
MB4XDTE0MDUxNTIwMzM0OFoXDTE1MDUxNTIwMzM0OFowPzEPMA0GA1UEAwwGYWRt
|
16
|
+
aW5zMRcwFQYKCZImiZPyLGQBGRYHc2hvcGlmeTETMBEGCgmSJomT8ixkARkWA2Nv
|
17
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0/81O3e1vh5smcwp2G
|
18
|
+
MpLQ6q0kejQLa65bPYPxdzWA1SYOKyGfw+yR9LdFzsuKpwWzKq6zX35lj1IckWS4
|
19
|
+
bNBEQzxmufUxU0XPM02haFB8fOfDJzdXsWte9Ge4IFwahwn68gpMqN+BvxL+KMYz
|
20
|
+
Iut9YmN44d4LZdsENEIO5vmybuG2vYDz7R56qB0PA+Q2P2CdhymsBad2DQs69FBo
|
21
|
+
uico9V6VMYYctL9lCYdzu9IXrOYNTt88suKIVzzAlHOKeN0Ng5qdztFoTR8sfxDr
|
22
|
+
Ydg3KHl5n47wlpgd8R0f/4b5gGxW+v9pyJCgQnLlRu7DedVSvv7+GMtj3g9r3nhJ
|
23
|
+
KqECAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFI/o
|
24
|
+
maf34HXbUOQsdoLHacEKQgunMB0GA1UdEQQWMBSBEmFkbWluc0BzaG9waWZ5LmNv
|
25
|
+
bTAdBgNVHRIEFjAUgRJhZG1pbnNAc2hvcGlmeS5jb20wDQYJKoZIhvcNAQEFBQAD
|
26
|
+
ggEBADkK9aj5T0HPExsov4EoMWFnO+G7RQ28C30VAfKxnL2UxG6i4XMHVs6Xi94h
|
27
|
+
qXFw1ec9Y2eDUqaolT3bviOk9BB197+A8Vz/k7MC6ci2NE+yDDB7HAC8zU6LAx8Y
|
28
|
+
Iqvw7B/PSZ/pz4bUVFlTATif4mi1vO3lidRkdHRtM7UePSn2rUpOi0gtXBP3bLu5
|
29
|
+
YjHJN7wx5cugMEyroKITG5gL0Nxtu21qtOlHX4Hc4KdE2JqzCPOsS4zsZGhgwhPs
|
30
|
+
fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
|
31
|
+
TConQSX2BnZdhIEYW+cKzEC/bLc=
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
date: 2015-03-30 00:00:00.000000000 Z
|
12
34
|
dependencies:
|
13
35
|
- !ruby/object:Gem::Dependency
|
14
36
|
name: activerecord
|
metadata.gz.sig
ADDED