Commit 91ef2a52 authored by Justin Bronn's avatar Justin Bronn
Browse files

Use native geometry types on PostGIS 2.0+ instead of `AddGeometryColumn` and...

Use native geometry types on PostGIS 2.0+ instead of `AddGeometryColumn` and don't query database in `PostGISCreation.sql_table_creation_suffix`.
parent b6b8a3f6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -32,8 +32,9 @@ class BaseSpatialOperations(object):
    # How the geometry column should be selected.
    select = None

    # Does the spatial database have a geography type?
    # Does the spatial database have a geometry or geography type?
    geography = False
    geometry = False

    area = False
    centroid = False
+12 −20
Original line number Diff line number Diff line
@@ -4,7 +4,8 @@ from django.db.backends.postgresql_psycopg2.creation import DatabaseCreation

class PostGISCreation(DatabaseCreation):
    geom_index_type = 'GIST'
    geom_index_opts = 'GIST_GEOMETRY_OPS'
    geom_index_ops = 'GIST_GEOMETRY_OPS'
    geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND'

    def sql_indexes_for_field(self, model, f, style):
        "Return any spatial index creation SQL for the field."
@@ -17,8 +18,9 @@ class PostGISCreation(DatabaseCreation):
            qn = self.connection.ops.quote_name
            db_table = model._meta.db_table

            if f.geography:
                # Geogrophy columns are created normally.
            if f.geography or self.connection.ops.geometry:
                # Geography and Geometry (PostGIS 2.0+) columns are
                # created normally.
                pass
            else:
                # Geometry columns are created by `AddGeometryColumn`
@@ -47,33 +49,23 @@ class PostGISCreation(DatabaseCreation):
                # which are fast on multidimensional cases, or just plain
                # gist index for the 2d case.
                if f.geography:
                    index_opts = ''
                elif self.connection.ops.spatial_version >= (2, 0):
                    index_ops = ''
                elif self.connection.ops.geometry:
                    if f.dim > 2:
                        index_opts = ' ' + style.SQL_KEYWORD('gist_geometry_ops_nd')
                        index_ops = ' ' + style.SQL_KEYWORD(self.geom_index_ops_nd)
                    else:
                        index_opts = ''
                        index_ops = ''
                else:
                    index_opts = ' ' + style.SQL_KEYWORD(self.geom_index_opts)
                    index_ops = ' ' + style.SQL_KEYWORD(self.geom_index_ops)
                output.append(style.SQL_KEYWORD('CREATE INDEX ') +
                              style.SQL_TABLE(qn('%s_%s_id' % (db_table, f.column))) +
                              style.SQL_KEYWORD(' ON ') +
                              style.SQL_TABLE(qn(db_table)) +
                              style.SQL_KEYWORD(' USING ') +
                              style.SQL_COLTYPE(self.geom_index_type) + ' ( ' +
                              style.SQL_FIELD(qn(f.column)) + index_opts + ' );')
                              style.SQL_FIELD(qn(f.column)) + index_ops + ' );')
        return output

    def sql_table_creation_suffix(self):
        cursor = self.connection.cursor()
        cursor.execute('SELECT datname FROM pg_database;')
        db_names = [row[0] for row in cursor.fetchall()]
        postgis_template = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')

        if postgis_template in db_names:
            qn = self.connection.ops.quote_name
            return ' TEMPLATE %s' % qn(postgis_template)
        elif self.connection.ops.spatial_version < (2, 0):
            raise ImproperlyConfigured("Template database '%s' does not exist." % postgis_template)
        else:
            return ''
        return ' TEMPLATE %s' % self.connection.ops.quote_name(postgis_template)
+18 −5
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
            self.geom_func_prefix = prefix
            self.spatial_version = version
        except DatabaseError:
            raise ImproperlyConfigured('Cannot determine PostGIS version for database "%s". '
            raise ImproperlyConfigured(
                'Cannot determine PostGIS version for database "%s". '
                'GeoDjango requires at least PostGIS version 1.3. '
                'Was the database created from a spatial database '
                'template?' % self.connection.settings_dict['NAME']
@@ -215,6 +216,10 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
                'bboverlaps' : PostGISOperator('&&'),
                }

        # Native geometry type support added in PostGIS 2.0.
        if version >= (2, 0, 0):
            self.geometry = True

        # Creating a dictionary lookup of all GIS terms for PostGIS.
        gis_terms = ['isnull']
        gis_terms += list(self.geometry_operators)
@@ -320,6 +325,14 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
                                          'only with an SRID of 4326.')

            return 'geography(%s,%d)'% (f.geom_type, f.srid)
        elif self.geometry:
            # Postgis 2.0 supports type-based geometries.
            # TODO: Support 'M' extension.
            if f.dim == 3:
                geom_type = f.geom_type + 'Z'
            else:
                geom_type = f.geom_type
            return 'geometry(%s,%d)' % (geom_type, f.srid)
        else:
            return None

+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ class GeometryField(Field):
        # Is this a geography rather than a geometry column?
        self.geography = geography

        # Oracle-specific private attributes for creating the entrie in
        # Oracle-specific private attributes for creating the entry in
        # `USER_SDO_GEOM_METADATA`
        self._extent = kwargs.pop('extent', (-180.0, -90.0, 180.0, 90.0))
        self._tolerance = kwargs.pop('tolerance', 0.05)