#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 [email protected].
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