2.0.0b4
Released: December 5, 2022
orm
-
[orm] [feature] Added a new parameter
_orm.mapped_column.use_existing_column
to
accommodate the use case of a single-table inheritance mapping that uses
the pattern of more than one subclass indicating the same column to take
place on the superclass. This pattern was previously possible by using
_orm.declared_attr()
in conjunction with locating the existing column
in the.__table__
of the superclass, however is now updated to work
with_orm.mapped_column()
as well as with pep-484 typing, in a
simple and succinct way.References: #8822
-
[orm] [usecase] Added support custom user-defined types which extend the Python
enum.Enum
base class to be resolved automatically
to SQLAlchemyEnum
SQL types, when using the Annotated
Declarative Table feature. The feature is made possible through new
lookup features added to the ORM type map feature, and includes support
for changing the arguments of theEnum
that's generated by
default as well as setting up specificenum.Enum
types within
the map with specific arguments.References: #8859
-
[orm] [usecase] Added
_orm.mapped_column.compare
parameter to relevant ORM
attribute constructs including_orm.mapped_column()
,
_orm.relationship()
etc. to provide for the Python dataclasses
compare
parameter onfield()
, when using the
orm_declarative_native_dataclasses
feature. Pull request courtesy
Simon Schiele.References: #8905
-
[orm] [bug] Fixed bug where
_orm.Session.merge()
would fail to preserve the
current loaded contents of relationship attributes that were indicated with
the_orm.relationship.viewonly
parameter, thus defeating
strategies that use_orm.Session.merge()
to pull fully loaded objects
from caches and other similar techniques. In a related change, fixed issue
where an object that contains a loaded relationship that was nonetheless
configured aslazy='raise'
on the mapping would fail when passed to
_orm.Session.merge()
; checks for "raise" are now suspended within
the merge process assuming the_orm.Session.merge.load
parameter remains at its default ofTrue
.Overall, this is a behavioral adjustment to a change introduced in the 1.4
series as of #4994, which took "merge" out of the set of cascades
applied by default to "viewonly" relationships. As "viewonly" relationships
aren't persisted under any circumstances, allowing their contents to
transfer during "merge" does not impact the persistence behavior of the
target object. This allows_orm.Session.merge()
to correctly suit one
of its use cases, that of adding objects to aSession
that were
loaded elsewhere, often for the purposes of restoring from a cache.This change is also backported to: 1.4.45
References: #8862
-
[orm] [bug] Fixed issues in
_orm.with_expression()
where expressions that were
composed of columns that were referenced from the enclosing SELECT would
not render correct SQL in some contexts, in the case where the expression
had a label name that matched the attribute which used
_orm.query_expression()
, even when_orm.query_expression()
had
no default expression. For the moment, if the_orm.query_expression()
does have a default expression, that label name is still used for that
default, and an additional label with the same name will continue to be
ignored. Overall, this case is pretty thorny so further adjustments might
be warranted.This change is also backported to: 1.4.45
References: #8881
-
[orm] [bug] Fixed bug where
_orm.Session.merge()
would fail to preserve the
current loaded contents of relationship attributes that were indicated with
the_orm.relationship.viewonly
parameter, thus defeating
strategies that use_orm.Session.merge()
to pull fully loaded objects
from caches and other similar techniques. In a related change, fixed issue
where an object that contains a loaded relationship that was nonetheless
configured aslazy='raise'
on the mapping would fail when passed to
_orm.Session.merge()
; checks for "raise" are now suspended within
the merge process assuming the_orm.Session.merge.load
parameter remains at its default ofTrue
.Overall, this is a behavioral adjustment to a change introduced in the 1.4
series as of #4994, which took "merge" out of the set of cascades
applied by default to "viewonly" relationships. As "viewonly" relationships
aren't persisted under any circumstances, allowing their contents to
transfer during "merge" does not impact the persistence behavior of the
target object. This allows_orm.Session.merge()
to correctly suit one
of its use cases, that of adding objects to aSession
that were
loaded elsewhere, often for the purposes of restoring from a cache.This change is also backported to: 1.4.45
References: #8862
-
[orm] [bug] Fixed issues in
_orm.with_expression()
where expressions that were
composed of columns that were referenced from the enclosing SELECT would
not render correct SQL in some contexts, in the case where the expression
had a label name that matched the attribute which used
_orm.query_expression()
, even when_orm.query_expression()
had
no default expression. For the moment, if the_orm.query_expression()
does have a default expression, that label name is still used for that
default, and an additional label with the same name will continue to be
ignored. Overall, this case is pretty thorny so further adjustments might
be warranted.This change is also backported to: 1.4.45
References: #8881
-
[orm] [bug] Fixed issue where use of an unknown datatype within a
Mapped
annotation for a column-based attribute would silently fail to map the
attribute, rather than reporting an exception; an informative exception
message is now raised.References: #8888
-
[orm] [bug] Fixed a suite of issues involving
Mapped
use with dictionary
types, such asMapped[dict[str, str] | None]
, would not be correctly
interpreted in Declarative ORM mappings. Support to correctly
"de-optionalize" this type including for lookup intype_annotation_map
has been fixed.References: #8777
-
[orm] [bug] [performance] Additional performance enhancements within ORM-enabled SQL statements,
specifically targeting callcounts within the construction of ORM
statements, using combinations of_orm.aliased()
with
_sql.union()
and similar "compound" constructs, in addition to direct
performance improvements to thecorresponding_column()
internal method
that is used heavily by the ORM by constructs like_orm.aliased()
and
similar.References: #8796
-
[orm] [bug] Fixed bug in
orm_declarative_native_dataclasses
feature where using
plain dataclass fields with the__allow_unmapped__
directive in a
mapping would not create a dataclass with the correct class-level state for
those fields, copying the rawField
object to the class inappropriately
after dataclasses itself had replaced theField
object with the
class-level default value.References: #8880
-
[orm] [bug] [regression] Fixed regression where flushing a mapped class that's mapped against a
subquery, such as a direct mapping or some forms of concrete table
inheritance, would fail if the_orm.Mapper.eager_defaults
parameter were used.References: #8812
-
[orm] [bug] Fixed regression in 2.0.0b3 caused by #8759 where indicating the
Mapped
name using a qualified name such as
sqlalchemy.orm.Mapped
would fail to be recognized by Declarative as
indicating theMapped
construct.References: #8853
orm extensions
-
[usecase] [orm extensions] Added support for the
association_proxy()
extension function to
take part within Pythondataclasses
configuration, when using
the native dataclasses feature described at
orm_declarative_native_dataclasses
. Included are attribute-level
arguments includingassociation_proxy.init
and
association_proxy.default_factory
.Documentation for association proxy has also been updated to use
"Annotated Declarative Table" forms within examples, including type
annotations used forAssocationProxy
itself.References: #8878
sql
-
[sql] [usecase] An informative re-raise is now thrown in the case where any "literal
bindparam" render operation fails, indicating the value itself and
the datatype in use, to assist in debugging when literal params
are being rendered in a statement.This change is also backported to: 1.4.45
References: #8800
-
[sql] [usecase] Added
_expression.ScalarValues
that can be used as a column
element allowing using_expression.Values
insideIN
clauses
or in conjunction withANY
orALL
collection aggregates.
This new class is generated using the method
_expression.Values.scalar_values()
.
The_expression.Values
instance is now coerced to a
_expression.ScalarValues
when used in aIN
orNOT IN
operation.References: #6289
-
[sql] [bug] Fixed a series of issues regarding positionally rendered bound parameters,
such as those used for SQLite, asyncpg, MySQL and others. Some compiled
forms would not maintain the order of parameters correctly, such as the
PostgreSQLregexp_replace()
function as well as within the "nesting"
feature of theCTE
construct first introduced in #4123.This change is also backported to: 1.4.45
References: #8827
-
[sql] [bug] Fixed critical memory issue identified in cache key generation, where for
very large and complex ORM statements that make use of lots of ORM aliases
with subqueries, cache key generation could produce excessively large keys
that were orders of magnitude bigger than the statement itself. Much thanks
to Rollo Konig Brock for their very patient, long term help in finally
identifying this issue.This change is also backported to: 1.4.44
References: #8790
-
[sql] [bug] The approach to the
numeric
pep-249 paramstyle has been rewritten, and
is now fully supported, including by features such as "expanding IN" and
"insertmanyvalues". Parameter names may also be repeated in the source SQL
construct which will be correctly represented within the numeric format
using a single parameter. Introduced an additional numeric paramstyle
callednumeric_dollar
, which is specifically what's used by the asyncpg
dialect; the paramstyle is equivalent tonumeric
except numeric
indicators are indicated by a dollar-sign rather than a colon. The asyncpg
dialect now usesnumeric_dollar
paramstyle directly, rather than
compiling toformat
style first.The
numeric
andnumeric_dollar
paramstyles assume that the target
backend is capable of receiving the numeric parameters in any order,
and will match the given parameter values to the statement based on
matching their position (1-based) to the numeric indicator. This is the
normal behavior of "numeric" paramstyles, although it was observed that
the SQLite DBAPI implements a not-used "numeric" style that does not honor
parameter ordering.References: #8849
-
[sql] [bug] Adjusted the rendering of
RETURNING
, in particular when using
_sql.Insert
, such that it now renders columns using the same logic
as that of theSelect
construct to generate labels, which will
include disambiguating labels, as well as that a SQL function surrounding a
named column will be labeled using the column name itself. This establishes
better cross-compatibility when selecting rows from eitherSelect
constructs or from DML statements that useUpdateBase.returning()
. A
narrower scale change was also made for the 1.4 series that adjusted the
function label issue only.References: #8770
schema
-
[schema] [bug] Stricter rules are in place for appending of
Column
objects to
Table
objects, both moving some previous deprecation warnings to
exceptions, and preventing some previous scenarios that would cause
duplicate columns to appear in tables, when
Table.extend_existing
were set toTrue
, for both
programmaticTable
construction as well as during reflection
operations.See
change_8925
for a rundown of these changes.References: #8925
typing
-
[typing] [usecase] Added a new type
SQLColumnExpression
which may be indicated in
user code to represent any SQL column oriented expression, including both
those based onColumnElement
as well as on ORM
QueryableAttribute
. This type is a real class, not an alias, so
can also be used as the foundation for other objects. An additional
ORM-specific subclassSQLORMExpression
is also included.References: #8847
-
[typing] [bug] Adjusted internal use of the Python
enum.IntFlag
class which changed
its behavioral contract in Python 3.11. This was not causing runtime
failures however caused typing runs to fail under Python 3.11.References: #8783
-
[typing] [bug] The
sqlalchemy.ext.mutable
extension andsqlalchemy.ext.automap
extensions are now fully pep-484 typed. Huge thanks to Gleb Kisenkov for
their efforts on this. -
[typing] [bug] Corrected typing support for the
_orm.relationship.secondary
argument which may also accept a callable (lambda) that returns a
FromClause
. -
[typing] [bug] Improved the typing for
sessionmaker
and
async_sessionmaker
, so that the default type of their return value
will beSession
orAsyncSession
, without the need to
type this explicitly. Previously, Mypy would not automaticaly infer these
return types from its generic base.As part of this change, arguments for
Session
,
AsyncSession
,sessionmaker
and
async_sessionmaker
beyond the initial "bind" argument have been
made keyword-only, which includes parameters that have always been
documented as keyword arguments, such asSession.autoflush
,
Session.class_
, etc.Pull request courtesy Sam Bull.
References: #8842
-
[typing] [bug] Fixed issue where passing a callbale function returning an iterable
of column elements to_orm.relationship.order_by
was
flagged as an error in type checkers.References: #8776
postgresql
-
[postgresql] [usecase] Complementing #8690, new comparison methods such as
_postgresql.Range.adjacent_to()
,
_postgresql.Range.difference()
,_postgresql.Range.union()
,
etc., were added to the PG-specific range objects, bringing them in par
with the standard operators implemented by the underlying
_postgresql.AbstractRange.comparator_factory
.In addition, the
__bool__()
method of the class has been corrected to
be consistent with the common Python containers behavior as well as how
other popular PostgreSQL drivers do: it now tells whether the range
instance is not empty, rather than the other way around.Pull request courtesy Lele Gaifax.
References: #8765
-
[postgresql] [change] [asyncpg] Changed the paramstyle used by asyncpg from
format
to
numeric_dollar
. This has two main benefits since it does not require
additional processing of the statement and allows for duplicate parameters
to be present in the statements.References: #8926
-
[postgresql] [bug] Made an adjustment to how the PostgreSQL dialect considers column types
when it reflects columns from a table, to accommodate for alternative
backends which may return NULL from the PGformat_type()
function.This change is also backported to: 1.4.45
References: #8748
-
[postgresql] [bug] [mssql] For the PostgreSQL and SQL Server dialects only, adjusted the compiler so
that when rendering column expressions in the RETURNING clause, the "non
anon" label that's used in SELECT statements is suggested for SQL
expression elements that generate a label; the primary example is a SQL
function that may be emitting as part of the column's type, where the label
name should match the column's name by default. This restores a not-well
defined behavior that had changed in version 1.4.21 due to #6718,
#6710. The Oracle dialect has a different RETURNING implementation
and was not affected by this issue. Version 2.0 features an across the
board change for its widely expanded support of RETURNING on other
backends.This change is also backported to: 1.4.44
References: #8770
-
[postgresql] [bug] Added additional type-detection for the new PostgreSQL
_postgresql.Range
type, where previous cases that allowed the
psycopg2-native range objects to be received directly by the DBAPI without
SQLAlchemy intercepting them stopped working, as we now have our own value
object. The_postgresql.Range
object has been enhanced such that
SQLAlchemy Core detects it in otherwise ambiguous situations (such as
comparison to dates) and applies appropriate bind handlers. Pull request
courtesy Lele Gaifax.References: #8884
sqlite
-
[sqlite] [usecase] Added support for the SQLite backend to reflect the "DEFERRABLE" and
"INITIALLY" keywords which may be present on a foreign key construct. Pull
request courtesy Michael Gorven.This change is also backported to: 1.4.45
References: #8903
-
[sqlite] [usecase] Added support for reflection of expression-oriented WHERE criteria included
in indexes on the SQLite dialect, in a manner similar to that of the
PostgreSQL dialect. Pull request courtesy Tobias Pfeiffer.This change is also backported to: 1.4.45
References: #8804
mssql
-
[mssql] [bug] Fixed regression caused by the combination of #8177, re-enable
setinputsizes for SQL server unless fast_executemany + DBAPI executemany is
used for a statement, along with #6047, implement
"insertmanyvalues", which bypasses DBAPI executemany in place of a custom
DBAPI execute for INSERT statements. setinputsizes would incorrectly not be
used for a multiple parameter-set INSERT statement that used
"insertmanyvalues" if fast_executemany were turned on, as the check would
incorrectly assume this is a DBAPI executemany call. The "regression"
would then be that the "insertmanyvalues" statement format is apparently
slightly more sensitive to multiple rows that don't use the same types
for each row, so in such a case setinputsizes is especially needed.The fix repairs the fast_executemany check so that it only disables
setinputsizes if true DBAPI executemany is to be used.References: #8917
oracle
-
[oracle] [bug] Continued fixes for Oracle fix #8708 released in 1.4.43 where
bound parameter names that start with underscores, which are disallowed by
Oracle, were still not being properly escaped in all circumstances.This change is also backported to: 1.4.45
References: #8708
tests
-
[tests] [bug] Fixed issue where the
--disable-asyncio
parameter to the test suite
would fail to not actually run greenlet tests and would also not prevent
the suite from using a "wrapping" greenlet for the whole suite. This
parameter now ensures that no greenlet or asyncio use will occur within the
entire run when set.This change is also backported to: 1.4.44
References: #8793