summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/gis/db/backends/spatialite/base.py5
-rw-r--r--django/contrib/gis/db/backends/spatialite/features.py2
-rw-r--r--django/contrib/gis/db/backends/spatialite/operations.py16
-rw-r--r--docs/ref/contrib/gis/db-api.txt12
-rw-r--r--docs/ref/contrib/gis/functions.txt9
-rw-r--r--docs/ref/contrib/gis/install/geolibs.txt3
-rw-r--r--docs/releases/4.0.txt2
-rw-r--r--tests/gis_tests/distapp/tests.py8
-rw-r--r--tests/gis_tests/geoapp/test_functions.py6
-rw-r--r--tests/gis_tests/geogapp/tests.py9
10 files changed, 47 insertions, 25 deletions
diff --git a/django/contrib/gis/db/backends/spatialite/base.py b/django/contrib/gis/db/backends/spatialite/base.py
index 1afba58706..fef7de62af 100644
--- a/django/contrib/gis/db/backends/spatialite/base.py
+++ b/django/contrib/gis/db/backends/spatialite/base.py
@@ -71,4 +71,7 @@ class DatabaseWrapper(SQLiteDatabaseWrapper):
with self.cursor() as cursor:
cursor.execute("PRAGMA table_info(geometry_columns);")
if cursor.fetchall() == []:
- cursor.execute("SELECT InitSpatialMetaData(1)")
+ if self.ops.spatial_version < (5,):
+ cursor.execute('SELECT InitSpatialMetaData(1)')
+ else:
+ cursor.execute('SELECT InitSpatialMetaDataFull(1)')
diff --git a/django/contrib/gis/db/backends/spatialite/features.py b/django/contrib/gis/db/backends/spatialite/features.py
index 947d874b30..b6c1746c07 100644
--- a/django/contrib/gis/db/backends/spatialite/features.py
+++ b/django/contrib/gis/db/backends/spatialite/features.py
@@ -11,7 +11,7 @@ class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
@cached_property
def supports_area_geodetic(self):
- return bool(self.connection.ops.lwgeom_version())
+ return bool(self.connection.ops.geom_lib_version())
@cached_property
def django_test_skips(self):
diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py
index 8fd95d414e..8dcd62de9b 100644
--- a/django/contrib/gis/db/backends/spatialite/operations.py
+++ b/django/contrib/gis/db/backends/spatialite/operations.py
@@ -81,7 +81,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
@cached_property
def unsupported_functions(self):
unsupported = {'BoundingCircle', 'GeometryDistance', 'MemSize'}
- if not self.lwgeom_version():
+ if not self.geom_lib_version():
unsupported |= {'Azimuth', 'GeoHash', 'MakeValid'}
return unsupported
@@ -167,6 +167,20 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
"""Return the version of LWGEOM library used by SpatiaLite."""
return self._get_spatialite_func('lwgeom_version()')
+ def rttopo_version(self):
+ """Return the version of RTTOPO library used by SpatiaLite."""
+ return self._get_spatialite_func('rttopo_version()')
+
+ def geom_lib_version(self):
+ """
+ Return the version of the version-dependant geom library used by
+ SpatiaLite.
+ """
+ if self.spatial_version >= (5,):
+ return self.rttopo_version()
+ else:
+ return self.lwgeom_version()
+
def spatialite_version(self):
"Return the SpatiaLite library version as a string."
return self._get_spatialite_func('spatialite_version()')
diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt
index 7921d53a8a..af2c1c04a0 100644
--- a/docs/ref/contrib/gis/db-api.txt
+++ b/docs/ref/contrib/gis/db-api.txt
@@ -344,9 +344,9 @@ functions are available on each spatial backend.
.. currentmodule:: django.contrib.gis.db.models.functions
-==================================== ======= ============== ============ =========== ==========
+==================================== ======= ============== ============ =========== =================
Function PostGIS Oracle MariaDB MySQL SpatiaLite
-==================================== ======= ============== ============ =========== ==========
+==================================== ======= ============== ============ =========== =================
:class:`Area` X X X X X
:class:`AsGeoJSON` X X X (≥ 10.2.4) X (≥ 5.7.5) X
:class:`AsGML` X X X
@@ -354,19 +354,19 @@ Function PostGIS Oracle MariaDB MySQL
:class:`AsSVG` X X
:class:`AsWKB` X X X X X
:class:`AsWKT` X X X X X
-:class:`Azimuth` X X (LWGEOM)
+:class:`Azimuth` X X (LWGEOM/RTTOPO)
:class:`BoundingCircle` X X
:class:`Centroid` X X X X X
:class:`Difference` X X X X X
:class:`Distance` X X X X X
:class:`Envelope` X X X X X
:class:`ForcePolygonCW` X X
-:class:`GeoHash` X X (≥ 5.7.5) X (LWGEOM)
+:class:`GeoHash` X X (≥ 5.7.5) X (LWGEOM/RTTOPO)
:class:`Intersection` X X X X X
:class:`IsValid` X X X (≥ 5.7.5) X
:class:`Length` X X X X X
:class:`LineLocatePoint` X X
-:class:`MakeValid` X X (LWGEOM)
+:class:`MakeValid` X X (LWGEOM/RTTOPO)
:class:`MemSize` X
:class:`NumGeometries` X X X X X
:class:`NumPoints` X X X X X
@@ -379,7 +379,7 @@ Function PostGIS Oracle MariaDB MySQL
:class:`Transform` X X X
:class:`Translate` X X
:class:`Union` X X X X X
-==================================== ======= ============== ============ =========== ==========
+==================================== ======= ============== ============ =========== =================
Aggregate Functions
-------------------
diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt
index cf2c3217e4..82aaf1196d 100644
--- a/docs/ref/contrib/gis/functions.txt
+++ b/docs/ref/contrib/gis/functions.txt
@@ -44,7 +44,7 @@ Oracle, `PostGIS <https://postgis.net/docs/ST_Area.html>`__, SpatiaLite
Accepts a single geographic field or expression and returns the area of the
field as an :class:`~django.contrib.gis.measure.Area` measure.
-MySQL and SpatiaLite without LWGEOM don't support area calculations on
+MySQL and SpatiaLite without LWGEOM/RTTOPO don't support area calculations on
geographic SRSes.
``AsGeoJSON``
@@ -208,7 +208,7 @@ __ https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry
.. class:: Azimuth(point_a, point_b, **extra)
*Availability*: `PostGIS <https://postgis.net/docs/ST_Azimuth.html>`__,
-SpatiaLite (LWGEOM)
+SpatiaLite (LWGEOM/RTTOPO)
Returns the azimuth in radians of the segment defined by the given point
geometries, or ``None`` if the two points are coincident. The azimuth is angle
@@ -334,7 +334,8 @@ are returned unchanged.
*Availability*: `MySQL
<https://dev.mysql.com/doc/refman/en/spatial-geohash-functions.html#function_st-geohash>`__ (≥ 5.7.5),
-`PostGIS <https://postgis.net/docs/ST_GeoHash.html>`__, SpatiaLite (LWGEOM)
+`PostGIS <https://postgis.net/docs/ST_GeoHash.html>`__, SpatiaLite
+(LWGEOM/RTTOPO)
Accepts a single geographic field or expression and returns a `GeoHash`__
representation of the geometry.
@@ -416,7 +417,7 @@ Returns a float between 0 and 1 representing the location of the closest point o
.. class:: MakeValid(expr)
*Availability*: `PostGIS <https://postgis.net/docs/ST_MakeValid.html>`__,
-SpatiaLite (LWGEOM)
+SpatiaLite (LWGEOM/RTTOPO)
Accepts a geographic field or expression and attempts to convert the value into
a valid geometry without losing any of the input vertices. Geometries that are
diff --git a/docs/ref/contrib/gis/install/geolibs.txt b/docs/ref/contrib/gis/install/geolibs.txt
index 058653c7d2..d24caec57f 100644
--- a/docs/ref/contrib/gis/install/geolibs.txt
+++ b/docs/ref/contrib/gis/install/geolibs.txt
@@ -13,7 +13,7 @@ Program Description Required
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.2, 3.1, 3.0, 2.4, 2.3, 2.2, 2.1
:doc:`GeoIP <../geoip2>` IP-based geolocation library No 2
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.0, 2.5, 2.4
-`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.3
+`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 5.0, 4.3
======================== ==================================== ================================ =================================
Note that older or more recent versions of these libraries *may* also work
@@ -36,6 +36,7 @@ totally fine with GeoDjango. Your mileage may vary.
PostGIS 2.5.0 2018-09-23
PostGIS 3.0.0 2019-10-20
SpatiaLite 4.3.0 2015-09-07
+ SpatiaLite 5.0.0 2020-08-23
.. note::
diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt
index ab06cbb40f..3792c4b716 100644
--- a/docs/releases/4.0.txt
+++ b/docs/releases/4.0.txt
@@ -100,7 +100,7 @@ Minor features
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
-* ...
+* Added support for SpatiaLite 5.
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/gis_tests/distapp/tests.py b/tests/gis_tests/distapp/tests.py
index bb03fc20c3..244c99a1d7 100644
--- a/tests/gis_tests/distapp/tests.py
+++ b/tests/gis_tests/distapp/tests.py
@@ -367,16 +367,12 @@ class DistanceFunctionsTests(FuncTestMixin, TestCase):
dist2 = SouthTexasCityFt.objects.annotate(distance=Distance('point', lagrange)).order_by('id')
dist_qs = [dist1, dist2]
- # Original query done on PostGIS, have to adjust AlmostEqual tolerance
- # for Oracle.
- tol = 2 if connection.ops.oracle else 5
-
# Ensuring expected distances are returned for each distance queryset.
for qs in dist_qs:
for i, c in enumerate(qs):
with self.subTest(c=c):
- self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
- self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
+ self.assertAlmostEqual(m_distances[i], c.distance.m, -1)
+ self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, -1)
@skipUnlessDBFeature("has_Distance_function", "supports_distance_geodetic")
def test_distance_geodetic(self):
diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py
index 22d40a4400..a1b1f48e02 100644
--- a/tests/gis_tests/geoapp/test_functions.py
+++ b/tests/gis_tests/geoapp/test_functions.py
@@ -183,7 +183,11 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
def test_azimuth(self):
# Returns the azimuth in radians.
azimuth_expr = functions.Azimuth(Point(0, 0, srid=4326), Point(1, 1, srid=4326))
- self.assertAlmostEqual(City.objects.annotate(azimuth=azimuth_expr).first().azimuth, math.pi / 4)
+ self.assertAlmostEqual(
+ City.objects.annotate(azimuth=azimuth_expr).first().azimuth,
+ math.pi / 4,
+ places=2,
+ )
# Returns None if the two points are coincident.
azimuth_expr = functions.Azimuth(Point(0, 0, srid=4326), Point(0, 0, srid=4326))
self.assertIsNone(City.objects.annotate(azimuth=azimuth_expr).first().azimuth)
diff --git a/tests/gis_tests/geogapp/tests.py b/tests/gis_tests/geogapp/tests.py
index 53852517e8..7f465f5753 100644
--- a/tests/gis_tests/geogapp/tests.py
+++ b/tests/gis_tests/geogapp/tests.py
@@ -111,9 +111,12 @@ class GeographyFunctionTests(FuncTestMixin, TestCase):
if connection.ops.oracle:
ref_dists = [0, 4899.68, 8081.30, 9115.15]
elif connection.ops.spatialite:
- # SpatiaLite returns non-zero distance for polygons and points
- # covered by that polygon.
- ref_dists = [326.61, 4899.68, 8081.30, 9115.15]
+ if connection.ops.spatial_version < (5,):
+ # SpatiaLite < 5 returns non-zero distance for polygons and points
+ # covered by that polygon.
+ ref_dists = [326.61, 4899.68, 8081.30, 9115.15]
+ else:
+ ref_dists = [0, 4899.68, 8081.30, 9115.15]
else:
ref_dists = [0, 4891.20, 8071.64, 9123.95]
htown = City.objects.get(name='Houston')