Refs #28459 -- Improved performance of loading DecimalField on SQLite.

This commit is contained in:
Sergey Fedoseev 2017-12-27 04:12:37 +05:00 committed by Tim Graham
parent 4c599ece57
commit d0f569b350
3 changed files with 16 additions and 25 deletions

View File

@ -39,7 +39,6 @@ Database.register_converter("date", decoder(parse_date))
Database.register_converter("datetime", decoder(parse_datetime))
Database.register_converter("timestamp", decoder(parse_datetime))
Database.register_converter("TIMESTAMP", decoder(parse_datetime))
Database.register_converter("decimal", decoder(decimal.Decimal))
Database.register_adapter(decimal.Decimal, backend_utils.rev_typecast_decimal)

View File

@ -214,7 +214,7 @@ class DatabaseOperations(BaseDatabaseOperations):
elif internal_type == 'TimeField':
converters.append(self.convert_timefield_value)
elif internal_type == 'DecimalField':
converters.append(self.convert_decimalfield_value)
converters.append(self.get_decimalfield_converter(expression))
elif internal_type == 'UUIDField':
converters.append(self.convert_uuidfield_value)
elif internal_type in ('NullBooleanField', 'BooleanField'):
@ -241,15 +241,21 @@ class DatabaseOperations(BaseDatabaseOperations):
value = parse_time(value)
return value
def convert_decimalfield_value(self, value, expression, connection):
if value is not None:
if not isinstance(expression, Col):
# SQLite stores only 15 significant digits. Digits coming from
# float inaccuracy must be removed.
return decimal.Context(prec=15).create_decimal_from_float(value)
value = expression.output_field.format_number(value)
return decimal.Decimal(value)
return value
def get_decimalfield_converter(self, expression):
# SQLite stores only 15 significant digits. Digits coming from
# float inaccuracy must be removed.
create_decimal = decimal.Context(prec=15).create_decimal_from_float
if isinstance(expression, Col):
quantize_value = decimal.Decimal(1).scaleb(-expression.output_field.decimal_places)
def converter(value, expression, connection):
if value is not None:
return create_decimal(value).quantize(quantize_value, context=expression.output_field.context)
else:
def converter(value, expression, connection):
if value is not None:
return create_decimal(value)
return converter
def convert_uuidfield_value(self, value, expression, connection):
if value is not None:

View File

@ -1560,20 +1560,6 @@ class DecimalField(Field):
params={'value': value},
)
def format_number(self, value):
"""
Format a number into a string with the requisite number of digits and
decimal places.
"""
# Method moved to django.db.backends.utils.
#
# It is preserved because it is used by the oracle backend
# (django.db.backends.oracle.query), and also for
# backwards-compatibility with any external code which may have used
# this method.
from django.db.backends import utils
return utils.format_number(value, self.max_digits, self.decimal_places)
def get_db_prep_save(self, value, connection):
return connection.ops.adapt_decimalfield_value(self.to_python(value), self.max_digits, self.decimal_places)