Fixed #32575 -- Added support for SpatiaLite 5.
This commit is contained in:
parent
b9d156761f
commit
30e123ed35
|
@ -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)')
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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()')
|
||||
|
|
|
@ -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
|
||||
-------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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::
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ Minor features
|
|||
:mod:`django.contrib.gis`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* ...
|
||||
* Added support for SpatiaLite 5.
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
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')
|
||||
|
|
Loading…
Reference in New Issue