Change8

rel_2_0_38

Breaking Changes
📦 sqlalchemyView on GitHub →
1 breaking1 features🐛 6 fixes🔧 6 symbols

Summary

SQLAlchemy 2.0.38 introduces a new asyncio.shield() safeguard for asyncpg termination, fixes several bugs across engines and dialects, and changes the default aiosqlite pool, which may require a migration step.

⚠️ Breaking Changes

  • The default connection pool for the aiosqlite dialect was changed from NullPool to AsyncAdaptedQueuePool, which may break code that relied on NullPool behavior. To fix, explicitly specify NullPool (e.g., poolclass=NullPool) or adjust your pool usage accordingly.

Migration Steps

  1. If your application relies on the aiosqlite dialect using NullPool, explicitly set poolclass=NullPool when creating the engine.
  2. Review any custom pool configurations for aiosqlite to ensure they are compatible with AsyncAdaptedQueuePool.
  3. No other migration steps are required for this release.

✨ New Features

  • Added an asyncio.shield() call within the asyncpg driver’s connection termination process to ensure termination completes under anyio.

🐛 Bug Fixes

  • Fixed event‑related issue where invoking Engine.execution_options() multiple times with event‑registering parameters (e.g., isolation_level) caused internal errors during event registration.
  • Reorganized the internals that generate the .c collection on a FromClause to make it safe for concurrent access, fixing issues in the Oracle dialect and other use cases.
  • Fixed SQL composition bug where a None value inside an in_() expression bypassed the expanded bind‑parameter logic, breaking caching.
  • Adjusted the asyncpg connection wrapper so that connection.transaction() sends None for isolation_level when not set, allowing asyncpg to use the server‑level default instead of a hard‑coded read_committed.
  • Fixed a bug in the MySQL statement compiler where _mysql.Insert.on_duplicate_key_update() could not compile when passed ORM‑mapped attributes (InstrumentedAttribute objects) as keys.
  • Changed the default connection pool used by the aiosqlite dialect from NullPool to AsyncAdaptedQueuePool, aligning it with the pysqlite dialect change.

🔧 Affected Symbols

sqlalchemy.engine.Engine.execution_optionssqlalchemy.sql.FromClause.csqlalchemy.sql.expression.in_sqlalchemy.dialects.postgresql.asyncpg.AsyncPGConnection.transactionsqlalchemy.dialects.mysql._mysql.Insert.on_duplicate_key_updatesqlalchemy.dialects.sqlite.aiosqlite.AsyncAdaptedQueuePool