summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2017-07-27 19:36:47 +0200
committerGitHub <noreply@github.com>2017-07-27 19:36:47 +0200
commitb61d5b1991e2ca2c3450ccc334224f3d51da39dc (patch)
tree8cb9dee554eb78d43d69950dcf756d8eedac5d0d
parent14172cf4426de6c867028f1c194011c0a26e662d (diff)
Fixed #28371 -- Fixed Cast() with CharField if the max_length argument isn't provided.
Thanks Tim Graham for the review.
-rw-r--r--django/db/backends/base/operations.py2
-rw-r--r--django/db/backends/mysql/operations.py1
-rw-r--r--django/db/backends/oracle/operations.py3
-rw-r--r--django/db/backends/postgresql/operations.py2
-rw-r--r--django/db/backends/sqlite3/operations.py2
-rw-r--r--django/db/models/fields/__init__.py5
-rw-r--r--docs/releases/2.0.txt6
-rw-r--r--tests/db_functions/test_cast.py4
8 files changed, 25 insertions, 0 deletions
diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py
index effdffd6e7..495d7e910b 100644
--- a/django/db/backends/base/operations.py
+++ b/django/db/backends/base/operations.py
@@ -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
diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index 71592234aa..e4492f866f 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -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
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index 903bad3307..60fce427d7 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -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'
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
index 497a5303a2..2cc886a76d 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -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"):
diff --git a/django/db/backends/sqlite3/operations.py b/django/db/backends/sqlite3/operations.py
index f3c31ee1b9..38f7ca7b69 100644
--- a/django/db/backends/sqlite3/operations.py
+++ b/django/db/backends/sqlite3/operations.py
@@ -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
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 5963339dad..1cfd0294e1 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -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"
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index 36359e4979..87f95210ee 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -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
-------------------------------
diff --git a/tests/db_functions/test_cast.py b/tests/db_functions/test_cast.py
index bd4541bf06..e266a13db1 100644
--- a/tests/db_functions/test_cast.py
+++ b/tests/db_functions/test_cast.py
@@ -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')