PERF: Don't use unaccent on string literals (#28120)

unaccent isn't marked as a pure function, so it gets evaluated per row
instead of once.
This commit is contained in:
Daniel Waterworth 2024-07-29 15:37:25 -05:00 committed by GitHub
parent b44190307f
commit 1a95543e93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -71,8 +71,16 @@ class Search
end end
end end
def self.wrap_unaccent(str) def self.unaccent(str)
SiteSetting.search_ignore_accents ? "unaccent(#{str})" : str if SiteSetting.search_ignore_accents
DB.query("SELECT unaccent(:str)", str: str)[0].unaccent
else
str
end
end
def self.wrap_unaccent(expr)
SiteSetting.search_ignore_accents ? "unaccent(#{expr})" : expr
end end
def self.segment_chinese? def self.segment_chinese?
@ -859,9 +867,9 @@ class Search
FROM topic_tags tt, tags FROM topic_tags tt, tags
WHERE tt.tag_id = tags.id WHERE tt.tag_id = tags.id
GROUP BY tt.topic_id GROUP BY tt.topic_id
HAVING to_tsvector(#{default_ts_config}, #{Search.wrap_unaccent("array_to_string(array_agg(lower(tags.name)), ' ')")}) @@ to_tsquery(#{default_ts_config}, #{Search.wrap_unaccent("?")}) HAVING to_tsvector(#{default_ts_config}, #{Search.wrap_unaccent("array_to_string(array_agg(lower(tags.name)), ' ')")}) @@ to_tsquery(#{default_ts_config}, ?)
)", )",
tags.join("&"), Search.unaccent(tags.join("&")),
) )
else else
tags = match.split(",") tags = match.split(",")
@ -1360,7 +1368,7 @@ class Search
def self.to_tsquery(ts_config: nil, term:, joiner: nil) def self.to_tsquery(ts_config: nil, term:, joiner: nil)
ts_config = ActiveRecord::Base.connection.quote(ts_config) if ts_config ts_config = ActiveRecord::Base.connection.quote(ts_config) if ts_config
escaped_term = wrap_unaccent("'#{escape_string(term)}'") escaped_term = "'#{escape_string(unaccent(term))}'"
tsquery = "TO_TSQUERY(#{ts_config || default_ts_config}, #{escaped_term})" tsquery = "TO_TSQUERY(#{ts_config || default_ts_config}, #{escaped_term})"
# PG 14 and up default to using the followed by operator # PG 14 and up default to using the followed by operator
# this restores the old behavior # this restores the old behavior