Commit 58d7b84d authored by Sergey Fedoseev's avatar Sergey Fedoseev Committed by Tim Graham
Browse files

[1.7.x] Fixed #23065 -- Quoted constraint names in SQL generated by migrations.

Backport of 83cd1863 from master
parent 09b5ff64
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -646,7 +646,7 @@ class BaseDatabaseSchemaEditor(object):
            self.execute(
                self.sql_create_pk % {
                    "table": self.quote_name(model._meta.db_table),
                    "name": self._create_index_name(model, [new_field.column], suffix="_pk"),
                    "name": self.quote_name(self._create_index_name(model, [new_field.column], suffix="_pk")),
                    "columns": self.quote_name(new_field.column),
                }
            )
@@ -679,7 +679,7 @@ class BaseDatabaseSchemaEditor(object):
            self.execute(
                self.sql_create_check % {
                    "table": self.quote_name(model._meta.db_table),
                    "name": self._create_index_name(model, [new_field.column], suffix="_check"),
                    "name": self.quote_name(self._create_index_name(model, [new_field.column], suffix="_check")),
                    "column": self.quote_name(new_field.column),
                    "check": new_db_params['check'],
                }
@@ -769,7 +769,7 @@ class BaseDatabaseSchemaEditor(object):
        columns = [field.column for field in fields]
        return self.sql_create_index % {
            "table": self.quote_name(model._meta.db_table),
            "name": self._create_index_name(model, columns, suffix=suffix),
            "name": self.quote_name(self._create_index_name(model, columns, suffix=suffix)),
            "columns": ", ".join(self.quote_name(column) for column in columns),
            "extra": "",
        }
@@ -786,7 +786,7 @@ class BaseDatabaseSchemaEditor(object):

        return self.sql_create_fk % {
            "table": self.quote_name(from_table),
            "name": self._create_index_name(model, [from_column], suffix=suffix),
            "name": self.quote_name(self._create_index_name(model, [from_column], suffix=suffix)),
            "column": self.quote_name(from_column),
            "to_table": self.quote_name(to_table),
            "to_column": self.quote_name(to_column),
@@ -795,14 +795,14 @@ class BaseDatabaseSchemaEditor(object):
    def _create_unique_sql(self, model, columns):
        return self.sql_create_unique % {
            "table": self.quote_name(model._meta.db_table),
            "name": self._create_index_name(model, columns, suffix="_uniq"),
            "name": self.quote_name(self._create_index_name(model, columns, suffix="_uniq")),
            "columns": ", ".join(self.quote_name(column) for column in columns),
        }

    def _delete_constraint_sql(self, template, model, name):
        return template % {
            "table": self.quote_name(model._meta.db_table),
            "name": name,
            "name": self.quote_name(name),
        }

    def _constraint_names(self, model, column_names=None, unique=None,
+3 −0
Original line number Diff line number Diff line
@@ -55,3 +55,6 @@ Bugfixes
* Formats for Welsh (``cy``) and several Chinese locales (``zh_CN``,
  ``zh_Hans``, ``zh_Hant`` and ``zh_TW``) have been added. Formats for
  Macedonian have been fixed (trailing dot removed, :ticket:`23532`).

* Added quoting of constraint names in the SQL generated by migrations to
  prevent crash with uppercase characters in the name (:ticket:`23065`).
+50 −0
Original line number Diff line number Diff line
@@ -1040,3 +1040,53 @@ class SchemaTests(TransactionTestCase):
            DatabaseError,
            lambda: list(Thing.objects.all()),
        )

    @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
    def test_remove_constraints_capital_letters(self):
        """
        #23065 - Constraint names must be quoted if they contain capital letters.
        """
        def get_field(*args, **kwargs):
            kwargs['db_column'] = "CamelCase"
            field = kwargs.pop('field_class', IntegerField)(*args, **kwargs)
            field.set_attributes_from_name("CamelCase")
            return field

        model = Author
        field = get_field()
        table = model._meta.db_table
        column = field.column

        with connection.schema_editor() as editor:
            editor.create_model(model)
            editor.add_field(model, field)

            editor.execute(
                editor.sql_create_index % {
                    "table": editor.quote_name(table),
                    "name": editor.quote_name("CamelCaseIndex"),
                    "columns": editor.quote_name(column),
                    "extra": "",
                }
            )
            editor.alter_field(model, get_field(db_index=True), field)

            editor.execute(
                editor.sql_create_unique % {
                    "table": editor.quote_name(table),
                    "name": editor.quote_name("CamelCaseUniqConstraint"),
                    "columns": editor.quote_name(field.column),
                }
            )
            editor.alter_field(model, get_field(unique=True), field)

            editor.execute(
                editor.sql_create_fk % {
                    "table": editor.quote_name(table),
                    "name": editor.quote_name("CamelCaseFKConstraint"),
                    "column": editor.quote_name(column),
                    "to_table": editor.quote_name(table),
                    "to_column": editor.quote_name(model._meta.auto_field.column),
                }
            )
            editor.alter_field(model, get_field(Author, field_class=ForeignKey), field)