Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Releases: sqlalchemy/sqlalchemy

2.1.0b3

2.1.0b3 Pre-release
Pre-release

Choose a tag to compare

@sqla-tester sqla-tester released this 27 Jun 18:52

2.1.0b3

Released: June 27, 2026

orm

  • [orm] [feature] Added selectinload.chunksize parameter to selectinload()
    allowing users to configure the number of primary keys sent per IN clause
    when loading relationships. Pull request courtesy bekapono.

    References: #11450

  • [orm] [usecase] The populate_existing execution option is now honored when passed in the
    Session.get.execution_options dict by the method
    Session.get() and analogous in other session kinds. The current
    Session.get.populate_existing parameter will takes precedence if
    specified, overriding the value of the execution options.

    References: #10610

  • [orm] [usecase] Updated the attribute _orm.ORMExecuteState.user_defined_options to
    include options that were added to the statement before calling
    Select.with_only_columns() or _orm.Query.with_entities().

    References: #13309

  • [orm] [usecase] [performance] Optimized _orm.selectinload() to skip the .unique() call on inner
    result sets when no nested _orm.joinedload() on a collection is
    present. The uniquing pass is only required when a joined eager load
    inflates rows due to a one-to-many or many-to-many JOIN; in the common case
    of a leaf selectin load, rows are already unique by construction and the
    per-row hashing overhead can be avoided. As a side effect, yield_per
    set in a do_orm_execute event for a _orm.selectinload()
    relationship load no longer raises InvalidRequestError when no nested
    collection joinedload is in effect, since .unique() is no longer called
    in that path. Pull request courtesy Oliver Parker.

    References: #13339

  • [orm] [usecase] Session level _orm.Session.execution_options now take
    effect for Core level SQL emitted by unit of work operations, in
    addition to their existing use within ORM statement executions.
    This is to provide for Core options such as
    _engine.Connection.execution_options.schema_translate_map
    to be applicable to a Session overall.

    References: #13346

  • [orm] [performance] ORM result row fetching now processes rows as plain tuples rather than
    constructing Row objects, as ORM loaders use position-based
    access and do not require the Row interface. Row
    construction is still used when engine-level debug logging is enabled so
    that individual rows can be logged. Benchmarks show a 3-16% improvement in
    ORM entity load times depending on query shape. Pull request courtesy
    Oliver Parker.

    References: #13363

  • [orm] [performance] Improved performance of _orm.selectinload() and
    _orm.subqueryload() result handling:

    -   in selectinloader, the primary key columns used to correlate related
        rows are now selected directly rather than being wrapped in a
        `Bundle`, and are read from positional slices of each result
        row.  This removes the per-row `Row` construction that the
        `Bundle` introduced, including for the common single-column
        primary key case.
    
    -   removed use of `groupby()` + `lambda` against `Row` objects
        in subqueryloader; rows are converted to plain tuples and the result
        lists are built via `append()`.
    
    -   many-to-one selectinload reads foreign key values directly from the
        parent instance dictionary when present, falling back to attribute-level
        access only for expired or deferred attributes.
    

    Pull request courtesy Oliver Parker.

    References: #13363

  • [orm] [performance] The selectinload() loader strategy now selects the omit_join
    optimization for many-to-many non-self-referential relationships, reducing
    the number of joins in the secondary SELECT by selecting from the secondary
    table directly rather than joining back to the parent entity. omit_join
    is enabled automatically when the join condition determines that the
    secondary table's foreign keys fully cover the parent's primary key. As
    always, omit_join can be disabled by setting
    relationship.omit_join to False. Pull request courtesy
    bekapono.

    References: #5987

  • [orm] [bug] Fixed issue where the declarative class registry would not consider
    class-level MetaData objects set on abstract mixin classes when
    resolving string-based table references in relationship()
    configurations. The registry now uses the same metadata resolution logic
    as table creation, first checking for a class-specific metadata
    attribute before falling back to registry.metadata.

    References: #13291

  • [orm] [bug] Fixed issue where the _engine.Result.unique() filter was not properly
    validated against the _engine.Result.yield_per() method when both
    were called as methods on the result object, such as
    result.unique().yield_per(N) or result.yield_per(N).unique(). The
    uniquing filter was previously only checked when yield_per was set via
    _engine.Connection.execution_options.yield_per. Since these two
    features are fundamentally incompatible for ORM results, an
    InvalidRequestError is now raised in all cases.

    References: #13293

  • [orm] [bug] A warning is now emitted when a Declarative attribute name is named
    metadata or registry. Previously, no warning was emitted for
    registry, and using the name metadata would raise an
    InvalidRequestError. Since these names can be used for attributes
    that are mapped as backrefs or using imperative mappings, usage
    under Declarative has been relaxed for metadata but also warns
    for both names as they may have unintended interactions with the
    Declarative reserved names.

    References: #13333

  • [orm] [bug] Fixed issue where the declarative class resolver would not consider
    the MetaData.schema default schema when resolving a
    string table name for the relationship.secondary parameter
    as well as within string-based
    relationship.primaryjoin and
    relationship.secondaryjoin expressions. The resolution now
    matches the behavior of ForeignKey, where an unqualified
    table name is implicitly resolved under the default schema. A
    deprecation warning is emitted when an unqualified name resolves to a
    :data:.BLANK_SCHEMA table in a MetaData that has a default
    schema set, as this implicit resolution will change in a future version.

    Unknown interpreted text role "data".

    References: #8068

