From: Mike Bayer Date: Thu, 18 Apr 2019 13:40:03 +0000 (-0400) Subject: negate True/False separately from other elements X-Git-Tag: rel_1_3_4~35^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9737a9d9b1becc7dba1661f17b247db3213c511;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git negate True/False separately from other elements 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) --- diff --git a/doc/build/changelog/unreleased_13/4618.rst b/doc/build/changelog/unreleased_13/4618.rst new file mode 100644 index 0000000000..a9597fb6d8 --- /dev/null +++ b/doc/build/changelog/unreleased_13/4618.rst @@ -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. diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index a4623128f2..b0d0feff5d 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -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): diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index dd9f76cd6c..82c69003bd 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -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(