mysql_framework 1.1.2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dea6c1520ad570dfaf0070efd3df024dbd8d8ba9bc745970ebc59a82ad38418
4
- data.tar.gz: 7f2e6a694727e104584c5304673841cf06231b3efc538fb1a0bce23f69772293
3
+ metadata.gz: 79a94352053f85513e65fe768c6a2dbe420c14dd84e483e6f5ee276029b3c494
4
+ data.tar.gz: 794c2b7cafbdfa11d9be23e924a71cec74140003396266c2cc2dec023f2c7c26
5
5
  SHA512:
6
- metadata.gz: 6adf70afb9966e920ef972c187679847ea08d1638b3be8b5473bb031d5be41bc607a9143d313aafd106ff748f295b7679437f597f28a88b4e68afa6e1bcb9068
7
- data.tar.gz: '0057569f653959047e9c12feac892e9e0fc51f3fa99085bcd153f26374b4057e7dbdf45f6515d5254798064992065056e7d981369c7700986073390fc88a94e3'
6
+ metadata.gz: affb71d82cf2c8446d72b2a898abbade1d62a04dbebc97502ccef5a92c6c1e0377a9acc9dccf2a08ce6d7d9da03b64eb0b1d1a861715ca15977c2b53f6aa8c89
7
+ data.tar.gz: 8f48457c4dbc815b62406ab8c64fa14a4cc572d0f30c683d66a22a0e9cc7f68112d364edc0bf24d6569fabfaef5869e0606282a9a998910cf1c78bf2f785f264
@@ -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
@@ -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}`"
@@ -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 '
@@ -136,7 +124,13 @@ module MysqlFramework
136
124
  @sql += ' WHERE' unless @sql.include?('WHERE')
137
125
  @sql += " (#{conditions.join(' AND ')}) "
138
126
 
139
- conditions.each { |condition| @params << condition.value }
127
+ conditions.each do |condition|
128
+ if condition.value.is_a?(Enumerable)
129
+ @params.concat(condition.value)
130
+ else
131
+ @params << condition.value
132
+ end
133
+ end
140
134
 
141
135
  self
142
136
  end
@@ -218,5 +212,53 @@ module MysqlFramework
218
212
 
219
213
  self
220
214
  end
215
+
216
+ # This method allows you to add a pessimistic lock to the record.
217
+ # The default lock is `FOR UPDATE`
218
+ # If you require any custom lock, e.g. FOR SHARE, just pass that in as the condition
219
+ # query.lock('FOR SHARE')
220
+ def lock(condition = nil)
221
+ raise 'This must be a SELECT query' unless @sql.start_with?('SELECT')
222
+
223
+ @lock = ' ' + (condition || 'FOR UPDATE')
224
+ self
225
+ end
226
+
227
+ # For insert queries if you need to handle that a primary key already exists and automatically do an update instead.
228
+ # If you do not pass in a hash specifying a column name and custom value for it.
229
+ # @param update_values [Hash] key is a column name. A nil value will make the query update
230
+ # the column with the value specified in the insert. Otherwise any value will be interpreted
231
+ # literally via mysql.
232
+ # @return SqlQuery
233
+ # e.g.
234
+ # query.insert('users')
235
+ # .into('id', first_name', 'login_count')
236
+ # .values(1, 'Bob', 1)
237
+ # .duplicate_update(
238
+ # {
239
+ # first_name: nil,
240
+ # login_count: 'login_count + 5'
241
+ # }
242
+ # )
243
+ # This would first create a record like => `1, 'Bob', 1`.
244
+ # The second time it would update it with => `'Bob', 6` (Note the 1 is not used in the update)
245
+ def on_duplicate(update_values = {})
246
+ raise 'This must be an INSERT query' unless @sql.start_with?('INSERT')
247
+
248
+ duplicates = []
249
+ update_values.each do |column, col_value|
250
+ if col_value.nil?
251
+ # value comes from what the INSERT intended
252
+ updated_value = "#{column} = VALUES (#{column})"
253
+ else
254
+ # custom value specified by col_value
255
+ updated_value = "#{column} = #{col_value}"
256
+ end
257
+ duplicates << updated_value
258
+ end
259
+ @dup_query = " ON DUPLICATE KEY UPDATE #{duplicates.join(', ')}"
260
+
261
+ self
262
+ end
221
263
  end
222
264
  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
- SqlColumn.new(table: @name, column: column)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MysqlFramework
4
- VERSION = '1.1.2'
4
+ VERSION = '2.0.0.rc1'
5
5
  end
@@ -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'
@@ -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`')
@@ -139,16 +139,6 @@ describe MysqlFramework::SqlQuery do
139
139
  end
