2
0
Эх сурвалжийг харах

Fixed #30155 -- Dropped support for PostgreSQL 9.4 and PostGIS 2.1.

Tim Graham 6 жил өмнө
parent
commit
39ebdf5a3c

+ 1 - 8
django/contrib/gis/db/backends/postgis/operations.py

@@ -151,13 +151,6 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
             'BoundingCircle': 'ST_MinimumBoundingCircle',
             'NumPoints': 'ST_NPoints',
         }
-        if self.spatial_version < (2, 2, 0):
-            function_names.update({
-                'DistanceSphere': 'ST_distance_sphere',
-                'DistanceSpheroid': 'ST_distance_spheroid',
-                'LengthSpheroid': 'ST_length_spheroid',
-                'MemSize': 'ST_mem_size',
-            })
         if self.spatial_version < (2, 4, 0):
             function_names['ForcePolygonCW'] = 'ST_ForceRHR'
         return function_names
@@ -185,7 +178,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.1. '
+                    'GeoDjango requires at least PostGIS version 2.2. '
                     'Was the database created from a spatial database '
                     'template?' % self.connection.settings_dict['NAME']
                 )

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

@@ -55,8 +55,6 @@ class BrinIndex(PostgresIndex):
         return path, args, kwargs
 
     def check_supported(self, schema_editor):
-        if not schema_editor.connection.features.has_brin_index_support:
-            raise NotSupportedError('BRIN indexes require PostgreSQL 9.5+.')
         if self.autosummarize and not schema_editor.connection.features.has_brin_autosummarize:
             raise NotSupportedError('BRIN option autosummarize requires PostgreSQL 10+.')
 
@@ -105,10 +103,6 @@ class GinIndex(PostgresIndex):
             kwargs['gin_pending_list_limit'] = self.gin_pending_list_limit
         return path, args, kwargs
 
-    def check_supported(self, schema_editor):
-        if self.gin_pending_list_limit and not schema_editor.connection.features.has_gin_pending_list_limit:
-            raise NotSupportedError('GIN option gin_pending_list_limit requires PostgreSQL 9.5+.')
-
     def get_with_params(self):
         with_params = []
         if self.gin_pending_list_limit is not None:

+ 1 - 9
django/db/backends/postgresql/features.py

@@ -16,6 +16,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     has_select_for_update = True
     has_select_for_update_nowait = True
     has_select_for_update_of = True
+    has_select_for_update_skip_locked = True
     can_release_savepoints = True
     supports_tablespaces = True
     supports_transactions = True
@@ -55,10 +56,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     supported_explain_formats = {'JSON', 'TEXT', 'XML', 'YAML'}
     validates_explain_options = False  # A query will error on invalid options.
 
-    @cached_property
-    def is_postgresql_9_5(self):
-        return self.connection.pg_version >= 90500
-
     @cached_property
     def is_postgresql_9_6(self):
         return self.connection.pg_version >= 90600
@@ -67,11 +64,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     def is_postgresql_10(self):
         return self.connection.pg_version >= 100000
 
-    has_select_for_update_skip_locked = property(operator.attrgetter('is_postgresql_9_5'))
-    has_brin_index_support = property(operator.attrgetter('is_postgresql_9_5'))
-    has_jsonb_agg = property(operator.attrgetter('is_postgresql_9_5'))
     has_brin_autosummarize = property(operator.attrgetter('is_postgresql_10'))
-    has_gin_pending_list_limit = property(operator.attrgetter('is_postgresql_9_5'))
-    supports_ignore_conflicts = property(operator.attrgetter('is_postgresql_9_5'))
     has_phraseto_tsquery = property(operator.attrgetter('is_postgresql_9_6'))
     supports_table_partitions = property(operator.attrgetter('is_postgresql_10'))

+ 1 - 2
docs/ref/contrib/gis/install/geolibs.txt

@@ -12,7 +12,7 @@ Program                   Description                           Required
 `PROJ.4`_                 Cartographic Projections library      Yes (PostgreSQL and SQLite only)  5.2, 5.1, 5.0, 4.x
 :doc:`GDAL <../gdal>`     Geospatial Data Abstraction Library   Yes                               2.3, 2.2, 2.1, 2.0, 1.11
 :doc:`GeoIP <../geoip2>`  IP-based geolocation library          No                                2
-`PostGIS`__               Spatial extensions for PostgreSQL     Yes (PostgreSQL only)             2.5, 2.4, 2.3, 2.2, 2.1
+`PostGIS`__               Spatial extensions for PostgreSQL     Yes (PostgreSQL only)             2.5, 2.4, 2.3, 2.2
 `SpatiaLite`__            Spatial extensions for SQLite         Yes (SQLite only)                 4.3
 ========================  ====================================  ================================  ===================================
 
