浏览代码

Fixed #27097 -- Added index type introspection to built-in db backends.

Akshesh 8 年之前
父节点
当前提交
dbccf163b6

+ 0 - 3
django/db/backends/base/features.py

@@ -163,9 +163,6 @@ class BaseDatabaseFeatures(object):
     # Can the backend introspect the column order (ASC/DESC) for indexes?
     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
     can_distinct_on_fields = False
 

+ 2 - 0
django/db/backends/base/introspection.py

@@ -172,6 +172,8 @@ class BaseDatabaseIntrospection(object):
          * foreign_key: (table, column) of target, or None
          * check: True if check constraint, False otherwise
          * index: True if index, False otherwise.
+         * orders: The order (ASC/DESC) defined for the columns of indexes
+         * type: The type of the index (btree, hash, etc.)
 
         Some backends may return special constraint names that don't exist
         if they don't name constraints of a certain type (e.g. SQLite)

+ 2 - 2
django/db/backends/mysql/introspection.py

@@ -201,17 +201,17 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                 constraints[constraint]['unique'] = True
         # Now add in the indexes
         cursor.execute("SHOW INDEX FROM %s" % self.connection.ops.quote_name(table_name))
-        for table, non_unique, index, colseq, column in [x[:5] for x in cursor.fetchall()]:
+        for table, non_unique, index, colseq, column, type_ in [x[:5] + (x[10],) for x in cursor.fetchall()]:
             if index not in constraints:
                 constraints[index] = {
                     'columns': OrderedSet(),
                     'primary_key': False,
                     'unique': False,
-                    'index': True,
                     'check': False,
                     'foreign_key': None,
                 }
             constraints[index]['index'] = True
+            constraints[index]['type'] = type_.lower()
             constraints[index]['columns'].add(column)
         # Convert the sorted sets to lists
         for constraint in constraints.values():

+ 7 - 6
django/db/backends/oracle/introspection.py

@@ -258,20 +258,20 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
         # Now get indexes
         cursor.execute("""
             SELECT
-                index_name,
-                LOWER(column_name), descend
+                cols.index_name, LOWER(cols.column_name), cols.descend,
+                LOWER(ind.index_type)
             FROM
-                user_ind_columns cols
+                user_ind_columns cols, user_indexes ind
             WHERE
-                table_name = UPPER(%s) AND
+                cols.table_name = UPPER(%s) AND
                 NOT EXISTS (
                     SELECT 1
                     FROM user_constraints cons
                     WHERE cols.index_name = cons.index_name
-                )
+                ) AND cols.index_name = ind.index_name
             ORDER BY cols.column_position
         """, [table_name])
-        for constraint, column, order in cursor.fetchall():
+        for constraint, column, order, type_ in cursor.fetchall():
             # If we're the first column, make the record
             if constraint not in constraints:
                 constraints[constraint] = {
@@ -282,6 +282,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                     "foreign_key": None,
                     "check": False,
                     "index": True,
+                    "type": 'btree' if type_ == 'normal' else type_,
                 }
             # Record the details
             constraints[constraint]['columns'].append(column)

+ 0 - 1
django/db/backends/postgresql/features.py

@@ -22,7 +22,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     can_introspect_autofield = True
     can_introspect_ip_address_field = True
     can_introspect_small_integer_field = True
-    can_introspect_index_type = True
     can_distinct_on_fields = True
     can_rollback_ddl = True
     supports_combined_alters = True

+ 3 - 1
django/db/backends/sqlite3/introspection.py

@@ -255,8 +255,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                         "index": True,
                     }
                 constraints[index]['columns'].append(column)
-            # Add column orders for indexes
+            # Add type and column orders for indexes
             if constraints[index]['index'] and not constraints[index]['unique']:
+                # SQLite doesn't support any index type other than b-tree
+                constraints[index]['type'] = 'btree'
                 cursor.execute(
                     "SELECT sql FROM sqlite_master "
                     "WHERE type='index' AND name=%s" % self.connection.ops.quote_name(index)

+ 4 - 3
tests/introspection/tests.py

@@ -184,13 +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)
+        index = {}
         for key, val in constraints.items():
-            if val['index'] and not (val['primary_key'] or val['unique']):
-                self.assertEqual(val['type'], 'btree')
+            if val['columns'] == ['headline', 'pub_date']:
+                index = val
+        self.assertEqual(index['type'], 'btree')
 
     @skipUnlessDBFeature('supports_index_column_ordering')
     def test_get_constraints_indexes_orders(self):

+ 5 - 4
tests/postgres_tests/test_indexes.py

@@ -44,13 +44,14 @@ class SchemaTests(PostgreSQLTestCase):
         # Ensure the table is there and doesn't have an index.
         self.assertNotIn('field', self.get_constraints(IntegerArrayModel._meta.db_table))
         # Add the index
-        index = GinIndex(fields=['field'], name='integer_array_model_field_gin')
+        index_name = 'integer_array_model_field_gin'
+        index = GinIndex(fields=['field'], name=index_name)
         with connection.schema_editor() as editor:
             editor.add_index(IntegerArrayModel, index)
-        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')
+        # Check gin index was added
+        self.assertEqual(constraints[index_name]['type'], 'gin')
         # Drop the index
         with connection.schema_editor() as editor:
             editor.remove_index(IntegerArrayModel, index)
-        self.assertNotIn('integer_array_model_field_gin', self.get_constraints(IntegerArrayModel._meta.db_table))
+        self.assertNotIn(index_name, self.get_constraints(IntegerArrayModel._meta.db_table))