diff --git a/django/db/backends/base/introspection.py b/django/db/backends/base/introspection.py index a3107c3034..27a3cb2b87 100644 --- a/django/db/backends/base/introspection.py +++ b/django/db/backends/base/introspection.py @@ -158,18 +158,6 @@ class BaseDatabaseIntrospection: return constraint['columns'][0] return None - def get_indexes(self, cursor, table_name): - """ - Deprecated in Django 1.11, use get_constraints instead. - Return a dictionary of indexed fieldname -> infodict for the given - table, where each infodict is in the format: - {'primary_key': boolean representing whether it's the primary key, - 'unique': boolean representing whether it's a unique index} - - Only single-column indexes are introspected. - """ - raise NotImplementedError('subclasses of BaseDatabaseIntrospection may require a get_indexes() method') - def get_constraints(self, cursor, table_name): """ Retrieve any constraints or keys (unique, pk, fk, check, index) diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py index caa5826e55..28dc47f769 100644 --- a/django/db/backends/mysql/introspection.py +++ b/django/db/backends/mysql/introspection.py @@ -1,4 +1,3 @@ -import warnings from collections import namedtuple from MySQLdb.constants import FIELD_TYPE @@ -8,7 +7,6 @@ from django.db.backends.base.introspection import ( ) from django.db.models.indexes import Index from django.utils.datastructures import OrderedSet -from django.utils.deprecation import RemovedInDjango21Warning FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('extra', 'is_unsigned')) InfoLine = namedtuple('InfoLine', 'col_name data_type max_len num_prec num_scale extra column_default is_unsigned') @@ -139,33 +137,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): key_columns.extend(cursor.fetchall()) return key_columns - def get_indexes(self, cursor, table_name): - warnings.warn( - "get_indexes() is deprecated in favor of get_constraints().", - RemovedInDjango21Warning, stacklevel=2 - ) - cursor.execute("SHOW INDEX FROM %s" % self.connection.ops.quote_name(table_name)) - # Do a two-pass search for indexes: on first pass check which indexes - # are multicolumn, on second pass check which single-column indexes - # are present. - rows = list(cursor.fetchall()) - multicol_indexes = set() - for row in rows: - if row[3] > 1: - multicol_indexes.add(row[2]) - indexes = {} - for row in rows: - if row[2] in multicol_indexes: - continue - if row[4] not in indexes: - indexes[row[4]] = {'primary_key': False, 'unique': False} - # It's possible to have the unique and PK constraints in separate indexes. - if row[2] == 'PRIMARY': - indexes[row[4]]['primary_key'] = True - if not row[1]: - indexes[row[4]]['unique'] = True - return indexes - def get_storage_engine(self, cursor, table_name): """ Retrieve the storage engine for a given table. Return the default diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py index 7b873fd0d0..dbd54c29be 100644 --- a/django/db/backends/oracle/introspection.py +++ b/django/db/backends/oracle/introspection.py @@ -1,4 +1,3 @@ -import warnings from collections import namedtuple import cx_Oracle @@ -7,7 +6,6 @@ from django.db import models from django.db.backends.base.introspection import ( BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo, ) -from django.utils.deprecation import RemovedInDjango21Warning FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('is_autofield',)) @@ -157,40 +155,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): return [tuple(cell.lower() for cell in row) for row in cursor.fetchall()] - def get_indexes(self, cursor, table_name): - warnings.warn( - "get_indexes() is deprecated in favor of get_constraints().", - RemovedInDjango21Warning, stacklevel=2 - ) - sql = """ - SELECT LOWER(uic1.column_name) AS column_name, - CASE user_constraints.constraint_type - WHEN 'P' THEN 1 ELSE 0 - END AS is_primary_key, - CASE user_indexes.uniqueness - WHEN 'UNIQUE' THEN 1 ELSE 0 - END AS is_unique - FROM user_constraints, user_indexes, user_ind_columns uic1 - WHERE user_constraints.constraint_type (+) = 'P' - AND user_constraints.index_name (+) = uic1.index_name - AND user_indexes.uniqueness (+) = 'UNIQUE' - AND user_indexes.index_name (+) = uic1.index_name - AND uic1.table_name = UPPER(%s) - AND uic1.column_position = 1 - AND NOT EXISTS ( - SELECT 1 - FROM user_ind_columns uic2 - WHERE uic2.index_name = uic1.index_name - AND uic2.column_position = 2 - ) - """ - cursor.execute(sql, [table_name]) - indexes = {} - for row in cursor.fetchall(): - indexes[row[0]] = {'primary_key': bool(row[1]), - 'unique': bool(row[2])} - return indexes - def get_constraints(self, cursor, table_name): """ Retrieve any constraints or keys (unique, pk, fk, check, index) across diff --git a/django/db/backends/postgresql/introspection.py b/django/db/backends/postgresql/introspection.py index 1e987d1779..f060546a53 100644 --- a/django/db/backends/postgresql/introspection.py +++ b/django/db/backends/postgresql/introspection.py @@ -1,10 +1,7 @@ -import warnings - from django.db.backends.base.introspection import ( BaseDatabaseIntrospection, FieldInfo, TableInfo, ) from django.db.models.indexes import Index -from django.utils.deprecation import RemovedInDjango21Warning class DatabaseIntrospection(BaseDatabaseIntrospection): @@ -138,31 +135,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): key_columns.extend(cursor.fetchall()) return key_columns - def get_indexes(self, cursor, table_name): - warnings.warn( - "get_indexes() is deprecated in favor of get_constraints().", - RemovedInDjango21Warning, stacklevel=2 - ) - # This query retrieves each index on the given table, including the - # first associated field name - cursor.execute(self._get_indexes_query, [table_name]) - indexes = {} - for row in cursor.fetchall(): - # row[1] (idx.indkey) is stored in the DB as an array. It comes out as - # a string of space-separated integers. This designates the field - # indexes (1-based) of the fields that have indexes on the table. - # Here, we skip any indexes across multiple fields. - if ' ' in row[1]: - continue - if row[0] not in indexes: - indexes[row[0]] = {'primary_key': False, 'unique': False} - # It's possible to have the unique and PK constraints in separate indexes. - if row[3]: - indexes[row[0]]['primary_key'] = True - if row[2]: - indexes[row[0]]['unique'] = True - return indexes - def get_constraints(self, cursor, table_name): """ Retrieve any constraints or keys (unique, pk, fk, check, index) across diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py index 0518641344..0326082996 100644 --- a/django/db/backends/sqlite3/introspection.py +++ b/django/db/backends/sqlite3/introspection.py @@ -1,11 +1,9 @@ import re -import warnings from django.db.backends.base.introspection import ( BaseDatabaseIntrospection, FieldInfo, TableInfo, ) from django.db.models.indexes import Index -from django.utils.deprecation import RemovedInDjango21Warning field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$') @@ -188,29 +186,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): return key_columns - def get_indexes(self, cursor, table_name): - warnings.warn( - "get_indexes() is deprecated in favor of get_constraints().", - RemovedInDjango21Warning, stacklevel=2 - ) - indexes = {} - for info in self._table_info(cursor, table_name): - if info['pk'] != 0: - indexes[info['name']] = {'primary_key': True, - 'unique': False} - cursor.execute('PRAGMA index_list(%s)' % self.connection.ops.quote_name(table_name)) - # seq, name, unique - for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]: - cursor.execute('PRAGMA index_info(%s)' % self.connection.ops.quote_name(index)) - info = cursor.fetchall() - # Skip indexes across multiple fields - if len(info) != 1: - continue - name = info[0][2] # seqno, cid, name - indexes[name] = {'primary_key': indexes.get(name, {}).get("primary_key", False), - 'unique': unique} - return indexes - def get_primary_key_column(self, cursor, table_name): """Return the column name of the primary key for the given table.""" # Don't use PRAGMA because that causes issues with some transactions diff --git a/docs/releases/2.1.txt b/docs/releases/2.1.txt index 7f0b6e77e8..909d537c39 100644 --- a/docs/releases/2.1.txt +++ b/docs/releases/2.1.txt @@ -244,3 +244,5 @@ how to remove usage of these features. * Silencing of exceptions raised while rendering the ``{% include %}`` template tag is removed. + +* ``DatabaseIntrospection.get_indexes()`` is removed. diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index ed10927b2a..2e68e52542 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -4,8 +4,6 @@ from django.db import connection from django.db.models import Index from django.db.utils import DatabaseError from django.test import TransactionTestCase, skipUnlessDBFeature -from django.test.utils import ignore_warnings -from django.utils.deprecation import RemovedInDjango21Warning from .models import Article, ArticleReporter, City, District, Reporter @@ -170,22 +168,6 @@ class IntrospectionTests(TransactionTestCase): self.assertEqual(primary_key_column, 'id') self.assertEqual(pk_fk_column, 'city_id') - @ignore_warnings(category=RemovedInDjango21Warning) - def test_get_indexes(self): - with connection.cursor() as cursor: - indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table) - self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False}) - - @ignore_warnings(category=RemovedInDjango21Warning) - def test_get_indexes_multicol(self): - """ - Multicolumn indexes are not included in the introspection results. - """ - with connection.cursor() as cursor: - indexes = connection.introspection.get_indexes(cursor, Reporter._meta.db_table) - self.assertNotIn('first_name', indexes) - self.assertIn('id', indexes) - def test_get_constraints_index_types(self): with connection.cursor() as cursor: constraints = connection.introspection.get_constraints(cursor, Article._meta.db_table)