Code

Ticket #7760: subquery_patch

File subquery_patch, 2.9 KB (added by henrybaxter, 6 years ago)

Subquery LIMIT and OFFSET

Line 
1Index: django/db/models/sql/query.py
2===================================================================
3--- django/db/models/sql/query.py       (revision 7922)
4+++ django/db/models/sql/query.py       (working copy)
5@@ -252,7 +252,7 @@
6 
7         # This must come after 'select' and 'ordering' -- see docstring of
8         # get_from_clause() for details.
9-        from_, f_params = self.get_from_clause()
10+        from_, f_params = self.get_from_clause(with_limits)
11 
12         where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias)
13         params = list(self.extra_select_params)
14@@ -283,7 +283,7 @@
15         if ordering:
16             result.append('ORDER BY %s' % ', '.join(ordering))
17 
18-        if with_limits:
19+        if self.outer_limits:
20             if self.high_mark is not None:
21                 result.append('LIMIT %d' % (self.high_mark - self.low_mark))
22             if self.low_mark:
23@@ -502,7 +502,7 @@
24             return result, None
25         return result, aliases
26 
27-    def get_from_clause(self):
28+    def get_from_clause(self, with_limits):
29         """
30         Returns a list of strings that are joined together to go after the
31         "FROM" part of the query, as well as a list any extra parameters that
32@@ -517,6 +517,7 @@
33         qn = self.quote_name_unless_alias
34         qn2 = self.connection.ops.quote_name
35         first = True
36+        self.outer_limits = True
37         for alias in self.tables:
38             if not self.alias_refcount[alias]:
39                 continue
40@@ -533,7 +534,25 @@
41                            qn2(lhs_col), qn(alias), qn2(col)))
42             else:
43                 connector = not first and ', ' or ''
44-                result.append('%s%s%s' % (connector, qn(name), alias_str))
45+                where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias)
46+                if not where and first and with_limits and (self.high_mark or self.low_mark) and len(self.tables) > 1:
47+                    self.outer_limits = False
48+                    result.append('(SELECT * FROM %s' % qn(name))
49+                    if self.high_mark is not None:
50+                        result.append('LIMIT %d' % (self.high_mark - self.low_mark))
51+                    if self.low_mark:
52+                        if self.high_mark is None:
53+                            val = self.connection.ops.no_limit_value()
54+                            if val:
55+                                result.append('LIMIT %d' % val)
56+                        result.append('OFFSET %d' % self.low_mark)
57+                    my_alias = alias_str
58+                    if not my_alias:
59+                        my_alias = name
60+                    result.append(') %s' % qn(my_alias))
61+                    #assert False, result
62+                else:
63+                    result.append('%s%s%s' % (connector, qn(name), alias_str))
64             first = False
65         for t in self.extra_tables:
66             alias, unused = self.table_alias(t)