Skip to content

Commit 3eba185

Browse files
authored
Updates for bulk insert/upsert (#795)
Typo
1 parent d16d958 commit 3eba185

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

lib/active_record/connection_adapters/sqlserver/database_statements.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ def default_insert_value(column)
137137
end
138138
private :default_insert_value
139139

140+
def build_insert_sql(insert) # :nodoc:
141+
sql = +"INSERT #{insert.into}"
142+
143+
if returning = insert.send(:insert_all).returning
144+
sql << " OUTPUT " << returning.map {|column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
145+
end
146+
147+
sql << " #{insert.values_list}"
148+
sql
149+
end
150+
140151
# === SQLServer Specific ======================================== #
141152

142153
def execute_procedure(proc_name, *variables)
@@ -243,10 +254,12 @@ def sql_for_insert(sql, pk, binds)
243254
table_name = query_requires_identity_insert?(sql)
244255
pk = primary_key(table_name)
245256
end
257+
246258
sql = if pk && use_output_inserted? && !database_prefix_remote_server?
247259
quoted_pk = SQLServer::Utils.extract_identifiers(pk).quoted
248260
table_name ||= get_table_name(sql)
249261
exclude_output_inserted = exclude_output_inserted_table_name?(table_name, sql)
262+
250263
if exclude_output_inserted
251264
id_sql_type = exclude_output_inserted.is_a?(TrueClass) ? 'bigint' : exclude_output_inserted
252265
<<~SQL.squish

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,22 @@ def supports_in_memory_oltp?
159159
@version_year >= 2014
160160
end
161161

162+
def supports_insert_returning?
163+
true
164+
end
165+
166+
def supports_insert_on_duplicate_skip?
167+
false
168+
end
169+
170+
def supports_insert_on_duplicate_update?
171+
false
172+
end
173+
174+
def supports_insert_conflict_target?
175+
false
176+
end
177+
162178
def disable_referential_integrity
163179
tables = tables_with_referential_integrity
164180
tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} NOCHECK CONSTRAINT ALL" }

test/cases/coerced_tests.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,3 +1407,39 @@ class EnumTest < ActiveRecord::TestCase
14071407
Book.connection.add_index(:books, [:author_id, :name], unique: true)
14081408
end
14091409
end
1410+
1411+
1412+
1413+
1414+
require 'models/task'
1415+
class QueryCacheExpiryTest < ActiveRecord::TestCase
1416+
1417+
# SQL Server does not support skipping or upserting duplicates.
1418+
coerce_tests! :test_insert_all
1419+
def test_insert_all_coerced
1420+
assert_raises(ArgumentError, /does not support skipping duplicates/) do
1421+
Task.cache { Task.insert({ starting: Time.now }) }
1422+
end
1423+
1424+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
1425+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
1426+
end
1427+
1428+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
1429+
Task.cache { Task.insert!({ starting: Time.now }) }
1430+
end
1431+
1432+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
1433+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
1434+
end
1435+
1436+
assert_raises(ArgumentError, /does not support upsert/) do
1437+
Task.cache { Task.upsert({ starting: Time.now }) }
1438+
end
1439+
1440+
assert_raises(ArgumentError, /does not support upsert/) do
1441+
Task.cache { Task.upsert_all([{ starting: Time.now }]) }
1442+
end
1443+
end
1444+
1445+
end

0 commit comments

Comments
 (0)