This commit is contained in:
parent
3fe92f4477
commit
4c7bf83cde
|
@ -24,16 +24,14 @@ 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
|
||||||
am.amname
|
|
||||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index idx,
|
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
|
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 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')
|
||||||
|
|
|
@ -36,15 +36,13 @@ 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_am am
|
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
|
||||||
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):
|
||||||
|
@ -134,7 +132,6 @@ 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
|
||||||
|
@ -145,7 +142,6 @@ 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):
|
||||||
|
@ -216,10 +212,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
indexname, array_agg(attname), indisunique, indisprimary,
|
indexname, array_agg(attname), indisunique, indisprimary,
|
||||||
array_agg(ordering)
|
array_agg(ordering), amname
|
||||||
FROM (
|
FROM (
|
||||||
SELECT
|
SELECT
|
||||||
c2.relname as indexname, idx.*, attr.attname,
|
c2.relname as indexname, idx.*, attr.attname, am.amname,
|
||||||
CASE
|
CASE
|
||||||
WHEN am.amcanorder THEN
|
WHEN am.amcanorder THEN
|
||||||
CASE (option & 1)
|
CASE (option & 1)
|
||||||
|
@ -238,9 +234,9 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
AND c2.relam=am.oid
|
AND c2.relam=am.oid
|
||||||
AND c.relname = %s
|
AND c.relname = %s
|
||||||
) s2
|
) s2
|
||||||
GROUP BY indexname, indisunique, indisprimary;
|
GROUP BY indexname, indisunique, indisprimary, amname;;
|
||||||
""", [table_name])
|
""", [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:
|
if index not in constraints:
|
||||||
constraints[index] = {
|
constraints[index] = {
|
||||||
"columns": columns,
|
"columns": columns,
|
||||||
|
@ -250,5 +246,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
"foreign_key": None,
|
"foreign_key": None,
|
||||||
"check": False,
|
"check": False,
|
||||||
"index": True,
|
"index": True,
|
||||||
|
"type": type_,
|
||||||
}
|
}
|
||||||
return constraints
|
return constraints
|
||||||
|
|
|
@ -172,11 +172,6 @@ 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):
|
||||||
|
@ -189,6 +184,14 @@ class IntrospectionTests(TransactionTestCase):
|
||||||
self.assertNotIn('first_name', indexes)
|
self.assertNotIn('first_name', indexes)
|
||||||
self.assertIn('id', 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')
|
@skipUnlessDBFeature('supports_index_column_ordering')
|
||||||
def test_get_constraints_indexes_orders(self):
|
def test_get_constraints_indexes_orders(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -33,23 +33,24 @@ class GinIndexTests(PostgreSQLTestCase):
|
||||||
|
|
||||||
class SchemaTests(PostgreSQLTestCase):
|
class SchemaTests(PostgreSQLTestCase):
|
||||||
|
|
||||||
def get_indexes(self, table):
|
def get_constraints(self, table):
|
||||||
"""
|
"""
|
||||||
Get the indexes on the table using a new cursor.
|
Get the indexes on the table using a new cursor.
|
||||||
"""
|
"""
|
||||||
with connection.cursor() as 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):
|
def test_gin_index(self):
|
||||||
# Ensure the table is there and doesn't have an index.
|
# 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
|
# Add the index
|
||||||
index = GinIndex(fields=['field'], name='integer_array_model_field_gin')
|
index = GinIndex(fields=['field'], name='integer_array_model_field_gin')
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.add_index(IntegerArrayModel, index)
|
editor.add_index(IntegerArrayModel, index)
|
||||||
self.assertIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
|
self.assertIn('integer_array_model_field_gin', self.get_constraints(IntegerArrayModel._meta.db_table))
|
||||||
self.assertEqual(self.get_indexes(IntegerArrayModel._meta.db_table)['field']['type'], 'gin')
|
constraints = self.get_constraints(IntegerArrayModel._meta.db_table)
|
||||||
|
self.assertEqual(constraints['integer_array_model_field_gin']['type'], 'gin')
|
||||||
# Drop the index
|
# Drop the index
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.remove_index(IntegerArrayModel, index)
|
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))
|
||||||
|
|
Loading…
Reference in New Issue