mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #28816 -- Prevented silencing data loss when decreasing CharField.max_length on PostgreSQL.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							519016e5f2
						
					
				
				
					commit
					1378d665a1
				
			| @@ -6,8 +6,6 @@ from django.db.backends.ddl_references import IndexColumns | ||||
|  | ||||
| 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_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE" | ||||
|     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) | ||||
|         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): | ||||
|         """ | ||||
|         Return the statement to create an index with varchar operator pattern | ||||
| @@ -59,7 +62,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): | ||||
|         return None | ||||
|  | ||||
|     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 | ||||
|         if new_type.lower() in ("serial", "bigserial"): | ||||
|             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.transaction import TransactionManagementError, atomic | ||||
| from django.db.utils import DataError | ||||
| from django.test import ( | ||||
|     TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature, | ||||
| ) | ||||
| @@ -803,6 +804,21 @@ class SchemaTests(TransactionTestCase): | ||||
|         with connection.schema_editor() as editor: | ||||
|             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): | ||||
|         """ | ||||
|         #24307 - Should skip an alter statement on databases with | ||||
|   | ||||
		Reference in New Issue
	
	Block a user