We recently started the test and upgrade process to bring our large Django applications more up to date with 1.3 to help test new things. We found that http://code.djangoproject.com/changeset/13363 introduced backwards incompatible changes.
Previously, using PostgreSQL, it was possible to take a manually defined INTEGER column and create a sequence and set the nextval() just as the SERIAL type does. Prior to 1.3, this worked fine as long as you named your sequence correctly. For example, we had a table named nut_food with "id INTEGER NOT NULL DEFAULT NEXTVAL('nut_food_id_seq'::regclass)" -- so at first glance, all appeared correct. However, inserting a new record with "Food.objects.create(..) would *silently* fail and assign None to the instance in Python, despite the record actually having an ID in the database. Two things of note: a) To fix this, one must identify the sequences that are not correct. I scoured pg_catalog and friends and cannot identify where PostgreSQL exposes the link between the "id" and sequence columns. We only identified the column in error by getting exceptions in the code that was using <instance>.pk. Once the errant columns are found: ALTER SEQUENCE nut_food_id_seq OWNED BY nut_food.id; must be run for each sequence/table/column. Without this, pg_get_serial_sequence('"table_name"', 'column_name") returns NULL. When Django creates tables or one has tables set up with a true SERIAL column, the above is not needed. It's *only* when the "serial" is manually constructed, such as from legacy or external databases. This may be useful to note in the Release Notes for 1.3 as a backwards incompatible change. b) The last_insert_id method in the postgresql backend will silently fail for any expected sequences and return None. pg_get_serial_sequence() returns NULL when it cannot find a sequence, and currval() returns NULL as well when passed NULL. def last_insert_id(self, cursor, table_name, pk_name): cursor.execute("SELECT CURRVAL(pg_get_serial_sequence('%s','%s'))" % (table_name, pk_name)) last_id = cursor.fetchone()[0] if last_id is None: raise IntegrityError("Valid sequence not found for %s.%s." % (table_name, pk_name)) return last_id would at least make this (and future sequence issues) at least visible instead of silently failing. Regards, Eric -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.