From 5a23cc00f535a045db6d9c04c3c14594ee23fbec Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Fri, 16 Dec 2016 01:00:08 +0600 Subject: [PATCH] Fixed #27607 -- Added Oracle support for AsGML GIS function. --- .../contrib/gis/db/backends/oracle/operations.py | 3 +-- django/contrib/gis/db/models/functions.py | 12 ++++++++++-- docs/ref/contrib/gis/db-api.txt | 2 +- docs/ref/contrib/gis/functions.txt | 8 ++++++-- docs/releases/1.11.txt | 3 ++- tests/gis_tests/geoapp/test_functions.py | 15 ++++++--------- 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index b4b04622c6..0680a8d0af 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -132,8 +132,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations): truncate_params = {'relate': None} unsupported_functions = { - 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG', - 'BoundingCircle', 'Envelope', + 'AsGeoJSON', 'AsKML', 'AsSVG', 'BoundingCircle', 'Envelope', 'ForceRHR', 'GeoHash', 'MakeValid', 'MemSize', 'Scale', 'SnapToGrid', 'Translate', } diff --git a/django/contrib/gis/db/models/functions.py b/django/contrib/gis/db/models/functions.py index 2301a50230..b404397f95 100644 --- a/django/contrib/gis/db/models/functions.py +++ b/django/contrib/gis/db/models/functions.py @@ -38,12 +38,12 @@ class GeoFunc(Func): except (AttributeError, FieldError): return None - def as_sql(self, compiler, connection): + def as_sql(self, compiler, connection, **extra_context): if self.function is None: self.function = connection.ops.spatial_function_name(self.name) if any(isinstance(field, RasterField) for field in self.get_source_fields()): raise TypeError("Geometry functions not supported for raster fields.") - return super(GeoFunc, self).as_sql(compiler, connection) + return super(GeoFunc, self).as_sql(compiler, connection, **extra_context) def resolve_expression(self, *args, **kwargs): res = super(GeoFunc, self).resolve_expression(*args, **kwargs) @@ -172,6 +172,14 @@ class AsGML(GeoFunc): expressions.append(self._handle_param(precision, 'precision', six.integer_types)) super(AsGML, self).__init__(*expressions, **extra) + def as_oracle(self, compiler, connection, **extra_context): + source_expressions = self.get_source_expressions() + version = source_expressions[0] + clone = self.copy() + clone.set_source_expressions([source_expressions[1]]) + extra_context['function'] = 'SDO_UTIL.TO_GML311GEOMETRY' if version.value == 3 else 'SDO_UTIL.TO_GMLGEOMETRY' + return super(AsGML, clone).as_sql(compiler, connection, **extra_context) + class AsKML(AsGML): def as_sqlite(self, compiler, connection): diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt index ad375dca46..670b23cd78 100644 --- a/docs/ref/contrib/gis/db-api.txt +++ b/docs/ref/contrib/gis/db-api.txt @@ -379,7 +379,7 @@ Function PostGIS Oracle MySQL SpatiaLite ==================================== ======= ====== =========== ========== :class:`Area` X X X X :class:`AsGeoJSON` X X -:class:`AsGML` X X +:class:`AsGML` X X X :class:`AsKML` X X :class:`AsSVG` X X :class:`BoundingCircle` X diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt index 456ffb83e7..3a731c96f9 100644 --- a/docs/ref/contrib/gis/functions.txt +++ b/docs/ref/contrib/gis/functions.txt @@ -81,7 +81,7 @@ Keyword Argument Description .. class:: AsGML(expression, version=2, precision=8, **extra) -*Availability*: PostGIS, SpatiaLite +*Availability*: Oracle, PostGIS, SpatiaLite Accepts a single geographic field or expression and returns a `Geographic Markup Language (GML)`__ representation of the geometry. @@ -98,13 +98,17 @@ Keyword Argument Description ===================== ===================================================== ``precision`` Specifies the number of significant digits for the coordinates in the GML representation -- the default - value is 8. + value is 8. Ignored on Oracle. ``version`` Specifies the GML version to use: 2 (default) or 3. ===================== ===================================================== __ https://en.wikipedia.org/wiki/Geography_Markup_Language +.. versionchanged:: 1.11 + + Oracle support was added. + ``AsKML`` ========= diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index a46edbdfb9..40467eca88 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -164,7 +164,8 @@ Minor features :lookup:`isvalid` lookup. * Added Oracle support for the - :class:`~django.contrib.gis.db.models.functions.IsValid` function and + :class:`~django.contrib.gis.db.models.functions.AsGML` function, + :class:`~django.contrib.gis.db.models.functions.IsValid` function, and :lookup:`isvalid` lookup. :mod:`django.contrib.messages` diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py index 3ce72b9d21..7b6281a4b9 100644 --- a/tests/gis_tests/geoapp/test_functions.py +++ b/tests/gis_tests/geoapp/test_functions.py @@ -11,7 +11,7 @@ from django.db.models import Sum from django.test import TestCase, skipUnlessDBFeature from django.utils import six -from ..utils import mysql, oracle, postgis, spatialite +from ..utils import mysql, oracle, spatialite from .models import City, Country, CountryWebMercator, State, Track @@ -104,7 +104,7 @@ class GISFunctionsTests(TestCase): if oracle: # No precision parameter for Oracle :-/ gml_regex = re.compile( - r'^' + r'^' r'-104.60925\d+,38.25500\d+ ' r'' ) @@ -113,14 +113,11 @@ class GISFunctionsTests(TestCase): r'^' r'-104\.60925\d+,38\.255001' ) - self.assertTrue(gml_regex.match(ptown.gml)) - - if postgis: - self.assertIn( - '', - City.objects.annotate(gml=functions.AsGML('point', version=3)).get(name='Pueblo').gml - ) + self.assertIn( + '', + City.objects.annotate(gml=functions.AsGML('point', version=3)).get(name='Pueblo').gml + ) @skipUnlessDBFeature("has_AsKML_function") def test_askml(self):