views:

61

answers:

2

Background: Running a PostgreSQL database for a Django app (Django 1.1.1, Python2.4, psycopg2 and Postgres 8.1) I've restored the database from a SQL dump several times. Each time I do that and then try to add a new row, either shell, admin, or site front end, I get this error:

IntegrityError: duplicate key violates unique constraint "app_model_pkey"

The data dump is fine and is resetting the sequences. But if I try adding the row again, it's successful! So I can just try jamming a new row into every table and then everything seems to be copacetic.

Question: Given that (1) the SQL dump is good and Postgres is reading it in correctly (per earlier question), and (2) Django's ORM does not seem to be failing systemically getting next values, what is going on in this specific instance?

+1  A: 

Django doesn't hold or directly read the sequence values in any way. I've explained it f.ex. in this question: 2088210/django-object-creation-and-postgres-sequences.

Postgresql does increment the sequence when you try to add a row, even if the result of the operation is not successful (raises a duplicate key error) the sequence incrementation doesn't rollback. So, that's the reason why it works the second time you try adding a row.

I don't know why your sequences are not set properly, could you check what is the sequence value before dump and after restore, and do the same with the max() pk of the table? Maybe it's an 8.1 bug with the restore? I don't know. What I'm sure of: it's not Django's fault.

zalew
I wish I understood why, but this appears to be the answer. I had only one auth group, and the dump sets the current value of that ID's sequence to 1: `SELECT pg_catalog.setval('auth_group_id_seq', 1, false);`. If I try selecting the nextval from that sequence it's also 1. The subsequent query for nextval bumps the sequence to 2.
bennylope
@zalew: That is incorrect; Django does in fact fetch values from PostgreSQL sequences. If you enable logging of all statements in your DB, you'll see that Django issues quite a few `SELECT CURRVAL('"app_table_id_seq"');` commands. In fact, if you look at the code for `django.db.models.sql.compiler.SQLInsertCompiler.execute_sql()` and `django.db.backends.postgresql.operations.DatabaseOperations.last_insert_id()`, youll see that it fetches the sequence value after every single INSERT command unless `autocommit=True`.
Aram Dulyan
+1  A: 

I am guessing that your sequence is out of date.

You can fix that like this:

select setval('app_model_id_seq', max(id)) from app_model;
WoLpH