Made gis_terms be a set, rather than a dict with None for all keys.

This commit is contained in:
Alex Gaynor 2013-05-09 08:13:13 -07:00
parent 6634cb7b53
commit a53d7a0a50
5 changed files with 45 additions and 40 deletions

View File

@ -3,10 +3,12 @@ Base/mixin classes for the spatial backend database operations and the
`SpatialRefSys` model the backend. `SpatialRefSys` model the backend.
""" """
import re import re
from django.contrib.gis import gdal from django.contrib.gis import gdal
from django.utils import six from django.utils import six
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
class BaseSpatialOperations(object): class BaseSpatialOperations(object):
""" """
This module holds the base `BaseSpatialBackend` object, which is This module holds the base `BaseSpatialBackend` object, which is
@ -18,7 +20,7 @@ class BaseSpatialOperations(object):
geometry_operators = {} geometry_operators = {}
geography_operators = {} geography_operators = {}
geography_functions = {} geography_functions = {}
gis_terms = {} gis_terms = set()
truncate_params = {} truncate_params = {}
# Quick booleans for the type of this spatial backend, and # Quick booleans for the type of this spatial backend, and

View File

@ -3,7 +3,6 @@ from django.db.backends.mysql.base import DatabaseOperations
from django.contrib.gis.db.backends.adapter import WKTAdapter from django.contrib.gis.db.backends.adapter import WKTAdapter
from django.contrib.gis.db.backends.base import BaseSpatialOperations from django.contrib.gis.db.backends.base import BaseSpatialOperations
from django.utils import six
class MySQLOperations(DatabaseOperations, BaseSpatialOperations): class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
@ -18,21 +17,21 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
Adaptor = Adapter # Backwards-compatibility alias. Adaptor = Adapter # Backwards-compatibility alias.
geometry_functions = { geometry_functions = {
'bbcontains' : 'MBRContains', # For consistency w/PostGIS API 'bbcontains': 'MBRContains', # For consistency w/PostGIS API
'bboverlaps' : 'MBROverlaps', # .. .. 'bboverlaps': 'MBROverlaps', # .. ..
'contained' : 'MBRWithin', # .. .. 'contained': 'MBRWithin', # .. ..
'contains' : 'MBRContains', 'contains': 'MBRContains',
'disjoint' : 'MBRDisjoint', 'disjoint': 'MBRDisjoint',
'equals' : 'MBREqual', 'equals': 'MBREqual',
'exact' : 'MBREqual', 'exact': 'MBREqual',
'intersects' : 'MBRIntersects', 'intersects': 'MBRIntersects',
'overlaps' : 'MBROverlaps', 'overlaps': 'MBROverlaps',
'same_as' : 'MBREqual', 'same_as': 'MBREqual',
'touches' : 'MBRTouches', 'touches': 'MBRTouches',
'within' : 'MBRWithin', 'within': 'MBRWithin',
} }
gis_terms = dict([(term, None) for term in list(geometry_functions) + ['isnull']]) gis_terms = set(geometry_functions) | set(['isnull'])
def geo_db_type(self, f): def geo_db_type(self, f):
return f.geom_type return f.geom_type

View File

