Ticket #17062: 17062.diff

File 17062.diff, 4.6 KB (added by akaariai, 4 years ago)
  • django/db/backends/postgresql_psycopg2/base.py

    diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
    index dbd49c5..e794715 100644
    a b class DatabaseWrapper(BaseDatabaseWrapper): 
    176176                conn_params['port'] = settings_dict['PORT']
    177177            self.connection = Database.connect(**conn_params)
    178178            self.connection.set_client_encoding('UTF8')
    179             self.connection.set_isolation_level(self.isolation_level)
     179            wanted_tz = 'UTC' if settings.USE_TZ else settings_dict.get('TIME_ZONE')
     180            db_default_tz = self.connection.get_parameter_status('TimeZone')
     181            if wanted_tz and db_default_tz <> wanted_tz:
     182                # We must set this in autocommit mode. Otherwise a rollback
     183                # will roll back also the SET TIME ZONE.
     184                self.connection.set_isolation_level(
     185                    psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
     186                self.connection.cursor().execute(
     187                    "SET TIME ZONE %s", (wanted_tz,))
     188
     189            self.connection.set_isolation_level(
     190                 psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
     191            self._get_pg_version()
    180192            connection_created.send(sender=self.__class__, connection=self)
    181193        cursor = self.connection.cursor()
    182194        cursor.tzinfo_factory = utc_tzinfo_factory if settings.USE_TZ else None
    183         if new_connection:
    184             tz = 'UTC' if settings.USE_TZ else settings_dict.get('TIME_ZONE')
    185             if tz:
    186                 cursor.execute("SET TIME ZONE %s", [tz])
    187             self._get_pg_version()
    188195        return CursorWrapper(cursor)
    189196
    190197    def _enter_transaction_management(self, managed):
  • tests/regressiontests/backends/tests.py

    diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
    index f2bd71d..0d54176 100644
    a b from django.db import (backend, connection, connections, DEFAULT_DB_ALIAS, 
    1010    IntegrityError, transaction)
    1111from django.db.backends.signals import connection_created
    1212from django.db.backends.postgresql_psycopg2 import version as pg_version
     13from django.db.utils import ConnectionHandler, DatabaseError
    1314from django.test import TestCase, skipUnlessDBFeature, TransactionTestCase
    1415from django.utils import unittest
    1516
    class PostgresVersionTest(TestCase): 
    229230        conn = OlderConnectionMock()
    230231        self.assertEqual(pg_version.get_version(conn), 80300)
    231232
     233class PostgresNewConnectionTest(TestCase):
     234    """
     235    PostgreSQL will roll back SET TIME ZONE if the transaction containing
     236    the SET TIME ZONE command is rolled back. Test that this does not happen.
     237    """
     238    @unittest.skipUnless(connection.vendor == 'postgresql',
     239                         "Test valid only for PostgreSQL")
     240    @unittest.skipUnless(connection.isolation_level > 0,
     241                         "Test valid only if not using autocommit")
     242    def test_connect_and_rollback(self):
     243        new_connections = ConnectionHandler(settings.DATABASES)
     244        new_connection = new_connections[DEFAULT_DB_ALIAS]
     245        try:
     246            # Ensure the database default time zone is different than
     247            # the time zone in new_connection.settings_dict. We can
     248            # get the default time zone by reset & show.
     249            cursor = new_connection.cursor()
     250            cursor.execute("reset timezone")
     251            cursor.execute("show timezone")
     252            db_default_tz = cursor.fetchone()[0]
     253            new_connection.close()
     254            new_tz = db_default_tz == 'UTC' and 'GMT+1' or 'UTC'
     255
     256            # Fetch a new connection with the new_tz as default
     257            # time zone, run a query and rollback.
     258            new_connection.settings_dict['TIME_ZONE'] = new_tz
     259            new_connection.enter_transaction_management()
     260            cursor = new_connection.cursor()
     261            cursor.execute("select 1")
     262            new_connection.rollback()
     263
     264            # Now lets see if the rollback rolled back the SET TIME ZONE.
     265            encoding = cursor.fetchone()[0]
     266            cursor.execute("show timezone")
     267            tz = cursor.fetchone()[0]
     268            self.assertEqual(new_tz, tz)
     269        finally:
     270            try:
     271                new_connection.close()
     272            except DatabaseError:
     273                pass
     274
     275
    232276# Unfortunately with sqlite3 the in-memory test database cannot be
    233277# closed, and so it cannot be re-opened during testing, and so we
    234278# sadly disable this test for now.
Back to Top