Browse Source

Fixed #24499 -- Dropped support for PostGIS 1.5.

Tim Graham 10 years ago
parent
commit
26996e2d55

+ 3 - 17
django/contrib/gis/db/backends/postgis/base.py

@@ -1,10 +1,7 @@
-from django.conf import settings
 from django.db.backends.base.base import NO_DB_ALIAS
 from django.db.backends.postgresql_psycopg2.base import \
     DatabaseWrapper as Psycopg2DatabaseWrapper
-from django.utils.functional import cached_property
 
-from .creation import PostGISCreation
 from .features import DatabaseFeatures
 from .introspection import PostGISIntrospection
 from .operations import PostGISOperations
@@ -18,22 +15,11 @@ class DatabaseWrapper(Psycopg2DatabaseWrapper):
         super(DatabaseWrapper, self).__init__(*args, **kwargs)
         if kwargs.get('alias', '') != NO_DB_ALIAS:
             self.features = DatabaseFeatures(self)
-            self.creation = PostGISCreation(self)
             self.ops = PostGISOperations(self)
             self.introspection = PostGISIntrospection(self)
 
-    @cached_property
-    def template_postgis(self):
-        template_postgis = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')
-        with self._nodb_connection.cursor() as cursor:
-            cursor.execute('SELECT 1 FROM pg_database WHERE datname = %s LIMIT 1;', (template_postgis,))
-            if cursor.fetchone():
-                return template_postgis
-        return None
-
     def prepare_database(self):
         super(DatabaseWrapper, self).prepare_database()
-        if self.template_postgis is None:
-            # Check that postgis extension is installed on PostGIS >= 2
-            with self.cursor() as cursor:
-                cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
+        # Check that postgis extension is installed.
+        with self.cursor() as cursor:
+            cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")

+ 0 - 10
django/contrib/gis/db/backends/postgis/creation.py

@@ -1,10 +0,0 @@
-from django.db.backends.postgresql_psycopg2.creation import DatabaseCreation
-
-
-class PostGISCreation(DatabaseCreation):
-
-    def sql_table_creation_suffix(self):
-        if self.connection.template_postgis is not None:
-            return ' TEMPLATE %s' % (
-                self.connection.ops.quote_name(self.connection.template_postgis),)
-        return ''

+ 7 - 34
django/contrib/gis/db/backends/postgis/operations.py

@@ -110,6 +110,7 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
         self.distance_spheroid = prefix + 'distance_spheroid'
         self.envelope = prefix + 'Envelope'
         self.extent = prefix + 'Extent'
+        self.extent3d = prefix + '3DExtent'
         self.force_rhr = prefix + 'ForceRHR'
         self.geohash = prefix + 'GeoHash'
         self.geojson = prefix + 'AsGeoJson'
@@ -117,12 +118,14 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
         self.intersection = prefix + 'Intersection'
         self.kml = prefix + 'AsKML'
         self.length = prefix + 'Length'
+        self.length3d = prefix + '3DLength'
         self.length_spheroid = prefix + 'length_spheroid'
         self.makeline = prefix + 'MakeLine'
         self.mem_size = prefix + 'mem_size'
         self.num_geom = prefix + 'NumGeometries'
         self.num_points = prefix + 'npoints'
         self.perimeter = prefix + 'Perimeter'
+        self.perimeter3d = prefix + '3DPerimeter'
         self.point_on_surface = prefix + 'PointOnSurface'
         self.polygonize = prefix + 'Polygonize'
         self.reverse = prefix + 'Reverse'
@@ -135,34 +138,6 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
         self.union = prefix + 'Union'
         self.unionagg = prefix + 'Union'
 
