Skip to content
Permalink
Browse files

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

  • Loading branch information...
timgraham committed Feb 4, 2019
1 parent d47498c commit 39ebdf5a3c5e4e979c71a18b4bad73e3946b02d0
@@ -151,13 +151,6 @@ def function_names(self):
'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 @@ def spatial_version(self):
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']
)
@@ -55,8 +55,6 @@ def deconstruct(self):
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 @@ def deconstruct(self):
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:
@@ -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 @@ def is_postgresql_9_6(self):
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'))
@@ -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
@@ -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+
@@ -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``
-------------
@@ -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
@@ -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/
@@ -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

@@ -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
-------------

@@ -81,21 +81,3 @@ def test_no_version_number(self):
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')
@@ -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 @@ def test_orderable_agg_alternative_fields(self):
)
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": []}'))
@@ -205,7 +205,6 @@ def test_partial_gin_index_with_tablespace(self):
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 @@ def test_gin_parameters(self):
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 @@ def test_brin_index(self):
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 @@ def test_brin_parameters(self):
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)

0 comments on commit 39ebdf5

Please sign in to comment.
You can’t perform that action at this time.