Ticket #18375: ticket_18375_15.diff
File ticket_18375_15.diff, 4.3 KB (added by , 12 years ago) |
---|
-
django/db/models/sql/expressions.py
diff --git a/django/db/models/sql/expressions.py b/django/db/models/sql/expressions.py index 3745099..a808183 100644
a b class SQLEvaluator(object): 9 9 self.cols = [] 10 10 11 11 self.contains_aggregate = False 12 self.used_joins = [] 12 13 self.expression.prepare(self, query, allow_joins) 13 14 14 15 def prepare(self): … … class SQLEvaluator(object): 51 52 field, source, opts, join_list, last, _ = query.setup_joins( 52 53 field_list, query.get_meta(), 53 54 query.get_initial_alias(), False) 55 # Note that even if we trim some joins away, the joins are 56 # still usable by this node. 57 self.used_joins.extend(join_list) 54 58 col, _, join_list = query.trim_joins(source, join_list, last, False) 55 56 59 self.cols.append((node, (join_list[-1], col))) 57 60 except FieldDoesNotExist: 58 61 raise FieldError("Cannot resolve keyword %r into field. " -
django/db/models/sql/query.py
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index f5a477f..cf4f7f5 100644
a b class Query(object): 1100 1100 elif isinstance(value, ExpressionNode): 1101 1101 # If value is a query expression, evaluate it 1102 1102 value = SQLEvaluator(value, self) 1103 if value.used_joins and can_reuse is not None: 1104 can_reuse.update(value.used_joins) 1105 1103 1106 having_clause = value.contains_aggregate 1104 1107 1105 1108 for alias, aggregate in self.aggregates.items(): -
docs/releases/1.5.txt
diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index 8b7af2c..d3cbe23 100644
a b Miscellaneous 563 563 :ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where 564 564 the operators are used as boolean AND and OR operators. 565 565 566 * When :ref:`F() expressions <query-expressions>` were used in lookups spanning 567 multi-valued relations it was possible that the F() and other lookups in a 568 single filter() call didn't target the same relation. This was change and now 569 F() expressions will reuse the same relation. 570 566 571 * The :ttag:`csrf_token` template tag is no longer enclosed in a div. If you need 567 572 HTML validation against pre-HTML5 Strict DTDs, you should add a div around it 568 573 in your pages. -
tests/modeltests/expressions/tests.py
diff --git a/tests/modeltests/expressions/tests.py b/tests/modeltests/expressions/tests.py index 99eb07e..ba3f827 100644
a b class ExpressionsTests(TestCase): 219 219 ) 220 220 acme.num_employees = F("num_employees") + 16 221 221 self.assertRaises(TypeError, acme.save) 222 223 def test_ticket_18375_join_reuse(self): 224 # Test that reverse multijoin F() references and the lookup target 225 # the same join. Pre #18375 the F() join was generated first, and the 226 # lookup couldn't reuse that join. 227 qs = Employee.objects.filter( 228 company_ceo_set__num_chairs=F('company_ceo_set__num_employees')) 229 self.assertEqual(str(qs.query).count('JOIN'), 1) 230 231 def test_ticket_18375_kwarg_ordering(self): 232 # The next query was dict-randomization dependent - if the "gte=1" 233 # was seen first, then the F() will reuse the join generated by the 234 # gte lookup, if F() was seen first, then it generated a join the 235 # other lookups could not reuse. 236 qs = Employee.objects.filter( 237 company_ceo_set__num_chairs=F('company_ceo_set__num_employees'), 238 company_ceo_set__num_chairs__gte=1) 239 self.assertEqual(str(qs.query).count('JOIN'), 1) 240 241 def test_ticket_18375_kwarg_ordering_2(self): 242 # Another similar case for F() than above. Now we have the same join 243 # in two filter kwargs, one in the lhs lookup, one in F. Here pre 244 # #18375 the amount of joins generated was random if dict 245 # randomization was enabled, that is the generated query dependend 246 # on which clause was seen first. 247 qs = Employee.objects.filter( 248 company_ceo_set__num_employees=F('pk'), 249 pk=F('company_ceo_set__num_employees') 250 ) 251 self.assertEqual(str(qs.query).count('JOIN'), 1)