Refs #27097, #27098 -- Moved PostgreSQL index type introspection to get_constraints().

This commit is contained in:
Akshesh 2016-08-25 12:42:17 +05:30 committed by Tim Graham
parent 3fe92f4477
commit 4c7bf83cde
4 changed files with 24 additions and 25 deletions

View File

@ -24,16 +24,14 @@ class PostGISIntrospection(DatabaseIntrospection):
# expression over the raster column through the ST_ConvexHull function.
# So the default query has to be adapted to include raster indices.
_get_indexes_query = """
SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary,
am.amname
SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index idx,
pg_catalog.pg_attribute attr, pg_catalog.pg_type t, pg_catalog.pg_am am
pg_catalog.pg_attribute attr, pg_catalog.pg_type t
WHERE
c.oid = idx.indrelid
AND idx.indexrelid = c2.oid
AND attr.attrelid = c.oid
AND t.oid = attr.atttypid
AND c2.relam = am.oid
AND (
attr.attnum = idx.indkey[0] OR
(t.typname LIKE 'raster' AND idx.indkey = '0')

View File

@ -36,15 +36,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
ignored_tables = []
_get_indexes_query = """
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary,
am.amname
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr, pg_catalog.pg_am am
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
WHERE c.oid = idx.indrelid
AND idx.indexrelid = c2.oid
AND attr.attrelid = c.oid
AND attr.attnum = idx.indkey[0]
AND c2.relam = am.oid
AND c.relname = %s"""
def get_field_type(self, data_type, description):
@ -134,7 +132,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
# 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.
# row[4] is the type of index, e.g. btree, hash, etc.
# Here, we skip any indexes across multiple fields.
if ' ' in row[1]:
continue
@ -145,7 +142,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
indexes[row[0]]['primary_key'] = True
if row[2]:
indexes[row[0]]['unique'] = True
indexes[row[0]]['type'] = row[4]
return indexes
def get_constraints(self, cursor, table_name):
@ -216,10 +212,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
cursor.execute("""
SELECT
indexname, array_agg(attname), indisunique, indisprimary,
array_agg(ordering)
array_agg(ordering), amname
FROM (
SELECT
c2.relname as indexname, idx.*, attr.attname,
c2.relname as indexname, idx.*, attr.attname, am.amname,
CASE
WHEN am.amcanorder THEN
CASE (option & 1)
@ -238,9 +234,9 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
AND c2.relam=am.oid
AND c.relname = %s
) s2
GROUP BY indexname, indisunique, indisprimary;
GROUP BY indexname, indisunique, indisprimary, amname;;
""", [table_name])
for index, columns, unique, primary, orders in cursor.fetchall():
for index, columns, unique, primary, orders, type_ in cursor.fetchall():
if index not in constraints:
constraints[index] = {
"columns": columns,
@ -250,5 +246,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
"foreign_key": None,
"check": False,
"index": True,
"type": type_,
}
return constraints

View File

@ -172,11 +172,6 @@ class IntrospectionTests(TransactionTestCase):
def test_get_indexes(self):
with connection.cursor() as cursor:
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})
def test_get_indexes_multicol(self):
@ -189,6 +184,14 @@ class IntrospectionTests(TransactionTestCase):
self.assertNotIn('first_name', indexes)
self.assertIn('id', indexes)
@skipUnlessDBFeature('can_introspect_index_type')
def test_get_constraints_index_types(self):
with connection.cursor() as cursor:
constraints = connection.introspection.get_constraints(cursor, Article._meta.db_table)
for key, val in constraints.items():
if val['index'] and not (val['primary_key'] or val['unique']):
self.assertEqual(val['type'], 'btree')
@skipUnlessDBFeature('supports_index_column_ordering')
def test_get_constraints_indexes_orders(self):
"""

View File

@ -33,23 +33,24 @@ class GinIndexTests(PostgreSQLTestCase):
class SchemaTests(PostgreSQLTestCase):
def get_indexes(self, table):
def get_constraints(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 connection.introspection.get_constraints(cursor, table)
def test_gin_index(self):
# Ensure the table is there and doesn't have an index.
self.assertNotIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
self.assertNotIn('field', self.get_constraints(IntegerArrayModel._meta.db_table))
# Add the index
index = GinIndex(fields=['field'], name='integer_array_model_field_gin')
with connection.schema_editor() as editor:
editor.add_index(IntegerArrayModel, index)
self.assertIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
self.assertEqual(self.get_indexes(IntegerArrayModel._meta.db_table)['field']['type'], 'gin')
self.assertIn('integer_array_model_field_gin', self.get_constraints(IntegerArrayModel._meta.db_table))
constraints = self.get_constraints(IntegerArrayModel._meta.db_table)
self.assertEqual(constraints['integer_array_model_field_gin']['type'], 'gin')
# Drop the index
with connection.schema_editor() as editor:
editor.remove_index(IntegerArrayModel, index)
self.assertNotIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
self.assertNotIn('integer_array_model_field_gin', self.get_constraints(IntegerArrayModel._meta.db_table))