summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Bank <sebastian.bank@uni-leipzig.de>2016-03-11 19:05:52 +0100
committerSebastian Bank <sebastian.bank@uni-leipzig.de>2016-03-13 22:08:45 +0100
commit19e5d667e18ff3c3ebcb399f03e30cabe9f8a09f (patch)
tree45b72babe26e7809c83b8ab9bc74e12b17ba21c1
parentf61194cb865db8b29cc65e47782bb72e54b14ada (diff)
downloadsqlalchemy-19e5d667e18ff3c3ebcb399f03e30cabe9f8a09f.tar.gz
add IS (NOT) DISTINCT FROM operator
-rw-r--r--lib/sqlalchemy/sql/compiler.py2
-rw-r--r--lib/sqlalchemy/sql/default_comparator.py12
-rw-r--r--lib/sqlalchemy/sql/operators.py27
-rw-r--r--test/sql/test_operators.py12
4 files changed, 49 insertions, 4 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 8600dbaeb..a0e8c124d 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -81,6 +81,8 @@ OPERATORS = {
operators.gt: ' > ',
operators.ge: ' >= ',
operators.eq: ' = ',
+ operators.is_distinct_from: ' IS DISTINCT FROM ',
+ operators.isnot_distinct_from: ' IS NOT DISTINCT FROM ',
operators.concat_op: ' || ',
operators.match_op: ' MATCH ',
operators.notmatch_op: ' NOT MATCH ',
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py
index 1bb1c344c..b6d7a6d48 100644
--- a/lib/sqlalchemy/sql/default_comparator.py
+++ b/lib/sqlalchemy/sql/default_comparator.py
@@ -32,8 +32,9 @@ def _boolean_compare(expr, op, obj, negate=None, reverse=False,
# allow x ==/!= True/False to be treated as a literal.
# this comes out to "== / != true/false" or "1/0" if those
# constants aren't supported and works on all platforms
- if op in (operators.eq, operators.ne) and \
- isinstance(obj, (bool, True_, False_)):
+ if (op in (operators.eq, operators.ne) and \
+ isinstance(obj, (bool, True_, False_))) or \
+ op in (operators.is_distinct_from, operators.isnot_distinct_from):
return BinaryExpression(expr,
_literal_as_text(obj),
op,
@@ -51,8 +52,9 @@ def _boolean_compare(expr, op, obj, negate=None, reverse=False,
negate=operators.is_)
else:
raise exc.ArgumentError(
- "Only '=', '!=', 'is_()', 'isnot()' operators can "
- "be used with None/True/False")
+ "Only '=', '!=', 'is_()', 'isnot()', "
+ "'is_distinct_from()', 'isnot_distinct_from()' "
+ "operators can be used with None/True/False")
else:
obj = _check_literal(expr, op, obj)
@@ -249,6 +251,8 @@ operator_lookup = {
"gt": (_boolean_compare, operators.le),
"ge": (_boolean_compare, operators.lt),
"eq": (_boolean_compare, operators.ne),
+ "is_distinct_from": (_boolean_compare, operators.isnot_distinct_from),
+ "isnot_distinct_from": (_boolean_compare, operators.isnot_distinct_from),
"like_op": (_boolean_compare, operators.notlike_op),
"ilike_op": (_boolean_compare, operators.notilike_op),
"notlike_op": (_boolean_compare, operators.like_op),
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index 80f08a97c..578f87c2c 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -311,6 +311,22 @@ class ColumnOperators(Operators):
"""
return self.operate(ne, other)
+ def is_distinct_from(self, other):
+ """Implement the ``IS DISTINCT FROM`` operator.
+
+
+
+ """
+ return self.operate(is_distinct_from, other)
+
+ def isnot_distinct_from(self, other):
+ """Implement the ``IS NOT DISTINCT FROM`` operator.
+
+
+
+ """
+ return self.operate(isnot_distinct_from, other)
+
def __gt__(self, other):
"""Implement the ``>`` operator.
@@ -722,6 +738,15 @@ def istrue(a):
def isfalse(a):
raise NotImplementedError()
+
+def is_distinct_from(a, b):
+ return a.is_distinct_from(b)
+
+
+def isnot_distinct_from(a, b):
+ return a.isnot_distinct_from(b)
+
+
def is_(a, b):
return a.is_(b)
@@ -931,6 +956,8 @@ _PRECEDENCE = {
eq: 5,
ne: 5,
+ is_distinct_from: 5,
+ isnot_distinct_from: 5,
gt: 5,
lt: 5,
ge: 5,
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py
index 86286a9a3..e8c4b924b 100644
--- a/test/sql/test_operators.py
+++ b/test/sql/test_operators.py
@@ -99,6 +99,18 @@ class DefaultColumnComparatorTest(fixtures.TestBase):
def test_notequals_true(self):
self._do_operate_test(operators.ne, True)
+ def test_is_distinct_from_true(self):
+ self._do_operate_test(operators.is_distinct_from, True)
+
+ def test_is_distinct_from_false(self):
+ self._do_operate_test(operators.is_distinct_from, False)
+
+ def test_is_distinct_from_null(self):
+ self._do_operate_test(operators.is_distinct_from, None)
+
+ def test_isnot_distinct_from_true(self):
+ self._do_operate_test(operators.isnot_distinct_from, True)
+
def test_is_true(self):
self._do_operate_test(operators.is_, True)