diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 0f9423c1c3e..2a7a206c3b8 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -352,6 +352,18 @@ class BaseDatabaseWrapper(object): def make_debug_cursor(self, cursor): return util.CursorDebugWrapper(cursor, self) + @contextmanager + def temporary_connection(self): + # Ensure a connection is established, and avoid leaving a dangling + # connection, for operations outside of the request-response cycle. + must_close = self.connection is None + cursor = self.cursor() + try: + yield + finally: + cursor.close() + if must_close: + self.close() class BaseDatabaseFeatures(object): allows_group_by_pk = False diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index 3719b3a6a79..fc2ff315813 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -453,7 +453,8 @@ class DatabaseWrapper(BaseDatabaseWrapper): @cached_property def mysql_version(self): - server_info = self.connection.get_server_info() + with self.temporary_connection(): + server_info = self.connection.get_server_info() match = server_version_re.match(server_info) if not match: raise Exception('Unable to determine MySQL version from version string %r' % server_info) diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index 3fdf67402a9..a9ae0251467 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -623,8 +623,10 @@ class DatabaseWrapper(BaseDatabaseWrapper): @cached_property def oracle_version(self): + with self.temporary_connection(): + version = self.connection.version try: - return int(self.connection.version.split('.')[0]) + return int(version.split('.')[0]) except ValueError: return None diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py index 831ad84843f..85a0991402c 100644 --- a/django/db/backends/postgresql_psycopg2/base.py +++ b/django/db/backends/postgresql_psycopg2/base.py @@ -152,7 +152,8 @@ class DatabaseWrapper(BaseDatabaseWrapper): @cached_property def pg_version(self): - return get_version(self.connection) + with self.temporary_connection(): + return get_version(self.connection) def get_connection_params(self): settings_dict = self.settings_dict diff --git a/django/db/backends/postgresql_psycopg2/operations.py b/django/db/backends/postgresql_psycopg2/operations.py index 8e87ed539f1..56535e08650 100644 --- a/django/db/backends/postgresql_psycopg2/operations.py +++ b/django/db/backends/postgresql_psycopg2/operations.py @@ -195,8 +195,7 @@ class DatabaseOperations(BaseDatabaseOperations): NotImplementedError if this is the database in use. """ if aggregate.sql_function in ('STDDEV_POP', 'VAR_POP'): - pg_version = self.connection.pg_version - if pg_version >= 80200 and pg_version <= 80204: + if 80200 <= self.connection.pg_version <= 80204: 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) def max_name_length(self):