diff --git a/django/contrib/gis/db/backends/postgis/operations.py b/django/contrib/gis/db/backends/postgis/operations.py index 36bec4ba5d..31ad31e2e5 100644 --- a/django/contrib/gis/db/backends/postgis/operations.py +++ b/django/contrib/gis/db/backends/postgis/operations.py @@ -172,8 +172,6 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): "BoundingCircle": "ST_MinimumBoundingCircle", "NumPoints": "ST_NPoints", } - if self.spatial_version < (2, 4, 0): - function_names["ForcePolygonCW"] = "ST_ForceRHR" return function_names @cached_property @@ -199,7 +197,7 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): raise ImproperlyConfigured( 'Cannot determine PostGIS version for database "%s" ' 'using command "SELECT postgis_lib_version()". ' - "GeoDjango requires at least PostGIS version 2.4. " + "GeoDjango requires at least PostGIS version 2.5. " "Was the database created from a spatial database " "template?" % self.connection.settings_dict["NAME"] ) diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py index 8aae4caf34..57688642eb 100644 --- a/django/db/backends/postgresql/features.py +++ b/django/db/backends/postgresql/features.py @@ -6,7 +6,7 @@ from django.utils.functional import cached_property class DatabaseFeatures(BaseDatabaseFeatures): - minimum_database_version = (10,) + minimum_database_version = (11,) allows_group_by_selected_pks = True can_return_columns_from_insert = True can_return_rows_from_bulk_insert = True @@ -59,6 +59,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): json_key_contains_list_matching_requires_list = True supports_update_conflicts = True supports_update_conflicts_with_target = True + supports_covering_indexes = True test_collations = { "non_default": "sv-x-icu", "swedish_ci": "sv-x-icu", @@ -81,10 +82,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): "PositiveSmallIntegerField": "SmallIntegerField", } - @cached_property - def is_postgresql_11(self): - return self.connection.pg_version >= 110000 - @cached_property def is_postgresql_12(self): return self.connection.pg_version >= 120000 @@ -98,8 +95,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): return self.connection.pg_version >= 140000 has_bit_xor = property(operator.attrgetter("is_postgresql_14")) - 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( diff --git a/docs/ref/contrib/gis/install/geolibs.txt b/docs/ref/contrib/gis/install/geolibs.txt index 2ac02d53ca..8e9178f585 100644 --- a/docs/ref/contrib/gis/install/geolibs.txt +++ b/docs/ref/contrib/gis/install/geolibs.txt @@ -12,7 +12,7 @@ Program Description Required `PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 9.x, 8.x, 7.x, 6.x, 5.x, 4.x :doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.4, 3.3, 3.2, 3.1, 3.0, 2.4, 2.3, 2.2 :doc:`GeoIP <../geoip2>` IP-based geolocation library No 2 -`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.2, 3.1, 3.0, 2.5, 2.4 +`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.2, 3.1, 3.0, 2.5 `SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 5.0, 4.3 ======================== ==================================== ================================ ====================================== @@ -34,7 +34,6 @@ totally fine with GeoDjango. Your mileage may vary. GDAL 3.2.0 2020-11-02 GDAL 3.3.0 2021-05-03 GDAL 3.4.0 2021-11-04 - PostGIS 2.4.0 2017-09-30 PostGIS 2.5.0 2018-09-23 PostGIS 3.0.0 2019-10-20 PostGIS 3.1.0 2020-12-18 diff --git a/docs/ref/contrib/gis/install/index.txt b/docs/ref/contrib/gis/install/index.txt index 5ff957061c..7f4f100bb8 100644 --- a/docs/ref/contrib/gis/install/index.txt +++ b/docs/ref/contrib/gis/install/index.txt @@ -58,7 +58,7 @@ supported versions, and any notes for each of the supported database backends: ================== ============================== ================== ========================================= Database Library Requirements Supported Versions Notes ================== ============================== ================== ========================================= -PostgreSQL GEOS, GDAL, PROJ, PostGIS 10+ Requires PostGIS. +PostgreSQL GEOS, GDAL, PROJ, PostGIS 11+ Requires PostGIS. MySQL GEOS, GDAL 5.7+ :ref:`Limited functionality `. Oracle GEOS, GDAL 19+ XE not supported. SQLite GEOS, GDAL, PROJ, SpatiaLite 3.9.0+ Requires SpatiaLite 4.3+ diff --git a/docs/ref/contrib/postgres/indexes.txt b/docs/ref/contrib/postgres/indexes.txt index ba4706da3c..88f55900bc 100644 --- a/docs/ref/contrib/postgres/indexes.txt +++ b/docs/ref/contrib/postgres/indexes.txt @@ -120,11 +120,6 @@ 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. - .. admonition:: Use this index only on PostgreSQL 10 and later - - Hash indexes have been available in PostgreSQL for a long time, but - they suffer from a number of data integrity issues in older versions. - .. _fillfactor: https://www.postgresql.org/docs/current/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS ``SpGistIndex`` diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt index 009cce6f97..c270f56942 100644 --- a/docs/ref/databases.txt +++ b/docs/ref/databases.txt @@ -114,7 +114,7 @@ below for information on how to set up your database correctly. PostgreSQL notes ================ -Django supports PostgreSQL 10 and higher. `psycopg2`_ 2.8.4 or higher is +Django supports PostgreSQL 11 and higher. `psycopg2`_ 2.8.4 or higher is required, though the latest release is recommended. .. _psycopg2: https://www.psycopg.org/ diff --git a/docs/ref/models/indexes.txt b/docs/ref/models/indexes.txt index 6d860ae739..6b3c7422b7 100644 --- a/docs/ref/models/indexes.txt +++ b/docs/ref/models/indexes.txt @@ -214,7 +214,7 @@ See the PostgreSQL documentation for more details about `covering indexes`_. .. admonition:: Restrictions on PostgreSQL - PostgreSQL 11+ only supports covering B-Tree indexes, PostgreSQL 12+ also + PostgreSQL < 12 only supports covering B-Tree indexes, PostgreSQL 12+ also supports covering :class:`GiST indexes `, and PostgreSQL 14+ also supports covering :class:`SP-GiST indexes diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt index 4cad556dc3..2864d179b2 100644 --- a/docs/releases/4.1.txt +++ b/docs/releases/4.1.txt @@ -453,6 +453,14 @@ backends. * Support for GDAL 2.1 is removed. +* Support for PostGIS 2.4 is removed. + +Dropped support for PostgreSQL 10 +--------------------------------- + +Upstream support for PostgreSQL 10 ends in November 2022. Django 4.1 supports +PostgreSQL 11 and higher. + Dropped support for MariaDB 10.2 -------------------------------- diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index 3f443e867b..cf3451a782 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -69,11 +69,6 @@ PostgreSQL PostgreSQL is the most capable of all the databases here in terms of schema support. -The only caveat is that prior to PostgreSQL 11, adding columns with default -values causes a full rewrite of the table, for a time proportional to its size. -For this reason, it's recommended you always create new columns with -``null=True``, as this way they will be added immediately. - MySQL ----- diff --git a/tests/backends/postgresql/tests.py b/tests/backends/postgresql/tests.py index ce8ed7b4d5..4e15e6843a 100644 --- a/tests/backends/postgresql/tests.py +++ b/tests/backends/postgresql/tests.py @@ -315,9 +315,9 @@ class Tests(TestCase): new_connection.pg_version = 110009 self.assertEqual(new_connection.get_database_version(), (11, 9)) - @mock.patch.object(connection, "get_database_version", return_value=(9, 6)) + @mock.patch.object(connection, "get_database_version", return_value=(10,)) def test_check_database_version_supported(self, mocked_get_database_version): - msg = "PostgreSQL 10 or later is required (found 9.6)." + msg = "PostgreSQL 11 or later is required (found 10)." with self.assertRaisesMessage(NotSupportedError, msg): connection.check_database_version_supported() self.assertTrue(mocked_get_database_version.called) diff --git a/tests/postgres_tests/test_search.py b/tests/postgres_tests/test_search.py index 670b0aaaa9..d085ac852c 100644 --- a/tests/postgres_tests/test_search.py +++ b/tests/postgres_tests/test_search.py @@ -7,7 +7,7 @@ transcript. """ from django.db import connection from django.db.models import F, Value -from django.test import modify_settings, skipUnlessDBFeature +from django.test import modify_settings from . import PostgreSQLSimpleTestCase, PostgreSQLTestCase from .models import Character, Line, LineSavedSearch, Scene @@ -265,7 +265,6 @@ class MultipleFieldsTest(GrailTestData, PostgreSQLTestCase): ) self.assertSequenceEqual(searched, [self.french]) - @skipUnlessDBFeature("has_websearch_to_tsquery") def test_web_search(self): line_qs = Line.objects.annotate(search=SearchVector("dialogue")) searched = line_qs.filter( @@ -290,7 +289,6 @@ class MultipleFieldsTest(GrailTestData, PostgreSQLTestCase): ) self.assertSequenceEqual(searched, [self.verse0, self.verse1]) - @skipUnlessDBFeature("has_websearch_to_tsquery") def test_web_search_with_config(self): line_qs = Line.objects.annotate( search=SearchVector("scene__setting", "dialogue", config="french"),