Fixed #25636 -- Dropped support for SpatiaLite < 3.0

This commit is contained in:
Sergey Fedoseev 2015-10-31 00:04:00 +05:00 committed by Claude Paroz
parent b67502fb8d
commit 8ad923b9d0
10 changed files with 25 additions and 68 deletions

View File

@ -1,6 +1,5 @@
"""
SQL functions reference lists:
http://www.gaia-gis.it/spatialite-2.4.0/spatialite-sql-2.4.html
http://www.gaia-gis.it/spatialite-3.0.0-BETA/spatialite-sql-3.0.0.html
http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.2.1.html
"""
@ -16,7 +15,6 @@ from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Distance
from django.core.exceptions import ImproperlyConfigured
from django.db.backends.sqlite3.operations import DatabaseOperations
from django.db.utils import DatabaseError
from django.utils import six
from django.utils.functional import cached_property
@ -37,7 +35,10 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
distance = 'Distance'
envelope = 'Envelope'
extent = 'Extent'
geojson = 'AsGeoJSON'
gml = 'AsGML'
intersection = 'Intersection'
kml = 'AsKML'
length = 'GLength' # OpenGis defines Length, but this conflicts with an SQLite reserved keyword
num_geom = 'NumGeometries'
num_points = 'NumPoints'
@ -110,44 +111,15 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
'database (error was "%s"). Was the SpatiaLite initialization '
'SQL loaded on this database?') % (self.connection.settings_dict['NAME'], msg)
six.reraise(ImproperlyConfigured, ImproperlyConfigured(new_msg), sys.exc_info()[2])
if version < (2, 4, 0):
raise ImproperlyConfigured('GeoDjango only supports SpatiaLite versions '
'2.4.0 and above')
if version < (3, 0, 0):
raise ImproperlyConfigured('GeoDjango only supports SpatiaLite versions 3.0.0 and above.')
return version
@property
def _version_greater_2_4_0_rc4(self):
if self.spatial_version >= (2, 4, 1):
return True
else:
# Spatialite 2.4.0-RC4 added AsGML and AsKML, however both
# RC2 (shipped in popular Debian/Ubuntu packages) and RC4
# report version as '2.4.0', so we fall back to feature detection
try:
self._get_spatialite_func("AsGML(GeomFromText('POINT(1 1)'))")
except DatabaseError:
return False
return True
@cached_property
def disallowed_aggregates(self):
disallowed = (aggregates.Extent3D, aggregates.MakeLine)
if self.spatial_version < (3, 0, 0):
disallowed += (aggregates.Collect, aggregates.Extent)
return disallowed
@cached_property
def gml(self):
return 'AsGML' if self._version_greater_2_4_0_rc4 else None
@cached_property
def kml(self):
return 'AsKML' if self._version_greater_2_4_0_rc4 else None
@cached_property
def geojson(self):
return 'AsGeoJSON' if self.spatial_version >= (3, 0, 0) else None
def convert_extent(self, box, srid):
"""
Convert the polygon data received from Spatialite to min/max values.

View File

@ -113,8 +113,7 @@ class GeoQuerySet(QuerySet):
"""
backend = connections[self.db].ops
if not backend.geojson:
raise NotImplementedError('Only PostGIS 1.3.4+ and SpatiaLite 3.0+ '
'support GeoJSON serialization.')
raise NotImplementedError('Only PostGIS and SpatiaLite support GeoJSON serialization.')
if not isinstance(precision, six.integer_types):
raise TypeError('Precision keyword must be set with an integer.')

View File

@ -345,8 +345,8 @@ support any of these aggregates, and is thus excluded from the table.
======================= ======= ====== ==========
Aggregate PostGIS Oracle SpatiaLite
======================= ======= ====== ==========
:class:`Collect` X (from v3.0)
:class:`Extent` X X (from v3.0)
:class:`Collect` X X
:class:`Extent` X X X
:class:`Extent3D` X
:class:`MakeLine` X
:class:`Union` X X X

View File

@ -1251,7 +1251,7 @@ Example::
.. class:: Collect(geo_field)
*Availability*: PostGIS, Spatialite (≥3.0)
*Availability*: PostGIS, Spatialite
Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry
column. This is analogous to a simplified version of the :class:`Union`
@ -1264,7 +1264,7 @@ not caring about dissolving boundaries.
.. class:: Extent(geo_field)
*Availability*: PostGIS, Oracle, Spatialite (≥3.0)
*Availability*: PostGIS, Oracle, Spatialite
Returns the extent of all ``geo_field`` in the ``QuerySet`` as a four-tuple,
comprising the lower left coordinate and the upper right coordinate.

View File

@ -13,7 +13,7 @@ Program Description Required
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes (SQLite only) 2.0, 1.11, 1.10, 1.9, 1.8, 1.7
:doc:`GeoIP <../geoip>` IP-based geolocation library No 1.4
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 2.1, 2.0
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.1, 4.0, 3.0, 2.4
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.1, 4.0, 3.0
======================== ==================================== ================================ ============================
Note that older or more recent versions of these libraries *may* also work
@ -31,7 +31,6 @@ totally fine with GeoDjango. Your mileage may vary.
GDAL 1.11.0 2014-04-25
PostGIS 2.0.0 2012-04-03
PostGIS 2.1.0 2013-08-17
Spatialite 2.4.0 2010-11-14
Spatialite 3.0.0 2011-12-30
Spatialite 4.0.0 2012-11-25
Spatialite 4.1.0 2013-06-04

View File

