Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed @no_oracle decorator. #13396

Merged
merged 2 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions django/contrib/gis/db/backends/base/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ def __hash__(self):

def __str__(self):
return self.wkt

@classmethod
def _fix_polygon(cls, poly):
# Hook for Oracle.
return poly
31 changes: 24 additions & 7 deletions django/contrib/gis/db/backends/oracle/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,31 @@ def __init__(self, geom):
* Inner ring(s) - clockwise
"""
if isinstance(geom, Polygon):
self._fix_polygon(geom)
if self._polygon_must_be_fixed(geom):
geom = self._fix_polygon(geom)
elif isinstance(geom, GeometryCollection):
self._fix_geometry_collection(geom)
if any(isinstance(g, Polygon) and self._polygon_must_be_fixed(g) for g in geom):
geom = self._fix_geometry_collection(geom)

self.wkt = geom.wkt
self.srid = geom.srid

def _fix_polygon(self, poly):
@staticmethod
def _polygon_must_be_fixed(poly):
return (
not poly.empty and
(
not poly.exterior_ring.is_counterclockwise or
any(x.is_counterclockwise for x in poly)
)
)

@classmethod
def _fix_polygon(cls, poly, clone=True):
"""Fix single polygon orientation as described in __init__()."""
if poly.empty:
return poly
if clone:
poly = poly.clone()

if not poly.exterior_ring.is_counterclockwise:
poly.exterior_ring = list(reversed(poly.exterior_ring))

Expand All @@ -36,11 +50,14 @@ def _fix_polygon(self, poly):

return poly

def _fix_geometry_collection(self, coll):
@classmethod
def _fix_geometry_collection(cls, coll):
"""
Fix polygon orientations in geometry collections as described in
__init__().
"""
coll = coll.clone()
for i, geom in enumerate(coll):
if isinstance(geom, Polygon):
coll[i] = self._fix_polygon(geom)
coll[i] = cls._fix_polygon(geom, clone=False)
return coll
4 changes: 4 additions & 0 deletions django/contrib/gis/db/backends/postgis/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ def __hash__(self):
def __str__(self):
return self.getquoted()

@classmethod
def _fix_polygon(cls, poly):
return poly

def prepare(self, conn):
"""
This method allows escaping the binary in the style required by the
Expand Down
5 changes: 5 additions & 0 deletions docs/releases/3.2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,11 @@ backends.

* Support for PostGIS 2.2 is removed.

* The Oracle backend now clones polygons (and geometry collections containing
polygons) before reorienting them and saving them to the database. They are
no longer mutated in place. You might notice this if you use the polygons
after a model is saved.

Dropped support for PostgreSQL 9.5
----------------------------------

Expand Down
5 changes: 1 addition & 4 deletions tests/gis_tests/distapp/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
from django.db.models import Exists, F, OuterRef, Q
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature

from ..utils import (
FuncTestMixin, mysql, no_oracle, oracle, postgis, spatialite,
)
from ..utils import FuncTestMixin, mysql, oracle, postgis, spatialite
from .models import (
AustraliaCity, CensusZipcode, Interstate, SouthTexasCity, SouthTexasCityFt,
SouthTexasInterstate, SouthTexasZipcode,
Expand Down Expand Up @@ -475,7 +473,6 @@ def test_distance_function_raw_result_d_lookup(self):
with self.assertRaisesMessage(ValueError, msg):
list(qs)

@no_oracle # Oracle already handles geographic distance calculation.
@skipUnlessDBFeature("has_Distance_function", 'has_Transform_function')
def test_distance_transform(self):
"""
Expand Down
13 changes: 6 additions & 7 deletions tests/gis_tests/geoapp/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from django.test import TestCase, skipUnlessDBFeature

from ..utils import (
mariadb, mysql, no_oracle, oracle, postgis, skipUnlessGISLookup,
spatialite,
mariadb, mysql, oracle, postgis, skipUnlessGISLookup, spatialite,
)
from .models import (
City, Country, Feature, MinusOneSRID, MultiFields, NonConcreteModel,
Expand Down Expand Up @@ -79,7 +78,7 @@ def test_proxy(self):
nullstate.save()

ns = State.objects.get(name='NullState')
self.assertEqual(ply, ns.poly)
self.assertEqual(connection.ops.Adapter._fix_polygon(ply), ns.poly)

# Testing the `ogr` and `srs` lazy-geometry properties.
self.assertIsInstance(ns.poly.ogr, gdal.OGRGeometry)
Expand All @@ -93,7 +92,10 @@ def test_proxy(self):
ply[1] = new_inner
self.assertEqual(4326, ns.poly.srid)
ns.save()
self.assertEqual(ply, State.objects.get(name='NullState').poly)
self.assertEqual(
connection.ops.Adapter._fix_polygon(ply),
State.objects.get(name='NullState').poly
)
ns.delete()

@skipUnlessDBFeature("supports_transform")
Expand Down Expand Up @@ -154,9 +156,6 @@ def test_geometryfield(self):
self.assertIsInstance(f_4.geom, GeometryCollection)
self.assertEqual(f_3.geom, f_4.geom[2])

# TODO: fix on Oracle: ORA-22901: cannot compare nested table or VARRAY or
# LOB attributes of an object type.
@no_oracle
@skipUnlessDBFeature("supports_transform")
def test_inherited_geofields(self):
"Database functions on inherited Geometry fields."
Expand Down
5 changes: 0 additions & 5 deletions tests/gis_tests/relatedapp/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from django.test.utils import override_settings
from django.utils import timezone

from ..utils import no_oracle
from .models import (
Article, Author, Book, City, DirectoryEntry, Event, Location, Parcel,
)
Expand Down Expand Up @@ -208,8 +207,6 @@ def test09_pk_relations(self):
self.assertEqual(val_dict['id'], c_id)
self.assertEqual(val_dict['location__id'], l_id)

# TODO: fix on Oracle -- qs2 returns an empty result for an unknown reason
@no_oracle
def test10_combine(self):
"Testing the combination of two QuerySets (#10807)."
buf1 = City.objects.get(name='Aurora').location.point.buffer(0.1)
Expand Down Expand Up @@ -252,8 +249,6 @@ def test13c_count(self):
self.assertEqual(2, qs[0]['num_cities'])
self.assertIsInstance(qs[0]['point'], GEOSGeometry)

# TODO: The phantom model does appear on Oracle.
@no_oracle
def test13_select_related_null_fk(self):
"Testing `select_related` on a nullable ForeignKey."
Book.objects.create(title='Without Author')
Expand Down
17 changes: 0 additions & 17 deletions tests/gis_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@ def skip_wrapper(*args, **kwargs):
return decorator


def no_backend(test_func, backend):
"Use this decorator to disable test on specified backend."
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].rsplit('.')[-1] == backend:
@unittest.skip("This test is skipped on '%s' backend" % backend)
def inner():
pass
return inner
else:
return test_func


# Decorators to disable entire test functions for specific
# spatial backends.
def no_oracle(func):
return no_backend(func, 'oracle')


# Shortcut booleans to omit only portions of tests.
_default_db = settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].rsplit('.')[-1]
oracle = _default_db == 'oracle'
Expand Down