1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

Fixed #27556 -- Added Oracle support for IsValid function and isvalid lookup.

This commit is contained in:
Sergey Fedoseev
2016-11-30 22:22:56 +06:00
committed by Tim Graham
parent e17f40f4b5
commit 4464b9b9ad
7 changed files with 32 additions and 11 deletions

View File

@@ -52,6 +52,10 @@ class SDORelate(SpatialOperator):
return super(SDORelate, self).as_sql(connection, lookup, template_params, sql_params)
class SDOIsValid(SpatialOperator):
sql_template = "%%(func)s(%%(lhs)s, %s) = 'TRUE'" % DEFAULT_TOLERANCE
class OracleOperations(BaseSpatialOperations, DatabaseOperations):
name = 'oracle'
@@ -85,6 +89,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
'Difference': 'SDO_GEOM.SDO_DIFFERENCE',
'Distance': 'SDO_GEOM.SDO_DISTANCE',
'Intersection': 'SDO_GEOM.SDO_INTERSECTION',
'IsValid': 'SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT',
'Length': 'SDO_GEOM.SDO_LENGTH',
'NumGeometries': 'SDO_UTIL.GETNUMELEM',
'NumPoints': 'SDO_UTIL.GETNUMVERTICES',
@@ -109,6 +114,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
'covers': SDOOperator(func='SDO_COVERS'),
'disjoint': SDODisjoint(),
'intersects': SDOOperator(func='SDO_OVERLAPBDYINTERSECT'), # TODO: Is this really the same as ST_Intersects()?
'isvalid': SDOIsValid(func='SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT'),
'equals': SDOOperator(func='SDO_EQUAL'),
'exact': SDOOperator(func='SDO_EQUAL'),
'overlaps': SDOOperator(func='SDO_OVERLAPS'),
@@ -128,7 +134,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
unsupported_functions = {
'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG',
'BoundingCircle', 'Envelope',
'ForceRHR', 'GeoHash', 'IsValid', 'MakeValid', 'MemSize', 'Scale',
'ForceRHR', 'GeoHash', 'MakeValid', 'MemSize', 'Scale',
'SnapToGrid', 'Translate',
}

View File

@@ -285,9 +285,13 @@ class Intersection(OracleToleranceMixin, GeoFuncWithGeoParam):
arity = 2
class IsValid(GeoFunc):
class IsValid(OracleToleranceMixin, GeoFunc):
output_field_class = BooleanField
def as_oracle(self, compiler, connection, **extra_context):
sql, params = super(IsValid, self).as_oracle(compiler, connection, **extra_context)
return "CASE %s WHEN 'TRUE' THEN 1 ELSE 0 END" % sql, params
class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc):
output_field_class = FloatField

View File

@@ -5,7 +5,7 @@ import re
from django.core.exceptions import FieldDoesNotExist
from django.db.models.constants import LOOKUP_SEP
from django.db.models.expressions import Col, Expression
from django.db.models.lookups import BuiltinLookup, Lookup, Transform
from django.db.models.lookups import Lookup, Transform
from django.db.models.sql.query import Query
from django.utils import six
@@ -352,15 +352,16 @@ class IntersectsLookup(GISLookup):
gis_lookups['intersects'] = IntersectsLookup
class IsValidLookup(BuiltinLookup):
class IsValidLookup(GISLookup):
lookup_name = 'isvalid'
sql_template = '%(func)s(%(lhs)s)'
def as_sql(self, compiler, connection):
if self.lhs.field.geom_type == 'RASTER':
raise ValueError('The isvalid lookup is only available on geometry fields.')
gis_op = connection.ops.gis_operators[self.lookup_name]
sql, params = self.process_lhs(compiler, connection)
sql = '%(func)s(%(lhs)s)' % {'func': gis_op.func, 'lhs': sql}
sql, params = gis_op.as_sql(connection, self, {'func': gis_op.func, 'lhs': sql}, params)
if not self.rhs:
sql = 'NOT ' + sql
return sql, params