summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-08-20 12:14:02 +0200
committerClaude Paroz <claude@2xlibre.net>2016-09-12 09:26:33 +0200
commitd389125606152a6cd57d0f6cadeddf0bd6232215 (patch)
tree20f8b19adbcccf3b274136743efe3c596a86ffe7
parent1ec1633cb294d8ce2a65ece6b56c258483596fba (diff)
downloaddjango-d389125606152a6cd57d0f6cadeddf0bd6232215.tar.gz
Fixed #27098 -- Deprecated DatabaseIntrospection.get_indexes
Thanks Akshesh <aksheshdoshi@gmail.com> for help with the PostgreSQL query. Thanks Tim Graham for the review.
-rw-r--r--django/contrib/gis/db/backends/spatialite/introspection.py15
-rw-r--r--django/core/management/commands/inspectdb.py18
-rw-r--r--django/db/backends/base/introspection.py9
-rw-r--r--django/db/backends/mysql/introspection.py6
-rw-r--r--django/db/backends/oracle/introspection.py7
-rw-r--r--django/db/backends/postgresql/introspection.py6
-rw-r--r--django/db/backends/sqlite3/introspection.py6
-rw-r--r--docs/internals/deprecation.txt2
-rw-r--r--docs/releases/1.11.txt7
-rw-r--r--tests/gis_tests/gis_migrations/test_operations.py4
-rw-r--r--tests/introspection/tests.py4
-rw-r--r--tests/postgres_tests/test_array.py8
-rw-r--r--tests/schema/tests.py18
13 files changed, 81 insertions, 29 deletions
diff --git a/django/contrib/gis/db/backends/spatialite/introspection.py b/django/contrib/gis/db/backends/spatialite/introspection.py
index c406baafdb..6c3ed1864c 100644
--- a/django/contrib/gis/db/backends/spatialite/introspection.py
+++ b/django/contrib/gis/db/backends/spatialite/introspection.py
@@ -61,11 +61,18 @@ class SpatiaLiteIntrospection(DatabaseIntrospection):
return field_type, field_params
- def get_indexes(self, cursor, table_name):
- indexes = super(SpatiaLiteIntrospection, self).get_indexes(cursor, table_name)
+ def get_constraints(self, cursor, table_name):
+ constraints = super(SpatiaLiteIntrospection, self).get_constraints(cursor, table_name)
cursor.execute('SELECT f_geometry_column '
'FROM geometry_columns '
'WHERE f_table_name=%s AND spatial_index_enabled=1', (table_name,))
for row in cursor.fetchall():
- indexes[row[0]] = {'primary_key': False, 'unique': False}
- return indexes
+ constraints['%s__spatial__index' % row[0]] = {
+ "columns": [row[0]],
+ "primary_key": False,
+ "unique": False,
+ "foreign_key": None,
+ "check": False,
+ "index": True,
+ }
+ return constraints
diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py
index 02a8ac225e..31079c1a47 100644
--- a/django/core/management/commands/inspectdb.py
+++ b/django/core/management/commands/inspectdb.py
@@ -71,13 +71,14 @@ class Command(BaseCommand):
except NotImplementedError:
relations = {}
try:
- indexes = connection.introspection.get_indexes(cursor, table_name)
- except NotImplementedError:
- indexes = {}
- try:
constraints = connection.introspection.get_constraints(cursor, table_name)
except NotImplementedError:
constraints = {}
+ primary_key_column = connection.introspection.get_primary_key_column(cursor, table_name)
+ unique_columns = [
+ c['columns'][0] for c in constraints.values()
+ if c['unique'] and len(c['columns']) == 1
+ ]
table_description = connection.introspection.get_table_description(cursor, table_name)
except Exception as e:
yield "# Unable to inspect table '%s'" % table_name
@@ -105,11 +106,10 @@ class Command(BaseCommand):
column_to_field_name[column_name] = att_name
# Add primary_key and unique, if necessary.
- if column_name in indexes:
- if indexes[column_name]['primary_key']:
- extra_params['primary_key'] = True
- elif indexes[column_name]['unique']:
- extra_params['unique'] = True
+ if column_name == primary_key_column:
+ extra_params['primary_key'] = True
+ elif column_name in unique_columns:
+ extra_params['unique'] = True
if is_relation:
rel_to = (
diff --git a/django/db/backends/base/introspection.py b/django/db/backends/base/introspection.py
index 7da14985c3..176a58e243 100644
--- a/django/db/backends/base/introspection.py
+++ b/django/db/backends/base/introspection.py
@@ -1,7 +1,5 @@
from collections import namedtuple
-from django.utils import six
-
# Structure returned by DatabaseIntrospection.get_table_list()
TableInfo = namedtuple('TableInfo', ['name', 'type'])
@@ -143,13 +141,14 @@ class BaseDatabaseIntrospection(object):
"""
Returns the name of the primary key column for the given table.
"""
- for column in six.iteritems(self.get_indexes(cursor, table_name)):
- if column[1]['primary_key']:
- return column[0]
+ for constraint in self.get_constraints(cursor, table_name).values():
+ if constraint['primary_key']:
+ return constraint['columns'][0]
return None
def get_indexes(self, cursor, table_name):
"""
+ Deprecated in Django 1.11, use get_constraints instead.
Returns 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,
diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
index 3a8b7f6933..fc7ce178fd 100644
--- a/django/db/backends/mysql/introspection.py
+++ b/django/db/backends/mysql/introspection.py
@@ -1,3 +1,4 @@
+import warnings
from collections import namedtuple
from MySQLdb.constants import FIELD_TYPE
@@ -6,6 +7,7 @@ from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
from django.utils.datastructures import OrderedSet
+from django.utils.deprecation import RemovedInDjango21Warning
from django.utils.encoding import force_text
FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('extra', 'default'))
@@ -122,6 +124,10 @@ 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
+ )
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
diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py
index 5c0c5c5861..2ac43deff6 100644
--- a/django/db/backends/oracle/introspection.py
+++ b/django/db/backends/oracle/introspection.py
@@ -1,8 +1,11 @@
+import warnings
+
import cx_Oracle
from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
+from django.utils.deprecation import RemovedInDjango21Warning
from django.utils.encoding import force_text
@@ -117,6 +120,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
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
diff --git a/django/db/backends/postgresql/introspection.py b/django/db/backends/postgresql/introspection.py
index 8a8465d443..29e11499a9 100644
--- a/django/db/backends/postgresql/introspection.py
+++ b/django/db/backends/postgresql/introspection.py
@@ -1,10 +1,12 @@
from __future__ import unicode_literals
+import warnings
from collections import namedtuple
from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
+from django.utils.deprecation import RemovedInDjango21Warning
from django.utils.encoding import force_text
FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('default',))
@@ -124,6 +126,10 @@ 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
+ )
# This query retrieves each index on the given table, including the
# first associated field name
cursor.execute(self._get_indexes_query, [table_name])
diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py
index db475505d8..2ed629f94a 100644
--- a/django/db/backends/sqlite3/introspection.py
+++ b/django/db/backends/sqlite3/introspection.py
@@ -1,9 +1,11 @@
import re
+import warnings
from collections import namedtuple
from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
+from django.utils.deprecation import RemovedInDjango21Warning
field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$')
FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('default',))
@@ -183,6 +185,10 @@ 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:
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index 151cdff68d..8be137e635 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -36,6 +36,8 @@ details on these changes.
* Silencing of exceptions raised while rendering the ``{% include %}`` template
tag will be removed.
+* ``DatabaseIntrospection.get_indexes()`` will be removed.
+
.. _deprecation-removed-in-2.0:
2.0
diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt
index b2ba159c8a..7b5bcc450f 100644
--- a/docs/releases/1.11.txt
+++ b/docs/releases/1.11.txt
@@ -399,6 +399,10 @@ Database backend API
dictionaries with a list of ``'ASC'`` and/or ``'DESC'`` values corresponding
to the the ordering of each column in the index.
+* :djadmin:`inspectdb` no longer calls ``DatabaseIntrospection.get_indexes()``
+ which is deprecated. Custom database backends should ensure all types of
+ indexes are returned by ``DatabaseIntrospection.get_constraints()``.
+
Dropped support for PostgreSQL 9.2 and PostGIS 2.0
--------------------------------------------------
@@ -549,3 +553,6 @@ Miscellaneous
:ttag:`{% include %} <include>` template tag is deprecated as the behavior is
often more confusing than helpful. In Django 2.1, the exception will be
raised.
+
+* ``DatabaseIntrospection.get_indexes()`` is deprecated in favor of
+ ``DatabaseIntrospection.get_constraints()``.
diff --git a/tests/gis_tests/gis_migrations/test_operations.py b/tests/gis_tests/gis_migrations/test_operations.py
index aa6b13bdda..84735d8fbd 100644
--- a/tests/gis_tests/gis_migrations/test_operations.py
+++ b/tests/gis_tests/gis_migrations/test_operations.py
@@ -69,8 +69,8 @@ class OperationTests(TransactionTestCase):
def assertSpatialIndexExists(self, table, column):
with connection.cursor() as cursor:
- indexes = connection.introspection.get_indexes(cursor, table)
- self.assertIn(column, indexes)
+ constraints = connection.introspection.get_constraints(cursor, table)
+ self.assertIn([column], [c['columns'] for c in constraints.values()])
def alter_gis_model(self, migration_class, model_name, field_name,
blank=False, field_class=None):
diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py
index 68d621d762..7c60902deb 100644
--- a/tests/introspection/tests.py
+++ b/tests/introspection/tests.py
@@ -5,6 +5,8 @@ from unittest import skipUnless
from django.db import connection
from django.db.utils import DatabaseError
from django.test import TransactionTestCase, mock, skipUnlessDBFeature
+from django.test.utils import ignore_warnings
+from django.utils.deprecation import RemovedInDjango21Warning
from .models import Article, ArticleReporter, City, District, Reporter
@@ -169,11 +171,13 @@ 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):
"""
Test that multicolumn indexes are not included in the introspection
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index 2b5796dc6f..0b788e0d23 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -483,9 +483,13 @@ class TestMigrations(TransactionTestCase):
]
# Only the CharField should have a LIKE index.
self.assertEqual(like_constraint_columns_list, [['char2']])
- with connection.cursor() as cursor:
- indexes = connection.introspection.get_indexes(cursor, table_name)
# All fields should have regular indexes.
+ with connection.cursor() as cursor:
+ indexes = [
+ c['columns'][0]
+ for c in connection.introspection.get_constraints(cursor, table_name).values()
+ if c['index'] and len(c['columns']) == 1
+ ]
self.assertIn('char', indexes)
self.assertIn('char2', indexes)
self.assertIn('text', indexes)
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index ef4d36a0df..9aeada3e67 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -105,12 +105,20 @@ class SchemaTests(TransactionTestCase):
raise DatabaseError("Table does not exist (empty pragma)")
return columns
+ def get_primary_key(self, table):
+ with connection.cursor() as cursor:
+ return connection.introspection.get_primary_key_column(cursor, table)
+
def get_indexes(self, table):
"""
Get the indexes on the table using a new cursor.
"""
with connection.cursor() as cursor:
- return connection.introspection.get_indexes(cursor, table)
+ return [
+ c['columns'][0]
+ for c in connection.introspection.get_constraints(cursor, table).values()
+ if c['index'] and len(c['columns']) == 1
+ ]
def get_constraints(self, table):
"""
@@ -1685,9 +1693,7 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor:
editor.create_model(Tag)
# Ensure the table is there and has the right PK
- self.assertTrue(
- self.get_indexes(Tag._meta.db_table)['id']['primary_key'],
- )
+ self.assertEqual(self.get_primary_key(Tag._meta.db_table), 'id')
# Alter to change the PK
id_field = Tag._meta.get_field("id")
old_field = Tag._meta.get_field("slug")
@@ -1702,9 +1708,7 @@ class SchemaTests(TransactionTestCase):
'id',
self.get_indexes(Tag._meta.db_table),
)
- self.assertTrue(
- self.get_indexes(Tag._meta.db_table)['slug']['primary_key'],
- )
+ self.assertEqual(self.get_primary_key(Tag._meta.db_table), 'slug')
def test_context_manager_exit(self):
"""