diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-10-04 11:21:35 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-10-04 12:04:11 -0400 |
commit | 81f99c1b143d33e275afef7472750b5174294e80 (patch) | |
tree | e0fd0e97a62a8632f80adfca8989d1052fc06b09 /test/sql/test_operators.py | |
parent | 71e463506217e3acc379a3f459e68a81792a0aac (diff) | |
download | sqlalchemy-81f99c1b143d33e275afef7472750b5174294e80.tar.gz |
repair any_() / all_() "implicit flip" behavior for None
Fixed an inconsistency in the any_() / all_() functions / methods where the
special behavior these functions have of "flipping" the expression such
that the "ANY" / "ALL" expression is always on the right side would not
function if the comparison were against the None value, that is,
"column.any_() == None" should produce the same SQL expression as "null()
== column.any_()". Added more docs to clarify this as well, plus mentions
that any_() / all_() generally supersede the ARRAY version "any()" /
"all()".
Fixes: #7140
Change-Id: Ia5d55414ba40eb3fbda3598931fdd24c9b4a4411
Diffstat (limited to 'test/sql/test_operators.py')
-rw-r--r-- | test/sql/test_operators.py | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index b2ba7ae73..79aa4d794 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -76,7 +76,11 @@ class LoopOperate(operators.ColumnOperators): return op -class DefaultColumnComparatorTest(fixtures.TestBase): +class DefaultColumnComparatorTest( + testing.AssertsCompiledSQL, fixtures.TestBase +): + dialect = "default_enhanced" + @testing.combinations((operators.desc_op, desc), (operators.asc_op, asc)) def test_scalar(self, operator, compare_to): left = column("left") @@ -159,6 +163,32 @@ class DefaultColumnComparatorTest(fixtures.TestBase): loop = LoopOperate() is_(operator(loop, *arg), operator) + def test_null_true_false_is_sanity_checks(self): + + d = default.DefaultDialect() + d.supports_native_boolean = True + + self.assert_compile( + column("q") == None, + "q IS NULL", + ) + self.assert_compile( + column("q") == null(), + "q IS NULL", + ) + # IS coercion only occurs from left to right (just discovered this) + self.assert_compile( + null() == column("q"), + "NULL = q", + ) + self.assert_compile(column("q") == true(), "q = true", dialect=d) + self.assert_compile(true() == column("q"), "true = q", dialect=d) + self.assert_compile(column("q") == True, "q = true", dialect=d) + + # this comes out reversed; no choice, column.__eq__() is called + # and we don't get to know it's "reverse" + self.assert_compile(True == column("q"), "q = true", dialect=d) + def test_no_getitem(self): assert_raises_message( NotImplementedError, @@ -3392,6 +3422,24 @@ class AnyAllTest(fixtures.TestBase, testing.AssertsCompiledSQL): ) return t + @testing.combinations( + lambda col: any_(col) == None, + lambda col: col.any_() == None, + lambda col: any_(col) == null(), + lambda col: col.any_() == null(), + lambda col: null() == any_(col), + lambda col: null() == col.any_(), + lambda col: None == any_(col), + lambda col: None == col.any_(), + argnames="expr", + ) + @testing.combinations("int", "array", argnames="datatype") + def test_any_generic_null(self, datatype, expr, t_fixture): + + col = t_fixture.c.data if datatype == "int" else t_fixture.c.arrval + + self.assert_compile(expr(col), "NULL = ANY (tab1.%s)" % col.name) + def test_any_array(self, t_fixture): t = t_fixture |