#34871: Validation of UniqueConstraint with Case() crashes.
-------------------------------------+-------------------------------------
     Reporter:  Andrew Roberts       |                    Owner:  Francesco
                                     |  Panico
         Type:  Bug                  |                   Status:  assigned
    Component:  Database layer       |                  Version:  4.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):

 * cc: Simon Charette (added)

Comment:

 Playing a bit with trying to implement `Q.replace_expressions` I have to
 retract myself; it's not trivial.

 The only solution I can think of is have the validate logic pass a special
 type of dict as `replacement` to `replace_expression` that would default
 missing key lookups for tuples of the form `('active', True)` to
 `query.resolve_lookup_value` so it gets turned into `Exact(F("active"),
 True).replace_expression(replacements)`.

 It's doable but certainly not trivial
 [https://github.com/charettes/django/pull/new/ticket-34871 as this branch
 demonstrate].

 I think this has some ties into #24267 where the idea would be that we'd
 introduce an `UnresolvedLookup(BaseExpression)` class initialized from
 `__init__(self, field, **lookup)` and that would store `F(field)` in its
 source expressions and thus allow `replace_expressions` to take place
 normally as `Q` would be storing `UnresolvedLookup(key_parts[0],
 key_parts[1:])` instead of tuple of the form `tuple[str, Any]` as
 children. All `UnresolvedLookup` would do in its `resolve_expressions` is
 what can be found in the trailing part of `Query.build_filter` today that
 calls `solve_lookup_type`, `resolve_lookup_value`, and `build_lookup` but
 it would behave like a normal expression and avoids all the hacks we have
 in place today that special case `Q` objects.

 Until work towards ^^ can be made the best solution here is to use lookups
 directly

 {{{#!python
 from django.db.models.lookups import Exact

 models.UniqueConstraint(
     Case(When(Exact(F("active", True), then=F("email"))),
         name="unique_active_email",
     )
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/34871#comment:10>
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/0107018dcfaca76b-1d8ea7e6-649a-42df-b774-bb4fc45cbb29-000000%40eu-central-1.amazonses.com.

Reply via email to