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
This commit is contained in:
parent
5663258de1
commit
b97178f7ec
|
@ -121,7 +121,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
|
cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
|
||||||
if not hasattr(self, '_version'):
|
if not hasattr(self, '_version'):
|
||||||
self.__class__._version = get_version(cursor)
|
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.
|
# No savepoint support for earlier version of PostgreSQL.
|
||||||
self.features.uses_savepoints = False
|
self.features.uses_savepoints = False
|
||||||
cursor.execute("SET client_encoding to 'UNICODE'")
|
cursor.execute("SET client_encoding to 'UNICODE'")
|
||||||
|
|
|
@ -2,8 +2,6 @@ import re
|
||||||
|
|
||||||
from django.db.backends import BaseDatabaseOperations
|
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
|
# This DatabaseOperations class lives in here instead of base.py because it's
|
||||||
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.
|
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.
|
||||||
|
|
||||||
|
@ -14,13 +12,9 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
def _get_postgres_version(self):
|
def _get_postgres_version(self):
|
||||||
if self._postgres_version is None:
|
if self._postgres_version is None:
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
from django.db.backends.postgresql.version import get_version
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT version()")
|
self._postgres_version = get_version(cursor)
|
||||||
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]
|
|
||||||
return self._postgres_version
|
return self._postgres_version
|
||||||
postgres_version = property(_get_postgres_version)
|
postgres_version = property(_get_postgres_version)
|
||||||
|
|
||||||
|
@ -72,7 +66,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
|
|
||||||
def sql_flush(self, style, tables, sequences):
|
def sql_flush(self, style, tables, sequences):
|
||||||
if tables:
|
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*
|
# 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
|
# in order to be able to truncate tables referenced by a foreign
|
||||||
# key in any other table. The result is a single SQL TRUNCATE
|
# 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.
|
NotImplementedError if this is the database in use.
|
||||||
"""
|
"""
|
||||||
if aggregate.sql_function == 'STDDEV_POP' or aggregate.sql_function == 'VAR_POP':
|
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)
|
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)
|
||||||
|
|
|
@ -4,20 +4,28 @@ Extracts the version of the PostgreSQL server.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# This reg-exp is intentionally fairly flexible here. Require only the major
|
# This reg-exp is intentionally fairly flexible here.
|
||||||
# and minor version numbers, but need to be able to handle standard stuff like:
|
# Needs to be able to handle stuff like:
|
||||||
# PostgreSQL 8.3.6
|
# PostgreSQL 8.3.6
|
||||||
# EnterpriseDB 8.3
|
# EnterpriseDB 8.3
|
||||||
# PostgreSQL 8.3 beta4
|
# 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):
|
def get_version(cursor):
|
||||||
"""
|
"""
|
||||||
Returns a tuple representing the major and minor version number of the
|
Returns a tuple representing the major, minor and revision number of the
|
||||||
server. For example, (7, 4) or (8, 3).
|
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()")
|
cursor.execute("SELECT version()")
|
||||||
version = cursor.fetchone()[0]
|
return _parse_version(cursor.fetchone()[0])
|
||||||
major, minor = VERSION_RE.search(version).groups()
|
|
||||||
return int(major), int(minor)
|
|
||||||
|
|
||||||
|
|
|
@ -105,11 +105,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
|
cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
|
||||||
if not hasattr(self, '_version'):
|
if not hasattr(self, '_version'):
|
||||||
self.__class__._version = get_version(cursor)
|
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.
|
# No savepoint support for earlier version of PostgreSQL.
|
||||||
self.features.uses_savepoints = False
|
self.features.uses_savepoints = False
|
||||||
if self.features.uses_autocommit:
|
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
|
# FIXME: Needs extra code to do reliable model insert
|
||||||
# handling, so we forbid it for now.
|
# handling, so we forbid it for now.
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
|
@ -21,7 +21,29 @@ class Callproc(unittest.TestCase):
|
||||||
def connection_created_test(sender, **kwargs):
|
def connection_created_test(sender, **kwargs):
|
||||||
print 'connection_created signal'
|
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
|
# Unfortunately with sqlite3 the in-memory test database cannot be
|
||||||
# closed, and so it cannot be re-opened during testing, and so we
|
# closed, and so it cannot be re-opened during testing, and so we
|
||||||
|
|
Loading…
Reference in New Issue