Ticket #12308: 12308.3.patch
File 12308.3.patch, 23.4 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
262 262 code are slightly emphasized. This change makes it easier to scan a stacktrace 263 263 for issues in user code. 264 264 265 * :doc:`Tablespace support </topics/db/tablespaces>` in PostgreSQL. 266 265 267 * Customizable names for :meth:`~django.template.Library.simple_tag`. 266 268 267 269 * 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
633 633 In this case, the Oracle backend will use a separate ``SELECT`` query to 634 634 retrieve AutoField values. 635 635 636 Tablespace options637 ------------------638 639 A common paradigm for optimizing performance in Oracle-based systems is the640 use of `tablespaces`_ to organize disk layout. The Oracle backend supports641 this use case by adding ``db_tablespace`` options to the ``Meta`` and642 ``Field`` classes. (When you use a backend that lacks support for tablespaces,643 Django ignores these options.)644 645 .. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace646 647 A tablespace can be specified for the table(s) generated by a model by648 supplying the ``db_tablespace`` option inside the model's ``class Meta``.649 Additionally, you can pass the ``db_tablespace`` option to a ``Field``650 constructor to specify an alternate tablespace for the ``Field``'s column651 index. If no index would be created for the column, the ``db_tablespace``652 option is ignored::653 654 class TablespaceExample(models.Model):655 name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")656 data = models.CharField(max_length=255, db_index=True)657 edges = models.ManyToManyField(to="self", db_tablespace="indexes")658 659 class Meta:660 db_tablespace = "tables"661 662 In this example, the tables generated by the ``TablespaceExample`` model663 (i.e., the model table and the many-to-many table) would be stored in the664 ``tables`` tablespace. The index for the name field and the indexes on the665 many-to-many table would be stored in the ``indexes`` tablespace. The ``data``666 field would also generate an index, but no tablespace for it is specified, so667 it would be stored in the model tablespace ``tables`` by default.668 669 Use the :setting:`DEFAULT_TABLESPACE` and :setting:`DEFAULT_INDEX_TABLESPACE`670 settings to specify default values for the db_tablespace options.671 These are useful for setting a tablespace for the built-in Django apps and672 other applications whose code you cannot control.673 674 Django does not create the tablespaces for you. Please refer to `Oracle's675 documentation`_ for details on creating and managing tablespaces.676 677 .. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403678 679 636 Naming issues 680 637 ------------- 681 638 -
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 import copy 2 3 from django.db import connection 4 from django.db import models 5 from django.db.models.loading import cache 6 from django.core.management.color import no_style 7 from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature 8 9 from models import Article, ArticleRef, Scientist, ScientistRef 10 11 # Automatically created models 12 Authors = Article._meta.get_field('authors').rel.through 13 Reviewers = Article._meta.get_field('reviewers').rel.through 14 15 # We can't test the DEFAULT_TABLESPACE and DEFAULT_INDEX_TABLESPACE settings 16 # because they're evaluated when the model class is defined. As a consequence, 17 # @override_settings doesn't work. 18 19 def sql_for_table(model): 20 return '\n'.join(connection.creation.sql_create_model(model, no_style())[0]) 21 22 def sql_for_index(model): 23 return '\n'.join(connection.creation.sql_indexes_for_model(model, no_style())) 24 25 26 class TablespacesTests(TestCase): 27 28 @classmethod 29 def setUpClass(cls): 30 # The unmanaged models need to be removed after the test in order to 31 # prevent bad interactions with other tests (proxy_models_inheritance). 32 cls.old_app_models = copy.deepcopy(cache.app_models) 33 cls.old_app_store = copy.deepcopy(cache.app_store) 34 35 for model in Article, Authors, Reviewers, Scientist: 36 model._meta.managed = True 37 38 @classmethod 39 def tearDownClass(cls): 40 for model in Article, Authors, Reviewers, Scientist: 41 model._meta.managed = False 42 43 cache.app_models = cls.old_app_models 44 cache.app_store = cls.old_app_store 45 cache._get_models_cache = {} 46 47 def assertNumContains(self, haystack, needle, count): 48 real_count = haystack.count(needle) 49 self.assertEqual(real_count, count, "Found %d instances of '%s', " 50 "expected %d" % (real_count, needle, count)) 51 52 @skipUnlessDBFeature('supports_tablespaces') 53 def test_tablespace_for_model(self): 54 # 1 for the table + 1 for the index on the primary key 55 self.assertNumContains(sql_for_table(Scientist), 'tbl_tbsp', 2) 56 57 @skipIfDBFeature('supports_tablespaces') 58 def test_tablespace_ignored_for_model(self): 59 # No tablespace-related SQL 60 self.assertEqual(sql_for_table(Scientist), 61 sql_for_table(ScientistRef).replace('ref', '')) 62 63 @skipUnlessDBFeature('supports_tablespaces') 64 def test_tablespace_for_indexed_field(self): 65 # 1 for the table + 1 for the primary key + 1 for the index on name 66 self.assertNumContains(sql_for_table(Article), 'tbl_tbsp', 3) 67 # 1 for the index on reference 68 self.assertNumContains(sql_for_table(Article), 'idx_tbsp', 1) 69 70 @skipIfDBFeature('supports_tablespaces') 71 def test_tablespace_ignored_for_indexed_field(self): 72 # No tablespace-related SQL 73 self.assertEqual(sql_for_table(Article), 74 sql_for_table(ArticleRef).replace('ref', '')) 75 76 @skipUnlessDBFeature('supports_tablespaces') 77 def test_tablespace_for_many_to_many_field(self): 78 # The join table of the ManyToManyField always goes to the tablespace 79 # of the model. 80 self.assertNumContains(sql_for_table(Authors), 'tbl_tbsp', 2) 81 self.assertNumContains(sql_for_table(Authors), 'idx_tbsp', 0) 82 # The ManyToManyField declares no db_tablespace, indexes for the two 83 # foreign keys in the join table go to the tablespace of the model. 84 self.assertNumContains(sql_for_index(Authors), 'tbl_tbsp', 2) 85 self.assertNumContains(sql_for_index(Authors), 'idx_tbsp', 0) 86 87 # The join table of the ManyToManyField always goes to the tablespace 88 # of the model. 89 self.assertNumContains(sql_for_table(Reviewers), 'tbl_tbsp', 2) 90 self.assertNumContains(sql_for_table(Reviewers), 'idx_tbsp', 0) 91 # The ManyToManyField declares db_tablespace, indexes for the two 92 # foreign keys in the join table go to this tablespace. 93 self.assertNumContains(sql_for_index(Reviewers), 'tbl_tbsp', 0) 94 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 setUpClass and tearDownClass). 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
74 74 can_defer_constraint_checks = True 75 75 has_select_for_update = True 76 76 has_select_for_update_nowait = True 77 supports_tablespaces = True 77 78 78 79 79 80 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))