Fixed #10888 -- May now insert NULL `GeometryField` values on Oracle.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10631 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d6829782d0
commit
44c062344f
|
@ -94,7 +94,7 @@ class OracleSpatialField(Field):
|
||||||
SDO_CS.TRANSFORM() function call.
|
SDO_CS.TRANSFORM() function call.
|
||||||
"""
|
"""
|
||||||
if value is None:
|
if value is None:
|
||||||
return '%s'
|
return 'NULL'
|
||||||
elif value.srid != self.srid:
|
elif value.srid != self.srid:
|
||||||
# Adding Transform() to the SQL placeholder.
|
# Adding Transform() to the SQL placeholder.
|
||||||
return '%s(SDO_GEOMETRY(%%s, %s), %s)' % (TRANSFORM, value.srid, self.srid)
|
return '%s(SDO_GEOMETRY(%%s, %s), %s)' % (TRANSFORM, value.srid, self.srid)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.db.models.manager import Manager
|
from django.db.models.manager import Manager
|
||||||
from django.contrib.gis.db.models.query import GeoQuerySet
|
from django.contrib.gis.db.models.query import GeoQuerySet
|
||||||
|
from django.contrib.gis.db.models.sql.subqueries import insert_query
|
||||||
|
|
||||||
class GeoManager(Manager):
|
class GeoManager(Manager):
|
||||||
"Overrides Manager to return Geographic QuerySets."
|
"Overrides Manager to return Geographic QuerySets."
|
||||||
|
@ -86,3 +87,6 @@ class GeoManager(Manager):
|
||||||
|
|
||||||
def unionagg(self, *args, **kwargs):
|
def unionagg(self, *args, **kwargs):
|
||||||
return self.get_query_set().unionagg(*args, **kwargs)
|
return self.get_query_set().unionagg(*args, **kwargs)
|
||||||
|
|
||||||
|
def _insert(self, values, **kwargs):
|
||||||
|
return insert_query(self.model, values, **kwargs)
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
from django.contrib.gis.db.backend import SpatialBackend
|
||||||
|
from django.db.models.query import insert_query
|
||||||
|
|
||||||
|
if SpatialBackend.oracle:
|
||||||
|
from django.db import connection
|
||||||
|
from django.db.models.sql.subqueries import InsertQuery
|
||||||
|
|
||||||
|
class OracleGeoInsertQuery(InsertQuery):
|
||||||
|
def insert_values(self, insert_values, raw_values=False):
|
||||||
|
"""
|
||||||
|
This routine is overloaded from InsertQuery so that no parameter is
|
||||||
|
passed into cx_Oracle for NULL geometries. The reason is that
|
||||||
|
cx_Oracle has no way to bind Oracle object values (like
|
||||||
|
MDSYS.SDO_GEOMETRY).
|
||||||
|
"""
|
||||||
|
placeholders, values = [], []
|
||||||
|
for field, val in insert_values:
|
||||||
|
if hasattr(field, 'get_placeholder'):
|
||||||
|
ph = field.get_placeholder(val)
|
||||||
|
else:
|
||||||
|
ph = '%s'
|
||||||
|
|
||||||
|
placeholders.append(ph)
|
||||||
|
self.columns.append(field.column)
|
||||||
|
|
||||||
|
# If 'NULL' for the placeholder, omit appending None
|
||||||
|
# to the values list (which is used for db params).
|
||||||
|
if not ph == 'NULL':
|
||||||
|
values.append(val)
|
||||||
|
if raw_values:
|
||||||
|
self.values.extend(values)
|
||||||
|
else:
|
||||||
|
self.params += tuple(values)
|
||||||
|
self.values.extend(placeholders)
|
||||||
|
|
||||||
|
def insert_query(model, values, return_id=False, raw_values=False):
|
||||||
|
query = OracleGeoInsertQuery(model, connection)
|
||||||
|
query.insert_values(values, raw_values)
|
||||||
|
return query.execute_sql(return_id)
|
|
@ -30,7 +30,7 @@ class GeoModelTest(unittest.TestCase):
|
||||||
data_dir = os.path.join(os.path.dirname(__file__), 'sql')
|
data_dir = os.path.join(os.path.dirname(__file__), 'sql')
|
||||||
def get_file(wkt_file):
|
def get_file(wkt_file):
|
||||||
return os.path.join(data_dir, wkt_file)
|
return os.path.join(data_dir, wkt_file)
|
||||||
|
State(name='Puerto Rico', poly=None).save()
|
||||||
State(name='Colorado', poly=fromfile(get_file('co.wkt'))).save()
|
State(name='Colorado', poly=fromfile(get_file('co.wkt'))).save()
|
||||||
State(name='Kansas', poly=fromfile(get_file('ks.wkt'))).save()
|
State(name='Kansas', poly=fromfile(get_file('ks.wkt'))).save()
|
||||||
Country(name='Texas', mpoly=fromfile(get_file('tx.wkt'))).save()
|
Country(name='Texas', mpoly=fromfile(get_file('tx.wkt'))).save()
|
||||||
|
@ -39,13 +39,7 @@ class GeoModelTest(unittest.TestCase):
|
||||||
# Ensuring that data was loaded from initial SQL.
|
# Ensuring that data was loaded from initial SQL.
|
||||||
self.assertEqual(2, Country.objects.count())
|
self.assertEqual(2, Country.objects.count())
|
||||||
self.assertEqual(8, City.objects.count())
|
self.assertEqual(8, City.objects.count())
|
||||||
|
self.assertEqual(3, State.objects.count())
|
||||||
# Only PostGIS can handle NULL geometries
|
|
||||||
if SpatialBackend.postgis or SpatialBackend.spatialite:
|
|
||||||
n_state = 3
|
|
||||||
else:
|
|
||||||
n_state = 2
|
|
||||||
self.assertEqual(n_state, State.objects.count())
|
|
||||||
|
|
||||||
def test02_proxy(self):
|
def test02_proxy(self):
|
||||||
"Testing Lazy-Geometry support (using the GeometryProxy)."
|
"Testing Lazy-Geometry support (using the GeometryProxy)."
|
||||||
|
@ -369,10 +363,6 @@ class GeoModelTest(unittest.TestCase):
|
||||||
m1.save()
|
m1.save()
|
||||||
self.assertEqual(-1, m1.geom.srid)
|
self.assertEqual(-1, m1.geom.srid)
|
||||||
|
|
||||||
# Oracle does not support NULL geometries in its spatial index for
|
|
||||||
# some routines (e.g., SDO_GEOM.RELATE).
|
|
||||||
@no_oracle
|
|
||||||
@no_spatialite
|
|
||||||
def test12_null_geometries(self):
|
def test12_null_geometries(self):
|
||||||
"Testing NULL geometry support, and the `isnull` lookup type."
|
"Testing NULL geometry support, and the `isnull` lookup type."
|
||||||
if DISABLE: return
|
if DISABLE: return
|
||||||
|
@ -391,9 +381,14 @@ class GeoModelTest(unittest.TestCase):
|
||||||
self.assertEqual(True, 'Kansas' in state_names)
|
self.assertEqual(True, 'Kansas' in state_names)
|
||||||
|
|
||||||
# Saving another commonwealth w/a NULL geometry.
|
# Saving another commonwealth w/a NULL geometry.
|
||||||
if not SpatialBackend.oracle:
|
nmi = State.objects.create(name='Northern Mariana Islands', poly=None)
|
||||||
# TODO: Fix saving w/NULL geometry on Oracle.
|
self.assertEqual(nmi.poly, None)
|
||||||
State(name='Northern Mariana Islands', poly=None).save()
|
|
||||||
|
# Assigning a geomery and saving -- then UPDATE back to NULL.
|
||||||
|
nmi.poly = 'POLYGON((0 0,1 0,1 1,1 0,0 0))'
|
||||||
|
nmi.save()
|
||||||
|
State.objects.filter(name='Northern Mariana Islands').update(poly=None)
|
||||||
|
self.assertEqual(None, State.objects.get(name='Northern Mariana Islands').poly)
|
||||||
|
|
||||||
@no_oracle # No specific `left` or `right` operators in Oracle.
|
@no_oracle # No specific `left` or `right` operators in Oracle.
|
||||||
@no_spatialite # No `left` or `right` operators in SpatiaLite.
|
@no_spatialite # No `left` or `right` operators in SpatiaLite.
|
||||||
|
|
Loading…
Reference in New Issue