diff options
author | Sebastian Bank <sebastian.bank@uni-leipzig.de> | 2016-03-11 19:05:52 +0100 |
---|---|---|
committer | Sebastian Bank <sebastian.bank@uni-leipzig.de> | 2016-03-13 22:08:45 +0100 |
commit | 19e5d667e18ff3c3ebcb399f03e30cabe9f8a09f (patch) | |
tree | 45b72babe26e7809c83b8ab9bc74e12b17ba21c1 | |
parent | f61194cb865db8b29cc65e47782bb72e54b14ada (diff) | |
download | sqlalchemy-19e5d667e18ff3c3ebcb399f03e30cabe9f8a09f.tar.gz |
add IS (NOT) DISTINCT FROM operator
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/default_comparator.py | 12 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/operators.py | 27 | ||||
-rw-r--r-- | test/sql/test_operators.py | 12 |
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) |