mirror of https://github.com/django/django.git
Refs #35074 -- Simplified and unified adding spatial indexes on MySQL and Oracle.
This uses `deferred_sql` and `_field_indexes_sql()` instead of custom hooks on MySQL.
This commit is contained in:
parent
b6ad8b687a
commit
e3de574c1e
|
@ -10,10 +10,6 @@ logger = logging.getLogger("django.contrib.gis")
|
||||||
class MySQLGISSchemaEditor(DatabaseSchemaEditor):
|
class MySQLGISSchemaEditor(DatabaseSchemaEditor):
|
||||||
sql_add_spatial_index = "CREATE SPATIAL INDEX %(index)s ON %(table)s(%(column)s)"
|
sql_add_spatial_index = "CREATE SPATIAL INDEX %(index)s ON %(table)s(%(column)s)"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.geometry_sql = []
|
|
||||||
|
|
||||||
def skip_default(self, field):
|
def skip_default(self, field):
|
||||||
# Geometry fields are stored as BLOB/TEXT, for which MySQL < 8.0.13
|
# Geometry fields are stored as BLOB/TEXT, for which MySQL < 8.0.13
|
||||||
# doesn't support defaults.
|
# doesn't support defaults.
|
||||||
|
@ -29,29 +25,29 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
|
||||||
return super().quote_value(str(value))
|
return super().quote_value(str(value))
|
||||||
return super().quote_value(value)
|
return super().quote_value(value)
|
||||||
|
|
||||||
def column_sql(self, model, field, include_default=False):
|
def _field_indexes_sql(self, model, field):
|
||||||
column_sql = super().column_sql(model, field, include_default)
|
|
||||||
# MySQL doesn't support spatial indexes on NULL columns
|
|
||||||
if isinstance(field, GeometryField) and field.spatial_index and not field.null:
|
if isinstance(field, GeometryField) and field.spatial_index and not field.null:
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
supports_spatial_index = (
|
||||||
|
self.connection.introspection.supports_spatial_index(
|
||||||
|
cursor, model._meta.db_table
|
||||||
|
)
|
||||||
|
)
|
||||||
qn = self.connection.ops.quote_name
|
qn = self.connection.ops.quote_name
|
||||||
db_table = model._meta.db_table
|
sql = self.sql_add_spatial_index % {
|
||||||
self.geometry_sql.append(
|
"index": qn(self._create_spatial_index_name(model, field)),
|
||||||
self.sql_add_spatial_index
|
"table": qn(model._meta.db_table),
|
||||||
% {
|
"column": qn(field.column),
|
||||||
"index": qn(self._create_spatial_index_name(model, field)),
|
}
|
||||||
"table": qn(db_table),
|
if supports_spatial_index:
|
||||||
"column": qn(field.column),
|
return [sql]
|
||||||
}
|
else:
|
||||||
)
|
logger.error(
|
||||||
return column_sql
|
f"Cannot create SPATIAL INDEX {sql}. Only MyISAM, Aria, and InnoDB "
|
||||||
|
f"support them.",
|
||||||
def create_model(self, model):
|
)
|
||||||
super().create_model(model)
|
return []
|
||||||
self.create_spatial_indexes()
|
return super()._field_indexes_sql(model, field)
|
||||||
|
|
||||||
def add_field(self, model, field):
|
|
||||||
super().add_field(model, field)
|
|
||||||
self.create_spatial_indexes()
|
|
||||||
|
|
||||||
def remove_field(self, model, field):
|
def remove_field(self, model, field):
|
||||||
if isinstance(field, GeometryField) and field.spatial_index and not field.null:
|
if isinstance(field, GeometryField) and field.spatial_index and not field.null:
|
||||||
|
@ -70,14 +66,3 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
|
||||||
|
|
||||||
def _create_spatial_index_name(self, model, field):
|
def _create_spatial_index_name(self, model, field):
|
||||||
return "%s_%s_id" % (model._meta.db_table, field.column)
|
return "%s_%s_id" % (model._meta.db_table, field.column)
|
||||||
|
|
||||||
def create_spatial_indexes(self):
|
|
||||||
for sql in self.geometry_sql:
|
|
||||||
try:
|
|
||||||
self.execute(sql)
|
|
||||||
except OperationalError:
|
|
||||||
logger.error(
|
|
||||||
f"Cannot create SPATIAL INDEX {sql}. Only MyISAM, Aria, and InnoDB "
|
|
||||||
f"support them.",
|
|
||||||
)
|
|
||||||
self.geometry_sql = []
|
|
||||||
|
|
|
@ -40,14 +40,27 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
||||||
return super().quote_value(str(value))
|
return super().quote_value(str(value))
|
||||||
return super().quote_value(value)
|
return super().quote_value(value)
|
||||||
|
|
||||||
|
def _field_indexes_sql(self, model, field):
|
||||||
|
if isinstance(field, GeometryField) and field.spatial_index:
|
||||||
|
return [
|
||||||
|
self.sql_add_spatial_index
|
||||||
|
% {
|
||||||
|
"index": self.quote_name(
|
||||||
|
self._create_spatial_index_name(model, field)
|
||||||
|
),
|
||||||
|
"table": self.quote_name(model._meta.db_table),
|
||||||
|
"column": self.quote_name(field.column),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return super()._field_indexes_sql(model, field)
|
||||||
|
|
||||||
def column_sql(self, model, field, include_default=False):
|
def column_sql(self, model, field, include_default=False):
|
||||||
column_sql = super().column_sql(model, field, include_default)
|
column_sql = super().column_sql(model, field, include_default)
|
||||||
if isinstance(field, GeometryField):
|
if isinstance(field, GeometryField):
|
||||||
db_table = model._meta.db_table
|
|
||||||
self.geometry_sql.append(
|
self.geometry_sql.append(
|
||||||
self.sql_add_geometry_metadata
|
self.sql_add_geometry_metadata
|
||||||
% {
|
% {
|
||||||
"table": self.geo_quote_name(db_table),
|
"table": self.geo_quote_name(model._meta.db_table),
|
||||||
"column": self.geo_quote_name(field.column),
|
"column": self.geo_quote_name(field.column),
|
||||||
"dim0": field._extent[0],
|
"dim0": field._extent[0],
|
||||||
"dim1": field._extent[1],
|
"dim1": field._extent[1],
|
||||||
|
@ -57,17 +70,6 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
||||||
"srid": field.srid,
|
"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
|
return column_sql
|
||||||
|
|
||||||
def create_model(self, model):
|
def create_model(self, model):
|
||||||
|
|
Loading…
Reference in New Issue