This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author r.david.murray
Recipients ghaering, r.david.murray
Date 2013-01-14.00:46:39
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1358124405.04.0.0310758361359.issue16958@psf.upfronthosting.co.za>
In-reply-to
Content
Its operation is also not particularly intuitive if isolation_level is not None, so its documentation needs some clarification.

Currently the transaction manager does nothing on enter, and does a commit or rollback on exit, depending on whether or not there was an exception inside the with block.  With isolation_level set to None, the sqlite3 library is in autocommit mode, so changes will get committed immediately inside the with, which is simply broken.

If isolation_level is not None, then the behavior of the transaction manager depends heavily on what happens inside the with block.  If the with block contains only the defined DQL statements (insert, update, delete, replace) and select statements, then things will work as expected.  However, if another statement (such as a CREATE TABLE or a PRAGMA) is included in the with block, an intermediate commit will be done and a new transaction started.

I propose to do two things to fix this issue: explain the above in the transactions manager docs, and have the context manager check to see if we are in isolation_level None, and if so, issue a begin (and then document that as well).

One question is, can the fix be backported?  It will change the behavior of code that doesn't throw an error, but most such code won't be doing what the author expected (run the with block inside a transaction...in pure autocommit mode the transaction manager is a no-op).  One place code could break is if someone figured out this issue and worked around it by explicitly starting a transaction before (or after) entering the with block.  In this case they would now get an error that a transaction cannot be started inside another.  I would think this is unlikely...the more obvious workaround would be to write a custom transaction manager, so I suspect that that is what is actually in the field.  But that's a (hopeful :) guess.

A fix for this problem would be to use 'savepoint' instead of 'begin' if the sqlite3 version supports it (it is apparently supported as of 3.6.8).

So, I'd like to see the fix, conditionally using SAVEPOINT, (once it written and tested) applied to all active python versions, but am open to the argument that it shouldn't be.
History
Date User Action Args
2013-01-14 00:46:45r.david.murraysetrecipients: + r.david.murray, ghaering
2013-01-14 00:46:45r.david.murraysetmessageid: <1358124405.04.0.0310758361359.issue16958@psf.upfronthosting.co.za>
2013-01-14 00:46:44r.david.murraylinkissue16958 messages
2013-01-14 00:46:39r.david.murraycreate