From: Mike Bayer Date: Fri, 9 Sep 2011 20:03:23 +0000 (-0400) Subject: - Behavioral improvement: empty X-Git-Tag: rel_0_7_3~58 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=840aab3beacdd1fe2a000dcd761d0514035cff94;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Behavioral improvement: empty conjunctions such as and_() and or_() will be flattened in the context of an enclosing conjunction, i.e. and_(x, or_()) will produce 'X' and not 'X AND ()'. [ticket:2257]. --- diff --git a/CHANGES b/CHANGES index 644c152c4e..8e0398d89a 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,12 @@ CHANGES Does not apply to 0.6.9. -sql + - Behavioral improvement: empty + conjunctions such as and_() and or_() will be + flattened in the context of an enclosing conjunction, + i.e. and_(x, or_()) will produce 'X' and not 'X AND + ()'. [ticket:2257]. + - Fixed bug regarding calculation of "from" list for a select() element. The "from" calc is now delayed, so that if the construct uses a Column diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 829adebac0..2741a853f2 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -445,7 +445,7 @@ class SQLCompiler(engine.Compiled): s for s in (c._compiler_dispatch(self, **kwargs) for c in clauselist.clauses) - if s is not None) + if s) def visit_case(self, clause, **kwargs): x = "CASE " diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 0823137248..9e920c34f7 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -2902,6 +2902,12 @@ class BooleanClauseList(ClauseList, ColumnElement): def _select_iterable(self): return (self, ) + def self_group(self, against=None): + if not self.clauses: + return self + else: + return super(BooleanClauseList, self).self_group(against=against) + class _Tuple(ClauseList, ColumnElement): def __init__(self, *clauses, **kw): diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index 5c6d163a5e..17a3a6018b 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -702,6 +702,27 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): checkparams = {'othername_1': 'asdf', 'othername_2':'foo', 'otherid_1': 9, 'myid_1': 12} ) + def test_nested_conjunctions_short_circuit(self): + """test that empty or_(), and_() conjunctions are collapsed by + an enclosing conjunction.""" + + t = table('t', column('x')) + + self.assert_compile( + select([t]).where(and_(t.c.x==5, + or_(and_(or_(t.c.x==7))))), + "SELECT t.x FROM t WHERE t.x = :x_1 AND t.x = :x_2" + ) + self.assert_compile( + select([t]).where(and_(or_(t.c.x==12, + and_(or_(t.c.x==8))))), + "SELECT t.x FROM t WHERE t.x = :x_1 OR t.x = :x_2" + ) + self.assert_compile( + select([t]).where(and_(or_(or_(t.c.x==12), + and_(or_(), or_(and_(t.c.x==8)), and_())))), + "SELECT t.x FROM t WHERE t.x = :x_1 OR t.x = :x_2" + ) def test_distinct(self): self.assert_compile(