@@ -30,7 +30,6 @@ totally fine with GeoDjango. Your mileage may vary.
     GDAL 2.1.0 2016-04
     GDAL 2.2.0 2017-05
     GDAL 2.3.0 2018-05
-    PostGIS 2.1.0 2013-08-17
     PostGIS 2.2.0 2015-10-17
     PostGIS 2.3.0 2016-09-26
     PostGIS 2.4.0 2017-09-30

+ 1 - 1
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.4, PostGIS     9.4+                Requires PostGIS.
+PostgreSQL          GEOS, GDAL, PROJ.4, PostGIS     9.5+                Requires PostGIS.
 MySQL               GEOS, GDAL                      5.6+                Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
 Oracle              GEOS, GDAL                      12.1+               XE not supported.
 SQLite              GEOS, GDAL, PROJ.4, SpatiaLite  3.8.3+              Requires SpatiaLite 4.3+

+ 1 - 1
docs/ref/contrib/postgres/aggregates.txt

@@ -90,7 +90,7 @@ General-purpose aggregation functions
 
 .. class:: JSONBAgg(expressions, filter=None, **extra)
 
-    Returns the input values as a ``JSON`` array. Requires PostgreSQL ≥ 9.5.
+    Returns the input values as a ``JSON`` array.
 
 ``StringAgg``
 -------------

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

@@ -61,7 +61,7 @@ available from the ``django.contrib.postgres.indexes`` module.
 
     Provide an integer number of bytes to the gin_pending_list_limit_ parameter
     to tune the maximum size of the GIN pending list which is used when
-    ``fastupdate`` is enabled. This parameter requires PostgreSQL ≥ 9.5.
+    ``fastupdate`` is enabled.
 
     .. _GIN Fast Update Technique: https://www.postgresql.org/docs/current/static/gin-implementation.html#GIN-FAST-UPDATE
     .. _gin_pending_list_limit: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-GIN-PENDING-LIST-LIMIT

+ 1 - 1
docs/ref/databases.txt

@@ -92,7 +92,7 @@ below for information on how to set up your database correctly.
 PostgreSQL notes
 ================
 
-Django supports PostgreSQL 9.4 and higher. `psycopg2`_ 2.5.4 or higher is
+Django supports PostgreSQL 9.5 and higher. `psycopg2`_ 2.5.4 or higher is
 required, though the latest release is recommended.
 
 .. _psycopg2: http://initd.org/psycopg/

+ 5 - 5
docs/ref/models/querysets.txt

@@ -2073,11 +2073,11 @@ The ``batch_size`` parameter controls how many objects are created in a single
 query. The default is to create all objects in one batch, except for SQLite
 where the default is such that at most 999 variables per query are used.
 
-On databases that support it (all except PostgreSQL < 9.5 and Oracle), setting
-the ``ignore_conflicts`` parameter to ``True`` tells the database to ignore
-failure to insert any rows that fail constraints such as duplicate unique
-values. Enabling this parameter disables setting the primary key on each model
-instance (if the database normally supports it).
+On databases that support it (all but Oracle), setting the ``ignore_conflicts``
+parameter to ``True`` tells the database to ignore failure to insert any rows
+that fail constraints such as duplicate unique values. Enabling this parameter
+disables setting the primary key on each model instance (if the database
+normally supports it).
 
 .. versionchanged:: 2.2
 

+ 8 - 0
docs/releases/3.0.txt

@@ -225,8 +225,16 @@ backends.
 :mod:`django.contrib.gis`
 -------------------------
 
+* Supported for PostGIS 2.1 is removed.
+
 * Support for SpatiaLite 4.1 and 4.2 is removed.
 
+Dropped support for PostgreSQL 9.4
+----------------------------------
+
+Upstream support for PostgreSQL 9.4 ends in December 2019. Django 3.0 supports
+PostgreSQL 9.5 and higher.
+
 Miscellaneous
 -------------
 

+ 0 - 18
tests/gis_tests/tests.py

@@ -81,21 +81,3 @@ class TestPostGISVersionCheck(unittest.TestCase):
         ops = FakePostGISOperations()
         with self.assertRaises(ImproperlyConfigured):
             ops.spatial_version
-
-    def test_version_dependent_funcs(self):
-        """
-        Resolve names of functions renamed and deprecated in PostGIS 2.2.0
-        depending on PostGIS version.
-        Remove when dropping support for PostGIS 2.1.
-        """
-        ops = FakePostGISOperations('2.2.0')
-        self.assertEqual(ops.spatial_function_name('DistanceSphere'), 'ST_DistanceSphere')
-        self.assertEqual(ops.spatial_function_name('DistanceSpheroid'), 'ST_DistanceSpheroid')
-        self.assertEqual(ops.spatial_function_name('LengthSpheroid'), 'ST_LengthSpheroid')
-        self.assertEqual(ops.spatial_function_name('MemSize'), 'ST_MemSize')
-
-        ops = FakePostGISOperations('2.1.0')
-        self.assertEqual(ops.spatial_function_name('DistanceSphere'), 'ST_distance_sphere')
-        self.assertEqual(ops.spatial_function_name('DistanceSpheroid'), 'ST_distance_spheroid')
-        self.assertEqual(ops.spatial_function_name('LengthSpheroid'), 'ST_length_spheroid')
-        self.assertEqual(ops.spatial_function_name('MemSize'), 'ST_mem_size')

