Kaydet (Commit) b61d5b19 authored tarafından Mariusz Felisiak's avatar Mariusz Felisiak Kaydeden (comit) GitHub

Fixed #28371 -- Fixed Cast() with CharField if the max_length argument isn't provided.

Thanks Tim Graham for the review.
üst 14172cf4
......@@ -36,6 +36,8 @@ class BaseDatabaseOperations:
# name) to the data type to use for the Cast() function, if different from
# DatabaseWrapper.data_types.
cast_data_types = {}
# CharField data type if the max_length argument isn't provided.
cast_char_field_without_max_length = None
def __init__(self, connection):
self.connection = connection
......
......@@ -24,6 +24,7 @@ class DatabaseOperations(BaseDatabaseOperations):
'PositiveIntegerField': 'unsigned integer',
'PositiveSmallIntegerField': 'unsigned integer',
}
cast_char_field_without_max_length = 'char'
def date_extract_sql(self, lookup_type, field_name):
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
......
......@@ -49,6 +49,9 @@ BEGIN
END;
/"""
# Oracle doesn't support string without precision; use the max string size.
cast_char_field_without_max_length = 'NVARCHAR2(2000)'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_operators['difference'] = 'MINUS'
......
......@@ -5,6 +5,8 @@ from django.db.backends.base.operations import BaseDatabaseOperations
class DatabaseOperations(BaseDatabaseOperations):
cast_char_field_without_max_length = 'varchar'
def unification_cast_sql(self, output_field):
internal_type = output_field.get_internal_type()
if internal_type in ("GenericIPAddressField", "IPAddressField", "TimeField", "UUIDField"):
......
......@@ -14,6 +14,8 @@ from django.utils.duration import duration_string
class DatabaseOperations(BaseDatabaseOperations):
cast_char_field_without_max_length = 'text'
def bulk_batch_size(self, fields, objs):
"""
SQLite has a compile-time default (SQLITE_LIMIT_VARIABLE_NUMBER) of
......
......@@ -1066,6 +1066,11 @@ class CharField(Field):
else:
return []
def cast_db_type(self, connection):
if self.max_length is None:
return connection.ops.cast_char_field_without_max_length
return super().cast_db_type(connection)
def get_internal_type(self):
return "CharField"
......
......@@ -348,6 +348,12 @@ backends.
requires that the arguments to ``OF`` be columns rather than tables, set
``DatabaseFeatures.select_for_update_of_column = True``.
* Third-party database backends should add a
``DatabaseOperations.cast_char_field_without_max_length`` attribute with the
database data type that will be used in the
:class:`~django.db.models.functions.Cast` function for a ``CharField`` if the
``max_length`` argument isn't provided.
Dropped support for Oracle 11.2
-------------------------------
......
......@@ -19,6 +19,10 @@ class CastTests(TestCase):
numbers = Author.objects.annotate(cast_string=Cast('age', models.CharField(max_length=255)),)
self.assertEqual(numbers.get().cast_string, '1')
def test_cast_to_char_field_without_max_length(self):
numbers = Author.objects.annotate(cast_string=Cast('age', models.CharField()))
self.assertEqual(numbers.get().cast_string, '1')
# Silence "Truncated incorrect CHAR(1) value: 'Bob'".
@ignore_warnings(module='django.db.backends.mysql.base')
@skipUnlessDBFeature('supports_cast_with_precision')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment