]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
raise for same param name in expanding + non expanding
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 13 May 2022 19:43:53 +0000 (15:43 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 15 May 2022 21:26:09 +0000 (17:26 -0400)
An informative error is raised if two individual :class:`.BindParameter`
objects share the same name, yet one is used within an "expanding" context
(typically an IN expression) and the other is not; mixing the same name in
these two different styles of usage is not supported and typically the
``expanding=True`` parameter should be set on the parameters that are to
receive list values outside of IN expressions (where ``expanding`` is set
by default).

Fixes: #8018
Change-Id: Ie707f29680eea16b9e421af93560ac1958e11a54

doc/build/changelog/unreleased_14/8018.rst [new file with mode: 0644]
lib/sqlalchemy/sql/compiler.py
test/sql/test_compiler.py

diff --git a/doc/build/changelog/unreleased_14/8018.rst b/doc/build/changelog/unreleased_14/8018.rst
new file mode 100644 (file)
index 0000000..c4aae3e
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 8018
+
+    An informative error is raised if two individual :class:`.BindParameter`
+    objects share the same name, yet one is used within an "expanding" context
+    (typically an IN expression) and the other is not; mixing the same name in
+    these two different styles of usage is not supported and typically the
+    ``expanding=True`` parameter should be set on the parameters that are to
+    receive list values outside of IN expressions (where ``expanding`` is set
+    by default).
index f774028f22cd984cb0b104c2dfd1abfe4bce8a6a..0eae31a1a4c8ce36926ef90cc5bab293b7347956 100644 (file)
@@ -2860,6 +2860,15 @@ class SQLCompiler(Compiled):
                         "Bind parameter '%s' conflicts with "
                         "unique bind parameter of the same name" % name
                     )
+                elif existing.expanding != bindparam.expanding:
+                    raise exc.CompileError(
+                        "Can't reuse bound parameter name '%s' in both "
+                        "'expanding' (e.g. within an IN expression) and "
+                        "non-expanding contexts.  If this parameter is to "
+                        "receive a list/array value, set 'expanding=True' on "
+                        "it for expressions that aren't IN, otherwise use "
+                        "a different parameter name." % (name,)
+                    )
                 elif existing._is_crud or bindparam._is_crud:
                     if existing._is_crud and bindparam._is_crud:
                         # TODO: this condition is not well understood.
index bf31824e56783bf3feadccebd70b299d7e1b07c0..d9f137349c75a18fcdbb2c7c9ae8d08ba59c2fe5 100644 (file)
@@ -3662,6 +3662,25 @@ class BindParameterTest(AssertsCompiledSQL, fixtures.TestBase):
             s,
         )
 
+    def test_expanding_non_expanding_conflict(self):
+        """test #8018"""
+
+        s = select(
+            literal("x").in_(bindparam("q")),
+            bindparam("q"),
+        )
+
+        with expect_raises_message(
+            exc.CompileError,
+            r"Can't reuse bound parameter name 'q' in both 'expanding' "
+            r"\(e.g. within an IN expression\) and non-expanding contexts.  "
+            "If this parameter is to "
+            "receive a list/array value, set 'expanding=True' on "
+            "it for expressions that aren't IN, otherwise use "
+            "a different parameter name.",
+        ):
+            str(s)
+
     def test_unique_binds_no_clone_collision(self):
         """test #6824"""
         bp = bindparam("foo", unique=True)