autocommit property broken with MySQL
Matthew Bogosian <[email protected]> Tue, 9 Aug 2005 22:28:27 -0700
| Newsgroups | gmane.comp.web.skunkweb |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I can't log this as a bug on BerliOS (since I can't seem to create an
account), so I thought I'd bring this up here instead.
I have been using PyDO-2.0b1 with MySQL and have been playing around
with InnoDB tables and ACID transactions (i.e., with commit, rollback,
etc.). I am using PyDO with MySQLdb 1.0.1.
I am trying to use the autocommit property, but I've noticed that it
doesn't work with this setup:
> >>> import MySQLdb.constants.CLIENT
> >>> import pydo
> >>> pydo.dbi.initAlias('my_test', 'mysql', { 'db': 'my_test', 'user':
> 'my_test', 'passwd': 'my_test', 'client_flag':
> MySQLdb.constants.CLIENT.FOUND_ROWS })
> >>> db = pydo.dbi.getConnection('my_test')
> >>> db.autocommit
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File
> "/Users/matt/Documents/dev/solus/dev/trunk/src/lib/py/pydo/dbi.py",
> line 40, in fget
> return self.conn.autocommit
> AttributeError: 'Connection' object has no attribute 'autocommit'
Setting the property before attempting to get its value avoids the
above exception, but has no affect on the underlying connection.
I'm proposing that the pydo.drivers.mysqlconn.MysqlDBI class be amended
to include the following (overriding) definition (I've tried to stay
true to form of the original code):
> class MysqlDBI(DBIBase):
>
> ...
>
> def autocommit():
> def fget(self):
> ac_row = self.execute('SELECT @@SESSION.AUTOCOMMIT')
> ac_val = ac_row[0]['AUTOCOMMIT']
> return bool(ac_val)
> def fset(self, val):
> ac_val = int(val == True)
> self.execute('SET AUTOCOMMIT = %s', (ac_val,))
> fdel = DBIBase.autocommit.fdel
> doc = DBIBase.autocommit.__doc__
> return fget, fset, fdel, doc
> autocommit=property(*autocommit())
>
> ...
This, while (I believe) correct, is not scalable, since the autocommit
property is accessed very frequently (potentially with every call to
execute()). After thinking about it some more, the following might be a
better solution:
> class MysqlDBI(DBIBase):
>
> ...
>
> def __init__(self, ...):
> ...
> ac_row = self.execute('SELECT @@SESSION.AUTOCOMMIT')
> ac_val = bool(ac_row[0]['AUTOCOMMIT'])
> DBIBase.autocommit.fset(self, ac_val)
>
> ...
>
> def autocommit():
> fget = DBIBase.autocommit.fget
> def fset(self, val):
> ac_val = bool(val)
> self.execute('SET AUTOCOMMIT = %s', (int(ac_val),))
> DBIBase.autocommit.fset(self, ac_val)
> fdel = DBIBase.autocommit.fdel
> doc = DBIBase.autocommit.__doc__
> return fget, fset, fdel, doc
> autocommit=property(*autocommit())
>
> ...
This approach may break if the underlying implementation of the
autocommit property of the base class changes, but at least this will
stay (mostly) true to form and effectively cache the value of the
AUTOCOMMIT session variable for MySQL connections without unnecessary
queries.
I believe this will also solve the MySQL breakage problem seen above.
Just my $0.02 from looking at it for a brief moment.
-- Matt
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Darwin)
iD8DBQFC+ZB8nLpDzL5I7l8RAi5NAKCKQabp+eY7DmNlBQdcaN1D0CiyVACdHO6C
iaAaLX+lxCykhs8vmFTF/IA=
=2Oij
-----END PGP SIGNATURE-----
-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf