Refs #27030 -- Added index type introspection on PostgreSQL.

This commit is contained in:
Akshesh 2016-08-08 10:29:08 +05:30 committed by Tim Graham
parent 72d541b61c
commit 2f19306a12
5 changed files with 21 additions and 6 deletions

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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):