defmodule Mv.Membership.Import.ColumnResolverQueryTest do # async: false — attaches a global telemetry handler to inspect emitted SQL. use Mv.DataCase, async: false alias Mv.Membership.Import.ColumnResolver setup do %{actor: Mv.Helpers.SystemActor.get_system_actor()} end describe "create_or_find_group/3 group lookup is name-filtered (no full-table scan)" do test "resolving a new name absent from the snapshot queries by name, not the whole table", %{actor: actor} do # Populate the table so a full-table read would be costly and observable. for n <- 1..20, do: Mv.Fixtures.group_fixture(%{name: "Existing #{n}"}) queries = capture_group_select_queries(fn -> # The name is absent from the (empty) snapshot, forcing a DB lookup # before the create attempt. That lookup must filter by name. assert {:ok, group} = ColumnResolver.create_or_find_group("New One", [], actor) assert group.name == "New One" end) # No SELECT against the groups table issued during resolution may be an # unfiltered full-table scan. The pre-create existence check must filter by # name (carry a WHERE predicate). refute Enum.any?(queries, &unfiltered_groups_select?/1), "expected no unfiltered groups table scan, got:\n#{Enum.join(queries, "\n")}" end end defp capture_group_select_queries(fun) do test_pid = self() handler_id = "test-group-query-#{System.unique_integer([:positive])}" :telemetry.attach( handler_id, [:mv, :repo, :query], fn _event, _measurements, metadata, _config -> sql = metadata[:query] || "" if String.contains?(sql, "SELECT") and String.contains?(sql, "\"groups\"") do send(test_pid, {:group_query, sql}) end end, nil ) try do fun.() after :telemetry.detach(handler_id) end collect_group_queries([]) end defp collect_group_queries(acc) do receive do {:group_query, sql} -> collect_group_queries([sql | acc]) after 0 -> Enum.reverse(acc) end end # An unfiltered groups SELECT reads the whole table: it selects FROM "groups" # with no WHERE clause at all. A name-filtered lookup carries a WHERE predicate. defp unfiltered_groups_select?(sql) do String.contains?(sql, "FROM \"groups\"") and not String.contains?(sql, "WHERE") end end