X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/9ec15072e6631578584bd9c08d26025e807a8d48..0f537bcaa60b8a1496010bc9d4a943484e69081c:/services/api/lib/record_filters.rb?ds=sidebyside diff --git a/services/api/lib/record_filters.rb b/services/api/lib/record_filters.rb index 900b784cd0..c8f024291c 100644 --- a/services/api/lib/record_filters.rb +++ b/services/api/lib/record_filters.rb @@ -44,6 +44,14 @@ module RecordFilters cond_out = [] + if attrs_in == 'any' && (operator.casecmp('ilike').zero? || operator.casecmp('like').zero?) && (operand.is_a? String) && operand.match('^[%].*[%]$') + # Trigram index search + cond_out << model_class.full_text_trgm + " #{operator} ?" + param_out << operand + # Skip the generic per-column operator loop below + attrs = [] + end + if operator == '@@' # Full-text search if attrs_in != 'any' @@ -66,15 +74,15 @@ module RecordFilters col = model_class.columns.select { |c| c.name == subproperty[0] }.first if subproperty.length == 2 - if col.type != :jsonb - raise ArgumentError.new("Invalid attribute '#{subproperty[0]}' for operator '#{operator}' in filter") + if col.nil? or col.type != :jsonb + raise ArgumentError.new("Invalid attribute '#{subproperty[0]}' for subproperty filter") end if subproperty[1][0] == "<" and subproperty[1][-1] == ">" subproperty[1] = subproperty[1][1..-2] end - # jsonb search + # jsonb search case operator.downcase when '=', '!=' not_in = if operator.downcase == "!=" then "NOT " else "" end @@ -109,12 +117,14 @@ module RecordFilters "for '#{operator}' operator in filters") end when 'exists' - if operand - cond_out << "jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)" - else - cond_out << "(NOT jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)) OR #{ar_table_name}.#{subproperty[0]} is NULL" - end - param_out << subproperty[1] + if operand == true + cond_out << "jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)" + elsif operand == false + cond_out << "(NOT jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)) OR #{ar_table_name}.#{subproperty[0]} is NULL" + else + raise ArgumentError.new("Invalid operand '#{operand}' for '#{operator}' must be true or false") + end + param_out << subproperty[1] else raise ArgumentError.new("Invalid operator for subproperty search '#{operator}'") end @@ -195,8 +205,17 @@ module RecordFilters operand.each do |op| cl = ArvadosModel::kind_class op if cl - cond << "#{ar_table_name}.#{attr} like ?" - param_out << cl.uuid_like_pattern + if attr == 'uuid' + if model_class.uuid_prefix == cl.uuid_prefix + cond << "1=1" + else + cond << "1=0" + end + else + # Use a substring query to support remote uuids + cond << "substring(#{ar_table_name}.#{attr}, 7, 5) = ?" + param_out << cl.uuid_prefix + end else cond << "1=0" end