diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-04-29 23:26:36 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-05-18 17:46:10 -0400 |
commit | f07e050c9ce4afdeb9c0c136dbcc547f7e5ac7b8 (patch) | |
tree | 1b3cd7409ae2eddef635960126551d74f469acc1 /lib/sqlalchemy/sql/functions.py | |
parent | 614dfb5f5b5a2427d5d6ce0bc5f34bf0581bf698 (diff) | |
download | sqlalchemy-f07e050c9ce4afdeb9c0c136dbcc547f7e5ac7b8.tar.gz |
Implement new ClauseElement role and coercion system
A major refactoring of all the functions handle all detection of
Core argument types as well as perform coercions into a new class hierarchy
based on "roles", each of which identify a syntactical location within a
SQL statement. In contrast to the ClauseElement hierarchy that identifies
"what" each object is syntactically, the SQLRole hierarchy identifies
the "where does it go" of each object syntactically. From this we define
a consistent type checking and coercion system that establishes well
defined behviors.
This is a breakout of the patch that is reorganizing select()
constructs to no longer be in the FromClause hierarchy.
Also includes a rename of as_scalar() into scalar_subquery(); deprecates
automatic coercion to scalar_subquery().
Partially-fixes: #4617
Change-Id: I26f1e78898693c6b99ef7ea2f4e7dfd0e8e1a1bd
Diffstat (limited to 'lib/sqlalchemy/sql/functions.py')
-rw-r--r-- | lib/sqlalchemy/sql/functions.py | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index d0aa23988..173789998 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -9,14 +9,15 @@ """ from . import annotation +from . import coercions from . import operators +from . import roles from . import schema from . import sqltypes from . import util as sqlutil from .base import ColumnCollection from .base import Executable from .elements import _clone -from .elements import _literal_as_binds from .elements import _type_from_args from .elements import BinaryExpression from .elements import BindParameter @@ -83,7 +84,12 @@ class FunctionElement(Executable, ColumnElement, FromClause): """Construct a :class:`.FunctionElement`. """ args = [ - _literal_as_binds(c, getattr(self, "name", None)) for c in clauses + coercions.expect( + roles.ExpressionElementRole, + c, + name=getattr(self, "name", None), + ) + for c in clauses ] self._has_args = self._has_args or bool(args) self.clause_expr = ClauseList( @@ -686,7 +692,12 @@ class GenericFunction(util.with_metaclass(_GenericMeta, Function)): def __init__(self, *args, **kwargs): parsed_args = kwargs.pop("_parsed_args", None) if parsed_args is None: - parsed_args = [_literal_as_binds(c, self.name) for c in args] + parsed_args = [ + coercions.expect( + roles.ExpressionElementRole, c, name=self.name + ) + for c in args + ] self._has_args = self._has_args or bool(parsed_args) self.packagenames = [] self._bind = kwargs.get("bind", None) @@ -751,7 +762,10 @@ class ReturnTypeFromArgs(GenericFunction): """Define a function whose return type is the same as its arguments.""" def __init__(self, *args, **kwargs): - args = [_literal_as_binds(c, self.name) for c in args] + args = [ + coercions.expect(roles.ExpressionElementRole, c, name=self.name) + for c in args + ] kwargs.setdefault("type_", _type_from_args(args)) kwargs["_parsed_args"] = args super(ReturnTypeFromArgs, self).__init__(*args, **kwargs) @@ -880,7 +894,7 @@ class array_agg(GenericFunction): type = sqltypes.ARRAY def __init__(self, *args, **kwargs): - args = [_literal_as_binds(c) for c in args] + args = [coercions.expect(roles.ExpressionElementRole, c) for c in args] default_array_type = kwargs.pop("_default_array_type", sqltypes.ARRAY) if "type_" not in kwargs: |