Fix ambiguous column in SQLite FTS multi-term search (#2688)

* Fix multi-term SQLite FTS5 search causing a 500 error

When filtering cards by more than one term, `matching` was called
once per term via an association join. Rails did not deduplicate
association joins, resulting in two JOINs to `search_records_fts`
in a single query. SQLite FTS5 then raised "ambiguous column name"
when evaluating the MATCH condition.

Fix by using a string join instead, which Rails deduplicates so
only one JOIN to `search_records_fts` is generated regardless of
how many terms are searched.

Fixes: https://github.com/basecamp/fizzy/discussions/2354

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: verify multi-term search requires ALL terms to match

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mike Dalessio <mike@37signals.com>
This commit is contained in:
Peter Baker
2026-03-18 15:38:06 +00:00
committed by GitHub
parent 5701aad8d7
commit e0d66b2fd0
2 changed files with 14 additions and 1 deletions
+4 -1
View File
@@ -10,7 +10,10 @@ module Search::Record::SQLite
after_save :upsert_to_fts5_table
scope :matching, ->(query, account_id) { joins(:search_records_fts).where("search_records_fts MATCH ?", query) }
scope :matching, ->(query, account_id) {
joins("INNER JOIN search_records_fts ON search_records_fts.rowid = #{table_name}.id")
.where("search_records_fts MATCH ?", query)
}
end
class_methods do
+10
View File
@@ -12,4 +12,14 @@ class Filter::SearchTest < ActiveSupport::TestCase
assert_equal [ card ], filter.cards.to_a
end
test "multiple terms all match" do
matching_card = @board.cards.create!(title: "haggis neeps tatties", creator: @user, status: "published")
@board.cards.create!(title: "haggis only", creator: @user, status: "published")
@board.cards.create!(title: "neeps only", creator: @user, status: "published")
filter = @user.filters.new(terms: [ "haggis", "neeps" ], indexed_by: "all", sorted_by: "latest")
assert_equal [ matching_card ], filter.cards.to_a
end
end