Loading django/contrib/gis/db/backends/base/features.py +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ class BaseSpatialFeatures(object): supports_distances_lookups = True supports_left_right_lookups = False # Does the database have raster support? supports_raster = False @property def supports_bbcontains_lookup(self): return 'bbcontains' in self.connection.ops.gis_operators Loading django/contrib/gis/db/backends/postgis/const.py 0 → 100644 +43 −0 Original line number Diff line number Diff line """ PostGIS to GDAL conversion constant definitions """ # Lookup to convert pixel type values from GDAL to PostGIS GDAL_TO_POSTGIS = [None, 4, 6, 5, 8, 7, 10, 11, None, None, None, None] # Lookup to convert pixel type values from PostGIS to GDAL POSTGIS_TO_GDAL = [1, 1, 1, 3, 1, 3, 2, 5, 4, None, 6, 7, None, None] # Struct pack structure for raster header, the raster header has the # following structure: # # Endianness, PostGIS raster version, number of bands, scale, origin, # skew, srid, width, and height. # # Scale, origin, and skew have x and y values. PostGIS currently uses # a fixed endianness (1) and there is only one version (0). POSTGIS_HEADER_STRUCTURE = 'B H H d d d d d d i H H' # Lookup values to convert GDAL pixel types to struct characters. This is # used to pack and unpack the pixel values of PostGIS raster bands. GDAL_TO_STRUCT = [ None, 'B', 'H', 'h', 'L', 'l', 'f', 'd', None, None, None, None, ] # Size of the packed value in bytes for different numerical types. # This is needed to cut chunks of band data out of PostGIS raster strings # when decomposing them into GDALRasters. # See https://docs.python.org/3/library/struct.html#format-characters STRUCT_SIZE = { 'b': 1, # Signed char 'B': 1, # Unsigned char '?': 1, # _Bool 'h': 2, # Short 'H': 2, # Unsigned short 'i': 4, # Integer 'I': 4, # Unsigned Integer 'l': 4, # Long 'L': 4, # Unsigned Long 'f': 4, # Float 'd': 8, # Double } django/contrib/gis/db/backends/postgis/features.py +1 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,4 @@ class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures): supports_3d_storage = True supports_3d_functions = True supports_left_right_lookups = True supports_raster = True django/contrib/gis/db/backends/postgis/introspection.py +20 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,26 @@ class PostGISIntrospection(DatabaseIntrospection): 'raster_overviews', ] # Overridden from parent to include raster indices in retrieval. # Raster indices have pg_index.indkey value 0 because they are an # expression over the raster column through the ST_ConvexHull function. # So the default query has to be adapted to include raster indices. _get_indexes_query = """ SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index idx, pg_catalog.pg_attribute attr LEFT JOIN pg_catalog.pg_type t ON t.oid = attr.atttypid WHERE c.oid = idx.indrelid AND idx.indexrelid = c2.oid AND attr.attrelid = c.oid AND ( attr.attnum = idx.indkey[0] OR (t.typname LIKE 'raster' AND idx.indkey = '0') ) AND attr.attnum > 0 AND c.relname = %s""" def get_postgis_types(self): """ Returns a dictionary with keys that are the PostgreSQL object Loading django/contrib/gis/db/backends/postgis/operations.py +29 −7 Original line number Diff line number Diff line Loading @@ -4,6 +4,9 @@ from django.conf import settings from django.contrib.gis.db.backends.base.operations import \ BaseSpatialOperations from django.contrib.gis.db.backends.postgis.adapter import PostGISAdapter from django.contrib.gis.db.backends.postgis.pgraster import ( from_pgraster, to_pgraster, ) from django.contrib.gis.db.backends.utils import SpatialOperator from django.contrib.gis.geometry.backend import Geometry from django.contrib.gis.measure import Distance Loading @@ -14,6 +17,7 @@ from django.db.utils import ProgrammingError from django.utils.functional import cached_property from .models import PostGISGeometryColumns, PostGISSpatialRefSys from .pgraster import get_pgraster_srid class PostGISOperator(SpatialOperator): Loading Loading @@ -205,12 +209,11 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): def geo_db_type(self, f): """ Return the database field type for the given geometry field. Typically this is `None` because geometry columns are added via the `AddGeometryColumn` stored procedure, unless the field has been specified to be of geography type instead. Return the database field type for the given spatial field. """ if f.geography: if f.geom_type == 'RASTER': return 'raster' elif f.geography: if f.srid != 4326: raise NotImplementedError('PostGIS only supports geography columns with an SRID of 4326.') Loading Loading @@ -272,10 +275,21 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): SRID of the field. Specifically, this routine will substitute in the ST_Transform() function call. """ if value is None or value.srid == f.srid: # Get the srid for this object if value is None: value_srid = None elif f.geom_type == 'RASTER': value_srid = get_pgraster_srid(value) else: value_srid = value.srid # Adding Transform() to the SQL placeholder if the value srid # is not equal to the field srid. if value_srid is None or value_srid == f.srid: placeholder = '%s' elif f.geom_type == 'RASTER': placeholder = '%s((%%s)::raster, %s)' % (self.transform, f.srid) else: # Adding Transform() to the SQL placeholder. placeholder = '%s(%%s, %s)' % (self.transform, f.srid) if hasattr(value, 'as_sql'): Loading Loading @@ -359,3 +373,11 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): def spatial_ref_sys(self): return PostGISSpatialRefSys # Methods to convert between PostGIS rasters and dicts that are # readable by GDALRaster. def parse_raster(self, value): return from_pgraster(value) def deconstruct_raster(self, value): return to_pgraster(value) Loading
django/contrib/gis/db/backends/base/features.py +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ class BaseSpatialFeatures(object): supports_distances_lookups = True supports_left_right_lookups = False # Does the database have raster support? supports_raster = False @property def supports_bbcontains_lookup(self): return 'bbcontains' in self.connection.ops.gis_operators Loading
django/contrib/gis/db/backends/postgis/const.py 0 → 100644 +43 −0 Original line number Diff line number Diff line """ PostGIS to GDAL conversion constant definitions """ # Lookup to convert pixel type values from GDAL to PostGIS GDAL_TO_POSTGIS = [None, 4, 6, 5, 8, 7, 10, 11, None, None, None, None] # Lookup to convert pixel type values from PostGIS to GDAL POSTGIS_TO_GDAL = [1, 1, 1, 3, 1, 3, 2, 5, 4, None, 6, 7, None, None] # Struct pack structure for raster header, the raster header has the # following structure: # # Endianness, PostGIS raster version, number of bands, scale, origin, # skew, srid, width, and height. # # Scale, origin, and skew have x and y values. PostGIS currently uses # a fixed endianness (1) and there is only one version (0). POSTGIS_HEADER_STRUCTURE = 'B H H d d d d d d i H H' # Lookup values to convert GDAL pixel types to struct characters. This is # used to pack and unpack the pixel values of PostGIS raster bands. GDAL_TO_STRUCT = [ None, 'B', 'H', 'h', 'L', 'l', 'f', 'd', None, None, None, None, ] # Size of the packed value in bytes for different numerical types. # This is needed to cut chunks of band data out of PostGIS raster strings # when decomposing them into GDALRasters. # See https://docs.python.org/3/library/struct.html#format-characters STRUCT_SIZE = { 'b': 1, # Signed char 'B': 1, # Unsigned char '?': 1, # _Bool 'h': 2, # Short 'H': 2, # Unsigned short 'i': 4, # Integer 'I': 4, # Unsigned Integer 'l': 4, # Long 'L': 4, # Unsigned Long 'f': 4, # Float 'd': 8, # Double }
django/contrib/gis/db/backends/postgis/features.py +1 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,4 @@ class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures): supports_3d_storage = True supports_3d_functions = True supports_left_right_lookups = True supports_raster = True
django/contrib/gis/db/backends/postgis/introspection.py +20 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,26 @@ class PostGISIntrospection(DatabaseIntrospection): 'raster_overviews', ] # Overridden from parent to include raster indices in retrieval. # Raster indices have pg_index.indkey value 0 because they are an # expression over the raster column through the ST_ConvexHull function. # So the default query has to be adapted to include raster indices. _get_indexes_query = """ SELECT DISTINCT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index idx, pg_catalog.pg_attribute attr LEFT JOIN pg_catalog.pg_type t ON t.oid = attr.atttypid WHERE c.oid = idx.indrelid AND idx.indexrelid = c2.oid AND attr.attrelid = c.oid AND ( attr.attnum = idx.indkey[0] OR (t.typname LIKE 'raster' AND idx.indkey = '0') ) AND attr.attnum > 0 AND c.relname = %s""" def get_postgis_types(self): """ Returns a dictionary with keys that are the PostgreSQL object Loading
django/contrib/gis/db/backends/postgis/operations.py +29 −7 Original line number Diff line number Diff line Loading @@ -4,6 +4,9 @@ from django.conf import settings from django.contrib.gis.db.backends.base.operations import \ BaseSpatialOperations from django.contrib.gis.db.backends.postgis.adapter import PostGISAdapter from django.contrib.gis.db.backends.postgis.pgraster import ( from_pgraster, to_pgraster, ) from django.contrib.gis.db.backends.utils import SpatialOperator from django.contrib.gis.geometry.backend import Geometry from django.contrib.gis.measure import Distance Loading @@ -14,6 +17,7 @@ from django.db.utils import ProgrammingError from django.utils.functional import cached_property from .models import PostGISGeometryColumns, PostGISSpatialRefSys from .pgraster import get_pgraster_srid class PostGISOperator(SpatialOperator): Loading Loading @@ -205,12 +209,11 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): def geo_db_type(self, f): """ Return the database field type for the given geometry field. Typically this is `None` because geometry columns are added via the `AddGeometryColumn` stored procedure, unless the field has been specified to be of geography type instead. Return the database field type for the given spatial field. """ if f.geography: if f.geom_type == 'RASTER': return 'raster' elif f.geography: if f.srid != 4326: raise NotImplementedError('PostGIS only supports geography columns with an SRID of 4326.') Loading Loading @@ -272,10 +275,21 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): SRID of the field. Specifically, this routine will substitute in the ST_Transform() function call. """ if value is None or value.srid == f.srid: # Get the srid for this object if value is None: value_srid = None elif f.geom_type == 'RASTER': value_srid = get_pgraster_srid(value) else: value_srid = value.srid # Adding Transform() to the SQL placeholder if the value srid # is not equal to the field srid. if value_srid is None or value_srid == f.srid: placeholder = '%s' elif f.geom_type == 'RASTER': placeholder = '%s((%%s)::raster, %s)' % (self.transform, f.srid) else: # Adding Transform() to the SQL placeholder. placeholder = '%s(%%s, %s)' % (self.transform, f.srid) if hasattr(value, 'as_sql'): Loading Loading @@ -359,3 +373,11 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations): def spatial_ref_sys(self): return PostGISSpatialRefSys # Methods to convert between PostGIS rasters and dicts that are # readable by GDALRaster. def parse_raster(self, value): return from_pgraster(value) def deconstruct_raster(self, value): return to_pgraster(value)