@ -61,7 +61,7 @@ Database Library Requirements Supported Versions Notes
PostgreSQL GEOS, PROJ.4, PostGIS 9.1+ Requires PostGIS.
MySQL GEOS 5.5+ Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
Oracle GEOS 11.2+ XE not supported.
SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 2.4+, pysqlite2 2.5+
SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 3.0+, pysqlite2 2.5+
================== ============================== ================== =========================================
See also `this comparison matrix`__ on the OSGeo Wiki for

View File

@ -297,6 +297,10 @@ Miscellaneous
* The ``repr()`` of a ``QuerySet`` is wrapped in ``<QuerySet >`` to
disambiguate it from a plain list when debugging.
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
* Support for SpatiaLite < 3.0 is dropped.
.. _deprecated-features-1.10:
Features deprecated in 1.10

View File

@ -10,7 +10,7 @@ from django.db.models import F, Q
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.utils.deprecation import RemovedInDjango20Warning
from ..utils import no_oracle, oracle, postgis, spatialite
from ..utils import no_oracle, oracle, postgis
from .models import (
AustraliaCity, CensusZipcode, Interstate, SouthTexasCity, SouthTexasCityFt,
SouthTexasInterstate, SouthTexasZipcode,
@ -123,7 +123,7 @@ class DistanceTest(TestCase):
# with different projected coordinate systems.
dist1 = SouthTexasCity.objects.distance(lagrange, field_name='point').order_by('id')
dist2 = SouthTexasCity.objects.distance(lagrange).order_by('id') # Using GEOSGeometry parameter
if spatialite or oracle:
if oracle:
dist_qs = [dist1, dist2]
else:
dist3 = SouthTexasCityFt.objects.distance(lagrange.ewkt).order_by('id') # Using EWKT string parameter.
@ -247,9 +247,8 @@ class DistanceTest(TestCase):
point__distance_lte=(self.stx_pnt, D(km=20)),
)
# Can't determine the units on SpatiaLite from PROJ.4 string, and
# Oracle 11 incorrectly thinks it is not projected.
if spatialite or oracle:
if oracle:
dist_qs = (qs1,)
else:
qs2 = SouthTexasCityFt.objects.filter(point__distance_gte=(self.stx_pnt, D(km=7))).filter(
@ -513,7 +512,7 @@ class DistanceFunctionsTests(TestCase):
# Testing using different variations of parameters and using models
# with different projected coordinate systems.
dist1 = SouthTexasCity.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
if spatialite or oracle:
if oracle:
dist_qs = [dist1]
else:
dist2 = SouthTexasCityFt.objects.annotate(distance=Distance('point', lagrange)).order_by('id')

View File

@ -27,7 +27,7 @@ class GISFunctionsTests(TestCase):
fixtures = ['initial']
def test_asgeojson(self):
# Only PostGIS and SpatiaLite 3.0+ support GeoJSON.
# Only PostGIS and SpatiaLite support GeoJSON.
if not connection.ops.geojson:
with self.assertRaises(NotImplementedError):
list(Country.objects.annotate(json=functions.AsGeoJSON('mpoly')))
@ -108,12 +108,6 @@ class GISFunctionsTests(TestCase):
r'<gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ '
r'</gml:coordinates></gml:Point>'
)
elif spatialite and connection.ops.spatial_version < (3, 0, 0):
# Spatialite before 3.0 has extra colon in SrsName
gml_regex = re.compile(
r'^<gml:Point SrsName="EPSG::4326"><gml:coordinates decimal="\." '
r'cs="," ts=" ">-104.609251\d+,38.255001</gml:coordinates></gml:Point>'
)
else:
gml_regex = re.compile(
r'^<gml:Point srsName="EPSG:4326"><gml:coordinates>'

View File

@ -149,9 +149,6 @@ class GeoModelTest(TestCase):
# If the GeometryField SRID is -1, then we shouldn't perform any
# transformation if the SRID of the input geometry is different.
if spatialite and connection.ops.spatial_version < (3, 0, 0):
# SpatiaLite < 3 does not support missing SRID values.
return
m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
m1.save()
self.assertEqual(-1, m1.geom.srid)
@ -272,10 +269,9 @@ class GeoLookupTest(TestCase):
self.assertEqual('Texas', tx.name)
self.assertEqual('New Zealand', nz.name)
# Spatialite 2.3 thinks that Lawrence is in Puerto Rico (a NULL geometry).
if not (spatialite and connection.ops.spatial_version < (3, 0, 0)):
ks = State.objects.get(poly__contains=lawrence.point)
self.assertEqual('Kansas', ks.name)
# Testing `contains` on the states using the point for Lawrence.
ks = State.objects.get(poly__contains=lawrence.point)
self.assertEqual('Kansas', ks.name)
# Pueblo and Oklahoma City (even though OK City is within the bounding box of Texas)
# are not contained in Texas or New Zealand.
@ -558,7 +554,7 @@ class GeoQuerySetTest(TestCase):
def test_geojson(self):
"Testing GeoJSON output from the database using GeoQuerySet.geojson()."
# Only PostGIS and SpatiaLite 3.0+ support GeoJSON.
# Only PostGIS and SpatiaLite support GeoJSON.
if not connection.ops.geojson:
self.assertRaises(NotImplementedError, Country.objects.all().geojson, field_name='mpoly')
return
@ -625,12 +621,6 @@ class GeoQuerySetTest(TestCase):
r'<gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ '
r'</gml:coordinates></gml:Point>'
)
elif spatialite and connection.ops.spatial_version < (3, 0, 0):
# Spatialite before 3.0 has extra colon in SrsName
gml_regex = re.compile(
r'^<gml:Point SrsName="EPSG::4326"><gml:coordinates decimal="\." '
r'cs="," ts=" ">-104.609251\d+,38.255001</gml:coordinates></gml:Point>'
)
else:
gml_regex = re.compile(
r'^<gml:Point srsName="EPSG:4326"><gml:coordinates>'