From: Mike Bayer Date: Sun, 1 May 2022 16:28:36 +0000 (-0400) Subject: use bindparam_type in BinaryElementImpl._post_coercion if available X-Git-Tag: rel_1_4_37~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55ac391ef92a46556c1579899feef051296acd4b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git use bindparam_type in BinaryElementImpl._post_coercion if available Fixed an issue where using :func:`.bindparam` with no explicit data or type given could be coerced into the incorrect type when used in expressions such as when using :meth:`.ARRAY.comparator.any` and :meth:`.ARRAY.comparator.all`. Fixes: #7979 Change-Id: If7779e713c9a3a5fee496b66e417cfd3fca5b1f9 (cherry picked from commit 889cbe53121c8fd50c845357dd52b24594346b68) --- diff --git a/doc/build/changelog/unreleased_14/7979.rst b/doc/build/changelog/unreleased_14/7979.rst new file mode 100644 index 0000000000..9a82a29097 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7979.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, sql + :tickets: 7979 + + Fixed an issue where using :func:`.bindparam` with no explicit data or type + given could be coerced into the incorrect type when used in expressions + such as when using :meth:`.ARRAY.comparator.any` and + :meth:`.ARRAY.comparator.all`. + diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index b3974c3d36..8cc73cb5c5 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -524,9 +524,11 @@ class BinaryElementImpl(ExpressionElementImpl, RoleImpl): except exc.ArgumentError as err: self._raise_for_expected(element, err=err) - def _post_coercion(self, resolved, expr, **kw): + def _post_coercion(self, resolved, expr, bindparam_type=None, **kw): if resolved.type._isnull and not expr.type._isnull: - resolved = resolved._with_binary_element_type(expr.type) + resolved = resolved._with_binary_element_type( + bindparam_type if bindparam_type is not None else expr.type + ) return resolved diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index c524b0aeaa..116d6b7923 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -3,6 +3,7 @@ import operator from sqlalchemy import and_ from sqlalchemy import between +from sqlalchemy import bindparam from sqlalchemy import exc from sqlalchemy import Integer from sqlalchemy import join @@ -3539,6 +3540,24 @@ class AnyAllTest(fixtures.TestBase, testing.AssertsCompiledSQL): t.c.data + all_(t.c.arrval), "tab1.data + ALL (tab1.arrval)" ) + @testing.combinations("all", "any", argnames="op") + def test_any_all_bindparam_coercion(self, t_fixture, op): + """test #7979""" + t = t_fixture + + if op == "all": + expr = t.c.arrval.all(bindparam("param")) + expected = "%(param)s = ALL (tab1.arrval)" + elif op == "any": + expr = t.c.arrval.any(bindparam("param")) + expected = "%(param)s = ANY (tab1.arrval)" + else: + assert False + + is_(expr.left.type._type_affinity, Integer) + + self.assert_compile(expr, expected, dialect="postgresql") + def test_any_array_comparator_accessor(self, t_fixture): t = t_fixture