Browse Source

Fixed #28626 -- Dropped support for PostgreSQL 9.3.

Thanks Simon Charette for the introspection changes.
Tim Graham 7 years ago
parent
commit
1d8cfa3608

+ 1 - 8
django/db/backends/postgresql/features.py

@@ -49,10 +49,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
         END;
     $$ LANGUAGE plpgsql;"""
     supports_over_clause = True
-
-    @cached_property
-    def supports_aggregate_filter_clause(self):
-        return self.connection.pg_version >= 90400
+    supports_aggregate_filter_clause = True
 
     @cached_property
     def has_select_for_update_skip_locked(self):
@@ -62,10 +59,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     def has_brin_index_support(self):
         return self.connection.pg_version >= 90500
 
-    @cached_property
-    def has_jsonb_datatype(self):
-        return self.connection.pg_version >= 90400
-
     @cached_property
     def has_jsonb_agg(self):
         return self.connection.pg_version >= 90500

+ 6 - 16
django/db/backends/postgresql/introspection.py

@@ -145,17 +145,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
         # Loop over the key table, collecting things as constraints. The column
         # array must return column names in the same order in which they were
         # created.
-        # The subquery containing generate_series can be replaced with
-        # "WITH ORDINALITY" when support for PostgreSQL 9.3 is dropped.
         cursor.execute("""
             SELECT
                 c.conname,
                 array(
                     SELECT attname
-                    FROM (
-                        SELECT unnest(c.conkey) AS colid,
-                               generate_series(1, array_length(c.conkey, 1)) AS arridx
-                    ) AS cols
+                    FROM unnest(c.conkey) WITH ORDINALITY cols(colid, arridx)
                     JOIN pg_attribute AS ca ON cols.colid = ca.attnum
                     WHERE ca.attrelid = c.conrelid
                     ORDER BY cols.arridx
@@ -183,17 +178,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                 "options": options,
             }
         # Now get indexes
