Fixed #28816 -- Prevented silencing data loss when decreasing CharField.max_length on PostgreSQL.
This commit is contained in:
parent
519016e5f2
commit
1378d665a1
|
@ -6,8 +6,6 @@ from django.db.backends.ddl_references import IndexColumns
|
||||||
|
|
||||||
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
|
|
||||||
sql_alter_column_type = "ALTER COLUMN %(column)s TYPE %(type)s USING %(column)s::%(type)s"
|
|
||||||
|
|
||||||
sql_create_sequence = "CREATE SEQUENCE %(sequence)s"
|
sql_create_sequence = "CREATE SEQUENCE %(sequence)s"
|
||||||
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
||||||
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
|
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
|
||||||
|
@ -36,6 +34,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
output.append(like_index_statement)
|
output.append(like_index_statement)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def _field_data_type(self, field):
|
||||||
|
if field.is_relation:
|
||||||
|
return field.rel_db_type(self.connection)
|
||||||
|
return self.connection.data_types[field.get_internal_type()]
|
||||||
|
|
||||||
def _create_like_index_sql(self, model, field):
|
def _create_like_index_sql(self, model, field):
|
||||||
"""
|
"""
|
||||||
Return the statement to create an index with varchar operator pattern
|
Return the statement to create an index with varchar operator pattern
|
||||||
|
@ -59,7 +62,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _alter_column_type_sql(self, model, old_field, new_field, new_type):
|
def _alter_column_type_sql(self, model, old_field, new_field, new_type):
|
||||||
"""Make ALTER TYPE with SERIAL make sense."""
|
self.sql_alter_column_type = 'ALTER COLUMN %(column)s TYPE %(type)s'
|
||||||
|
# Cast when data type changed.
|
||||||
|
if self._field_data_type(old_field) != self._field_data_type(new_field):
|
||||||
|
self.sql_alter_column_type += ' USING %(column)s::%(type)s'
|
||||||
|
# Make ALTER TYPE with SERIAL make sense.
|
||||||
table = model._meta.db_table
|
table = model._meta.db_table
|
||||||
if new_type.lower() in ("serial", "bigserial"):
|
if new_type.lower() in ("serial", "bigserial"):
|
||||||
column = new_field.column
|
column = new_field.column
|
||||||
|
|
|
@ -21,6 +21,7 @@ from django.db.models.fields.related import (
|
||||||
)
|
)
|
||||||
from django.db.models.indexes import Index
|
from django.db.models.indexes import Index
|
||||||
from django.db.transaction import TransactionManagementError, atomic
|
from django.db.transaction import TransactionManagementError, atomic
|
||||||
|
from django.db.utils import DataError
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature,
|
TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature,
|
||||||
)
|
)
|
||||||
|
@ -803,6 +804,21 @@ class SchemaTests(TransactionTestCase):
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.alter_field(Author, old_field, new_field, strict=True)
|
editor.alter_field(Author, old_field, new_field, strict=True)
|
||||||
|
|
||||||
|
@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific')
|
||||||
|
def test_alter_char_field_decrease_length(self):
|
||||||
|
# Create the table.
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.create_model(Author)
|
||||||
|
Author.objects.create(name='x' * 255)
|
||||||
|
# Change max_length of CharField.
|
||||||
|
old_field = Author._meta.get_field('name')
|
||||||
|
new_field = CharField(max_length=254)
|
||||||
|
new_field.set_attributes_from_name('name')
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
msg = 'value too long for type character varying(254)'
|
||||||
|
with self.assertRaisesMessage(DataError, msg):
|
||||||
|
editor.alter_field(Author, old_field, new_field, strict=True)
|
||||||
|
|
||||||
def test_alter_textfield_to_null(self):
|
def test_alter_textfield_to_null(self):
|
||||||
"""
|
"""
|
||||||
#24307 - Should skip an alter statement on databases with
|
#24307 - Should skip an alter statement on databases with
|
||||||
|
|
Loading…
Reference in New Issue