-    # Following "attributes" are properties due to the spatial_version check and
-    # to delay database access
-    @property
-    def extent3d(self):
-        if self.spatial_version >= (2, 0, 0):
-            return self.geom_func_prefix + '3DExtent'
-        else:
-            return self.geom_func_prefix + 'Extent3D'
-
-    @property
-    def length3d(self):
-        if self.spatial_version >= (2, 0, 0):
-            return self.geom_func_prefix + '3DLength'
-        else:
-            return self.geom_func_prefix + 'Length3D'
-
-    @property
-    def perimeter3d(self):
-        if self.spatial_version >= (2, 0, 0):
-            return self.geom_func_prefix + '3DPerimeter'
-        else:
-            return self.geom_func_prefix + 'Perimeter3D'
-
-    @property
-    def geometry(self):
-        # Native geometry type support added in PostGIS 2.0.
-        return self.spatial_version >= (2, 0, 0)
-
     @cached_property
     def spatial_version(self):
         """Determine the version of the PostGIS library."""
@@ -180,7 +155,7 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
             except ProgrammingError:
                 raise ImproperlyConfigured(
                     'Cannot determine PostGIS version for database "%s". '
-                    'GeoDjango requires at least PostGIS version 1.5. '
+                    'GeoDjango requires at least PostGIS version 2.0. '
                     'Was the database created from a spatial database '
                     'template?' % self.connection.settings_dict['NAME']
                 )
@@ -234,16 +209,14 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
                 raise NotImplementedError('PostGIS only supports geography columns with an SRID of 4326.')
 
             return 'geography(%s,%d)' % (f.geom_type, f.srid)
-        elif self.geometry:
-            # Postgis 2.0 supports type-based geometries.
+        else:
+            # 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
 
     def get_distance(self, f, dist_val, lookup_type):
         """
@@ -253,7 +226,7 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
         This is the most complex implementation of the spatial backends due to
         what is supported on geodetic geometry columns vs. what's available on
         projected geometry columns.  In addition, it has to take into account
-        the geography column type newly introduced in PostGIS 1.5.
+        the geography column type.
         """
         # Getting the distance parameter and any options.
         if len(dist_val) == 1:

+ 5 - 50
django/contrib/gis/db/backends/postgis/schema.py

@@ -3,12 +3,8 @@ from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor
 
 class PostGISSchemaEditor(DatabaseSchemaEditor):
     geom_index_type = 'GIST'
-    geom_index_ops = 'GIST_GEOMETRY_OPS'
     geom_index_ops_nd = 'GIST_GEOMETRY_OPS_ND'
 
-    sql_add_geometry_column = "SELECT AddGeometryColumn(%(table)s, %(column)s, %(srid)s, %(geom_type)s, %(dim)s)"
-    sql_drop_geometry_column = "SELECT DropGeometryColumn(%(table)s, %(column)s)"
-    sql_alter_geometry_column_not_null = "ALTER TABLE %(table)s ALTER COLUMN %(column)s SET NOT NULL"
     sql_add_spatial_index = "CREATE INDEX %(index)s ON %(table)s USING %(index_type)s (%(column)s %(ops)s)"
     sql_clear_geometry_columns = "DELETE FROM geometry_columns WHERE f_table_name = %(table)s"
 
@@ -24,48 +20,21 @@ class PostGISSchemaEditor(DatabaseSchemaEditor):
         if not isinstance(field, GeometryField):
             return super(PostGISSchemaEditor, self).column_sql(model, field, include_default)
 
-        if field.geography or self.connection.ops.geometry:
-            # Geography and Geometry (PostGIS 2.0+) columns are
-            # created normally.
-            column_sql = super(PostGISSchemaEditor, self).column_sql(model, field, include_default)
-        else:
-            column_sql = None, None
-            # Geometry columns are created by the `AddGeometryColumn`
-            # stored procedure.
-            self.geometry_sql.append(
-                self.sql_add_geometry_column % {
-                    "table": self.geo_quote_name(model._meta.db_table),
-                    "column": self.geo_quote_name(field.column),
-                    "srid": field.srid,
-                    "geom_type": self.geo_quote_name(field.geom_type),
-                    "dim": field.dim,
-                }
-            )
-
-            if not field.null:
-                self.geometry_sql.append(
-                    self.sql_alter_geometry_column_not_null % {
-                        "table": self.quote_name(model._meta.db_table),
-                        "column": self.quote_name(field.column),
-                    }
-                )
+        column_sql = super(PostGISSchemaEditor, self).column_sql(model, field, include_default)
 
         if field.spatial_index:
             # Spatial indexes created the same way for both Geometry and
             # Geography columns.
