summaryrefslogtreecommitdiff
path: root/test/sql/test_operators.py
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2020-01-23 17:51:38 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-01-25 18:03:48 -0500
commit1de64504d8e68e2c0d14669c7638cf6f6d74973f (patch)
treebcb2f19fe89efc629408c4576c355f3fe998578b /test/sql/test_operators.py
parent411637fbcf679f36448f1b094afef375158df15e (diff)
downloadsqlalchemy-1de64504d8e68e2c0d14669c7638cf6f6d74973f.tar.gz
Deprecate empty or_() and and_()
Creating an :func:`.and_` or :func:`.or_` construct with no arguments or empty ``*args`` will now emit a deprecation warning, as the SQL produced is a no-op (i.e. it renders as a blank string). This behavior is considered to be non-intuitive, so for empty or possibly empty :func:`.and_` or :func:`.or_` constructs, an appropriate default boolean should be included, such as ``and_(True, *args)`` or ``or_(False, *args)``. As has been the case for many major versions of SQLAlchemy, these particular boolean values will not render if the ``*args`` portion is non-empty. As there are some internal cases where an empty and_() construct is used in order to build an optional WHERE expression, a private utility function is added to suit this use case. Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com> Fixes: #5054 Closes: #5062 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5062 Pull-request-sha: 5ca2f27281977d74e390148c0fb8deaa0e0e4ad9 Change-Id: I599b9c8befa64d9a59a35ad7dd84ff400e3aa647
Diffstat (limited to 'test/sql/test_operators.py')
-rw-r--r--test/sql/test_operators.py63
1 files changed, 59 insertions, 4 deletions
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py
index a90b03b38..d3afc2dee 100644
--- a/test/sql/test_operators.py
+++ b/test/sql/test_operators.py
@@ -42,6 +42,7 @@ from sqlalchemy.sql import sqltypes
from sqlalchemy.sql import table
from sqlalchemy.sql import true
from sqlalchemy.sql.elements import BindParameter
+from sqlalchemy.sql.elements import BooleanClauseList
from sqlalchemy.sql.elements import Label
from sqlalchemy.sql.expression import BinaryExpression
from sqlalchemy.sql.expression import ClauseList
@@ -51,6 +52,7 @@ from sqlalchemy.sql.expression import tuple_
from sqlalchemy.sql.expression import UnaryExpression
from sqlalchemy.sql.expression import union
from sqlalchemy.testing import assert_raises_message
+from sqlalchemy.testing import combinations
from sqlalchemy.testing import eq_
from sqlalchemy.testing import expect_warnings
from sqlalchemy.testing import fixtures
@@ -1062,14 +1064,67 @@ class ConjunctionTest(fixtures.TestBase, testing.AssertsCompiledSQL):
__dialect__ = default.DefaultDialect(supports_native_boolean=True)
- def test_one(self):
+ def test_single_bool_one(self):
self.assert_compile(~and_(true()), "false")
- def test_two(self):
+ def test_single_bool_two(self):
+ self.assert_compile(~and_(True), "false")
+
+ def test_single_bool_three(self):
self.assert_compile(or_(~and_(true())), "false")
- def test_three(self):
- self.assert_compile(or_(and_()), "")
+ def test_single_bool_four(self):
+ self.assert_compile(~or_(false()), "true")
+
+ def test_single_bool_five(self):
+ self.assert_compile(~or_(False), "true")
+
+ def test_single_bool_six(self):
+ self.assert_compile(and_(~or_(false())), "true")
+
+ def test_single_bool_seven(self):
+ self.assert_compile(and_(True), "true")
+
+ def test_single_bool_eight(self):
+ self.assert_compile(or_(False), "false")
+
+ def test_single_bool_nine(self):
+ self.assert_compile(
+ and_(True),
+ "1 = 1",
+ dialect=default.DefaultDialect(supports_native_boolean=False),
+ )
+
+ def test_single_bool_ten(self):
+ self.assert_compile(
+ or_(False),
+ "0 = 1",
+ dialect=default.DefaultDialect(supports_native_boolean=False),
+ )
+
+ @combinations((and_, "and_", "True"), (or_, "or_", "False"))
+ def test_empty_clauses(self, op, str_op, str_continue):
+ # these warning classes will change to ArgumentError when the
+ # deprecated behavior is disabled
+ assert_raises_message(
+ exc.SADeprecationWarning,
+ r"Invoking %(str_op)s\(\) without arguments is deprecated, and "
+ r"will be disallowed in a future release. For an empty "
+ r"%(str_op)s\(\) construct, use "
+ r"%(str_op)s\(%(str_continue)s, \*args\)\."
+ % {"str_op": str_op, "str_continue": str_continue},
+ op,
+ )
+
+ def test_empty_and_raw(self):
+ self.assert_compile(
+ BooleanClauseList._construct_raw(operators.and_), ""
+ )
+
+ def test_empty_or_raw(self):
+ self.assert_compile(
+ BooleanClauseList._construct_raw(operators.and_), ""
+ )
def test_four(self):
x = column("x")