[3.1.x] Fixed #31735 -- Fixed migrations crash on namespaced inline FK addition on PostgreSQL.

The namespace of the constraint must be included when making the
constraint immediate.

Regression in 22ce5d0031.

Thanks Rodrigo Estevao for the report.

Backport of 2e8941b6f9 from master
This commit is contained in:
Simon Charette 2020-06-23 23:43:22 -04:00 committed by Mariusz Felisiak
parent ac0ff7d700
commit b8cb14e8a0
4 changed files with 36 additions and 1 deletions

View File

@ -466,8 +466,10 @@ class BaseDatabaseSchemaEditor:
if self.sql_create_column_inline_fk:
to_table = field.remote_field.model._meta.db_table
to_column = field.remote_field.model._meta.get_field(field.remote_field.field_name).column
namespace, _ = split_identifier(model._meta.db_table)
definition += " " + self.sql_create_column_inline_fk % {
'name': self._fk_constraint_name(model, field, constraint_suffix),
'namespace': '%s.' % self.quote_name(namespace) if namespace else '',
'column': self.quote_name(field.column),
'to_table': self.quote_name(to_table),
'to_column': self.quote_name(to_column),

View File

@ -23,7 +23,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
# transaction.
sql_create_column_inline_fk = (
'CONSTRAINT %(name)s REFERENCES %(to_table)s(%(to_column)s)%(deferrable)s'
'; SET CONSTRAINTS %(name)s IMMEDIATE'
'; SET CONSTRAINTS %(namespace)s%(name)s IMMEDIATE'
)
# Setting the constraint to IMMEDIATE runs any deferred checks to allow
# dropping it in the same transaction.

View File

@ -18,3 +18,7 @@ Bugfixes
* Reallowed, following a regression in Django 3.0, non-expressions having a
``filterable`` attribute to be used as the right-hand side in queryset
filters (:ticket:`31664`).
* Fixed a regression in Django 3.0.2 that caused a migration crash on
PostgreSQL when adding a foreign key to a model with a namespaced
``db_table`` (:ticket:`31735`).

View File

@ -3059,6 +3059,35 @@ class SchemaTests(TransactionTestCase):
student = Student.objects.create(name='Some man')
doc.students.add(student)
@isolate_apps('schema')
@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific db_table syntax.')
def test_namespaced_db_table_foreign_key_reference(self):
with connection.cursor() as cursor:
cursor.execute('CREATE SCHEMA django_schema_tests')
def delete_schema():
with connection.cursor() as cursor:
cursor.execute('DROP SCHEMA django_schema_tests CASCADE')
self.addCleanup(delete_schema)
class Author(Model):
class Meta:
app_label = 'schema'
class Book(Model):
class Meta:
app_label = 'schema'
db_table = '"django_schema_tests"."schema_book"'
author = ForeignKey(Author, CASCADE)
author.set_attributes_from_name('author')
with connection.schema_editor() as editor:
editor.create_model(Author)
editor.create_model(Book)
editor.add_field(Book, author)
def test_rename_table_renames_deferred_sql_references(self):
atomic_rename = connection.features.supports_atomic_references_rename
with connection.schema_editor(atomic=atomic_rename) as editor: