Introspected alternate SQLite FK definitions

This commit is contained in:
Claude Paroz 2015-01-10 16:48:07 +01:00
parent ffca9b49d4
commit 7289d01973
2 changed files with 21 additions and 2 deletions

View File

@ -106,16 +106,23 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
# Walk through and look for references to other tables. SQLite doesn't # Walk through and look for references to other tables. SQLite doesn't
# really have enforced references, but since it echoes out the SQL used # really have enforced references, but since it echoes out the SQL used
# to create the table we can look for REFERENCES statements used there. # to create the table we can look for REFERENCES statements used there.
field_names = []
for field_index, field_desc in enumerate(results.split(',')): for field_index, field_desc in enumerate(results.split(',')):
field_desc = field_desc.strip() field_desc = field_desc.strip()
if field_desc.startswith("UNIQUE"): if field_desc.startswith("UNIQUE"):
continue continue
m = re.search('references (.*) \(["|](.*)["|]\)', field_desc, re.I) field_names.append(field_desc.split()[0].strip('"'))
m = re.search('references (\S*) ?\(["|]?(.*)["|]?\)', field_desc, re.I)
if not m: if not m:
continue continue
table, column = [s.strip('"') for s in m.groups()] table, column = [s.strip('"') for s in m.groups()]
if field_desc.startswith("FOREIGN KEY"):
# Find index of the target FK field
m = re.match('FOREIGN KEY\(([^\)]*)\).*', field_desc, re.I)
fkey_field = m.groups()[0].strip('"')
field_index = field_names.index(fkey_field)
cursor.execute("SELECT sql FROM sqlite_master WHERE tbl_name = %s", [table]) cursor.execute("SELECT sql FROM sqlite_master WHERE tbl_name = %s", [table])
result = cursor.fetchall()[0] result = cursor.fetchall()[0]

View File

@ -1,8 +1,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from unittest import skipUnless
from django.db import connection from django.db import connection
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
from django.test import TransactionTestCase, skipUnlessDBFeature from django.test import TransactionTestCase, mock, skipUnlessDBFeature
from .models import Reporter, Article from .models import Reporter, Article
@ -119,6 +121,16 @@ class IntrospectionTests(TransactionTestCase):
self.assertEqual(relations, {3: (0, Reporter._meta.db_table), self.assertEqual(relations, {3: (0, Reporter._meta.db_table),
4: (0, Article._meta.db_table)}) 4: (0, Article._meta.db_table)})
@skipUnless(connection.vendor == 'sqlite', "This is an sqlite-specific issue")
def test_get_relations_alt_format(self):
"""With SQLite, foreign keys can be added with different syntaxes."""
with connection.cursor() as cursor:
cursor.fetchone = mock.Mock(return_value=[
"CREATE TABLE track(id, art INTEGER, FOREIGN KEY(art) REFERENCES %s(id));" % Article._meta.db_table
])
relations = connection.introspection.get_relations(cursor, 'mocked_table')
self.assertEqual(relations, {1: (0, Article._meta.db_table)})
@skipUnlessDBFeature('can_introspect_foreign_keys') @skipUnlessDBFeature('can_introspect_foreign_keys')
def test_get_key_columns(self): def test_get_key_columns(self):
with connection.cursor() as cursor: with connection.cursor() as cursor: