From: Mike Bayer Date: Sat, 8 Sep 2007 20:28:26 +0000 (+0000) Subject: - adjusted operator precedence of NOT to match '==' and others, so that X-Git-Tag: rel_0_4beta6~31 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8c14291b6d634604a6da3bbc9c965e0de3084933;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - adjusted operator precedence of NOT to match '==' and others, so that ~(x y) produces NOT (x y), which is better compatible with MySQL. [ticket:764]. this doesn't apply to "~(x==y)" as it does in 0.3 since ~(x==y) compiles to "x != y", but still applies to operators like BETWEEN. --- diff --git a/CHANGES b/CHANGES index fe43273003..efcc57e70a 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,11 @@ CHANGES and can be used to determine correct shard id (since execute() doesn't take an instance) +- adjusted operator precedence of NOT to match '==' and others, so that + ~(x y) produces NOT (x y), which is better compatible with MySQL. + [ticket:764]. this doesn't apply to "~(x==y)" as it does in 0.3 since ~(x==y) + compiles to "x != y", but still applies to operators like BETWEEN. + - other tickets: [ticket:768] 0.4.0beta5 @@ -65,7 +70,7 @@ CHANGES - postgres reflects tables with autoincrement=False for primary key columns which have no defaults. - + - postgres no longer wraps executemany() with individual execute() calls, instead favoring performance. "rowcount"/"concurrency" checks with deleted items (which use executemany) diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index b1a5bf96f1..f7514fec9d 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -1159,7 +1159,7 @@ PRECEDENCE = { operators.le:5, operators.between_op:5, operators.distinct_op:5, - operators.inv:4, + operators.inv:5, operators.and_:3, operators.or_:2, operators.comma_op:-1, diff --git a/test/sql/select.py b/test/sql/select.py index 6a81310460..1114f17358 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -339,7 +339,6 @@ sq.myothertable_othername AS sq_myothertable_othername FROM (" + sqstring + ") A ) def testoperators(self): - # exercise arithmetic operators for (py_op, sql_op) in ((operator.add, '+'), (operator.mul, '*'), (operator.sub, '-'), (operator.div, '/'), @@ -389,6 +388,11 @@ sq.myothertable_othername AS sq_myothertable_othername FROM (" + sqstring + ") A "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid != :mytable_myid AND mytable.name != :mytable_name" ) + self.assert_compile( + table1.select((table1.c.myid != 12) & ~(table1.c.name.between('jack','john'))), + "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid != :mytable_myid AND NOT (mytable.name BETWEEN :mytable_name AND :mytable_name_1)" + ) + self.assert_compile( table1.select((table1.c.myid != 12) & ~and_(table1.c.name=='john', table1.c.name=='ed', table1.c.name=='fred')), "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid != :mytable_myid AND NOT (mytable.name = :mytable_name AND mytable.name = :mytable_name_1 AND mytable.name = :mytable_name_2)" @@ -1083,6 +1087,10 @@ UNION SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE "SELECT op.field FROM op WHERE :op_field + op.field IN (:literal, :literal_1)") self.assert_compile(table.select(not_(and_(table.c.field == 5, table.c.field == 7))), "SELECT op.field FROM op WHERE NOT (op.field = :op_field AND op.field = :op_field_1)") + self.assert_compile(table.select(not_(table.c.field == 5)), + "SELECT op.field FROM op WHERE op.field != :op_field") + self.assert_compile(table.select(not_(table.c.field.between(5, 6))), + "SELECT op.field FROM op WHERE NOT (op.field BETWEEN :op_field AND :op_field_1)") self.assert_compile(table.select(not_(table.c.field) == 5), "SELECT op.field FROM op WHERE (NOT op.field) = :literal") self.assert_compile(table.select((table.c.field == table.c.field).between(False, True)),