From: Roman Podoliaka Date: Sat, 31 Jan 2015 11:50:20 +0000 (+0200) Subject: Add 'native' autocommit support for mysql drivers X-Git-Tag: rel_1_1_0b1~99 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a87b3c2101114d82f999c23d113ad2018629ed48;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add 'native' autocommit support for mysql drivers Sometimes it might be useful to have 'native' autocommit support provided by a DB API driver rather than rely on SQLAlchemy autocommit emulation. --- diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 0d2c361897..c45f8c3ee6 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -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. " diff --git a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py index 417e1ad6f0..4dc803d2c9 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py +++ b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py @@ -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 diff --git a/lib/sqlalchemy/dialects/mysql/mysqldb.py b/lib/sqlalchemy/dialects/mysql/mysqldb.py index 9293174674..67d2f3d1da 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -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 diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py index e6bad71a44..03f4c494af 100644 --- a/test/dialect/mysql/test_dialect.py +++ b/test/dialect/mysql/test_dialect.py @@ -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