You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

49 lines
1.3 KiB

require 'active_record'
class Carto::VisualizationQuerySearcher
PATTERN_ESCAPE_CHARS = ['_', '%'].freeze
def initialize(query)
@query = query
end
def search(tainted_search_pattern)
search_pattern = escape_characters_from_pattern(tainted_search_pattern)
@query.where(partial_match_sql, search_pattern, "%#{search_pattern}%")
.order("#{rank_sql(search_pattern)} DESC, visualizations.updated_at DESC")
end
private
def escape_characters_from_pattern(pattern)
pattern.chars.map { |c| PATTERN_ESCAPE_CHARS.include?(c) ? "\\" + c : c }.join
end
def tsvector
%{
setweight(to_tsvector('english', coalesce("visualizations"."name",'')), 'A') ||
setweight(to_tsvector('english', coalesce(array_to_string(visualizations.tags, ''),'')), 'B') ||
setweight(to_tsvector('english', coalesce("visualizations"."description",'')), 'C')
}
end
def rank_sql(search_pattern)
%{
ts_rank(
#{tsvector},
plainto_tsquery('english', #{ActiveRecord::Base.sanitize(search_pattern)})
)
}.squish
end
def partial_match_sql
%{
#{tsvector} @@ plainto_tsquery('english', ?)
OR CONCAT("visualizations"."name", array_to_string(visualizations.tags, ''), "visualizations"."description")
ILIKE ?
}.squish
end
end