Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: django/django
...
head fork: akaariai/django
compare: ticket_19276
Checking mergeability… Don’t worry, you can still create the pull request.
  • 3 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Nov 13, 2012
@akaariai akaariai Some changes to SortedDict to make it faster under py2
Refs #19276
1973fd5
@akaariai akaariai Removed use of SortedDict for query.alias_refcount
This will have a smallish impact on performance. Refs #19276.
732fc75
@akaariai akaariai Fixed select_related performance regressions
The regression was caused by select_related fix for Oracle, commit
c159d9c.
27163e8
View
11 django/db/models/options.py
@@ -9,11 +9,10 @@
from django.db.models.fields import AutoField, FieldDoesNotExist
from django.db.models.fields.proxy import OrderWrt
from django.db.models.loading import get_models, app_cache_ready
-from django.utils.translation import activate, deactivate_all, get_language, string_concat
-from django.utils.encoding import force_text, smart_text
-from django.utils.datastructures import SortedDict
from django.utils import six
-from django.utils.encoding import python_2_unicode_compatible
+from django.utils.datastructures import SortedDict
+from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
+from django.utils.translation import activate, deactivate_all, get_language, string_concat
# Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
@@ -175,6 +174,10 @@ def setup_pk(self, field):
self.pk = field
field.serialize = False
+ def pk_index(self):
+ return [pos for pos, field in enumerate(self.fields)
+ if field == self.pk][0]
+
def setup_proxy(self, target):
"""
Does the internal setup so that the current model is a proxy for
View
22 django/db/models/query.py
@@ -1395,8 +1395,12 @@ def get_klass_info(klass, max_depth=0, cur_depth=0, requested=None,
klass_info = get_klass_info(o.model, max_depth=max_depth, cur_depth=cur_depth+1,
requested=next, only_load=only_load, local_only=True)
reverse_related_fields.append((o.field, klass_info))
+ if field_names:
+ pk_idx = field_names.index(klass._meta.pk.attname)
+ else:
+ pk_idx = klass._meta.pk_index()
- return klass, field_names, field_count, related_fields, reverse_related_fields
+ return klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx
def get_cached_row(row, index_start, using, klass_info, offset=0):
@@ -1419,7 +1423,7 @@ def get_cached_row(row, index_start, using, klass_info, offset=0):
"""
if klass_info is None:
return None
- klass, field_names, field_count, related_fields, reverse_related_fields = klass_info
+ klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx = klass_info
fields = row[index_start : index_start + field_count]
# If all the select_related columns are None, then the related
@@ -1427,18 +1431,12 @@ def get_cached_row(row, index_start, using, klass_info, offset=0):
# Otherwise, construct the related object. Also, some backends treat ''
# and None equivalently for char fields, so we have to be prepared for
# '' values.
- if connections[using].features.interprets_empty_strings_as_nulls:
- vals = tuple([None if f == '' else f for f in fields])
- else:
- vals = fields
-
- if vals == (None,) * field_count:
+ if fields[pk_idx] == None or fields[pk_idx] == '':
obj = None
+ elif field_names:
+ obj = klass(**dict(zip(field_names, fields)))
else:
- if field_names:
- obj = klass(**dict(zip(field_names, fields)))
- else:
- obj = klass(*fields)
+ obj = klass(*fields)
# If an object was retrieved, set the database state.
if obj:
View
10 django/db/models/sql/query.py
@@ -103,7 +103,7 @@ class Query(object):
def __init__(self, model, where=WhereNode):
self.model = model
- self.alias_refcount = SortedDict()
+ self.alias_refcount = {}
# alias_map is the most important data structure regarding joins.
# It's used for recording which joins exist in the query and what
# type they are. The key is the alias of the joined table (possibly
@@ -860,7 +860,7 @@ def count_active_tables(self):
count. Note that after execution, the reference counts are zeroed, so
tables added in compiler will not be seen by this method.
"""
- return len([1 for count in six.itervalues(self.alias_refcount) if count])
+ return len([1 for count in self.alias_refcount.values() if count])
def join(self, connection, reuse=REUSE_ALL, promote=False,
outer_if_first=False, nullable=False):
@@ -1532,9 +1532,9 @@ def split_exclude(self, filter_expr, prefix, can_reuse):
# comparison to NULL (e.g. in
# Tag.objects.exclude(parent__parent__name='t1'), a tag with no parent
# would otherwise be overlooked).
- active_positions = [pos for (pos, count) in
- enumerate(six.itervalues(query.alias_refcount)) if count]
- if active_positions[-1] > 1:
+ active_positions = len([count for count
+ in query.alias_refcount.items() if count])
+ if active_positions > 1:
self.add_filter(('%s__isnull' % prefix, False), negate=True,
trim=True, can_reuse=can_reuse)
View
33 django/utils/datastructures.py
@@ -1,6 +1,5 @@
import copy
import warnings
-from types import GeneratorType
from django.utils import six
@@ -120,27 +119,23 @@ def __new__(cls, *args, **kwargs):
return instance
def __init__(self, data=None):
- if data is None:
- data = {}
- elif isinstance(data, GeneratorType):
- # Unfortunately we need to be able to read a generator twice. Once
- # to get the data into self with our super().__init__ call and a
- # second time to setup keyOrder correctly
- data = list(data)
- super(SortedDict, self).__init__(data)
- if isinstance(data, dict):
- self.keyOrder = list(data)
+ if data is None or isinstance(data, dict):
+ data = data or []
+ super(SortedDict, self).__init__(data)
+ self.keyOrder = list(data) if data else []
else:
- self.keyOrder = []
- seen = set()
+ super(SortedDict, self).__init__()
+ super_set = super(SortedDict, self).__setitem__
for key, value in data:
- if key not in seen:
+ # Take the ordering from first key
+ if key not in self:
self.keyOrder.append(key)
- seen.add(key)
+ # But override with last value in data (dict() does this)
+ super_set(key, value)
def __deepcopy__(self, memo):
return self.__class__([(key, copy.deepcopy(value, memo))
- for key, value in six.iteritems(self)])
+ for key, value in self.items()])
def __copy__(self):
# The Python's default copy implementation will alter the state
@@ -199,13 +194,13 @@ def _itervalues(self):
itervalues = _itervalues
def items(self):
- return list(self.iteritems())
+ return [(k, self[k]) for k in self.keyOrder]
def keys(self):
- return list(self.iterkeys())
+ return self.keyOrder[:]
def values(self):
- return list(self.itervalues())
+ return [self[k] for k in self.keyOrder]
def update(self, dict_):
for k, v in six.iteritems(dict_):

No commit comments for this range

Something went wrong with that request. Please try again.