From ae19315b4d8a19eda07ea8f313c485ca0a7875d0 Mon Sep 17 00:00:00 2001
From: Andrew Godwin <andrew@aeracode.org>
Date: Sun, 11 Aug 2013 14:23:31 +0100
Subject: [PATCH] Support index_together during model creation

---
 django/db/backends/schema.py                |  9 +++++++++
 django/db/backends/sqlite3/introspection.py |  5 ++++-
 tests/schema/models.py                      |  9 +++++++++
 tests/schema/tests.py                       | 19 ++++++++++++++++++-
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py
index 1e1376a4e2..d868bf79b5 100644
--- a/django/db/backends/schema.py
+++ b/django/db/backends/schema.py
@@ -210,6 +210,15 @@ class BaseDatabaseSchemaEditor(object):
             "definition": ", ".join(column_sqls)
         }
         self.execute(sql, params)
+        # Add any index_togethers
+        for fields in model._meta.index_together:
+            columns = [model._meta.get_field_by_name(field)[0].column for field in fields]
+            self.execute(self.sql_create_index % {
+                "table": self.quote_name(model._meta.db_table),
+                "name": self._create_index_name(model, columns, suffix="_idx"),
+                "columns": ", ".join(self.quote_name(column) for column in columns),
+                "extra": "",
+            })
         # Make M2M tables
         for field in model._meta.local_many_to_many:
             self.create_model(field.rel.through)
diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py
index 2e674bc05b..92777dd910 100644
--- a/django/db/backends/sqlite3/introspection.py
+++ b/django/db/backends/sqlite3/introspection.py
@@ -168,7 +168,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
         """
         # Don't use PRAGMA because that causes issues with some transactions
         cursor.execute("SELECT sql FROM sqlite_master WHERE tbl_name = %s AND type = %s", [table_name, "table"])
-        results = cursor.fetchone()[0].strip()
+        row = cursor.fetchone()
+        if row is None:
+            raise ValueError("Table %s does not exist" % table_name)
+        results = row[0].strip()
         results = results[results.index('(') + 1:results.rindex(')')]
         for field_desc in results.split(','):
             field_desc = field_desc.strip()
diff --git a/tests/schema/models.py b/tests/schema/models.py
index a160b9aaa8..69cf06f3c4 100644
--- a/tests/schema/models.py
+++ b/tests/schema/models.py
@@ -62,6 +62,15 @@ class Tag(models.Model):
         app_cache = new_app_cache
 
 
+class TagIndexed(models.Model):
+    title = models.CharField(max_length=255)
+    slug = models.SlugField(unique=True)
+
+    class Meta:
+        app_cache = new_app_cache
+        index_together = [["slug", "title"]]
+
+
 class TagUniqueRename(models.Model):
     title = models.CharField(max_length=255)
     slug2 = models.SlugField(unique=True)
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index 3a82cd15ff..f6e45599b8 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -6,7 +6,7 @@ from django.db import connection, DatabaseError, IntegrityError
 from django.db.models.fields import IntegerField, TextField, CharField, SlugField
 from django.db.models.fields.related import ManyToManyField, ForeignKey
 from django.db.transaction import atomic
-from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagUniqueRename, UniqueTest
+from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagUniqueRename, UniqueTest
 
 
 class SchemaTests(TransactionTestCase):
@@ -503,6 +503,23 @@ class SchemaTests(TransactionTestCase):
             ),
         )
 
+    def test_create_index_together(self):
+        """
+        Tests creating models with index_together already defined
+        """
+        # Create the table
+        with connection.schema_editor() as editor:
+            editor.create_model(TagIndexed)
+        # Ensure there is an index
+        self.assertEqual(
+            True,
+            any(
+                c["index"]
+                for c in connection.introspection.get_constraints(connection.cursor(), "schema_tagindexed").values()
+                if c['columns'] == ["slug", "title"]
+            ),
+        )
+
     def test_db_table(self):
         """
         Tests renaming of the table