engine

  • [engine] [bug] Expanded try/except error handling to encompass the
    _events.ConnectionEvents.before_cursor_execute() and
    _events.ConnectionEvents.after_cursor_execute() event hooks, so that
    exceptions raised within these hooks, including BaseException
    subclasses such as asyncio.CancelledError, are properly handled via the
    error handling path used for DBAPI errors. This ensures proper connection
    invalidation and pool notification when exit-type exceptions are raised in
    event hooks. As part of this change, DBAPI errors raised from within these
    event hooks will now be wrapped as SQLAlchemy exceptions.

    References: #13381

  • [engine] [reflection] Removed the legacy include_columns key from the dictionary returned
    by the index reflection methods of some dialects.
    This information is now part of the dialect_options dictionary under the key
    {dialect_name}_include, such as postgresql_include or mssql_include.

    References: #13350

sql

  • [sql] [usecase] Added _sql.Delete.using(), allowing explicit FROM expressions such as
    joins to be rendered in backend-specific multiple-table DELETE forms
    including MySQL/MariaDB DELETE .. USING. Pull request courtesy
    cjc0013.

    References: #8130

  • [sql] [bug] Fixed issue where negation of comparison expressions involving
    func.any(), func.all(), and func.some() SQL functions would
    incorrectly flip the comparison operator (e.g. = to !=) rather
    than wrapping the expression with NOT. These functions are now
    registered as collection aggregate functions that prevent operator
    flipping on negation, consistent with the behavior of the standalone
    _expression.any_() and _expression.all_() constructs.

    References: #13343

postgresql

  • [postgresql] [usecase] Changed the default backslash escape value in the PostgreSQL dialect to
    False to align it with the default value of
    standard_conforming_strings=on. This change should not affect most users
    since the value is set at driver initialization on first connect.

    References: #13268

mysql

  • [mysql] [bug] Improved the regular expression used to parse index COMMENT clauses
    in MySQL SHOW CREATE TABLE reflection to use an unambiguous
    single-quoted-string pattern; the previous pattern was theoretically
    subject to backtracking on malformed input, though such input ...
Read more

2.0.51

Choose a tag to compare

@sqla-tester sqla-tester released this 15 Jun 15:41

2.0.51

Released: June 15, 2026

orm

  • [orm] [bug] Fixed issue where _orm.subqueryload() combined with
    PropComparator.of_type() and PropComparator.and_() would
    silently drop the additional filter criteria, causing all related objects
    to be loaded instead of only those matching the filter. The
    LoaderCriteriaOption was 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
    IllegalStateChangeError instead 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 original CursorResult, causing
    key-based access on the thawed result to silently return a value instead of
    raising InvalidRequestError. The
    SimpleResultMetaData now 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.StatementLambdaElement would 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 the xid()
    method of the psycopg connection.

    References: #13355

  • [postgresql] [bug] Fixed regular expression in the pure Python hstore result processor,
    used when use_native_hstore=False is set, which could hang on
    malformed hstore text containing unterminated quoted segments with
    backslashes. Pull request courtesy dxbjavid.

    References: #13370

2.0.50

Choose a tag to compare

@sqla-tester sqla-tester released this 24 May 19:20

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
    with PropComparator.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 as yield_per and
    loader-specific state from the first orm_pre_session_exec pass to leak
    into the second pass, leading to errors when using relationship loaders
    such as selectinload() and immediateload(). 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 an AttributeError when used in an ORM statement, due to
    _orm.configure_mappers() not being triggered implicitly. The fix
    ensures that AliasedInsp participates in the _post_inspect
    hook, triggering mapper configuration during ORM statement compilation.

    References: #13319