140
140
  end
141
141
 
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
142
  describe '#set' do
153
143
  it 'sets the sql for the set statement' do
154
144
  subject.set(name: 'mysql_framework', author: 'sage', created_at: '2016-06-28 10:00:00')
@@ -330,4 +320,69 @@ describe MysqlFramework::SqlQuery do
330
320
  end
331
321
  end
332
322
  end
323
+
324
+ describe '#lock' do
325
+ it 'appends `FOR_UPDATE` to the query' do
326
+ subject.select('*').from(gems).lock
327
+ expect(subject.sql).to end_with('FOR UPDATE')
328
+ end
329
+ end
330
+
331
+ describe '#on_duplicate' do
332
+ let(:query) do
333
+ subject.insert(gems)
334
+ .into(
335
+ gems[:id],
336
+ gems[:name],
337
+ gems[:author]
338
+ )
339
+ .values(
340
+ 1,
341
+ 'mysql_framework',
342
+ 'Bob Hope'
343
+ )
344
+ end
345
+
346
+ context 'when no custom values are specified' do
347
+ it 'updates with the value from the INSERT clause' do
348
+ query.on_duplicate(
349
+ {
350
+ gems[:name] => nil,
351
+ gems[:author] => nil
352
+ }
353
+ )
354
+
355
+ expect(query.sql)
356
+ .to end_with 'ON DUPLICATE KEY UPDATE `gems`.`name` = VALUES (`gems`.`name`), `gems`.`author` = VALUES (`gems`.`author`)'
357
+ end
358
+ end
359
+
360
+ context 'when a custom value is specified' do
361
+ it 'updates the value based on the custom value' do
362
+ query.on_duplicate(
363
+ {
364
+ gems[:name] => '"mysql_alternative"',
365
+ gems[:author] => '"Michael Caine"'
366
+ }
367
+ )
368
+
369
+ expect(query.sql)
370
+ .to end_with 'ON DUPLICATE KEY UPDATE `gems`.`name` = "mysql_alternative", `gems`.`author` = "Michael Caine"'
371
+ end
372
+ end
373
+
374
+ context 'when column names are specified instead of SqlColumn objects' do
375
+ it 'updates the value based on the custom column key names' do
376
+ query.on_duplicate(
377
+ {
378
+ name: '"mysql_alternative"',
379
+ author: '"Michael Caine"'
380
+ }
381
+ )
382
+
383
+ expect(query.sql)
384
+ .to end_with 'ON DUPLICATE KEY UPDATE name = "mysql_alternative", author = "Michael Caine"'
385
+ end
386
+ end
387
+ end
333
388
  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: 1.1.2
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sage
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-09 00:00:00.000000000 Z
11
+ date: 2019-11-12 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
@@ -132,9 +133,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
133
  version: '0'
133
134
  required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  requirements:
135
- - - ">="
136
+ - - ">"
136
137
  - !ruby/object:Gem::Version
137
- version: '0'
138
+ version: 1.3.1
138
139
  requirements: []
139
140
  rubyforge_project:
140
141
  rubygems_version: 2.7.7