-
Notifications
You must be signed in to change notification settings - Fork 897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes custom_attribute virtual_attributes to support AREL/SQL #17615
Changes custom_attribute virtual_attributes to support AREL/SQL #17615
Conversation
Test failures seem to be from these changes... but I will look at it tomorrow... it's late... |
8941a96
to
90a1505
Compare
app/models/miq_report/generator.rb
Outdated
@@ -307,6 +307,13 @@ def generate_basic_results(options = {}) | |||
# TODO: add once only_cols is fixed | |||
# targets = targets.select(only_cols) | |||
where_clause = MiqExpression.merge_where_clauses(self.where_clause, options[:where_clause]) | |||
|
|||
# Remove custom_attributes as part of the `inlcudes` if all of them exist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
includes ☝️
app/models/miq_report/generator.rb
Outdated
|
||
# Remove custom_attributes as part of the `inlcudes` if all of them exist | ||
# in the select statement | ||
if all_custom_attributes_in_select? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like all_custom_attributes_are_virtual?
ca_sym = custom_attribute.to_sym | ||
without_prefix = custom_attribute.sub(CUSTOM_ATTRIBUTES_PREFIX, "") | ||
name_val, section = without_prefix.split(SECTION_SEPARATOR) | ||
ca_db_col = custom_attribute.tr('.', 'DOT').tr('/', 'BS').tr(':', 'CLN') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanitized_column_alias
maybe?
LGTM other than some nits. @kbrock can you approve of the arel changes? I don't have my arel dictionary with me. |
@NickLaMuro was there a test covering this? |
90a1505
to
41d0e2a
Compare
@jrafanie yeah, this gets exercised with some of the tests here: manageiq/spec/models/miq_report_spec.rb Lines 100 to 110 in 362b5ff
These were the tests that were failing when I mentioned them failing on CI here: #17615 (comment) |
@kbrock mind weighing in on this PR? |
Pretty sure these are sporadic test failures. Going to kick travis to confirm. |
https://bugzilla.redhat.com/show_bug.cgi?id=1592480 This method is responsible for checking if the virtual_attributes in the Rbac query will contain all of the custom_attributes virtual_attributes. To be used to determine if we can safely remove: { :custom_attributes => {} } From the `include` hash on MiqReport, avoiding needing to load a lot of records.
https://bugzilla.redhat.com/show_bug.cgi?id=1592480 Conditionally removes `:custom_attributes => {}` from the includes clause if all of the `custom_attribute` columns happen to be in the select statement (the `@va_sql_cols` value). When the `custom_attribute` `virtual_attributes` can be converted to Arel, this will have some value, but for now this will mostly do nothing
https://bugzilla.redhat.com/show_bug.cgi?id=1592480 This change allows `custom_attributes` to be accessible via SQL. Most of the additions are found in the `custom_attribute_arel`, included by `CustomAttributeMixin`, and will simply generate the Arel equivalent necessary for determined the `virtual_attribute` value via SQL. Other notable changes: - The method defined for accessing the `virtual_attribute` from the instance will now check the attributes hash prior to executing the rest of the method, and return something if it has a key - Some shared values calculated in both the method definition and would be in the `custom_attribute_arel` method have been extracted out so it is only calculated once (minor performance benefit).
41d0e2a
to
065405d
Compare
Checked commits NickLaMuro/manageiq@0ad75c2~...065405d with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very sweet.
Just the 1 concern.
define_method(custom_attribute.to_sym) do | ||
custom_attribute_without_prefix = custom_attribute.sub(CUSTOM_ATTRIBUTES_PREFIX, "") | ||
custom_attribute_without_section, section = custom_attribute_without_prefix.split(SECTION_SEPARATOR) | ||
virtual_column(ca_sym, :type => :string, :uses => :custom_attributes, :arel => ca_arel) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the trend is to always define the uses even with arel (as you have here)
Could we remove the :uses
from the virtual_column
and get rid of the remove_loading_relations_for_virtual_custom_attributes?
?
(speculation here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we can't remove the remove_loading_relations_for_virtual_custom_attributes
.
The remove_loading_relations_for_virtual_custom_attributes
is making sure we don't have a :custom_attributes =>{}
in the include
of the report, which will get added to the .includes
and .references
in Rbac, causing the join bomb we were observing.
The :custom_attributes =>{}
is also added via remove_loading_relations_for_virtual_custom_attributes
's sister method, add_includes_for_virtual_custom_attributes
, and that is only call as part of of the controller in the UI prior to saving the record.
The call to remove_loading_relations_for_virtual_custom_attributes
is making sure we don't get that LEFT JOIN
happening in the query, while the rest of the PR is avoiding not introducing an N+1 as a result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding :uses
, unsure if keeping it has any value, though not really sure it hurts. Don't care either way though.
return self[sanatized_column_alias] if has_attribute?(sanatized_column_alias) | ||
|
||
where_args = {} | ||
where_args[:name] = name_val |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
where_args = {:name => name_val}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't write this originally, just updated the variable name. Just left it the same as it was.
# in the select statement | ||
if all_custom_attributes_are_virtual_sql_attributes? | ||
remove_loading_relations_for_virtual_custom_attributes | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to understand this more:
def _generate_table
if ...
4 generate_* methods
else
generate_basic_results # A
end
build_table # B
end
This change adds remove_loading_relations_for_virtual_custom_attributes
A (optionally).
build_table
always calls remove_loading_relations_for_virtual_custom_attributes
.
- Do we need to consider using that method for other
generate_*
methods? - Do we need to make it optional in
build_table
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Do we need to consider using that method for other
generate_*
methods?
Possibly, though not the priority for this BZ. Should function still without it at the moment, and I think the way we gather results for reports is vastly different in each of those methods, so I think waiting to do that makes sense for this PR.
2. Do we need to make it optional in build_table?
No, this should be idempotent to remove the value from the include
hash. It is not saving the record with it removed anyway, so we are just removing it earlier than originally planed.
where_args[:section] = section if section | ||
|
||
custom_attributes.find_by(where_args).try(:value) | ||
end | ||
end | ||
|
||
def self.custom_attribute_arel(name_val, section, column_alias) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nicely done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😊
@miq-bot add_labels fine/yes, gaprindashvili/yes |
Backported to Gaprindashvili via #17629 |
Backported #17629 to Fine branch. |
Converts the
virtual_column
definitions inCustomAttributeMixin
to support thearel
attribute, and allowMiqReport#generate
to take advantage of this, and avoid needing an extra include.Other notable changes:
custom_attributes
have arel backedvirtual_attribute
(akavirtual_column
) methods, then the includes of:custom_attributes => {}
will be removed from theRbac
query. A helper method was added to assist with thisvirtual_attribute
from the instance will now check the attributes hash prior to executing the rest of the method, and return something if it has a keyvirtual_attribute
method definition and would be in thecustom_attribute_arel
method have been extracted out so it is only calculated once (minor performance benefit).Benchmarks
These benchmarks are currently a work in progress, and contain some incomplete data. Most of those inconsistencies are noted in below.
Tested on a local machine with the DB running on the same machine, so next to no network based latency for queries is observed.
Before
50 uniq query types executed. 212961 are just the N+1 fetching
custom_attributes
Raw
Benchmark.measure
numbers:After
While that patch was present during the benchmarks, most of what is done in this patch negates it's usefulness, so almost everything seeing here is from the changes in this pull request.
NOTE: 10141 of the total queries and ~3580ms of the
query (ms)
here areINSERT
statements intomiq_report_result_details
.Raw
Benchmark.measure
numbers:Links