@@ -2,25 +2,50 @@ defmodule Torus.BM25Test do
22 @ moduledoc false
33 use Torus.Case , async: false
44
5- # @moduletag :skip
5+ @ moduletag :skip
6+
7+ # NOTE: pg_textsearch has a known limitation where uncommitted rows from
8+ # rolled-back transactions remain in the BM25 memtable. This can cause
9+ # ORDER BY + LIMIT queries to return stale TIDs that fail visibility checks.
10+ # This is why this test is skipped by default on CI and needs to be run manually.
611
712 import Ecto.Query
813
14+ alias Ecto.Adapters.SQL.Sandbox
915 alias Torus.Test.Repo
1016 alias TorusTest.Post
1117
12- # NOTE: pg_textsearch has a known limitation where uncommitted rows from
13- # rolled-back transactions remain in the BM25 memtable. This can cause
14- # ORDER BY + LIMIT queries to return stale TIDs that fail visibility checks.
15- # The standalone operator (without ORDER BY) works correctly.
18+ setup_all do
19+ Sandbox . unboxed_run ( Repo , fn ->
20+ Repo . query! ( "CREATE EXTENSION IF NOT EXISTS pg_textsearch" )
21+
22+ Repo . query! ( """
23+ CREATE INDEX IF NOT EXISTS posts_body_bm25_idx ON posts
24+ USING bm25(body) WITH (text_config='english')
25+ """ )
26+
27+ Repo . query! ( """
28+ CREATE INDEX IF NOT EXISTS posts_title_bm25_idx ON posts
29+ USING bm25(title) WITH (text_config='english')
30+ """ )
31+ end )
32+
33+ :ok
34+ end
1635
1736 defp flush_bm25! ( index_name \\ "posts_body_bm25_idx" ) do
18- Repo . query! ( "SELECT bm25_spill_index($1)" , [ index_name ] )
37+ Sandbox . unboxed_run ( Repo , fn ->
38+ Repo . query! ( "SELECT bm25_spill_index($1)" , [ index_name ] )
39+ end )
40+
1941 :ok
2042 end
2143
2244 defp reset_bm25_state! do
23- Repo . query! ( "TRUNCATE TABLE posts RESTART IDENTITY CASCADE" )
45+ Sandbox . unboxed_run ( Repo , fn ->
46+ Repo . query! ( "TRUNCATE TABLE posts RESTART IDENTITY CASCADE" )
47+ end )
48+
2449 flush_bm25! ( )
2550 flush_bm25! ( "posts_title_bm25_idx" )
2651 :ok
0 commit comments