]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add 'native' autocommit support for mysql drivers
authorRoman Podoliaka <rpodolyaka@mirantis.com>
Sat, 31 Jan 2015 11:50:20 +0000 (13:50 +0200)
committerRoman Podoliaka <rpodolyaka@mirantis.com>
Tue, 24 Feb 2015 17:50:54 +0000 (19:50 +0200)
Sometimes it might be useful to have 'native' autocommit support
provided by a DB API driver rather than rely on SQLAlchemy autocommit
emulation.

lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/mysql/mysqlconnector.py
lib/sqlalchemy/dialects/mysql/mysqldb.py
test/dialect/mysql/test_dialect.py

index 0d2c361897cbab2de42e1344681d12024925f93d..c45f8c3ee699a81d0a08fe61801673af8c903eb6 100644 (file)
@@ -2387,6 +2387,14 @@ class MySQLDialect(default.DefaultDialect):
 
     def set_isolation_level(self, connection, level):
         level = level.replace('_', ' ')
+
+        # adjust for ConnectionFairy being present
+        if hasattr(connection, 'connection'):
+            connection = connection.connection
+
+        self._set_isolation_level(connection, level)
+
+    def _set_isolation_level(self, connection, level):
         if level not in self._isolation_lookup:
             raise exc.ArgumentError(
                 "Invalid value '%s' for isolation_level. "
index 417e1ad6f008e91e15b4f9ee864a1e584e4a0fb8..4dc803d2c932c249828e290764fe611eec2964d1 100644 (file)
@@ -167,4 +167,17 @@ class MySQLDialect_mysqlconnector(MySQLDialect):
     def _compat_fetchone(self, rp, charset=None):
         return rp.fetchone()
 
+    _isolation_lookup = set(['SERIALIZABLE', 'READ UNCOMMITTED',
+                             'READ COMMITTED', 'REPEATABLE READ',
+                             'AUTOCOMMIT'])
+
+    def _set_isolation_level(self, connection, level):
+        if level == 'AUTOCOMMIT':
+            connection.autocommit = True
+        else:
+            connection.autocommit = False
+            super(MySQLDialect_mysqlconnector, self)._set_isolation_level(
+                connection, level)
+
+
 dialect = MySQLDialect_mysqlconnector
index 929317467432e669cec403476f9f53650a4fdbc6..67d2f3d1daeaac1a71c5229a54ed6ad98e14ec0c 100644 (file)
@@ -203,5 +203,17 @@ class MySQLDialect_mysqldb(MySQLDialect):
         else:
             return cset_name()
 
+    _isolation_lookup = set(['SERIALIZABLE', 'READ UNCOMMITTED',
+                             'READ COMMITTED', 'REPEATABLE READ',
+                             'AUTOCOMMIT'])
+
+    def _set_isolation_level(self, connection, level):
+        if level == 'AUTOCOMMIT':
+            connection.autocommit(True)
+        else:
+            connection.autocommit(False)
+            super(MySQLDialect_mysqldb, self)._set_isolation_level(connection,
+                                                                   level)
+
 
 dialect = MySQLDialect_mysqldb
index e6bad71a44332477a74530ec6a5a2dd8bfc67e81..03f4c494aff6c9334ec3a955f4904e3a75dfeae6 100644 (file)
@@ -148,3 +148,27 @@ class ExecutionTest(fixtures.TestBase):
     def test_sysdate(self):
         d = testing.db.scalar(func.sysdate())
         assert isinstance(d, datetime.datetime)
+
+    @testing.only_on(['mysql+mysqldb',
+                      'mysql+mysqlconnector',
+                      'mysql+pymysql',
+                      'mysql+cymysql'])
+    def test_autocommit_isolation_level(self):
+        c = testing.db.connect().execution_options(
+            isolation_level='AUTOCOMMIT'
+        )
+        assert c.execute('SELECT @@autocommit;').scalar()
+
+    def test_isolation_level(self):
+        values = {
+            # sqlalchemy -> mysql
+            'READ UNCOMMITTED': 'READ-UNCOMMITTED',
+            'READ COMMITTED': 'READ-COMMITTED',
+            'REPEATABLE READ': 'REPEATABLE-READ',
+            'SERIALIZABLE': 'SERIALIZABLE'
+        }
+        for sa_value, mysql_value in values.items():
+            c = testing.db.connect().execution_options(
+                isolation_level=sa_value
+            )
+            assert c.execute('SELECT @@tx_isolation;').scalar() == mysql_value