mirror of https://github.com/django/django.git
Refs #27030 -- Added index type introspection on PostgreSQL.
This commit is contained in:
parent
72d541b61c
commit
2f19306a12
|
@ -24,14 +24,16 @@ class PostGISIntrospection(DatabaseIntrospection):
|
||||||
# expression over the raster column through the ST_ConvexHull function.
|
# expression over the raster column through the ST_ConvexHull function.
|
||||||
# So the default query has to be adapted to include raster indices.
|
# So the default query has to be adapted to include raster indices.
|
||||||
_get_indexes_query = """
|
_get_indexes_query = """
|
||||||
SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
|
SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary,
|
||||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
am.amname
|
||||||
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index idx,
|
||||||
LEFT JOIN pg_catalog.pg_type t ON t.oid = attr.atttypid
|
pg_catalog.pg_attribute attr, pg_catalog.pg_type t, pg_catalog.pg_am am
|
||||||
WHERE
|
WHERE
|
||||||
c.oid = idx.indrelid
|
c.oid = idx.indrelid
|
||||||
AND idx.indexrelid = c2.oid
|
AND idx.indexrelid = c2.oid
|
||||||
AND attr.attrelid = c.oid
|
AND attr.attrelid = c.oid
|
||||||
|
AND t.oid = attr.atttypid
|
||||||
|
AND c2.relam = am.oid
|
||||||
AND (
|
AND (
|
||||||
attr.attnum = idx.indkey[0] OR
|
attr.attnum = idx.indkey[0] OR
|
||||||
(t.typname LIKE 'raster' AND idx.indkey = '0')
|
(t.typname LIKE 'raster' AND idx.indkey = '0')
|
||||||
|
|
|
@ -163,6 +163,9 @@ class BaseDatabaseFeatures(object):
|
||||||
# Can the backend introspect the column order (ASC/DESC) for indexes?
|
# Can the backend introspect the column order (ASC/DESC) for indexes?
|
||||||
supports_index_column_ordering = True
|
supports_index_column_ordering = True
|
||||||
|
|
||||||
|
# Can the backend introspect the type of index created?
|
||||||
|
can_introspect_index_type = False
|
||||||
|
|
||||||
# Support for the DISTINCT ON clause
|
# Support for the DISTINCT ON clause
|
||||||
can_distinct_on_fields = False
|
can_distinct_on_fields = False
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
can_introspect_autofield = True
|
can_introspect_autofield = True
|
||||||
can_introspect_ip_address_field = True
|
can_introspect_ip_address_field = True
|
||||||
can_introspect_small_integer_field = True
|
can_introspect_small_integer_field = True
|
||||||
|
can_introspect_index_type = True
|
||||||
can_distinct_on_fields = True
|
can_distinct_on_fields = True
|
||||||
can_rollback_ddl = True
|
can_rollback_ddl = True
|
||||||
supports_combined_alters = True
|
supports_combined_alters = True
|
||||||
|
|
|
@ -36,13 +36,15 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
ignored_tables = []
|
ignored_tables = []
|
||||||
|
|
||||||
_get_indexes_query = """
|
_get_indexes_query = """
|
||||||
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
|
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary,
|
||||||
|
am.amname
|
||||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
||||||
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
|
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr, pg_catalog.pg_am am
|
||||||
WHERE c.oid = idx.indrelid
|
WHERE c.oid = idx.indrelid
|
||||||
AND idx.indexrelid = c2.oid
|
AND idx.indexrelid = c2.oid
|
||||||
AND attr.attrelid = c.oid
|
AND attr.attrelid = c.oid
|
||||||
AND attr.attnum = idx.indkey[0]
|
AND attr.attnum = idx.indkey[0]
|
||||||
|
AND c2.relam = am.oid
|
||||||
AND c.relname = %s"""
|
AND c.relname = %s"""
|
||||||
|
|
||||||
def get_field_type(self, data_type, description):
|
def get_field_type(self, data_type, description):
|
||||||
|
@ -132,6 +134,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
# row[1] (idx.indkey) is stored in the DB as an array. It comes out as
|
# 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
|
# a string of space-separated integers. This designates the field
|
||||||
# indexes (1-based) of the fields that have indexes on the table.
|
# indexes (1-based) of the fields that have indexes on the table.
|
||||||
|
# row[4] is the type of index, e.g. btree, hash, etc.
|
||||||
# Here, we skip any indexes across multiple fields.
|
# Here, we skip any indexes across multiple fields.
|
||||||
if ' ' in row[1]:
|
if ' ' in row[1]:
|
||||||
continue
|
continue
|
||||||
|
@ -142,6 +145,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
indexes[row[0]]['primary_key'] = True
|
indexes[row[0]]['primary_key'] = True
|
||||||
if row[2]:
|
if row[2]:
|
||||||
indexes[row[0]]['unique'] = True
|
indexes[row[0]]['unique'] = True
|
||||||
|
indexes[row[0]]['type'] = row[4]
|
||||||
return indexes
|
return indexes
|
||||||
|
|
||||||
def get_constraints(self, cursor, table_name):
|
def get_constraints(self, cursor, table_name):
|
||||||
|
|
|
@ -170,6 +170,11 @@ class IntrospectionTests(TransactionTestCase):
|
||||||
def test_get_indexes(self):
|
def test_get_indexes(self):
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table)
|
indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table)
|
||||||
|
if connection.features.can_introspect_index_type:
|
||||||
|
index_type = indexes['reporter_id'].pop('type', None)
|
||||||
|
self.assertIsNotNone(index_type)
|
||||||
|
if connection.vendor == 'postgresql':
|
||||||
|
self.assertEqual(index_type, 'btree')
|
||||||
self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False})
|
self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False})
|
||||||
|
|
||||||
def test_get_indexes_multicol(self):
|
def test_get_indexes_multicol(self):
|
||||||
|
|
Loading…
Reference in New Issue