From b8cdc7dcc3fc6897fb2a75f90023f5c67aad327f Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 20 Sep 2014 21:34:23 +0200 Subject: [PATCH] Made get_table_list return a TableInfo named tuple --- django/db/backends/__init__.py | 20 ++++++++++--------- django/db/backends/mysql/introspection.py | 11 ++++++---- django/db/backends/oracle/introspection.py | 11 ++++++---- .../postgresql_psycopg2/introspection.py | 14 ++++++++----- django/db/backends/sqlite3/introspection.py | 10 ++++++---- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 5b3be7f86c..3420cadc47 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -23,6 +23,13 @@ from django.utils.functional import cached_property from django.utils import six from django.utils import timezone +# Structure returned by DatabaseIntrospection.get_table_list() +TableInfo = namedtuple('TableInfo', ['name', 'type']) + +# Structure returned by the DB-API cursor.description interface (PEP 249) +FieldInfo = namedtuple('FieldInfo', + 'name type_code display_size internal_size precision scale null_ok') + class BaseDatabaseWrapper(object): """ @@ -1235,11 +1242,6 @@ class BaseDatabaseOperations(object): return self.integer_field_ranges[internal_type] -# Structure returned by the DB-API cursor.description interface (PEP 249) -FieldInfo = namedtuple('FieldInfo', - 'name type_code display_size internal_size precision scale null_ok') - - class BaseDatabaseIntrospection(object): """ This class encapsulates all backend-specific introspection utilities @@ -1281,13 +1283,13 @@ class BaseDatabaseIntrospection(object): """ if cursor is None: with self.connection.cursor() as cursor: - return sorted(self.get_table_list(cursor)) - return sorted(self.get_table_list(cursor)) + return sorted([ti.name for ti in self.get_table_list(cursor) if ti.type == 't']) + return sorted([ti.name for ti in self.get_table_list(cursor) if ti.type == 't']) def get_table_list(self, cursor): """ - Returns an unsorted list of names of all tables that exist in the - database. + Returns an unsorted list of TableInfo named tuples of all tables and + views that exist in the database. """ raise NotImplementedError('subclasses of BaseDatabaseIntrospection may require a get_table_list() method') diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py index 9b1a9a319b..8b7ff3c1e5 100644 --- a/django/db/backends/mysql/introspection.py +++ b/django/db/backends/mysql/introspection.py @@ -1,7 +1,7 @@ import re from .base import FIELD_TYPE from django.utils.datastructures import OrderedSet -from django.db.backends import BaseDatabaseIntrospection, FieldInfo +from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo from django.utils.encoding import force_text @@ -33,9 +33,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): } def get_table_list(self, cursor): - "Returns a list of table names in the current database." - cursor.execute("SHOW TABLES") - return [row[0] for row in cursor.fetchall()] + """ + Returns a list of table and view names in the current database. + """ + cursor.execute("SHOW FULL TABLES") + return [TableInfo(row[0], {'BASE TABLE': 't', 'VIEW': 'v'}.get(row[1])) + for row in cursor.fetchall()] def get_table_description(self, cursor, table_name): """ diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py index c89ceb0ebd..37ed7e1f00 100644 --- a/django/db/backends/oracle/introspection.py +++ b/django/db/backends/oracle/introspection.py @@ -2,7 +2,7 @@ import re import cx_Oracle -from django.db.backends import BaseDatabaseIntrospection, FieldInfo +from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo from django.utils.encoding import force_text foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") @@ -48,9 +48,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): return super(DatabaseIntrospection, self).get_field_type(data_type, description) def get_table_list(self, cursor): - "Returns a list of table names in the current database." - cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") - return [row[0].lower() for row in cursor.fetchall()] + """ + Returns a list of table and view names in the current database. + """ + cursor.execute("SELECT TABLE_NAME, 't' FROM USER_TABLES UNION ALL " + "SELECT VIEW_NAME, 'v' FROM USER_VIEWS") + return [TableInfo(row[0].lower(), row[1]) for row in cursor.fetchall()] def get_table_description(self, cursor, table_name): "Returns a description of the table, with the DB-API cursor.description interface." diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py index a38a13ac5c..ca1cb961c0 100644 --- a/django/db/backends/postgresql_psycopg2/introspection.py +++ b/django/db/backends/postgresql_psycopg2/introspection.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from django.db.backends import BaseDatabaseIntrospection, FieldInfo +from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo from django.utils.encoding import force_text @@ -29,15 +29,19 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ignored_tables = [] def get_table_list(self, cursor): - "Returns a list of table names in the current database." + """ + Returns a list of table and view names in the current database. + """ cursor.execute(""" - SELECT c.relname + SELECT c.relname, c.relkind FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind IN ('r', 'v', '') + WHERE c.relkind IN ('r', 'v') AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_catalog.pg_table_is_visible(c.oid)""") - return [row[0] for row in cursor.fetchall() if row[0] not in self.ignored_tables] + return [TableInfo(row[0], {'r':'t', 'v': 'v'}.get(row[1])) + for row in cursor.fetchall() + if row[0] not in self.ignored_tables] def get_table_description(self, cursor, table_name): "Returns a description of the table, with the DB-API cursor.description interface." diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py index 0d7c36a40c..eb80b32c8b 100644 --- a/django/db/backends/sqlite3/introspection.py +++ b/django/db/backends/sqlite3/introspection.py @@ -1,6 +1,6 @@ import re -from django.db.backends import BaseDatabaseIntrospection, FieldInfo +from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$') @@ -54,14 +54,16 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): data_types_reverse = FlexibleFieldLookupDict() def get_table_list(self, cursor): - "Returns a list of table names in the current database." + """ + Returns a list of table and view names in the current database. + """ # Skip the sqlite_sequence system table used for autoincrement key # generation. cursor.execute(""" - SELECT name FROM sqlite_master + SELECT name, type FROM sqlite_master WHERE type in ('table', 'view') AND NOT name='sqlite_sequence' ORDER BY name""") - return [row[0] for row in cursor.fetchall()] + return [TableInfo(row[0], row[1][0]) for row in cursor.fetchall()] def get_table_description(self, cursor, table_name): "Returns a description of the table, with the DB-API cursor.description interface."