On Tue, Jul 7, 2009 at 9:05 PM, Steve Howell <[email protected]> wrote:

>
> On Jul 7, 3:07 pm, Karen Tracey <[email protected]> wrote:
> >
> >
> > > On Jun 29, 10:53 am, Steve Howell <[email protected]> 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()'.  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.

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.  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?

Karen

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

Reply via email to