Skip to content

Commit 16ab336

Browse files
committed
Fix MySQL test cleanup using db.synchronize for same connection
The root cause of the FK constraint violations was that MySQL's SET FOREIGN_KEY_CHECKS is session-specific (per-connection). When using Sequel's connection pool, each db.run() call can get a different connection, so SET FOREIGN_KEY_CHECKS=0 executed on one connection doesn't affect TRUNCATE statements executed on other connections. Solution: Use db.synchronize to hold a single connection from the pool and execute all operations (SET FK=0, TRUNCATE, SET FK=1) on that same connection using conn.query() instead of db.run(). This ensures the FK checks are properly disabled for all TRUNCATE operations while they execute, then re-enabled afterward, all on the same connection. PostgreSQL continues to use TRUNCATE with CASCADE, which doesn't require this workaround as it handles foreign keys correctly in a single statement. This fixes thousands of FK constraint violations in MySQL 8.2 tests.
1 parent c27eaf2 commit 16ab336

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

spec/support/table_truncator.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,25 @@ def self.isolated_tables(db)
99
end
1010

1111
def truncate_tables
12-
referential_integrity = ReferentialIntegrity.new(db)
13-
referential_integrity.without do
14-
case db.database_type
15-
when :postgres
12+
case db.database_type
13+
when :postgres
14+
referential_integrity = ReferentialIntegrity.new(db)
15+
referential_integrity.without do
1616
tables.each do |table|
1717
db.run("TRUNCATE TABLE #{table} RESTART IDENTITY CASCADE;")
1818
end
19-
when :mysql
19+
end
20+
when :mysql
21+
# Use db.synchronize to ensure SET FOREIGN_KEY_CHECKS and all TRUNCATE
22+
# statements run on the SAME connection from the pool. Without this,
23+
# each db.run() can get a different connection, and SET FOREIGN_KEY_CHECKS=0
24+
# (which is session-specific) won't apply to the TRUNCATE statements.
25+
db.synchronize do |conn|
26+
conn.query('SET FOREIGN_KEY_CHECKS = 0')
2027
tables.each do |table|
21-
db.run("TRUNCATE TABLE #{table};")
28+
conn.query("TRUNCATE TABLE #{table}")
2229
end
30+
conn.query('SET FOREIGN_KEY_CHECKS = 1')
2331
end
2432
end
2533
end

0 commit comments

Comments
 (0)