Fixed select_related performance regressions
The regression was caused by select_related fix for Oracle, commit
c159d9cec0
.
This commit is contained in:
parent
ce1af8d702
commit
ebcf6b36ff
|
@ -9,11 +9,10 @@ from django.db.models.fields.related import ManyToManyRel
|
||||||
from django.db.models.fields import AutoField, FieldDoesNotExist
|
from django.db.models.fields import AutoField, FieldDoesNotExist
|
||||||
from django.db.models.fields.proxy import OrderWrt
|
from django.db.models.fields.proxy import OrderWrt
|
||||||
from django.db.models.loading import get_models, app_cache_ready
|
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 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".
|
# 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()
|
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 @@ class Options(object):
|
||||||
self.pk = field
|
self.pk = field
|
||||||
field.serialize = False
|
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):
|
def setup_proxy(self, target):
|
||||||
"""
|
"""
|
||||||
Does the internal setup so that the current model is a proxy for
|
Does the internal setup so that the current model is a proxy for
|
||||||
|
|
|
@ -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,
|
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)
|
requested=next, only_load=only_load, local_only=True)
|
||||||
reverse_related_fields.append((o.field, klass_info))
|
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):
|
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:
|
if klass_info is None:
|
||||||
return 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]
|
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.
|
# object must be non-existent - set the relation to None.
|
||||||
# Otherwise, construct the related object. Also, some backends treat ''
|
if fields[pk_idx] == None or fields[pk_idx] == '':
|
||||||
# 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:
|
|
||||||
obj = None
|
obj = None
|
||||||
|
elif field_names:
|
||||||
|
obj = klass(**dict(zip(field_names, fields)))
|
||||||
else:
|
else:
|
||||||
if field_names:
|
obj = klass(*fields)
|
||||||
obj = klass(**dict(zip(field_names, fields)))
|
|
||||||
else:
|
|
||||||
obj = klass(*fields)
|
|
||||||
|
|
||||||
# If an object was retrieved, set the database state.
|
# If an object was retrieved, set the database state.
|
||||||
if obj:
|
if obj:
|
||||||
|
|
Loading…
Reference in New Issue