From 35f376197f961a14e6154b27d35456193700b03d Mon Sep 17 00:00:00 2001 From: Glen Holcomb Date: Wed, 30 Oct 2024 15:52:41 -0600 Subject: [PATCH] Recurse query and apply filtering directly as appropriate --- lib/ecto/soft_delete_repo.ex | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/ecto/soft_delete_repo.ex b/lib/ecto/soft_delete_repo.ex index f0bc4ea..8de61b4 100644 --- a/lib/ecto/soft_delete_repo.ex +++ b/lib/ecto/soft_delete_repo.ex @@ -81,11 +81,37 @@ defmodule Ecto.SoftDelete.Repo do if has_include_deleted_at_clause?(query) || opts[:with_deleted] || !soft_deletable?(query) do {query, opts} else - query = from(x in query, where: is_nil(x.deleted_at)) + query = filter_soft_deleted(query) {query, opts} end end + # We need to check the entire query and apply filtering + # where appropriate. So, we recurse the query here and + # rebuild it with filtering where appropriate. This + # currently only considers the source and does not handle + # things like joins... + defp filter_soft_deleted(%Ecto.Query{from: %{source: {_schema, _module}}} = query) do + if Ecto.SoftDelete.Query.soft_deletable?(query) do + from(x in query, where: is_nil(x.deleted_at)) + else + query + end + end + + defp filter_soft_deleted(%Ecto.SubQuery{query: query} = sub) do + if Ecto.SoftDelete.Query.soft_deletable?(query) do + from(x in query, where: is_nil(x.deleted_at)) |> subquery() + else + sub + end + end + + defp filter_soft_deleted(%Ecto.Query{from: from} = query) do + updated_from = %{from | source: filter_soft_deleted(from.source)} + %{query | from: updated_from} + end + # Checks the query to see if it contains a where not is_nil(deleted_at) # if it does, we want to be sure that we don't exclude soft deleted records defp has_include_deleted_at_clause?(%Ecto.Query{wheres: wheres}) do