Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#10406 closed (fixed)

Primary keys with model inheritance problems.

Reported by: Ramiro Morales Owned by: Malcolm Tredinnick
Component: Database layer (models, ORM) Version: master
Severity: Keywords: parent_link primary_key onetoonefield
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

With this model setup:

from django.db import models

class Persona(models.Model):
    nombre = models.CharField(max_length=60)

class Cliente(Persona):
    cli_id = models.AutoField(primary_key=True)
    persona = models.OneToOneField(Persona, parent_link=True)

sqlall output (with SQLite, MySQL shows the same) shows that the two Client fields are declared PRIMARY KEY:

CREATE TABLE "thread1_persona" (
    "id" integer NOT NULL PRIMARY KEY,
    "nombre" varchar(60) NOT NULL
)
;
CREATE TABLE "thread1_cliente" (
    "cli_id" integer NOT NULL PRIMARY KEY,
    "persona_id" integer NOT NULL PRIMARY KEY REFERENCES "thread1_persona" ("id")
)
;
COMMIT;

Problem also show if the explicit Cliente PK is changed from AutoField to another field type.

Commenting out http://code.djangoproject.com/browser/django/trunk/django/db/models/base.py#L101
solves the problem (and Django test suite still passes):

BEGIN;
CREATE TABLE "thread1_persona" (
    "id" integer NOT NULL PRIMARY KEY,
    "nombre" varchar(60) NOT NULL
)
;
CREATE TABLE "thread1_cliente" (
    "cli_id" integer NOT NULL PRIMARY KEY,
    "persona_id" integer NOT NULL UNIQUE REFERENCES "thread1_persona" ("id")
)
;
COMMIT;

If Cliente is changed to inherit from models.Model, problem also goes away.

This issue could be related to #10251, but the example posted there doesn't show this double PK problem because it isn't using an explicit OneToOneField with parent_link for the inheritance.

Change History (6)

comment:1 Changed 8 years ago by Malcolm Tredinnick

Owner: changed from nobody to Malcolm Tredinnick

It's the same sort of problem as #10251 (and a couple of others). I'm looking at those at the moment, so I suspect this will get fixed in passing.

comment:2 Changed 8 years ago by Malcolm Tredinnick

Triage Stage: UnreviewedAccepted

comment:3 in reply to:  1 Changed 8 years ago by Ramiro Morales

Summary: Explicit PK plus explicit multi-table inheritance parent link o2o field result in two primary keysInconsistent handling of primary key flag between implicit and explicit (parent_link=True) model inheritance o2o fields when another explicit PK field is also used

Replying to mtredinnick:

It's the same sort of problem as #10251 (and a couple of others). I'm looking at those at the moment, so I suspect this will get fixed in passing.

Ok, here is a bit of additional info I was going to post, HTH:

Further tests show that the parent_link=True part isn't even needed to reproduce this situation.

This would make this ticket a duplicate of #7367 but IMHO that ticket was both opened and closed because of the wrong reasons.

If a multi-table inheritance o2o field should be always a child model PK we have an inconsistency because if rather that using OneToOneField(Persona, parent_link=True) we let Django handle the inheritance with its <whatever>_prt_id implicit field it doesn't automatically flag it as a primary key:

class Cliente(Persona):
    cli_id = models.AutoField(primary_key=True)
-- ...
CREATE TABLE "thread1_cliente" (
    "persona_ptr_id" integer NOT NULL UNIQUE REFERENCES "thread1_persona" ("id"),
    "cli_id" integer NOT NULL PRIMARY KEY
)
;

I will re-purpose this ticket to be about this inconsistency.

Another problem possibly exposed by this example is the fact that model validation isn't catching the double PK condition. Will open a ticket depending on feedback about this one.

comment:4 Changed 8 years ago by Malcolm Tredinnick

Summary: Inconsistent handling of primary key flag between implicit and explicit (parent_link=True) model inheritance o2o fields when another explicit PK field is also usedPrimary keys with model inheritance problems.

Relax. This doesn't need another ticket (and the paragraph-long title isn't really making things clearer at a glance. :-))

We're just messing up the pk assignment in some cases. It's the same root cause as #10251. #7367 is an old ticket (pre-queryset-refactor) and one-to-one fields no longer need to be primary keys, since otherwise multiple inheritance wouldn't be possible.

comment:5 Changed 8 years ago by Malcolm Tredinnick

Resolution: fixed
Status: newclosed

(In [9971]) Fixed #10406 -- Fixed some problems with model inheritance and pk fields.

Manually specifying both a OneToOneField(parent_link=True) and separate a
primary key field was causing invalid SQL to be generated. Thanks to Ramiro
Morales for some analysis on this one.

comment:6 Changed 8 years ago by Malcolm Tredinnick

(In [9973]) [1.0.X] Fixed #10406 -- Fixed some problems with model inheritance and pk fields.

Manually specifying both a OneToOneField(parent_link=True) and separate a
primary key field was causing invalid SQL to be generated. Thanks to Ramiro
Morales for some analysis on this one.

Backport of r9971 from trunk.

Note: See TracTickets for help on using tickets.
Back to Top