Django

Code

Ticket #2091 (closed: fixed)

Opened 2 years ago

Last modified 3 weeks ago

IN field lookup returns all objects without filtering by the supplied list when used on ManyToMany field.

Reported by: real dot human at mrmachine dot net Assigned to: nobody
Component: Database wrapper Version: SVN
Keywords: in field lookup filter manytomany m2m many, qs-rf-fixed Cc: gabor@nekomancer.net, freakboy3742@gmail.com, real.human@mrmachine.net
Triage Stage: Accepted Has patch: 0
Needs documentation: 0 Needs tests: 0
Patch needs improvement: 0

Description

using an IN field lookup in a filter on a ManyToMany? field seems to return all objects. as far as i know, the two e.filter statements below should return the same queryset.

>>> e = Entry.objects.all()
>>> e
[<Entry: smooth sailing>, <Entry: wii rocks e3>, <Entry: 30thirty reboot>]

>>> t = Tag.objects.get(id=6)
>>> t
<Tag: django>

>>> t.entry_set.all()
[<Entry: smooth sailing>, <Entry: 30thirty reboot>]

>>> e.filter(tags__id__exact=6)
[<Entry: smooth sailing>, <Entry: 30thirty reboot>]

>>> e.filter(tags__id__in=[6])
[<Entry: smooth sailing>, <Entry: wii rocks e3>, <Entry: 30thirty reboot>]

Attachments

Change History

06/07/06 01:21:52 changed by real dot human at mrmachine dot net

here's some additional information showing the broken sql being generated.

>>> from thirty30.blog.models import Category, Entry, Tag
>>> from django.db import connection
>>> Entry.objects.filter(tags__id__in = [6])
[<Entry: smooth sailing>, <Entry: wii rocks e3>, <Entry: 30thirty reboot>]
>>> print connection.queries[-1]['sql']
SELECT "blog_entry"."id","blog_entry"."created","blog_entry"."modified","blog_entry"."author_id","blog_entry"."title","blog_entry"."synopsis","blog_entry"."synopsis_html","blog_entry"."body","blog_entry"."body_html","blog_entry"."slug","blog_entry"."category_id","blog_entry"."published","blog_entry"."status","blog_entry"."enable_comments","blog_entry"."is_sticky" FROM "blog_entry" LEFT OUTER JOIN "blog_entry_tags" AS "m2m_blog_entry__tags" ON "blog_entry"."id" = "m2m_blog_entry__tags"."entry_id" INNER JOIN "blog_tag" AS "blog_entry__tags" ON "m2m_blog_entry__tags"."tag_id" = "blog_entry__tags"."id" WHERE ("blog_entry__tags"."id" IN (6)) ORDER BY "blog_entry"."published" DESC

07/30/06 10:13:27 changed by gabor@nekomancer.net

  • cc set to gabor@nekomancer.net.

i had the same problem, but for me it's only happening with sqlite3.

which database did you use? and if you used sqlite3, could you try to reproduce the problem with postgresql?

09/08/06 08:30:21 changed by russellm

  • cc changed from gabor@nekomancer.net to gabor@nekomancer.net, freakboy3742@gmail.com.

I see this problem as well, but only with SQLite3. It doesn't appear to be a problem with PostgreSQL.

The problem appears to be caused by the fact that m2m tables are collated using a LEFT OUTER JOIN, rather than an INNER JOIN. Using SQLite, this approach puts partially sparse rows into the combined table for those m2m entries that should be excluded from the result set. PostgreSQL omits the sparse rows, and therefore returns the correct results.

If you hand modify the query produced by the filter operation and replace the outer join with an inner join, the results return as expected.

The use of LEFT OUTER JOIN was introduced in r2613 to fix #1535; however, it has caused other problems, such as #2306.

09/16/06 02:51:15 changed by mtredinnick

  • owner changed from adrian to mtredinnick.

11/20/06 09:41:05 changed by Gábor Farkas <gabor@nekomancer.net>

this issue seems to be very similar to the one in #2457. maybe it's the same issue?

02/21/07 18:11:55 changed by mrmachine <real dot human at mrmachine dot net>

  • cc changed from gabor@nekomancer.net, freakboy3742@gmail.com to gabor@nekomancer.net, freakboy3742@gmail.com, real.human@mrmachine.net.

02/22/07 01:15:03 changed by Simon G. <dev@simon.net.nz>

  • stage changed from Unreviewed to Accepted.

09/13/07 16:35:29 changed by mtredinnick

  • keywords changed from in field lookup filter manytomany m2m many to in field lookup filter manytomany m2m many, qs-rf-fixed.

04/26/08 21:50:16 changed by mtredinnick

  • status changed from new to closed.
  • resolution set to fixed.

(In [7477]) Merged the queryset-refactor branch into trunk.

This is a big internal change, but mostly backwards compatible with existing code. Also adds a couple of new features.

Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658


Add/Change #2091 (IN field lookup returns all objects without filtering by the supplied list when used on ManyToMany field.)




Change Properties
Action