Mike Bayer [Fri, 19 Mar 2021 18:52:59 +0000 (14:52 -0400)]
Use tuple for function package names
Fixed issue where using a ``func`` that includes dotted packagenames would
fail to be cacheable by the SQL caching system due to a Python list of
names that needed to be a tuple.
Mike Bayer [Fri, 19 Mar 2021 14:34:31 +0000 (10:34 -0400)]
Correct for coercion from list args to positional for case
Fixed regression in the :func:`_sql.case` construct, where the "dictionary"
form of argument specification failed to work correctly if it were passed
positionally, rather than as a "whens" keyword argument.
Mike Bayer [Fri, 19 Mar 2021 05:18:06 +0000 (01:18 -0400)]
Deannoate functions before matching .__class__
Fixed regression where the SQL compilation of a :class:`.Function` would
not work correctly if the object had been "annotated", which is an internal
memoization process used mostly by the ORM. In particular it could affect
ORM lazy loads which make greater use of this feature in 1.4.
Mike Bayer [Thu, 18 Mar 2021 23:34:32 +0000 (19:34 -0400)]
Ensure ClauseAdapter treats FunctionElement as a ColumnElement
Fixed regression where use of an unnamed SQL expression such as a SQL
function would raise a column targeting error if the query itself were
using joinedload for an entity and was also being wrapped in a subquery by
the joinedload eager loading process.
Mike Bayer [Thu, 18 Mar 2021 21:46:24 +0000 (17:46 -0400)]
repair legacy_last_joined_entity for no onclause
Fixed regression where the :meth:`_orm.Query.filter_by` method would fail
to locate the correct source entity if the :meth:`_orm.Query.join` method
had been used targeting an entity without any kind of ON clause.
Mike Bayer [Thu, 18 Mar 2021 19:26:05 +0000 (15:26 -0400)]
check for MemberExpr looking for column argument
Fixed issue in MyPy extension which crashed on detecting the type of a
:class:`.Column` if the type were given with a module prefix like
``sa.Integer()``.
Mike Bayer [Thu, 18 Mar 2021 19:07:03 +0000 (15:07 -0400)]
Adjust dataclass rules to account for field w/ default
Fixed issue in new ORM dataclasses functionality where dataclass fields on
an abstract base or mixin that contained column or other mapping constructs
would not be mapped if they also included a "default" key within the
dataclasses.field() object.
Mike Bayer [Thu, 18 Mar 2021 15:59:16 +0000 (11:59 -0400)]
Raise at Core / ORM concrete inh level for label overlap
Fixed regression where the :class:`.ConcreteBase` would fail to map at all
when a mapped column name overlapped with the discriminator column name,
producing an assertion error. The use case here did not function correctly
in 1.3 as the polymorphic union would produce a query that ignored the
discriminator column entirely, while emitting duplicate column warnings. As
1.4's architecture cannot easily reproduce this essentially broken behavior
of 1.3 at the ``select()`` level right now, the use case now raises an
informative error message instructing the user to use the
``.ConcreteBase._concrete_discriminator_name`` attribute to resolve the
conflict. To assist with this configuration,
``.ConcreteBase._concrete_discriminator_name`` may be placed on the base
class only where it will be automatically used by subclasses; previously
this was not the case.
Mike Bayer [Wed, 17 Mar 2021 15:04:58 +0000 (11:04 -0400)]
Use explicit names for mapper _get_clause parameters
Fixed a critical regression in the relationship lazy loader where the SQL
criteria used to fetch a related many-to-one object could go stale in
relation to other memoized structures within the loader if the mapper had
configuration changes, such as can occur when mappers are late configured
or configured on demand, producing a comparison to None and returning no
object. Huge thanks to Alan Hamlett for their help tracking this down late
into the night.
The primary change is that mapper._get_clause() uses a fixed name
for its bound parameters, which is memoized under a lambda statement
in the case of many-to-one lazy loading. This has implications for some other
logic namely the .compare() used by loader strategies to determine
use_get needed to be adjusted.
This change also repairs the lambda module's behavior of removing
the "required" flag from bound parameters, which caused this issue
to also fail silently rather than issuing an error for a required
bind parameter.
Mike Bayer [Wed, 17 Mar 2021 12:39:45 +0000 (08:39 -0400)]
Provide special row proxies for count and index
The Python ``namedtuple()`` has the behavior such that the names ``count``
and ``index`` will be served as tuple values if the named tuple includes
those names; if they are absent, then their behavior as methods of
``collections.abc.Sequence`` is maintained. Therefore the
:class:`_result.Row` and :class:`_result.LegacyRow` classes have been fixed
so that they work in this same way, maintaining the expected behavior for
database rows that have columns named "index" or "count".
Mike Bayer [Wed, 17 Mar 2021 12:59:09 +0000 (08:59 -0400)]
Ensure entity or None returned from _entity_from_pre_ent_zero()
Fixed regression where the :meth:`_orm.Query.exists` method would fail to
create an expression if the entity list of the :class:`_orm.Query` were
an arbitrary SQL column expression.
Mike Bayer [Tue, 16 Mar 2021 22:32:30 +0000 (18:32 -0400)]
Fix typo in Session.identity_key
Fixed regression in :meth:`_orm.Session.identity_key`, including that the
method and related methods were not covered by any unit test as well as
that the method contained a typo preventing it from functioning correctly.
Mike Bayer [Tue, 16 Mar 2021 21:59:44 +0000 (17:59 -0400)]
turn off eager configure_mappers() outside of Query, Load
Fixed regression where producing a Core expression construct such as
:func:`_sql.select` using ORM entities would eagerly configure the mappers,
in an effort to maintain compatibility with the :class:`_orm.Query` object
which necessarily does this to support many backref-related legacy cases.
However, core :func:`_sql.select` constructs are also used in mapper
configurations and such, and to that degree this eager configuration is
more of an inconvenience, so eager configure has been disabled for the
:func:`_sql.select` and other Core constructs in the absence of ORM loading
types of functions such as :class:`_orm.Load`.
The change maintains the behavior of :class:`_orm.Query` so that backwards
compatibility is maintained. However, when using a :func:`_sql.select` in
conjunction with ORM entities, a "backref" that isn't explicitly placed on
one of the classes until mapper configure time won't be available unless
:func:`_orm.configure_mappers` or the newer :func:`_orm.registry.configure`
has been called elsewhere. Prefer using
:paramref:`_orm.relationship.back_populates` for more explicit relationship
configuration which does not have the eager configure requirement.
Mike Bayer [Tue, 16 Mar 2021 19:03:22 +0000 (15:03 -0400)]
Early-assign Base.registry to a private name
Fixed bug where user-mapped classes that contained an attribute named
"registry" would cause conflicts with the new registry-based mapping system
when using :class:`.DeclarativeMeta`. While the attribute remains
something that can be set explicitly on a declarative base to be
consumed by the metaclass, once located it is placed under a private
class variable so it does not conflict with future subclasses that use
the same name for other purposes.
Mike Bayer [Tue, 16 Mar 2021 15:23:07 +0000 (11:23 -0400)]
Turn off pyodbc setinputsizes() by default
Fixed regression where a new setinputsizes() API that's available for
pyodbc was enabled, which is apparently incompatible with pyodbc's
fast_executemany() mode in the absence of more accurate typing information,
which as of yet is not fully implemented or tested. The pyodbc dialect and
connector has been modified so that setinputsizes() is not used at all
unless the parameter ``use_setinputsizes`` is passed to the dialect, e.g.
via :func:`_sa.create_engine`, at which point its behavior can be
customized using the :meth:`.DialectEvents.do_setinputsizes` hook.
Federico Caselli [Wed, 10 Mar 2021 22:54:52 +0000 (23:54 +0100)]
CAST the elements in ARRAYs when using psycopg2
Adjusted the psycopg2 dialect to emit an explicit PostgreSQL-style cast for
bound parameters that contain ARRAY elements. This allows the full range of
datatypes to function correctly within arrays. The asyncpg dialect already
generated these internal casts in the final statement. This also includes
support for array slice updates as well as the PostgreSQL-specific
:meth:`_postgresql.ARRAY.contains` method.
Mike Bayer [Tue, 16 Mar 2021 00:01:23 +0000 (20:01 -0400)]
Move enable_eagerloads(False) out of _from_self() into count()
Fixed regression where calling upon :meth:`_orm.Query.count` in conjunction
with a loader option such as :func:`_orm.joinedload` would fail to ignore
the loader option. This is a behavior that has always been very specific to
the :meth:`_orm.Query.count` method; an error is normally raised if a given
:class:`_orm.Query` has options that don't apply to what it is returning.
Specifically, the call to enable_eagerloads(False) inside of
_from_self() is not needed as loader options are now not invoked
for subqueries. Instead, set enable_eagerloads(False) in the
count() method itself, so that these options won't be considered
in this specific case.
Mike Bayer [Tue, 16 Feb 2021 23:36:50 +0000 (18:36 -0500)]
Implement Mypy plugin
Rudimentary and experimental support for Mypy has been added in the form of
a new plugin, which itself depends on new typing stubs for SQLAlchemy. The
plugin allows declarative mappings in their standard form to both be
compatible with Mypy as well as to provide typing support for mapped
classes and instances.
Mike Bayer [Fri, 12 Mar 2021 03:13:52 +0000 (22:13 -0500)]
Clarify ORM server side results
the docs here implied that the buffering scheme used by
BufferedRowCursorFetchStrategy is also used by the ORM, however
this is not currently the case. The ORM strictly uses the
"yield_per" option, which is either set explcitly, or passed
at result time via the fetchmany() / partitions() / yield_per()
methods.
Mike Bayer [Tue, 9 Mar 2021 18:36:34 +0000 (13:36 -0500)]
Apply percent sign escaping to op(), custom_op()
Fixed bug where the "percent escaping" feature that occurs with dialects
that use the "format" or "pyformat" bound parameter styles was not enabled
for the :meth:`.Operations.op` and :meth:`.Operations.custom_op` methods,
for custom operators that use percent signs. The percent sign will now be
automatically doubled based on the paramstyle as necessary.
Mike Bayer [Tue, 9 Mar 2021 15:48:59 +0000 (10:48 -0500)]
Link to state, not object, for mutable extension
The ``sqlalchemy.ext.mutable`` extension now tracks the "parents"
collection using the :class:`.InstanceState` associated with objects,
rather than the object itself. The latter approach required that the object
be hashable so that it can be inside of a ``WeakKeyDictionary``, which goes
against the behavioral contract of the ORM overall which is that ORM mapped
objects do not need to provide any particular kind of ``__hash__()`` method
and that unhashable objects are supported.
Mike Bayer [Fri, 5 Mar 2021 22:34:10 +0000 (17:34 -0500)]
Replace reset_agent with direct call from connection
Fixed a regression where the "reset agent" of the connection pool wasn't
really being utilized by the :class:`_engine.Connection` when it were
closed, and also leading to a double-rollback scenario that was somewhat
wasteful. The newer architecture of the engine has been updated so that
the connection pool "reset-on-return" logic will be skipped when the
:class:`_engine.Connection` explicitly closes out the transaction before
returning the pool to the connection.
Gord Thompson [Sat, 6 Mar 2021 19:19:13 +0000 (12:19 -0700)]
Fix named CHECK constraint name omitted on repeated creates
Fixed issue where the CHECK constraint generated by :class:`_types.Boolean`
or :class:`_types.Enum` would fail to render the naming convention
correctly after the first compilation, due to an unintended change of state
within the name given to the constraint. This issue was first introduced in
0.9 in the fix for issue #3067, and the fix revises the approach taken at
that time which appears to have been more involved than what was needed.
Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com> Fixes: #6007
Change-Id: I7ecff0a9d86191520f6841b3922a5af5a6971fba
Mike Bayer [Sat, 6 Mar 2021 02:52:03 +0000 (21:52 -0500)]
improve targeting and labeling for unary() in columns clause
Fixed regression where usage of the standalone :func:`_sql.distinct()` used
in the form of being directly SELECTed would fail to be locatable in the
result set by column identity, which is how the ORM locates columns. While
standalone :func:`_sql.distinct()` is not oriented towards being directly
SELECTed (use :meth:`_sql.select.distinct` for a regular
``SELECT DISTINCT..``) , it was usable to a limited extent in this way
previously (but wouldn't work in subqueries, for example). The column
targeting for unary expressions such as "DISTINCT <col>" has been improved
so that this case works again, and an additional improvement has been made
so that usage of this form in a subquery at least generates valid SQL which
was not the case previously.
The change additionally enhances the ability to target elements in
``row._mapping`` based on SQL expression objects in ORM-enabled
SELECT statements, including whether the statement was invoked by
``connection.execute()`` or ``session.execute()``.
Mike Bayer [Fri, 5 Mar 2021 21:02:38 +0000 (16:02 -0500)]
Ensure all Query statements compile w/ orm, fix test harness
Fixed regression where :meth:`_orm.Query.join` would produce no effect if
the query itself as well as the join target were against a
:class:`_schema.Table` object, rather than a mapped class. This was part of
a more systemic issue where the legacy ORM query compiler would not be
correctly used from a :class:`_orm.Query` if the statement produced had not
ORM entities present within it.
Also repair the assert_compile() method, which was using
Query._compile_state() which was bypassing the bug. A handful
of ORM tests with Query objects and Core-only objects were actually
failing if the default compilation path were used.
Mike Bayer [Fri, 5 Mar 2021 17:27:09 +0000 (12:27 -0500)]
Clarify COMMIT/ROLLBACK logging when autocommit is turned on
Improved engine logging to note ROLLBACK and COMMIT which is logged while
the DBAPI driver is in AUTOCOMMIT mode. These ROLLBACK/COMMIT are library
level and do not have any effect when AUTOCOMMIT is in effect, however it's
still worthwhile to log as these indicate where SQLAlchemy sees the
"transaction" demarcation.
Fixed issue where the :class:`_mutable.MutableComposite` construct could be
placed into an invalid state when the parent object was already loaded, and
then covered by a subsequent query, due to the composite properties'
refresh handler replacing the object with a new one not handled by the
mutable extension.
Mike Bayer [Tue, 2 Mar 2021 23:48:08 +0000 (18:48 -0500)]
Remove passive_deletes warning for many-to-one
Removed very old warning that states that passive_deletes is not intended
for many-to-one relationships. While it is likely that in many cases
placing this parameter on a many-to-one relationship is not what was
intended, there are use cases where delete cascade may want to be
disallowed following from such a relationship.
Mike Bayer [Tue, 2 Mar 2021 16:16:49 +0000 (11:16 -0500)]
convert AsyncSession.delete into awaitable
The API for :meth:`_asyncio.AsyncSession.delete` is now an awaitable;
this method cascades along relationships which must be loaded in a
similar manner as the :meth:`_asyncio.AsyncSession.merge` method.
Mike Bayer [Fri, 26 Feb 2021 04:20:05 +0000 (23:20 -0500)]
disable all raiseload within the unit of work process.
The unit of work process now turns off all "lazy='raise'" behavior
altogether when a flush is proceeding. While there are areas where the UOW
is sometimes loading things that aren't ultimately needed, the lazy="raise"
strategy is not helpful here as the user often does not have much control
or visibility into the flush process.