Commit b97178f7 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #10842 -- Corrected parsing of version numbers for PostgreSQL 8.4beta...

Fixed #10842 -- Corrected parsing of version numbers for PostgreSQL 8.4beta series. Thanks to hgdeoro for the report and fix.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10730 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 5663258d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
            cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
            if not hasattr(self, '_version'):
                self.__class__._version = get_version(cursor)
            if self._version < (8, 0):
            if self._version[0:2] < [8, 0]:
                # No savepoint support for earlier version of PostgreSQL.
                self.features.uses_savepoints = False
        cursor.execute("SET client_encoding to 'UNICODE'")
+6 −11
Original line number Diff line number Diff line
@@ -2,8 +2,6 @@ import re

from django.db.backends import BaseDatabaseOperations

server_version_re = re.compile(r'PostgreSQL (\d{1,2})\.(\d{1,2})\.?(\d{1,2})?')

# This DatabaseOperations class lives in here instead of base.py because it's
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.

@@ -14,13 +12,9 @@ class DatabaseOperations(BaseDatabaseOperations):
    def _get_postgres_version(self):
        if self._postgres_version is None:
            from django.db import connection
            from django.db.backends.postgresql.version import get_version
            cursor = connection.cursor()
            cursor.execute("SELECT version()")
            version_string = cursor.fetchone()[0]
            m = server_version_re.match(version_string)
            if not m:
                raise Exception('Unable to determine PostgreSQL version from version() function string: %r' % version_string)
            self._postgres_version = [int(val) for val in m.groups() if val]
            self._postgres_version = get_version(cursor)
        return self._postgres_version
    postgres_version = property(_get_postgres_version)

@@ -72,7 +66,7 @@ class DatabaseOperations(BaseDatabaseOperations):

    def sql_flush(self, style, tables, sequences):
        if tables:
            if self.postgres_version[0] >= 8 and self.postgres_version[1] >= 1:
            if self.postgres_version[0:2] >= [8,1]:
                # Postgres 8.1+ can do 'TRUNCATE x, y, z...;'. In fact, it *has to*
                # in order to be able to truncate tables referenced by a foreign
                # key in any other table. The result is a single SQL TRUNCATE
@@ -157,5 +151,6 @@ class DatabaseOperations(BaseDatabaseOperations):
        NotImplementedError if this is the database in use.
        """
        if aggregate.sql_function == 'STDDEV_POP' or aggregate.sql_function == 'VAR_POP':
            if self.postgres_version[0] == 8 and self.postgres_version[1] == 2 and self.postgres_version[2] <= 4:
            if self.postgres_version[0:2] == [8,2]:
                if self.postgres_version[2] is None or self.postgres_version[2] <= 4:
                    raise NotImplementedError('PostgreSQL 8.2 to 8.2.4 is known to have a faulty implementation of %s. Please upgrade your version of PostgreSQL.' % aggregate.sql_function)
+17 −9
Original line number Diff line number Diff line
@@ -4,20 +4,28 @@ Extracts the version of the PostgreSQL server.

import re

# This reg-exp is intentionally fairly flexible here. Require only the major
# and minor version numbers, but need to be able to handle standard stuff like:
# This reg-exp is intentionally fairly flexible here.
# Needs to be able to handle stuff like:
#   PostgreSQL 8.3.6
#   EnterpriseDB 8.3
#   PostgreSQL 8.3 beta4
VERSION_RE = re.compile(r'\S+ (\d+)\.(\d+)')
#   PostgreSQL 8.4beta1
VERSION_RE = re.compile(r'\S+ (\d+)\.(\d+)\.?(\d+)?')

def _parse_version(text):
    "Internal parsing method. Factored out for testing purposes."
    major, major2, minor = VERSION_RE.search(text).groups()
    try:
        return int(major), int(major2), int(minor)
    except (ValueError, TypeError):
        return int(major), int(major2), None

def get_version(cursor):
    """
    Returns a tuple representing the major and minor version number of the
    server. For example, (7, 4) or (8, 3).
    Returns a tuple representing the major, minor and revision number of the
    server. For example, (7, 4, 1) or (8, 3, 4). The revision number will be
    None in the case of initial releases (e.g., 'PostgreSQL 8.3') or in the
    case of beta and prereleases ('PostgreSQL 8.4beta1').
    """
    cursor.execute("SELECT version()")
    version = cursor.fetchone()[0]
    major, minor = VERSION_RE.search(version).groups()
    return int(major), int(minor)
    return _parse_version(cursor.fetchone()[0])
+2 −2
Original line number Diff line number Diff line
@@ -105,11 +105,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
            cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
            if not hasattr(self, '_version'):
                self.__class__._version = get_version(cursor)
            if self._version < (8, 0):
            if self._version[0:2] < [8, 0]:
                # No savepoint support for earlier version of PostgreSQL.
                self.features.uses_savepoints = False
            if self.features.uses_autocommit:
                if self._version < (8, 2):
                if self._version[0:2] < [8, 2]:
                    # FIXME: Needs extra code to do reliable model insert
                    # handling, so we forbid it for now.
                    from django.core.exceptions import ImproperlyConfigured
+23 −1
Original line number Diff line number Diff line
@@ -21,7 +21,29 @@ class Callproc(unittest.TestCase):
def connection_created_test(sender, **kwargs):
    print 'connection_created signal'

__test__ = {'API_TESTS': ''}
__test__ = {'API_TESTS': """
# Check Postgres version parsing
>>> from django.db.backends.postgresql import version as pg_version

>>> pg_version._parse_version("PostgreSQL 8.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)")
(8, 3, 1)

>>> pg_version._parse_version("PostgreSQL 8.3.6")
(8, 3, 6)

>>> pg_version._parse_version("PostgreSQL 8.3")
(8, 3, None)

>>> pg_version._parse_version("EnterpriseDB 8.3")
(8, 3, None)

>>> pg_version._parse_version("PostgreSQL 8.3 beta4")
(8, 3, None)

>>> pg_version._parse_version("PostgreSQL 8.4beta1")
(8, 4, None)

"""}

# Unfortunately with sqlite3 the in-memory test database cannot be
# closed, and so it cannot be re-opened during testing, and so we