Does database/sql support reversible DDL operations across different drivers
0 reputation · 30 Jul 2021, 15:08 UTC
0 reputation · 30 Jul 2021, 15:08 UTC
The Go database/sql package provides transaction management through Tx.Begin, Tx.Commit, and Tx.Rollback. While these methods handle DML operations, the standard library does not define an abstraction for Data Definition Language (DDL) changes or schema migrations.
Because many SQL engines perform implicit commits when a DDL statement (like CREATE TABLE or ALTER) is executed, the behavior of Tx.Rollback becomes inconsistent across different database drivers. This creates a boundary where the standard library's transaction safety depends on the engine's ability to undo schema changes.
How does the database/sql package ensure consistency when DDL statements are executed within a transaction, and are there specific error patterns developers should look for to identify when a schema-level rollback failed due to implicit commits?
No. Assuming a current Go toolchain and a standard database/sql driver, the package does not support reversible DDL across different drivers. It has no abstraction for DDL, DML, or schema migrations; it forwards SQL strings to drivers unchanged. Whether Tx.Rollback can undo a CREATE TABLE or ALTER depends entirely on the underlying database engine.
Confirmed: database/sql treats every statement as an opaque string. It does not parse SQL, classify statements, or coordinate with the driver to ensure schema changes are transactional. The Tx type only wraps the driver's transaction primitives.
Likely explanation: the inconsistency you observed comes from the engine, not the library. PostgreSQL and SQLite can roll back CREATE and ALTER inside a transaction. MySQL and Oracle typically issue an implicit commit when DDL executes, closing the transaction before Rollback is called.
There is no sentinel error, error code, or interface in database/sql that identifies an implicit commit caused by DDL. If the engine commits implicitly, Tx.Rollback may still return nil because the driver successfully ends the already-committed transaction. A nil error from Rollback does not prove that schema changes were undone.
tx, _ := db.Begin()
_, _ = tx.Exec("CREATE TABLE tmp_check (id int)")
_ = tx.Rollback()
// PostgreSQL: SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'tmp_check');
// MySQL: SHOW TABLES LIKE 'tmp_check';
If the table still exists, the engine committed implicitly.
If you are targeting a single engine rather than portable code, tell me which database and driver version you use. That determines whether transactional DDL is available in your specific stack.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.