Releases: sqlalchemy/sqlalchemy
2.0.51
2.0.51
Released: June 15, 2026
orm
-
[orm] [bug] Fixed issue where
_orm.subqueryload()combined with
PropComparator.of_type()andPropComparator.and_()would
silently drop the additional filter criteria, causing all related objects
to be loaded instead of only those matching the filter. The
LoaderCriteriaOptionwas being constructed against the base
entity rather than the effective entity indicated by
PropComparator.of_type(). Pull request courtesy Arya Rizky.References: #13207
-
[orm] [bug] Fixed bug where a failure during
tpc_prepare()within
_orm.Session.commit()for a two-phase session would raise
IllegalStateChangeErrorinstead of the original database
exception. The internal_prepare_impl()method's error handler
was unable to invoke_orm.SessionTransaction.rollback()due
to a state-change guard, preventing proper cleanup and masking the
underlying error.References: #13356
engine
-
[engine] [bug] Fixed issue where
Result.freeze()would lose track of ambiguous
column names present in the originalCursorResult, causing
key-based access on the thawed result to silently return a value instead of
raisingInvalidRequestError. The
SimpleResultMetaDatanow accepts and propagates ambiguous key
information so that frozen, thawed, and pickled results raise consistently
for duplicate column names. Pull request courtesy Saurabh Kohli.References: #9427
sql
-
[sql] [bug] Fixed issue where
_sql.StatementLambdaElementwould proxy
attribute access through the cached "expected" expression rather than the
resolved expression, causing stale closure-bound parameter values to be
used when a lambda statement was extended with non-lambda criteria such as
an additional.where()clause. Courtesy cjc0013.References: #10827
postgresql
-
[postgresql] [bug] Repaired bug introduced in #13229 where a two-phase
transaction recovery would not return the correct transaction
identifier when generating the identifiers using thexid()
method of the psycopg connection.References: #13355
-
[postgresql] [bug] Fixed regular expression in the pure Python hstore result processor,
used whenuse_native_hstore=Falseis set, which could hang on
malformed hstore text containing unterminated quoted segments with
backslashes. Pull request courtesy dxbjavid.References: #13370
2.0.50
2.0.50
Released: May 24, 2026
orm
-
[orm] [bug] Fixed issue where using
_orm.joinedload()with
PropComparator.of_type()targeting a joined-table subclass combined
withPropComparator.and_()referencing a column on that subclass
would generate invalid SQL, where the subclass column was not adapted to
the subquery alias. Pull request courtesy Joaquin Hui Gomez.References: #13203
-
[orm] [bug] Fixed issue where the presence of a
SessionEvents.do_orm_execute()
event hook would cause internal execution options such asyield_perand
loader-specific state from the firstorm_pre_session_execpass to leak
into the second pass, leading to errors when using relationship loaders
such asselectinload()andimmediateload(). The execution
options passed to the second compilation pass are now based on the original
options plus only the explicit updates made via
ORMExecuteState.update_execution_options()within the event hook.References: #13301
-
[orm] [bug] Fixed issue where using
_orm.with_polymorphic()on a leaf class (a
subclass with no further descendants) or a non-inherited class would fail
with anAttributeErrorwhen used in an ORM statement, due to
_orm.configure_mappers()not being triggered implicitly. The fix
ensures thatAliasedInspparticipates in the_post_inspect
hook, triggering mapper configuration during ORM statement compilation.References: #13319
sql
-
[sql] [bug] Fixed issue where floor division (
//) between aFloator
Numericnumerator and anIntegerdenominator would omit
theFLOOR()SQL wrapper on dialects where
Dialect.div_is_floordivisTrue(the default, including
PostgreSQL and SQLite).FLOOR()is now applied if either the
denominator or the numerator is a non-integer, so that expressions such as
float_col // int_colrender asFLOOR(float_col / int_col)instead
of the incorrectfloat_col / int_col. Pull request courtesy r266-tech.References: #10528
postgresql
-
[postgresql] [bug] Improve handling of two phase transaction identifiers for PostgreSQL
when the identifier is provided by the user.
As part of this change the psycopg dialect was updated to use the DBAPI
two phase transaction API instead of executing the SQL directly.References: #13229
-
[postgresql] [bug] Fixed issue where the asyncpg driver could throw an insufficiently-handled
exceptionInternalClientErrorunder some circumstances, leading to
connections not being properly marked as invalidated.References: #13241
-
[postgresql] [bug] Fixed issue where the
ExcludeConstraintconstruct did not
correctly forward theExcludeConstraint.infoparameter to
the superclass, causing user-defined metadata to be lost. Pull request
courtesy Wiktor Byrka.References: #13317
mysql
-
[mysql] [bug] [reflection] Narrowed the scope of the internal workaround for MySQL bugs #88718 and #96365 so that it is only applied
where needed: MySQL 8.0.1 through 8.0.13 (where bug 88718 is present), and
on systems withlower_case_table_names=2(where bug 96365 applies,
typically macOS). Previously the workaround was applied unconditionally
for all MySQL 8.0+ versions, which caused aKeyErrorduring foreign key
reflection when the database user lacked SELECT privileges on referred
tables.References: #13243
-
[mysql] [bug] Fixed issue in aiomysql and asyncmy dialects that appears as of using
pymysql 1.2.0; the dialects were not properly taking into account logic
that detects the argument signature of pymysql'sping()method which
was added as part of #10492.References: #13306
sqlite
-
[sqlite] [bug] Escape key and pragma values when utilizing the pysqlcipher dialect.
References: #13230
2.1.0b2
2.1.0b2
Released: April 16, 2026
orm
-
[orm] [usecase] The
metadata,type_annotation_map, orregistrycan now be
set up in a declarative base also via a mixin class, not only by
directly setting them on the subclass like before.
The declarative class setup now usesgetattr()to look for these
attributes, instead of relying only on the class__dict__.References: #13198
sql
-
[sql] [usecase] Added new parameter
_sql.over.excludeto_sql.over()and
related methods, enabling SQL standard frame exclusion clausesEXCLUDE CURRENT ROW,EXCLUDE GROUP,EXCLUDE TIES,EXCLUDE NO OTHERS
in window functions. Pull request courtesy of Varun Chawla.References: #11671
-
[sql] [usecase] The
ColumnCollectionclass hierarchy has been refactored to allow
column names such asadd,remove,update,extend, and
clearto be used without conflicts.ColumnCollectionis now
an abstract base class, with mutation operations moved to
WriteableColumnCollectionandDedupeColumnCollection
subclasses. TheReadOnlyColumnCollectionexposed as attributes
such asTable.cno longer includes mutation methods that raised
NotImplementedError, allowing these common column names to be
accessed naturally, e.g.table.c.add,table.c.remove,
table.c.update, etc. -
[sql] [bug] A warning is emitted when using the standalone
_sql.distinct()
function in a_sql.select()columns list outside of an aggregate
function; this function is not intended as a replacement for the use of
Select.distinct(). Pull request courtesy bekapono.References: #11526
-
[sql] [bug] Improved the ability for
TypeDecoratorto produce a correct
repr()for "schema" types such asEnumandBoolean.
This is mostly to support the Alembic autogenerate use case so that custom
types render with relevant arguments present. Improved the architecture
used byTypeEngineto producerepr()strings to be more
modular for compound types likeTypeDecorator.References: #13140
schema
-
[schema] [usecase] Most
_sql.FromClausesubclasses are now generic on
_schema.TypedColumnssubclasses, that can be used to type their
_sql.FromClause.ccollection.
This applied to_schema.Table,_sql.Join,
_sql.Subquery,_sql.CTEand more.References: #13085
-
[schema] [bug] Amended the
repr()output forEnumso that the
MetaDatais not shown in the output, as this interferes with
Alembic-autogenerated forms of this type which should be inheriting the
MetaDataof the parent table in the migration script.References: #10604
typing
-
[typing] [bug] Fixed issue in new PEP 646 support for result sets where an issue in the
mypy type checker prevented "scalar" methods including
Connection.scalar(),Result.scalar(),
_orm.Session.scalar(), as well as async versions of these methods
from applying the correct type to the scalar result value, when the columns
in the originating_sql.select()were typed asAny. Pull request
courtesy Yurii Karabas.References: #13091
-
[typing] [bug] Improved typing of
_sqltypes.JSONas well as dialect specific
variants like_postgresql.JSONto include generic capabilities, so
that the types may be parameterized to indicate any specific type of
contents expected, e.g.JSONB[list[str]]().References: #13131
mssql
-
[mssql] [feature] Added support for the
mssql-pythondriver, Microsoft's official Python
driver for SQL Server.References: #12869
oracle
-
[oracle] [feature] Added support for the
_sqltypes.JSONdatatype when using the
Oracle database with the oracledb dialect. JSON values are serialized and
deserialized using configurable strategies that accommodate Oracle's native
JSON type available as of Oracle 21c. Pull request courtesy Abdallah
Alhadad.References: #10375
2.0.49
2.0.49
Released: April 3, 2026
orm
-
[orm] [bug] Fixed issue where
_orm.Session.get()would bypass the identity map
and emit unnecessary SQL whenwith_for_update=Falsewas passed,
rather than treating it equivalently to the default ofNone.
Pull request courtesy of Joshua Swanson.References: #13176
-
[orm] [bug] Fixed issue where chained
_orm.joinedload()options would not be
applied correctly when the final relationship in the chain is declared on a
base mapper and accessed through a subclass mapper in a
_orm.with_polymorphic()query. The path registry now correctly
computes the natural path when a property declared on a base class is
accessed through a path containing a subclass mapper, ensuring the loader
option can be located during query compilation.References: #13193
-
[orm] [bug] [inheritance] Fixed issue where using
_orm.Load.options()to apply a chained loader
option such as_orm.joinedload()or_orm.selectinload()with
_orm.PropComparator.of_type()for a polymorphic relationship would
not generate the necessary clauses for the polymorphic subclasses. The
polymorphic loading strategy is now correctly propagated when using a call
such asjoinedload(A.b).options(joinedload(B.c.of_type(poly)))to match
the behavior of direct chaining e.g.
joinedload(A.b).joinedload(B.c.of_type(poly)).References: #13202
-
[orm] [bug] [inheritance] Fixed issue where using chained loader options such as
_orm.selectinload()after_orm.joinedload()with
_orm.PropComparator.of_type()for a polymorphic relationship would
not properly apply the chained loader option. The loader option is now
correctly applied when using a call such as
joinedload(A.b.of_type(poly)).selectinload(poly.SubClass.c)to eagerly
load related objects.References: #13209
typing
-
[typing] [bug] Fixed a typing issue where the typed members of :data:
.funcwould return
the appropriate class of the same name, however this creates an issue for
typecheckers such as Zuban and pyrefly that assume PEP 749 style
typechecking even if the file states that it's a PEP 563 file; they see
the returned name as indicating the method object and not the class object.
These typecheckers are actually following along with an upcoming test
harness that insists on PEP 749 style name resolution for this case
unconditionally. Since PEP 749 is the way of the future regardless,
differently-named type aliases have been added for these return types.Unknown interpreted text role "data".
References: #13167
postgresql
-
[postgresql] [bug] Fixed regular expression used when reflecting foreign keys in PostgreSQL to
support escaped quotes in table names.
Pull request courtesy of Austin GrahamReferences: #10902
mssql
-
[mssql] [usecase] Enhanced the
aioodbcdialect to expose thefast_executemany
attribute of the pyodbc cursor. This allows thefast_executemany
parameter to work with themssql+aioodbcdialect. Pull request
courtesy Georg Sieber.References: #13152
-
[mssql] [usecase] Remove warning for SQL Server dialect when a new version is detected.
The warning was originally added more than 15 years ago due to an unexpected
value returned when using an old version of FreeTDS.
The assumption is that since then the issue has been resolved, so make the
SQL Server dialect behave like the other ones that don't have an upper bound
check on the version number.References: #13185
-
[mssql] [bug] [reflection] Fixed regression from version 2.0.42 caused by #12654 where the
updated column reflection query would receive SQL Server "type alias" names
for special types such assysname, whereas previously the base name
would be received (e.g.nvarcharforsysname), leading to warnings
that such types could not be reflected and resulting inNullType,
rather than the expectedNVARCHARfor a type likesysname.
The column reflection query now joinssys.typesa second time to look
up the base type when the user type name is not present in
MSDialect.ischema_names, and both names are checked in
MSDialect.ischema_namesfor a match. Pull request courtesy Carlos
Serrano.
oracle
-
[oracle] [bug] Fixed issue in Oracle dialect where the
_oracle.RAWdatatype would
not reflect the length parameter. Pull request courtesy Daniel Sullivan.References: #13150
2.0.48
2.0.48
Released: March 2, 2026
engine
-
[engine] [bug] Fixed a critical issue in
Enginewhere connections created in
conjunction with theDialectEvents.do_connect()event listeners
would receive shared, mutable collections for the connection arguments,
leading to a variety of potential issues including unlimited growth of the
argument list as well as elements within the parameter dictionary being
shared among concurrent connection calls. In particular this could impact
do_connect routines making use of complex mutable authentication
structures.References: #13144
2.0.47
2.0.47
Released: February 24, 2026
orm
-
[orm] [bug] Fixed issue when using ORM mappings with Python 3.14's PEP 649 feature
that no longer requires "future annotations", where the ORM's introspection
of the__init__method of mapped classes would fail if non-present
identifiers in annotations were present. The vendoredgetfullargspec()
method has been amended to useFormat.FORWARDREFunder Python 3.14 to
prevent resolution of names that aren't present.References: #13104
engine
-
[engine] [usecase] The connection object returned by
_engine.Engine.raw_connection()
now supports the context manager protocol, automatically returning the
connection to the pool when exiting the context.References: #13116
postgresql
-
[postgresql] [bug] Fixed an issue in the PostgreSQL dialect where foreign key constraint
reflection would incorrectly swap or fail to captureonupdateand
ondeletevalues when these clauses appeared in a different order than
expected in the constraint definition. This issue primarily affected
PostgreSQL-compatible databases such as CockroachDB, which may returnON DELETEbeforeON UPDATEin the constraint definition string. The
reflection logic now correctly parses both clauses regardless of their
ordering.References: #13105
-
[postgresql] [bug] Fixed issue in the
engine_insertmanyvaluesfeature where using
PostgreSQL'sON CONFLICTclause with
_dml.Insert.returning.sort_by_parameter_orderenabled would
generate invalid SQL when the insert used an implicit sentinel (server-side
autoincrement primary key). The generated SQL would incorrectly declare a
sentinel counter column in theimp_sentable alias without providing
corresponding values in theVALUESclause, leading to a
ProgrammingErrorindicating column count mismatch. The fix allows batch
execution mode whenembed_values_counteris active, as the embedded
counter provides the ordering capability needed even with upsert behaviors,
rather than unnecessarily downgrading to row-at-a-time execution.References: #13107
-
[postgresql] [bug] Fixed issue where
_postgresql.Insert.on_conflict_do_update()
parameters were not respecting compilation options such as
literal_binds=True. Pull request courtesy LoΓ―c Simon.References: #13110
-
[postgresql] [bug] Fixed issue where
_postgresql.Insert.on_conflict_do_update()
using parametrized bound parameters in theset_clause would fail
when used with executemany batching. For dialects that use the
use_insertmanyvalues_wo_returningoptimization (psycopg2),
insertmanyvalues is now disabled when there is an ON CONFLICT clause.
For cases with RETURNING, row-at-a-time mode is used when the SET
clause contains parametrized bindparams (bindparams that receive
values from the parameters dict), ensuring each row's parameters are
correctly applied. ON CONFLICT statements using expressions like
excluded.<column>continue to batch normally.References: #13130
mysql
-
[mysql] [bug] Fixed issue where DDL compilation options were registered to the hard-coded
dialect namemysql. This made it awkward for MySQL-derived dialects
like MariaDB, StarRocks, etc. to work with such options when different sets
of options exist for different platforms. Options are now registered under
the actual dialect name, and a fallback was added to help avoid errors when
an option does not exist for that dialect.To maintain backwards compatibility, when using the MariaDB dialect with
the optionsmysql_with_parserormysql_usingwithout also specifying
the correspondingmariadb_prefixed options, a deprecation warning will
be emitted. Themysql_prefixed options will continue to work during
the deprecation period. Users should update their code to additionally
specifymariadb_with_parserandmariadb_usingwhen using the
mariadb://dialect, or specify both options to support both dialects.Pull request courtesy Tiansu Yu.
References: #13134
sqlite
-
[sqlite] [bug] Fixed issue where
_sqlite.Insert.on_conflict_do_update()
parameters were not respecting compilation options such as
literal_binds=True. Pull request courtesy LoΓ―c Simon.References: #13110
-
[sqlite] [bug] Fixed issue where
_sqlite.Insert.on_conflict_do_update()
using parametrized bound parameters in theset_clause would fail
when used with executemany batching. Row-at-a-time mode is now used
for ON CONFLICT statements with RETURNING that contain parametrized
bindparams, ensuring each row's parameters are correctly applied. ON
CONFLICT statements using expressions likeexcluded.<column>
continue to batch normally.References: #13130
2.0.46
2.0.46
Released: January 21, 2026
typing
-
[typing] [bug] Fixed typing issues where ORM mapped classes and aliased entities could not
be used as keys in result row mappings or as join targets in select
statements. Patterns such asrow._mapping[User],
row._mapping[aliased(User)],row._mapping[with_polymorphic(...)]
(rejected by both mypy and Pylance), and.join(aliased(User))
(rejected by Pylance) are documented and fully supported at runtime but
were previously rejected by type checkers. The type definitions for
_KeyTypeand_FromClauseArgumenthave been updated to
accept these ORM entity types.References: #13075
postgresql
-
[postgresql] [bug] Fixed issue where PostgreSQL JSONB operators
_postgresql.JSONB.Comparator.path_match()and
_postgresql.JSONB.Comparator.path_exists()were applying incorrect
VARCHARcasts to the right-hand side operand when used with newer
PostgreSQL drivers such as psycopg. The operators now indicate the
right-hand type asJSONPATH, which currently results in no casting
taking place, but is also compatible with explicit casts if the
implementation were require it at a later point.References: #13059
-
[postgresql] [bug] Fixed regression in PostgreSQL dialect where JSONB subscription syntax
would generate incorrect SQL forcast()expressions returning JSONB,
causing syntax errors. The dialect now properly wraps cast expressions in
parentheses when using the[]subscription syntax, generating
(CAST(...))[index]instead ofCAST(...)[index]to comply with
PostgreSQL syntax requirements. This extends the fix from #12778
which addressed the same issue for function calls.References: #13067
-
[postgresql] [bug] Improved the foreign key reflection regular expression pattern used by the
PostgreSQL dialect to be more permissive in matching identifier characters,
allowing it to correctly handle unicode characters in table and column
names. This change improves compatibility with PostgreSQL variants such as
CockroachDB that may use different quoting patterns in combination with
unicode characters in their identifiers. Pull request courtesy Gord
Thompson.
mariadb
-
[mariadb] [bug] Fixed the SQL compilation for the mariadb sequence "NOCYCLE" keyword that
is to be emitted when theSequence.cycleparameter is set to
False on aSequence. Pull request courtesy Diego Dupin.References: #13070
sqlite
-
[sqlite] [bug] Fixed issue in the aiosqlite driver where SQLAlchemy's setting of
aiosqlite's worker thread to "daemon" stopped working because the aiosqlite
architecture moved the location of the worker thread in version 0.22.0.
This "daemon" flag is necessary so that a program is able to exit if the
SQLite connection itself was not explicitly closed, which is particularly
likely with SQLAlchemy as it maintains SQLite connections in a connection
pool. While it's perfectly fine to callAsyncEngine.dispose()
before program exit, this is not historically or technically necessary for
any driver of any known backend, since a primary feature of relational
databases is durability. The change also implements support for
"terminate" with aiosqlite when using version version 0.22.1 or greater,
which implements a sync.stop()method.References: #13039
mssql
-
[mssql] [usecase] Added support for the
IF EXISTSclause when dropping indexes on SQL
Server 2016 (13.x) and later versions. TheDropIndex.if_exists
parameter is now honored by the SQL Server dialect, allowing conditional
index drops that will not raise an error if the index does not exist.
Pull request courtesy Edgar RamΓrez MondragΓ³n.References: #13045
2.1.0b1
2.1.0b1
Released: January 21, 2026
platform
-
[platform] [feature] Free-threaded Python versions are now supported in wheels released on Pypi.
This integrates with overall free-threaded support added as part of
#12881 for the 2.0 and 2.1 series, which includes new test suites
as well as a few improvements to race conditions observed under
freethreading.References: #12881
-
[platform] [change] The
greenletdependency used for asyncio support no longer installs
by default. This dependency does not publish wheel files for every architecture
and is not needed for applications that aren't using asyncio features.
Use thesqlalchemy[asyncio]install target to include this dependency.References: #10197
-
[platform] [change] Updated the setup manifest definition to use PEP 621-compliant
pyproject.toml. Also updated the extra install dependency to comply with
PEP-685. Thanks for the help of Matt Oberle and KOLANICH on this change. -
[platform] [change] Python 3.10 or above is now required; support for Python 3.9, 3.8 and 3.7
is dropped as these versions are EOL.
orm
-
[orm] [feature] The
_orm.relationship.back_populatesargument to
_orm.relationship()may now be passed as a Python callable, which
resolves to either the direct linked ORM attribute, or a string value as
before. ORM attributes are also accepted directly by
_orm.relationship.back_populates. This change allows type
checkers and IDEs to confirm the argument for
_orm.relationship.back_populatesis valid. Thanks to Priyanshu
Parikh for the help on suggesting and helping to implement this feature.References: #10050
-
[orm] [feature] Added new hybrid method
hybrid_property.bulk_dml()which
works in a similar way ashybrid_property.update_expression()for
bulk ORM operations. A user-defined class method can now populate a bulk
insert mapping dictionary using the desired hybrid mechanics. New
documentation is added showing how both of these methods can be used
including in combination with the new_sql.from_dml_column()
construct.References: #12496
-
[orm] [feature] Added new parameter
_orm.composite.return_none_onto
_orm.composite(), which allows control over if and when this
composite attribute should resolve toNonewhen queried or retrieved
from the object directly. By default, a composite object is always present
on the attribute, including for a pending object which is a behavioral
change since 2.0. When_orm.composite.return_none_onis
specified, a callable is passed that returns True or False to indicate if
the given arguments indicate the composite should be returned as None. This
parameter may also be set automatically when ORM Annotated Declarative is
used; if the annotation is given asMapped[SomeClass|None], a
_orm.composite.return_none_onrule is applied that will return
Noneif all contained columns are themselvesNone.References: #12570
-
[orm] [feature] Added support for per-session execution options that are merged into all
queries executed within that session. The_orm.Session,
_orm.sessionmaker,_orm.scoped_session,
_ext.asyncio.AsyncSession, and
_ext.asyncio.async_sessionmakerconstructors now accept an
_orm.Session.execution_optionsparameter that will be applied
to all explicit query executions (e.g. using_orm.Session.execute(),
_orm.Session.get(),_orm.Session.scalars()) for that session
instance.References: #12659
-
[orm] [feature] Session autoflush behavior has been simplified to unconditionally flush the
session each time an execution takes place, regardless of whether an ORM
statement or Core statement is being executed. This change eliminates the
previous conditional logic that only flushed when ORM-related statements
were detected, which had become difficult to define clearly with the unified
v2 syntax that allows both Core and ORM execution patterns. The change
provides more consistent and predictable session behavior across all types
of SQL execution.References: #9809
-
[orm] [feature] Added
_orm.RegistryEventsevent class that allows event listeners
to be established on a_orm.registryobject. The new class
provides three events:_orm.RegistryEvents.resolve_type_annotation()
which allows customization of type annotation resolution that can
supplement or replace the use of the
registry.type_annotation_mapdictionary, including that it can
be helpful with custom resolution for complex types such as those of
PEP 695, as well as_orm.RegistryEvents.before_configured()and
_orm.RegistryEvents.after_configured(), which are registry-local
forms of the mapper-wide version of these hooks.References: #9832
-
[orm] [usecase] The
_orm.Session.flush.objectsparameter is now
deprecated.References: #10816
-
[orm] [usecase] Added the utility method
_orm.Session.merge_all()and
_orm.Session.delete_all()that operate on a collection
of instances.References: #11776
-
[orm] [usecase] Added support for using
_orm.with_expression()to populate a
_orm.query_expression()attribute that is also configured as the
polymorphic_ondiscriminator column. The ORM now detects when a query
expression column is serving as the polymorphic discriminator and updates
it to use the column provided via_orm.with_expression(), enabling
polymorphic loading to work correctly in this scenario. This allows for
patterns such as where the discriminator value is computed from a related
table.References: #12631
-
[orm] [usecase] Added default implementations of
ColumnOperators.desc(),
ColumnOperators.asc(),ColumnOperators.nulls_first(),
ColumnOperators.nulls_last()to_orm.composite()attributes,
by default applying the modifier to all contained columns. Can be
overridden using a custom comparator.References: #12769
-
[orm] [usecase] The
_orm.aliased()object now emits warnings when an attribute is
accessed on an aliased class that cannot be located in the target
selectable, for those cases where the_orm.aliased()is against a
different FROM clause than the regular mapped table (such as a subquery).
This helps users identify cases where column names don't match between the
aliased class and the underlying selectable. When
_orm.aliased.adapt_on_namesisTrue, the warning suggests
checking the column name; whenFalse, it suggests using the
adapt_on_namesparameter for name-based matching.References: #12838
-
[orm] [usecase] Improvements to the use case of using
Declarative Dataclass Mapping <orm_declarative_native_dataclasses>with intermediary classes that are
unmapped. As was the existing behavior, classes can subclass
_orm.MappedAsDataclassalone without a declarative base to act as
mixins, or along with a declarative base as well as__abstract__ = True
to define an abstract base. However, the improved behavior scans ORM
attributes like_orm.mapped_column()in this case to create correct
dataclasses.field()constructs based on their arguments, allowing for
more natural ordering of fields without dataclass errors being thrown.
Additionally, added a new_orm.unmapped_dataclass()decorator
function, which may be used to create unmapped mixins in a mapped hierarchy
that is using the_orm.mapped_dataclass()decorator to create mapped
dataclasses.References: #12854
-
[orm] [usecase] Added
_orm.DictBundleas a subclass of_orm.Bundle
that returnsdictobjects.References: #12960
-
[orm] [change] A sweep through class and function names in the ORM renames many classes
and functions that have no intent of public visibility to be underscored.
This is to reduce ambiguity as to which APIs are intended to be targeted by
third party applications and extensions. Third parties are encouraged to
propose new public APIs in Discussions to the extent they are needed to
replace those that have been clarified as private.References: #10497
-
[orm] [change] The
first_initORM event has been removed. This event was
non-functional throughout the 1.4 and 2.0 series and could not be invoked
without raising an internal error, so it is not expected that there is any
real-world use of this event hook.References: #10500
-
[orm] [change] Removed legacy signatures dating back to 0.9 release fro...
2.0.45
2.0.45
Released: December 9, 2025
orm
-
[orm] [bug] Fixed issue where calling
Mapper.add_property()within mapper event
hooks such asMapperEvents.instrument_class(),
MapperEvents.after_mapper_constructed(), or
MapperEvents.before_mapper_configured()would raise an
AttributeErrorbecause the mapper's internal property collections were
not yet initialized. TheMapper.add_property()method now handles
early-stage property additions correctly, allowing properties including
column properties, deferred columns, and relationships to be added during
mapper initialization events. Pull request courtesy G Allajmi.References: #12858
-
[orm] [bug] Fixed issue in Python 3.14 where dataclass transformation would fail when
a mapped class usingMappedAsDataclassincluded a
relationship()referencing a class that was not available at
runtime (e.g., within aTYPE_CHECKINGblock). This occurred when using
Python 3.14's PEP 649 deferred annotations feature, which is the
default behavior without afrom __future__ import annotations
directive.References: #12952
examples
- [examples] [bug] Fixed the "short_selects" performance example where the cache was being
used in all the examples, making it impossible to compare performance with
and without the cache. Less important comparisons like "lambdas" and
"baked queries" have been removed.
sql
-
[sql] [bug] Some improvements to the
_sql.ClauseElement.params()method to
replace bound parameters in a query were made, however the ultimate issue
in #12915 involving ORM_orm.aliased()cannot be fixed fully
until 2.1, where the method is being rewritten to work without relying on
Core cloned traversal.References: #12915
-
[sql] [bug] Fixed issue where using the
ColumnOperators.in_()operator with a
nestedCompoundSelectstatement (e.g. anINTERSECTof
UNIONqueries) would raise aNotImplementedErrorwhen the
nested compound select was the first argument to the outer compound select.
The_scalar_type()internal method now properly handles nested compound
selects.References: #12987
typing
-
[typing] [bug] Fixed typing issue where
Select.with_for_update()would not support
lists of ORM entities or other FROM clauses in the
Select.with_for_update.ofparameter. Pull request courtesy
Shamil.References: #12730
-
[typing] [bug] Fixed typing issue where
coalescewould not return the correct
return type when a nullable form of that argument were passed, even though
this function is meant to select the non-null entry among possibly null
arguments. Pull request courtesy Yannick PΓROUX.
postgresql
-
[postgresql] [usecase] Added support for reflection of collation in types for PostgreSQL.
Thecollationwill be set only if different from the default
one for the type.
Pull request courtesy Denis Laxalde.References: #6511
-
[postgresql] [bug] Fixed issue where PostgreSQL dialect options such as
postgresql_include
onPrimaryKeyConstraintandUniqueConstraintwere
rendered in the wrong position when combined with constraint deferrability
options likedeferrable=True. Pull request courtesy G Allajmi.References: #12867
-
[postgresql] [bug] Fixed the structure of the SQL string used for the
engine_insertmanyvaluesfeature when an explicit sequence with
nextval()is used. The SQL function invocation for the sequence has
been moved from being rendered inline within each tuple inside of VALUES to
being rendered once in the SELECT that reads from VALUES. This change
ensures the function is invoked in the correct order as rows are processed,
rather than assuming PostgreSQL will execute inline function calls within
VALUES in a particular order. While current PostgreSQL versions appear to
handle the previous approach correctly, the database does not guarantee
this behavior for future versions.References: #13015
mysql
-
[mysql] [usecase] Added support for MySQL 8.0.1 +
FOR SHAREto be emitted for the
Select.with_for_update()method, which offers compatibility with
NOWAITandSKIP LOCKED. The new syntax is used only for MySQL when
version 8.0.1 or higher is detected. Pull request courtesy JetDrag.References: #12964
sqlite
-
[sqlite] [bug] [reflection] A series of improvements have been made for reflection of CHECK constraints
on SQLite. The reflection logic now correctly handles table names
containing the strings "CHECK" or "CONSTRAINT", properly supports all four
SQLite identifier quoting styles (double quotes, single quotes, brackets,
and backticks) for constraint names, and accurately parses CHECK constraint
expressions containing parentheses within string literals using balanced
parenthesis matching with string context tracking. Big thanks to
GruzdevAV for new test cases and implementation ideas.References: #12924
-
[sqlite] [bug] Fixed issue where SQLite dialect would fail to reflect constraint names
that contained uppercase letters or other characters requiring quoting. The
regular expressions used to parse primary key, foreign key, and unique
constraint names from theCREATE TABLEstatement have been updated to
properly handle both quoted and unquoted constraint names.References: #12954
tests
- [tests] [change] A noxfile.py has been added to allow testing with nox. This is a direct
port of 2.1's move to nox, however leaves the tox.ini file in place and
retains all test documentation in terms of tox. Version 2.1 will move to
nox fully, including deprecation warnings for tox and new testing
documentation.
2.0.44
2.0.44
Released: October 10, 2025
platform
- [platform] [bug] Unblocked automatic greenlet installation for Python 3.14 now that
there are greenlet wheels on pypi for python 3.14.
orm
-
[orm] [usecase] The way ORM Annotated Declarative interprets Python PEP 695 type aliases
inMapped[]annotations has been refined to expand the lookup scheme. A
PEP 695 type can now be resolved based on either its direct presence in
_orm.registry.type_annotation_mapor its immediate resolved
value, as long as a recursive lookup across multiple PEP 695 types is
not required for it to resolve. This change reverses part of the
restrictions introduced in 2.0.37 as part of #11955, which
deprecated (and disallowed in 2.1) the ability to resolve any PEP 695
type that was not explicitly present in
_orm.registry.type_annotation_map. Recursive lookups of
PEP 695 types remains deprecated in 2.0 and disallowed in version 2.1,
as do implicit lookups ofNewTypetypes without an entry in
_orm.registry.type_annotation_map.Additionally, new support has been added for generic PEP 695 aliases that
refer to PEP 593Annotatedconstructs containing
_orm.mapped_column()configurations. See the sections below for
examples.References: #12829
-
[orm] [bug] Fixed a caching issue where
_orm.with_loader_criteria()would
incorrectly reuse cached bound parameter values when used with
_sql.CompoundSelectconstructs such as_sql.union(). The
issue was caused by the cache key for compound selects not including the
execution options that are part of the_sql.Executablebase class,
which_orm.with_loader_criteria()uses to apply its criteria
dynamically. The fix ensures that compound selects and other executable
constructs properly include execution options in their cache key traversal.References: #12905
engine
-
[engine] [bug] Implemented initial support for free-threaded Python by adding new tests
and reworking the test harness to include Python 3.13t and Python 3.14t in
test runs. Two concurrency issues have been identified and fixed: the first
involves initialization of the.ccollection on aFromClause, a
continuation of #12302, where an optional mutex under
free-threading is added; the second involves synchronization of the pool
"first_connect" event, which first received thread synchronization in
#2964, however under free-threading the creation of the mutex
itself runs under the same free-threading mutex. Support for free-threaded
wheels on Pypi is implemented as well within the 2.1 series only. Initial
pull request and test suite courtesy Lysandros Nikolaou.References: #12881
sql
-
[sql] [bug] Improved the implementation of
UpdateBase.returning()to use more
robust logic in setting up the.ccollection of a derived statement
such as a CTE. This fixes issues related to RETURNING clauses that feature
expressions based on returned columns with or without qualifying labels.References: #12271
schema
-
[schema] [bug] Fixed issue where
_schema.MetaData.reflect()did not forward
dialect-specific keyword arguments to the_engine.Inspector
methods, causing options likeoracle_resolve_synonymsto be ignored
during reflection. The method now ensures that all extra kwargs passed to
_schema.MetaData.reflect()are forwarded to
_engine.Inspector.get_table_names()and related reflection methods.
Pull request courtesy LukΓ‘Ε‘ KoΕΎuΕ‘nΓk.References: #12884
typing
-
[typing] [bug] Fixed typing bug where the
Session.execute()method advertised that
it would return aCursorResultif given an insert/update/delete
statement. This is not the general case as several flavors of ORM
insert/update do not actually yield aCursorResultwhich cannot
be differentiated at the typing overload level, so the method now yields
Resultin all cases. For those cases where
CursorResultis known to be returned and the.rowcount
attribute is required, please usetyping.cast().References: #12813
-
[typing] [bug] Added new decorator
_orm.mapped_as_dataclass(), which is a function
based form of_orm.registry.mapped_as_dataclass(); the method form
_orm.registry.mapped_as_dataclass()does not seem to be correctly
recognized within the scope of PEP 681 in recent mypy versions.References: #12855
asyncio
-
[asyncio] [usecase] Generalize the terminate logic employed by the asyncpg dialect to reuse
it in the aiomysql and asyncmy dialect implementation.References: #12273
postgresql
-
[postgresql] [bug] Fixed issue where selecting an enum array column containing NULL values
would fail to parse properly in the PostgreSQL dialect. The
_split_enum_values()function now correctly handles NULL entries by
converting them to PythonNonevalues.References: #12847
-
[postgresql] [bug] Fixed issue where the
_sql.any_()and_sql.all_()aggregation
operators would not correctly coerce the datatype of the compared value, in
those cases where the compared value were not a simple int/str etc., such
as a PythonEnumor other custom value. This would lead to execution
time errors for these values. This issue is essentially the same as
#6515 which was for the now-legacyARRAY.any()and
ARRAY.all()methods.References: #12874
sqlite
-
[sqlite] [bug] Fixed issue where SQLite table reflection would fail for tables using
WITHOUT ROWIDand/orSTRICTtable options when the table contained
generated columns. The regular expression used to parseCREATE TABLE
statements for generated column detection has been updated to properly
handle these SQLite table options that appear after the column definitions.
Pull request courtesy Tip ten Brink.References: #12864
mssql
-
[mssql] [bug] Improved the base implementation of the asyncio cursor such that it
includes the option for the underlying driver's cursor to be actively
closed in those cases where it requiresawaitin order to complete the
close sequence, rather than relying on garbage collection to "close" it,
when a plainResultis returned that does not useawaitfor
any of its methods. The previous approach of relying on gc was fine for
MySQL and SQLite dialects but has caused problems with the aioodbc
implementation on top of SQL Server. The new option is enabled
for those dialects which have an "awaitable"cursor.close(), which
includes the aioodbc, aiomysql, and asyncmy dialects (aiosqlite is also
modified for 2.1 only).References: #12798
-
[mssql] [bug] Fixed issue where the index reflection for SQL Server would
not correctly return the order of the column inside an index
when the order of the columns in the index did not match the
order of the columns in the table.
Pull request courtesy of Allen Chen.References: #12894
-
[mssql] [bug] [reflection] Fixed issue in the MSSQL dialect's foreign key reflection query where
duplicate rows could be returned when a foreign key column and its
referenced primary key column have the same name, and both the referencing
and referenced tables have indexes with the same name. This resulted in an
"ForeignKeyConstraint with duplicate source column references are not
supported" error when attempting to reflect such tables. The query has been
corrected to exclude indexes on the child table when looking for unique
indexes referenced by foreign keys.References: #12907
misc
-
[bug] [ext] Fixed issue caused by an unwanted functional change while typing
theMutableListclass.
This change also reverts all other functional changes done in
the same change.References: #12802