Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#10406 closed (fixed)

Primary keys with model inheritance problems.

Reported by: ramiro Owned by: mtredinnick
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 follow-up: Changed 6 years ago by mtredinnick

  • Needs documentation unset
  • Needs tests unset
  • Owner changed from nobody to mtredinnick
  • Patch needs improvement unset

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 6 years ago by mtredinnick

  • Triage Stage changed from Unreviewed to Accepted

comment:3 in reply to: ↑ 1 Changed 6 years ago by ramiro

  • Summary changed from Explicit PK plus explicit multi-table inheritance parent link o2o field result in two primary keys to Inconsistent 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 6 years ago by mtredinnick

  • Summary changed from Inconsistent handling of primary key flag between implicit and explicit (parent_link=True) model inheritance o2o fields when another explicit PK field is also used to Primary 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 6 years ago by mtredinnick

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

(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 6 years ago by mtredinnick

(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