Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9558 (closed defect: fixed)

Opened 1 year ago

Last modified 1 year ago

[PATCH] [TEST] ActiveRecord::ConnectionAdapters::SQLServerAdapter#update doesn't return AffectedRows accurately

Reported by: ryepup Assigned to: core
Priority: normal Milestone: 2.x
Component: ActiveRecord Version:
Severity: normal Keywords: sqlserver, patch, test
Cc: ryan@acceleration.net

Description

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.

Attachments

records_affected_test.rb (1.2 kB) - added by ryepup on 09/14/07 21:24:56.
unit test, needs customization for local database connection info
affected_rows.patch (2.5 kB) - added by lawrence on 10/18/07 23:10:50.
sqlserver_affected_rows.patch (2.2 kB) - added by lawrence on 10/18/07 23:20:36.

Change History

09/14/07 21:24:56 changed by ryepup

  • attachment records_affected_test.rb added.

unit test, needs customization for local database connection info

09/21/07 07:07:56 changed by lawrence

  • keywords changed from sqlserver to sqlserver, patch, test.
  • summary changed from ActiveRecord::ConnectionAdapters::SQLServerAdapter#update doesn't return AffectedRows accurately to [PATCH] [TEST] ActiveRecord::ConnectionAdapters::SQLServerAdapter#update doesn't return AffectedRows accurately.

When running within a transaction SQL Server returns the nr of affected rows upon an update or delete just fine. As the tests from test_base.rb are running within a transaction several tests run fine now.

Added separate test in affected_rows_test.rb to test behavior when not within transaction, i.e. when autocommiting. Patched sqlserver_adapter.rb to pass the test.

10/18/07 23:10:50 changed by lawrence

  • attachment affected_rows.patch added.

10/18/07 23:20:36 changed by lawrence

  • attachment sqlserver_affected_rows.patch added.

10/18/07 23:39:53 changed by lawrence

Todo:

- apply affected_rows.patch to AR core

- apply sqlserver_affected_rows.patch to SQL Server plugin

10/18/07 23:48:03 changed by bitsweat

(In [7968]) SQL Server: test for affected row count. References #9558 [lawrence, ryepup]

10/18/07 23:53:12 changed by lawrence

  • status changed from new to closed.
  • resolution set to fixed.

(In [7969]) SQL Server: test for affected row count. Closes #9558 [lawrence, ryepup]