sqlite savepoint problem [solved]
Ryan Kelly
ryan at rfk.id.au
Mon Mar 15 03:53:49 EDT 2010
On Fri, 2010-03-12 at 09:35 +0100, Laszlo Nagy wrote:
> > No it doesn't. The problem is that using a connection as a context
> > manager doesn't do what you think.
> >
> > It does *not* start a new transaction on __enter__ and commit it on
> > __exit__. As far as I can tell it does nothing on __enter__ and calls
> > con.commit() or con.rollback() on exit. With isolation_level=None,
> > these are no-ops.
> >
> Thank you Ryan! You are abolutely right, and thank you for reading the
> source. Now everything works as I imagined.
No problemo - isolation_level has given me my fair share of headaches in
the past, so I couldn't resist the opportunity to understand it a little
better.
> The way the context manager and isolation_level works looks very very
> strange to me. Here is a demonstration:
>
> import sqlite3
> def getconn():
> conn = sqlite3.connect(':memory:')
> conn.isolation_level = None
> return conn
> def main():
> with getconn() as conn:
> conn.execute("create table a ( i integer ) ")
> try:
> conn.execute("insert into a values (1)")
> with conn:
> conn.execute("insert into a values (2)")
> raise Exception
> except:
> print "There was an error"
> for row in conn.execute("select * from a"):
> print row
> main()
>
>
> Output:
>
> There was an error
> (1,)
> (2,)
>
>
> Looks like the context manager did not roll back anything.
Yes, because there were no transactions created so there was nothing to
roll back.
> If I remove
> isolation_level=None then I get this:
>
> There was an error
>
> E.g. the context manager rolled back something that was executed outside
> the context.
Yes, because the transactions created by the default isolation level do
not nest, so the rollback happens at outermost scope.
> I cannot argue with the implementation - it is that way.
> But this is not what I would expect. I believe I'm not alone with this.
That's at least two of us :-)
> Just for clarity, we should put a comment at the end of the
> documentation here:
>
> http://docs.python.org/library/sqlite3.html#sqlite3-controlling-transactions
>
> I would add at least these things:
>
> #1. By using isolation_level = None, connection objects (used as a
> context manager) WON'T automatically commit or rollback transactions.
> #2. Using any isolation level, connection objects WON'T automatically
> begin a transaction.
> #3. Possibly, include your connection manager class code, to show how to
> do it "the expected" way.
>
> Also one should clarify in the documentation, what isolation_level does.
> Looks like setting isolation_level to None is not really an "auto commit
> mode". It is not even part of sqlite itself. It is part of the python
> extension.
I think of it as almost the opposite - you have to set
isolation_level=None to get the unadulterated behaviour of the
underlying sqlite library.
I'm sure the devs would appreciate a documentation patch (submission
details at http://python.org/dev/patches/). I'm also pretty confident
that I won't have time to do one up anytime soon :-)
Good luck with your project!
Ryan
--
Ryan Kelly
http://www.rfk.id.au | This message is digitally signed. Please visit
ryan at rfk.id.au | http://www.rfk.id.au/ramblings/gpg/ for details
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://mail.python.org/pipermail/python-list/attachments/20100315/48b57baf/attachment.sig>
More information about the Python-list
mailing list