mysql_framework 2.0.0 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mysql_framework/connector.rb +14 -5
- data/lib/mysql_framework/sql_condition.rb +5 -0
- data/lib/mysql_framework/sql_query.rb +3 -0
- data/lib/mysql_framework/version.rb +1 -1
- data/spec/lib/mysql_framework/connector_spec.rb +74 -0
- data/spec/lib/mysql_framework/sql_condition_spec.rb +30 -0
- data/spec/lib/mysql_framework/sql_query_spec.rb +13 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38653f6e3d1d849566574e58eb8386b4c32890370404cb3eade583b0070f5041
|
4
|
+
data.tar.gz: 5534eca9f224d13580cfd09f4e2478208857e5b353c9a664ed7b772bf8a088e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa4e726ac90ac8b1ecd8ca20a64b4c33e81d003c395b49c340f712df500fc7879956f5479f9c23e53fe20ca947d41d2798ad42732c596a03ab219129f02a7dbd
|
7
|
+
data.tar.gz: ba2080bb5f7595b82996a48a0316ed70cf7560b5687abb9d5c9768c73f5e2b296e42378aa9139c80e2d5f705a8fa7bdb08167a740c019a6d5d0a0825436873e7
|
@@ -59,10 +59,9 @@ module MysqlFramework
|
|
59
59
|
|
60
60
|
# This method is called to check a client back in to the connection when no longer needed.
|
61
61
|
def check_in(client)
|
62
|
-
return client
|
63
|
-
|
64
|
-
client = new_client if client.closed?
|
62
|
+
return client&.close unless connection_pool_enabled?
|
65
63
|
|
64
|
+
client = new_client if client.nil? || client.closed?
|
66
65
|
@connection_pool.push(client)
|
67
66
|
end
|
68
67
|
|
@@ -75,10 +74,20 @@ module MysqlFramework
|
|
75
74
|
end
|
76
75
|
|
77
76
|
# This method is called to execute a prepared statement
|
77
|
+
#
|
78
|
+
# @note Ensure we free any result and close each statement, otherwise we
|
79
|
+
# can run into a 'Commands out of sync' error if multiple threads are
|
80
|
+
# running different queries at the same time.
|
78
81
|
def execute(query, provided_client = nil)
|
79
82
|
with_client(provided_client) do |client|
|
80
|
-
|
81
|
-
|
83
|
+
begin
|
84
|
+
statement = client.prepare(query.sql)
|
85
|
+
result = statement.execute(*query.params)
|
86
|
+
result&.to_a
|
87
|
+
ensure
|
88
|
+
result&.free
|
89
|
+
statement&.close
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
@@ -50,7 +50,12 @@ module MysqlFramework
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def invalid_nil_value?(value)
|
53
|
+
return false if skip_nil_validation?
|
53
54
|
nil_comparison? == false && value.nil?
|
54
55
|
end
|
56
|
+
|
57
|
+
def skip_nil_validation?
|
58
|
+
ENV.fetch('MYSQL_FRAMEWORK_SKIP_NIL_VALUE_VALIDATION', 'false').downcase == 'true'
|
59
|
+
end
|
55
60
|
end
|
56
61
|
end
|
@@ -120,11 +120,14 @@ module MysqlFramework
|
|
120
120
|
end
|
121
121
|
|
122
122
|
# This method is called to specify a where clause for a query.
|
123
|
+
#
|
124
|
+
# Condition values are added to @params unless the value is nil.
|
123
125
|
def where(*conditions)
|
124
126
|
@sql += ' WHERE' unless @sql.include?('WHERE')
|
125
127
|
@sql += " (#{conditions.join(' AND ')}) "
|
126
128
|
|
127
129
|
conditions.each do |condition|
|
130
|
+
next if condition.value.nil?
|
128
131
|
if condition.value.is_a?(Enumerable)
|
129
132
|
@params.concat(condition.value)
|
130
133
|
else
|
@@ -232,6 +232,24 @@ describe MysqlFramework::Connector do
|
|
232
232
|
subject.check_in(client)
|
233
233
|
end
|
234
234
|
end
|
235
|
+
|
236
|
+
context 'when client is nil' do
|
237
|
+
let(:client) { nil }
|
238
|
+
|
239
|
+
context 'when connection pooling is enabled' do
|
240
|
+
it 'does not raise an error' do
|
241
|
+
expect { subject.check_in(client) }.not_to raise_error
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'when connection pooling is disabled' do
|
246
|
+
let(:connection_pooling_enabled) { 'false' }
|
247
|
+
|
248
|
+
it 'does not raise an error' do
|
249
|
+
expect { subject.check_in(client) }.not_to raise_error
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
235
253
|
end
|
236
254
|
|
237
255
|
describe '#with_client' do
|
@@ -272,6 +290,62 @@ describe MysqlFramework::Connector do
|
|
272
290
|
expect(results.length).to eq(1)
|
273
291
|
expect(results[0][:id]).to eq(guid)
|
274
292
|
end
|
293
|
+
|
294
|
+
context 'when cleaning up resources' do
|
295
|
+
let(:mock_client) { double('client') }
|
296
|
+
let(:mock_statement) { double('statement') }
|
297
|
+
let(:mock_result) { double('result') }
|
298
|
+
let(:select_query) { MysqlFramework::SqlQuery.new.select('*').from('demo') }
|
299
|
+
|
300
|
+
before do
|
301
|
+
allow(mock_result).to receive(:to_a)
|
302
|
+
allow(mock_result).to receive(:free)
|
303
|
+
|
304
|
+
allow(mock_statement).to receive(:close)
|
305
|
+
allow(mock_statement).to receive(:execute).and_return(mock_result)
|
306
|
+
|
307
|
+
allow(mock_client).to receive(:prepare).and_return(mock_statement)
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'frees the result' do
|
311
|
+
expect(mock_result).to receive(:free)
|
312
|
+
|
313
|
+
subject.execute(select_query, mock_client)
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'closes the statement' do
|
317
|
+
expect(mock_statement).to receive(:close)
|
318
|
+
|
319
|
+
subject.execute(select_query, mock_client)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'does not raise a commands out of sync error' do
|
324
|
+
threads = []
|
325
|
+
threads << Thread.new do
|
326
|
+
350.times do
|
327
|
+
update_query = MysqlFramework::SqlQuery.new.update('gems')
|
328
|
+
.set(updated_at: Time.now)
|
329
|
+
expect { subject.execute(update_query) }.not_to raise_error
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
threads << Thread.new do
|
334
|
+
350.times do
|
335
|
+
select_query = MysqlFramework::SqlQuery.new.select('*').from('demo')
|
336
|
+
expect { subject.execute(select_query) }.not_to raise_error
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
threads << Thread.new do
|
341
|
+
350.times do
|
342
|
+
select_query = MysqlFramework::SqlQuery.new.select('*').from('test')
|
343
|
+
expect { subject.execute(select_query) }.not_to raise_error
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
threads.each(&:join)
|
348
|
+
end
|
275
349
|
end
|
276
350
|
|
277
351
|
describe '#query' do
|
@@ -3,6 +3,12 @@
|
|
3
3
|
describe MysqlFramework::SqlCondition do
|
4
4
|
subject { described_class.new(column: 'version', comparison: '=', value: '1.0.0') }
|
5
5
|
|
6
|
+
before :each do
|
7
|
+
allow_any_instance_of(MysqlFramework::SqlCondition).to receive(:skip_nil_validation?).and_return(skip_nil_validation)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:skip_nil_validation) { false }
|
11
|
+
|
6
12
|
describe '#to_s' do
|
7
13
|
it 'returns the condition as a string for a prepared statement' do
|
8
14
|
expect(subject.to_s).to eq('version = ?')
|
@@ -16,6 +22,14 @@ describe MysqlFramework::SqlCondition do
|
|
16
22
|
it 'does raises an ArgumentError' do
|
17
23
|
expect { subject }.to raise_error(ArgumentError, "Comparison of = requires value to be not nil")
|
18
24
|
end
|
25
|
+
|
26
|
+
context 'when skip_nil_validation? is true' do
|
27
|
+
let(:skip_nil_validation) { true }
|
28
|
+
|
29
|
+
it 'does not raise an ArgumentError' do
|
30
|
+
expect(subject.value).to be_nil
|
31
|
+
end
|
32
|
+
end
|
19
33
|
end
|
20
34
|
end
|
21
35
|
|
@@ -33,6 +47,14 @@ describe MysqlFramework::SqlCondition do
|
|
33
47
|
it 'raises an ArgumentError if value is set' do
|
34
48
|
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NULL')
|
35
49
|
end
|
50
|
+
|
51
|
+
context 'when skip_nil_validation? is true' do
|
52
|
+
let(:skip_nil_validation) { true }
|
53
|
+
|
54
|
+
it 'raises an ArgumentError if value is set' do
|
55
|
+
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NULL')
|
56
|
+
end
|
57
|
+
end
|
36
58
|
end
|
37
59
|
end
|
38
60
|
|
@@ -67,6 +89,14 @@ describe MysqlFramework::SqlCondition do
|
|
67
89
|
it 'raises an ArgumentError if value is set' do
|
68
90
|
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NOT NULL')
|
69
91
|
end
|
92
|
+
|
93
|
+
context 'when skip_nil_validation? is true' do
|
94
|
+
let(:skip_nil_validation) { true }
|
95
|
+
|
96
|
+
it 'raises an ArgumentError if value is set' do
|
97
|
+
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NOT NULL')
|
98
|
+
end
|
99
|
+
end
|
70
100
|
end
|
71
101
|
end
|
72
102
|
|
@@ -50,6 +50,19 @@ describe MysqlFramework::SqlQuery do
|
|
50
50
|
expect(subject.params).to eq(['9876'])
|
51
51
|
end
|
52
52
|
|
53
|
+
context 'when a select query contains conditions with nil values' do
|
54
|
+
it 'does not store them as parameters' do
|
55
|
+
subject.select('*')
|
56
|
+
.from(gems, 40)
|
57
|
+
.where(
|
58
|
+
MysqlFramework::SqlCondition.new(column: 'id', comparison: '=', value: 9876),
|
59
|
+
MysqlFramework::SqlCondition.new(column: 'foo', comparison: 'IS NOT NULL'),
|
60
|
+
)
|
61
|
+
expect(subject.sql).to eq('SELECT * FROM `gems` PARTITION (p40) WHERE (id = ? AND foo IS NOT NULL)')
|
62
|
+
expect(subject.params.size).to eq 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
53
66
|
it 'builds a joined select query as expected' do
|
54
67
|
subject.select('*')
|
55
68
|
.from(gems, 40)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sage
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -137,8 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
requirements: []
|
140
|
-
|
141
|
-
rubygems_version: 2.7.7
|
140
|
+
rubygems_version: 3.0.8
|
142
141
|
signing_key:
|
143
142
|
specification_version: 4
|
144
143
|
summary: A lightweight framework to provide managers for working with MySQL.
|