#36787: In and Range lookups crash when provided to filter() if RHS contains 
mix of
expressions and strings
-------------------------------------+-------------------------------------
     Reporter:  Jacob Walls          |                    Owner:  (none)
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  5.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Jacob Walls:

Old description:

> {{{#!diff
> diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py
> index 5b9dd8e5ec..4cb90ed1d9 100644
> --- a/tests/lookup/tests.py
> +++ b/tests/lookup/tests.py
> @@ -1847,6 +1847,8 @@ class LookupQueryingTests(TestCase):
>              ((1842, 2042), (self.s2, self.s3)),
>              ((1942, 1942, 1942), (self.s1,)),
>              ((1942, 2042, 1842), (self.s1, self.s2, self.s3)),
> +            # Mix expressions and string field references.
> +            ((models.F("year") + 100, "gt"), (self.s1,)),
>          ]
>
>          for years, seasons in test_cases:
> ).exists()
> }}}
> {{{#!py
> ======================================================================
> ERROR: test_in_lookup_in_filter
> (lookup.tests.LookupQueryingTests.test_in_lookup_in_filter)
> (years=(<CombinedExpression: F(year) + Value(100)>, 'gt'),
> seasons=(<Season: 1942>,))
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/jwalls/django/tests/lookup/tests.py", line 1857, in
> test_in_lookup_in_filter
>     Season.objects.filter(In(F("year"), years)).order_by("pk"), seasons
>                           ~~^^^^^^^^^^^^^^^^^^
>   File "/Users/jwalls/django/django/db/models/lookups.py", line 35, in
> __init__
>     self.rhs = self.get_prep_lookup()
>                ~~~~~~~~~~~~~~~~~~~~^^
>   File "/Users/jwalls/django/django/db/models/lookups.py", line 517, in
> get_prep_lookup
>     return super().get_prep_lookup()
>            ~~~~~~~~~~~~~~~~~~~~~~~^^
>   File "/Users/jwalls/django/django/db/models/lookups.py", line 310, in
> get_prep_lookup
>     Value(prep_value, self.lhs.output_field)
>                       ^^^^^^^^^^^^^^^^^^^^^
> AttributeError: 'F' object has no attribute 'output_field'
> }}}
> Seems like 089deb82b9ac2d002af36fd36f288368cdac4b53 (5.2) needed the same
> tweak as 0bfaa55708d402432d44882d9a8e4cb85011472c (5.2).

New description:

 The invariance between `__in` and `In` is broken when the right hand side
 contains a mix of expressions and strings (where the strings are possible
 literal values). EDIT: replaced draft test case, first version was
 misleading.
 {{{#!diff
 diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py
 index 5b9dd8e5ec..a34d95b8cb 100644
 --- a/tests/lookup/tests.py
 +++ b/tests/lookup/tests.py
 @@ -1855,6 +1855,19 @@ class LookupQueryingTests(TestCase):
                      Season.objects.filter(In(F("year"),
 years)).order_by("pk"), seasons
                  )

 +    def test_in_lookup_in_filter_text_field(self):
 +        self.assertSequenceEqual(
 +            # this works...
 +            # Season.objects.filter(
 +            #     nulled_text_field__in=[F("nulled_text_field"),
 "special_value"]
 +            # ),
 +            # this doesn't...
 +            Season.objects.filter(
 +                In(F("nulled_text_field"), [F("nulled_text_field"),
 "special_value"])
 +            ),
 +            [self.s2],
 +        )
 +
      def test_filter_lookup_lhs(self):
          qs = Season.objects.annotate(before_20=LessThan(F("year"),
 2000)).filter(
              before_20=LessThan(F("year"), 1900),

 }}}
 {{{#!py
 ======================================================================
 ERROR: test_in_lookup_in_filter_text_field
 (lookup.tests.LookupQueryingTests.test_in_lookup_in_filter_text_field)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "/django/source/tests/lookup/tests.py", line 1866, in
 test_in_lookup_in_filter_text_field
     In(F("nulled_text_field"), [F("nulled_text_field"), "special_value"])
   File "/django/source/django/db/models/lookups.py", line 35, in __init__
     self.rhs = self.get_prep_lookup()
                ^^^^^^^^^^^^^^^^^^^^^^
   File "/django/source/django/db/models/lookups.py", line 517, in
 get_prep_lookup
     return super().get_prep_lookup()
            ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/django/source/django/db/models/lookups.py", line 310, in
 get_prep_lookup
     Value(prep_value, self.lhs.output_field)
                       ^^^^^^^^^^^^^^^^^^^^^
 AttributeError: 'F' object has no attribute 'output_field'
 }}}
 Seems like 089deb82b9ac2d002af36fd36f288368cdac4b53 (5.2) needed the same
 tweak as 0bfaa55708d402432d44882d9a8e4cb85011472c (5.2).

--
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36787#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 view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019b04f57ee9-97ffdfe8-672e-47b6-b28c-ca641cde8b84-000000%40eu-central-1.amazonses.com.

Reply via email to