From 987581e6d2c893f4fe1c6877bd4b096f00ff63c3 Mon Sep 17 00:00:00 2001 From: Ants Aasma Date: Mon, 25 Jun 2007 18:14:40 +0000 Subject: [PATCH] fix precedence of between (ticket #621) --- lib/sqlalchemy/sql.py | 16 +++++----------- test/sql/select.py | 4 ++++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index 9bea33946e..be1ed8a699 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -33,7 +33,7 @@ __all__ = ['AbstractDialect', 'Alias', 'ClauseElement', 'ClauseParameters', 'ClauseVisitor', 'ColumnCollection', 'ColumnElement', 'Compiled', 'CompoundSelect', 'Executor', 'FromClause', 'Join', 'Select', 'Selectable', 'TableClause', 'alias', 'and_', 'asc', - 'between_', 'bindparam', 'case', 'cast', 'column', 'delete', + 'between_', 'between', 'bindparam', 'case', 'cast', 'column', 'delete', 'desc', 'distinct', 'except_', 'except_all', 'exists', 'extract', 'func', 'modifier', 'insert', 'intersect', 'intersect_all', 'join', 'literal', 'literal_column', 'not_', 'null', 'or_', 'outerjoin', 'select', @@ -62,13 +62,13 @@ PRECEDENCE = { '<':5, '>=':5, '<=':5, + 'BETWEEN':5, 'NOT':4, 'AND':3, 'OR':2, ',':-1, 'AS':-1, 'EXISTS':0, - 'BETWEEN':0, '_smallest': -1000, '_largest': 1000 } @@ -404,7 +404,7 @@ def between(ctest, cleft, cright): provides similar functionality. """ - return _BinaryExpression(ctest, and_(_literals_as_binds(cleft, type=ctest.type), _literals_as_binds(cright, type=ctest.type)), 'BETWEEN') + return _BinaryExpression(ctest, ClauseList(_literals_as_binds(cleft, type=ctest.type), _literals_as_binds(cright, type=ctest.type), operator='AND', group=False), 'BETWEEN') def between_(*args, **kwargs): """synonym for [sqlalchemy.sql#between()] (deprecated).""" @@ -1352,7 +1352,7 @@ class _CompareMixin(object): def between(self, cleft, cright): """produce a BETWEEN clause, i.e. `` BETWEEN AND ``""" - return _BinaryExpression(self, and_(self._check_literal(cleft), self._check_literal(cright)), 'BETWEEN') + return _BinaryExpression(self, ClauseList(self._check_literal(cleft), self._check_literal(cright), operator='AND', group=False), 'BETWEEN') def op(self, operator): """produce a generic operator function. @@ -1953,12 +1953,6 @@ class ClauseList(ClauseElement): clauses = [clause.copy_container() for clause in self.clauses] return ClauseList(operator=self.operator, *clauses) - def self_group(self, against=None): - if self.group: - return _Grouping(self) - else: - return self - def append(self, clause): # TODO: not sure if i like the 'group_contents' flag. need to define the difference between # a ClauseList of ClauseLists, and a "flattened" ClauseList of ClauseLists. flatten() method ? @@ -1980,7 +1974,7 @@ class ClauseList(ClauseElement): return f def self_group(self, against=None): - if self.operator != against and PRECEDENCE.get(self.operator, PRECEDENCE['_smallest']) <= PRECEDENCE.get(against, PRECEDENCE['_largest']): + if self.group and self.operator != against and PRECEDENCE.get(self.operator, PRECEDENCE['_smallest']) <= PRECEDENCE.get(against, PRECEDENCE['_largest']): return _Grouping(self) else: return self diff --git a/test/sql/select.py b/test/sql/select.py index 7ae830e6ae..10fa631f0b 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -940,6 +940,10 @@ UNION SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE "SELECT op.field FROM op WHERE NOT op.field = :op_field") self.runtest(table.select(not_(table.c.field) == 5), "SELECT op.field FROM op WHERE (NOT op.field) = :literal") + self.runtest(table.select((table.c.field == table.c.field).between(False, True)), + "SELECT op.field FROM op WHERE (op.field = op.field) BETWEEN :literal AND :literal_1") + self.runtest(table.select(between((table.c.field == table.c.field), False, True)), + "SELECT op.field FROM op WHERE (op.field = op.field) BETWEEN :literal AND :literal_1") class CRUDTest(SQLTest): def testinsert(self): -- 2.47.2