Ticket #8784: diff.txt

File diff.txt, 3.3 KB (added by Johntron, 7 years ago)

Patch to add HAVING clauses to QuerySets

Line 
1Index: django/db/models/sql/query.py
2===================================================================
3--- django/db/models/sql/query.py       (revision 8818)
4+++ django/db/models/sql/query.py       (working copy)
5@@ -84,6 +84,7 @@
6         self.extra_tables = ()
7         self.extra_where = ()
8         self.extra_params = ()
9+        self.extra_having = ()
10         self.extra_order_by = ()
11 
12     def __str__(self):
13@@ -186,6 +187,7 @@
14         obj.extra_tables = self.extra_tables
15         obj.extra_where = self.extra_where
16         obj.extra_params = self.extra_params
17+        obj.extra_having = self.extra_having
18         obj.extra_order_by = self.extra_order_by
19         if self.filter_is_sticky and self.used_aliases:
20             obj.used_aliases = self.used_aliases.copy()
21@@ -292,6 +294,9 @@
22             grouping = self.get_grouping()
23             result.append('GROUP BY %s' % ', '.join(grouping))
24 
25+        if self.extra_having:
26+            result.append('HAVING %s' % self.extra_having[0])
27+
28         if ordering:
29             result.append('ORDER BY %s' % ', '.join(ordering))
30 
31@@ -388,10 +393,14 @@
32             if self.extra_where and rhs.extra_where:
33                 raise ValueError("When merging querysets using 'or', you "
34                         "cannot have extra(where=...) on both sides.")
35+            if self.extra_having and rhs.extra_having:
36+                raise ValueError("When merging querysets using 'or', you "
37+                        "cannot have extra(having=...) on both sides.")
38         self.extra_select.update(rhs.extra_select)
39         self.extra_tables += rhs.extra_tables
40         self.extra_where += rhs.extra_where
41         self.extra_params += rhs.extra_params
42+        self.extra_having += rhs.extra_having
43 
44         # Ordering uses the 'rhs' ordering, unless it has none, in which case
45         # the current ordering is used.
46@@ -1567,7 +1576,7 @@
47         self.related_select_cols = []
48         self.related_select_fields = []
49 
50-    def add_extra(self, select, select_params, where, params, tables, order_by):
51+    def add_extra(self, select, select_params, where, params, tables, order_by, having):
52         """
53         Adds data to the various extra_* attributes for user-created additions
54         to the query.
55@@ -1598,6 +1607,8 @@
56             self.extra_params += tuple(params)
57         if tables:
58             self.extra_tables += tuple(tables)
59+        if having:
60+            self.extra_having += tuple(having)
61         if order_by:
62             self.extra_order_by = order_by
63 
64Index: django/db/models/query.py
65===================================================================
66--- django/db/models/query.py   (revision 8818)
67+++ django/db/models/query.py   (working copy)
68@@ -567,14 +567,14 @@
69         return obj
70 
71     def extra(self, select=None, where=None, params=None, tables=None,
72-              order_by=None, select_params=None):
73+              order_by=None, select_params=None, having=None):
74         """
75         Adds extra SQL fragments to the query.
76         """
77         assert self.query.can_filter(), \
78                 "Cannot change a query once a slice has been taken"
79         clone = self._clone()
80-        clone.query.add_extra(select, select_params, where, params, tables, order_by)
81+        clone.query.add_extra(select, select_params, where, params, tables, order_by, having)
82         return clone
83 
84     def reverse(self):
Back to Top