Commit 32256048 authored by Claude Paroz's avatar Claude Paroz
Browse files

[1.7.x] Fixed #24051 -- Made schema infrastructure honor tablespaces

Partial backport of 30cbd5d3. Thanks Douglas J. Reynolds for the
report and initial patch.
parent 2af33a07
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -254,6 +254,11 @@ class BaseDatabaseSchemaEditor(object):
            "table": self.quote_name(model._meta.db_table),
            "definition": ", ".join(column_sqls)
        }
        if model._meta.db_tablespace:
            tablespace_sql = self.connection.ops.tablespace_sql(model._meta.db_tablespace)
            if tablespace_sql:
                sql += ' ' + tablespace_sql

        self.execute(sql, params)

        # Add any field index and index_together's (deferred as SQLite3 _remake_table needs it)
+2 −0
Original line number Diff line number Diff line
@@ -170,3 +170,5 @@ Bugfixes

* Enabled the ``sqlsequencereset`` command on apps with migrations
  (:ticket:`24054`).

* Added tablespace SQL to apps with migrations (:ticket:`24051`).
+32 −12
Original line number Diff line number Diff line
@@ -10,20 +10,32 @@ from .models.tablespaces import (Article, ArticleRef, Authors, Reviewers,
    Scientist, ScientistRef)


def sql_for_table(model):
def sql_for_table_creation(model):
    return '\n'.join(connection.creation.sql_create_model(model,
                                                          no_style())[0])


def sql_for_index(model):
def sql_for_table_schema(model):
    with connection.schema_editor(collect_sql=True) as editor:
        editor.create_model(model)
    return editor.collected_sql[0]


def sql_for_index_creation(model):
    return '\n'.join(connection.creation.sql_indexes_for_model(model,
                                                               no_style()))


def sql_for_index_schema(model):
    return '\n'.join(connection.schema_editor()._model_indexes_sql(model))


# We can't test the DEFAULT_TABLESPACE and DEFAULT_INDEX_TABLESPACE settings
# because they're evaluated when the model class is defined. As a consequence,
# @override_settings doesn't work, and the tests depend
class TablespacesTests(TestCase):
    sql_for_table = staticmethod(sql_for_table_creation)
    sql_for_index = staticmethod(sql_for_index_creation)

    def setUp(self):
        # The unmanaged models need to be removed after the test in order to
@@ -48,7 +60,7 @@ class TablespacesTests(TestCase):

    @skipUnlessDBFeature('supports_tablespaces')
    def test_tablespace_for_model(self):
        sql = sql_for_table(Scientist).lower()
        sql = self.sql_for_table(Scientist).lower()
        if settings.DEFAULT_INDEX_TABLESPACE:
            # 1 for the table
            self.assertNumContains(sql, 'tbl_tbsp', 1)
@@ -61,12 +73,12 @@ class TablespacesTests(TestCase):
    @skipIfDBFeature('supports_tablespaces')
    def test_tablespace_ignored_for_model(self):
        # No tablespace-related SQL
        self.assertEqual(sql_for_table(Scientist),
                         sql_for_table(ScientistRef))
        self.assertEqual(self.sql_for_table(Scientist),
                         self.sql_for_table(ScientistRef))

    @skipUnlessDBFeature('supports_tablespaces')
    def test_tablespace_for_indexed_field(self):
        sql = sql_for_table(Article).lower()
        sql = self.sql_for_table(Article).lower()
        if settings.DEFAULT_INDEX_TABLESPACE:
            # 1 for the table
            self.assertNumContains(sql, 'tbl_tbsp', 1)
@@ -82,12 +94,12 @@ class TablespacesTests(TestCase):
    @skipIfDBFeature('supports_tablespaces')
    def test_tablespace_ignored_for_indexed_field(self):
        # No tablespace-related SQL
        self.assertEqual(sql_for_table(Article),
                         sql_for_table(ArticleRef))
        self.assertEqual(self.sql_for_table(Article),
                         self.sql_for_table(ArticleRef))

    @skipUnlessDBFeature('supports_tablespaces')
    def test_tablespace_for_many_to_many_field(self):
        sql = sql_for_table(Authors).lower()
        sql = self.sql_for_table(Authors).lower()
        # The join table of the ManyToManyField goes to the model's tablespace,
        # and its indexes too, unless DEFAULT_INDEX_TABLESPACE is set.
        if settings.DEFAULT_INDEX_TABLESPACE:
@@ -100,7 +112,7 @@ class TablespacesTests(TestCase):
            self.assertNumContains(sql, 'tbl_tbsp', 2)
        self.assertNumContains(sql, 'idx_tbsp', 0)

        sql = sql_for_index(Authors).lower()
        sql = self.sql_for_index(Authors).lower()
        # The ManyToManyField declares no db_tablespace, its indexes go to
        # the model's tablespace, unless DEFAULT_INDEX_TABLESPACE is set.
        if settings.DEFAULT_INDEX_TABLESPACE:
@@ -109,7 +121,7 @@ class TablespacesTests(TestCase):
            self.assertNumContains(sql, 'tbl_tbsp', 2)
        self.assertNumContains(sql, 'idx_tbsp', 0)

        sql = sql_for_table(Reviewers).lower()
        sql = self.sql_for_table(Reviewers).lower()
        # The join table of the ManyToManyField goes to the model's tablespace,
        # and its indexes too, unless DEFAULT_INDEX_TABLESPACE is set.
        if settings.DEFAULT_INDEX_TABLESPACE:
@@ -122,7 +134,15 @@ class TablespacesTests(TestCase):
            self.assertNumContains(sql, 'tbl_tbsp', 2)
        self.assertNumContains(sql, 'idx_tbsp', 0)

        sql = sql_for_index(Reviewers).lower()
        sql = self.sql_for_index(Reviewers).lower()
        # The ManyToManyField declares db_tablespace, its indexes go there.
        self.assertNumContains(sql, 'tbl_tbsp', 0)
        self.assertNumContains(sql, 'idx_tbsp', 2)


class TablespacesSchemaTests(TablespacesTests):
    """
    Same tests as TablespacesTests, but for the new schema infrastructure.
    """
    sql_for_table = staticmethod(sql_for_table_schema)
    sql_for_index = staticmethod(sql_for_index_schema)