+ 0 - 3
tests/postgres_tests/test_aggregates.py

@@ -1,7 +1,6 @@
 import json
 
 from django.db.models.expressions import F, Value
-from django.test.testcases import skipUnlessDBFeature
 from django.test.utils import Approximate
 
 from . import PostgreSQLTestCase
@@ -184,12 +183,10 @@ class TestGeneralAggregate(PostgreSQLTestCase):
         )
         self.assertEqual(values, {'arrayagg': [0, 1, 0, 2]})
 
-    @skipUnlessDBFeature('has_jsonb_agg')
     def test_json_agg(self):
         values = AggregateTestModel.objects.aggregate(jsonagg=JSONBAgg('char_field'))
         self.assertEqual(values, {'jsonagg': ['Foo1', 'Foo2', 'Foo4', 'Foo3']})
 
-    @skipUnlessDBFeature('has_jsonb_agg')
     def test_json_agg_empty(self):
         values = AggregateTestModel.objects.none().aggregate(jsonagg=JSONBAgg('integer_field'))
         self.assertEqual(values, json.loads('{"jsonagg": []}'))

+ 1 - 23
tests/postgres_tests/test_indexes.py

@@ -205,7 +205,6 @@ class SchemaTests(PostgreSQLTestCase):
                 editor.remove_index(CharFieldModel, index)
             self.assertNotIn(index_name, self.get_constraints(CharFieldModel._meta.db_table))
 
-    @skipUnlessDBFeature('has_gin_pending_list_limit')
     def test_gin_parameters(self):
         index_name = 'integer_array_gin_params'
         index = GinIndex(fields=['field'], name=index_name, fastupdate=True, gin_pending_list_limit=64)
@@ -218,17 +217,6 @@ class SchemaTests(PostgreSQLTestCase):
             editor.remove_index(IntegerArrayModel, index)
         self.assertNotIn(index_name, self.get_constraints(IntegerArrayModel._meta.db_table))
 
-    @mock.patch('django.db.backends.postgresql.features.DatabaseFeatures.has_gin_pending_list_limit', False)
-    def test_gin_parameters_exception(self):
-        index_name = 'gin_options_exception'
-        index = GinIndex(fields=['field'], name=index_name, gin_pending_list_limit=64)
-        msg = 'GIN option gin_pending_list_limit requires PostgreSQL 9.5+.'
-        with self.assertRaisesMessage(NotSupportedError, msg):
-            with connection.schema_editor() as editor:
-                editor.add_index(IntegerArrayModel, index)
-        self.assertNotIn(index_name, self.get_constraints(IntegerArrayModel._meta.db_table))
-
-    @skipUnlessDBFeature('has_brin_index_support')
     def test_brin_index(self):
         index_name = 'char_field_model_field_brin'
         index = BrinIndex(fields=['field'], name=index_name, pages_per_range=4)
@@ -241,7 +229,7 @@ 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')
+    @skipUnlessDBFeature('has_brin_autosummarize')
     def test_brin_parameters(self):
         index_name = 'char_field_brin_params'
         index = BrinIndex(fields=['field'], name=index_name, autosummarize=True)
@@ -254,16 +242,6 @@ class SchemaTests(PostgreSQLTestCase):
             editor.remove_index(CharFieldModel, index)
         self.assertNotIn(index_name, self.get_constraints(CharFieldModel._meta.db_table))
 
-    def test_brin_index_not_supported(self):
-        index_name = 'brin_index_exception'
-        index = BrinIndex(fields=['field'], name=index_name)
-        with self.assertRaisesMessage(NotSupportedError, 'BRIN indexes require PostgreSQL 9.5+.'):
-            with mock.patch('django.db.backends.postgresql.features.DatabaseFeatures.has_brin_index_support', False):
-                with connection.schema_editor() as editor:
-                    editor.add_index(CharFieldModel, index)
-        self.assertNotIn(index_name, self.get_constraints(CharFieldModel._meta.db_table))
-
-    @skipUnlessDBFeature('has_brin_index_support')
     def test_brin_autosummarize_not_supported(self):
         index_name = 'brin_options_exception'
         index = BrinIndex(fields=['field'], name=index_name, autosummarize=True)