@ -18,6 +18,7 @@ from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Distance from django.contrib.gis.measure import Distance
from django.utils import six from django.utils import six
class SDOOperation(SpatialFunction): class SDOOperation(SpatialFunction):
"Base class for SDO* Oracle operations." "Base class for SDO* Oracle operations."
sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'"
@ -32,6 +33,7 @@ class SDODistance(SpatialFunction):
sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) ' sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) '
'%(operator)s %(result)s') '%(operator)s %(result)s')
dist_func = 'SDO_GEOM.SDO_DISTANCE' dist_func = 'SDO_GEOM.SDO_DISTANCE'
def __init__(self, op, tolerance=0.05): def __init__(self, op, tolerance=0.05):
super(SDODistance, self).__init__(self.dist_func, super(SDODistance, self).__init__(self.dist_func,
tolerance=tolerance, tolerance=tolerance,
@ -40,6 +42,7 @@ class SDODistance(SpatialFunction):
class SDODWithin(SpatialFunction): class SDODWithin(SpatialFunction):
dwithin_func = 'SDO_WITHIN_DISTANCE' dwithin_func = 'SDO_WITHIN_DISTANCE'
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'"
def __init__(self): def __init__(self):
super(SDODWithin, self).__init__(self.dwithin_func) super(SDODWithin, self).__init__(self.dwithin_func)
@ -48,6 +51,7 @@ class SDOGeomRelate(SpatialFunction):
relate_func = 'SDO_GEOM.RELATE' relate_func = 'SDO_GEOM.RELATE'
sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, " sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, "
"%(tolerance)s) %(operator)s '%(mask)s'") "%(tolerance)s) %(operator)s '%(mask)s'")
def __init__(self, mask, tolerance=0.05): def __init__(self, mask, tolerance=0.05):
# SDO_GEOM.RELATE(...) has a peculiar argument order: column, mask, geom, tolerance. # SDO_GEOM.RELATE(...) has a peculiar argument order: column, mask, geom, tolerance.
# Moreover, the runction result is the mask (e.g., 'DISJOINT' instead of 'TRUE'). # Moreover, the runction result is the mask (e.g., 'DISJOINT' instead of 'TRUE').
@ -60,6 +64,7 @@ class SDORelate(SpatialFunction):
mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I) mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I)
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s') = 'TRUE'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s') = 'TRUE'"
relate_func = 'SDO_RELATE' relate_func = 'SDO_RELATE'
def __init__(self, mask): def __init__(self, mask):
if not self.mask_regex.match(mask): if not self.mask_regex.match(mask):
raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask)) raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask))
@ -79,12 +84,12 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
Adaptor = Adapter # Backwards-compatibility alias. Adaptor = Adapter # Backwards-compatibility alias.
area = 'SDO_GEOM.SDO_AREA' area = 'SDO_GEOM.SDO_AREA'
gml= 'SDO_UTIL.TO_GMLGEOMETRY' gml = 'SDO_UTIL.TO_GMLGEOMETRY'
centroid = 'SDO_GEOM.SDO_CENTROID' centroid = 'SDO_GEOM.SDO_CENTROID'
difference = 'SDO_GEOM.SDO_DIFFERENCE' difference = 'SDO_GEOM.SDO_DIFFERENCE'
distance = 'SDO_GEOM.SDO_DISTANCE' distance = 'SDO_GEOM.SDO_DISTANCE'
extent= 'SDO_AGGR_MBR' extent = 'SDO_AGGR_MBR'
intersection= 'SDO_GEOM.SDO_INTERSECTION' intersection = 'SDO_GEOM.SDO_INTERSECTION'
length = 'SDO_GEOM.SDO_LENGTH' length = 'SDO_GEOM.SDO_LENGTH'
num_geom = 'SDO_UTIL.GETNUMELEM' num_geom = 'SDO_UTIL.GETNUMELEM'
num_points = 'SDO_UTIL.GETNUMVERTICES' num_points = 'SDO_UTIL.GETNUMVERTICES'
@ -127,9 +132,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
} }
geometry_functions.update(distance_functions) geometry_functions.update(distance_functions)
gis_terms = ['isnull'] gis_terms = set(['isnull'])
gis_terms += list(geometry_functions) gis_terms.update(geometry_functions)
gis_terms = dict([(term, None) for term in gis_terms])
truncate_params = {'relate' : None} truncate_params = {'relate' : None}
@ -272,7 +276,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
given Aggregate instance. given Aggregate instance.
""" """
agg_name = agg.__class__.__name__.lower() agg_name = agg.__class__.__name__.lower()
if agg_name == 'union' : agg_name += 'agg' if agg_name == 'union':
agg_name += 'agg'
if agg.is_extent: if agg.is_extent:
sql_template = '%(function)s(%(field)s)' sql_template = '%(function)s(%(field)s)'
else: else:
@ -295,5 +300,5 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
""" """
# This code doesn't work for bulk insert cases. # This code doesn't work for bulk insert cases.
assert len(placeholders) == 1 assert len(placeholders) == 1
return [[param for pholder,param return [[param for pholder, param
in six.moves.zip(placeholders[0], params[0]) if pholder != 'NULL'], ] in six.moves.zip(placeholders[0], params[0]) if pholder != 'NULL'], ]

