summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Pope <nick@nickpope.me.uk>2021-05-28 23:52:57 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-10-01 13:11:34 +0200
commite76f9d5b443845639262e18d9020ef4b070f1c7d (patch)
tree1119213b5e3143318040026770efc649c1fd260d
parentbd47b9bc816bf213b6d0027ed9a9a44955bb7694 (diff)
downloaddjango-e76f9d5b443845639262e18d9020ef4b070f1c7d.tar.gz
Refs #32943 -- Added support for covering SP-GiST indexes on PostgreSQL 14+.
-rw-r--r--django/contrib/postgres/indexes.py7
-rw-r--r--django/db/backends/postgresql/features.py1
-rw-r--r--docs/ref/contrib/postgres/indexes.txt4
-rw-r--r--docs/ref/models/indexes.txt12
-rw-r--r--docs/releases/4.1.txt3
-rw-r--r--docs/spelling_wordlist1
-rw-r--r--tests/postgres_tests/migrations/0002_create_test_models.py2
-rw-r--r--tests/postgres_tests/models.py2
-rw-r--r--tests/postgres_tests/test_indexes.py27
9 files changed, 54 insertions, 5 deletions
diff --git a/django/contrib/postgres/indexes.py b/django/contrib/postgres/indexes.py
index 014bbc379d..2e3de1d275 100644
--- a/django/contrib/postgres/indexes.py
+++ b/django/contrib/postgres/indexes.py
@@ -220,6 +220,13 @@ class SpGistIndex(PostgresIndex):
with_params.append('fillfactor = %d' % self.fillfactor)
return with_params
+ def check_supported(self, schema_editor):
+ if (
+ self.include and
+ not schema_editor.connection.features.supports_covering_spgist_indexes
+ ):
+ raise NotSupportedError('Covering SP-GiST indexes require PostgreSQL 14+.')
+
class OpClass(Func):
template = '%(expressions)s %(name)s'
diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py
index caa37335e0..2917fc4f9a 100644
--- a/django/db/backends/postgresql/features.py
+++ b/django/db/backends/postgresql/features.py
@@ -99,4 +99,5 @@ class DatabaseFeatures(BaseDatabaseFeatures):
has_websearch_to_tsquery = property(operator.attrgetter('is_postgresql_11'))
supports_covering_indexes = property(operator.attrgetter('is_postgresql_11'))
supports_covering_gist_indexes = property(operator.attrgetter('is_postgresql_12'))
+ supports_covering_spgist_indexes = property(operator.attrgetter('is_postgresql_14'))
supports_non_deterministic_collations = property(operator.attrgetter('is_postgresql_12'))
diff --git a/docs/ref/contrib/postgres/indexes.txt b/docs/ref/contrib/postgres/indexes.txt
index de1715c239..35de2bf31a 100644
--- a/docs/ref/contrib/postgres/indexes.txt
+++ b/docs/ref/contrib/postgres/indexes.txt
@@ -138,6 +138,10 @@ available from the ``django.contrib.postgres.indexes`` module.
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.
+ .. versionchanged:: 4.1
+
+ Support for covering SP-GiST indexes on PostgreSQL 14+ was added.
+
.. _fillfactor: https://www.postgresql.org/docs/current/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS
``OpClass()`` expressions
diff --git a/docs/ref/models/indexes.txt b/docs/ref/models/indexes.txt
index 77739aab65..2992d51d2a 100644
--- a/docs/ref/models/indexes.txt
+++ b/docs/ref/models/indexes.txt
@@ -210,8 +210,14 @@ See the PostgreSQL documentation for more details about `covering indexes`_.
.. admonition:: Restrictions on PostgreSQL
- PostgreSQL 11+ only supports covering B-Tree indexes, and PostgreSQL 12+
- also supports covering :class:`GiST indexes
- <django.contrib.postgres.indexes.GistIndex>`.
+ PostgreSQL 11+ only supports covering B-Tree indexes, PostgreSQL 12+ also
+ supports covering :class:`GiST indexes
+ <django.contrib.postgres.indexes.GistIndex>`, and PostgreSQL 14+ also
+ supports covering :class:`SP-GiST indexes
+ <django.contrib.postgres.indexes.SpGistIndex>`.
+
+.. versionchanged:: 4.1
+
+ Support for covering SP-GiST indexes with PostgreSQL 14+ was added.
.. _covering indexes: https://www.postgresql.org/docs/current/indexes-index-only-scans.html
diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt
index e089ea6cf9..da805df315 100644
--- a/docs/releases/4.1.txt
+++ b/docs/releases/4.1.txt
@@ -68,6 +68,9 @@ Minor features
aggregate function returns an ``int`` of the bitwise ``XOR`` of all non-null
input values.
+* :class:`~django.contrib.postgres.indexes.SpGistIndex` now supports covering
+ indexes on PostgreSQL 14+.
+
:mod:`django.contrib.redirects`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist
index 8d9b17a43d..af9b8ca56b 100644
--- a/docs/spelling_wordlist
+++ b/docs/spelling_wordlist
@@ -196,6 +196,7 @@ geospatial
Gettext
GiB
gis
+GiST
Googol
Greenhill
gunicorn
diff --git a/tests/postgres_tests/migrations/0002_create_test_models.py b/tests/postgres_tests/migrations/0002_create_test_models.py
index 32f99ed6bb..377e220db1 100644
--- a/tests/postgres_tests/migrations/0002_create_test_models.py
+++ b/tests/postgres_tests/migrations/0002_create_test_models.py
@@ -142,7 +142,7 @@ class Migration(migrations.Migration):
name='Scene',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('scene', models.CharField(max_length=255)),
+ ('scene', models.TextField()),
('setting', models.CharField(max_length=255)),
],
options=None,
diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py
index fa20378071..adb2e89201 100644
--- a/tests/postgres_tests/models.py
+++ b/tests/postgres_tests/models.py
@@ -101,7 +101,7 @@ class BigAutoFieldModel(models.Model):
# Scene/Character/Line models are used to test full text search. They're
# populated with content from Monty Python and the Holy Grail.
class Scene(models.Model):
- scene = models.CharField(max_length=255)
+ scene = models.TextField()
setting = models.CharField(max_length=255)
diff --git a/tests/postgres_tests/test_indexes.py b/tests/postgres_tests/test_indexes.py
index e5d1bb02bb..75d0640a08 100644
--- a/tests/postgres_tests/test_indexes.py
+++ b/tests/postgres_tests/test_indexes.py
@@ -518,6 +518,33 @@ class SchemaTests(PostgreSQLTestCase):
editor.remove_index(TextFieldModel, index)
self.assertNotIn(index_name, self.get_constraints(TextFieldModel._meta.db_table))
+ @skipUnlessDBFeature('supports_covering_spgist_indexes')
+ def test_spgist_include(self):
+ index_name = 'scene_spgist_include_setting'
+ index = SpGistIndex(name=index_name, fields=['scene'], include=['setting'])
+ with connection.schema_editor() as editor:
+ editor.add_index(Scene, index)
+ constraints = self.get_constraints(Scene._meta.db_table)
+ self.assertIn(index_name, constraints)
+ self.assertEqual(constraints[index_name]['type'], SpGistIndex.suffix)
+ self.assertEqual(constraints[index_name]['columns'], ['scene', 'setting'])
+ with connection.schema_editor() as editor:
+ editor.remove_index(Scene, index)
+ self.assertNotIn(index_name, self.get_constraints(Scene._meta.db_table))
+
+ def test_spgist_include_not_supported(self):
+ index_name = 'spgist_include_exception'
+ index = SpGistIndex(fields=['scene'], name=index_name, include=['setting'])
+ msg = 'Covering SP-GiST indexes require PostgreSQL 14+.'
+ with self.assertRaisesMessage(NotSupportedError, msg):
+ with mock.patch(
+ 'django.db.backends.postgresql.features.DatabaseFeatures.supports_covering_spgist_indexes',
+ False,
+ ):
+ with connection.schema_editor() as editor:
+ editor.add_index(Scene, index)
+ self.assertNotIn(index_name, self.get_constraints(Scene._meta.db_table))
+
def test_op_class(self):
index_name = 'test_op_class'
index = Index(