Return a list of 2-tuples of form (sql, params). The logic of what exactly the GROUP BY clause contains is hard to describe in other words than "if it passes the test suite, then it is correct".
(self, select, order_by)
| 96 | return extra_select, order_by, group_by |
| 97 | |
| 98 | def get_group_by(self, select, order_by): |
| 99 | """ |
| 100 | Return a list of 2-tuples of form (sql, params). |
| 101 | |
| 102 | The logic of what exactly the GROUP BY clause contains is hard |
| 103 | to describe in other words than "if it passes the test suite, |
| 104 | then it is correct". |
| 105 | """ |
| 106 | # Some examples: |
| 107 | # SomeModel.objects.annotate(Count('somecol')) |
| 108 | # GROUP BY: all fields of the model |
| 109 | # |
| 110 | # SomeModel.objects.values('name').annotate(Count('somecol')) |
| 111 | # GROUP BY: name |
| 112 | # |
| 113 | # SomeModel.objects.annotate(Count('somecol')).values('name') |
| 114 | # GROUP BY: all cols of the model |
| 115 | # |
| 116 | # SomeModel.objects.values('name', 'pk') |
| 117 | # .annotate(Count('somecol')).values('pk') |
| 118 | # GROUP BY: name, pk |
| 119 | # |
| 120 | # SomeModel.objects.values('name').annotate(Count('somecol')).values('pk') |
| 121 | # GROUP BY: name, pk |
| 122 | # |
| 123 | # In fact, the self.query.group_by is the minimal set to GROUP BY. It |
| 124 | # can't be ever restricted to a smaller set, but additional columns in |
| 125 | # HAVING, ORDER BY, and SELECT clauses are added to it. Unfortunately |
| 126 | # the end result is that it is impossible to force the query to have |
| 127 | # a chosen GROUP BY clause - you can almost do this by using the form: |
| 128 | # .values(*wanted_cols).annotate(AnAggregate()) |
| 129 | # but any later annotations, extra selects, values calls that |
| 130 | # refer some column outside of the wanted_cols, order_by, or even |
| 131 | # filter calls can alter the GROUP BY clause. |
| 132 | |
| 133 | # The query.group_by is either None (no GROUP BY at all), True |
| 134 | # (group by select fields), or a list of expressions to be added |
| 135 | # to the group by. |
| 136 | if self.query.group_by is None: |
| 137 | return [] |
| 138 | expressions = [] |
| 139 | group_by_refs = set() |
| 140 | if self.query.group_by is not True: |
| 141 | # If the group by is set to a list (by .values() call most likely), |
| 142 | # then we need to add everything in it to the GROUP BY clause. |
| 143 | # Backwards compatibility hack for setting query.group_by. Remove |
| 144 | # when we have public API way of forcing the GROUP BY clause. |
| 145 | # Converts string references to expressions. |
| 146 | for expr in self.query.group_by: |
| 147 | if not hasattr(expr, "as_sql"): |
| 148 | expr = self.query.resolve_ref(expr) |
| 149 | if isinstance(expr, Ref): |
| 150 | if expr.refs not in group_by_refs: |
| 151 | group_by_refs.add(expr.refs) |
| 152 | expressions.append(expr.source) |
| 153 | else: |
| 154 | expressions.append(expr) |
| 155 | # Note that even if the group_by is set, it is only the minimal |
no test coverage detected