Skip to content

Commit 67ca8b5

Browse files
authored
feat: add transactional migrations support (#132) (#137)
Adds transactional migrations for database adapters that support DDL transactions. When enabled, migrations run atomically - either everything succeeds or everything rolls back. No more partial migrations leaving your database in an inconsistent state. Builds on the hybrid versioning work in #128.
1 parent 8c9fa38 commit 67ca8b5

File tree

14 files changed

+226
-51
lines changed

14 files changed

+226
-51
lines changed

sqlspec/adapters/adbc/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
100100

101101
driver_type: ClassVar[type[AdbcDriver]] = AdbcDriver
102102
connection_type: "ClassVar[type[AdbcConnection]]" = AdbcConnection
103+
supports_transactional_ddl: ClassVar[bool] = False
103104

104105
def __init__(
105106
self,

sqlspec/adapters/aiosqlite/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
7373

7474
driver_type: "ClassVar[type[AiosqliteDriver]]" = AiosqliteDriver
7575
connection_type: "ClassVar[type[AiosqliteConnection]]" = AiosqliteConnection
76+
supports_transactional_ddl: "ClassVar[bool]" = True
7677

7778
def __init__(
7879
self,

sqlspec/adapters/asyncmy/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class AsyncmyConfig(AsyncDatabaseConfig[AsyncmyConnection, "AsyncmyPool", Asyncm
8383

8484
driver_type: ClassVar[type[AsyncmyDriver]] = AsyncmyDriver
8585
connection_type: "ClassVar[type[AsyncmyConnection]]" = AsyncmyConnection # pyright: ignore
86+
supports_transactional_ddl: ClassVar[bool] = False
8687

8788
def __init__(
8889
self,

sqlspec/adapters/asyncpg/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class AsyncpgConfig(AsyncDatabaseConfig[AsyncpgConnection, "Pool[Record]", Async
9696

9797
driver_type: "ClassVar[type[AsyncpgDriver]]" = AsyncpgDriver
9898
connection_type: "ClassVar[type[AsyncpgConnection]]" = type(AsyncpgConnection) # type: ignore[assignment]
99+
supports_transactional_ddl: "ClassVar[bool]" = True
99100

100101
def __init__(
101102
self,

sqlspec/adapters/bigquery/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class BigQueryConfig(NoPoolSyncConfig[BigQueryConnection, BigQueryDriver]):
8888

8989
driver_type: ClassVar[type[BigQueryDriver]] = BigQueryDriver
9090
connection_type: "ClassVar[type[BigQueryConnection]]" = BigQueryConnection
91+
supports_transactional_ddl: ClassVar[bool] = False
9192

9293
def __init__(
9394
self,

sqlspec/adapters/duckdb/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class DuckDBConfig(SyncDatabaseConfig[DuckDBConnection, DuckDBConnectionPool, Du
176176

177177
driver_type: "ClassVar[type[DuckDBDriver]]" = DuckDBDriver
178178
connection_type: "ClassVar[type[DuckDBConnection]]" = DuckDBConnection
179+
supports_transactional_ddl: "ClassVar[bool]" = True
179180

180181
def __init__(
181182
self,

sqlspec/adapters/oracledb/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class OracleSyncConfig(SyncDatabaseConfig[OracleSyncConnection, "OracleSyncConne
106106
driver_type: ClassVar[type[OracleSyncDriver]] = OracleSyncDriver
107107
connection_type: "ClassVar[type[OracleSyncConnection]]" = OracleSyncConnection
108108
migration_tracker_type: "ClassVar[type[OracleSyncMigrationTracker]]" = OracleSyncMigrationTracker
109+
supports_transactional_ddl: ClassVar[bool] = False
109110

110111
def __init__(
111112
self,
@@ -263,6 +264,7 @@ class OracleAsyncConfig(AsyncDatabaseConfig[OracleAsyncConnection, "OracleAsyncC
263264
connection_type: "ClassVar[type[OracleAsyncConnection]]" = OracleAsyncConnection
264265
driver_type: ClassVar[type[OracleAsyncDriver]] = OracleAsyncDriver
265266
migration_tracker_type: "ClassVar[type[OracleAsyncMigrationTracker]]" = OracleAsyncMigrationTracker
267+
supports_transactional_ddl: ClassVar[bool] = False
266268

267269
def __init__(
268270
self,

sqlspec/adapters/psqlpy/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class PsqlpyConfig(AsyncDatabaseConfig[PsqlpyConnection, ConnectionPool, PsqlpyD
9494

9595
driver_type: ClassVar[type[PsqlpyDriver]] = PsqlpyDriver
9696
connection_type: "ClassVar[type[PsqlpyConnection]]" = PsqlpyConnection
97+
supports_transactional_ddl: "ClassVar[bool]" = True
9798

9899
def __init__(
99100
self,

sqlspec/adapters/psycopg/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class PsycopgSyncConfig(SyncDatabaseConfig[PsycopgSyncConnection, ConnectionPool
9595

9696
driver_type: "ClassVar[type[PsycopgSyncDriver]]" = PsycopgSyncDriver
9797
connection_type: "ClassVar[type[PsycopgSyncConnection]]" = PsycopgSyncConnection
98+
supports_transactional_ddl: "ClassVar[bool]" = True
9899

99100
def __init__(
100101
self,
@@ -285,6 +286,7 @@ class PsycopgAsyncConfig(AsyncDatabaseConfig[PsycopgAsyncConnection, AsyncConnec
285286

286287
driver_type: ClassVar[type[PsycopgAsyncDriver]] = PsycopgAsyncDriver
287288
connection_type: "ClassVar[type[PsycopgAsyncConnection]]" = PsycopgAsyncConnection
289+
supports_transactional_ddl: "ClassVar[bool]" = True
288290

289291
def __init__(
290292
self,

sqlspec/adapters/sqlite/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class SqliteConfig(SyncDatabaseConfig[SqliteConnection, SqliteConnectionPool, Sq
6262

6363
driver_type: "ClassVar[type[SqliteDriver]]" = SqliteDriver
6464
connection_type: "ClassVar[type[SqliteConnection]]" = SqliteConnection
65+
supports_transactional_ddl: "ClassVar[bool]" = True
6566

6667
def __init__(
6768
self,

0 commit comments

Comments
 (0)