mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #1142 -- Added multiple database support.
This monster of a patch is the result of Alex Gaynor's 2009 Google Summer of Code project. Congratulations to Alex for a job well done. Big thanks also go to: * Justin Bronn for keeping GIS in line with the changes, * Karen Tracey and Jani Tiainen for their help testing Oracle support * Brett Hoerner, Jon Loyens, and Craig Kimmerer for their feedback. * Malcolm Treddinick for his guidance during the GSoC submission process. * Simon Willison for driving the original design process * Cal Henderson for complaining about ponies he wanted. ... and everyone else too numerous to mention that helped to bring this feature into fruition. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11952 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
0
django/contrib/gis/db/backends/oracle/__init__.py
Normal file
0
django/contrib/gis/db/backends/oracle/__init__.py
Normal file
5
django/contrib/gis/db/backends/oracle/adapter.py
Normal file
5
django/contrib/gis/db/backends/oracle/adapter.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from cx_Oracle import CLOB
|
||||
from django.contrib.gis.db.backends.adapter import WKTAdapter
|
||||
|
||||
class OracleSpatialAdapter(WKTAdapter):
|
||||
input_size = CLOB
|
||||
10
django/contrib/gis/db/backends/oracle/base.py
Normal file
10
django/contrib/gis/db/backends/oracle/base.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.db.backends.oracle.base import *
|
||||
from django.db.backends.oracle.base import DatabaseWrapper as OracleDatabaseWrapper
|
||||
from django.contrib.gis.db.backends.oracle.creation import OracleCreation
|
||||
from django.contrib.gis.db.backends.oracle.operations import OracleOperations
|
||||
|
||||
class DatabaseWrapper(OracleDatabaseWrapper):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseWrapper, self).__init__(*args, **kwargs)
|
||||
self.creation = OracleCreation(self)
|
||||
self.ops = OracleOperations(self)
|
||||
44
django/contrib/gis/db/backends/oracle/compiler.py
Normal file
44
django/contrib/gis/db/backends/oracle/compiler.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler
|
||||
from django.db.backends.oracle import compiler
|
||||
|
||||
SQLCompiler = compiler.SQLCompiler
|
||||
|
||||
class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
|
||||
def placeholder(self, field, val):
|
||||
if field is None:
|
||||
# A field value of None means the value is raw.
|
||||
return val
|
||||
elif hasattr(field, 'get_placeholder'):
|
||||
# Some fields (e.g. geo fields) need special munging before
|
||||
# they can be inserted.
|
||||
ph = field.get_placeholder(val, self.connection)
|
||||
if ph == 'NULL':
|
||||
# If the placeholder returned is 'NULL', then we need to
|
||||
# to remove None from the Query parameters. Specifically,
|
||||
# cx_Oracle will assume a CHAR type when a placeholder ('%s')
|
||||
# is used for columns of MDSYS.SDO_GEOMETRY. Thus, we use
|
||||
# 'NULL' for the value, and remove None from the query params.
|
||||
# See also #10888.
|
||||
param_idx = self.query.columns.index(field.column)
|
||||
params = list(self.query.params)
|
||||
params.pop(param_idx)
|
||||
self.query.params = tuple(params)
|
||||
return ph
|
||||
else:
|
||||
# Return the common case for the placeholder
|
||||
return '%s'
|
||||
|
||||
class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
42
django/contrib/gis/db/backends/oracle/creation.py
Normal file
42
django/contrib/gis/db/backends/oracle/creation.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from django.db.backends.oracle.creation import DatabaseCreation
|
||||
from django.db.backends.util import truncate_name
|
||||
|
||||
class OracleCreation(DatabaseCreation):
|
||||
|
||||
def sql_indexes_for_field(self, model, f, style):
|
||||
"Return any spatial index creation SQL for the field."
|
||||
from django.contrib.gis.db.models.fields import GeometryField
|
||||
|
||||
output = super(OracleCreation, self).sql_indexes_for_field(model, f, style)
|
||||
|
||||
if isinstance(f, GeometryField):
|
||||
gqn = self.connection.ops.geo_quote_name
|
||||
qn = self.connection.ops.quote_name
|
||||
db_table = model._meta.db_table
|
||||
|
||||
output.append(style.SQL_KEYWORD('INSERT INTO ') +
|
||||
style.SQL_TABLE('USER_SDO_GEOM_METADATA') +
|
||||
' (%s, %s, %s, %s)\n ' % tuple(map(qn, ['TABLE_NAME', 'COLUMN_NAME', 'DIMINFO', 'SRID'])) +
|
||||
style.SQL_KEYWORD(' VALUES ') + '(\n ' +
|
||||
style.SQL_TABLE(gqn(db_table)) + ',\n ' +
|
||||
style.SQL_FIELD(gqn(f.column)) + ',\n ' +
|
||||
style.SQL_KEYWORD("MDSYS.SDO_DIM_ARRAY") + '(\n ' +
|
||||
style.SQL_KEYWORD("MDSYS.SDO_DIM_ELEMENT") +
|
||||
("('LONG', %s, %s, %s),\n " % (f._extent[0], f._extent[2], f._tolerance)) +
|
||||
style.SQL_KEYWORD("MDSYS.SDO_DIM_ELEMENT") +
|
||||
("('LAT', %s, %s, %s)\n ),\n" % (f._extent[1], f._extent[3], f._tolerance)) +
|
||||
' %s\n );' % f.srid)
|
||||
|
||||
if f.spatial_index:
|
||||
# Getting the index name, Oracle doesn't allow object
|
||||
# names > 30 characters.
|
||||
idx_name = truncate_name('%s_%s_id' % (db_table, f.column), 30)
|
||||
|
||||
output.append(style.SQL_KEYWORD('CREATE INDEX ') +
|
||||
style.SQL_TABLE(qn(idx_name)) +
|
||||
style.SQL_KEYWORD(' ON ') +
|
||||
style.SQL_TABLE(qn(db_table)) + '(' +
|
||||
style.SQL_FIELD(qn(f.column)) + ') ' +
|
||||
style.SQL_KEYWORD('INDEXTYPE IS ') +
|
||||
style.SQL_TABLE('MDSYS.SPATIAL_INDEX') + ';')
|
||||
return output
|
||||
67
django/contrib/gis/db/backends/oracle/models.py
Normal file
67
django/contrib/gis/db/backends/oracle/models.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""
|
||||
The GeometryColumns and SpatialRefSys models for the Oracle spatial
|
||||
backend.
|
||||
|
||||
It should be noted that Oracle Spatial does not have database tables
|
||||
named according to the OGC standard, so the closest analogs are used.
|
||||
For example, the `USER_SDO_GEOM_METADATA` is used for the GeometryColumns
|
||||
model and the `SDO_COORD_REF_SYS` is used for the SpatialRefSys model.
|
||||
"""
|
||||
from django.contrib.gis.db import models
|
||||
from django.contrib.gis.db.models.fields import GeometryField
|
||||
from django.contrib.gis.db.backends.base import SpatialRefSysMixin
|
||||
|
||||
class GeometryColumns(models.Model):
|
||||
"Maps to the Oracle USER_SDO_GEOM_METADATA table."
|
||||
table_name = models.CharField(max_length=32)
|
||||
column_name = models.CharField(max_length=1024)
|
||||
srid = models.IntegerField(primary_key=True)
|
||||
# TODO: Add support for `diminfo` column (type MDSYS.SDO_DIM_ARRAY).
|
||||
class Meta:
|
||||
app_label = 'gis'
|
||||
db_table = 'USER_SDO_GEOM_METADATA'
|
||||
managed = False
|
||||
|
||||
@classmethod
|
||||
def table_name_col(cls):
|
||||
"""
|
||||
Returns the name of the metadata column used to store the
|
||||
the feature table name.
|
||||
"""
|
||||
return 'table_name'
|
||||
|
||||
@classmethod
|
||||
def geom_col_name(cls):
|
||||
"""
|
||||
Returns the name of the metadata column used to store the
|
||||
the feature geometry column.
|
||||
"""
|
||||
return 'column_name'
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s - %s (SRID: %s)' % (self.table_name, self.column_name, self.srid)
|
||||
|
||||
class SpatialRefSys(models.Model, SpatialRefSysMixin):
|
||||
"Maps to the Oracle MDSYS.CS_SRS table."
|
||||
cs_name = models.CharField(max_length=68)
|
||||
srid = models.IntegerField(primary_key=True)
|
||||
auth_srid = models.IntegerField()
|
||||
auth_name = models.CharField(max_length=256)
|
||||
wktext = models.CharField(max_length=2046)
|
||||
# Optional geometry representing the bounds of this coordinate
|
||||
# system. By default, all are NULL in the table.
|
||||
cs_bounds = models.PolygonField(null=True)
|
||||
objects = models.GeoManager()
|
||||
|
||||
class Meta:
|
||||
app_label = 'gis'
|
||||
db_table = 'CS_SRS'
|
||||
managed = False
|
||||
|
||||
@property
|
||||
def wkt(self):
|
||||
return self.wktext
|
||||
|
||||
@classmethod
|
||||
def wkt_col(cls):
|
||||
return 'wktext'
|
||||
289
django/contrib/gis/db/backends/oracle/operations.py
Normal file
289
django/contrib/gis/db/backends/oracle/operations.py
Normal file
@@ -0,0 +1,289 @@
|
||||
"""
|
||||
This module contains the spatial lookup types, and the `get_geo_where_clause`
|
||||
routine for Oracle Spatial.
|
||||
|
||||
Please note that WKT support is broken on the XE version, and thus
|
||||
this backend will not work on such platforms. Specifically, XE lacks
|
||||
support for an internal JVM, and Java libraries are required to use
|
||||
the WKT constructors.
|
||||
"""
|
||||
import re
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db.backends.oracle.base import DatabaseOperations
|
||||
from django.contrib.gis.db.backends.base import BaseSpatialOperations
|
||||
from django.contrib.gis.db.backends.oracle.adapter import OracleSpatialAdapter
|
||||
from django.contrib.gis.db.backends.util import SpatialFunction
|
||||
from django.contrib.gis.geometry.backend import Geometry
|
||||
from django.contrib.gis.measure import Distance
|
||||
|
||||
class SDOOperation(SpatialFunction):
|
||||
"Base class for SDO* Oracle operations."
|
||||
sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'"
|
||||
|
||||
def __init__(self, func, **kwargs):
|
||||
kwargs.setdefault('operator', '=')
|
||||
kwargs.setdefault('result', 'TRUE')
|
||||
super(SDOOperation, self).__init__(func, **kwargs)
|
||||
|
||||
class SDODistance(SpatialFunction):
|
||||
"Class for Distance queries."
|
||||
sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) '
|
||||
'%(operator)s %(result)s')
|
||||
dist_func = 'SDO_GEOM.SDO_DISTANCE'
|
||||
def __init__(self, op, tolerance=0.05):
|
||||
super(SDODistance, self).__init__(self.dist_func,
|
||||
tolerance=tolerance,
|
||||
operator=op, result='%s')
|
||||
|
||||
class SDODWithin(SpatialFunction):
|
||||
dwithin_func = 'SDO_WITHIN_DISTANCE'
|
||||
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'"
|
||||
def __init__(self):
|
||||
super(SDODWithin, self).__init__(self.dwithin_func)
|
||||
|
||||
class SDOGeomRelate(SpatialFunction):
|
||||
"Class for using SDO_GEOM.RELATE."
|
||||
relate_func = 'SDO_GEOM.RELATE'
|
||||
sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, "
|
||||
"%(tolerance)s) %(operator)s '%(mask)s'")
|
||||
def __init__(self, mask, tolerance=0.05):
|
||||
# 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').
|
||||
super(SDOGeomRelate, self).__init__(self.relate_func, operator='=',
|
||||
mask=mask, tolerance=tolerance)
|
||||
|
||||
class SDORelate(SpatialFunction):
|
||||
"Class for using SDO_RELATE."
|
||||
masks = 'TOUCH|OVERLAPBDYDISJOINT|OVERLAPBDYINTERSECT|EQUAL|INSIDE|COVEREDBY|CONTAINS|COVERS|ANYINTERACT|ON'
|
||||
mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I)
|
||||
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s)' = 'TRUE'"
|
||||
relate_func = 'SDO_RELATE'
|
||||
def __init__(self, mask):
|
||||
if not self.mask_regex.match(mask):
|
||||
raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask))
|
||||
super(SDORelate, self).__init__(self.relate_func, mask=mask)
|
||||
|
||||
# Valid distance types and substitutions
|
||||
dtypes = (Decimal, Distance, float, int, long)
|
||||
|
||||
class OracleOperations(DatabaseOperations, BaseSpatialOperations):
|
||||
compiler_module = "django.contrib.gis.db.backends.oracle.compiler"
|
||||
|
||||
name = 'oracle'
|
||||
oracle = True
|
||||
valid_aggregates = dict([(a, None) for a in ('Union', 'Extent')])
|
||||
|
||||
Adapter = OracleSpatialAdapter
|
||||
|
||||
area = 'SDO_GEOM.SDO_AREA'
|
||||
gml= 'SDO_UTIL.TO_GMLGEOMETRY'
|
||||
centroid = 'SDO_GEOM.SDO_CENTROID'
|
||||
difference = 'SDO_GEOM.SDO_DIFFERENCE'
|
||||
distance = 'SDO_GEOM.SDO_DISTANCE'
|
||||
extent= 'SDO_AGGR_MBR'
|
||||
intersection= 'SDO_GEOM.SDO_INTERSECTION'
|
||||
length = 'SDO_GEOM.SDO_LENGTH'
|
||||
num_geom = 'SDO_UTIL.GETNUMELEM'
|
||||
num_points = 'SDO_UTIL.GETNUMVERTICES'
|
||||
perimeter = length
|
||||
point_on_surface = 'SDO_GEOM.SDO_POINTONSURFACE'
|
||||
sym_difference = 'SDO_GEOM.SDO_XOR'
|
||||
transform = 'SDO_CS.TRANSFORM'
|
||||
union = 'SDO_GEOM.SDO_UNION'
|
||||
unionagg = 'SDO_AGGR_UNION'
|
||||
|
||||
# We want to get SDO Geometries as WKT because it is much easier to
|
||||
# instantiate GEOS proxies from WKT than SDO_GEOMETRY(...) strings.
|
||||
# However, this adversely affects performance (i.e., Java is called
|
||||
# to convert to WKT on every query). If someone wishes to write a
|
||||
# SDO_GEOMETRY(...) parser in Python, let me know =)
|
||||
select = 'SDO_UTIL.TO_WKTGEOMETRY(%s)'
|
||||
|
||||
distance_functions = {
|
||||
'distance_gt' : (SDODistance('>'), dtypes),
|
||||
'distance_gte' : (SDODistance('>='), dtypes),
|
||||
'distance_lt' : (SDODistance('<'), dtypes),
|
||||
'distance_lte' : (SDODistance('<='), dtypes),
|
||||
'dwithin' : (SDODWithin(), dtypes),
|
||||
}
|
||||
|
||||
geometry_functions = {
|
||||
'contains' : SDOOperation('SDO_CONTAINS'),
|
||||
'coveredby' : SDOOperation('SDO_COVEREDBY'),
|
||||
'covers' : SDOOperation('SDO_COVERS'),
|
||||
'disjoint' : SDOGeomRelate('DISJOINT'),
|
||||
'intersects' : SDOOperation('SDO_OVERLAPBDYINTERSECT'), # TODO: Is this really the same as ST_Intersects()?
|
||||
'equals' : SDOOperation('SDO_EQUAL'),
|
||||
'exact' : SDOOperation('SDO_EQUAL'),
|
||||
'overlaps' : SDOOperation('SDO_OVERLAPS'),
|
||||
'same_as' : SDOOperation('SDO_EQUAL'),
|
||||
'relate' : (SDORelate, basestring), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
|
||||
'touches' : SDOOperation('SDO_TOUCH'),
|
||||
'within' : SDOOperation('SDO_INSIDE'),
|
||||
}
|
||||
geometry_functions.update(distance_functions)
|
||||
|
||||
gis_terms = ['isnull']
|
||||
gis_terms += geometry_functions.keys()
|
||||
gis_terms = dict([(term, None) for term in gis_terms])
|
||||
|
||||
def __init__(self, connection):
|
||||
super(OracleOperations, self).__init__()
|
||||
self.connection = connection
|
||||
|
||||
def convert_extent(self, clob):
|
||||
if clob:
|
||||
# Generally, Oracle returns a polygon for the extent -- however,
|
||||
# it can return a single point if there's only one Point in the
|
||||
# table.
|
||||
ext_geom = Geometry(clob.read())
|
||||
gtype = str(ext_geom.geom_type)
|
||||
if gtype == 'Polygon':
|
||||
# Construct the 4-tuple from the coordinates in the polygon.
|
||||
shell = ext_geom.shell
|
||||
ll, ur = shell[0][:2], shell[2][:2]
|
||||
elif gtype == 'Point':
|
||||
ll = ext_geom.coords[:2]
|
||||
ur = ll
|
||||
else:
|
||||
raise Exception('Unexpected geometry type returned for extent: %s' % gtype)
|
||||
xmin, ymin = ll
|
||||
xmax, ymax = ur
|
||||
return (xmin, ymin, xmax, ymax)
|
||||
else:
|
||||
return None
|
||||
|
||||
def convert_geom(self, clob, geo_field):
|
||||
if clob:
|
||||
return Geometry(clob.read(), geo_field.srid)
|
||||
else:
|
||||
return None
|
||||
|
||||
def geo_db_type(self, f):
|
||||
"""
|
||||
Returns the geometry database type for Oracle. Unlike other spatial
|
||||
backends, no stored procedure is necessary and it's the same for all
|
||||
geometry types.
|
||||
"""
|
||||
return 'MDSYS.SDO_GEOMETRY'
|
||||
|
||||
def get_distance(self, f, value, lookup_type):
|
||||
"""
|
||||
Returns the distance parameters given the value and the lookup type.
|
||||
On Oracle, geometry columns with a geodetic coordinate system behave
|
||||
implicitly like a geography column, and thus meters will be used as
|
||||
the distance parameter on them.
|
||||
"""
|
||||
if not value:
|
||||
return []
|
||||
value = value[0]
|
||||
if isinstance(value, Distance):
|
||||
if f.geodetic(self.connection):
|
||||
dist_param = value.m
|
||||
else:
|
||||
dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
|
||||
else:
|
||||
dist_param = value
|
||||
|
||||
# dwithin lookups on oracle require a special string parameter
|
||||
# that starts with "distance=".
|
||||
if lookup_type == 'dwithin':
|
||||
dist_param = 'distance=%s' % dist_param
|
||||
|
||||
return [dist_param]
|
||||
|
||||
def get_geom_placeholder(self, f, value):
|
||||
"""
|
||||
Provides a proper substitution value for Geometries that are not in the
|
||||
SRID of the field. Specifically, this routine will substitute in the
|
||||
SDO_CS.TRANSFORM() function call.
|
||||
"""
|
||||
if value is None:
|
||||
return 'NULL'
|
||||
|
||||
def transform_value(val, srid):
|
||||
return val.srid != srid
|
||||
|
||||
if hasattr(value, 'expression'):
|
||||
if transform_value(value, f.srid):
|
||||
placeholder = '%s(%%s, %s)' % (self.transform, f.srid)
|
||||
else:
|
||||
placeholder = '%s'
|
||||
# No geometry value used for F expression, substitue in
|
||||
# the column name instead.
|
||||
return placeholder % '%s.%s' % tuple(map(self.quote_name, value.cols[value.expression]))
|
||||
else:
|
||||
if transform_value(value, f.srid):
|
||||
return '%s(SDO_GEOMETRY(%%s, %s), %s)' % (self.transform, value.srid, f.srid)
|
||||
else:
|
||||
return 'SDO_GEOMETRY(%%s, %s)' % f.srid
|
||||
|
||||
def spatial_lookup_sql(self, lvalue, lookup_type, value, field, qn):
|
||||
"Returns the SQL WHERE clause for use in Oracle spatial SQL construction."
|
||||
alias, col, db_type = lvalue
|
||||
|
||||
# Getting the quoted table name as `geo_col`.
|
||||
geo_col = '%s.%s' % (qn(alias), qn(col))
|
||||
|
||||
# See if a Oracle Geometry function matches the lookup type next
|
||||
lookup_info = self.geometry_functions.get(lookup_type, False)
|
||||
if lookup_info:
|
||||
# Lookup types that are tuples take tuple arguments, e.g., 'relate' and
|
||||
# 'dwithin' lookup types.
|
||||
if isinstance(lookup_info, tuple):
|
||||
# First element of tuple is lookup type, second element is the type
|
||||
# of the expected argument (e.g., str, float)
|
||||
sdo_op, arg_type = lookup_info
|
||||
geom = value[0]
|
||||
|
||||
# Ensuring that a tuple _value_ was passed in from the user
|
||||
if not isinstance(value, tuple):
|
||||
raise ValueError('Tuple required for `%s` lookup type.' % lookup_type)
|
||||
if len(value) != 2:
|
||||
raise ValueError('2-element tuple required for %s lookup type.' % lookup_type)
|
||||
|
||||
# Ensuring the argument type matches what we expect.
|
||||
if not isinstance(value[1], arg_type):
|
||||
raise ValueError('Argument type should be %s, got %s instead.' % (arg_type, type(value[1])))
|
||||
|
||||
if lookup_type == 'relate':
|
||||
# The SDORelate class handles construction for these queries,
|
||||
# and verifies the mask argument.
|
||||
return sdo_op(value[1]).as_sql(geo_col, self.get_geom_placeholder(field, geom))
|
||||
else:
|
||||
# Otherwise, just call the `as_sql` method on the SDOOperation instance.
|
||||
return sdo_op.as_sql(geo_col, self.get_geom_placeholder(field, geom))
|
||||
else:
|
||||
# Lookup info is a SDOOperation instance, whose `as_sql` method returns
|
||||
# the SQL necessary for the geometry function call. For example:
|
||||
# SDO_CONTAINS("geoapp_country"."poly", SDO_GEOMTRY('POINT(5 23)', 4326)) = 'TRUE'
|
||||
return lookup_info.as_sql(geo_col, self.get_geom_placeholder(field, value))
|
||||
elif lookup_type == 'isnull':
|
||||
# Handling 'isnull' lookup type
|
||||
return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))
|
||||
|
||||
raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type))
|
||||
|
||||
def spatial_aggregate_sql(self, agg):
|
||||
"""
|
||||
Returns the spatial aggregate SQL template and function for the
|
||||
given Aggregate instance.
|
||||
"""
|
||||
agg_name = agg.__class__.__name__.lower()
|
||||
if agg_name == 'union' : agg_name += 'agg'
|
||||
if agg.is_extent:
|
||||
sql_template = '%(function)s(%(field)s)'
|
||||
else:
|
||||
sql_template = '%(function)s(SDOAGGRTYPE(%(field)s,%(tolerance)s))'
|
||||
sql_function = getattr(self, agg_name)
|
||||
return self.select % sql_template, sql_function
|
||||
|
||||
# Routines for getting the OGC-compliant models.
|
||||
def geometry_columns(self):
|
||||
from django.contrib.gis.db.backends.oracle.models import GeometryColumns
|
||||
return GeometryColumns
|
||||
|
||||
def spatial_ref_sys(self):
|
||||
from django.contrib.gis.db.backends.oracle.models import SpatialRefSys
|
||||
return SpatialRefSys
|
||||
Reference in New Issue
Block a user