2015-08-05 22:08:56 +08:00
|
|
|
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
2013-11-27 21:32:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
class PostGISSchemaEditor(DatabaseSchemaEditor):
|
|
|
|
geom_index_type = 'GIST'
|
|
|
|
geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND'
|
2015-06-19 23:46:03 +08:00
|
|
|
rast_index_wrapper = 'ST_ConvexHull(%s)'
|
2013-11-27 21:32:12 +08:00
|
|
|
|
2016-09-19 15:58:58 +08:00
|
|
|
sql_alter_column_to_3d = "ALTER COLUMN %(column)s TYPE %(type)s USING ST_Force3D(%(column)s)::%(type)s"
|
|
|
|
sql_alter_column_to_2d = "ALTER COLUMN %(column)s TYPE %(type)s USING ST_Force2D(%(column)s)::%(type)s"
|
|
|
|
|
2013-11-27 21:32:12 +08:00
|
|
|
def geo_quote_name(self, name):
|
|
|
|
return self.connection.ops.geo_quote_name(name)
|
|
|
|
|
2016-09-17 23:51:13 +08:00
|
|
|
def _field_should_be_indexed(self, model, field):
|
|
|
|
if getattr(field, 'spatial_index', False):
|
|
|
|
return True
|
2017-01-21 21:13:44 +08:00
|
|
|
return super()._field_should_be_indexed(model, field)
|
2016-09-17 23:51:13 +08:00
|
|
|
|
2017-08-04 05:33:06 +08:00
|
|
|
def _create_index_sql(self, model, fields, **kwargs):
|
2016-09-17 23:51:13 +08:00
|
|
|
if len(fields) != 1 or not hasattr(fields[0], 'geodetic'):
|
2017-08-04 05:33:06 +08:00
|
|
|
return super()._create_index_sql(model, fields, **kwargs)
|
2016-09-17 23:51:13 +08:00
|
|
|
|
|
|
|
field = fields[0]
|
|
|
|
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
|
|
|
|
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)
|
|
|
|
|
|
|
|
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": '',
|
|
|
|
}
|
2016-09-19 15:58:58 +08:00
|
|
|
|
|
|
|
def _alter_column_type_sql(self, table, old_field, new_field, new_type):
|
|
|
|
"""
|
|
|
|
Special case when dimension changed.
|
|
|
|
"""
|
|
|
|
if not hasattr(old_field, 'dim') or not hasattr(new_field, 'dim'):
|
2017-01-21 21:13:44 +08:00
|
|
|
return super()._alter_column_type_sql(table, old_field, new_field, new_type)
|
2016-09-19 15:58:58 +08:00
|
|
|
|
|
|
|
if old_field.dim == 2 and new_field.dim == 3:
|
|
|
|
sql_alter = self.sql_alter_column_to_3d
|
|
|
|
elif old_field.dim == 3 and new_field.dim == 2:
|
|
|
|
sql_alter = self.sql_alter_column_to_2d
|
|
|
|
else:
|
|
|
|
sql_alter = self.sql_alter_column_type
|
|
|
|
return (
|
|
|
|
(
|
|
|
|
sql_alter % {
|
|
|
|
"column": self.quote_name(new_field.column),
|
|
|
|
"type": new_type,
|
|
|
|
},
|
|
|
|
[],
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
)
|