Created
October 16, 2012 20:59
-
-
Save anonymous/3902015 to your computer and use it in GitHub Desktop.
Django 1.4.1 SQL Hints Patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/db/models/query.py b/db/models/query.py | |
| index 44acadf..a241fbd 100644 | |
| --- a/db/models/query.py | |
| +++ b/db/models/query.py | |
| @@ -90,7 +90,7 @@ class QuerySet(object): | |
| return len(self._result_cache) | |
| def __iter__(self): | |
| - if self._prefetch_related_lookups and not self._prefetch_done: | |
| + if hasattr(self, "_prefetch_related_lookups") and self._prefetch_related_lookups and not self._prefetch_done: | |
| # We need all the results in order to be able to do the prefetch | |
| # in one go. To minimize code duplication, we use the __len__ | |
| # code path which also forces this, and also does the prefetch | |
| @@ -822,6 +822,14 @@ class QuerySet(object): | |
| clone._db = alias | |
| return clone | |
| + def with_hints(self, *args, **kwargs): | |
| + clone = self._clone() | |
| + for hint in args: | |
| + clone.query.add_hint(self.model, hint) | |
| + for model, hint in kwargs.items(): | |
| + clone.query.add_hint(model, hint) | |
| + return clone | |
| + | |
| ################################### | |
| # PUBLIC INTROSPECTION ATTRIBUTES # | |
| ################################### | |
| diff --git a/db/models/sql/compiler.py b/db/models/sql/compiler.py | |
| index 6c516e2..ca319e6 100644 | |
| --- a/db/models/sql/compiler.py | |
| +++ b/db/models/sql/compiler.py | |
| @@ -517,13 +517,22 @@ class SQLCompiler(object): | |
| # alias_map if they aren't in a join. That's OK. We skip them. | |
| continue | |
| alias_str = (alias != name and ' %s' % alias or '') | |
| + index_hint = '' | |
| + | |
| + for model, hint in self.query.hints.items(): | |
| + if model._meta.db_table == name: | |
| + index_hint = ' USE INDEX (%s)' % ', '.join(hint) | |
| + break | |
| + | |
| if join_type and not first: | |
| - result.append('%s %s%s ON (%s.%s = %s.%s)' | |
| - % (join_type, qn(name), alias_str, qn(lhs), | |
| - qn2(lhs_col), qn(alias), qn2(col))) | |
| + part = '%s %s%s%s ON (%s.%s = %s.%s)' \ | |
| + % (join_type, qn(name), alias_str, index_hint, qn(lhs), | |
| + qn2(lhs_col), qn(alias), qn2(col)) | |
| else: | |
| connector = not first and ', ' or '' | |
| - result.append('%s%s%s' % (connector, qn(name), alias_str)) | |
| + part = '%s%s%s' % (connector, qn(name), alias_str) | |
| + | |
| + result.append(part) | |
| first = False | |
| for t in self.query.extra_tables: | |
| alias, unused = self.query.table_alias(t) | |
| diff --git a/db/models/sql/query.py b/db/models/sql/query.py | |
| index ce11716..59a7e9d 100644 | |
| --- a/db/models/sql/query.py | |
| +++ b/db/models/sql/query.py | |
| @@ -95,6 +95,7 @@ class Query(object): | |
| alias_prefix = 'T' | |
| query_terms = QUERY_TERMS | |
| aggregates_module = base_aggregates_module | |
| + hints={} | |
| compiler = 'SQLCompiler' | |
| @@ -132,6 +133,7 @@ class Query(object): | |
| self.select_for_update_nowait = False | |
| self.select_related = False | |
| self.related_select_cols = [] | |
| + self.hints = {} | |
| # SQL aggregate-related attributes | |
| self.aggregates = SortedDict() # Maps alias -> SQL aggregate function | |
| @@ -1794,6 +1796,10 @@ class Query(object): | |
| if order_by: | |
| self.extra_order_by = order_by | |
| + def add_hint(self, model, hints): | |
| + for hint in hints: | |
| + add_to_dict(self.hints, hint["model"], hint["hint"]) | |
| + | |
| def clear_deferred_loading(self): | |
| """ | |
| Remove any fields from the deferred loading set. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment