Ticket #12308: 12308.patch
File 12308.patch, 22.8 KB (added by , 13 years ago) |
---|
-
docs/index.txt
66 66 :doc:`Transactions <topics/db/transactions>` | 67 67 :doc:`Aggregation <topics/db/aggregation>` | 68 68 :doc:`Custom fields <howto/custom-model-fields>` | 69 :doc:`Multiple databases <topics/db/multi-db>` 69 :doc:`Multiple databases <topics/db/multi-db>` | 70 :doc:`Tablespaces <topics/db/tablespaces>` 70 71 71 72 * **Other:** 72 73 :doc:`Supported databases <ref/databases>` | -
docs/howto/custom-model-fields.txt
218 218 * :attr:`~django.db.models.Field.choices` 219 219 * :attr:`~django.db.models.Field.help_text` 220 220 * :attr:`~django.db.models.Field.db_column` 221 * :attr:`~django.db.models.Field.db_tablespace`: Currently only used with222 the Oracle backend and only for index creation. You can usually ignore223 this option.221 * :attr:`~django.db.models.Field.db_tablespace`: Only for index creation, 222 if the backend supports :doc:`tablespaces </topics/db/tablespaces>`. You 223 can usually ignore this option. 224 224 * :attr:`~django.db.models.Field.auto_created`: True if the field was 225 225 automatically created, as for the `OneToOneField` used by model 226 226 inheritance. For advanced use only. -
docs/topics/db/tablespaces.txt
1 =========== 2 Tablespaces 3 =========== 4 5 A common paradigm for optimizing performance in database systems is the use of 6 `tablespaces`_ to organize disk layout. 7 8 .. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace 9 10 .. warning:: 11 Django does not create the tablespaces for you. Please refer to your 12 database engine's documentation for details on creating and managing 13 tablespaces. 14 15 16 Declaring tablespaces for tables 17 -------------------------------- 18 19 A tablespace can be specified for the table generated by a model by supplying 20 the :attr:`~django.db.models.Options.db_tablespace` option inside the model's 21 ``class Meta``. This option also affects tables automatically created for 22 :class:`~django.db.models.ManyToManyField`\ s in the model. 23 24 You can use the :setting:`DEFAULT_TABLESPACE` setting to specify a default value 25 for :attr:`~django.db.models.Options.db_tablespace`. These is useful for setting 26 a tablespace for the built-in Django apps and other applications whose code you 27 cannot control. 28 29 Declaring tablespaces for indexes 30 --------------------------------- 31 32 You can pass the :attr:`~django.db.models.Field.db_tablespace` option to a 33 ``Field`` constructor to specify an alternate tablespace for the ``Field``'s 34 column index. If no index would be created for the column, the option is 35 ignored. 36 37 You can use the :setting:`DEFAULT_INDEX_TABLESPACE` setting to specify 38 a default value for :attr:`~django.db.models.Field.db_tablespace`. 39 40 If :attr:`~django.db.models.Field.db_tablespace` isn't specified and you didn't 41 set :setting:`DEFAULT_INDEX_TABLESPACE`, the index is created in the same 42 tablespace as the tables. 43 44 An example 45 ---------- 46 47 .. code-block:: python 48 49 class TablespaceExample(models.Model): 50 name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes") 51 data = models.CharField(max_length=255, db_index=True) 52 edges = models.ManyToManyField(to="self", db_tablespace="indexes") 53 54 class Meta: 55 db_tablespace = "tables" 56 57 In this example, the tables generated by the ``TablespaceExample`` model (i.e. 58 the model table and the many-to-many table) would be stored in the ``tables`` 59 tablespace. The index for the name field and the indexes on the many-to-many 60 table would be stored in the ``indexes`` tablespace. The ``data`` field would 61 also generate an index, but no tablespace for it is specified, so it would be 62 stored in the model tablespace ``tables`` by default. 63 64 Database support 65 ---------------- 66 67 PostgreSQL and Oracle support tablespaces. SQLite and MySQL don't. 68 69 When you use a backend that lacks support for tablespaces, Django ignores all 70 tablespace-related options. 71 72 .. versionchanged:: 1.4 73 Since Django 1.4, the PostgreSQL backend supports tablespaces. -
docs/topics/db/index.txt
17 17 sql 18 18 transactions 19 19 multi-db 20 tablespaces 20 21 optimization -
docs/releases/1.4.txt
245 245 code are slightly emphasized. This change makes it easier to scan a stacktrace 246 246 for issues in user code. 247 247 248 * :doc:`Tablespace support </topics/db/tablespaces>` in PostgreSQL. 249 248 250 * Customizable names for :meth:`~django.template.Library.simple_tag`. 249 251 250 252 * In the documentation, a helpful :doc:`security overview </topics/security>` -
docs/ref/models/fields.txt
178 178 179 179 .. attribute:: Field.db_tablespace 180 180 181 The name of the database tablespace to use for this field's index, if this field 182 is indexed. The default is the project's :setting:`DEFAULT_INDEX_TABLESPACE` 183 setting, if set, or the :attr:`~Field.db_tablespace` of the model, if any. If 184 the backend doesn't support tablespaces, this option is ignored. 181 The name of the :doc:`database tablespace </topics/db/tablespaces>` to use for 182 this field's index, if this field is indexed. The default is the project's 183 :setting:`DEFAULT_INDEX_TABLESPACE` setting, if set, or the 184 :attr:`~Options.db_tablespace` of the model, if any. If the backend doesn't 185 support tablespaces for indexes, this option is ignored. 185 186 186 187 ``default`` 187 188 ----------- -
docs/ref/models/options.txt
66 66 67 67 .. attribute:: Options.db_tablespace 68 68 69 The name of the database tablespace to use for the model. If the backend 70 doesn't support tablespaces, this option is ignored. 69 The name of the :doc:`database tablespace </topics/db/tablespaces>` to use 70 for this model. The default is the project's :setting:`DEFAULT_TABLESPACE` 71 setting, if set. If the backend doesn't support tablespaces, this option is 72 ignored. 71 73 72 74 ``get_latest_by`` 73 75 ----------------- -
docs/ref/databases.txt
620 620 In this case, the Oracle backend will use a separate ``SELECT`` query to 621 621 retrieve AutoField values. 622 622 623 Tablespace options624 ------------------625 626 A common paradigm for optimizing performance in Oracle-based systems is the627 use of `tablespaces`_ to organize disk layout. The Oracle backend supports628 this use case by adding ``db_tablespace`` options to the ``Meta`` and629 ``Field`` classes. (When you use a backend that lacks support for tablespaces,630 Django ignores these options.)631 632 .. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace633 634 A tablespace can be specified for the table(s) generated by a model by635 supplying the ``db_tablespace`` option inside the model's ``class Meta``.636 Additionally, you can pass the ``db_tablespace`` option to a ``Field``637 constructor to specify an alternate tablespace for the ``Field``'s column638 index. If no index would be created for the column, the ``db_tablespace``639 option is ignored::640 641 class TablespaceExample(models.Model):642 name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")643 data = models.CharField(max_length=255, db_index=True)644 edges = models.ManyToManyField(to="self", db_tablespace="indexes")645 646 class Meta:647 db_tablespace = "tables"648 649 In this example, the tables generated by the ``TablespaceExample`` model650 (i.e., the model table and the many-to-many table) would be stored in the651 ``tables`` tablespace. The index for the name field and the indexes on the652 many-to-many table would be stored in the ``indexes`` tablespace. The ``data``653 field would also generate an index, but no tablespace for it is specified, so654 it would be stored in the model tablespace ``tables`` by default.655 656 Use the :setting:`DEFAULT_TABLESPACE` and :setting:`DEFAULT_INDEX_TABLESPACE`657 settings to specify default values for the db_tablespace options.658 These are useful for setting a tablespace for the built-in Django apps and659 other applications whose code you cannot control.660 661 Django does not create the tablespaces for you. Please refer to `Oracle's662 documentation`_ for details on creating and managing tablespaces.663 664 .. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403665 666 623 Naming issues 667 624 ------------- 668 625 -
docs/ref/settings.txt
857 857 Default: ``''`` (Empty string) 858 858 859 859 Default tablespace to use for indexes on fields that don't specify 860 one, if the backend supports it .860 one, if the backend supports it (see :doc:`/topics/db/tablespaces`). 861 861 862 862 .. setting:: DEFAULT_TABLESPACE 863 863 … … 867 867 Default: ``''`` (Empty string) 868 868 869 869 Default tablespace to use for models that don't specify one, if the 870 backend supports it .870 backend supports it (see :doc:`/topics/db/tablespaces`). 871 871 872 872 .. setting:: DISALLOWED_USER_AGENTS 873 873 -
tests/modeltests/tablespaces/tests.py
1 from django.db import connection 2 from django.db import models 3 from django.core.management.color import no_style 4 from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature 5 6 from models import Article, ArticleRef, Scientist, ScientistRef 7 8 # Automatically created models 9 Authors = Article._meta.get_field('authors').rel.through 10 Reviewers = Article._meta.get_field('reviewers').rel.through 11 12 # We can't test the DEFAULT_TABLESPACE and DEFAULT_INDEX_TABLESPACE settings 13 # because they're evaluated when the model class is defined. As a consequence, 14 # @override_settings doesn't work. 15 16 def sql_for_table(model): 17 return '\n'.join(connection.creation.sql_create_model(model, no_style())[0]) 18 19 def sql_for_index(model): 20 return '\n'.join(connection.creation.sql_indexes_for_model(model, no_style())) 21 22 23 class TablespacesTests(TestCase): 24 25 def setUp(self): 26 for model in Article, Authors, Reviewers, Scientist: 27 model._meta.managed = True 28 29 def tearDown(self): 30 for model in Article, Authors, Reviewers, Scientist: 31 model._meta.managed = False 32 33 def assertNumContains(self, haystack, needle, count): 34 real_count = haystack.count(needle) 35 self.assertEqual(real_count, count, "Found %d instances of '%s', " 36 "expected %d" % (real_count, needle, count)) 37 38 @skipUnlessDBFeature('supports_tablespaces') 39 def test_tablespace_for_model(self): 40 # 1 for the table + 1 for the index on the primary key 41 self.assertNumContains(sql_for_table(Scientist), 'tbl_tbsp', 2) 42 43 @skipIfDBFeature('supports_tablespaces') 44 def test_tablespace_ignored_for_model(self): 45 # No tablespace-related SQL 46 self.assertEqual(sql_for_table(Scientist), 47 sql_for_table(ScientistRef).replace('ref', '')) 48 49 @skipUnlessDBFeature('supports_tablespaces') 50 def test_tablespace_for_indexed_field(self): 51 # 1 for the table + 1 for the primary key + 1 for the index on name 52 self.assertNumContains(sql_for_table(Article), 'tbl_tbsp', 3) 53 # 1 for the index on reference 54 self.assertNumContains(sql_for_table(Article), 'idx_tbsp', 1) 55 56 @skipIfDBFeature('supports_tablespaces') 57 def test_tablespace_ignored_for_indexed_field(self): 58 # No tablespace-related SQL 59 self.assertEqual(sql_for_table(Article), 60 sql_for_table(ArticleRef).replace('ref', '')) 61 62 @skipUnlessDBFeature('supports_tablespaces') 63 def test_tablespace_for_many_to_many_field(self): 64 # The join table of the ManyToManyField always goes to the tablespace 65 # of the model. 66 self.assertNumContains(sql_for_table(Authors), 'tbl_tbsp', 2) 67 self.assertNumContains(sql_for_table(Authors), 'idx_tbsp', 0) 68 # The ManyToManyField declares no db_tablespace, indexes for the two 69 # foreign keys in the join table go to the tablespace of the model. 70 self.assertNumContains(sql_for_index(Authors), 'tbl_tbsp', 2) 71 self.assertNumContains(sql_for_index(Authors), 'idx_tbsp', 0) 72 73 # The join table of the ManyToManyField always goes to the tablespace 74 # of the model. 75 self.assertNumContains(sql_for_table(Reviewers), 'tbl_tbsp', 2) 76 self.assertNumContains(sql_for_table(Reviewers), 'idx_tbsp', 0) 77 # The ManyToManyField declares db_tablespace, indexes for the two 78 # foreign keys in the join table go to this tablespace. 79 self.assertNumContains(sql_for_index(Reviewers), 'tbl_tbsp', 0) 80 self.assertNumContains(sql_for_index(Reviewers), 'idx_tbsp', 2) -
tests/modeltests/tablespaces/models.py
1 from django.db import models 2 3 # Since the test database doesn't have tablespaces, it's impossible for Django 4 # to create the tables for models where db_tablespace is set. To avoid this 5 # problem, we mark the models as unmanaged, and temporarily revert them to 6 # managed during each test (see setUp and tearDown). 7 8 class ScientistRef(models.Model): 9 name = models.CharField(max_length=50) 10 11 class ArticleRef(models.Model): 12 title = models.CharField(max_length=50, unique=True) 13 code = models.CharField(max_length=50, unique=True) 14 authors = models.ManyToManyField(ScientistRef, related_name='articles_written_set') 15 reviewers = models.ManyToManyField(ScientistRef, related_name='articles_reviewed_set') 16 17 class Scientist(models.Model): 18 name = models.CharField(max_length=50) 19 class Meta: 20 db_tablespace = 'tbl_tbsp' 21 managed = False 22 23 class Article(models.Model): 24 title = models.CharField(max_length=50, unique=True) 25 code = models.CharField(max_length=50, unique=True, db_tablespace='idx_tbsp') 26 authors = models.ManyToManyField(Scientist, related_name='articles_written_set') 27 reviewers = models.ManyToManyField(Scientist, related_name='articles_reviewed_set', db_tablespace='idx_tbsp') 28 class Meta: 29 db_tablespace = 'tbl_tbsp' 30 managed = False -
django/db/models/fields/related.py
988 988 'managed': managed, 989 989 'auto_created': klass, 990 990 'app_label': klass._meta.app_label, 991 'db_tablespace': klass._meta.db_tablespace, 991 992 'unique_together': (from_, to), 992 993 'verbose_name': '%(from)s-%(to)s relationship' % {'from': from_, 'to': to}, 993 994 'verbose_name_plural': '%(from)s-%(to)s relationships' % {'from': from_, 'to': to}, … … 996 997 return type(name, (models.Model,), { 997 998 'Meta': meta, 998 999 '__module__': klass.__module__, 999 from_: models.ForeignKey(klass, related_name='%s+' % name ),1000 to: models.ForeignKey(to_model, related_name='%s+' % name )1000 from_: models.ForeignKey(klass, related_name='%s+' % name, db_tablespace=field.db_tablespace), 1001 to: models.ForeignKey(to_model, related_name='%s+' % name, db_tablespace=field.db_tablespace) 1001 1002 }) 1002 1003 1003 1004 class ManyToManyField(RelatedField, Field): -
django/db/backends/oracle/base.py
78 78 supports_bitwise_or = False 79 79 can_defer_constraint_checks = True 80 80 ignores_nulls_in_unique_constraints = False 81 supports_tablespaces = True 81 82 82 83 class DatabaseOperations(BaseDatabaseOperations): 83 84 compiler_module = "django.db.backends.oracle.compiler" … … 325 326 return '' 326 327 327 328 def tablespace_sql(self, tablespace, inline=False): 328 return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), 329 self.quote_name(tablespace)) 329 if inline: 330 return "USING INDEX TABLESPACE %s" % self.quote_name(tablespace) 331 else: 332 return "TABLESPACE %s" % self.quote_name(tablespace) 330 333 331 334 def value_to_db_datetime(self, value): 332 335 # Oracle doesn't support tz-aware datetimes -
django/db/backends/__init__.py
364 364 # date_interval_sql can properly handle mixed Date/DateTime fields and timedeltas 365 365 supports_mixed_date_datetime_comparisons = True 366 366 367 # Does the backend support tablespaces? Default to False because it isn't 368 # in the SQL standard. 369 supports_tablespaces = False 370 367 371 # Features that need to be confirmed at runtime 368 372 # Cache whether the confirmation has been performed. 369 373 _confirmed = False … … 695 699 696 700 def tablespace_sql(self, tablespace, inline=False): 697 701 """ 698 Returns the SQL that will be appended to tables or rows to define 699 a tablespace. Returns '' if the backend doesn't use tablespaces. 702 Returns the SQL that will be used in a query to define the tablespace. 703 704 Returns '' if the backend doesn't support tablespaces. 705 706 If inline is True, the SQL is appended to a row; otherwise it's appended 707 to the entire CREATE TABLE or CREATE INDEX statement. 700 708 """ 701 709 return '' 702 710 -
django/db/backends/postgresql_psycopg2/base.py
71 71 can_defer_constraint_checks = True 72 72 has_select_for_update = True 73 73 has_select_for_update_nowait = True 74 supports_tablespaces = True 74 75 75 76 76 77 class DatabaseWrapper(BaseDatabaseWrapper): -
django/db/backends/postgresql_psycopg2/operations.py
99 99 else: 100 100 return [] 101 101 102 def tablespace_sql(self, tablespace, inline=False): 103 if inline: 104 return "USING INDEX TABLESPACE %s" % self.quote_name(tablespace) 105 else: 106 return "TABLESPACE %s" % self.quote_name(tablespace) 107 102 108 def sequence_reset_sql(self, style, model_list): 103 109 from django.db import models 104 110 output = [] -
django/db/backends/postgresql_psycopg2/creation.py
44 44 db_table = model._meta.db_table 45 45 tablespace = f.db_tablespace or model._meta.db_tablespace 46 46 if tablespace: 47 sql = self.connection.ops.tablespace_sql(tablespace) 48 if sql: 49 tablespace_sql = ' ' + sql 50 else: 51 tablespace_sql = '' 47 tablespace_sql = self.connection.ops.tablespace_sql(tablespace) 48 if tablespace_sql: 49 tablespace_sql = ' ' + tablespace_sql 52 50 else: 53 51 tablespace_sql = '' 54 52 -
django/db/backends/creation.py
57 57 if tablespace and f.unique: 58 58 # We must specify the index tablespace inline, because we 59 59 # won't be generating a CREATE INDEX statement for this field. 60 field_output.append(self.connection.ops.tablespace_sql(tablespace, inline=True)) 60 tablespace_sql = self.connection.ops.tablespace_sql(tablespace, inline=True) 61 if tablespace_sql: 62 field_output.append(tablespace_sql) 61 63 if f.rel: 62 64 ref_output, pending = self.sql_for_inline_foreign_key_references(f, known_models, style) 63 65 if pending: … … 74 76 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 75 77 full_statement.append(')') 76 78 if opts.db_tablespace: 77 full_statement.append(self.connection.ops.tablespace_sql(opts.db_tablespace)) 79 tablespace_sql = self.connection.ops.tablespace_sql(opts.db_tablespace) 80 if tablespace_sql: 81 full_statement.append(tablespace_sql) 78 82 full_statement.append(';') 79 83 final_output.append('\n'.join(full_statement)) 80 84 … … 149 153 qn = self.connection.ops.quote_name 150 154 tablespace = f.db_tablespace or model._meta.db_tablespace 151 155 if tablespace: 152 sql = self.connection.ops.tablespace_sql(tablespace) 153 if sql: 154 tablespace_sql = ' ' + sql 155 else: 156 tablespace_sql = '' 156 tablespace_sql = self.connection.ops.tablespace_sql(tablespace) 157 if tablespace_sql: 158 tablespace_sql = ' ' + tablespace_sql 157 159 else: 158 160 tablespace_sql = '' 159 161 i_name = '%s_%s' % (model._meta.db_table, self._digest(f.column))