-            # PostGIS 2.0 does not support GIST_GEOMETRY_OPS. So, on 1.5
-            # we use GIST_GEOMETRY_OPS, on 2.0 we use either "nd" ops
-            # which are fast on multidimensional cases, or just plain
-            # gist index for the 2d case.
+
             if field.geography:
                 index_ops = ''
-            elif self.connection.ops.geometry:
+            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 = ''
-            else:
-                index_ops = self.geom_index_ops
             self.geometry_sql.append(
                 self.sql_add_spatial_index % {
                     "index": self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)),
@@ -96,17 +65,3 @@ class PostGISSchemaEditor(DatabaseSchemaEditor):
         for sql in self.geometry_sql:
             self.execute(sql)
         self.geometry_sql = []
-
-    def remove_field(self, model, field):
-        from django.contrib.gis.db.models.fields import GeometryField
-        if not isinstance(field, GeometryField) or \
-           self.connection.ops.spatial_version > (2, 0) or \
-           field.geography:
-            super(PostGISSchemaEditor, self).remove_field(model, field)
-        else:
-            self.execute(
-                self.sql_drop_geometry_column % {
-                    "table": self.geo_quote_name(model._meta.db_table),
-                    "column": self.geo_quote_name(field.column),
-                }
-            )

+ 2 - 2
django/db/backends/base/schema.py

