Skip to content

Commit

Permalink
Get rid of double-join to rbac_entries without filter
Browse files Browse the repository at this point in the history
apply_filters_to_query was performing an outerjoin to rbac_entries
unconditionally when model_query could have already performed an
outerjoin (if the request was from an unprivileged user) and/or when
the join wasn't even necessary (the '?shared=False' query that uses
a subquery and not a join). This resulted in terrible performance
because of cartesian products of rbac entries with themselves.

This fixes the issue by ensuring there is only an outerjoin to the
rbac table if it's going to be used for a filter condition and it's
not already joined because of a query scope imposed due to the user
not being privileged.

Unfortunately this doesn't include tests to prevent regressions because
we don't have any methods for testing the performance of individual
queries.

Closes-Bug: #1630939
Change-Id: I4364f4a97a29041e86b2fbd8aa895578153f4cf9
(cherry picked from commit 145dbaa)
  • Loading branch information
kevinbenton committed Oct 11, 2016
1 parent 1575205 commit 369faa2
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion neutron/db/common_db_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ def _apply_filters_to_query(self, query, model, filters, context=None):
elif key == 'shared' and hasattr(model, 'rbac_entries'):
# translate a filter on shared into a query against the
# object's rbac entries
query = query.outerjoin(model.rbac_entries)
rbac = model.rbac_entries.property.mapper.class_
matches = [rbac.target_tenant == '*']
if context:
Expand All @@ -260,6 +259,12 @@ def _apply_filters_to_query(self, query, model, filters, context=None):
query.session.query(rbac.object_id).
filter(is_shared)
)
elif (not context or
not self.model_query_scope(context, model)):
# we only want to join if we aren't using the subquery
# and if we aren't already joined because this is a
# scoped query
query = query.outerjoin(model.rbac_entries)
query = query.filter(is_shared)
for _nam, hooks in six.iteritems(self._model_query_hooks.get(model,
{})):
Expand Down

0 comments on commit 369faa2

Please sign in to comment.