diff options
| author | Federico Caselli <cfederico87@gmail.com> | 2020-01-23 17:51:38 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-01-25 18:03:48 -0500 |
| commit | 1de64504d8e68e2c0d14669c7638cf6f6d74973f (patch) | |
| tree | bcb2f19fe89efc629408c4576c355f3fe998578b /test/sql/test_operators.py | |
| parent | 411637fbcf679f36448f1b094afef375158df15e (diff) | |
| download | sqlalchemy-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.py | 63 |
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") |
