#30172: Incorrect migration applying for new Meta.constraints/indexes and field
check/unique or unique/index_together with same fields
------------------------------------------+------------------------
               Reporter:  Pavel Tyslacki  |          Owner:  nobody
                   Type:  Bug             |         Status:  new
              Component:  Migrations      |        Version:  2.2
               Severity:  Normal          |       Keywords:
           Triage Stage:  Unreviewed      |      Has patch:  0
    Needs documentation:  0               |    Needs tests:  0
Patch needs improvement:  0               |  Easy pickings:  0
                  UI/UX:  0               |
------------------------------------------+------------------------
 Case 1: trying remove check constraint from field when `CheckConstraint`
 exists in `Meta.constraints` with same field will remove both constraints:
 {{{
 class TestCheck(models.Model):
     f1 = models.PositiveIntegerField()  # will change to `f1 =
 models.IntegerField()`

     class Meta:
         constraints = [
             models.CheckConstraint(check=models.Q(f1__gte=0),
 name='TestCheck_f1_check'),
         ]


 # initial migration:

         migrations.CreateModel(
             name='TestCheck',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('f1', models.PositiveIntegerField()),
             ],
         ),
         migrations.AddConstraint(
             model_name='testcheck',
             constraint=models.CheckConstraint(check=models.Q(f1__gte=0),
 name='TestCheck_f1_check'),
         ),

 # applied migration:

         migrations.AlterField(
             model_name='testcheck',
             name='f1',
             field=models.IntegerField(),
         ),
 }}}


 Case 2: trying remove `unique=True` from field when `UniqueConstraint`
 exists in `Meta.constraints` with same field will remove both constraints
 or raise exception if `UniqueConstraint` has condition:
 {{{
 class TestUniqCondField(models.Model):
     f1 = models.IntegerField(unique=True)  # will change to `f1 =
 models.IntegerField()`

     class Meta:
         constraints = [
             models.UniqueConstraint(fields=['f1'],
 name='TestUniqCondField_f1_uniq', condition=models.Q(f1__gte=0)),
         ]


 # initial migration:

         migrations.CreateModel(
             name='TestUniqCondField',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('f1', models.IntegerField(unique=True)),
             ],
         ),
         migrations.AddConstraint(
             model_name='testuniqcondfield',
 constraint=models.UniqueConstraint(condition=models.Q(f1__gte=0),
 fields=('f1',), name='TestUniqCondField_f1_uniq'),
         ),


 # applied migration:

         migrations.AlterField(
             model_name='testuniqcondfield',
             name='f1',
             field=models.IntegerField(),
         ),

 }}}

 Case 3: trying remove `Meta.unique_together` for same
 `UniqueConstraint.fields` in `Meta.constraints` get incorrect state via
 introspection (the same if UniqueConstraint has condition):
 {{{
 class TestUniqTogether(models.Model):
     f1 = models.IntegerField()
     f2 = models.IntegerField()

     class Meta:
         unique_together = [
             ('f1', 'f2'),  # will be removed
         ]

         constraints = [
             models.UniqueConstraint(fields=['f1', 'f2'],
 name='TestUniqTogether_f1_f2_uniq'),
         ]


 # initial migration:

         migrations.CreateModel(
             name='TestUniqTogether',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('f1', models.IntegerField()),
                 ('f2', models.IntegerField()),
             ],
         ),
         migrations.AddConstraint(
             model_name='testuniqtogether',
             constraint=models.UniqueConstraint(fields=('f1', 'f2'),
 name='TestUniqTogether_f1_f2_uniq'),
         ),
         migrations.AlterUniqueTogether(
             name='testuniqtogether',
             unique_together={('f1', 'f2')},
         ),


 # applied migration

         migrations.AlterUniqueTogether(
             name='testuniqtogether',
             unique_together=set(),
         ),
 }}}

 Case 4: trying remove `Meta.index_together` for same `Index.fields` in
 `Meta.indexes` get incorrect state via introspection (the same if Index
 has condition):
 {{{
 class TestIndexTogether(models.Model):
     f1 = models.IntegerField()
     f2 = models.IntegerField()

     class Meta:
         index_together = [
             ('f1', 'f2'),  # will be removed
         ]

         indexes = [
             models.Index(fields=['f1', 'f2'],
 name='TestIndexTogether_f1_f2_index'),
         ]


 # initial migration:

         migrations.CreateModel(
             name='TestIndexTogether',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('f1', models.IntegerField()),
                 ('f2', models.IntegerField()),
             ],
         ),
         migrations.AddIndex(
             model_name='testindextogether',
             index=models.Index(fields=['f1', 'f2'],
 name='TestIndexTogether_f1_f2_index'),
         ),
         migrations.AlterIndexTogether(
             name='testindextogether',
             index_together={('f1', 'f2')},
         ),


 # applied migration:

         migrations.AlterIndexTogether(
             name='testindextogether',
             index_together=set(),
         ),
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30172>
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/048.aed9a42997b8cc4e68acb5f912baa55e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to