diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-12-27 12:29:38 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-12-27 14:04:19 -0500 |
| commit | 502df8a4730abf999546e1910270004c194b0c08 (patch) | |
| tree | b7c7e4ed5bbb253c5405100efba84f048f5b7b24 /lib/sqlalchemy/sql | |
| parent | 10123d86ba02c53960ad3234e4d03b7e31b6756b (diff) | |
| download | sqlalchemy-502df8a4730abf999546e1910270004c194b0c08.tar.gz | |
pass more contextual information to PyWrapper param create
Fixed issue in lambda SQL feature where the calculated type of a literal
value would not take into account the type coercion rules of the "compared
to type", leading to a lack of typing information for SQL expressions, such
as comparisons to :class:`.JSON` elements and similar.
Fixes: #9029
Change-Id: I381c8d7458d98ba762313dee9ec47a9c1881f74a
Diffstat (limited to 'lib/sqlalchemy/sql')
| -rw-r--r-- | lib/sqlalchemy/sql/coercions.py | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/lambdas.py | 15 |
2 files changed, 17 insertions, 7 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index 9c3e7480a..7a4e68773 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -355,7 +355,12 @@ def expect( if not isinstance( element, - (elements.CompilerElement, schema.SchemaItem, schema.FetchedValue), + ( + elements.CompilerElement, + schema.SchemaItem, + schema.FetchedValue, + lambdas.PyWrapper, + ), ): resolved = None @@ -404,6 +409,8 @@ def expect( ) else: resolved = element + elif isinstance(element, lambdas.PyWrapper): + resolved = element._sa__py_wrapper_literal(**kw) else: resolved = element diff --git a/lib/sqlalchemy/sql/lambdas.py b/lib/sqlalchemy/sql/lambdas.py index 26e3a21bb..d9b4988a6 100644 --- a/lib/sqlalchemy/sql/lambdas.py +++ b/lib/sqlalchemy/sql/lambdas.py @@ -33,7 +33,6 @@ from . import coercions from . import elements from . import roles from . import schema -from . import type_api from . import visitors from .base import _clone from .base import Executable @@ -1308,11 +1307,11 @@ class PyWrapper(ColumnOperators): return value def operate(self, op, *other, **kwargs): - elem = object.__getattribute__(self, "__clause_element__")() + elem = object.__getattribute__(self, "_py_wrapper_literal")() return op(elem, *other, **kwargs) def reverse_operate(self, op, other, **kwargs): - elem = object.__getattribute__(self, "__clause_element__")() + elem = object.__getattribute__(self, "_py_wrapper_literal")() return op(other, elem, **kwargs) def _extract_bound_parameters(self, starting_point, result_list): @@ -1325,16 +1324,19 @@ class PyWrapper(ColumnOperators): element = getter(starting_point) pywrapper._sa__extract_bound_parameters(element, result_list) - def __clause_element__(self): + def _py_wrapper_literal(self, expr=None, operator=None, **kw): param = object.__getattribute__(self, "_param") to_evaluate = object.__getattribute__(self, "_to_evaluate") if param is None: name = object.__getattribute__(self, "_name") self._param = param = elements.BindParameter( - name, required=False, unique=True + name, + required=False, + unique=True, + _compared_to_operator=operator, + _compared_to_type=expr.type if expr is not None else None, ) self._has_param = True - param.type = type_api._resolve_value_to_type(to_evaluate) return param._with_value(to_evaluate, maintain_key=True) def __bool__(self): @@ -1348,6 +1350,7 @@ class PyWrapper(ColumnOperators): "__clause_element__", "operate", "reverse_operate", + "_py_wrapper_literal", "__class__", "__dict__", ): |
