Code

Opened 4 years ago

Closed 4 years ago

Last modified 3 years ago

#12171 closed (fixed)

transaction.savepoint_rollback fails with postgresql DATABASE_ENGINE

Reported by: andrewbadr Owned by: nobody
Component: Database layer (models, ORM) Version: 1.1
Severity: Keywords:
Cc: andrewbadr.etc@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Calls to transaction.rollback_savepoint fail because they try to create a new cursor, which executes "SET client_encoding to 'UNICODE'" inside the already failed transaction. This is in 1.1 and trunk (r11724).

To repro: create a project w/the "postgresql" database backend, and do python runtests.py get_or_create.

Example traceback:

 File "/var/www/yourworld/ywot/views.py", line 136, in send_edits
   tile, _ = Tile.objects.get_or_create(world=world, tileY=tileY, tileX=tileX)

 File "/usr/local/lib/python2.6/dist-packages/django/db/models/manager.py", line 123, in get_or_create
   return self.get_query_set().get_or_create(**kwargs)

 File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 339, in get_or_create
   transaction.savepoint_rollback(sid)

 File "/usr/local/lib/python2.6/dist-packages/django/db/transaction.py", line 199, in savepoint_rollback
   connection._savepoint_rollback(sid)

 File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 67, in _savepoint_rollback
   self.cursor().execute(self.ops.savepoint_rollback_sql(sid))

 File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 81, in cursor
   cursor = self._cursor()

 File "/usr/local/lib/python2.6/dist-packages/django/db/backends/postgresql/base.py", line 127, in _cursor
   cursor.execute("SET client_encoding to 'UNICODE'")

ProgrammingError: ERROR:  current transaction is aborted, commands ignored until end of transaction block

SET client_encoding to 'UNICODE'

Attachments (0)

Change History (15)

comment:1 Changed 4 years ago by andrewbadr

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Eh, botched the title. :)

comment:2 Changed 4 years ago by andrewbadr

  • Summary changed from transaction.rollback_savepoint fails with postgresql database backend to transaction.savepoint_rollback fails with postgresql database backend

I mean it *has* tests. Am I missing something?

comment:3 Changed 4 years ago by andrewbadr

  • Summary changed from transaction.savepoint_rollback fails with postgresql database backend to transaction.savepoint_rollback fails with postgresql DATABASE_ENGINE

To clarify, this is with DATABASE_ENGINE = "postgresql", *not* "postgresql_psycopg2".

comment:4 Changed 4 years ago by jonathan

Hello Andrew,

This is a duplicate of #12087.
I have the same problem with postgresql, postgresql_psycopg2, on 1.1.1 and TRUNK versions.
FYI, I use postgresql 8.3

comment:5 Changed 4 years ago by andrewbadr

Jonathan, it looks like these are separate issues. The ticket you refer to is only about tests, and successfully repro's under psycopg2. Neither of those are true for this ticket. Also, I'd try changing your setup to isolate the bug because other people can run the tests fine without running into what you're seeing.

comment:6 Changed 4 years ago by andrewbadr

  • Cc andrewbadr.etc@… added

comment:7 Changed 4 years ago by jacob

  • milestone set to 1.2

comment:8 Changed 4 years ago by russellm

  • Triage Stage changed from Unreviewed to Accepted

comment:9 Changed 4 years ago by kmtracey

I can't figure out how you are even getting to the point where get_or_create tries to rollback the transaction. At the revision mentioned (and now), get_or_create only tries the rollback when it catches an IntegrityError (see http://code.djangoproject.com/browser/django/trunk/django/db/models/query.py?rev=11724#L311). Yet when I try to run the get_or_create testcase with the old postgres backend, the first problem encountered is that no IntegrityError is raised but rather a ProgrammingError is raised. (This is true even with 1.1 or trunk r11724). I have to change the except IntegrityError, e in get_or_create to except Exception, e and then I can see the subsequent problem that attempting to do a savepoint rollback will first try to set do that "SET client_encoding to 'UNICODE'":

> c:\u\kmt\django\django-1.1\django\test\_doctest.py(362)set_trace()->None
-> pdb.Pdb.set_trace(self)
(Pdb) n
> c:\u\kmt\django\django-1.1\django\db\models\query.py(341)get_or_create()
-> transaction.savepoint_rollback(sid)
(Pdb) l
336                     transaction.savepoint_commit(sid)
337                     return obj, True
338     #           except IntegrityError, e:
339                 except Exception, e:
340                     import pdb; pdb.set_trace()
341  ->                 transaction.savepoint_rollback(sid)
342                     try:
343                         return self.get(**kwargs), False
344                     except self.model.DoesNotExist:
345                         raise e
346
(Pdb) n
ProgrammingError: "ERROR:  current transaction is aborted, commands ignored until end of transaction block\n\nSET client
_encoding to 'UNICODE'"
> c:\u\kmt\django\django-1.1\django\db\models\query.py(341)get_or_create()
-> transaction.savepoint_rollback(sid)
(Pdb)

So, a question: have you done anything to your install to fix this IntegrityError/ProgrammingError mismatch I see? I'm also wondering why you are using the old backend instead of psycopg2?

The error I see is reported in #12766 but since this is a bit different I'm going to leave both open for now.

comment:10 follow-up: Changed 4 years ago by andrewbadr

I really don't think I did anything to fix the exception mismatch you're seeing. I don't remember encountering it at all. Could it be that my test case was using a field with a unique constraint?

How do I install psycopg1 on Ubuntu? Not sure how I was able to do this before.

(I'm not using it anymore, and when I was it was only by accident. Maybe the BDFLs should consider dropping psycopg1 support for 1.2?)

comment:11 in reply to: ↑ 10 Changed 4 years ago by russellm

Replying to andrewbadr:

Maybe the BDFLs should consider dropping psycopg1 support for 1.2?)

We can't just drop support, but we have put the postgresql backend on the deprecation path: See [12510]

comment:12 Changed 4 years ago by kmtracey

Thanks for responding. I don't know how to get it on Ubuntu, I've only managed to get binaries for it on Windows. Could be what I've managed to find for Windows is not quite a match for what you were running. (I don't actually use it myself, just tried to get a test setup with it working after seeing some problems reported against it.)

It's been put on the deprecation path (http://docs.djangoproject.com/en/dev/releases/1.2/#postgresql-database-backend) but that's a mutli-release cycle thing before it's completely cut. In the meantime we've got a few things not working right with it. psycopg2 is definitely a better bet unless there's some reason you can't use it (which I have not heard anyone report yet).

comment:13 Changed 4 years ago by andrewbadr

Yeah, I know -- I was proposing to accelerate the process in a rash violation of policy.

I can't figure out how to install this without downgrading python.

comment:14 Changed 4 years ago by russellm

  • Resolution set to fixed
  • Status changed from new to closed

This was fixed (inadvertently) by r12848.

comment:15 Changed 3 years ago by jacob

  • milestone 1.2 deleted

Milestone 1.2 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.