sql

  • [sql] [bug] Fixed issue where floor division (//) between a Float or
    Numeric numerator and an Integer denominator would omit
    the FLOOR() SQL wrapper on dialects where
    Dialect.div_is_floordiv is True (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_col render as FLOOR(float_col / int_col) instead
    of the incorrect float_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
    exception InternalClientError under some circumstances, leading to
    connections not being properly marked as invalidated.

    References: #13241

  • [postgresql] [bug] Fixed issue where the ExcludeConstraint construct did not
    correctly forward the ExcludeConstraint.info parameter 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 with lower_case_table_names=2 (where bug 96365 applies,
    typically macOS). Previously the workaround was applied unconditionally
    for all MySQL 8.0+ versions, which caused a KeyError during 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's ping() 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 Pre-release
Pre-release

Choose a tag to compare

@sqla-tester sqla-tester released this 16 Apr 20:16

2.1.0b2

Released: April 16, 2026

orm

  • [orm] [usecase] The metadata, type_annotation_map, or registry can 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 uses getattr() to look for these
    attributes, instead of relying only on the class __dict__.

    References: #13198

sql

  • [sql] [usecase] Added new parameter _sql.over.exclude to _sql.over() and
    related methods, enabling SQL standard frame exclusion clauses EXCLUDE CURRENT ROW, EXCLUDE GROUP, EXCLUDE TIES, EXCLUDE NO OTHERS
    in window functions. Pull request courtesy of Varun Chawla.

    References: #11671

  • [sql] [usecase] The ColumnCollection class hierarchy has been refactored to allow
    column names such as add, remove, update, extend, and
    clear to be used without conflicts. ColumnCollection is now
    an abstract base class, with mutation operations moved to
    WriteableColumnCollection and DedupeColumnCollection
    subclasses. The ReadOnlyColumnCollection exposed as attributes
    such as Table.c no 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 TypeDecorator to produce a correct
    repr() for "schema" types such as Enum and Boolean.
    This is mostly to support the Alembic autogenerate use case so that custom
    types render with relevant arguments present. Improved the architecture
    used by TypeEngine to produce repr() strings to be more
    modular for compound types like TypeDecorator.

    References: #13140

schema

  • [schema] [usecase] Most _sql.FromClause subclasses are now generic on
    _schema.TypedColumns subclasses, that can be used to type their
    _sql.FromClause.c collection.
    This applied to _schema.Table, _sql.Join,
    _sql.Subquery, _sql.CTE and more.

    References: #13085

  • [schema] [bug] Amended the repr() output for Enum so that the
    MetaData is not shown in the output, as this interferes with
    Alembic-autogenerated forms of this type which should be inheriting the
    MetaData of 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 as Any. Pull request
    courtesy Yurii Karabas.

    References: #13091

  • [typing] [bug] Improved typing of _sqltypes.JSON as well as dialect specific
    variants like _postgresql.JSON to 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-python driver, Microsoft's official Python
    driver for SQL Server.

    References: #12869

oracle

  • [oracle] [feature] Added support for the _sqltypes.JSON datatype 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

Choose a tag to compare

@sqla-tester sqla-tester released this 03 Apr 16:38

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 when with_for_update=False was passed,
    rather than treating it equivalently to the default of None.
    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 as joinedload(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:.func would 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 Graham

    References: #10902

mssql

  • [mssql] [usecase] Enhanced the aioodbc dialect to expose the fast_executemany
    attribute of the pyodbc cursor. This allows the fast_executemany
    parameter to work with the mssql+aioodbc dialect. 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 as sysname, whereas previously the base name
    would be received (e.g. nvarchar for sysname), leading to warnings
    that such types could not be reflected and resulting in NullType,
    rather than the expected NVARCHAR for a type like sysname.
    The column reflection query now joins sys.types a 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_names for a match. Pull request courtesy Carlos
    Serrano.

    References: #13181, #13182

oracle

  • [oracle] [bug] Fixed issue in Oracle dialect where the _oracle.RAW datatype would
    not reflect the length parameter. Pull request courtesy Daniel Sullivan.

    References: #13150

2.0.48

Choose a tag to compare

@sqla-tester sqla-tester released this 02 Mar 15:28

2.0.48

Released: March 2, 2026

engine

  • [engine] [bug] Fixed a critical issue in Engine where connections created in
    conjunction with the DialectEvents.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

Choose a tag to compare

@sqla-tester sqla-tester released this 24 Feb 16:34

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 vendored getfullargspec()
    method has been amended to use Format.FORWARDREF under 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 capture onupdate and
    ondelete values 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 return ON DELETE before ON UPDATE in 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_insertmanyvalues feature where using
    PostgreSQL's ON CONFLICT clause with
    _dml.Insert.returning.sort_by_parameter_order enabled 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 the imp_sen table alias without providing
    corresponding values in the VALUES clause, leading to a
    ProgrammingError indicating column count mismatch. The fix allows batch
    execution mode when embed_values_counter is 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 the set_ clause would fail
    when used with executemany batching. For dialects that use the
    use_insertmanyvalues_wo_returning optimization (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 name mysql. 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 options mysql_with_parser or mysql_using without also specifying
    the corresponding mariadb_ prefixed options, a deprecation warning will
    be emitted. The mysql_ prefixed options will continue to work during
    the deprecation period. Users should update their code to additionally
    specify mariadb_with_parser and mariadb_using when 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 the set_ 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 like excluded.<column>
    continue to batch normally.

    References: #13130

2.0.46

Choose a tag to compare

@sqla-tester sqla-tester released this 21 Jan 18:03

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 as row._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
    _KeyType and _FromClauseArgument have 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
    VARCHAR casts to the right-hand side operand when used with newer
    PostgreSQL drivers such as psycopg. The operators now indicate the
    right-hand type as JSONPATH, 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 for cast() expressions returning JSONB,
    causing syntax errors. The dialect now properly wraps cast expressions in
    parentheses when using the [] subscription syntax, generating
    (CAST(...))[index] instead of CAST(...)[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 the Sequence.cycle parameter is set to
    False on a Sequence. 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 call AsyncEngine.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 EXISTS clause when dropping indexes on SQL
    Server 2016 (13.x) and later versions. The DropIndex.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 Pre-release
Pre-release

Choose a tag to compare

@sqla-tester sqla-tester released this 21 Jan 20:56

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 greenlet dependency 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 the sqlalchemy[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.

    References: #10357, #12029, #12819

orm

  • [orm] [feature] The _orm.relationship.back_populates argument 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_populates is 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 as hybrid_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_on to
    _orm.composite(), which allows control over if and when this
    composite attribute should resolve to None when 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_on is
    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 as Mapped[SomeClass|None], a
    _orm.composite.return_none_on rule is applied that will return
    None if all contained columns are themselves None.

    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_sessionmaker constructors now accept an
    _orm.Session.execution_options parameter 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.RegistryEvents event class that allows event listeners
    to be established on a _orm.registry object. 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_map dictionary, 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.objects parameter 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_on discriminator 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_names is True, the warning suggests
    checking the column name; when False, it suggests using the
    adapt_on_names parameter 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.MappedAsDataclass alone 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.DictBundle as a subclass of _orm.Bundle
    that returns dict objects.

    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_init ORM 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...

Read more

2.0.45

Choose a tag to compare

@sqla-tester sqla-tester released this 09 Dec 21:05

2.0.45

Released: December 9, 2025

orm

  • [orm] [bug] Fixed issue where calling Mapper.add_property() within mapper event
    hooks such as MapperEvents.instrument_class(),
    MapperEvents.after_mapper_constructed(), or
    MapperEvents.before_mapper_configured() would raise an
    AttributeError because the mapper's internal property collections were
    not yet initialized. The Mapper.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 using MappedAsDataclass included a
    relationship() referencing a class that was not available at
    runtime (e.g., within a TYPE_CHECKING block). This occurred when using
    Python 3.14's PEP 649 deferred annotations feature, which is the
    default behavior without a from __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
    nested CompoundSelect statement (e.g. an INTERSECT of
    UNION queries) would raise a NotImplementedError when 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.of parameter. Pull request courtesy
    Shamil.

    References: #12730

  • [typing] [bug] Fixed typing issue where coalesce would 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.
    The collation will 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
    on PrimaryKeyConstraint and UniqueConstraint were
    rendered in the wrong position when combined with constraint deferrability
    options like deferrable=True. Pull request courtesy G Allajmi.

    References: #12867

  • [postgresql] [bug] Fixed the structure of the SQL string used for the
    engine_insertmanyvalues feature 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 SHARE to be emitted for the
    Select.with_for_update() method, which offers compatibility with
    NOWAIT and SKIP 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 the CREATE TABLE statement 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.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.