Skip to content

Commit 1c44234

Browse files
authored
Fix table name parsing for INSERT INTO <table> WITH (<hints>) (#1424)
1 parent 08806e4 commit 1c44234

4 files changed

Lines changed: 11 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
- [#1397](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1397) Treat "DBPROCESS is dead or not enabled" as ConnectionNotEstablished.
1212
- [#1406](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1406) Stop deserializing column defaults.
1313
- [#1405](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1405) Fix `insert_all`/`upsert_all` for single character, temporary, non-ASCII and three part table names, and stop an aliased target being included in the `MERGE` table name.
14+
- [#1424](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1424) Fix table name parsing for `INSERT INTO <table> WITH (<hints>)`.
1415

1516
Please check [8-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/8-1-stable/CHANGELOG.md) for previous changes.

‎lib/active_record/connection_adapters/sqlserver/database_statements.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ def query_requires_identity_insert?(sql)
550550
id_column = identity_columns(raw_table_name).first
551551

552552
if id_column && (
553-
sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)[^(]+\([^)]*\b(#{id_column.name})\b,?[^)]*\)/i ||
553+
sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)[^(]+(?:WITH\s*\([^)]*\)\s*)?\([^)]*\b(#{id_column.name})\b,?[^)]*\)/i ||
554554
sql =~ /^\s*MERGE INTO.+THEN INSERT \([^)]*\b(#{id_column.name})\b,?[^)]*\)/im
555555
)
556556
SQLServer::Utils.extract_identifiers(raw_table_name).quoted

‎lib/active_record/connection_adapters/sqlserver/schema_statements.rb‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ def get_raw_table_name(sql)
911911
.split(/OUTPUT INSERTED/i)[0]
912912
.split(/(DEFAULT)?\s+VALUES/i)[0]
913913
.split(/\bSELECT\b(?![^\[]*\])/i)[0]
914+
.split(/\s+WITH\s*\(/i)[0] # Strip table hints (eg: "INSERT INTO books WITH (TABLOCK) (title)")
914915
.match(/\s*([^(]*)/i)[0]
915916
elsif s.match?(/^\s*UPDATE\s+.*/i)
916917
s.match(/UPDATE\s+([^(\s]+)\s*/i)[1]

‎test/cases/adapter_test_sqlserver.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
111111
assert_equal "customers", connection.send(:get_table_name, basic_select_sql)
112112
end
113113

114+
it "execute INSERT statements with table hints" do
115+
assert_difference -> { connection.select_value("SELECT COUNT(*) FROM [funny_jokes]") }, 2 do
116+
connection.execute("INSERT INTO [funny_jokes] WITH (TABLOCK) ([name]) VALUES ('Knock knock')")
117+
connection.execute("INSERT INTO [funny_jokes] WITH (TABLOCK) ([id], [name]) VALUES (420, 'Knock knock')")
118+
end
119+
assert_equal "Knock knock", connection.select_value("SELECT [name] FROM [funny_jokes] WHERE [id] = 420")
120+
end
121+
114122
it "test bad connection" do
115123
assert_raise ActiveRecord::NoDatabaseError do
116124
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")

0 commit comments

Comments
 (0)