Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed select_related performance regressions

The regression was caused by select_related fix for Oracle, commit
c159d9c.
  • Loading branch information...
commit ebcf6b36ffa7ee20b7219d34200b093186befcb4 1 parent ce1af8d
@akaariai akaariai authored
Showing with 18 additions and 20 deletions.
  1. +7 −4 django/db/models/options.py
  2. +11 −16 django/db/models/query.py
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
27 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,26 +1423,17 @@ 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
+ # If the pk column is None (or the Oracle equivalent ''), then the related
# object must be non-existent - set the relation to None.
- # 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:
Please sign in to comment.
Something went wrong with that request. Please try again.