View File

@ -208,23 +208,22 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
# for the geography type. # for the geography type.
self.geography_functions = self.distance_functions.copy() self.geography_functions = self.distance_functions.copy()
self.geography_functions.update({ self.geography_functions.update({
'coveredby' : self.geometry_functions['coveredby'], 'coveredby': self.geometry_functions['coveredby'],
'covers' : self.geometry_functions['covers'], 'covers': self.geometry_functions['covers'],
'intersects' : self.geometry_functions['intersects'], 'intersects': self.geometry_functions['intersects'],
}) })
self.geography_operators = { self.geography_operators = {
'bboverlaps' : PostGISOperator('&&'), 'bboverlaps': PostGISOperator('&&'),
} }
# Native geometry type support added in PostGIS 2.0. # Native geometry type support added in PostGIS 2.0.
if version >= (2, 0, 0): if version >= (2, 0, 0):
self.geometry = True self.geometry = True
# Creating a dictionary lookup of all GIS terms for PostGIS. # Creating a dictionary lookup of all GIS terms for PostGIS.
gis_terms = ['isnull'] self.gis_terms = set(['isnull'])
gis_terms += list(self.geometry_operators) self.gis_terms.update(self.geometry_operators)
gis_terms += list(self.geometry_functions) self.gis_terms.update(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
self.area = prefix + 'Area' self.area = prefix + 'Area'
self.bounding_circle = BOUNDINGCIRCLE self.bounding_circle = BOUNDINGCIRCLE
@ -247,7 +246,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.makeline = prefix + 'MakeLine' self.makeline = prefix + 'MakeLine'
self.mem_size = prefix + 'mem_size' self.mem_size = prefix + 'mem_size'
self.num_geom = prefix + 'NumGeometries' self.num_geom = prefix + 'NumGeometries'
self.num_points =prefix + 'npoints' self.num_points = prefix + 'npoints'
self.perimeter = prefix + 'Perimeter' self.perimeter = prefix + 'Perimeter'
self.point_on_surface = prefix + 'PointOnSurface' self.point_on_surface = prefix + 'PointOnSurface'
self.polygonize = prefix + 'Polygonize' self.polygonize = prefix + 'Polygonize'
@ -324,7 +323,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
raise NotImplementedError('PostGIS 1.5 supports geography columns ' raise NotImplementedError('PostGIS 1.5 supports geography columns '
'only with an SRID of 4326.') 'only with an SRID of 4326.')
return 'geography(%s,%d)'% (f.geom_type, f.srid) return 'geography(%s,%d)' % (f.geom_type, f.srid)
elif self.geometry: elif self.geometry:
# Postgis 2.0 supports type-based geometries. # Postgis 2.0 supports type-based geometries.
# TODO: Support 'M' extension. # TODO: Support 'M' extension.
@ -565,7 +564,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
if not self.check_aggregate_support(agg): if not self.check_aggregate_support(agg):
raise NotImplementedError('%s spatial aggregate is not implmented for this backend.' % agg_name) raise NotImplementedError('%s spatial aggregate is not implmented for this backend.' % agg_name)
agg_name = agg_name.lower() agg_name = agg_name.lower()
if agg_name == 'union': agg_name += 'agg' if agg_name == 'union':
agg_name += 'agg'
sql_template = '%(function)s(%(field)s)' sql_template = '%(function)s(%(field)s)'
sql_function = getattr(self, agg_name) sql_function = getattr(self, agg_name)
return sql_template, sql_function return sql_template, sql_function

View File

@ -117,9 +117,8 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
super(DatabaseOperations, self).__init__(connection) super(DatabaseOperations, self).__init__(connection)
# Creating the GIS terms dictionary. # Creating the GIS terms dictionary.
gis_terms = ['isnull'] self.gis_terms = set(['isnull'])
gis_terms += self.geometry_functions.keys() self.gis_terms.update(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
@cached_property @cached_property
def spatial_version(self): def spatial_version(self):