Skip to content

Commit

Permalink
Made table_names() output sorted.
Browse files Browse the repository at this point in the history
Fixed #18218 -- previously Django's introspection table_names() and
get_table_list() methods did not sort the output consistently. This
resulted in random order of inspected models.

This commit also removed all external usages of get_table_list().
table_names() should be used instead.

Thanks to claudep for patch and report.
  • Loading branch information
akaariai committed Apr 28, 2012
1 parent c2055ee commit 527cce8
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 8 deletions.
2 changes: 1 addition & 1 deletion django/core/management/commands/inspectdb.py
Expand Up @@ -42,7 +42,7 @@ def handle_inspection(self, options):
yield 'from %s import models' % self.db_module
yield ''
known_models = []
for table_name in connection.introspection.get_table_list(cursor):
for table_name in connection.introspection.table_names(cursor):
yield 'class %s(models.Model):' % table2model(table_name)
known_models.append(table2model(table_name))
try:
Expand Down
2 changes: 1 addition & 1 deletion django/core/management/sql.py
Expand Up @@ -63,7 +63,7 @@ def sql_delete(app, style, connection):

# Figure out which tables already exist
if cursor:
table_names = connection.introspection.get_table_list(cursor)
table_names = connection.introspection.table_names(cursor)
else:
table_names = []

Expand Down
21 changes: 17 additions & 4 deletions django/db/backends/__init__.py
Expand Up @@ -898,10 +898,23 @@ def table_name_converter(self, name):
"""
return name

def table_names(self):
"Returns a list of names of all tables that exist in the database."
cursor = self.connection.cursor()
return self.get_table_list(cursor)
def table_names(self, cursor=None):
"""
Returns a list of names of all tables that exist in the database.
The returned table list is sorted by Python's default sorting. We
do NOT use database's ORDER BY here to avoid subtle differences
in sorting order between databases.
"""
if cursor is None:
cursor = self.connection.cursor()
return sorted(self.get_table_list(cursor))

def get_table_list(self, cursor):
"""
Returns an unsorted list of names of all tables that exist in the
database.
"""
raise NotImplementedError

def django_table_names(self, only_existing=False):
"""
Expand Down
2 changes: 1 addition & 1 deletion django/db/backends/mysql/base.py
Expand Up @@ -454,7 +454,7 @@ def check_constraints(self, table_names=None):
"""
cursor = self.cursor()
if table_names is None:
table_names = self.introspection.get_table_list(cursor)
table_names = self.introspection.table_names(cursor)
for table_name in table_names:
primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
if not primary_key_column_name:
Expand Down
2 changes: 1 addition & 1 deletion django/db/backends/sqlite3/base.py
Expand Up @@ -295,7 +295,7 @@ def check_constraints(self, table_names=None):
"""
cursor = self.cursor()
if table_names is None:
table_names = self.introspection.get_table_list(cursor)
table_names = self.introspection.table_names(cursor)
for table_name in table_names:
primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
if not primary_key_column_name:
Expand Down
1 change: 1 addition & 0 deletions tests/regressiontests/introspection/tests.py
Expand Up @@ -40,6 +40,7 @@ class IntrospectionTests(TestCase):

def test_table_names(self):
tl = connection.introspection.table_names()
self.assertEqual(tl, sorted(tl))
self.assertTrue(Reporter._meta.db_table in tl,
"'%s' isn't in table_list()." % Reporter._meta.db_table)
self.assertTrue(Article._meta.db_table in tl,
Expand Down

0 comments on commit 527cce8

Please sign in to comment.