summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2024-05-17 20:57:13 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-07-29 12:31:32 +0200
commite3de574c1e60f644b817e5d938c2d0bd3e535f00 (patch)
treeb08dc5e2bbe812a26c3c5ce4af43eed5142d982c
parentb6ad8b687adf011245270df17a38c1a42792e3d7 (diff)
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.
-rw-r--r--django/contrib/gis/db/backends/mysql/schema.py57
-rw-r--r--django/contrib/gis/db/backends/oracle/schema.py28
2 files changed, 36 insertions, 49 deletions
diff --git a/django/contrib/gis/db/backends/mysql/schema.py b/django/contrib/gis/db/backends/mysql/schema.py
index f3ddf14fa7..152cbc3960 100644
--- a/django/contrib/gis/db/backends/mysql/schema.py
+++ b/django/contrib/gis/db/backends/mysql/schema.py
@@ -10,10 +10,6 @@ logger = logging.getLogger("django.contrib.gis")
class MySQLGISSchemaEditor(DatabaseSchemaEditor):
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):
# Geometry fields are stored as BLOB/TEXT, for which MySQL < 8.0.13
# doesn't support defaults.
@@ -29,29 +25,29 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
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
+ def _field_indexes_sql(self, model, field):
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
- db_table = model._meta.db_table
- self.geometry_sql.append(
- self.sql_add_spatial_index
- % {
- "index": qn(self._create_spatial_index_name(model, field)),
- "table": qn(db_table),
- "column": qn(field.column),
- }
- )
- return column_sql
-
- def create_model(self, model):
- super().create_model(model)
- self.create_spatial_indexes()
-
- def add_field(self, model, field):
- super().add_field(model, field)
- self.create_spatial_indexes()
+ sql = self.sql_add_spatial_index % {
+ "index": qn(self._create_spatial_index_name(model, field)),
+ "table": qn(model._meta.db_table),
+ "column": qn(field.column),
+ }
+ if supports_spatial_index:
+ return [sql]
+ else:
+ logger.error(
+ f"Cannot create SPATIAL INDEX {sql}. Only MyISAM, Aria, and InnoDB "
+ f"support them.",
+ )
+ return []
+ return super()._field_indexes_sql(model, field)
def remove_field(self, model, field):
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):
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 = []
diff --git a/django/contrib/gis/db/backends/oracle/schema.py b/django/contrib/gis/db/backends/oracle/schema.py
index fd542531eb..e17a4b1911 100644
--- a/django/contrib/gis/db/backends/oracle/schema.py
+++ b/django/contrib/gis/db/backends/oracle/schema.py
@@ -40,14 +40,27 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
return super().quote_value(str(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):
column_sql = super().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),
+ "table": self.geo_quote_name(model._meta.db_table),
"column": self.geo_quote_name(field.column),
"dim0": field._extent[0],
"dim1": field._extent[1],
@@ -57,17 +70,6 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
"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):