Skip to content

Commit

Permalink
Introspected alternate SQLite FK definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
claudep committed Jan 10, 2015
1 parent ffca9b4 commit 7289d01
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
9 changes: 8 additions & 1 deletion django/db/backends/sqlite3/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,23 @@ def get_relations(self, cursor, table_name):
# Walk through and look for references to other tables. SQLite doesn't
# really have enforced references, but since it echoes out the SQL used
# to create the table we can look for REFERENCES statements used there.
field_names = []
for field_index, field_desc in enumerate(results.split(',')):
field_desc = field_desc.strip()
if field_desc.startswith("UNIQUE"):
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:
continue

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])
result = cursor.fetchall()[0]
Expand Down
14 changes: 13 additions & 1 deletion tests/introspection/tests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from __future__ import unicode_literals

from unittest import skipUnless

from django.db import connection
from django.db.utils import DatabaseError
from django.test import TransactionTestCase, skipUnlessDBFeature
from django.test import TransactionTestCase, mock, skipUnlessDBFeature

from .models import Reporter, Article

Expand Down Expand Up @@ -119,6 +121,16 @@ def test_get_relations(self):
self.assertEqual(relations, {3: (0, Reporter._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')
def test_get_key_columns(self):
with connection.cursor() as cursor:
Expand Down

0 comments on commit 7289d01

Please sign in to comment.