ActiveRecord::ConnectionAdapters::SQLServerAdapter#update doesn't return the correct number of rows affected. Due to autocommit behavior, this is actually returning "1" if the update was in a transaction, and "0" if not.
The attached test case creates a temp table, inserts 10 rows, and then updates all rows. Instead of the expect 10 rows affected, we get 0 because the test wasn't running in a transaction.
A SQL trace of the test reveals the problem:
-- test setup
CREATE TABLE #RecordsAffectedTest(int foo)
IF @@TRANCOUNT > 0 COMMIT TRAN
[active record reflecting on the #RecordsAffectedTest]
-- actual test
[bunch of inserts, each followed by "IF @@TRANCOUNT > 0 COMMIT TRAN"]
UPDATE #RecordsAffectedTest SET foo = -1
IF @@TRANCOUNT > 0 COMMIT TRAN
SELECT @@ROWCOUNT AS AffectedRows
-- test teardown
DROP TABLE #RecordsAffectedTest
The IF @@TRANCOUNT > 0 COMMIT TRAN seems to be coming from the ADO/ODBC driver, I couldn't see that anywhere in ruby DBI source that the connection adapter is using.
I get this bug running on WinXP with ActiveRecord 1.15.3. This can be fixed by disabling AutoCommit during an update, but I'm not sure if that's a reasonable thing to do or not.
Interestingly, this test runs fine on Debian using freeTDS and unixodbc. The trace of this test running on Debian is:
-- test setup
CREATE TABLE #RecordsAffectedTest(int foo)
[active record reflecting on the #RecordsAffectedTest]
-- actual test
[bunch of inserts]
UPDATE #RecordsAffectedTest SET foo = -1
-- test teardown
DROP TABLE #RecordsAffectedTest
The debian driver doesn't issue a single IF @@TRANCOUNT > 0 COMMIT TRAN, even though AutoCommit is on, nor does it SELECT @@ROWCOUNT. The driver used there returns the rows affected directly as handle.rows.