diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-12-01 17:24:27 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-05-24 11:54:08 -0400 |
commit | dce8c7a125cb99fad62c76cd145752d5afefae36 (patch) | |
tree | 352dfa2c38005207ca64f45170bbba2c0f8c927e /lib/sqlalchemy/sql/coercions.py | |
parent | 1502b5b3e4e4b93021eb927a6623f288ef006ba6 (diff) | |
download | sqlalchemy-dce8c7a125cb99fad62c76cd145752d5afefae36.tar.gz |
Unify Query and select() , move all processing to compile phase
Convert Query to do virtually all compile state computation
in the _compile_context() phase, and organize it all
such that a plain select() construct may also be used as the
source of information in order to generate ORM query state.
This makes it such that Query is not needed except for
its additional methods like from_self() which are all to
be deprecated.
The construction of ORM state will occur beyond the
caching boundary when the new execution model is integrated.
future select() gains a working join() and filter_by() method.
as we continue to rebase and merge each commit in the steps,
callcounts continue to bump around. will have to look at
the final result when it's all in.
References: #5159
References: #4705
References: #4639
References: #4871
References: #5010
Change-Id: I19e05b3424b07114cce6c439b05198ac47f7ac10
Diffstat (limited to 'lib/sqlalchemy/sql/coercions.py')
-rw-r--r-- | lib/sqlalchemy/sql/coercions.py | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index c7b85c415..2fc63b82f 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -57,7 +57,7 @@ def expect(role, element, **kw): if not isinstance( element, - (elements.ClauseElement, schema.SchemaItem, schema.FetchedValue), + (elements.ClauseElement, schema.SchemaItem, schema.FetchedValue,), ): resolved = impl._resolve_for_clause_element(element, **kw) else: @@ -106,7 +106,9 @@ class RoleImpl(object): self.name = role_class._role_name self._use_inspection = issubclass(role_class, roles.UsesInspection) - def _resolve_for_clause_element(self, element, argname=None, **kw): + def _resolve_for_clause_element( + self, element, argname=None, apply_plugins=None, **kw + ): original_element = element is_clause_element = False @@ -115,18 +117,39 @@ class RoleImpl(object): if not getattr(element, "is_clause_element", False): element = element.__clause_element__() else: - return element + break + + should_apply_plugins = ( + apply_plugins is not None + and apply_plugins._compile_state_plugin is None + ) if is_clause_element: + if ( + should_apply_plugins + and "compile_state_plugin" in element._annotations + ): + apply_plugins._compile_state_plugin = element._annotations[ + "compile_state_plugin" + ] return element if self._use_inspection: insp = inspection.inspect(element, raiseerr=False) if insp is not None: + insp._post_inspect try: - return insp.__clause_element__() + element = insp.__clause_element__() except AttributeError: self._raise_for_expected(original_element, argname) + else: + if ( + should_apply_plugins + and "compile_state_plugin" in element._annotations + ): + plugin = element._annotations["compile_state_plugin"] + apply_plugins._compile_state_plugin = plugin + return element return self._literal_coercion(element, argname=argname, **kw) @@ -287,7 +310,7 @@ class _SelectIsNotFrom(object): advice = ( "To create a " "FROM clause from a %s object, use the .subquery() method." - % (element.__class__) + % (element.__class__,) ) code = "89ve" else: @@ -453,6 +476,18 @@ class OrderByImpl(ByOfImpl, RoleImpl): return resolved +class GroupByImpl(ByOfImpl, RoleImpl): + __slots__ = () + + def _implicit_coercions( + self, original_element, resolved, argname=None, **kw + ): + if isinstance(resolved, roles.StrictFromClauseRole): + return elements.ClauseList(*resolved.c) + else: + return resolved + + class DMLColumnImpl(_ReturnsStringKey, RoleImpl): __slots__ = () @@ -618,6 +653,37 @@ class HasCTEImpl(ReturnsRowsImpl, roles.HasCTERole): pass +class JoinTargetImpl(RoleImpl): + __slots__ = () + + def _literal_coercion(self, element, legacy=False, **kw): + if isinstance(element, str): + return element + + def _implicit_coercions( + self, original_element, resolved, argname=None, legacy=False, **kw + ): + if isinstance(original_element, roles.JoinTargetRole): + return original_element + elif legacy and isinstance(resolved, (str, roles.WhereHavingRole)): + return resolved + elif legacy and resolved._is_select_statement: + util.warn_deprecated( + "Implicit coercion of SELECT and textual SELECT " + "constructs into FROM clauses is deprecated; please call " + ".subquery() on any Core select or ORM Query object in " + "order to produce a subquery object.", + version="1.4", + ) + # TODO: doing _implicit_subquery here causes tests to fail, + # how was this working before? probably that ORM + # join logic treated it as a select and subquery would happen + # in _ORMJoin->Join + return resolved + else: + self._raise_for_expected(original_element, argname, resolved) + + class FromClauseImpl(_SelectIsNotFrom, _NoTextCoercion, RoleImpl): __slots__ = () @@ -647,6 +713,12 @@ class FromClauseImpl(_SelectIsNotFrom, _NoTextCoercion, RoleImpl): else: self._raise_for_expected(original_element, argname, resolved) + def _post_coercion(self, element, deannotate=False, **kw): + if deannotate: + return element._deannotate() + else: + return element + class StrictFromClauseImpl(FromClauseImpl): __slots__ = () |