SQLAlchemy 2.1 Documentation
Changes and Migration
- What’s New in SQLAlchemy 2.1?
- 2.1 Changelog¶
- 2.0 Changelog
- 1.4 Changelog
- 1.3 Changelog
- 1.2 Changelog
- 1.1 Changelog
- 1.0 Changelog
- 0.9 Changelog
- 0.8 Changelog
- 0.7 Changelog
- 0.6 Changelog
- 0.5 Changelog
- 0.4 Changelog
- 0.3 Changelog
- 0.2 Changelog
- 0.1 Changelog
- SQLAlchemy 2.0 - Major Migration Guide
- What’s New in SQLAlchemy 2.0?
- What’s New in SQLAlchemy 1.4?
- What’s New in SQLAlchemy 1.3?
- What’s New in SQLAlchemy 1.2?
- What’s New in SQLAlchemy 1.1?
- What’s New in SQLAlchemy 1.0?
- What’s New in SQLAlchemy 0.9?
- What’s New in SQLAlchemy 0.8?
- What’s New in SQLAlchemy 0.7?
- What’s New in SQLAlchemy 0.6?
- What’s new in SQLAlchemy 0.5?
- What’s new in SQLAlchemy 0.4?
Project Versions
- Previous: What’s New in SQLAlchemy 2.1?
- Next: 2.0 Changelog
- Up: Home
- On this page:
2.1 Changelog¶
2.1.0b1¶
no release dateorm¶
The
relationship.back_populates
argument torelationship()
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 byrelationship.back_populates
. This change allows type checkers and IDEs to confirm the argument forrelationship.back_populates
is valid. Thanks to Priyanshu Parikh for the help on suggesting and helping to implement this feature.References: #10050
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
Removed legacy signatures dating back to 0.9 release from the
SessionEvents.after_bulk_update()
andSessionEvents.after_bulk_delete()
.References: #10721
The
relationship.secondary
parameter no longer uses Pythoneval()
to evaluate the given string. This parameter when passed a string should resolve to a table name that’s present in the localMetaData
collection only, and never needs to be any kind of Python expression otherwise. To use a real deferred callable based on a name that may not be locally present yet, use a lambda instead.References: #10564
Revised the set “binary” operators for the association proxy
set()
interface to correctly raiseTypeError
for invalid use of the|
,&
,^
, and-
operators, as well as the in-place mutation versions of these methods, to match the behavior of standard Pythonset()
as well as SQLAlchemy ORM’s “intstrumented” set implementation.References: #11349
Ignore
Session.join_transaction_mode
in all cases when the bind provided to theSession
is anEngine
. Previously if an event that executed before the session logic, likeConnectionEvents.engine_connect()
, left the connection with an active transaction, theSession.join_transaction_mode
behavior took place, leading to a surprising behavior.References: #11163
engine¶
Added new execution option
Connection.execution_options.driver_column_names
. This option disables the “name normalize” step that takes place against the DBAPIcursor.description
for uppercase-default backends like Oracle, and will cause the keys of a result set (e.g. named tuple names, dictionary keys inRow._mapping
, etc.) to be exactly what was delivered in cursor.description. This is mostly useful for plain textual statements usingtext()
orConnection.exec_driver_sql()
.References: #10789
An empty sequence passed to any
execute()
method now raised a deprecation warning, since such an executemany is invalid. Pull request courtesy of Carlos Sousa.References: #9647
sql¶
Fixed issue in name normalization (e.g. “uppercase” backends like Oracle) where using a
TextualSelect
would not properly maintain as uppercase column names that were quoted as uppercase, even though theTextualSelect
includes aColumn
that explicitly holds this uppercase name.References: #10788
Enhanced the caching structure of the
over.rows
andover.range
so that different numerical values for the rows / range fields are cached on the same cache key, to the extent that the underlying SQL does not actually change (i.e. “unbounded”, “current row”, negative/positive status will still change the cache key). This prevents the use of many different numerical range/rows value for a query that is otherwise identical from filling up the SQL cache.Note that the semi-private compiler method
_format_frame_clause()
is removed by this fix, replaced with a new methodvisit_frame_clause()
. Third party dialects which may have referred to this method will need to change the name and revise the approach to rendering the correct SQL for that dialect.References: #11515
schema¶
Deprecate Oracle only parameters
Sequence.order
,Identity.order
andIdentity.on_null
. They should be configured using the dialect kwargsoracle_order
andoracle_on_null
.References: #10247
typing¶
The
Row
object now no longer makes use of an intermediaryTuple
in order to represent its individual element types; instead, the individual element types are present directly, via new PEP 646 integration, now available in more recent versions of Mypy. Mypy 1.7 or greater is now required for statements, results and rows to be correctly typed. Pull request courtesy Yurii Karabas.References: #10635
asyncio¶
Adapted all asyncio dialects, including aiosqlite, aiomysql, asyncmy, psycopg, asyncpg to use the generic asyncio connection adapter first added in #6521 for the aioodbc DBAPI, allowing these dialects to take advantage of a common framework.
References: #10415
Added an initialize step to the import of
sqlalchemy.ext.asyncio
so thatgreenlet
will be imported only when the asyncio extension is first imported. Alternatively, thegreenlet
library is still imported lazily on first use to support use case that don’t make direct use of the SQLAlchemy asyncio extension.References: #10296
Removed the compatibility
async_fallback
mode for async dialects, since it’s no longer used by SQLAlchemy tests. Also removed the internal functionawait_fallback()
and renamed the internal functionawait_only()
toawait_()
. No change is expected to user code.
mariadb¶
Modified the MariaDB dialect so that when using the
Uuid
datatype with MariaDB >= 10.7, leaving theUuid.native_uuid
parameter at its default of True, the nativeUUID
datatype will be rendered in DDL and used for database communication, rather thanCHAR(32)
(the non-native UUID type) as was the case previously. This is a behavioral change since 2.0, where the genericUuid
datatype deliveredCHAR(32)
for all MySQL and MariaDB variants. Support for all major DBAPIs is implemented including support for less common “insertmanyvalues” scenarios where UUID values are generated in different ways for primary keys. Thanks much to Volodymyr Kochetkov for delivering the PR.References: #10339
mssql¶
Fix mssql+pyodbc issue where valid plus signs in an already-unquoted
odbc_connect=
(raw DBAPI) connection string are replaced with spaces.The pyodbc connector would unconditionally pass the odbc_connect value to unquote_plus(), even if it was not required. So, if the (unquoted) odbc_connect value contained
PWD=pass+word
that would get changed toPWD=pass word
, and the login would fail. One workaround was to quote just the plus sign —PWD=pass%2Bword
— which would then get unquoted toPWD=pass+word
.References: #11250
misc¶
Python 3.9 or above is now required; support for Python 3.8 and 3.7 is dropped as these versions are EOL.
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 thesqlalchemy[asyncio]
install target to include this dependency.References: #10197
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.
flambé! the dragon and The Alchemist image designs created and generously donated by Rotem Yaari.
Created using Sphinx 7.2.6. Documentation last generated: Wed 06 Nov 2024 07:03:25 PM EST