@@ -462,8 +462,8 @@ class BaseDatabaseSchemaEditor(object):
                 (new_type is None and new_field.remote_field is None)):
             raise ValueError(
                 "Cannot alter field %s into %s - they do not properly define "
-                "db_type (are you using PostGIS 1.5 or badly-written custom "
-                "fields?)" % (old_field, new_field),
+                "db_type (are you using a badly-written custom field?)" %
+                (old_field, new_field),
             )
         elif old_type is None and new_type is None and (
                 old_field.remote_field.through and new_field.remote_field.through and

+ 0 - 16
docs/ref/contrib/gis/install/create_template_postgis-1.5.sh

@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-if [[ `uname -r | grep el6` ]]; then
-  POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis
-  POSTGIS_SQL_FILE=$POSTGIS_SQL_PATH/postgis-64.sql
-else
-  POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5
-  POSTGIS_SQL_FILE=$POSTGIS_SQL_PATH/postgis.sql
-fi
-createdb -E UTF8 template_postgis # Create the template spatial database.
-createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
-psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
-psql -d template_postgis -f $POSTGIS_SQL_FILE # Loading the PostGIS SQL routines
-psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
-psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
-psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
-psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

+ 0 - 18
docs/ref/contrib/gis/install/create_template_postgis-debian.sh

@@ -1,18 +0,0 @@
-#!/bin/bash
-
-POSTGIS_SQL=postgis.sql
-
-# For Ubuntu 11.10, 12.04 / Linux Mint 12 (with PostGIS 1.5)
-if [ -d "/usr/share/postgresql/9.1/contrib/postgis-1.5" ]
-then
-    POSTGIS_SQL_PATH=/usr/share/postgresql/9.1/contrib/postgis-1.5
-fi
-
-createdb -E UTF8 template_postgis && \
-( createlang -d template_postgis -l | grep plpgsql || createlang -d template_postgis plpgsql ) && \
-psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" && \
-psql -d template_postgis -f $POSTGIS_SQL_PATH/$POSTGIS_SQL && \
-psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql && \
-psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" && \
-psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
-psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"

+ 1 - 2
docs/ref/contrib/gis/install/geolibs.txt

@@ -12,7 +12,7 @@ Program                   Description                           Required
 `PROJ.4`_                 Cartographic Projections library      Yes (PostgreSQL and SQLite only)  4.9, 4.8, 4.7, 4.6, 4.5, 4.4
 :doc:`GDAL <../gdal>`     Geospatial Data Abstraction Library   Yes (SQLite only)                 1.11, 1.10, 1.9, 1.8, 1.7
 :doc:`GeoIP <../geoip>`   IP-based geolocation library          No                                1.4
-`PostGIS`__               Spatial extensions for PostgreSQL     Yes (PostgreSQL only)             2.1, 2.0, 1.5
+`PostGIS`__               Spatial extensions for PostgreSQL     Yes (PostgreSQL only)             2.1, 2.0
 `SpatiaLite`__            Spatial extensions for SQLite         Yes (SQLite only)                 4.1, 4.0, 3.0, 2.4
 ========================  ====================================  ================================  ============================
 
@@ -29,7 +29,6 @@ totally fine with GeoDjango. Your mileage may vary.
     GDAL 1.9.0 2012-01-03
     GDAL 1.10.0 2013-04-29
     GDAL 1.11.0 2014-04-25
-    PostGIS 1.5.0 2010-02-04
     PostGIS 2.0.0 2012-04-03
     PostGIS 2.1.0 2013-08-17
     Spatialite 2.4.0 2010-11-14

+ 4 - 93
docs/ref/contrib/gis/install/postgis.txt

@@ -43,8 +43,7 @@ Finally, make and install::
 .. note::
 
     GeoDjango does not automatically create a spatial database.  Please consult
-    the section on :ref:`spatialdb_template91` or
-    :ref:`spatialdb_template_earlier` for more information.
+    the section on :ref:`spatialdb_template91` for more information.
 
 __ http://postgis.net/
 
@@ -54,8 +53,8 @@ Post-installation
 .. _spatialdb_template:
 .. _spatialdb_template91:
 
-Creating a spatial database with PostGIS 2.0 and PostgreSQL 9.1+
-----------------------------------------------------------------
+Creating a spatial database
+---------------------------
 
 PostGIS 2 includes an extension for Postgres 9.1+ that can be used to enable
 spatial functionality::
@@ -77,94 +76,6 @@ __ http://postgis.net/docs/Topology.html
     the :djadmin:`migrate` process. You can still create it manually if you
     wish.
 
-.. _spatialdb_template_earlier:
-
-Creating a spatial database template for earlier versions
----------------------------------------------------------
-
-If you have an earlier version of PostGIS or PostgreSQL, the CREATE
-EXTENSION isn't available and you need to create the spatial database
-using the following instructions.
-
-Creating a spatial database with PostGIS is different than normal because
-additional SQL must be loaded to enable spatial functionality.  Because of
-the steps in this process, it's better to create a database template that
-can be reused later.
-
-First, you need to be able to execute the commands as a privileged database
-user.  For example, you can use the following to become the ``postgres`` user::
-
-    $ sudo su - postgres
-
-.. note::
-
-   The location *and* name of the PostGIS SQL files (e.g., from
-   ``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS.
-   Version 1.5 uses ``<sharedir>/contrib/postgis-1.5/postgis.sql``.
-
-   To complicate matters, Debian/Ubuntu distributions have their own separate
-   directory naming system that might change with time. In this case, use the
-   :download:`create_template_postgis-debian.sh` script.
-
-   The example below assumes PostGIS 1.5, thus you may need to modify
-   ``POSTGIS_SQL_PATH`` and the name of the SQL file for the specific
-   version of PostGIS you are using.
-
-Once you're a database super user, then you may execute the following commands
-to create a PostGIS spatial database template::
-
-    $ POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-2.0
-    # Creating the template spatial database.
-    $ createdb -E UTF8 template_postgis
-    $ createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
-    # Allows non-superusers the ability to create from this template
-    $ psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
-    # Loading the PostGIS SQL routines
-    $ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql
-    $ psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
-    # Enabling users to alter spatial tables.
-    $ psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
-    $ psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
-    $ psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
-
-These commands may be placed in a shell script for later use; for convenience
-the following scripts are available:
-
-===============  =============================================
-PostGIS version  Bash shell script
-===============  =============================================
-1.5              :download:`create_template_postgis-1.5.sh`
-Debian/Ubuntu    :download:`create_template_postgis-debian.sh`
-===============  =============================================
-
-Afterwards, you may create a spatial database by simply specifying
-``template_postgis`` as the template to use (via the ``-T`` option)::
-
-    $ createdb -T template_postgis <db name>
-
-.. note::
-
-    While the ``createdb`` command does not require database super-user privileges,
-    it must be executed by a database user that has permissions to create databases.
-    You can create such a user with the following command::
-
-        $ createuser --createdb <user>
-
-PostgreSQL's createdb fails
----------------------------
-
-When the PostgreSQL cluster uses a non-UTF8 encoding, the
-:file:`create_template_postgis-*.sh` script will fail when executing
-``createdb``::
-
-    createdb: database creation failed: ERROR:  new encoding (UTF8) is incompatible
-      with the encoding of the template database (SQL_ASCII)
-
-The `current workaround`__ is to re-create the cluster using UTF8 (back up any
-databases before dropping the cluster).
-
-__ http://jacobian.org/writing/pg-encoding-ubuntu/
-
 Managing the database
 ---------------------
 
@@ -175,4 +86,4 @@ For example, to create a ``geodjango`` spatial database and user, the following
 may be executed from the SQL Shell as the ``postgres`` user::
 
     postgres# CREATE USER geodjango PASSWORD 'my_passwd';
-    postgres# CREATE DATABASE geodjango OWNER geodjango TEMPLATE template_postgis ENCODING 'utf8';
+    postgres# CREATE DATABASE geodjango OWNER geodjango;

+ 0 - 19
docs/ref/contrib/gis/testing.txt

@@ -17,16 +17,6 @@ Settings
 
     The settings below have sensible defaults, and shouldn't require manual setting.
 
-.. setting:: POSTGIS_TEMPLATE
-
-``POSTGIS_TEMPLATE``
-^^^^^^^^^^^^^^^^^^^^
-
-This setting may be used to customize the name of the PostGIS template
-database to use. It automatically defaults to ``'template_postgis'``
-(the same name used in the
-:ref:`installation documentation <spatialdb_template>`).
-
 .. setting:: POSTGIS_VERSION
 
 ``POSTGIS_VERSION``
@@ -80,15 +70,6 @@ is done from an existing superuser account)::
 
     postgres# ALTER ROLE <user_name> SUPERUSER;
 
-Create a database using PostGIS version 2
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-When testing projects using :ref:`PostGIS 2 <spatialdb_template91>`,
-the test database is created using the ``CREATE EXTENSION postgis``
-instruction, provided that no template ``template_postgis`` (or named
-accordingly to :setting:`POSTGIS_TEMPLATE`) exists in the current
-database.
-
 Windows
 -------
 

+ 0 - 6
docs/ref/contrib/gis/tutorial.txt

@@ -308,12 +308,6 @@ This command should produce the following output:
     CREATE INDEX "world_worldborder_mpoly_id" ON "world_worldborder" USING GIST ( "mpoly" );
     COMMIT;
 
-.. note::
-
-    With PostGIS < 2.0, the output is slightly different. The ``mpoly`` geometry
-    column is added through a separate ``SELECT AddGeometryColumn(...)``
-    statement.
-
 If this looks correct, run :djadmin:`migrate` to create this table in the
 database:
 

+ 2 - 0
docs/releases/1.9.txt

@@ -418,6 +418,8 @@ Miscellaneous
   backwards incompatible if you have overridden the ``get_context_data()``
   method without calling ``super()``.
 
+* Support for PostGIS 1.5 has been dropped.
+
 .. _deprecated-features-1.9:
 
 Features deprecated in 1.9

+ 2 - 6
tests/gis_tests/geoapp/tests.py

@@ -696,12 +696,8 @@ class GeoQuerySetTest(TestCase):
 
         for c in City.objects.filter(point__isnull=False).num_geom():
             # Oracle and PostGIS 2.0+ will return 1 for the number of
-            # geometries on non-collections, whereas PostGIS < 2.0.0
-            # will return None.
-            if postgis and connection.ops.spatial_version < (2, 0, 0):
-                self.assertIsNone(c.num_geom)
-            else:
-                self.assertEqual(1, c.num_geom)
+            # geometries on non-collections.
+            self.assertEqual(1, c.num_geom)
 
     @skipUnlessDBFeature("supports_num_points_poly")
     def test_num_points(self):