2010-01-19 05:02:47 +08:00
|
|
|
from django.contrib.gis.gdal import OGRGeomType
|
2015-01-28 20:35:27 +08:00
|
|
|
from django.db.backends.sqlite3.introspection import (
|
|
|
|
DatabaseIntrospection, FlexibleFieldLookupDict,
|
|
|
|
)
|
2010-01-19 05:02:47 +08:00
|
|
|
|
2013-11-03 01:18:46 +08:00
|
|
|
|
2010-01-19 05:02:47 +08:00
|
|
|
class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict):
|
|
|
|
"""
|
|
|
|
Sublcass that includes updates the `base_data_types_reverse` dict
|
|
|
|
for geometry field types.
|
|
|
|
"""
|
|
|
|
base_data_types_reverse = FlexibleFieldLookupDict.base_data_types_reverse.copy()
|
|
|
|
base_data_types_reverse.update(
|
2013-10-27 09:27:42 +08:00
|
|
|
{'point': 'GeometryField',
|
|
|
|
'linestring': 'GeometryField',
|
|
|
|
'polygon': 'GeometryField',
|
|
|
|
'multipoint': 'GeometryField',
|
|
|
|
'multilinestring': 'GeometryField',
|
|
|
|
'multipolygon': 'GeometryField',
|
|
|
|
'geometrycollection': 'GeometryField',
|
2010-01-19 05:02:47 +08:00
|
|
|
})
|
|
|
|
|
2013-11-03 01:18:46 +08:00
|
|
|
|
2010-01-19 05:02:47 +08:00
|
|
|
class SpatiaLiteIntrospection(DatabaseIntrospection):
|
|
|
|
data_types_reverse = GeoFlexibleFieldLookupDict()
|
|
|
|
|
|
|
|
def get_geometry_type(self, table_name, geo_col):
|
|
|
|
cursor = self.connection.cursor()
|
|
|
|
try:
|
|
|
|
# Querying the `geometry_columns` table to get additional metadata.
|
2016-05-31 23:31:51 +08:00
|
|
|
cursor.execute('SELECT coord_dimension, srid, geometry_type '
|
2013-09-12 17:14:16 +08:00
|
|
|
'FROM geometry_columns '
|
2016-05-31 23:31:51 +08:00
|
|
|
'WHERE f_table_name=%s AND f_geometry_column=%s',
|
2010-01-19 05:02:47 +08:00
|
|
|
(table_name, geo_col))
|
|
|
|
row = cursor.fetchone()
|
|
|
|
if not row:
|
|
|
|
raise Exception('Could not find a geometry column for "%s"."%s"' %
|
|
|
|
(table_name, geo_col))
|
|
|
|
|
|
|
|
# OGRGeomType does not require GDAL and makes it easy to convert
|
|
|
|
# from OGC geom type name to Django field.
|
2014-11-04 05:03:59 +08:00
|
|
|
ogr_type = row[2]
|
2016-12-29 23:27:49 +08:00
|
|
|
if isinstance(ogr_type, int) and ogr_type > 1000:
|
2016-08-10 00:46:14 +08:00
|
|
|
# SpatiaLite versions >= 4 use the new SFSQL 1.2 offsets
|
2014-11-04 05:03:59 +08:00
|
|
|
# 1000 (Z), 2000 (M), and 3000 (ZM) to indicate the presence of
|
|
|
|
# higher dimensional coordinates (M not yet supported by Django).
|
|
|
|
ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit
|
|
|
|
field_type = OGRGeomType(ogr_type).django
|
2010-01-19 05:02:47 +08:00
|
|
|
|
|
|
|
# Getting any GeometryField keyword arguments that are not the default.
|
|
|
|
dim = row[0]
|
|
|
|
srid = row[1]
|
|
|
|
field_params = {}
|
|
|
|
if srid != 4326:
|
|
|
|
field_params['srid'] = srid
|
2016-12-29 23:27:49 +08:00
|
|
|
if (isinstance(dim, str) and 'Z' in dim) or dim == 3:
|
2010-01-19 05:02:47 +08:00
|
|
|
field_params['dim'] = 3
|
|
|
|
finally:
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
return field_type, field_params
|
2014-09-24 02:13:59 +08:00
|
|
|
|
2016-08-20 18:14:02 +08:00
|
|
|
def get_constraints(self, cursor, table_name):
|
2017-01-21 21:13:44 +08:00
|
|
|
constraints = super().get_constraints(cursor, table_name)
|
2014-09-24 02:13:59 +08:00
|
|
|
cursor.execute('SELECT f_geometry_column '
|
|
|
|
'FROM geometry_columns '
|
|
|
|
'WHERE f_table_name=%s AND spatial_index_enabled=1', (table_name,))
|
|
|
|
for row in cursor.fetchall():
|
2016-08-20 18:14:02 +08:00
|
|
|
constraints['%s__spatial__index' % row[0]] = {
|
|
|
|
"columns": [row[0]],
|
|
|
|
"primary_key": False,
|
|
|
|
"unique": False,
|
|
|
|
"foreign_key": None,
|
|
|
|
"check": False,
|
|
|
|
"index": True,
|
|
|
|
}
|
|
|
|
return constraints
|