2.1.0rc2
- Made the collection of per-mapper / per-table binds available publicly as Session.binds, an immutable dictionary that is replaced rather than mutated when a new bind is added
- AsyncSession.bind and AsyncSession.binds are now always present and derived from the underlying sync_session, translated back into their asyncio equivalents
- Added AsyncSession.get_async_bind(), AsyncSession.bind_mapper() and AsyncSession.bind_table() as the asyncio-facing counterparts to the Session methods
- Implemented Inspector.get_table_options() for the SQLite dialect, which returns the sqlite_with_rowid and sqlite_strict dialect options for a table
- Improved the implementation of Pool to use weakref.finalize() instead of a weakref.ref() finalizer to handle GC cleanup of non-detached, pooled connections
- Fixed issue where an expression passed to with_expression() that embedded a select(), such as a correlated exists(), would fail to populate the attribute correctly on the second and subsequent executions when loaded by a relationship loader
- Fixed memory issue where mapped classes, along with their Table and Mapper objects, would not be garbage collected after the registry had been disposed and dereferenced
- Fixed memory issue where a declarative class making use of __declare_first__() or __declare_last__() hooks could never be garbage collected
- Reworked the regular expression that parses FOREIGN KEY constraints during SQLite CREATE TABLE reflection to avoid potential exponential backtracking
From SQLAlchemy
Released: September 8, 2026
orm
-
[orm] [usecase] The collection of per-mapper / per-table binds established by the
_orm.Session.bindsparameter, as well as by the_orm.Session.bind_mapper()and_orm.Session.bind_table()methods, is now available publicly as_orm.Session.binds; the collection was previously stored under a private, name-mangled attribute. It is an immutable dictionary, and is replaced rather than mutated when a new bind is added, so a reference to it will not observe subsequent changes. The collection is also proxied by_orm.scoping.scoped_session.References: #13563
-
[orm] [bug] Fixed issue where an expression passed to
_orm.with_expression()that embedded a_sql.select(), such as a correlated_sql.exists(), would fail to populate the attribute correctly on the second and subsequent executions of an otherwise identical statement, when the_orm.query_expression()attribute was loaded by a relationship loader that emits a second query, i.e._orm.selectinload(),_orm.lazyload()or_orm.immediateload().This change is also backported to: 2.0.53
References: #13560
-
[orm] [bug] Fixed memory issue where mapped classes, along with their
Tableand_orm.Mapperobjects, would not be garbage collected after the_orm.registryin which they were mapped had been disposed and dereferenced. The issue would occur for mappings that made use of_orm.relationship()together with constructs such as anIndexestablished against an ORM-annotated expression.This change is also backported to: 2.0.53
References: #13566
orm declarative
-
[bug] [orm declarative] Fixed memory issue where a declarative class making use of the
__declare_first__()or__declare_last__()hooks could never be garbage collected, as each such class established its own permanent_orm.Mapper-wide event listener referring to it. These hooks are now invoked by_orm.registry-localRegistryEventslisteners which refer to the classes weakly, and which are invoked only for the_orm.registrybeing configured. As the hooks are now located as the class is added to the_orm.registry, they also take effect for classes mapped using_orm.registry.map_imperatively().References: #9147
engine
- [engine] [changed] Improved the implementation of
_pool.Poolto useweakref.finalize()instead of aweakref.ref()finalizer to handle GC cleanup of non-detached, pooled connections that were not explicitly closed.
asyncio
-
[asyncio] [usecase]
_asyncio.AsyncSession.bindand_asyncio.AsyncSession.bindsare now always present and are derived from the underlying_asyncio.AsyncSession.sync_session, translated back into their asyncio equivalents. Added_asyncio.AsyncSession.get_async_bind(),_asyncio.AsyncSession.bind_mapper()and_asyncio.AsyncSession.bind_table()as the asyncio-facing counterparts to the_orm.Sessionmethods of the same name. Both attributes, along with_asyncio.AsyncSession.get_async_bind(), are proxied by_asyncio.async_scoped_session.References: #13563
sqlite
-
[sqlite] [usecase] [reflection] Implemented
_engine.Inspector.get_table_options()for the SQLite dialect, which previously raisedNotImplementedError. The method returns thesqlite_with_rowidandsqlite_strictdialect options for a table that was created using theWITHOUT ROWIDand / orSTRICTkeywords. As a result, these keywords are now also present in_schema.Table.kwargsfor a_schema.Tablethat is reflected using autoload, so that a table which is recreated from its reflected form, such as by Alembic's batch migration mode, renders the keywords again rather than silently dropping them.This change is also backported to: 2.0.53
References: #13543
-
[sqlite] [bug] [reflection] Reworked the regular expression that parses
FOREIGN KEYconstraints during SQLiteCREATE TABLEreflection so that the referred column list is matched unambiguously avoiding potential exponential backtracking. Pull request courtesy of Javid Khan.This change is also backported to: 2.0.53
References: #13530