Loading django/contrib/gis/db/backends/oracle/base.py +4 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from django.db.backends.oracle.base import DatabaseWrapper as OracleDatabaseWrap from django.contrib.gis.db.backends.oracle.creation import OracleCreation from django.contrib.gis.db.backends.oracle.introspection import OracleIntrospection from django.contrib.gis.db.backends.oracle.operations import OracleOperations from django.contrib.gis.db.backends.oracle.schema import OracleGISSchemaEditor class DatabaseWrapper(OracleDatabaseWrapper): Loading @@ -10,3 +11,6 @@ class DatabaseWrapper(OracleDatabaseWrapper): self.ops = OracleOperations(self) self.creation = OracleCreation(self) self.introspection = OracleIntrospection(self) def schema_editor(self, *args, **kwargs): return OracleGISSchemaEditor(self, *args, **kwargs) django/contrib/gis/db/backends/oracle/operations.py +3 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,9 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): truncate_params = {'relate': None} def geo_quote_name(self, name): return super(OracleOperations, self).geo_quote_name(name).upper() def convert_extent(self, clob): if clob: # Generally, Oracle returns a polygon for the extent -- however, Loading django/contrib/gis/db/backends/oracle/schema.py 0 → 100644 +94 −0 Original line number Diff line number Diff line from django.contrib.gis.db.models.fields import GeometryField from django.db.backends.oracle.schema import DatabaseSchemaEditor from django.db.backends.utils import truncate_name class OracleGISSchemaEditor(DatabaseSchemaEditor): sql_add_geometry_metadata = (""" INSERT INTO USER_SDO_GEOM_METADATA ("TABLE_NAME", "COLUMN_NAME", "DIMINFO", "SRID") VALUES ( %(table)s, %(column)s, MDSYS.SDO_DIM_ARRAY( MDSYS.SDO_DIM_ELEMENT('LONG', %(dim0)s, %(dim2)s, %(tolerance)s), MDSYS.SDO_DIM_ELEMENT('LAT', %(dim1)s, %(dim3)s, %(tolerance)s) ), %(srid)s )""") sql_add_spatial_index = 'CREATE INDEX %(index)s ON %(table)s(%(column)s) INDEXTYPE IS MDSYS.SPATIAL_INDEX' sql_drop_spatial_index = 'DROP INDEX %(index)s' sql_clear_geometry_table_metadata = 'DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s' sql_clear_geometry_field_metadata = ( 'DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s ' 'AND COLUMN_NAME = %(column)s' ) def __init__(self, *args, **kwargs): super(OracleGISSchemaEditor, self).__init__(*args, **kwargs) self.geometry_sql = [] def geo_quote_name(self, name): return self.connection.ops.geo_quote_name(name) def column_sql(self, model, field, include_default=False): column_sql = super(OracleGISSchemaEditor, self).column_sql(model, field, include_default) if isinstance(field, GeometryField): db_table = model._meta.db_table self.geometry_sql.append( self.sql_add_geometry_metadata % { 'table': self.geo_quote_name(db_table), 'column': self.geo_quote_name(field.column), 'dim0': field._extent[0], 'dim1': field._extent[1], 'dim2': field._extent[2], 'dim3': field._extent[3], 'tolerance': field._tolerance, 'srid': field.srid, } ) if field.spatial_index: self.geometry_sql.append( self.sql_add_spatial_index % { 'index': self.quote_name(self._create_spatial_index_name(model, field)), 'table': self.quote_name(db_table), 'column': self.quote_name(field.column), } ) return column_sql def create_model(self, model): super(OracleGISSchemaEditor, self).create_model(model) self.run_geometry_sql() def delete_model(self, model): super(OracleGISSchemaEditor, self).delete_model(model) self.execute(self.sql_clear_geometry_table_metadata % { 'table': self.geo_quote_name(model._meta.db_table), }) def add_field(self, model, field): super(OracleGISSchemaEditor, self).add_field(model, field) self.run_geometry_sql() def remove_field(self, model, field): if isinstance(field, GeometryField): self.execute(self.sql_clear_geometry_field_metadata % { 'table': self.geo_quote_name(model._meta.db_table), 'column': self.geo_quote_name(field.column), }) if field.spatial_index: self.execute(self.sql_drop_spatial_index % { 'index': self.quote_name(self._create_spatial_index_name(model, field)), }) super(OracleGISSchemaEditor, self).remove_field(model, field) def run_geometry_sql(self): for sql in self.geometry_sql: self.execute(sql) self.geometry_sql = [] def _create_spatial_index_name(self, model, field): # Oracle doesn't allow object names > 30 characters. Use this scheme # instead of self._create_index_name() for backwards compatibility. return truncate_name('%s_%s_id' % (model._meta.db_table, field.column), 30) django/contrib/gis/tests/gis_migrations/test_operations.py +13 −8 Original line number Diff line number Diff line Loading @@ -53,6 +53,17 @@ class OperationTests(TransactionTestCase): )] return self.apply_operations('gis', ProjectState(), operations) def assertGeometryColumnsCount(self, expected_count): table_name = "gis_neighborhood" if connection.features.uppercases_column_names: table_name = table_name.upper() self.assertEqual( GeometryColumns.objects.filter(**{ GeometryColumns.table_name_col(): table_name, }).count(), expected_count ) def test_add_gis_field(self): """ Tests the AddField operation with a GIS-enabled column. Loading @@ -72,10 +83,7 @@ class OperationTests(TransactionTestCase): # Test GeometryColumns when available if HAS_GEOMETRY_COLUMNS: self.assertEqual( GeometryColumns.objects.filter(**{GeometryColumns.table_name_col(): "gis_neighborhood"}).count(), 2 ) self.assertGeometryColumnsCount(2) if self.has_spatial_indexes: with connection.cursor() as cursor: Loading @@ -97,10 +105,7 @@ class OperationTests(TransactionTestCase): # Test GeometryColumns when available if HAS_GEOMETRY_COLUMNS: self.assertEqual( GeometryColumns.objects.filter(**{GeometryColumns.table_name_col(): "gis_neighborhood"}).count(), 0 ) self.assertGeometryColumnsCount(0) def test_create_model_spatial_index(self): self.current_state = self.set_up_test_model() Loading docs/releases/1.7.1.txt +3 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ Bugfixes * Added ``SchemaEditor`` for MySQL GIS backend so that spatial indexes will be created for apps with migrations (:ticket:`23538`). * Added ``SchemaEditor`` for Oracle GIS backend so that spatial metadata and indexes will be created for apps with migrations (:ticket:`23537`). * Coerced the ``related_name`` model field option to unicode during migration generation to generate migrations that work with both Python 2 and 3 (:ticket:`23455`). Loading
django/contrib/gis/db/backends/oracle/base.py +4 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from django.db.backends.oracle.base import DatabaseWrapper as OracleDatabaseWrap from django.contrib.gis.db.backends.oracle.creation import OracleCreation from django.contrib.gis.db.backends.oracle.introspection import OracleIntrospection from django.contrib.gis.db.backends.oracle.operations import OracleOperations from django.contrib.gis.db.backends.oracle.schema import OracleGISSchemaEditor class DatabaseWrapper(OracleDatabaseWrapper): Loading @@ -10,3 +11,6 @@ class DatabaseWrapper(OracleDatabaseWrapper): self.ops = OracleOperations(self) self.creation = OracleCreation(self) self.introspection = OracleIntrospection(self) def schema_editor(self, *args, **kwargs): return OracleGISSchemaEditor(self, *args, **kwargs)
django/contrib/gis/db/backends/oracle/operations.py +3 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,9 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): truncate_params = {'relate': None} def geo_quote_name(self, name): return super(OracleOperations, self).geo_quote_name(name).upper() def convert_extent(self, clob): if clob: # Generally, Oracle returns a polygon for the extent -- however, Loading
django/contrib/gis/db/backends/oracle/schema.py 0 → 100644 +94 −0 Original line number Diff line number Diff line from django.contrib.gis.db.models.fields import GeometryField from django.db.backends.oracle.schema import DatabaseSchemaEditor from django.db.backends.utils import truncate_name class OracleGISSchemaEditor(DatabaseSchemaEditor): sql_add_geometry_metadata = (""" INSERT INTO USER_SDO_GEOM_METADATA ("TABLE_NAME", "COLUMN_NAME", "DIMINFO", "SRID") VALUES ( %(table)s, %(column)s, MDSYS.SDO_DIM_ARRAY( MDSYS.SDO_DIM_ELEMENT('LONG', %(dim0)s, %(dim2)s, %(tolerance)s), MDSYS.SDO_DIM_ELEMENT('LAT', %(dim1)s, %(dim3)s, %(tolerance)s) ), %(srid)s )""") sql_add_spatial_index = 'CREATE INDEX %(index)s ON %(table)s(%(column)s) INDEXTYPE IS MDSYS.SPATIAL_INDEX' sql_drop_spatial_index = 'DROP INDEX %(index)s' sql_clear_geometry_table_metadata = 'DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s' sql_clear_geometry_field_metadata = ( 'DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s ' 'AND COLUMN_NAME = %(column)s' ) def __init__(self, *args, **kwargs): super(OracleGISSchemaEditor, self).__init__(*args, **kwargs) self.geometry_sql = [] def geo_quote_name(self, name): return self.connection.ops.geo_quote_name(name) def column_sql(self, model, field, include_default=False): column_sql = super(OracleGISSchemaEditor, self).column_sql(model, field, include_default) if isinstance(field, GeometryField): db_table = model._meta.db_table self.geometry_sql.append( self.sql_add_geometry_metadata % { 'table': self.geo_quote_name(db_table), 'column': self.geo_quote_name(field.column), 'dim0': field._extent[0], 'dim1': field._extent[1], 'dim2': field._extent[2], 'dim3': field._extent[3], 'tolerance': field._tolerance, 'srid': field.srid, } ) if field.spatial_index: self.geometry_sql.append( self.sql_add_spatial_index % { 'index': self.quote_name(self._create_spatial_index_name(model, field)), 'table': self.quote_name(db_table), 'column': self.quote_name(field.column), } ) return column_sql def create_model(self, model): super(OracleGISSchemaEditor, self).create_model(model) self.run_geometry_sql() def delete_model(self, model): super(OracleGISSchemaEditor, self).delete_model(model) self.execute(self.sql_clear_geometry_table_metadata % { 'table': self.geo_quote_name(model._meta.db_table), }) def add_field(self, model, field): super(OracleGISSchemaEditor, self).add_field(model, field) self.run_geometry_sql() def remove_field(self, model, field): if isinstance(field, GeometryField): self.execute(self.sql_clear_geometry_field_metadata % { 'table': self.geo_quote_name(model._meta.db_table), 'column': self.geo_quote_name(field.column), }) if field.spatial_index: self.execute(self.sql_drop_spatial_index % { 'index': self.quote_name(self._create_spatial_index_name(model, field)), }) super(OracleGISSchemaEditor, self).remove_field(model, field) def run_geometry_sql(self): for sql in self.geometry_sql: self.execute(sql) self.geometry_sql = [] def _create_spatial_index_name(self, model, field): # Oracle doesn't allow object names > 30 characters. Use this scheme # instead of self._create_index_name() for backwards compatibility. return truncate_name('%s_%s_id' % (model._meta.db_table, field.column), 30)
django/contrib/gis/tests/gis_migrations/test_operations.py +13 −8 Original line number Diff line number Diff line Loading @@ -53,6 +53,17 @@ class OperationTests(TransactionTestCase): )] return self.apply_operations('gis', ProjectState(), operations) def assertGeometryColumnsCount(self, expected_count): table_name = "gis_neighborhood" if connection.features.uppercases_column_names: table_name = table_name.upper() self.assertEqual( GeometryColumns.objects.filter(**{ GeometryColumns.table_name_col(): table_name, }).count(), expected_count ) def test_add_gis_field(self): """ Tests the AddField operation with a GIS-enabled column. Loading @@ -72,10 +83,7 @@ class OperationTests(TransactionTestCase): # Test GeometryColumns when available if HAS_GEOMETRY_COLUMNS: self.assertEqual( GeometryColumns.objects.filter(**{GeometryColumns.table_name_col(): "gis_neighborhood"}).count(), 2 ) self.assertGeometryColumnsCount(2) if self.has_spatial_indexes: with connection.cursor() as cursor: Loading @@ -97,10 +105,7 @@ class OperationTests(TransactionTestCase): # Test GeometryColumns when available if HAS_GEOMETRY_COLUMNS: self.assertEqual( GeometryColumns.objects.filter(**{GeometryColumns.table_name_col(): "gis_neighborhood"}).count(), 0 ) self.assertGeometryColumnsCount(0) def test_create_model_spatial_index(self): self.current_state = self.set_up_test_model() Loading
docs/releases/1.7.1.txt +3 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ Bugfixes * Added ``SchemaEditor`` for MySQL GIS backend so that spatial indexes will be created for apps with migrations (:ticket:`23538`). * Added ``SchemaEditor`` for Oracle GIS backend so that spatial metadata and indexes will be created for apps with migrations (:ticket:`23537`). * Coerced the ``related_name`` model field option to unicode during migration generation to generate migrations that work with both Python 2 and 3 (:ticket:`23455`).