.. changelog::
:version: 1.2.0b1
+ .. change:: 3969
+ :tags: bug, sql
+ :tickets: 3969
+
+ Fixed the negation of a :class:`.Label` construct so that the
+ inner element is negated correctly, when the :func:`.not_` modifier
+ is applied to the labeled expression.
+
.. change::
:tags: bug, orm
:tickets: 3967
return self._element.self_group(against=operators.as_)
def self_group(self, against=None):
- sub_element = self._element.self_group(against=against)
+ return self._apply_to_inner(self._element.self_group, against=against)
+
+ def _negate(self):
+ return self._apply_to_inner(self._element._negate)
+
+ def _apply_to_inner(self, fn, *arg, **kw):
+ sub_element = fn(*arg, **kw)
if sub_element is not self._element:
return Label(self.name,
sub_element,
from sqlalchemy import String, Integer, LargeBinary
from sqlalchemy import exc
from sqlalchemy.engine import default
-from sqlalchemy.sql.elements import _literal_as_text
+from sqlalchemy.sql.elements import _literal_as_text, Label
from sqlalchemy.schema import Column, Table, MetaData
from sqlalchemy.sql import compiler
from sqlalchemy.types import TypeEngine, TypeDecorator, UserDefinedType, \
self.table1.c.myid.type,
)
+ def test_negate_operator_label(self):
+ orig_expr = or_(
+ self.table1.c.myid == 1, self.table1.c.myid == 2).label('foo')
+ expr = not_(orig_expr)
+ isinstance(expr, Label)
+ eq_(expr.name, 'foo')
+ is_not_(expr, orig_expr)
+ is_(expr._element.operator, operator.inv) # e.g. and not false_
+
+ self.assert_compile(
+ expr,
+ "NOT (mytable.myid = :myid_1 OR mytable.myid = :myid_2)"
+ )
+
class LikeTest(fixtures.TestBase, testing.AssertsCompiledSQL):
__dialect__ = 'default'