Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrock committed Apr 12, 2024
1 parent e8cf212 commit 5f7d944
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
2 changes: 2 additions & 0 deletions app/models/condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def self.conditions
pluck(:expression)
end

# TODO: don't pass attr (or create 2 different methods)
def self.evaluate(cond, rec, _inputs = {}, attr = :expression)
expression = cond.send(attr)
name = cond.try(:description) || cond.try(:name)
Expand All @@ -65,6 +66,7 @@ def self.evaluate(cond, rec, _inputs = {}, attr = :expression)
result = false if expression["include"] == "all"
end
end
# TODO: drop tag_expr support
when "tag_expr", "tag_expr_v2", "object"
expr = case mode
when "tag_expr"
Expand Down
28 changes: 25 additions & 3 deletions lib/miq_expression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,14 @@ def self._to_human(exp, options = {})
clause = "#{operands.first} #{operator} #{operands.last}"
when "between dates", "between times"
col_name = exp[operator]["field"]
# NOTE: Since to_human does not pre-processed, field-field is not available
col_type = Target.parse(col_name).column_type
col_human, _value = operands2humanvalue(exp[operator], options)
vals_human = exp[operator]["value"].collect { |v| quote_human(v, col_type) }
clause = "#{col_human} #{operator} #{vals_human.first} AND #{vals_human.last}"
when "from"
col_name = exp[operator]["field"]
# NOTE: Since to_human does not pre-processed, field-field is not available
col_type = Target.parse(col_name).column_type
col_human, _value = operands2humanvalue(exp[operator], options)
vals_human = exp[operator]["value"].collect { |v| quote_human(v, col_type) }
Expand Down Expand Up @@ -190,11 +192,14 @@ def self._to_ruby(exp, context_type, tz)
clause = operands.join(" #{normalize_ruby_operator(operator)} ")
when "before"
col_type = Target.parse(col_name).column_type if col_name
# TODO: verify there are tests here (so then we can verify field-field is present)
# byebug if col_name && !field
col_ruby, _value = operands2rubyvalue(operator, {"field" => col_name}, context_type)
val = op_args["value"]
clause = ruby_for_date_compare(col_ruby, col_type, tz, "<", val)
when "after"
col_type = Target.parse(col_name).column_type if col_name
byebug if col_name && !field
col_ruby, _value = operands2rubyvalue(operator, {"field" => col_name}, context_type)
val = op_args["value"]
clause = ruby_for_date_compare(col_ruby, col_type, tz, nil, nil, ">", val)
Expand Down Expand Up @@ -250,6 +255,7 @@ def self._to_ruby(exp, context_type, tz)
when "contains"
op_args["tag"] ||= col_name
operands = if context_type != "hash"
# TODO: op_args["tag-field"]
target = Target.parse(op_args["tag"])
["<exist ref=#{target.model.to_s.downcase}>#{target.tag_path_with(op_args["value"])}</exist>"]
elsif context_type == "hash"
Expand Down Expand Up @@ -318,6 +324,7 @@ def to_sql(tz = nil)
[nil, nil, {:supported_by_sql => false}]
end

# TODO: new_exp[operator.downcase] =
def preprocess_exp(exp)
exp.each_with_object({}) do |(operator, operator_values), new_exp|
next if operator == :token
Expand All @@ -331,7 +338,12 @@ def preprocess_exp(exp)
# "not" => exp
preprocess_exp(operator_values)
when "find"
# "find" => {"search" => exp, "checkall" => exp}
ops = operator_values.keys
searchop, checkop = ops.partition { |op| op.downcase == "search" }.map(&:first)
unless ops.size == 2 && searchop && %w[checkall checkany checkcount].include?(checkop.downcase)
raise(InvalidExpression, "expecting find to have search and a check* node")
end
# TODO: raise(InvalidExpression, "invalid count node") unless operator_values["checkcount"][op][*]["field"] == "<count>"
operator_values.each_with_object({}) { |(op2, op_values2), hash| hash[op2] = preprocess_exp(op_values2) }
else
# op => {"regkey"=>"foo", "regval"=>"bar", "value"=>"baz"}
Expand All @@ -350,6 +362,10 @@ def preprocess_exp(exp)
value_field = operator_values["value-field"] = Field.parse(value)
raise(InvalidExpression, field) if value_field && !value_field.valid?
end
# count = operator_values["count"] ###
# operator_values["count-field"] = Field.parse(count) if count
# tag = operator_values["tag"]
# operator_values["tag-field"] = Field.parse(tag) if tag

# 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
Expand Down Expand Up @@ -521,6 +537,7 @@ def sql_supports_atom?(exp)
end
end

# value is not a field || it is a field that is sql friendly
def value_in_sql?(value_field)
!value_field&.valid? || value_field&.attribute_supported_by_sql?
end
Expand Down Expand Up @@ -627,6 +644,7 @@ def self.operands2humanvalue(ops, options = {})
else
col_type = Target.parse(ops["field"]).column_type
ret.push(quote_human(ops["value"], col_type))
# TODO?: ret.push(quote_human(ops["value"], ops["field-field"].column_type))
end
end
elsif ops["count"]
Expand Down Expand Up @@ -709,6 +727,7 @@ def self.operands2rubyvalue(operator, ops, context_type)
if ops["field"] == "<count>"
["<count>", quote(ops["value"], :integer)]
else
# TODO: ops["field-field"]
target = Target.parse(ops["field"])
col_type = target.column_type || :string

Expand All @@ -719,6 +738,7 @@ def self.operands2rubyvalue(operator, ops, context_type)
end, quote_by(operator, ops["value"], col_type)]
end
elsif ops["count"]
# TODO: ops["count-field"]
target = Target.parse(ops["count"])
["<count ref=#{target.model.to_s.downcase}>#{target.tag_path_with}</count>", quote(ops["value"], target.column_type)]
elsif ops["regkey"]
Expand All @@ -733,8 +753,9 @@ def self.operands2rubyvalue(operator, ops, context_type)
end

def self.quote(val, typ)
# TODO: pass in field - if !field.nil?
if Field.is_field?(val)
target = Target.parse(val)
target = Target.parse(val) # TODO: fix
value = target.tag_path_with
col_type = target.column_type || :string

Expand Down Expand Up @@ -1148,7 +1169,7 @@ def self.get_column_details(column_names, class_path, assoc_path, opts)
end.compact
end

def self.get_col_operators(field)
def self.get_col_operators(field) # TODO: pass in field
col_type =
if [:count, :regkey].include?(field)
field
Expand Down Expand Up @@ -1368,6 +1389,7 @@ def self.parse_field_or_tag(str)
end
Vmdb::Deprecation.deprecate_methods(self, :parse_field_or_tag => "MiqExpression::Target.parse")

# TODO: drop this and just use the fields in the expressoin
def fields(expression = exp)
case expression
when Array
Expand Down
6 changes: 4 additions & 2 deletions spec/lib/miq_expression_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3281,9 +3281,11 @@

context "when ops key is count" do
let(:ops) do
field = "ManageIQ::Providers::InfraManager::Vm.advanced_settings"
{
"count" => "ManageIQ::Providers::InfraManager::Vm.advanced_settings",
"value" => "foo"
"count" => field,
"count-field" => MiqExpression::Field.parse(field),
"value" => "foo"
}
end
include_examples :coerces_value_to_integer
Expand Down

0 comments on commit 5f7d944

Please sign in to comment.