diff --git a/lib/search.rb b/lib/search.rb index d1669d6d227..88379952939 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -1333,7 +1333,7 @@ class Search tsquery = "TO_TSQUERY(#{ts_config || default_ts_config}, #{escaped_term})" # PG 14 and up default to using the followed by operator # this restores the old behavior - tsquery = "REPLACE(#{tsquery}::text, '<->', '&')::tsquery" + tsquery = "REGEXP_REPLACE(#{tsquery}::text, '<->|<\\d+>', '&', 'g')::tsquery" tsquery = "REPLACE(#{tsquery}::text, '&', '#{escape_string(joiner)}')::tsquery" if joiner tsquery end diff --git a/spec/lib/search_spec.rb b/spec/lib/search_spec.rb index c938e0275f3..3e8d9d592fd 100644 --- a/spec/lib/search_spec.rb +++ b/spec/lib/search_spec.rb @@ -1025,6 +1025,14 @@ RSpec.describe Search do results = Search.execute("tiger", guardian: Guardian.new(user)) expect(results.posts).to eq([post]) end + + it "does not rely on postgres's proximity opreators" do + topic.update!(title: "End-to-end something something testing") + + results = Search.execute("end-to-end test") + + expect(results.posts).to eq([post]) + end end describe "topics" do @@ -2375,13 +2383,19 @@ RSpec.describe Search do it "escapes the term correctly" do expect(Search.ts_query(term: 'Title with trailing backslash\\')).to eq( - "REPLACE(TO_TSQUERY('english', '''Title with trailing backslash\\\\\\\\'':*')::text, '<->', '&')::tsquery", + "REGEXP_REPLACE(TO_TSQUERY('english', '''Title with trailing backslash\\\\\\\\'':*')::text, '<->|<\\d+>', '&', 'g')::tsquery", ) expect(Search.ts_query(term: "Title with trailing quote'")).to eq( - "REPLACE(TO_TSQUERY('english', '''Title with trailing quote'''''':*')::text, '<->', '&')::tsquery", + "REGEXP_REPLACE(TO_TSQUERY('english', '''Title with trailing quote'''''':*')::text, '<->|<\\d+>', '&', 'g')::tsquery", ) end + + it "remaps postgres's proximity operators '<->' and its `` variant" do + expect( + DB.query_single("SELECT #{Search.ts_query(term: "end-to-end")}::text"), + ).to contain_exactly("'end-to-end':* & 'end':* & 'end':*") + end end describe "#word_to_date" do