From 35e649b197e16fff0de95562950d22ce7b1a51f6 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 17 Sep 2016 17:51:13 +0200 Subject: [PATCH] Simplified PostGIS index creation Less special-casing and code more in line with 'normal' index creation. --- .../contrib/gis/db/backends/postgis/schema.py | 74 ++++++------------- 1 file changed, 23 insertions(+), 51 deletions(-) diff --git a/django/contrib/gis/db/backends/postgis/schema.py b/django/contrib/gis/db/backends/postgis/schema.py index c75b65c5f0..4ee46cb3ff 100644 --- a/django/contrib/gis/db/backends/postgis/schema.py +++ b/django/contrib/gis/db/backends/postgis/schema.py @@ -6,61 +6,33 @@ class PostGISSchemaEditor(DatabaseSchemaEditor): geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND' rast_index_wrapper = 'ST_ConvexHull(%s)' - sql_add_spatial_index = "CREATE INDEX %(index)s ON %(table)s USING %(index_type)s (%(column)s %(ops)s)" - - def __init__(self, *args, **kwargs): - super(PostGISSchemaEditor, 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): - from django.contrib.gis.db.models.fields import BaseSpatialField - if not isinstance(field, BaseSpatialField): - return super(PostGISSchemaEditor, self).column_sql(model, field, include_default) + def _field_should_be_indexed(self, model, field): + if getattr(field, 'spatial_index', False): + return True + return super(PostGISSchemaEditor, self)._field_should_be_indexed(model, field) - column_sql = super(PostGISSchemaEditor, self).column_sql(model, field, include_default) + def _create_index_sql(self, model, fields, suffix="", sql=None): + if len(fields) != 1 or not hasattr(fields[0], 'geodetic'): + return super(PostGISSchemaEditor, self)._create_index_sql(model, fields, suffix=suffix, sql=sql) - if field.spatial_index: - # Spatial indexes created the same way for both Geometry and - # Geography columns. - field_column = self.quote_name(field.column) - if field.geom_type == 'RASTER': - # For raster fields, wrap index creation SQL statement with ST_ConvexHull. - # Indexes on raster columns are based on the convex hull of the raster. - field_column = self.rast_index_wrapper % field_column - index_ops = '' - elif field.geography: - index_ops = '' - else: - # Use either "nd" ops which are fast on multidimensional cases - # or just plain gist index for the 2d case. - if field.dim > 2: - index_ops = self.geom_index_ops_nd - else: - index_ops = '' - self.geometry_sql.append( - self.sql_add_spatial_index % { - "index": self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)), - "table": self.quote_name(model._meta.db_table), - "column": field_column, - "index_type": self.geom_index_type, - "ops": index_ops, - } - ) - return column_sql + field = fields[0] + field_column = self.quote_name(field.column) - def create_model(self, model): - super(PostGISSchemaEditor, self).create_model(model) - # Create geometry columns - for sql in self.geometry_sql: - self.execute(sql) - self.geometry_sql = [] + if field.geom_type == 'RASTER': + # For raster fields, wrap index creation SQL statement with ST_ConvexHull. + # Indexes on raster columns are based on the convex hull of the raster. + field_column = self.rast_index_wrapper % field_column + elif field.dim > 2 and not field.geography: + # Use "nd" ops which are fast on multidimensional cases + field_column = "%s %s" % (field_column, self.geom_index_ops_nd) - def add_field(self, model, field): - super(PostGISSchemaEditor, self).add_field(model, field) - # Create geometry columns - for sql in self.geometry_sql: - self.execute(sql) - self.geometry_sql = [] + return self.sql_create_index % { + "name": self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)), + "table": self.quote_name(model._meta.db_table), + "using": "USING %s" % self.geom_index_type, + "columns": field_column, + "extra": '', + }