For-upstream: maybe
Website: http://code.djangoproject.com/ticket/10099
diff a/db/backends/__init__.py b/db/backends/__init__.py
a
|
b
|
|
81 | 81 | # If True, don't use integer foreign keys referring to, e.g., positive |
82 | 82 | # integer primary keys. |
83 | 83 | related_fields_match_type = False |
| 84 | allow_limit_in_in_subquery = True |
84 | 85 | |
85 | 86 | class BaseDatabaseOperations(object): |
86 | 87 | """ |
diff a/db/backends/mysql/base.py b/db/backends/mysql/base.py
a
|
b
|
|
112 | 112 | update_can_self_select = False |
113 | 113 | allows_group_by_pk = True |
114 | 114 | related_fields_match_type = True |
| 115 | allow_limit_in_in_subquery = False |
115 | 116 | |
116 | 117 | class DatabaseOperations(BaseDatabaseOperations): |
117 | 118 | def date_extract_sql(self, lookup_type, field_name): |
diff a/db/models/fields/__init__.py b/db/models/fields/__init__.py
a
|
b
|
|
193 | 193 | |
194 | 194 | def get_db_prep_lookup(self, lookup_type, value): |
195 | 195 | "Returns field's value prepared for database lookup." |
| 196 | def pk_trace(value): |
| 197 | # Value may be a primary key, or an object held in a relation. |
| 198 | # If it is an object, then we need to get the primary key value for |
| 199 | # that object. In certain conditions (especially one-to-one relations), |
| 200 | # the primary key may itself be an object - so we need to keep drilling |
| 201 | # down until we hit a value that can be used for a comparison. |
| 202 | v, field = value, None |
| 203 | try: |
| 204 | while True: |
| 205 | v, field = getattr(v, v._meta.pk.name), v._meta.pk |
| 206 | except AttributeError: |
| 207 | pass |
| 208 | if field: |
| 209 | if lookup_type in ('range', 'in'): |
| 210 | v = [v] |
| 211 | v = field.get_db_prep_lookup(lookup_type, v) |
| 212 | if isinstance(v, list): |
| 213 | v = v[0] |
| 214 | return v |
196 | 215 | if hasattr(value, 'as_sql'): |
197 | 216 | # If the value has a relabel_aliases method, it will need to |
198 | 217 | # be invoked before the final SQL is evaluated |
199 | 218 | if hasattr(value, 'relabel_aliases'): |
200 | 219 | return value |
| 220 | if lookup_type == 'in': |
| 221 | query_uses_limit = value.query.high_mark is not None or \ |
| 222 | value.query.low_mark |
| 223 | if query_uses_limit and \ |
| 224 | not connection.features.allow_limit_in_in_subquery: |
| 225 | ret = map(pk_trace, value) |
| 226 | value.value_annotation = bool(ret) |
| 227 | return ret |
201 | 228 | sql, params = value.as_sql() |
202 | 229 | return QueryWrapper(('(%s)' % sql), params) |
203 | 230 | |
diff a/db/models/fields/related.py b/db/models/fields/related.py
a
|
b
|
|
145 | 145 | # be invoked before the final SQL is evaluated |
146 | 146 | if hasattr(value, 'relabel_aliases'): |
147 | 147 | return value |
| 148 | if lookup_type == 'in': |
| 149 | query_uses_limit = value.query.high_mark is not None or \ |
| 150 | value.query.low_mark |
| 151 | if query_uses_limit and \ |
| 152 | not connection.features.allow_limit_in_in_subquery: |
| 153 | ret = map(pk_trace, value) |
| 154 | value.value_annotation = bool(ret) |
| 155 | return ret |
148 | 156 | sql, params = value.as_sql() |
149 | 157 | return QueryWrapper(('(%s)' % sql), params) |
150 | 158 | |