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

This commit is contained in:
Mariusz Felisiak 2017-01-03 07:13:12 +01:00 committed by Tim Graham
parent 27267afc41
commit fd2f7e4767
2 changed files with 12 additions and 6 deletions

View File

@ -199,11 +199,12 @@ class DatabaseOperations(BaseDatabaseOperations):
return "VALUES " + values_sql return "VALUES " + values_sql
def combine_expression(self, connector, sub_expressions): def combine_expression(self, connector, sub_expressions):
"""
MySQL requires special cases for ^ operators in query expressions
"""
if connector == '^': if connector == '^':
return 'POW(%s)' % ','.join(sub_expressions) 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) return super(DatabaseOperations, self).combine_expression(connector, sub_expressions)
def get_db_converters(self, expression): def get_db_converters(self, expression):

View File

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