[1.0.X] Fixed various Oracle errata and test failures present in this branch (including not going to 11).

Backport of Oracle-related changes from trunk in r10197.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@10614 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2009-04-21 21:25:47 +00:00
parent ed5e3c3d2b
commit f110f91a03
5 changed files with 68 additions and 34 deletions

View File

@ -201,7 +201,7 @@ class GeoQuery(sql.Query):
"""
if SpatialBackend.oracle:
# Running through Oracle's first.
value = super(GeoQuery, self).convert_values(value, field)
value = super(GeoQuery, self).convert_values(value, field or GeomField())
if isinstance(field, DistanceField):
# Using the field's distance attribute, can instantiate
# `Distance` with the right context.
@ -325,15 +325,22 @@ class GeoQuery(sql.Query):
return self._check_geo_field(self.model, field_name)
### Field Classes for `convert_values` ####
class AreaField(object):
class BaseField(object):
def get_internal_type(self):
"Overloaded method so OracleQuery.convert_values doesn't balk."
return None
if SpatialBackend.oracle: BaseField.empty_strings_allowed = False
class AreaField(BaseField):
def __init__(self, area_att):
self.area_att = area_att
class DistanceField(object):
class DistanceField(BaseField):
def __init__(self, distance_att):
self.distance_att = distance_att
# Rather than use GeometryField (which requires a SQL query
# upon instantiation), use this lighter weight class.
class GeomField(object):
class GeomField(BaseField):
pass

View File

@ -13,7 +13,7 @@ def geo_suite():
from django.contrib.gis.utils import HAS_GEOIP
# Tests that require use of a spatial database (e.g., creation of models)
test_models = ['geoapp',]
test_models = ['geoapp', 'layermap', 'relatedapp']
# Tests that do not require setting up and tearing down a spatial database.
test_suite_names = [
@ -21,15 +21,8 @@ def geo_suite():
'test_measure',
]
if HAS_GDAL:
if oracle:
# TODO: There's a problem with `select_related` and GeoQuerySet on
# Oracle -- e.g., GeoModel.objects.distance(geom, field_name='fk__point')
# doesn't work so we don't test `relatedapp`.
test_models += ['distapp', 'layermap']
elif postgis:
test_models += ['distapp', 'layermap', 'relatedapp']
elif mysql:
test_models += ['relatedapp', 'layermap']
if oracle or postgis:
test_models.append('distapp')
test_suite_names += [
'test_gdal_driver',

View File

@ -115,8 +115,12 @@ class DistanceTest(unittest.TestCase):
# with different projected coordinate systems.
dist1 = SouthTexasCity.objects.distance(lagrange, field_name='point')
dist2 = SouthTexasCity.objects.distance(lagrange) # Using GEOSGeometry parameter
dist3 = SouthTexasCityFt.objects.distance(lagrange.ewkt) # Using EWKT string parameter.
dist4 = SouthTexasCityFt.objects.distance(lagrange)
if oracle:
dist_qs = [dist1, dist2]
else:
dist3 = SouthTexasCityFt.objects.distance(lagrange.ewkt) # Using EWKT string parameter.
dist4 = SouthTexasCityFt.objects.distance(lagrange)
dist_qs = [dist1, dist2, dist3, dist4]
# Original query done on PostGIS, have to adjust AlmostEqual tolerance
# for Oracle.
@ -124,7 +128,7 @@ class DistanceTest(unittest.TestCase):
else: tol = 5
# Ensuring expected distances are returned for each distance queryset.
for qs in [dist1, dist2, dist3, dist4]:
for qs in dist_qs:
for i, c in enumerate(qs):
self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
@ -194,8 +198,16 @@ class DistanceTest(unittest.TestCase):
# (thus, Houston and Southside place will be excluded as tested in
# the `test02_dwithin` above).
qs1 = SouthTexasCity.objects.filter(point__distance_gte=(self.stx_pnt, D(km=7))).filter(point__distance_lte=(self.stx_pnt, D(km=20)))
qs2 = SouthTexasCityFt.objects.filter(point__distance_gte=(self.stx_pnt, D(km=7))).filter(point__distance_lte=(self.stx_pnt, D(km=20)))
for qs in qs1, qs2:
# Oracle 11 incorrectly thinks spatial reference system for the
# SouthTexasCityFt model is not projected, so omit.
if oracle:
dist_qs = (qs1,)
else:
qs2 = SouthTexasCityFt.objects.filter(point__distance_gte=(self.stx_pnt, D(km=7))).filter(point__distance_lte=(self.stx_pnt, D(km=20)))
dist_qs = (qs1, qs2)
for qs in dist_qs:
cities = self.get_names(qs)
self.assertEqual(cities, ['Bellaire', 'Pearland', 'West University Place'])

View File

@ -150,7 +150,7 @@ class GeoModelTest(unittest.TestCase):
if SpatialBackend.oracle:
# No precision parameter for Oracle :-/
import re
gml_regex = re.compile(r'<gml:Point srsName="SDO:4326" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="\." cs="," ts=" ">-104.60925199\d+,38.25500\d+ </gml:coordinates></gml:Point>')
gml_regex = re.compile(r'<gml:Point srsName="SDO:4326" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ </gml:coordinates></gml:Point>')
for ptown in [ptown1, ptown2]:
self.assertEqual(True, bool(gml_regex.match(ptown.gml)))
else:

View File

@ -1,6 +1,6 @@
import os, unittest
from django.contrib.gis.geos import *
from django.contrib.gis.tests.utils import no_mysql, postgis
from django.contrib.gis.tests.utils import no_mysql, no_oracle, oracle, postgis
from django.conf import settings
from models import City, Location, DirectoryEntry
@ -19,6 +19,7 @@ class RelatedGeoModelTest(unittest.TestCase):
c = City(name=name, state=state, location=loc)
c.save()
@no_oracle # There are problems w/spatial Oracle pagination and select_related()
def test02_select_related(self):
"Testing `select_related` on geographic models (see #7126)."
qs1 = City.objects.all()
@ -33,6 +34,7 @@ class RelatedGeoModelTest(unittest.TestCase):
self.assertEqual(Point(lon, lat), c.location.point)
@no_mysql
@no_oracle # Pagination problem is implicated in this test as well.
def test03_transform_related(self):
"Testing the `transform` GeoQuerySet method on related geographic models."
# All the transformations are to state plane coordinate systems using
@ -71,22 +73,42 @@ class RelatedGeoModelTest(unittest.TestCase):
#self.assertEqual(nqueries, len(connection.queries))
@no_mysql
def test04_related_aggregate(self):
"Testing the `extent` and `unionagg` GeoQuerySet aggregates on related geographic models."
if postgis:
# One for all locations, one that excludes Roswell.
all_extent = (-104.528060913086, 33.0583305358887,-79.4607315063477, 40.1847610473633)
txpa_extent = (-97.51611328125, 33.0583305358887,-79.4607315063477, 40.1847610473633)
e1 = City.objects.extent(field_name='location__point')
e2 = City.objects.exclude(name='Roswell').extent(field_name='location__point')
for ref, e in [(all_extent, e1), (txpa_extent, e2)]:
for ref_val, e_val in zip(ref, e): self.assertAlmostEqual(ref_val, e_val)
@no_oracle
def test04a_related_extent_aggregate(self):
"Testing the `extent` GeoQuerySet aggregates on related geographic models."
# One for all locations, one that excludes Roswell.
all_extent = (-104.528060913086, 33.0583305358887,-79.4607315063477, 40.1847610473633)
txpa_extent = (-97.51611328125, 33.0583305358887,-79.4607315063477, 40.1847610473633)
e1 = City.objects.extent(field_name='location__point')
e2 = City.objects.exclude(name='Roswell').extent(field_name='location__point')
tol = 9
for ref, e in [(all_extent, e1), (txpa_extent, e2)]:
for ref_val, e_val in zip(ref, e): self.assertAlmostEqual(ref_val, e_val, tol)
@no_mysql
def test04b_related_union_aggregate(self):
"Testing the `unionagg` GeoQuerySet aggregates on related geographic models."
# These are the points that are components of the aggregate geographic
# union that is returned.
p1 = Point(-104.528056, 33.387222)
p2 = Point(-97.516111, 33.058333)
p3 = Point(-79.460734, 40.18476)
# Creating the reference union geometry depending on the spatial backend,
# as Oracle will have a different internal ordering of the component
# geometries than PostGIS. The second union aggregate is for a union
# query that includes limiting information in the WHERE clause (in other
# words a `.filter()` precedes the call to `.unionagg()`).
if oracle:
ref_u1 = MultiPoint(p3, p1, p2, srid=4326)
ref_u2 = MultiPoint(p3, p2, srid=4326)
else:
ref_u1 = MultiPoint(p1, p2, p3, srid=4326)
ref_u2 = MultiPoint(p2, p3, srid=4326)
# The second union is for a query that has something in the WHERE clause.
ref_u1 = GEOSGeometry('MULTIPOINT(-104.528056 33.387222,-97.516111 33.058333,-79.460734 40.18476)', 4326)
ref_u2 = GEOSGeometry('MULTIPOINT(-97.516111 33.058333,-79.460734 40.18476)', 4326)
u1 = City.objects.unionagg(field_name='location__point')
u2 = City.objects.exclude(name='Roswell').unionagg(field_name='location__point')
self.assertEqual(ref_u1, u1)
self.assertEqual(ref_u2, u2)