diff --git a/django/contrib/postgres/indexes.py b/django/contrib/postgres/indexes.py index 363a9431ae1d..cc944ed33558 100644 --- a/django/contrib/postgres/indexes.py +++ b/django/contrib/postgres/indexes.py @@ -117,20 +117,27 @@ def get_with_params(self): class BTreeIndex(PostgresIndex): suffix = "btree" - def __init__(self, *expressions, fillfactor=None, **kwargs): + def __init__(self, *expressions, fillfactor=None, deduplicate_items=None, **kwargs): self.fillfactor = fillfactor + self.deduplicate_items = deduplicate_items super().__init__(*expressions, **kwargs) def deconstruct(self): path, args, kwargs = super().deconstruct() if self.fillfactor is not None: kwargs["fillfactor"] = self.fillfactor + if self.deduplicate_items is not None: + kwargs["deduplicate_items"] = self.deduplicate_items return path, args, kwargs def get_with_params(self): with_params = [] if self.fillfactor is not None: with_params.append("fillfactor = %d" % self.fillfactor) + if self.deduplicate_items is not None: + with_params.append( + "deduplicate_items = %s" % ("on" if self.deduplicate_items else "off") + ) return with_params diff --git a/docs/ref/contrib/postgres/indexes.txt b/docs/ref/contrib/postgres/indexes.txt index 5dfbef5c4c6e..73ef195309bb 100644 --- a/docs/ref/contrib/postgres/indexes.txt +++ b/docs/ref/contrib/postgres/indexes.txt @@ -46,14 +46,23 @@ available from the ``django.contrib.postgres.indexes`` module. ``BTreeIndex`` ============== -.. class:: BTreeIndex(*expressions, fillfactor=None, **options) +.. class:: BTreeIndex(*expressions, fillfactor=None, deduplicate_items=None, **options) Creates a B-Tree index. Provide an integer value from 10 to 100 to the fillfactor_ parameter to tune how packed the index pages will be. PostgreSQL's default is 90. + Provide a boolean value to the deduplicate_items_ parameter to control + whether deduplication is enabled. PostgreSQL enables deduplication by + default. + + .. versionchanged:: 5.1 + + The ``deduplicate_items`` parameter was added. + .. _fillfactor: https://www.postgresql.org/docs/current/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS + .. _deduplicate_items: https://www.postgresql.org/docs/current/btree-implementation.html#BTREE-DEDUPLICATION ``GinIndex`` ============ diff --git a/docs/releases/5.1.txt b/docs/releases/5.1.txt index 539ff566a351..f949b31ad25b 100644 --- a/docs/releases/5.1.txt +++ b/docs/releases/5.1.txt @@ -63,7 +63,8 @@ Minor features :mod:`django.contrib.postgres` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* ... +* :class:`~django.contrib.postgres.indexes.BTreeIndex` now supports the + ``deduplicate_items`` parameter. :mod:`django.contrib.redirects` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index c217719a8a29..5828b24253bb 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -119,6 +119,7 @@ datetimes declaratively decrementing deduplicates +deduplication deepcopy deferrable deprecations diff --git a/tests/postgres_tests/test_indexes.py b/tests/postgres_tests/test_indexes.py index d063ac64a2d1..8a7ee39a76ea 100644 --- a/tests/postgres_tests/test_indexes.py +++ b/tests/postgres_tests/test_indexes.py @@ -143,12 +143,29 @@ def test_suffix(self): self.assertEqual(BTreeIndex.suffix, "btree") def test_deconstruction(self): - index = BTreeIndex(fields=["title"], name="test_title_btree", fillfactor=80) + index = BTreeIndex(fields=["title"], name="test_title_btree") + path, args, kwargs = index.deconstruct() + self.assertEqual(path, "django.contrib.postgres.indexes.BTreeIndex") + self.assertEqual(args, ()) + self.assertEqual(kwargs, {"fields": ["title"], "name": "test_title_btree"}) + + index = BTreeIndex( + fields=["title"], + name="test_title_btree", + fillfactor=80, + deduplicate_items=False, + ) path, args, kwargs = index.deconstruct() self.assertEqual(path, "django.contrib.postgres.indexes.BTreeIndex") self.assertEqual(args, ()) self.assertEqual( - kwargs, {"fields": ["title"], "name": "test_title_btree", "fillfactor": 80} + kwargs, + { + "fields": ["title"], + "name": "test_title_btree", + "fillfactor": 80, + "deduplicate_items": False, + }, ) @@ -455,13 +472,18 @@ def test_btree_index(self): ) def test_btree_parameters(self): - index_name = "integer_array_btree_fillfactor" - index = BTreeIndex(fields=["field"], name=index_name, fillfactor=80) + index_name = "integer_array_btree_parameters" + index = BTreeIndex( + fields=["field"], name=index_name, fillfactor=80, deduplicate_items=False + ) 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"], BTreeIndex.suffix) - self.assertEqual(constraints[index_name]["options"], ["fillfactor=80"]) + self.assertEqual( + constraints[index_name]["options"], + ["fillfactor=80", "deduplicate_items=off"], + ) with connection.schema_editor() as editor: editor.remove_index(CharFieldModel, index) self.assertNotIn(