X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/2de827e57ae9ba1b0d322199d071ae900a5b7e0c..6c91320c3a53ddbe1b81bee8ed6322c20acbd047:/services/api/lib/record_filters.rb diff --git a/services/api/lib/record_filters.rb b/services/api/lib/record_filters.rb index d3727d30f3..f31875b47d 100644 --- a/services/api/lib/record_filters.rb +++ b/services/api/lib/record_filters.rb @@ -30,22 +30,39 @@ module RecordFilters end case operator.downcase when '=', '<', '<=', '>', '>=', '!=', 'like' + attr_type = model_class.attribute_column(attr).type + operator = '<>' if operator == '!=' if operand.is_a? String - if operator == '!=' - operator = '<>' + if attr_type == :boolean + if not ['=', '<>'].include?(operator) + raise ArgumentError.new("Invalid operator '#{operator}' for " \ + "boolean attribute '#{attr}'") + end + case operand.downcase + when '1', 't', 'true', 'y', 'yes' + operand = true + when '0', 'f', 'false', 'n', 'no' + operand = false + else + raise ArgumentError("Invalid operand '#{operand}' for " \ + "boolean attribute '#{attr}'") + end end cond_out << "#{ar_table_name}.#{attr} #{operator} ?" if (# any operator that operates on value rather than # representation: - operator.match(/[<=>]/) and - model_class.attribute_column(attr).type == :datetime) + operator.match(/[<=>]/) and (attr_type == :datetime)) operand = Time.parse operand end param_out << operand elsif operand.nil? and operator == '=' cond_out << "#{ar_table_name}.#{attr} is null" - elsif operand.nil? and operator == '!=' + elsif operand.nil? and operator == '<>' cond_out << "#{ar_table_name}.#{attr} is not null" + elsif (attr_type == :boolean) and ['=', '<>'].include?(operator) and + [true, false].include?(operand) + cond_out << "#{ar_table_name}.#{attr} #{operator} ?" + param_out << operand else raise ArgumentError.new("Invalid operand type '#{operand.class}' "\ "for '#{operator}' operator in filters") @@ -54,6 +71,10 @@ module RecordFilters if operand.is_a? Array cond_out << "#{ar_table_name}.#{attr} #{operator} (?)" param_out << operand + if operator == 'not in' and not operand.include?(nil) + # explicitly allow NULL + cond_out[-1] = "(#{cond_out[-1]} OR #{ar_table_name}.#{attr} IS NULL)" + end else raise ArgumentError.new("Invalid operand type '#{operand.class}' "\ "for '#{operator}' operator in filters")