summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-12-27 12:29:38 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-12-27 14:04:19 -0500
commit502df8a4730abf999546e1910270004c194b0c08 (patch)
treeb7c7e4ed5bbb253c5405100efba84f048f5b7b24 /lib/sqlalchemy/sql
parent10123d86ba02c53960ad3234e4d03b7e31b6756b (diff)
downloadsqlalchemy-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.py9
-rw-r--r--lib/sqlalchemy/sql/lambdas.py15
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__",
):