Mike Bayer [Tue, 23 Mar 2021 22:49:28 +0000 (18:49 -0400)]
support as_declarative, as_declarative_base
Added support for the Mypy extension to correctly interpret a declarative
base class that's generated using the :func:`_orm.as_declarative` function
as well as the :meth:`_orm.registry.as_declarative_base` method.
Mike Bayer [Thu, 25 Mar 2021 14:37:12 +0000 (10:37 -0400)]
don't rely on pk-only group_by
Fixed the test test_aliased_stmt_includes_unnamed_fn
recently added in c1c999c01d to include the additional
column in the GROUP BY statement, allowing this statement
to succeed on SQL Server which seems to not support "group by pk only"
syntax.
Mike Bayer [Thu, 25 Mar 2021 12:40:16 +0000 (08:40 -0400)]
Accept **kw in annotated._clone() method
Fixed bug where combinations of the new "relationship with criteria"
feature could fail in conjunction with features that make use of the new
"lambda SQL" feature, including loader strategies such as selectinload and
lazyload, for more complicated scenarios such as polymorphic loading.
Mike Bayer [Wed, 24 Mar 2021 21:43:06 +0000 (17:43 -0400)]
Use class-local metadata for declarative base
Fixed regression where the ``.metadata`` attribute on a per class level
would not be honored, breaking the use case of per-class-hierarchy
:class:`.schema.MetaData` for abstract declarative classes and mixins.
Mike Bayer [Wed, 24 Mar 2021 15:33:04 +0000 (11:33 -0400)]
Repair pysqlcipher and use sqlcipher3
The ``pysqlcipher`` dialect now imports the ``sqlcipher3`` module
for Python 3 by default. Regressions have been repaired such that
the connection routine was not working.
To better support the post-connection steps of the pysqlcipher
dialect, a new hook Dialect.on_connect_url() is added, which
supersedes Dialect.on_connect() and is passed the URL object.
The dialect now pulls the passphrase and other cipher args
from the URL directly without including them in the
"connect" args. This will allow any user-defined extensibility
to connecting to work as it would for other dialects.
The commit also builds upon the extended routines in
sqlite/provisioning.py to better support running tests against
multiple simultaneous SQLite database files. Additionally enables
backend for test_sqlite which was skipping everything
for aiosqlite too, fortunately everything there is passing.
Mike Bayer [Wed, 24 Mar 2021 16:15:53 +0000 (12:15 -0400)]
Support __visit_name__ on PropComparator to work in cloning
Repaired support so that the :meth:`_sql.Select.params` method can work
correctly with a :class:`_sql.Select` object that includes joins across ORM
relationship structures, which is a new feature in 1.4.
Martin Häcker [Tue, 23 Mar 2021 15:46:18 +0000 (11:46 -0400)]
Use compat.exec_()
Fixed a bug where python 2.7.5 (default on CentOS 7) wasn't able to import
sqlalchemy, because on this version of Python ``exec "statement"`` and
``exec("statement")`` do not behave the same way. The compatibility
``exec_()`` function was used instead.
Mike Bayer [Tue, 23 Mar 2021 02:56:36 +0000 (22:56 -0400)]
Remove internal use of string attr in loader option
Fixed issue where a "removed in 2.0" warning were generated internally by
the relationship loader mechanics.
This changeset started the effort of converting all string usage
in the test suite, however this is a much longer job as the
use of strings in loader options is widespread. In particular
I'm not totally comfortable with strings not being accepted
in obvious spots like Load(User).load_only("x", "y", "z"), which
points to a new string expecting functionality that's not
what's there now. However at the moment it seems like we need
to continue removing all support for strings and then figure out
"immediate strings from an explicit class" later.
Mike Bayer [Tue, 16 Mar 2021 23:46:40 +0000 (19:46 -0400)]
Adjust derivation rules for table vs. subquery against a join
Fixed bug where ORM queries using a correlated subquery in conjunction with
:func:`_orm.column_property` would fail to correlate correctly to an
enclosing subquery or to a CTE when :meth:`_sql.Select.correlate_except`
were used in the property to control correlation, in cases where the
subquery contained the same selectables as ones within the correlated
subquery that were intended to not be correlated.
This is achieved by adding a limiting factor to ClauseAdapter
which is to explicitly pass the selectables we will be adapting
"from", which is then used by AliasedClass to limit "from"
to the mappers represented by the AliasedClass.
This did cause one test where an alias for a contains_eager()
was missing to suddenly fail, and the test was corrected, however
there may be some very edge cases like that one where the tighter
criteria causes an existing use case that's relying on the more
liberal aliasing to require modifications.
Mike Bayer [Tue, 23 Mar 2021 14:23:23 +0000 (10:23 -0400)]
warn / document for Query.with_polymorphic() with with_loader_criteria()
These are illustrated as not working in #6111. As this is
a highly complex and legacy method, encourage users to
migrate off of it before using with_loader_criteria().
Mike Bayer [Sun, 21 Mar 2021 21:10:18 +0000 (17:10 -0400)]
Add support for Boolean, Enum
Fixed bug in Mypy plugin where the Python type detection
for the :class:`_sqltypes.Boolean` column type would produce
an exception; additionally implemented support for :class:`_sqltypes.Enum`,
including detection of a string-based enum vs. use of Python ``enum.Enum``.
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.