Code

Ticket #18092: composite_indexes.diff

File composite_indexes.diff, 3.8 KB (added by ivan_virabyan, 2 years ago)
Line 
1Index: django/db/models/options.py
2===================================================================
3--- django/db/models/options.py (revision 17889)
4+++ django/db/models/options.py (working copy)
5@@ -28,6 +28,7 @@
6         self.db_table = ''
7         self.ordering = []
8         self.unique_together =  []
9+        self.composite_indexes = []
10         self.permissions =  []
11         self.object_name, self.app_label = None, app_label
12         self.get_latest_by = None
13@@ -97,6 +98,11 @@
14                 ut = (ut,)
15             self.unique_together = ut
16 
17+            ci = meta_attrs.pop('composite_indexes', self.composite_indexes)
18+            if ci and not isinstance(ci[0], (tuple, list)):
19+                ci = (ci,)
20+            self.composite_indexes = ci
21+
22             # verbose_name_plural is a special case because it uses a 's'
23             # by default.
24             if self.verbose_name_plural is None:
25Index: django/db/backends/creation.py
26===================================================================
27--- django/db/backends/creation.py      (revision 17889)
28+++ django/db/backends/creation.py      (working copy)
29@@ -164,34 +164,35 @@
30             return []
31         output = []
32         for f in model._meta.local_fields:
33-            output.extend(self.sql_indexes_for_field(model, f, style))
34+            if f.db_index and not f.unique:
35+                output.extend(self.sql_indexes_for_fields(model, [f], style, f.db_tablespace))
36+
37+        for fields in model._meta.composite_indexes:
38+            fields = [model._meta.get_field(f) for f in fields]
39+            output.extend(self.sql_indexes_for_fields(model, fields, style))
40         return output
41 
42-    def sql_indexes_for_field(self, model, f, style):
43+    def sql_indexes_for_fields(self, model, fields, style, tablespace=None):
44         """
45-        Return the CREATE INDEX SQL statements for a single model field.
46+        Return the CREATE INDEX SQL statements for model fields.
47         """
48         from django.db.backends.util import truncate_name
49-
50-        if f.db_index and not f.unique:
51-            qn = self.connection.ops.quote_name
52-            tablespace = f.db_tablespace or model._meta.db_tablespace
53-            if tablespace:
54-                tablespace_sql = self.connection.ops.tablespace_sql(tablespace)
55-                if tablespace_sql:
56-                    tablespace_sql = ' ' + tablespace_sql
57-            else:
58-                tablespace_sql = ''
59-            i_name = '%s_%s' % (model._meta.db_table, self._digest(f.column))
60-            output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
61-                style.SQL_TABLE(qn(truncate_name(
62-                    i_name, self.connection.ops.max_name_length()))) + ' ' +
63-                style.SQL_KEYWORD('ON') + ' ' +
64-                style.SQL_TABLE(qn(model._meta.db_table)) + ' ' +
65-                "(%s)" % style.SQL_FIELD(qn(f.column)) +
66-                "%s;" % tablespace_sql]
67+        qn = self.connection.ops.quote_name
68+        tablespace = tablespace or model._meta.db_tablespace
69+        if tablespace:
70+            tablespace_sql = self.connection.ops.tablespace_sql(tablespace)
71+            if tablespace_sql:
72+                tablespace_sql = ' ' + tablespace_sql
73         else:
74-            output = []
75+            tablespace_sql = ''
76+        i_name = '%s_%s' % (model._meta.db_table, self._digest(*[f.column for f in fields]))
77+        output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
78+            style.SQL_TABLE(qn(truncate_name(
79+                i_name, self.connection.ops.max_name_length()))) + ' ' +
80+            style.SQL_KEYWORD('ON') + ' ' +
81+            style.SQL_TABLE(qn(model._meta.db_table)) + ' ' +
82+            "(%s)" % ','.join(style.SQL_FIELD(qn(f.column)) for f in fields) +
83+            "%s;" % tablespace_sql]
84         return output
85 
86     def sql_destroy_model(self, model, references_to_delete, style):