rails-sqlserver/activerecord-sqlserver-adapter

exclude_output_inserted_table_names does not support composite primary keys with different data types

vividmuimui opened this issue · 0 comments

Issue

The exclude_output_inserted_table_names feature does not handle composite primary keys with defferent data types properly.

Expected behavior

The exclude_output_inserted_table_names should be able to handle composite primary keys of different data types without errors.

Actual behavior

Currently, if you try to use exclude_output_inserted_table_names for a table with a composite primary key, this setting will not handle the scenario correctly. This limitation makes it particularly difficult to manage tables with composite keys containing different data types.

How to reproduce

Create a table with a composite primary key where the keys have different data types and attempt to insert data using the ActiveRecord-SQLServer adapter with exclude_output_inserted_table_names configured. Here is an example setup that triggers the error:

create_table "SampleTable", primary_key: ["KeyPart1", "KeyPart2"], force: :cascade do |t|
  t.uuid "KeyPart1", null: false
  t.integer "KeyPart2", null: false # different data type
end
adapter = ActiveRecord::ConnectionAdapters::SQLServerAdapter
adapter.exclude_output_inserted_table_names[SampleTable] = 'uniqueidentifier'

Attempting to insert data into this table results in the following error:

  TRANSACTION (0.7ms)  BEGIN TRANSACTION
  SampleTable Create (6.4ms)  EXEC sp_executesql N'DECLARE @ssaIdInsertTable table ([KeyPart1] uniqueidentifier, [KeyPart2] uniqueidentifier); INSERT INTO [SampleTable] ([KeyPart1], [KeyPart2], [CreatedAt], [UpdatedAt]) OUTPUT INSERTED.[KeyPart1], INSERTED.[KeyPart2] INTO @ssaIdInsertTable VALUES (@0, @1, @2, @3) SELECT CAST([KeyPart1] AS uniqueidentifier) [KeyPart1], CAST([KeyPart2] AS uniqueidentifier) [KeyPart2] FROM @ssaIdInsertTable', N'@0 uniqueidentifier, @1 int, @2 datetimeoffset(7), @3 datetimeoffset(7)', @0 = '4128767C-9775-4FC0-966E-757030073AD1', @1 = 1, @2 = '04-23-2024 09:21:01.189011', @3 = '04-23-2024 09:21:01.189011'  [["KeyPart1", nil], ["KeyPart2", nil], ["CreatedAt", nil], ["UpdatedAt", nil]]
  TRANSACTION (0.8ms)  IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
/path/to/project/vendor/bundle/ruby/3.3.0/gems/activerecord-sqlserver-adapter-7.1.3/lib/active_record/connection_adapters/sqlserver/database_statements.rb:416:in `each': TinyTds::Error: Operand type clash: int is incompatible with uniqueidentifier (ActiveRecord::StatementInvalid)
/path/to/project/vendor/bundle/ruby/3.3.0/gems/activerecord-sqlserver-adapter-7.1.3/lib/active_record/connection_adapters/sqlserver/database_statements.rb:416:in `each': Operand type clash: int is incompatible with uniqueidentifier (TinyTds::Error)

Details

  • Rails version: 7.1.3.2
  • SQL Server adapter version: 7.1.3
  • TinyTDS version: 2.1.7
  • FreeTDS details:
Compile-time settings (established with the "configure" script)
                            Version: freetds v1.4.12
             freetds.conf directory: /opt/homebrew/etc
     MS db-lib source compatibility: no
        Sybase binary compatibility: yes
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 7.3
                              iODBC: no
                           unixodbc: yes
              SSPI "trusted" logins: no
                           Kerberos: yes
                            OpenSSL: yes
                             GnuTLS: no
                               MARS: yes