Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit b97178f7ec311da7c885a122a2ccc1036bacf0d3 1 parent 5663258
@freakboy3742 freakboy3742 authored
View
2  django/db/backends/postgresql/base.py
@@ -121,7 +121,7 @@ def _cursor(self):
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'")
View
17 django/db/backends/postgresql/operations.py
@@ -2,8 +2,6 @@
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 @@ def __init__(self):
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 @@ def quote_name(self, name):
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 @@ def check_aggregate_support(self, aggregate):
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:
- 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)
+ 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)
View
26 django/db/backends/postgresql/version.py
@@ -4,20 +4,28 @@
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])
View
4 django/db/backends/postgresql_psycopg2/base.py
@@ -105,11 +105,11 @@ def _cursor(self):
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
View
24 tests/regressiontests/backends/tests.py
@@ -21,7 +21,29 @@ def test_dbms_session(self):
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
Please sign in to comment.
Something went wrong with that request. Please try again.