#34293: Extra validation introduced in 30581 breaks certain constraint setups
-------------------------------------------------+------------------------
               Reporter:  Ionel Cristian Mărieș  |          Owner:  nobody
                   Type:  Uncategorized          |         Status:  new
              Component:  Uncategorized          |        Version:  4.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                      |
-------------------------------------------------+------------------------
 So I have this model
 {{{
 class TimeTsTzRange(models.Func):
     function = 'timetstzrange'
     output_field = fields.DateTimeRangeField()
 class Schedule(models.Model):
     class Meta:
         constraints = [
             models.CheckConstraint(
                 name='schedule_start_lt_end',
                 check=(
                     Q(start_time__lt=F('end_time')) |
                     Q(start_time__lte=HALF_HOUR_BEFORE_MIDNIGHT,
 end_time=MIDNIGHT)
                 ),
             ),
             constraints.ExclusionConstraint(
                 name='schedule_exclude_overlapping',
                 expressions=[
                     (
                         TimeTsTzRange(
                             'start_time',
                             'end_time',
                             fields.RangeBoundary(inclusive_upper=True),
                         ),
                         fields.RangeOperators.OVERLAPS,
                     ),
                     ('weekday', fields.RangeOperators.EQUAL),
                     ('therapist', fields.RangeOperators.EQUAL),
                 ],
             ),
         ]
     start_time = models.TimeField(
         verbose_name=_('start time'),
     )
     end_time = models.TimeField(
         verbose_name=_('end time'),
     )
    # and some other irrelevant fields
 }}}

 Under 3.2 this worked fine,
 Schedule.objects.create(start_time=time(2),end_time=time(1)) would raise
 an IntegrityError as expected with a decently helpful message: new row for
 relation "app_schedule" violates check constraint "schedule_start_lt_end"
 DETAIL:  Failing row contains (13, 3, 02:00:00, 01:00:00, 3).

 Under 4.2a1 this raises django.db.utils.DataError with a not really
 helpful message: range lower bound must be less than or equal to range
 upper bound
 CONTEXT:  PL/pgSQL function timetstzrange(time without time zone,time
 without time zone,text) line 6 at RETURN

 Now this happens because in 4.2 all the constraints are checked,
 regardless if 1st one faile, and obviously the second will fail horribly.

 I've tried adding deferrable=models.Deferrable.DEFERRED to the second
 contraint but it's still run in validation - maybe this could be changed?
 And then my problem would go away.

 Sure, I could make a custom function (that wraps timetstzrange) to
 shortcircuit the second constraint if range is invalid but that seems ugly
 if not dangerous.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34293>
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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070185e9c9797c-d4016eea-555f-4936-9934-0b6c4c091477-000000%40eu-central-1.amazonses.com.

Reply via email to