#29868: Database Check Constraints Not Retained (Only Last Is Stored)
-------------------------------------+-------------------------------------
Reporter: Scott Stevens | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: check constraint | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Scott Stevens):
Here's my `models.py` (everything else is a default `django-admin
startproject djangoproject .` followed by `./manage.py startapp example`,
with `'example'` added to `INSTALLED_APPS`):
{{{
from django.db import models
from django.db.models import Q
from django.core.validators import MinValueValidator
CHOICES = [
(0, 'A'),
(1, 'B'),
(2, 'C'),
]
class ExampleModel(models.Model):
# Auto PK
# No constraint generated by MinValueValidator, so I add my own.
counter =
models.PositiveIntegerField(validators=[MinValueValidator(1)])
dropdown = models.PositiveSmallIntegerField(choices=CHOICES)
class Meta:
constraints = [
models.CheckConstraint(
check=Q(counter__gt=0), name="counter_bounds"),
models.CheckConstraint(
check=Q(dropdown__in=[choice[0] for choice in CHOICES]),
name="dropdown_choices"),
]
}}}
Here's the result of `./manage.py sqlmigrate example 0001`:
{{{
BEGIN;
--
-- Create model ExampleModel
--
CREATE TABLE "example_examplemodel" ("id" integer NOT NULL PRIMARY KEY
AUTOINCREMENT, "counter" integer unsigned NOT NULL CHECK ("counter" >= 0),
"dropdown" smallint unsigned NOT NULL CHECK ("dropdown" >= 0));
--
-- Create constraint counter_bounds on model examplemodel
--
ALTER TABLE "example_examplemodel" RENAME TO "example_examplemodel__old";
CREATE TABLE "example_examplemodel" ("id" integer NOT NULL PRIMARY KEY
AUTOINCREMENT, "counter" integer unsigned NOT NULL CHECK ("counter" >= 0),
"dropdown" smallint unsigned NOT NULL CHECK ("dropdown" >= 0), CONSTRAINT
"counter_bounds" CHECK ("counter" > 0));
INSERT INTO "example_examplemodel" ("id", "counter", "dropdown") SELECT
"id", "counter", "dropdown" FROM "example_examplemodel__old";
DROP TABLE "example_examplemodel__old";
--
-- Create constraint dropdown_choices on model examplemodel
--
ALTER TABLE "example_examplemodel" RENAME TO "example_examplemodel__old";
CREATE TABLE "example_examplemodel" ("id" integer NOT NULL PRIMARY KEY
AUTOINCREMENT, "counter" integer unsigned NOT NULL CHECK ("counter" >= 0),
"dropdown" smallint unsigned NOT NULL CHECK ("dropdown" >= 0), CONSTRAINT
"dropdown_choices" CHECK ("dropdown" IN (0, 1, 2)));
INSERT INTO "example_examplemodel" ("id", "counter", "dropdown") SELECT
"id", "counter", "dropdown" FROM "example_examplemodel__old";
DROP TABLE "example_examplemodel__old";
COMMIT;
}}}
I can then (using the shell) save an object `ExampleModel(counter=0,
dropdown=2)`, but not `ExampleModel(counter=1, dropdown=3)`.
Notably, all constraints are included when I am altering fields on the
table after the initial migration, so it seems that adding constraints
simply doesn't keep track of previous constraints to include on the
`CREATE TABLE` query.
This example was reproduced with commit
19126339f307e589f99259ab0176c4367a8055f0.
--
Ticket URL: <https://code.djangoproject.com/ticket/29868#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.f12d2a27ef4b6c6ba0902f94b4b7fa66%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.