Browse Source

Fixed #28990 -- Added autosummarize parameter to BrinIndex.

Nick Pope 7 years ago
parent
commit
d6381d3559

+ 6 - 1
django/contrib/postgres/indexes.py

@@ -31,20 +31,25 @@ class PostgresIndex(Index):
 class BrinIndex(PostgresIndex):
     suffix = 'brin'
 
-    def __init__(self, *, pages_per_range=None, **kwargs):
+    def __init__(self, *, autosummarize=None, pages_per_range=None, **kwargs):
         if pages_per_range is not None and pages_per_range <= 0:
             raise ValueError('pages_per_range must be None or a positive integer')
+        self.autosummarize = autosummarize
         self.pages_per_range = pages_per_range
         super().__init__(**kwargs)
 
     def deconstruct(self):
         path, args, kwargs = super().deconstruct()
+        if self.autosummarize is not None:
+            kwargs['autosummarize'] = self.autosummarize
         if self.pages_per_range is not None:
             kwargs['pages_per_range'] = self.pages_per_range
         return path, args, kwargs
 
     def get_with_params(self):
         with_params = []
+        if self.autosummarize is not None:
+            with_params.append('autosummarize = %s' % ('on' if self.autosummarize else 'off'))
         if self.pages_per_range is not None:
             with_params.append('pages_per_range = %d' % self.pages_per_range)
         return with_params

+ 5 - 0
django/db/backends/postgresql/features.py

@@ -57,7 +57,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     def is_postgresql_9_5(self):
         return self.connection.pg_version >= 90500
 
+    @cached_property
+    def is_postgresql_10(self):
+        return self.connection.pg_version >= 100000
+
     has_select_for_update_skip_locked = is_postgresql_9_5
     has_brin_index_support = is_postgresql_9_5
     has_jsonb_agg = is_postgresql_9_5
+    has_brin_autosummarize = is_postgresql_10
     has_gin_pending_list_limit = is_postgresql_9_5

+ 10 - 1
docs/ref/contrib/postgres/indexes.txt

@@ -10,13 +10,22 @@ available from the ``django.contrib.postgres.indexes`` module.
 ``BrinIndex``
 =============
 
-.. class:: BrinIndex(pages_per_range=None, **options)
+.. class:: BrinIndex(autosummarize=None, pages_per_range=None, **options)
 
     Creates a `BRIN index
     <https://www.postgresql.org/docs/current/static/brin-intro.html>`_.
 
+    Set the ``autosummarize`` parameter to ``True`` to enable `automatic
+    summarization`_ to be performed by autovacuum.
+
     The ``pages_per_range`` argument takes a positive integer.
 
+    .. _automatic summarization: https://www.postgresql.org/docs/current/static/brin-intro.html#BRIN-OPERATION
+
+    .. versionchanged:: 2.2
+
+        The ``autosummarize`` parameter was added.
+
 ``GinIndex``
 ============
 

+ 3 - 0
docs/releases/2.2.txt

@@ -86,6 +86,9 @@ Minor features
   :class:`~django.contrib.postgres.indexes.SpGistIndex` classes allow
   creating ``hash`` and ``SP-GiST`` indexes in the database.
 
+* :class:`~django.contrib.postgres.indexes.BrinIndex` now has the
+  ``autosummarize`` parameter.
+
 :mod:`django.contrib.redirects`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

+ 1 - 0
docs/spelling_wordlist

@@ -42,6 +42,7 @@ autoextend
 autogenerated
 autoincrement
 autoreload
+autovacuum
 Azerbaijani
 backend
 backends

+ 20 - 2
tests/postgres_tests/test_indexes.py

@@ -31,11 +31,16 @@ class BrinIndexTests(IndexTestMixin, PostgreSQLTestCase):
         self.assertEqual(BrinIndex.suffix, 'brin')
 
     def test_deconstruction(self):
-        index = BrinIndex(fields=['title'], name='test_title_brin', pages_per_range=16)
+        index = BrinIndex(fields=['title'], name='test_title_brin', autosummarize=True, pages_per_range=16)
         path, args, kwargs = index.deconstruct()
         self.assertEqual(path, 'django.contrib.postgres.indexes.BrinIndex')
         self.assertEqual(args, ())
-        self.assertEqual(kwargs, {'fields': ['title'], 'name': 'test_title_brin', 'pages_per_range': 16})
+        self.assertEqual(kwargs, {
+            'fields': ['title'],
+            'name': 'test_title_brin',
+            'autosummarize': True,
+            'pages_per_range': 16,
+        })
 
     def test_invalid_pages_per_range(self):
         with self.assertRaisesMessage(ValueError, 'pages_per_range must be None or a positive integer'):
@@ -176,6 +181,19 @@ class SchemaTests(PostgreSQLTestCase):
             editor.remove_index(CharFieldModel, index)
         self.assertNotIn(index_name, self.get_constraints(CharFieldModel._meta.db_table))
 
+    @skipUnlessDBFeature('has_brin_index_support', 'has_brin_autosummarize')
+    def test_brin_parameters(self):
+        index_name = 'char_field_brin_params'
+        index = BrinIndex(fields=['field'], name=index_name, autosummarize=True)
+        with connection.schema_editor() as editor:
+            editor.add_index(CharFieldModel, index)
+        constraints = self.get_constraints(CharFieldModel._meta.db_table)
+        self.assertEqual(constraints[index_name]['type'], BrinIndex.suffix)
+        self.assertEqual(constraints[index_name]['options'], ['autosummarize=on'])
+        with connection.schema_editor() as editor:
+            editor.remove_index(CharFieldModel, index)
+        self.assertNotIn(index_name, self.get_constraints(CharFieldModel._meta.db_table))
+
     def test_gist_index(self):
         # Ensure the table is there and doesn't have an index.
         self.assertNotIn('field', self.get_constraints(CharFieldModel._meta.db_table))