diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 0a41525..492120c 100644
|
|
class Query(object):
|
1356 | 1356 | # Then, add the path to the query's joins. Note that we can't trim |
1357 | 1357 | # joins at this stage - we will need the information about join type |
1358 | 1358 | # of the trimmed joins. |
| 1359 | last = None |
| 1360 | final_path = [] |
1359 | 1361 | for pos, join in enumerate(path): |
1360 | | opts = join.to_opts |
| 1362 | if pos < len(path) - 1: |
| 1363 | next = path[pos + 1] |
| 1364 | else: |
| 1365 | next = None |
1361 | 1366 | if join.direct: |
1362 | 1367 | nullable = self.is_nullable(join.join_field) |
1363 | 1368 | else: |
1364 | 1369 | nullable = True |
1365 | | connection = alias, opts.db_table, join.join_field.get_joining_columns() |
| 1370 | final_path.append(join) |
| 1371 | joining_columns = join.join_field.get_joining_columns() |
| 1372 | if last and next: |
| 1373 | # Try removing previous join if the current one maps directly |
| 1374 | # to the next one (much in the way trim_joins does it): |
| 1375 | cur_targets = set(t.column for t in zip(*join.join_field.related_fields)[0]) |
| 1376 | join_targets = set(t.column for t in next.join_field.foreign_related_fields) |
| 1377 | if cur_targets.issubset(join_targets): |
| 1378 | self.unref_alias(joins.pop()) |
| 1379 | alias = joins[-1] |
| 1380 | final_path.pop() |
| 1381 | from_join = joining_columns[0][1] |
| 1382 | to_join = next.join_field.get_joining_columns()[0][0] |
| 1383 | joining_columns = ((from_join, to_join),) |
| 1384 | last = join |
| 1385 | opts = join.to_opts |
| 1386 | connection = alias, opts.db_table, joining_columns |
1366 | 1387 | reuse = can_reuse if join.m2m else None |
1367 | 1388 | alias = self.join(connection, reuse=reuse, |
1368 | 1389 | nullable=nullable, join_field=join.join_field) |
1369 | 1390 | joins.append(alias) |
1370 | 1391 | if hasattr(final_field, 'field'): |
1371 | 1392 | final_field = final_field.field |
1372 | | return final_field, targets, opts, joins, path |
| 1393 | return final_field, targets, opts, joins, final_path |
1373 | 1394 | |
1374 | 1395 | def trim_joins(self, targets, joins, path): |
1375 | 1396 | """ |
diff --git a/tests/m2m_through/tests.py b/tests/m2m_through/tests.py
index 259dc68..bbf7595 100644
|
|
class M2mThroughTests(TestCase):
|
343 | 343 | ], |
344 | 344 | attrgetter("name") |
345 | 345 | ) |
| 346 | |
| 347 | def test_ticket_20535_join_trimming(self): |
| 348 | qs = Friendship.objects.filter(first__rel_to_set__first__id=1) |
| 349 | self.assertEqual(str(qs.query).count('JOIN'), 1) |
| 350 | |
| 351 | def test_ticket_20535_no_join_trimming(self): |
| 352 | qs = Friendship.objects.filter(first__rel_to_set__first__id=1, first__name='Jane') |
| 353 | self.assertEqual(str(qs.query).count('JOIN'), 2) |