mysql_framework 2.0.0 → 2.1.3
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.
- 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.
|