Skip to content

Commit 4a872c9

Browse files
committed
Prefer Arel to string interpolation in tsearch feature
1 parent 08df66a commit 4a872c9

File tree

4 files changed

+27
-31
lines changed

4 files changed

+27
-31
lines changed

lib/pg_search/features/feature.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def self.valid_options
1010
%i[only sort_only]
1111
end
1212

13-
delegate :connection, :quoted_table_name, to: :@model
13+
delegate :connection, :arel_table, to: :@model
1414

1515
def initialize(query, options, all_columns, model, normalizer)
1616
@query = query

lib/pg_search/features/tsearch.rb

+23-27
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ def self.valid_options
1212

1313
def conditions
1414
Arel::Nodes::Grouping.new(
15-
Arel::Nodes::InfixOperation.new("@@", arel_wrap(tsdocument), arel_wrap(tsquery))
15+
Arel::Nodes::InfixOperation.new("@@", tsdocument, tsquery)
1616
)
1717
end
1818

1919
def rank
20-
arel_wrap(tsearch_rank)
20+
Arel::Nodes::NamedFunction.new("ts_rank", [
21+
tsdocument,
22+
tsquery,
23+
normalization
24+
])
2125
end
2226

2327
def highlight
@@ -30,7 +34,7 @@ def ts_headline
3034
Arel::Nodes::NamedFunction.new("ts_headline", [
3135
dictionary,
3236
arel_wrap(document),
33-
arel_wrap(tsquery),
37+
tsquery,
3438
Arel::Nodes.build_quoted(ts_headline_options)
3539
]).to_sql
3640
end
@@ -131,29 +135,28 @@ def tsquery_expression(term_sql, negated:, prefix:)
131135
end
132136

133137
def tsquery
134-
return "''" if query.blank?
138+
return Arel::Nodes.build_quoted("") if query.blank?
135139

136140
query_terms = query.split.compact
137141
tsquery_terms = query_terms.map { |term| tsquery_for_term(term) }
138-
tsquery_terms.join(options[:any_word] ? " || " : " && ")
142+
tsquery_string = tsquery_terms.join(options[:any_word] ? " || " : " && ")
143+
144+
arel_wrap(tsquery_string)
139145
end
140146

141147
def tsdocument
142-
tsdocument_terms = (columns_to_use || []).map do |search_column|
143-
column_to_tsvector(search_column)
144-
end
148+
tsdocument_terms = [
149+
*(columns_to_use || []).map { column_to_tsvector(_1) },
150+
*Array.wrap(options[:tsvector_column]).map { arel_table[_1] }
151+
]
145152

146-
if options[:tsvector_column]
147-
tsvector_columns = Array.wrap(options[:tsvector_column])
148-
149-
tsdocument_terms << tsvector_columns.map do |tsvector_column|
150-
column_name = connection.quote_column_name(tsvector_column)
153+
return Arel::Nodes.build_quoted(nil) if tsdocument_terms.empty?
151154

152-
"#{quoted_table_name}.#{column_name}"
155+
Arel::Nodes::Grouping.new(
156+
tsdocument_terms.reduce do |memo, term|
157+
Arel::Nodes::InfixOperation.new("||", memo, term)
153158
end
154-
end
155-
156-
tsdocument_terms.join(" || ")
159+
)
157160
end
158161

159162
# From http://www.postgresql.org/docs/8.3/static/textsearch-controls.html
@@ -169,14 +172,6 @@ def normalization
169172
options[:normalization] || 0
170173
end
171174

172-
def tsearch_rank
173-
Arel::Nodes::NamedFunction.new("ts_rank", [
174-
arel_wrap(tsdocument),
175-
arel_wrap(tsquery),
176-
normalization
177-
]).to_sql
178-
end
179-
180175
def dictionary
181176
Arel::Nodes.build_quoted(options[:dictionary] || :simple)
182177
end
@@ -197,12 +192,13 @@ def column_to_tsvector(search_column)
197192
tsvector = Arel::Nodes::NamedFunction.new(
198193
"to_tsvector",
199194
[dictionary, Arel.sql(normalize(search_column.to_sql))]
200-
).to_sql
195+
)
201196

202197
if search_column.weight.nil?
203198
tsvector
204199
else
205-
"setweight(#{tsvector}, #{connection.quote(search_column.weight)})"
200+
weight = Arel::Nodes.build_quoted(search_column.weight)
201+
Arel::Nodes::NamedFunction.new("setweight", [tsvector, weight])
206202
end
207203
end
208204
end

spec/lib/pg_search/features/dmetaphone_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
feature = described_class.new(query, options, columns, Model, normalizer)
2525
expect(feature.rank.to_sql).to eq(
26-
%{(ts_rank((to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."name")::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."content")::text, '')))), (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')), 0))}
26+
%{ts_rank((to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."name")::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."content")::text, '')))), (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')), 0)}
2727
)
2828
end
2929
end

spec/lib/pg_search/features/tsearch_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
feature = described_class.new(query, options, columns, Model, normalizer)
2626
expect(feature.rank.to_sql).to eq(
27-
%{(ts_rank((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 0))}
27+
%{ts_rank((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 0)}
2828
)
2929
end
3030

@@ -41,7 +41,7 @@
4141

4242
feature = described_class.new(query, options, columns, Model, normalizer)
4343
expect(feature.rank.to_sql).to eq(
44-
%{(ts_rank((#{Model.quoted_table_name}."my_tsvector"), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 2))}
44+
%{ts_rank((#{Model.quoted_table_name}."my_tsvector"), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 2)}
4545
)
4646
end
4747
end

0 commit comments

Comments
 (0)