Files
accounted/extensions/general
MattssonandClaude Fable 5 bf3104dd21 fix(mcp): query_journal text search runs two-step instead of the LATERAL embed (#1804)
The two free-text ilike legs of gnubok_query_journal were the last users of
the journal_entries!inner embed. PostgREST compiles that embed to a
correlated LATERAL join that walks every tenant's journal_entry_lines, and
prod logs showed it as the query behind the daily 8 s statement timeouts
(SQLSTATE 57014), which reached agents as a generic UNKNOWN_ERROR.

- Both legs now run fetchEntryLines (lib/bookkeeping/entry-lines.ts) over the
  same entry/line filter set as the plain query: leg A ilikes
  journal_entries.description on the entry side, leg B ilikes
  line_description on the line side. Leg B fetches the entry ids the plain
  query already fetches, but only the matching lines, so it is never more
  expensive than the same query without text.
- Each leg pulls its full match set, so text queries now report exact
  totals/total_lines/truncated; legLimit/legCapHit and
  totals_scope='returned_slice' are gone. The totals_scope field stays,
  always 'full_match'.
- The amount filter runs before the display slice on every path, so limit=N
  returns N matching lines instead of N minus what the filter removed.
- DB failures are still sanitised, but a transient one (statement timeout,
  connection drop) now carries code TRANSIENT_ERROR plus a hint to retry or
  narrow with date_from/date_to, so the structured-error layer returns the
  retryable envelope instead of "Något gick fel".

Tests: text suite rewritten on a filter-aware two-step fake (no
.from() call-order pinning), plus text+date-range, no-embed, amount-before-
slice, and 57014 -> TRANSIENT_ERROR cases.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 01:10:18 +02:00
..
2026-07-21 23:00:15 +02:00