Refs #27098 -- Removed DatabaseIntrospection.get_indexes() per deprecation timeline.

This commit is contained in:
Tim Graham 2017-09-02 20:28:48 -04:00
parent e62165b898
commit 578711c310
7 changed files with 2 additions and 148 deletions

View File

@ -158,18 +158,6 @@ class BaseDatabaseIntrospection:
return constraint['columns'][0] return constraint['columns'][0]
return None 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): def get_constraints(self, cursor, table_name):
""" """
Retrieve any constraints or keys (unique, pk, fk, check, index) Retrieve any constraints or keys (unique, pk, fk, check, index)

View File

@ -1,4 +1,3 @@
import warnings
from collections import namedtuple from collections import namedtuple
from MySQLdb.constants import FIELD_TYPE 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.db.models.indexes import Index
from django.utils.datastructures import OrderedSet from django.utils.datastructures import OrderedSet
from django.utils.deprecation import RemovedInDjango21Warning
FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('extra', 'is_unsigned')) 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') 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()) key_columns.extend(cursor.fetchall())
return key_columns 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): def get_storage_engine(self, cursor, table_name):
""" """
Retrieve the storage engine for a given table. Return the default Retrieve the storage engine for a given table. Return the default

View File

@ -1,4 +1,3 @@
import warnings
from collections import namedtuple from collections import namedtuple
import cx_Oracle import cx_Oracle
@ -7,7 +6,6 @@ from django.db import models
from django.db.backends.base.introspection import ( from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo, BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo,
) )
from django.utils.deprecation import RemovedInDjango21Warning
FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('is_autofield',)) FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('is_autofield',))
@ -157,40 +155,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
return [tuple(cell.lower() for cell in row) return [tuple(cell.lower() for cell in row)
for row in cursor.fetchall()] 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): def get_constraints(self, cursor, table_name):
""" """
Retrieve any constraints or keys (unique, pk, fk, check, index) across Retrieve any constraints or keys (unique, pk, fk, check, index) across

View File

@ -1,10 +1,7 @@
import warnings
from django.db.backends.base.introspection import ( from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo, BaseDatabaseIntrospection, FieldInfo, TableInfo,
) )
from django.db.models.indexes import Index from django.db.models.indexes import Index
from django.utils.deprecation import RemovedInDjango21Warning
class DatabaseIntrospection(BaseDatabaseIntrospection): class DatabaseIntrospection(BaseDatabaseIntrospection):
@ -138,31 +135,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
key_columns.extend(cursor.fetchall()) key_columns.extend(cursor.fetchall())
return key_columns 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): def get_constraints(self, cursor, table_name):
""" """
Retrieve any constraints or keys (unique, pk, fk, check, index) across Retrieve any constraints or keys (unique, pk, fk, check, index) across

View File

@ -1,11 +1,9 @@
import re import re
import warnings
from django.db.backends.base.introspection import ( from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo, BaseDatabaseIntrospection, FieldInfo, TableInfo,
) )
from django.db.models.indexes import Index 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*$') field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$')
@ -188,29 +186,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
return key_columns 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): def get_primary_key_column(self, cursor, table_name):
"""Return the column name of the primary key for the given table.""" """Return the column name of the primary key for the given table."""
# Don't use PRAGMA because that causes issues with some transactions # Don't use PRAGMA because that causes issues with some transactions

View File

@ -244,3 +244,5 @@ how to remove usage of these features.
* Silencing of exceptions raised while rendering the ``{% include %}`` template * Silencing of exceptions raised while rendering the ``{% include %}`` template
tag is removed. tag is removed.
* ``DatabaseIntrospection.get_indexes()`` is removed.

View File

@ -4,8 +4,6 @@ from django.db import connection
from django.db.models import Index from django.db.models import Index
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
from django.test import TransactionTestCase, skipUnlessDBFeature 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 from .models import Article, ArticleReporter, City, District, Reporter
@ -170,22 +168,6 @@ class IntrospectionTests(TransactionTestCase):
self.assertEqual(primary_key_column, 'id') self.assertEqual(primary_key_column, 'id')
self.assertEqual(pk_fk_column, 'city_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): def test_get_constraints_index_types(self):
with connection.cursor() as cursor: with connection.cursor() as cursor:
constraints = connection.introspection.get_constraints(cursor, Article._meta.db_table) constraints = connection.introspection.get_constraints(cursor, Article._meta.db_table)