Skip to content

Commit 446bca4

Browse files
authored
Fix Composite Key Inserts with Triggers (#1152)
1 parent 58c72ea commit 446bca4

File tree

5 files changed

+41
-4
lines changed

5 files changed

+41
-4
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## Unreleased
2+
3+
#### Fixed
4+
5+
- [#1152](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1152) Fix Composite Key Inserts with Triggers
6+
17
## v7.1.2
28

39
#### Fixed

lib/active_record/connection_adapters/sqlserver/database_statements.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,13 @@ def sql_for_insert(sql, pk, binds, returning)
278278
exclude_output_inserted = exclude_output_inserted_table_name?(table_name, sql)
279279

280280
if exclude_output_inserted
281-
quoted_pk = SQLServer::Utils.extract_identifiers(pk).quoted
281+
quoted_pk = Array(pk).map { |subkey| SQLServer::Utils.extract_identifiers(subkey).quoted }
282282

283283
id_sql_type = exclude_output_inserted.is_a?(TrueClass) ? "bigint" : exclude_output_inserted
284284
<<~SQL.squish
285-
DECLARE @ssaIdInsertTable table (#{quoted_pk} #{id_sql_type});
286-
#{sql.dup.insert sql.index(/ (DEFAULT )?VALUES/i), " OUTPUT INSERTED.#{quoted_pk} INTO @ssaIdInsertTable"}
287-
SELECT CAST(#{quoted_pk} AS #{id_sql_type}) FROM @ssaIdInsertTable
285+
DECLARE @ssaIdInsertTable table (#{quoted_pk.map { |subkey| "#{subkey} #{id_sql_type}"}.join(", ") });
286+
#{sql.dup.insert sql.index(/ (DEFAULT )?VALUES/i), " OUTPUT #{ quoted_pk.map { |subkey| "INSERTED.#{subkey}" }.join(", ") } INTO @ssaIdInsertTable"}
287+
SELECT #{quoted_pk.map {|subkey| "CAST(#{subkey} AS #{id_sql_type}) #{subkey}"}.join(", ")} FROM @ssaIdInsertTable
288288
SQL
289289
else
290290
returning_columns = returning || Array(pk)

test/cases/trigger_test_sqlserver.rb

+10
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,14 @@ class SQLServerTriggerTest < ActiveRecord::TestCase
2828
_(obj.id).must_be :present?
2929
_(obj.id.to_s).must_equal SSTestTriggerHistory.first.id_source
3030
end
31+
32+
it "can insert into a table with composite pk with output inserted - with a true setting for table name" do
33+
exclude_output_inserted_table_names["sst_table_with_composite_pk_trigger"] = true
34+
assert SSTestTriggerHistory.all.empty?
35+
obj = SSTestTriggerCompositePk.create! pk_col_one: 123, pk_col_two: 42, event_name: "test trigger"
36+
_(obj.event_name).must_equal "test trigger"
37+
_(obj.pk_col_one).must_equal 123
38+
_(obj.pk_col_two).must_equal 42
39+
_(obj.pk_col_one.to_s).must_equal SSTestTriggerHistory.first.id_source
40+
end
3141
end

test/models/sqlserver/trigger.rb

+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ class SSTestTrigger < ActiveRecord::Base
77
class SSTestTriggerUuid < ActiveRecord::Base
88
self.table_name = "sst_table_with_uuid_trigger"
99
end
10+
11+
class SSTestTriggerCompositePk < ActiveRecord::Base
12+
self.table_name = "sst_table_with_composite_pk_trigger"
13+
end

test/schema/sqlserver_specific_schema.rb

+17
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,23 @@
232232
SELECT id AS id_source, event_name FROM INSERTED
233233
SQL
234234

235+
execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sst_table_with_composite_pk_trigger') DROP TABLE sst_table_with_composite_pk_trigger"
236+
execute <<-SQL
237+
CREATE TABLE sst_table_with_composite_pk_trigger(
238+
pk_col_one int NOT NULL,
239+
pk_col_two int NOT NULL,
240+
event_name nvarchar(255),
241+
CONSTRAINT PK_sst_table_with_composite_pk_trigger PRIMARY KEY (pk_col_one, pk_col_two)
242+
)
243+
SQL
244+
execute <<-SQL
245+
CREATE TRIGGER sst_table_with_composite_pk_trigger_t ON sst_table_with_composite_pk_trigger
246+
FOR INSERT
247+
AS
248+
INSERT INTO sst_table_with_trigger_history (id_source, event_name)
249+
SELECT pk_col_one AS id_source, event_name FROM INSERTED
250+
SQL
251+
235252
# Another schema.
236253

237254
create_table :sst_schema_columns, force: true do |t|

0 commit comments

Comments
 (0)