Fixed #33047 -- Fixed CheckConstraint crash with GIS lookups on PostGIS and MySQL GIS backends.
Thanks Daniel Swain for the report and Arsalan Ghassemi for the initial patch. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
ae4077e13e
commit
64c3f049ea
|
@ -22,6 +22,11 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
|
|||
return True
|
||||
return super().skip_default(field)
|
||||
|
||||
def quote_value(self, value):
|
||||
if isinstance(value, self.connection.ops.Adapter):
|
||||
return super().quote_value(str(value))
|
||||
return super().quote_value(value)
|
||||
|
||||
def column_sql(self, model, field, include_default=False):
|
||||
column_sql = super().column_sql(model, field, include_default)
|
||||
# MySQL doesn't support spatial indexes on NULL columns
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures
|
|||
from django.db.backends.oracle.features import (
|
||||
DatabaseFeatures as OracleDatabaseFeatures,
|
||||
)
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
|
||||
class DatabaseFeatures(BaseSpatialFeatures, OracleDatabaseFeatures):
|
||||
|
@ -12,3 +13,13 @@ class DatabaseFeatures(BaseSpatialFeatures, OracleDatabaseFeatures):
|
|||
supports_dwithin_distance_expr = False
|
||||
supports_tolerance_parameter = True
|
||||
unsupported_geojson_options = {'bbox', 'crs', 'precision'}
|
||||
|
||||
@cached_property
|
||||
def django_test_skips(self):
|
||||
skips = super().django_test_skips
|
||||
skips.update({
|
||||
"Oracle doesn't support spatial operators in constraints.": {
|
||||
'gis_tests.gis_migrations.test_operations.OperationTests.test_add_check_constraint',
|
||||
},
|
||||
})
|
||||
return skips
|
||||
|
|
|
@ -31,6 +31,11 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
|||
def geo_quote_name(self, name):
|
||||
return self.connection.ops.geo_quote_name(name)
|
||||
|
||||
def quote_value(self, value):
|
||||
if isinstance(value, self.connection.ops.Adapter):
|
||||
return super().quote_value(str(value))
|
||||
return super().quote_value(value)
|
||||
|
||||
def column_sql(self, model, field, include_default=False):
|
||||
column_sql = super().column_sql(model, field, include_default)
|
||||
if isinstance(field, GeometryField):
|
||||
|
|
|
@ -60,10 +60,10 @@ class PostGISAdapter:
|
|||
"""
|
||||
if self.is_geometry:
|
||||
# Psycopg will figure out whether to use E'\\000' or '\000'.
|
||||
return '%s(%s)' % (
|
||||
'ST_GeogFromWKB' if self.geography else 'ST_GeomFromEWKB',
|
||||
self._adapter.getquoted().decode()
|
||||
return b'%s(%s)' % (
|
||||
b'ST_GeogFromWKB' if self.geography else b'ST_GeomFromEWKB',
|
||||
self._adapter.getquoted()
|
||||
)
|
||||
else:
|
||||
# For rasters, add explicit type cast to WKB string.
|
||||
return "'%s'::raster" % self.ewkb
|
||||
return b"'%s'::raster" % self.ewkb.encode()
|
||||
|
|
|
@ -235,6 +235,24 @@ class OperationTests(OperationTestCase):
|
|||
)
|
||||
self.assertFalse(Neighborhood.objects.first().geom.hasz)
|
||||
|
||||
@skipUnlessDBFeature('supports_column_check_constraints', 'can_introspect_check_constraints')
|
||||
def test_add_check_constraint(self):
|
||||
Neighborhood = self.current_state.apps.get_model('gis', 'Neighborhood')
|
||||
poly = Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)))
|
||||
constraint = models.CheckConstraint(
|
||||
check=models.Q(geom=poly),
|
||||
name='geom_within_constraint',
|
||||
)
|
||||
Neighborhood._meta.constraints = [constraint]
|
||||
with connection.schema_editor() as editor:
|
||||
editor.add_constraint(Neighborhood, constraint)
|
||||
with connection.cursor() as cursor:
|
||||
constraints = connection.introspection.get_constraints(
|
||||
cursor,
|
||||
Neighborhood._meta.db_table,
|
||||
)
|
||||
self.assertIn('geom_within_constraint', constraints)
|
||||
|
||||
|
||||
@skipIfDBFeature('supports_raster')
|
||||
class NoRasterSupportTests(OperationTestCase):
|
||||
|
|
Loading…
Reference in New Issue