Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/database_rewinder/cleaner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def delete_all(ar_conn, tables, multiple: true)
# Print the warning message, then fall back to non-multiple deletion
Kernel.warn "WARNING: You may be executing DatabaseRewinder inside a transactional test. You're presumably misconfiguring your tests. Please read DatabaseRewinder's document, and properly configure your tests."
else
ar_conn.execute_multiple tables.map {|t| "DELETE FROM #{ar_conn.quote_table_name(t)}"}.join(';')
ar_conn.delete_multiple tables
return
end
end
Expand Down
34 changes: 19 additions & 15 deletions lib/database_rewinder/multiple_statements_executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,47 @@ def supports_multiple_statements?
%w(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::SQLite3Adapter).include? self.class.name
end

def execute_multiple(sql)
def delete_multiple(tables)
#TODO Use ADAPTER_NAME when we've dropped AR 4.1 support
case self.class.name
when 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter'
sql = tables_to_one_delete_sql tables
disable_referential_integrity { log(sql) { @connection.exec sql } }

when 'ActiveRecord::ConnectionAdapters::Mysql2Adapter'
if @connection.query_options[:connect_flags] & Mysql2::Client::MULTI_STATEMENTS != 0
disable_referential_integrity do
sql = tables_to_one_delete_sql tables
_result = log(sql) { @connection.query sql }
while @connection.next_result
# just to make sure that all queries are finished
_result = @connection.store_result
end
end

else
query_options = @connection.query_options.dup
query_options[:connect_flags] |= Mysql2::Client::MULTI_STATEMENTS
# opens another connection to the DB
client = Mysql2::Client.new query_options
begin
# disable_referential_integrity
client.query("SET FOREIGN_KEY_CHECKS = 0")
_result = log(sql) { client.query sql }
while client.next_result
# just to make sure that all queries are finished
_result = client.store_result
end
ensure
client.close
@connection.query 'drop procedure if exists rewind_em_all'
@connection.query <<-SQL
create procedure rewind_em_all(in tables text, in num integer) begin declare i int default 0; while i < num do set i = i + 1; set @delete_sql = concat('DELETE FROM ', substring_index(substring_index(tables, ',', i), ',', -1)); prepare stmt from @delete_sql; execute stmt; deallocate prepare stmt; end while; end;
SQL
disable_referential_integrity do
@connection.query "call rewind_em_all('#{tables.join(',')}', #{tables.length})"
end
end

when 'ActiveRecord::ConnectionAdapters::SQLite3Adapter'
sql = tables_to_one_delete_sql tables
disable_referential_integrity { log(sql) { @connection.execute_batch sql } }

else
raise 'Multiple deletion is not supported with the current database adapter.'
end
end

private
def tables_to_one_delete_sql(tables)
tables.map {|t| "DELETE FROM #{quote_table_name(t)}"}.join(';')
end
end
end
end