See below.

On Jul 8, 10:49 am, Karen Tracey <kmtra...@gmail.com> wrote:
> On Tue, Jul 7, 2009 at 9:05 PM, Steve Howell <showel...@yahoo.com> wrote:
>
> > On Jul 7, 3:07 pm, Karen Tracey <kmtra...@gmail.com> wrote:
>
> > > > On Jun 29, 10:53 am, Steve Howell <showel...@yahoo.com> wrote:
> > > > > Hi, I have created a management command that populates some tables in
> > > > > a Postgres database, and I use the handy get_or_create() method in
> > db/
> > > > > models/query.py.  I tried running a command recently where I had
> > > > > inadvertently left some foreign key references dangling around,
>
> > > Could you be a little more specific about what the error was in your
> > code?
>
> > Sorry I never reported the error, but, of course, part of my problem
> > was that the error was caught by the try/except in Django code.
>
> > I did the following sequence, conceptually:
>
> >  1) I had a database with books and authors.
> >  2) I received a new feed of books.
> >  3) I cleaned the books table without cleaning the authors table.
> >  4) When I tried to import the first book, there was still a stale
> > author.
> >  5) Instead of getting the normal integrity error, I got the red
> > herring savepoint error.
> >  6) When I went back and cleaned BOTH tables, everything worked fine.
>
> > > From looking at the full get_or_create routine you include below it isn't
> > > immediately obvious to me where it might be raising an IntegrityError
> > before
> > > the savepoint is created, yet it sounds like that is what is happening.
> >  We
> > > need to understand how that is happening before figuring out what the
> > right
> > > fix is.
>
> > If memory serves correctly, it was this line that raised the original
> > error:
>
> >                obj.save(force_insert=True)
>
> > Here's the code in more context:
>
> >            try:
> >                params = dict([(k, v) for k, v in kwargs.items() if
> > '__' not in k])
> >                params.update(defaults)
> >                obj = self.model(**params)
> >                sid = transaction.savepoint()
> >                obj.save(force_insert=True)
> >                transaction.savepoint_commit(sid)
> >                return obj, True
> >            except IntegrityError, e:
> >                transaction.savepoint_rollback(sid)
> >                try:
> >                    return self.get(**kwargs), False
> >                except self.model.DoesNotExist:
> >                    raise e
>
> But if it's the obj.save(force_insert=True) that is causing the
> IntegrityError, then the savepoint should have been created by the
> immediately preceding line: 'sid = transaction.savepoint()'.  

There's no code there that prevents sid from being None, FWIW.

> Thus
> attempting to rollback that savepoint should not fail.  I was thinking you
> were hitting the IntegrityError earlier, before the savepoint had been
> created (though I couldn't see where that could possibly be happening), but
> if that were the case I think you'd be getting a Python error about sid
> being referenced before being set.  So, the savepoint has been created but
> the DB doesn't seem to know about it, which is a bit of a mystery.
>

Yep, I think it's definitely a strange DB anomaly, and I've seen long
threads about how there have been some disconnects between Postgres
transaction model and how Django works, but they've been a bit above
my head.

I'm pretty confident the savepoint gets created, but just can't roll
back correctly for whatever reason.


> If you look at that code you see it tries to not swallow any IntegrityErrors
> that aren't in fact due to collisions on insert.  

I agree with you there.  I think it's perfectly valid for the code to
reach the except clause and try to do the savepoint_rollback, but it
does not seem to be working.

FWIW I am launching these commands as a management command, so it's
possible that I need to do something in the management command to put
Django into a "normal" transaction mode, although I agree it's strange
that the code wouldn't fail earlier when it's trying to create the
savepoint.

> If the save fails, it
> tries the get again, and if that again returns DoesNotExist then the
> original IntegrityError e is raised.  You have hit an unexpected case where
> the savepoint rollback is failing.  As the code is written I don't see how
> that could be failing, and I don't have time to try to recreate myself right
> now.
>
> What version of PostgreSQL are you running?
>

8.3
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to