diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 91065ecc99..484b272294 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -221,6 +221,10 @@ class BaseDatabaseFeatures(object): # Defaults to False to allow third-party backends to opt-in. can_clone_databases = False + # Does the backend consider quoted identifiers with different casing to + # be equal? + ignores_quoted_identifier_case = False + def __init__(self, connection): self.connection = connection diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 2fd0d2738c..156f119c0d 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -363,7 +363,9 @@ class BaseDatabaseSchemaEditor(object): """ Renames the table a model points to. """ - if old_db_table == new_db_table: + if (old_db_table == new_db_table or + (self.connection.features.ignores_quoted_identifier_case and + old_db_table.lower() == new_db_table.lower())): return self.execute(self.sql_rename_table % { "old_table": self.quote_name(old_db_table), diff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py index ee300f3530..84e18cf9ba 100644 --- a/django/db/backends/oracle/features.py +++ b/django/db/backends/oracle/features.py @@ -40,6 +40,9 @@ class DatabaseFeatures(BaseDatabaseFeatures): # select for update with limit can be achieved on Oracle, but not with the current backend. supports_select_for_update_with_limit = False supports_temporal_subtraction = True + # Oracle doesn't ignore quoted identifiers case but the current backend + # does by uppercasing all identifiers. + ignores_quoted_identifier_case = True def introspected_boolean_field_type(self, field=None, created_separately=False): """ diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index acf20d569f..e834ec61a3 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -39,6 +39,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_sequence_reset = False can_clone_databases = True supports_temporal_subtraction = True + ignores_quoted_identifier_case = True @cached_property def uses_savepoints(self): diff --git a/tests/schema/tests.py b/tests/schema/tests.py index b0d5b407ac..8b35b77c7b 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -825,6 +825,15 @@ class SchemaTests(TransactionTestCase): author_is_fk = True self.assertTrue(author_is_fk, "No FK constraint for author_id found") + def test_alter_db_table_case(self): + # Create the table + with connection.schema_editor() as editor: + editor.create_model(Author) + # Alter the case of the table + old_table_name = Author._meta.db_table + with connection.schema_editor() as editor: + editor.alter_db_table(Author, old_table_name, old_table_name.upper()) + def test_alter_implicit_id_to_explicit(self): """ Should be able to convert an implicit "id" field to an explicit "id"