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 -~----------~----~----~----~------~----~------~--~---