mirror of https://github.com/django/django.git
Refs #27098 -- Removed DatabaseIntrospection.get_indexes() per deprecation timeline.
This commit is contained in:
parent
e62165b898
commit
578711c310
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue