From 361e82313648c321f563adb67d9815103a8b8a95 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Thu, 28 Mar 2024 23:23:21 -0400 Subject: [PATCH] MiqExpression#preprocess_exp for more cases still work even if :token is the first key in the exp still process find sub targets this gets us more values with field-field --- lib/miq_expression.rb | 69 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/lib/miq_expression.rb b/lib/miq_expression.rb index c7bb3c4d9a7..cc08e4f3975 100644 --- a/lib/miq_expression.rb +++ b/lib/miq_expression.rb @@ -303,19 +303,16 @@ def self._to_ruby(exp, context_type, tz) clause, = operands2rubyvalue(operator, op_args, context_type) when "is" col_ruby, _value = operands2rubyvalue(operator, {"field" => col_name}, context_type) - col_type = Target.parse(col_name).column_type value = op_args["value"] - clause = if col_type == :date && !RelativeDatetime.relative?(value) - ruby_for_date_compare(col_ruby, col_type, tz, "==", value) + clause = if field.date? && !RelativeDatetime.relative?(value) + ruby_for_date_compare(col_ruby, field.column_type, tz, "==", value) else - ruby_for_date_compare(col_ruby, col_type, tz, ">=", value, "<=", value) + ruby_for_date_compare(col_ruby, field.column_type, tz, ">=", value, "<=", value) end when "from" col_ruby, _value = operands2rubyvalue(operator, {"field" => col_name}, context_type) - col_type = Target.parse(col_name).column_type - start_val, end_val = op_args["value"] - clause = ruby_for_date_compare(col_ruby, col_type, tz, ">=", start_val, "<=", end_val) + clause = ruby_for_date_compare(col_ruby, field.column_type, tz, ">=", start_val, "<=", end_val) else raise _("operator '%{operator_name}' is not supported") % {:operator_name => operator.upcase} end @@ -335,30 +332,42 @@ def to_sql(tz = nil) end def preprocess_exp(exp) - operator = exp.keys.first - operator_values = exp[operator] - case operator.downcase - when "and", "or" - operator_values = operator_values.map { |atom| preprocess_exp(atom) } - when "not", "!" - operator_values = preprocess_exp(operator_values) - else # field - # {"regkey"=>"foo", "regval"=>"bar", "value"=>"baz"} - # {"field" => "foo", "value" => "baz"} - # {"count" => "Vm.snapshots", "value"=>"1"} - # {"tag"=>"Host.managed-environment", "value"=>"prod"} - operator_values = operator_values.dup - field = operator_values["field"] - field_field = operator_values["field-field"] = Field.parse(field) if field - value = operator_values["value"] - operator_values["value-field"] = Field.parse(value) if value - - # attempt to do conversion only if db type of column is integer and value to compare to is String - if %w[= != <= >= > <].include?(operator) && field_field&.integer? && value.class == String - operator_values["value"] = convert_size_in_units_to_integer(field, field_field.sub_type, value) - end + exp.each_with_object({}) do |(operator, operator_values), new_exp| + next if operator == :token + + new_exp[operator] = + case operator.downcase + when "and", "or" + # "and" => [exp, exp, exp] + operator_values.map { |atom| preprocess_exp(atom) } + when "not", "!" + # "not" => exp + preprocess_exp(operator_values) + when "find" + # "find" => {"search" => exp, "checkall" => exp} + operator_values.each_with_object({}) { |(op2, op_values2), hash| hash[op2] = preprocess_exp(op_values2) } + else + # op => {"regkey"=>"foo", "regval"=>"bar", "value"=>"baz"} + # op => {"field" => "foo", "value" => "baz"} + # op => {"count" => "Vm.snapshots", "value"=>"1"} + # op => {"tag"=>"Host.managed-environment", "value"=>"prod"} + operator_values = operator_values.dup + field = operator_values["field"] + if field + field_field = operator_values["field-field"] = Field.parse(field) + end + value = operator_values["value"] + if value + value_field = operator_values["value-field"] = Field.parse(value) + end + + # attempt to do conversion only if db type of column is integer and value to compare to is String + if %w[= != <= >= > <].include?(operator) && field_field&.integer? && value.class == String + operator_values["value"] = convert_size_in_units_to_integer(field, field_field.sub_type, value) + end + operator_values + end end - {operator => operator_values} end # @param operator [String] operator (i.e.: AND, OR, NOT)