Jelajahi Sumber

Fixed #26781 -- Made table name case change a noop on SQLite.

SQLite disgresses from the SQL standard by ignoring case of quoted identifiers.

Thanks to laozzzi for the report and Tim for the review.
Simon Charette 8 tahun lalu
induk
melakukan
c2e62fd1ae

+ 4 - 0
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
 

+ 3 - 1
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),

+ 3 - 0
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):
         """

+ 1 - 0
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):

+ 9 - 0
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"