From 527cce80dc03b57f8654f4a5ea64a17a1b3ef7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Sun, 29 Apr 2012 02:11:55 +0300 Subject: [PATCH] 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. --- django/core/management/commands/inspectdb.py | 2 +- django/core/management/sql.py | 2 +- django/db/backends/__init__.py | 21 ++++++++++++++++---- django/db/backends/mysql/base.py | 2 +- django/db/backends/sqlite3/base.py | 2 +- tests/regressiontests/introspection/tests.py | 1 + 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py index af2da45154..10fd9bd463 100644 --- a/django/core/management/commands/inspectdb.py +++ b/django/core/management/commands/inspectdb.py @@ -42,7 +42,7 @@ class Command(NoArgsCommand): 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: diff --git a/django/core/management/sql.py b/django/core/management/sql.py index 454a3427aa..68c72b3487 100644 --- a/django/core/management/sql.py +++ b/django/core/management/sql.py @@ -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 = [] diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 0d664d452a..a85e7b984c 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -898,10 +898,23 @@ class BaseDatabaseIntrospection(object): """ 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): """ diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index 6397a0972c..1be7998c49 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -454,7 +454,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): """ 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: diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 0b19442e78..8f883e2dc3 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -295,7 +295,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): """ 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: diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py index 3bd9d60fa2..b425b6401d 100644 --- a/tests/regressiontests/introspection/tests.py +++ b/tests/regressiontests/introspection/tests.py @@ -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,