Reputation: 1629
The full error is
ActiveRecord::StatementInvalid: Mysql2::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1
I am writing a unit test and getting this error whenever I try to create a new ActiveRecord object -- but only after a certain point. This occurs after these lines:
ActiveRecord::Base.connection.execute "DROP TABLE IF EXISTS foo"
ActiveRecord::Base.connection.execute "CREATE TABLE foo (id INTEGER PRIMARY KEY)"
(The table 'foo' will be populated with data if my test succeeds)
Before the above lines, I can write something like
User.create(email => '[email protected]')
and everything works fine. However, if I try writing the above line after my call to ActiveRecord::Base.connection.execute
, then I get this SAVEPOINT error
described above. I've also tried putting my execute statements within a transaction, but that didn't help. I'm stumped.
FYI - I'm using Rails 3.2.8
Upvotes: 29
Views: 20496
Reputation: 1526
First ensure that you have the DatabaseCleaner gem installed which will allow you to pick the DB cleaning strategy. The error we are receiving means it will be best to use the truncation
strategy.
# file: Gemfile
group :test do
gem ‘database_cleaner’
end
Add a DatabaseCleaner config to features directory(see below).
#file: features/support/database_cleaner.rb
begin
require 'database_cleaner'
require 'database_cleaner/cucumber'
DatabaseCleaner.strategy = :truncation
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
Around do |scenario, block|
DatabaseCleaner.cleaning(&block)
end
Upvotes: 0
Reputation: 2274
Just to clarify. You can isolate tests that trigger MySql DDE statements into their own file and then cram config.use_transactional_fixtures = false
in that file. This way all your other tests not going to be affected. Now you are responsible for cleanup in that isolated test file.
Upvotes: 2
Reputation: 604
To solve this issue..
config.use_transactional_fixtures = false
Upvotes: 9
Reputation: 41
You can use "TEMPORARY" when you create/drop tables.
http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html ALTER TABLE, CREATE TABLE, and DROP TABLE do not commit a transaction if the TEMPORARY keyword is used. (This does not apply to other operations on temporary tables such as CREATE INDEX, which do cause a commit.) However, although no implicit commit occurs, neither can the statement be rolled back. Therefore, use of such statements will violate transaction atomicity: For example, if you use CREATE TEMPORARY TABLE and then roll back the transaction, the table remains in existence.
Upvotes: 4
Reputation: 2769
You are using Mysql DDE statements (create/drop/truncate table) which will result in an implicit commit.
Because of the implicit commit, all savepoints of the current transaction are deleted (Refer to above documentation).
To get around this, you can turn off transactions and use DatabaseCleaner (truncation mode).
Upvotes: 31
Reputation: 174
I found the following links that helped me:
Upvotes: 0