Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 7AD296326D8 for ; Mon, 27 Jul 2009 09:40:45 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 78307-01 for ; Mon, 27 Jul 2009 12:40:34 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from starfish.geekisp.com (mail.geekisp.com [216.168.135.169]) by mail.postgresql.org (Postfix) with ESMTP id D0C19632621 for ; Mon, 27 Jul 2009 09:40:34 -0300 (ADT) Received: (qmail 10149 invoked by uid 1003); 27 Jul 2009 12:40:32 -0000 Received: from localhost (HELO ?10.20.15.111?) (science@misuse.org@127.0.0.1) by mail.geekisp.com with SMTP; 27 Jul 2009 12:40:32 -0000 Message-ID: <4A6DA03C.1040404@misuse.org> Date: Mon, 27 Jul 2009 08:40:28 -0400 From: Science User-Agent: Thunderbird 2.0.0.22 (Windows/20090605) MIME-Version: 1.0 To: Craig Ringer CC: pgsql-sql@postgresql.org Subject: Re: Bit by "commands ignored until end of transaction block" again References: <4A6CE37B.9020709@misuse.org> <1248652828.2303.5.camel@ayaki> In-Reply-To: <1248652828.2303.5.camel@ayaki> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0 tagged_above=-10 required=5 tests=none X-Spam-Level: X-Archive-Number: 200907/132 X-Sequence-Number: 32873 Craig Ringer wrote: > On Sun, 2009-07-26 at 19:15 -0400, Science wrote: > >> FWIW, the way the Rails ORM ActiveRecord (another fairly damaged ORM) >> handles this is by allowing you to open any number of transaction >> blocks, but only the outer transaction block commits (in Pg): >> >> Property.transaction { # SQL => 'BEGIN' >> User.transaction { >> Foo.transaction { >> Foo.connection.execute('--some sql code') # SQL => '--some sql code' >> } >> } >> } # SQL => 'COMMIT' > > What happens if, Foo.transaction does something that causes an error, > though, or issues a rollback? It's not creating savepoints, so if > Foo.transaction rolls back it throws out the work of User.transaction > and Property.transaction too. > > Ugh. > > That design would be quite good _IF_ it used savepoints: > > > Property.transaction { # SQL => 'BEGIN' > User.transaction { # SQL => SAVEPOINT User > Foo.transaction { # SQL => SAVEPOINT Foo > Foo.connection.execute('--some sql code') # SQL => '--some sql code' > } # SQL => RELEASE SAVEPOINT Foo > } # SQL => RELEASE SAVEPOINT User > } # SQL => 'COMMIT' > > ... so that inner transactions could ROLLBACK TO SAVEPOINT on error , > and so that asking for a rollback would give you a ROLLBACK TO SAVEPOINT > if the transaction is a subtransaction. > For all I know that's how it works these days. I haven't looked at the code underneath this in a couple of years. It should be trivial to implement in the way you describe based on how the Ruby codebase is set up -- hopefully all this will help OP with the Django/Python version of the same problem. Steve