]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
negate True/False separately from other elements
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 18 Apr 2019 13:40:03 +0000 (09:40 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 18 Apr 2019 17:41:10 +0000 (13:41 -0400)
Fixed issue where double negation of a boolean column wouldn't reset
the "NOT" operator.

Fixes: #4618
Change-Id: Ica280a0d6b5b0870aa2d05c4d059a1e559e6b12a
(cherry picked from commit 18f25f50353d9736e6638266585b2cb3ef7b0ea4)

doc/build/changelog/unreleased_13/4618.rst [new file with mode: 0644]
lib/sqlalchemy/sql/elements.py
test/sql/test_operators.py

diff --git a/doc/build/changelog/unreleased_13/4618.rst b/doc/build/changelog/unreleased_13/4618.rst
new file mode 100644 (file)
index 0000000..a9597fb
--- /dev/null
@@ -0,0 +1,6 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 4618
+
+    Fixed issue where double negation of a boolean column wouldn't reset
+    the "NOT" operator.
index a4623128f241e1a268a103a9db7a7e130a234bbb..b0d0feff5d9b5a29fb56d85b3e07ef7772c42111 100644 (file)
@@ -691,9 +691,6 @@ class ColumnElement(operators.ColumnOperators, ClauseElement):
 
     def _negate(self):
         if self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity:
-            # TODO: see the note in AsBoolean that it seems to assume
-            # the element is the True_() / False_() constant, so this
-            # is too broad
             return AsBoolean(self, operators.isfalse, operators.istrue)
         else:
             return super(ColumnElement, self)._negate()
@@ -3035,10 +3032,10 @@ class AsBoolean(UnaryExpression):
         return self
 
     def _negate(self):
-        # TODO: this assumes the element is the True_() or False_()
-        # object, but this assumption isn't enforced and
-        # ColumnElement._negate() can send any number of expressions here
-        return self.element._negate()
+        if isinstance(self.element, (True_, False_)):
+            return self.element._negate()
+        else:
+            return AsBoolean(self.element, self.negate, self.operator)
 
 
 class BinaryExpression(ColumnElement):
index dd9f76cd6c79b23e3a2f02bdc21181c9d5942f68..82c69003bd346b98d8e7386ced159b5d88da5950 100644 (file)
@@ -912,6 +912,14 @@ class BooleanEvalTest(fixtures.TestBase, testing.AssertsCompiledSQL):
             dialect=self._dialect(False),
         )
 
+    def test_three_a_double(self):
+        c = column("x", Boolean)
+        self.assert_compile(
+            select([c]).where(~~c),
+            "SELECT x WHERE x = 1",
+            dialect=self._dialect(False),
+        )
+
     def test_three_b(self):
         c = column("x", Boolean)
         self.assert_compile(
@@ -928,6 +936,14 @@ class BooleanEvalTest(fixtures.TestBase, testing.AssertsCompiledSQL):
             dialect=self._dialect(True),
         )
 
+    def test_four_double(self):
+        c = column("x", Boolean)
+        self.assert_compile(
+            select([c]).where(~~c),
+            "SELECT x WHERE x",
+            dialect=self._dialect(True),
+        )
+
     def test_five_a(self):
         c = column("x", Boolean)
         self.assert_compile(