Made table_names() output sorted.

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.
This commit is contained in:
Anssi Kääriäinen 2012-04-29 02:11:55 +03:00
parent c2055ee161
commit 527cce80dc
6 changed files with 22 additions and 8 deletions

View File

@ -42,7 +42,7 @@ class Command(NoArgsCommand):
yield 'from %s import models' % self.db_module yield 'from %s import models' % self.db_module
yield '' yield ''
known_models = [] 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) yield 'class %s(models.Model):' % table2model(table_name)
known_models.append(table2model(table_name)) known_models.append(table2model(table_name))
try: try:

View File

@ -63,7 +63,7 @@ def sql_delete(app, style, connection):
# Figure out which tables already exist # Figure out which tables already exist
if cursor: if cursor:
table_names = connection.introspection.get_table_list(cursor) table_names = connection.introspection.table_names(cursor)
else: else:
table_names = [] table_names = []

View File

@ -898,10 +898,23 @@ class BaseDatabaseIntrospection(object):
""" """
return name return name
def table_names(self): def table_names(self, cursor=None):
"Returns a list of names of all tables that exist in the database." """
cursor = self.connection.cursor() Returns a list of names of all tables that exist in the database.
return self.get_table_list(cursor) 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): def django_table_names(self, only_existing=False):
""" """

View File

@ -454,7 +454,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
""" """
cursor = self.cursor() cursor = self.cursor()
if table_names is None: 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: for table_name in table_names:
primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
if not primary_key_column_name: if not primary_key_column_name:

View File

@ -295,7 +295,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
""" """
cursor = self.cursor() cursor = self.cursor()
if table_names is None: 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: for table_name in table_names:
primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
if not primary_key_column_name: if not primary_key_column_name:

View File

@ -40,6 +40,7 @@ class IntrospectionTests(TestCase):
def test_table_names(self): def test_table_names(self):
tl = connection.introspection.table_names() tl = connection.introspection.table_names()
self.assertEqual(tl, sorted(tl))
self.assertTrue(Reporter._meta.db_table in tl, self.assertTrue(Reporter._meta.db_table in tl,
"'%s' isn't in table_list()." % Reporter._meta.db_table) "'%s' isn't in table_list()." % Reporter._meta.db_table)
self.assertTrue(Article._meta.db_table in tl, self.assertTrue(Article._meta.db_table in tl,