Skip to content

Commit c27d737

Browse files
committed
Migrate on_conflict_statement to statement adapters
1 parent 092a153 commit c27d737

6 files changed

Lines changed: 34 additions & 46 deletions

File tree

lib/bulk_insert/statement_adapters/generic_adapter.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ def insert_ignore_statement
55
''
66
end
77

8-
def on_conflict_ignore_statement
9-
end
10-
11-
def on_conflict_update_statement
8+
def on_conflict_statement(columns, ignore, update_duplicates)
9+
''
1210
end
1311

1412
def primary_key_return_statement(primary_key)

lib/bulk_insert/statement_adapters/mysql_adapter.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ def insert_ignore_statement
55
'IGNORE'
66
end
77

8-
def on_conflict_ignore_statement
9-
end
8+
def on_conflict_statement(columns, ignore, update_duplicates)
9+
return '' unless update_duplicates
1010

11-
def on_conflict_update_statement
11+
update_values = columns.map do |column|
12+
"`#{column.name}`=VALUES(`#{column.name}`)"
13+
end.join(', ')
14+
' ON DUPLICATE KEY UPDATE ' + update_values
1215
end
1316

1417
def primary_key_return_statement(primary_key)

lib/bulk_insert/statement_adapters/postgresql_adapter.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ def insert_ignore_statement
55
''
66
end
77

8-
def on_conflict_ignore_statement
9-
end
10-
11-
def on_conflict_update_statement
8+
def on_conflict_statement(columns, ignore, update_duplicates)
9+
if ignore
10+
' ON CONFLICT DO NOTHING'
11+
elsif update_duplicates
12+
update_values = columns.map do |column|
13+
"#{column.name}=EXCLUDED.#{column.name}"
14+
end.join(', ')
15+
' ON CONFLICT(' + update_duplicates.join(', ') + ') DO UPDATE SET ' + update_values
16+
end
1217
end
1318

1419
def primary_key_return_statement(primary_key)

lib/bulk_insert/statement_adapters/sqlite_adapter.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ def insert_ignore_statement
55
'OR IGNORE'
66
end
77

8-
def on_conflict_ignore_statement
9-
end
10-
11-
def on_conflict_update_statement
8+
def on_conflict_statement(columns, ignore, update_duplicates)
9+
''
1210
end
1311

1412
def primary_key_return_statement(primary_key)

lib/bulk_insert/worker.rb

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def compose_insert_query
120120

121121
if !rows.empty?
122122
sql << rows.join(",")
123-
sql << on_conflict_statement
123+
sql << @statement_adapter.on_conflict_statement(@columns, ignore, update_duplicates)
124124
sql << @statement_adapter.primary_key_return_statement(@primary_key) if @return_primary_keys
125125
sql
126126
else
@@ -132,24 +132,5 @@ def insert_sql_statement
132132
insert_ignore = @ignore ? @statement_adapter.insert_ignore_statement : ''
133133
"INSERT #{insert_ignore} INTO #{@table_name} (#{@column_names}) VALUES "
134134
end
135-
136-
def on_conflict_statement
137-
is_postgres = adapter_name =~ /\APost(?:greSQL|GIS)/i
138-
if is_postgres && ignore
139-
' ON CONFLICT DO NOTHING'
140-
elsif is_postgres && update_duplicates
141-
update_values = @columns.map do |column|
142-
"#{column.name}=EXCLUDED.#{column.name}"
143-
end.join(', ')
144-
' ON CONFLICT(' + update_duplicates.join(', ') + ') DO UPDATE SET ' + update_values
145-
elsif adapter_name =~ /^mysql/i && update_duplicates
146-
update_values = @columns.map do |column|
147-
"`#{column.name}`=VALUES(`#{column.name}`)"
148-
end.join(', ')
149-
' ON DUPLICATE KEY UPDATE ' + update_values
150-
else
151-
''
152-
end
153-
end
154135
end
155136
end

test/bulk_insert/worker_test.rb

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -420,17 +420,20 @@ class BulkInsertWorkerTest < ActiveSupport::TestCase
420420
end
421421

422422
test "mysql adapter can update duplicates" do
423-
mysql_worker = BulkInsert::Worker.new(
424-
Testing.connection,
425-
Testing.table_name,
426-
'id',
427-
%w(greeting age happy created_at updated_at color),
428-
500, # batch size
429-
false, # ignore
430-
true) # update_duplicates
431-
mysql_worker.adapter_name = 'MySQL'
432-
mysql_worker.add ["Yo", 15, false, nil, nil]
423+
connection = Testing.connection
424+
connection.stub :adapter_name, 'MySQL' do
425+
mysql_worker = BulkInsert::Worker.new(
426+
connection,
427+
Testing.table_name,
428+
'id',
429+
%w(greeting age happy created_at updated_at color),
430+
500, # batch size
431+
false, # ignore
432+
true # update_duplicates
433+
)
434+
mysql_worker.add ["Yo", 15, false, nil, nil]
433435

434-
assert_equal mysql_worker.compose_insert_query, "INSERT INTO \"testings\" (\"greeting\",\"age\",\"happy\",\"created_at\",\"updated_at\",\"color\") VALUES ('Yo',15,0,NULL,NULL,'chartreuse') ON DUPLICATE KEY UPDATE `greeting`=VALUES(`greeting`), `age`=VALUES(`age`), `happy`=VALUES(`happy`), `created_at`=VALUES(`created_at`), `updated_at`=VALUES(`updated_at`), `color`=VALUES(`color`)"
436+
assert_equal mysql_worker.compose_insert_query, "INSERT INTO \"testings\" (\"greeting\",\"age\",\"happy\",\"created_at\",\"updated_at\",\"color\") VALUES ('Yo',15,0,NULL,NULL,'chartreuse') ON DUPLICATE KEY UPDATE `greeting`=VALUES(`greeting`), `age`=VALUES(`age`), `happy`=VALUES(`happy`), `created_at`=VALUES(`created_at`), `updated_at`=VALUES(`updated_at`), `color`=VALUES(`color`)"
437+
end
435438
end
436439
end

0 commit comments

Comments
 (0)