-        # The row_number() function for ordering the index fields can be
-        # replaced by WITH ORDINALITY in the unnest() functions when support
-        # for PostgreSQL 9.3 is dropped.
         cursor.execute("""
             SELECT
-                indexname, array_agg(attname ORDER BY rnum), indisunique, indisprimary,
-                array_agg(ordering ORDER BY rnum), amname, exprdef, s2.attoptions
+                indexname, array_agg(attname ORDER BY arridx), indisunique, indisprimary,
+                array_agg(ordering ORDER BY arridx), amname, exprdef, s2.attoptions
             FROM (
                 SELECT
-                    row_number() OVER () as rnum, c2.relname as indexname,
-                    idx.*, attr.attname, am.amname,
+                    c2.relname as indexname, idx.*, attr.attname, am.amname,
                     CASE
                         WHEN idx.indexprs IS NOT NULL THEN
                             pg_get_indexdef(idx.indexrelid)
@@ -206,9 +197,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                     END as ordering,
                     c2.reloptions as attoptions
                 FROM (
-                    SELECT
-                        *, unnest(i.indkey) as key, unnest(i.indoption) as option
-                    FROM pg_index i
+                    SELECT *
+                    FROM pg_index i, unnest(i.indkey, i.indoption) WITH ORDINALITY koi(key, option, arridx)
                 ) idx
                 LEFT JOIN pg_class c ON idx.indrelid = c.oid
                 LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid

+ 1 - 1
docs/ref/contrib/gis/install/index.txt

@@ -58,7 +58,7 @@ supported versions, and any notes for each of the supported database backends:
 ==================  ==============================  ==================  =========================================
 Database            Library Requirements            Supported Versions  Notes
 ==================  ==============================  ==================  =========================================
-PostgreSQL          GEOS, GDAL, PROJ.4, PostGIS     9.3+                Requires PostGIS.
+PostgreSQL          GEOS, GDAL, PROJ.4, PostGIS     9.4+                Requires PostGIS.
 MySQL               GEOS, GDAL                      5.6+                Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
 Oracle              GEOS, GDAL                      12.1+               XE not supported.
 SQLite              GEOS, GDAL, PROJ.4, SpatiaLite  3.6.+               Requires SpatiaLite 4.0+

+ 0 - 2
docs/ref/contrib/postgres/fields.txt

@@ -509,8 +509,6 @@ using in conjunction with lookups on
     of the JSON which allows indexing. The trade-off is a small additional cost
     on writing to the ``jsonb`` field. ``JSONField`` uses ``jsonb``.
 
-    **As a result, this field requires PostgreSQL ≥ 9.4**.
-
 Querying ``JSONField``
 ----------------------
 

+ 0 - 2
docs/ref/contrib/postgres/functions.txt

@@ -16,8 +16,6 @@ All of these functions are available from the
 
 Returns a version 4 UUID.
 
-Requires PostgreSQL 9.4 or greater.
-
 The `pgcrypto extension`_ must be installed. You can use the
 :class:`~django.contrib.postgres.operations.CryptoExtension` migration
 operation to install it.

+ 1 - 1
docs/ref/databases.txt

@@ -92,7 +92,7 @@ below for information on how to set up your database correctly.
 PostgreSQL notes
 ================
 
-Django supports PostgreSQL 9.3 and higher. `psycopg2`_ 2.5.4 or higher is
+Django supports PostgreSQL 9.4 and higher. `psycopg2`_ 2.5.4 or higher is
 required, though the latest release is recommended.
 
 .. _psycopg2: http://initd.org/psycopg/

+ 6 - 0
docs/releases/2.1.txt

@@ -206,6 +206,12 @@ Dropped support for MySQL 5.5
 The end of upstream support for MySQL 5.5 is December 2018. Django 2.1 supports
 MySQL 5.6 and higher.
 
+Dropped support for PostgreSQL 9.3
+----------------------------------
+
+The end of upstream support for PostgreSQL 9.3 is September 2018. Django 2.1
+supports PostgreSQL 9.4 and higher.
+
 Miscellaneous
 -------------
 

+ 0 - 10
tests/postgres_tests/__init__.py

@@ -7,16 +7,6 @@ from django.db.backends.signals import connection_created
 from django.test import TestCase, modify_settings
 
 
-def skipUnlessPG94(test):
-    try:
-        PG_VERSION = connection.pg_version
-    except AttributeError:
-        PG_VERSION = 0
-    if PG_VERSION < 90400:
-        return unittest.skip('PostgreSQL ≥ 9.4 required')(test)
-    return test
-
-
 @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific tests")
 class PostgreSQLTestCase(TestCase):
     @classmethod

+ 1 - 1
tests/postgres_tests/migrations/0002_create_test_models.py

@@ -242,7 +242,7 @@ class Migration(migrations.Migration):
                 ('field_custom', JSONField(null=True, blank=True, encoder=DjangoJSONEncoder)),
             ],
             options={
-                'required_db_features': {'has_jsonb_datatype'},
+                'required_db_vendor': 'postgresql',
             },
             bases=(models.Model,),
         ),

+ 1 - 4
tests/postgres_tests/models.py

@@ -140,13 +140,10 @@ class RangeLookupsModel(PostgreSQLModel):
     date = models.DateField(blank=True, null=True)
 
 
-class JSONModel(models.Model):
+class JSONModel(PostgreSQLModel):
     field = JSONField(blank=True, null=True)
     field_custom = JSONField(blank=True, null=True, encoder=DjangoJSONEncoder)
 
-    class Meta:
-        required_db_features = ['has_jsonb_datatype']
-
 
 class ArrayFieldSubclass(ArrayField):
     def __init__(self, *args, **kwargs):

+ 1 - 2
tests/postgres_tests/test_functions.py

@@ -4,7 +4,7 @@ from time import sleep
 
 from django.contrib.postgres.functions import RandomUUID, TransactionNow
 
-from . import PostgreSQLTestCase, skipUnlessPG94
+from . import PostgreSQLTestCase
 from .models import NowTestModel, UUIDTestModel
 
 
@@ -29,7 +29,6 @@ class TestTransactionNow(PostgreSQLTestCase):
         self.assertEqual(m1.when, m2.when)
 
 
-@skipUnlessPG94
 class TestRandomUUID(PostgreSQLTestCase):
 
     def test_random_uuid(self):

+ 0 - 2
tests/postgres_tests/test_introspection.py

@@ -1,7 +1,6 @@
 from io import StringIO
 
 from django.core.management import call_command
-from django.test import skipUnlessDBFeature
 from django.test.utils import modify_settings
 
 from . import PostgreSQLTestCase
@@ -20,7 +19,6 @@ class InspectDBTests(PostgreSQLTestCase):
         for field_output in field_outputs:
             self.assertIn(field_output, output)
 
-    @skipUnlessDBFeature('has_jsonb_datatype')
     def test_json_field(self):
         self.assertFieldsInModel(
             'postgres_tests_jsonmodel',

+ 0 - 4
tests/postgres_tests/test_json.py

@@ -5,7 +5,6 @@ from decimal import Decimal
 from django.core import exceptions, serializers
 from django.core.serializers.json import DjangoJSONEncoder
 from django.forms import CharField, Form, widgets
-from django.test import skipUnlessDBFeature
 from django.utils.html import escape
 
 from . import PostgreSQLTestCase
@@ -18,7 +17,6 @@ except ImportError:
     pass
 
 
-@skipUnlessDBFeature('has_jsonb_datatype')
 class TestSaveLoad(PostgreSQLTestCase):
     def test_null(self):
         instance = JSONModel()
@@ -92,7 +90,6 @@ class TestSaveLoad(PostgreSQLTestCase):
         self.assertEqual(loaded.field_custom, obj_after)
 
 
-@skipUnlessDBFeature('has_jsonb_datatype')
 class TestQuerying(PostgreSQLTestCase):
     @classmethod
     def setUpTestData(cls):
@@ -262,7 +259,6 @@ class TestQuerying(PostgreSQLTestCase):
         self.assertTrue(JSONModel.objects.filter(field__foo__iregex=r'^bAr$').exists())
 
 
-@skipUnlessDBFeature('has_jsonb_datatype')
 class TestSerialization(PostgreSQLTestCase):
     test_data = (
         '[{"fields": {"field": {"a": "b", "c": null}, "field_custom": null}, '