summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/db/backends/sqlite3/introspection.py30
-rw-r--r--django/db/backends/sqlite3/schema.py27
2 files changed, 40 insertions, 17 deletions
diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py
index 0518641344..de6d6da465 100644
--- a/django/db/backends/sqlite3/introspection.py
+++ b/django/db/backends/sqlite3/introspection.py
@@ -239,6 +239,22 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
'pk': field[5], # undocumented
} for field in cursor.fetchall()]
+ def _get_foreign_key_constraints(self, cursor, table_name):
+ constraints = {}
+ cursor.execute('PRAGMA foreign_key_list(%s)' % self.connection.ops.quote_name(table_name))
+ for row in cursor.fetchall():
+ # Remaining on_update/on_delete/match values are of no interest.
+ id_, _, table, from_, to = row[:5]
+ constraints['fk_%d' % id_] = {
+ 'columns': [from_],
+ 'primary_key': False,
+ 'unique': False,
+ 'foreign_key': (table, to),
+ 'check': False,
+ 'index': False,
+ }
+ return constraints
+
def get_constraints(self, cursor, table_name):
"""
Retrieve any constraints or keys (unique, pk, fk, check, index) across
@@ -293,17 +309,5 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
"check": False,
"index": False,
}
- # Get foreign keys
- cursor.execute('PRAGMA foreign_key_list(%s)' % self.connection.ops.quote_name(table_name))
- for row in cursor.fetchall():
- # Remaining on_update/on_delete/match values are of no interest here
- id_, seq, table, from_, to = row[:5]
- constraints['fk_%d' % id_] = {
- 'columns': [from_],
- 'primary_key': False,
- 'unique': False,
- 'foreign_key': (table, to),
- 'check': False,
- 'index': False,
- }
+ constraints.update(self._get_foreign_key_constraints(cursor, table_name))
return constraints
diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py
index 8c427bee45..add05843c3 100644
--- a/django/db/backends/sqlite3/schema.py
+++ b/django/db/backends/sqlite3/schema.py
@@ -61,8 +61,27 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
else:
raise ValueError("Cannot quote parameter value %r of type %s" % (value, type(value)))
+ def _is_referenced_by_fk_constraint(self, table_name, column_name=None, ignore_self=False):
+ """
+ Return whether or not the provided table name is referenced by another
+ one. If `column_name` is specified, only references pointing to that
+ column are considered. If `ignore_self` is True, self-referential
+ constraints are ignored.
+ """
+ with self.connection.cursor() as cursor:
+ for other_table in self.connection.introspection.get_table_list(cursor):
+ if ignore_self and other_table.name == table_name:
+ continue
+ constraints = self.connection.introspection._get_foreign_key_constraints(cursor, other_table.name)
+ for constraint in constraints.values():
+ constraint_table, constraint_column = constraint['foreign_key']
+ if (constraint_table == table_name and
+ (column_name is None or constraint_column == column_name)):
+ return True
+ return False
+
def alter_db_table(self, model, old_db_table, new_db_table, disable_constraints=True):
- if model._meta.related_objects and disable_constraints:
+ if disable_constraints and self._is_referenced_by_fk_constraint(old_db_table):
if self.connection.in_atomic_block:
raise NotSupportedError((
'Renaming the %r table while in a transaction is not '
@@ -77,8 +96,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
def alter_field(self, model, old_field, new_field, strict=False):
old_field_name = old_field.name
+ table_name = model._meta.db_table
+ _, old_column_name = old_field.get_attname_column()
if (new_field.name != old_field_name and
- any(r.field_name == old_field.name for r in model._meta.related_objects)):
+ self._is_referenced_by_fk_constraint(table_name, old_column_name, ignore_self=True)):
if self.connection.in_atomic_block:
raise NotSupportedError((
'Renaming the %r.%r column while in a transaction is not '
@@ -93,9 +114,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
with self.connection.cursor() as cursor:
schema_version = cursor.execute('PRAGMA schema_version').fetchone()[0]
cursor.execute('PRAGMA writable_schema = 1')
- table_name = model._meta.db_table
references_template = ' REFERENCES "%s" ("%%s") ' % table_name
- old_column_name = old_field.get_attname_column()[1]
new_column_name = new_field.get_attname_column()[1]
search = references_template % old_column_name
replacement = references_template % new_column_name