Skip to content

Commit 135ac82

Browse files
committed
Enable identity insert on view's base table for fixtures
1 parent 1c5fb1f commit 135ac82

File tree

3 files changed

+65
-53
lines changed

3 files changed

+65
-53
lines changed

lib/active_record/connection_adapters/sqlserver/database_statements.rb

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@ def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notif
1717
id_insert_table_name = query_requires_identity_insert?(sql)
1818

1919
result, affected_rows = if id_insert_table_name
20-
# If the table name is a view, we need to get the base table name for enabling identity insert.
21-
id_insert_table_name = view_table_name(id_insert_table_name) if view_exists?(id_insert_table_name)
22-
23-
with_identity_insert_enabled(id_insert_table_name, raw_connection) do
24-
internal_exec_sql_query(sql, raw_connection)
25-
end
26-
else
27-
internal_exec_sql_query(sql, raw_connection)
28-
end
20+
with_identity_insert_enabled(id_insert_table_name, raw_connection) do
21+
internal_exec_sql_query(sql, raw_connection)
22+
end
23+
else
24+
internal_exec_sql_query(sql, raw_connection)
25+
end
2926

3027
verified!
3128
notification_payload[:affected_rows] = affected_rows
@@ -239,10 +236,10 @@ def merge_insert_values_list(insert:, insert_all:)
239236

240237
def execute_procedure(proc_name, *variables)
241238
vars = if variables.any? && variables.first.is_a?(Hash)
242-
variables.first.map { |k, v| "@#{k} = #{quote(v)}" }
243-
else
244-
variables.map { |v| quote(v) }
245-
end.join(", ")
239+
variables.first.map { |k, v| "@#{k} = #{quote(v)}" }
240+
else
241+
variables.map { |v| quote(v) }
242+
end.join(", ")
246243
sql = "EXEC #{proc_name} #{vars}".strip
247244

248245
log(sql, "Execute Procedure") do |notification_payload|
@@ -264,11 +261,14 @@ def execute_procedure(proc_name, *variables)
264261
end
265262

266263
def with_identity_insert_enabled(table_name, conn)
267-
table_name = quote_table_name(table_name)
268-
set_identity_insert(table_name, conn, true)
264+
# If the table name is a view, we need to get the base table name for enabling identity insert.
265+
table_name = view_table_name(table_name) if view_exists?(table_name)
266+
quoted_table_name = quote_table_name(table_name)
267+
268+
set_identity_insert(quoted_table_name, conn, true)
269269
yield
270270
ensure
271-
set_identity_insert(table_name, conn, false)
271+
set_identity_insert(quoted_table_name, conn, false)
272272
end
273273

274274
def use_database(database = nil)
@@ -345,35 +345,35 @@ def sql_for_insert(sql, pk, binds, returning)
345345
end
346346

347347
sql = if pk && use_output_inserted? && !database_prefix_remote_server?
348-
table_name ||= get_table_name(sql)
349-
exclude_output_inserted = exclude_output_inserted_table_name?(table_name, sql)
350-
351-
if exclude_output_inserted
352-
pk_and_types = Array(pk).map do |subkey|
353-
{
354-
quoted: SQLServer::Utils.extract_identifiers(subkey).quoted,
355-
id_sql_type: exclude_output_inserted_id_sql_type(subkey, exclude_output_inserted)
356-
}
357-
end
358-
359-
<<~SQL.squish
348+
table_name ||= get_table_name(sql)
349+
exclude_output_inserted = exclude_output_inserted_table_name?(table_name, sql)
350+
351+
if exclude_output_inserted
352+
pk_and_types = Array(pk).map do |subkey|
353+
{
354+
quoted: SQLServer::Utils.extract_identifiers(subkey).quoted,
355+
id_sql_type: exclude_output_inserted_id_sql_type(subkey, exclude_output_inserted)
356+
}
357+
end
358+
359+
<<~SQL.squish
360360
DECLARE @ssaIdInsertTable table (#{pk_and_types.map { |pk_and_type| "#{pk_and_type[:quoted]} #{pk_and_type[:id_sql_type]}" }.join(", ")});
361361
#{sql.dup.insert sql.index(/ (DEFAULT )?VALUES/i), " OUTPUT #{pk_and_types.map { |pk_and_type| "INSERTED.#{pk_and_type[:quoted]}" }.join(", ")} INTO @ssaIdInsertTable"}
362362
SELECT #{pk_and_types.map { |pk_and_type| "CAST(#{pk_and_type[:quoted]} AS #{pk_and_type[:id_sql_type]}) #{pk_and_type[:quoted]}" }.join(", ")} FROM @ssaIdInsertTable
363363
SQL
364-
else
365-
returning_columns = returning || Array(pk)
366-
367-
if returning_columns.any?
368-
returning_columns_statements = returning_columns.map { |c| " INSERTED.#{SQLServer::Utils.extract_identifiers(c).quoted}" }
369-
sql.dup.insert sql.index(/ (DEFAULT )?VALUES/i), " OUTPUT" + returning_columns_statements.join(",")
370-
else
371-
sql
372-
end
373-
end
374-
else
375-
"#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
376-
end
364+
else
365+
returning_columns = returning || Array(pk)
366+
367+
if returning_columns.any?
368+
returning_columns_statements = returning_columns.map { |c| " INSERTED.#{SQLServer::Utils.extract_identifiers(c).quoted}" }
369+
sql.dup.insert sql.index(/ (DEFAULT )?VALUES/i), " OUTPUT" + returning_columns_statements.join(",")
370+
else
371+
sql
372+
end
373+
end
374+
else
375+
"#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
376+
end
377377

378378
[sql, binds]
379379
end
@@ -542,16 +542,16 @@ def build_sql_for_returning(insert:, insert_all:)
542542
return "" unless insert_all.returning
543543

544544
returning_values_sql = if insert_all.returning.is_a?(String)
545-
insert_all.returning
546-
else
547-
Array(insert_all.returning).map do |attribute|
548-
if insert.model.attribute_alias?(attribute)
549-
"INSERTED.#{quote_column_name(insert.model.attribute_alias(attribute))} AS #{quote_column_name(attribute)}"
550-
else
551-
"INSERTED.#{quote_column_name(attribute)}"
552-
end
553-
end.join(",")
554-
end
545+
insert_all.returning
546+
else
547+
Array(insert_all.returning).map do |attribute|
548+
if insert.model.attribute_alias?(attribute)
549+
"INSERTED.#{quote_column_name(insert.model.attribute_alias(attribute))} AS #{quote_column_name(attribute)}"
550+
else
551+
"INSERTED.#{quote_column_name(attribute)}"
552+
end
553+
end.join(",")
554+
end
555555

556556
" OUTPUT #{returning_values_sql}"
557557
end

test/cases/view_test_sqlserver.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,16 @@ class ViewTestSQLServer < ActiveRecord::TestCase
5353
end
5454

5555
describe "identity insert" do
56-
it "identity insert works with views" do
57-
assert_difference("SSTestCustomersView.count", 1) do
56+
it "creates table record through a view" do
57+
assert_difference("SSTestCustomersView.count", 2) do
5858
SSTestCustomersView.create!(id: 5, name: "Bob")
59+
SSTestCustomersView.create!(id: 6, name: "Tim")
5960
end
6061
end
62+
63+
it "creates table records through a view using fixtures" do
64+
ActiveRecord::FixtureSet.create_fixtures(File.join(ARTest::SQLServer.test_root_sqlserver, "fixtures"), ["sst_customers_view"])
65+
assert_equal SSTestCustomersView.all.count, 2
66+
end
6167
end
6268
end

test/fixtures/sst_customers_view.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
david:
2+
name: "David"
3+
balance: 2,004
4+
aidan:
5+
name: "Aidan"
6+
balance: 10,191

0 commit comments

Comments
 (0)