mysql_framework 1.1.1 → 2.1.0
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.rb +1 -0
- data/lib/mysql_framework/connector.rb +11 -2
- data/lib/mysql_framework/in_condition.rb +12 -0
- data/lib/mysql_framework/scripts/base.rb +2 -2
- data/lib/mysql_framework/sql_column.rb +4 -0
- data/lib/mysql_framework/sql_condition.rb +37 -1
- data/lib/mysql_framework/sql_query.rb +60 -15
- data/lib/mysql_framework/sql_table.rb +3 -1
- data/lib/mysql_framework/version.rb +1 -1
- data/spec/lib/mysql_framework/connector_spec.rb +27 -0
- data/spec/lib/mysql_framework/sql_column_spec.rb +8 -0
- data/spec/lib/mysql_framework/sql_condition_spec.rb +78 -0
- data/spec/lib/mysql_framework/sql_query_spec.rb +85 -10
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f48c69762d95976838c6779c9acfc6591e2113d9a91128f69a2621890332bee0
|
4
|
+
data.tar.gz: 5d9d0250828d1e93626010796f79364d2f23b22554c38f4bda313ca718faffc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e477a4a454360a80a979421aad3ba7db1b7399656062dc7cd129174af1f48953fb3c56d2ad2d959fafbf009a7c1e9f9aa57d34c91c5a06aeb853d0f0e518fb8
|
7
|
+
data.tar.gz: 2c0980c6a0c94718d0df07d56ae1f88367ce8716d5af457b1c9c6526c29878380bbaeaffaca314dcdf4943d1366c27940675d693fdec4fe961fc183e7a6bb3ed
|
data/lib/mysql_framework.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'mysql_framework/logger'
|
|
7
7
|
require_relative 'mysql_framework/scripts'
|
8
8
|
require_relative 'mysql_framework/sql_column'
|
9
9
|
require_relative 'mysql_framework/sql_condition'
|
10
|
+
require_relative 'mysql_framework/in_condition'
|
10
11
|
require_relative 'mysql_framework/sql_query'
|
11
12
|
require_relative 'mysql_framework/sql_table'
|
12
13
|
require_relative 'mysql_framework/version'
|
@@ -75,10 +75,19 @@ module MysqlFramework
|
|
75
75
|
end
|
76
76
|
|
77
77
|
# This method is called to execute a prepared statement
|
78
|
+
#
|
79
|
+
# @note Ensure we close each statement, otherwise we can run into
|
80
|
+
# a 'Commands out of sync' error if multiple threads are running different
|
81
|
+
# queries at the same time.
|
78
82
|
def execute(query, provided_client = nil)
|
79
83
|
with_client(provided_client) do |client|
|
80
|
-
|
81
|
-
|
84
|
+
begin
|
85
|
+
statement = client.prepare(query.sql)
|
86
|
+
result = statement.execute(*query.params)
|
87
|
+
result.to_a if result
|
88
|
+
ensure
|
89
|
+
statement.close if statement
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MysqlFramework
|
4
|
+
# This class is used to represent a Sql IN Condition for a column.
|
5
|
+
class InCondition < SqlCondition
|
6
|
+
# This method is called to get the condition as a string for a sql prepared statement
|
7
|
+
def to_s
|
8
|
+
params = value.map { |_| '?' }
|
9
|
+
"#{@column} #{@comparison} (#{params.join(', ')})"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -36,7 +36,7 @@ module MysqlFramework
|
|
36
36
|
|
37
37
|
def column_exists?(client, table_name, column_name)
|
38
38
|
result = client.query(<<~SQL)
|
39
|
-
SHOW COLUMNS FROM
|
39
|
+
SHOW COLUMNS FROM #{table_name} WHERE Field="#{column_name}";
|
40
40
|
SQL
|
41
41
|
|
42
42
|
result.count == 1
|
@@ -44,7 +44,7 @@ module MysqlFramework
|
|
44
44
|
|
45
45
|
def index_exists?(client, table_name, index_name)
|
46
46
|
result = client.query(<<~SQL)
|
47
|
-
SHOW INDEX FROM
|
47
|
+
SHOW INDEX FROM #{table_name} WHERE Key_name="#{index_name}" LIMIT 1;
|
48
48
|
SQL
|
49
49
|
|
50
50
|
result.count == 1
|
@@ -46,6 +46,10 @@ module MysqlFramework
|
|
46
46
|
SqlCondition.new(column: to_s, comparison: '<=', value: value)
|
47
47
|
end
|
48
48
|
|
49
|
+
def in(*values)
|
50
|
+
InCondition.new(column: to_s, comparison: 'IN', value: values)
|
51
|
+
end
|
52
|
+
|
49
53
|
# This method is called to generate an alias statement for this column.
|
50
54
|
def as(name)
|
51
55
|
"#{self} as `#{name}`"
|
@@ -3,18 +3,54 @@
|
|
3
3
|
module MysqlFramework
|
4
4
|
# This class is used to represent a Sql Condition for a column.
|
5
5
|
class SqlCondition
|
6
|
+
NIL_COMPARISONS = ['IS NULL', 'IS NOT NULL'].freeze
|
7
|
+
|
6
8
|
# This method is called to get the value of this condition for prepared statements.
|
7
9
|
attr_reader :value
|
8
10
|
|
9
|
-
|
11
|
+
# Creates a new SqlCondition using the given parameters.
|
12
|
+
#
|
13
|
+
# @raise ArgumentError if comparison is 'IS NULL' and value is not nil
|
14
|
+
# @raise ArgumentError if comparison is 'IS NOT NULL' and value is not nil
|
15
|
+
# @raise ArgumentError if comparison is neither 'IS NULL' or 'IS NOT NULL' and value is nil
|
16
|
+
#
|
17
|
+
# @param column [String] - the name of the column to use in the comparison
|
18
|
+
# @param comparison [String] - the MySQL comparison operator to use
|
19
|
+
# @param value [Object] - the value to use in the comparison (default nil)
|
20
|
+
def initialize(column:, comparison:, value: nil)
|
10
21
|
@column = column
|
11
22
|
@comparison = comparison
|
23
|
+
|
24
|
+
validate(value)
|
12
25
|
@value = value
|
13
26
|
end
|
14
27
|
|
15
28
|
# This method is called to get the condition as a string for a sql prepared statement
|
29
|
+
#
|
30
|
+
# @return [String]
|
16
31
|
def to_s
|
32
|
+
return "#{@column} #{@comparison.upcase}" if nil_comparison?
|
33
|
+
|
17
34
|
"#{@column} #{@comparison} ?"
|
18
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def nil_comparison?
|
40
|
+
NIL_COMPARISONS.include?(@comparison.upcase)
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate(value)
|
44
|
+
raise ArgumentError, "Cannot set value when comparison is #{@comparison}" if invalid_null_condition?(value)
|
45
|
+
raise ArgumentError, "Comparison of #{@comparison} requires value to be not nil" if invalid_nil_value?(value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def invalid_null_condition?(value)
|
49
|
+
nil_comparison? && value != nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def invalid_nil_value?(value)
|
53
|
+
nil_comparison? == false && value.nil?
|
54
|
+
end
|
19
55
|
end
|
20
56
|
end
|
@@ -9,11 +9,12 @@ module MysqlFramework
|
|
9
9
|
def initialize
|
10
10
|
@sql = ''
|
11
11
|
@params = []
|
12
|
+
@lock = nil
|
12
13
|
end
|
13
14
|
|
14
15
|
# This method is called to access the sql string for this query.
|
15
16
|
def sql
|
16
|
-
@sql.strip
|
17
|
+
(@sql + @lock.to_s + @dup_query.to_s).strip
|
17
18
|
end
|
18
19
|
|
19
20
|
# This method is called to start a select query
|
@@ -76,19 +77,6 @@ module MysqlFramework
|
|
76
77
|
self
|
77
78
|
end
|
78
79
|
|
79
|
-
# This method is called to specify the columns to bulk upsert.
|
80
|
-
def bulk_upsert(columns)
|
81
|
-
@sql += 'ON DUPLICATE KEY UPDATE '
|
82
|
-
|
83
|
-
columns.each do |column|
|
84
|
-
@sql += "#{column} = VALUES(#{column}), "
|
85
|
-
end
|
86
|
-
|
87
|
-
@sql = @sql.chomp(', ')
|
88
|
-
|
89
|
-
self
|
90
|
-
end
|
91
|
-
|
92
80
|
# This method is called to specify the columns to update.
|
93
81
|
def set(values)
|
94
82
|
@sql += ' SET '
|
@@ -132,11 +120,20 @@ module MysqlFramework
|
|
132
120
|
end
|
133
121
|
|
134
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.
|
135
125
|
def where(*conditions)
|
136
126
|
@sql += ' WHERE' unless @sql.include?('WHERE')
|
137
127
|
@sql += " (#{conditions.join(' AND ')}) "
|
138
128
|
|
139
|
-
conditions.each
|
129
|
+
conditions.each do |condition|
|
130
|
+
next if condition.value.nil?
|
131
|
+
if condition.value.is_a?(Enumerable)
|
132
|
+
@params.concat(condition.value)
|
133
|
+
else
|
134
|
+
@params << condition.value
|
135
|
+
end
|
136
|
+
end
|
140
137
|
|
141
138
|
self
|
142
139
|
end
|
@@ -218,5 +215,53 @@ module MysqlFramework
|
|
218
215
|
|
219
216
|
self
|
220
217
|
end
|
218
|
+
|
219
|
+
# This method allows you to add a pessimistic lock to the record.
|
220
|
+
# The default lock is `FOR UPDATE`
|
221
|
+
# If you require any custom lock, e.g. FOR SHARE, just pass that in as the condition
|
222
|
+
# query.lock('FOR SHARE')
|
223
|
+
def lock(condition = nil)
|
224
|
+
raise 'This must be a SELECT query' unless @sql.start_with?('SELECT')
|
225
|
+
|
226
|
+
@lock = ' ' + (condition || 'FOR UPDATE')
|
227
|
+
self
|
228
|
+
end
|
229
|
+
|
230
|
+
# For insert queries if you need to handle that a primary key already exists and automatically do an update instead.
|
231
|
+
# If you do not pass in a hash specifying a column name and custom value for it.
|
232
|
+
# @param update_values [Hash] key is a column name. A nil value will make the query update
|
233
|
+
# the column with the value specified in the insert. Otherwise any value will be interpreted
|
234
|
+
# literally via mysql.
|
235
|
+
# @return SqlQuery
|
236
|
+
# e.g.
|
237
|
+
# query.insert('users')
|
238
|
+
# .into('id', first_name', 'login_count')
|
239
|
+
# .values(1, 'Bob', 1)
|
240
|
+
# .on_duplicate(
|
241
|
+
# {
|
242
|
+
# first_name: nil,
|
243
|
+
# login_count: 'login_count + 5'
|
244
|
+
# }
|
245
|
+
# )
|
246
|
+
# This would first create a record like => `1, 'Bob', 1`.
|
247
|
+
# The second time it would update it with => `'Bob', 6` (Note the 1 is not used in the update)
|
248
|
+
def on_duplicate(update_values = {})
|
249
|
+
raise 'This must be an INSERT query' unless @sql.start_with?('INSERT')
|
250
|
+
|
251
|
+
duplicates = []
|
252
|
+
update_values.each do |column, col_value|
|
253
|
+
if col_value.nil?
|
254
|
+
# value comes from what the INSERT intended
|
255
|
+
updated_value = "#{column} = VALUES (#{column})"
|
256
|
+
else
|
257
|
+
# custom value specified by col_value
|
258
|
+
updated_value = "#{column} = #{col_value}"
|
259
|
+
end
|
260
|
+
duplicates << updated_value
|
261
|
+
end
|
262
|
+
@dup_query = " ON DUPLICATE KEY UPDATE #{duplicates.join(', ')}"
|
263
|
+
|
264
|
+
self
|
265
|
+
end
|
221
266
|
end
|
222
267
|
end
|
@@ -5,11 +5,13 @@ module MysqlFramework
|
|
5
5
|
class SqlTable
|
6
6
|
def initialize(name)
|
7
7
|
@name = name
|
8
|
+
@column_objects = {}
|
8
9
|
end
|
9
10
|
|
10
11
|
# This method is called to get a sql column for this table
|
11
12
|
def [](column)
|
12
|
-
|
13
|
+
return @column_objects[column.to_sym] if @column_objects[column.to_sym]
|
14
|
+
@column_objects[column.to_sym] = SqlColumn.new(table: @name, column: column)
|
13
15
|
end
|
14
16
|
|
15
17
|
def to_s
|
@@ -272,6 +272,33 @@ describe MysqlFramework::Connector do
|
|
272
272
|
expect(results.length).to eq(1)
|
273
273
|
expect(results[0][:id]).to eq(guid)
|
274
274
|
end
|
275
|
+
|
276
|
+
it 'does not raise a commands out of sync error' do
|
277
|
+
threads = []
|
278
|
+
threads << Thread.new do
|
279
|
+
350.times do
|
280
|
+
update_query = MysqlFramework::SqlQuery.new.update('gems')
|
281
|
+
.set(updated_at: Time.now)
|
282
|
+
expect { subject.execute(update_query) }.not_to raise_error
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
threads << Thread.new do
|
287
|
+
350.times do
|
288
|
+
select_query = MysqlFramework::SqlQuery.new.select('*').from('demo')
|
289
|
+
expect { subject.execute(select_query) }.not_to raise_error
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
threads << Thread.new do
|
294
|
+
350.times do
|
295
|
+
select_query = MysqlFramework::SqlQuery.new.select('*').from('test')
|
296
|
+
expect { subject.execute(select_query) }.not_to raise_error
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
threads.each(&:join)
|
301
|
+
end
|
275
302
|
end
|
276
303
|
|
277
304
|
describe '#query' do
|
@@ -63,6 +63,14 @@ describe MysqlFramework::SqlColumn do
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
describe '#in' do
|
67
|
+
it 'returns a SqlCondition for the comparison' do
|
68
|
+
condition = subject.in('a', 'b', 'c')
|
69
|
+
expect(condition).to be_a(MysqlFramework::InCondition)
|
70
|
+
expect(condition.to_s).to eq('`gems`.`version` IN (?, ?, ?)')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
66
74
|
describe '#as' do
|
67
75
|
it 'returns the column specified as another name' do
|
68
76
|
expect(subject.as('v')).to eq('`gems`.`version` as `v`')
|
@@ -8,4 +8,82 @@ describe MysqlFramework::SqlCondition do
|
|
8
8
|
expect(subject.to_s).to eq('version = ?')
|
9
9
|
end
|
10
10
|
end
|
11
|
+
|
12
|
+
context 'when comparison is neither IS NULL or IS NOT NULL' do
|
13
|
+
context 'when value is nil' do
|
14
|
+
subject { described_class.new(column: 'version', comparison: '=', value: nil) }
|
15
|
+
|
16
|
+
it 'does raises an ArgumentError' do
|
17
|
+
expect { subject }.to raise_error(ArgumentError, "Comparison of = requires value to be not nil")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when comparison is IS NULL' do
|
23
|
+
subject { described_class.new(column: 'version', comparison: 'IS NULL') }
|
24
|
+
|
25
|
+
it 'has a nil value by default' do
|
26
|
+
expect(subject.value).to be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when a value is passed to the constructor' do
|
30
|
+
subject { described_class.new(column: 'version', comparison: 'IS NULL', value: 'foo') }
|
31
|
+
|
32
|
+
describe '#new' do
|
33
|
+
it 'raises an ArgumentError if value is set' do
|
34
|
+
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NULL')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#to_s' do
|
40
|
+
it 'does not include a value placeholder' do
|
41
|
+
expect(subject.to_s).to eq('version IS NULL')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when comparison is lowercase is null' do
|
47
|
+
subject { described_class.new(column: 'version', comparison: 'is null') }
|
48
|
+
|
49
|
+
describe '#to_s' do
|
50
|
+
it 'ignores case' do
|
51
|
+
expect(subject.to_s).to eq 'version IS NULL'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when comparison is IS NOT NULL' do
|
57
|
+
subject { described_class.new(column: 'version', comparison: 'IS NOT NULL') }
|
58
|
+
|
59
|
+
it 'has a nil value by default' do
|
60
|
+
expect(subject.value).to be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when a value is passed to the constructor' do
|
64
|
+
subject { described_class.new(column: 'version', comparison: 'IS NOT NULL', value: 'foo') }
|
65
|
+
|
66
|
+
describe '#new' do
|
67
|
+
it 'raises an ArgumentError if value is set' do
|
68
|
+
expect { subject }.to raise_error(ArgumentError, 'Cannot set value when comparison is IS NOT NULL')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#to_s' do
|
74
|
+
it 'does not include a value placeholder' do
|
75
|
+
expect(subject.to_s).to eq('version IS NOT NULL')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when comparison is lowercase is not null' do
|
81
|
+
subject { described_class.new(column: 'version', comparison: 'is not null') }
|
82
|
+
|
83
|
+
describe '#to_s' do
|
84
|
+
it 'ignores case' do
|
85
|
+
expect(subject.to_s).to eq 'version IS NOT NULL'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
11
89
|
end
|
@@ -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)
|
@@ -139,16 +152,6 @@ describe MysqlFramework::SqlQuery do
|
|
139
152
|
end
|
140
153
|
end
|
141
154
|
|
142
|
-
describe '#bulk_upsert' do
|
143
|
-
it 'sets the sql for the upsert statement' do
|
144
|
-
columns = %w(column_1 column_2)
|
145
|
-
|
146
|
-
subject.bulk_upsert(columns)
|
147
|
-
|
148
|
-
expect(subject.sql).to eq('ON DUPLICATE KEY UPDATE column_1 = VALUES(column_1), column_2 = VALUES(column_2)')
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
155
|
describe '#set' do
|
153
156
|
it 'sets the sql for the set statement' do
|
154
157
|
subject.set(name: 'mysql_framework', author: 'sage', created_at: '2016-06-28 10:00:00')
|
@@ -223,6 +226,13 @@ describe MysqlFramework::SqlQuery do
|
|
223
226
|
expect(subject.sql).to eq('WHERE (`gems`.`author` = ? AND `gems`.`created_at` > ?) AND (`gems`.`name` = ?)')
|
224
227
|
end
|
225
228
|
end
|
229
|
+
|
230
|
+
context 'when the condition includes an array of parameters' do
|
231
|
+
it 'concats the parameter collections' do
|
232
|
+
subject.and.where(gems[:name].in('a','b'))
|
233
|
+
expect(subject.sql).to eq('WHERE (`gems`.`author` = ? AND `gems`.`created_at` > ?) AND (`gems`.`name` IN (?, ?))')
|
234
|
+
end
|
235
|
+
end
|
226
236
|
end
|
227
237
|
|
228
238
|
describe '#and' do
|
@@ -330,4 +340,69 @@ describe MysqlFramework::SqlQuery do
|
|
330
340
|
end
|
331
341
|
end
|
332
342
|
end
|
343
|
+
|
344
|
+
describe '#lock' do
|
345
|
+
it 'appends `FOR_UPDATE` to the query' do
|
346
|
+
subject.select('*').from(gems).lock
|
347
|
+
expect(subject.sql).to end_with('FOR UPDATE')
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe '#on_duplicate' do
|
352
|
+
let(:query) do
|
353
|
+
subject.insert(gems)
|
354
|
+
.into(
|
355
|
+
gems[:id],
|
356
|
+
gems[:name],
|
357
|
+
gems[:author]
|
358
|
+
)
|
359
|
+
.values(
|
360
|
+
1,
|
361
|
+
'mysql_framework',
|
362
|
+
'Bob Hope'
|
363
|
+
)
|
364
|
+
end
|
365
|
+
|
366
|
+
context 'when no custom values are specified' do
|
367
|
+
it 'updates with the value from the INSERT clause' do
|
368
|
+
query.on_duplicate(
|
369
|
+
{
|
370
|
+
gems[:name] => nil,
|
371
|
+
gems[:author] => nil
|
372
|
+
}
|
373
|
+
)
|
374
|
+
|
375
|
+
expect(query.sql)
|
376
|
+
.to end_with 'ON DUPLICATE KEY UPDATE `gems`.`name` = VALUES (`gems`.`name`), `gems`.`author` = VALUES (`gems`.`author`)'
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
context 'when a custom value is specified' do
|
381
|
+
it 'updates the value based on the custom value' do
|
382
|
+
query.on_duplicate(
|
383
|
+
{
|
384
|
+
gems[:name] => '"mysql_alternative"',
|
385
|
+
gems[:author] => '"Michael Caine"'
|
386
|
+
}
|
387
|
+
)
|
388
|
+
|
389
|
+
expect(query.sql)
|
390
|
+
.to end_with 'ON DUPLICATE KEY UPDATE `gems`.`name` = "mysql_alternative", `gems`.`author` = "Michael Caine"'
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'when column names are specified instead of SqlColumn objects' do
|
395
|
+
it 'updates the value based on the custom column key names' do
|
396
|
+
query.on_duplicate(
|
397
|
+
{
|
398
|
+
name: '"mysql_alternative"',
|
399
|
+
author: '"Michael Caine"'
|
400
|
+
}
|
401
|
+
)
|
402
|
+
|
403
|
+
expect(query.sql)
|
404
|
+
.to end_with 'ON DUPLICATE KEY UPDATE name = "mysql_alternative", author = "Michael Caine"'
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
333
408
|
end
|
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:
|
4
|
+
version: 2.1.0
|
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: 2020-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -89,6 +89,7 @@ extra_rdoc_files: []
|
|
89
89
|
files:
|
90
90
|
- lib/mysql_framework.rb
|
91
91
|
- lib/mysql_framework/connector.rb
|
92
|
+
- lib/mysql_framework/in_condition.rb
|
92
93
|
- lib/mysql_framework/logger.rb
|
93
94
|
- lib/mysql_framework/scripts.rb
|
94
95
|
- lib/mysql_framework/scripts/base.rb
|
@@ -136,8 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
137
|
- !ruby/object:Gem::Version
|
137
138
|
version: '0'
|
138
139
|
requirements: []
|
139
|
-
|
140
|
-
rubygems_version: 2.7.7
|
140
|
+
rubygems_version: 3.0.8
|
141
141
|
signing_key:
|
142
142
|
specification_version: 4
|
143
143
|
summary: A lightweight framework to provide managers for working with MySQL.
|