瀏覽代碼

Fixed #27681 -- Fixed binary &/| operators for negative values on MySQL.

Mariusz Felisiak 8 年之前
父節點
當前提交
fd2f7e4767
共有 2 個文件被更改,包括 12 次插入6 次删除
  1. 4 3
      django/db/backends/mysql/operations.py
  2. 8 3
      tests/expressions/tests.py

+ 4 - 3
django/db/backends/mysql/operations.py

@@ -199,11 +199,12 @@ class DatabaseOperations(BaseDatabaseOperations):
         return "VALUES " + values_sql
 
     def combine_expression(self, connector, sub_expressions):
-        """
-        MySQL requires special cases for ^ operators in query expressions
-        """
         if connector == '^':
             return 'POW(%s)' % ','.join(sub_expressions)
+        # Convert the result to a signed integer since MySQL's binary operators
+        # return an unsigned integer.
+        elif connector in ('&', '|'):
+            return 'CONVERT(%s, SIGNED)' % connector.join(sub_expressions)
         return super(DatabaseOperations, self).combine_expression(connector, sub_expressions)
 
     def get_db_converters(self, expression):

+ 8 - 3
tests/expressions/tests.py

@@ -693,8 +693,10 @@ class ExpressionsNumericTests(TestCase):
 
 
 class ExpressionOperatorTests(TestCase):
-    def setUp(self):
-        self.n = Number.objects.create(integer=42, float=15.5)
+    @classmethod
+    def setUpTestData(cls):
+        cls.n = Number.objects.create(integer=42, float=15.5)
+        cls.n1 = Number.objects.create(integer=-42, float=-15.5)
 
     def test_lefthand_addition(self):
         # LH Addition of floats and integers
@@ -737,15 +739,18 @@ class ExpressionOperatorTests(TestCase):
     def test_lefthand_bitwise_and(self):
         # LH Bitwise ands on integers
         Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitand(56))
+        Number.objects.filter(pk=self.n1.pk).update(integer=F('integer').bitand(-56))
 
         self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
+        self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -64)
         self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
 
     def test_lefthand_bitwise_or(self):
         # LH Bitwise or on integers
-        Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitor(48))
+        Number.objects.update(integer=F('integer').bitor(48))
 
         self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
+        self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -10)
         self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
 
     def test_lefthand_power(self):