attrs.each do |attr|
subproperty = attr.split(".", 2)
- if !model_class.searchable_columns(operator).index subproperty[0]
- raise ArgumentError.new("Invalid attribute '#{subproperty[0]}' in filter")
- end
+ col = model_class.columns.select { |c| c.name == subproperty[0] }.first
if subproperty.length == 2
- # jsonb search
+ 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
case operator.downcase
when '=', '!='
not_in = if operator.downcase == "!=" then "NOT " else "" end
raise ArgumentError.new("Invalid operand type '#{operand.class}' "\
"for '#{operator}' operator in filters")
end
- when 'exists', 'not exists'
- if operand
- raise ArgumentError.new("Invalid operand for subproperty existence filter, should be empty or null")
- end
- if operator.downcase[0..2] == "not" then
- cond_out << "(NOT jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)) OR #{ar_table_name}.#{subproperty[0]} is NULL"
- else
- cond_out << "jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)"
- end
- param_out << subproperty[1]
+ when 'exists'
+ 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
+ elsif operator.downcase == "exists"
+ if col.type != :jsonb
+ raise ArgumentError.new("Invalid attribute '#{subproperty[0]}' for operator '#{operator}' in filter")
+ end
+
+ cond_out << "jsonb_exists(#{ar_table_name}.#{subproperty[0]}, ?)"
+ param_out << operand
else
+ if !model_class.searchable_columns(operator).index subproperty[0]
+ raise ArgumentError.new("Invalid attribute '#{subproperty[0]}' in filter")
+ end
+
case operator.downcase
when '=', '<', '<=', '>', '>=', '!=', 'like', 'ilike'
attr_type = model_class.attribute_column(attr).type
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