diff --git a/lib/alog/connection.ex b/lib/alog/connection.ex index 6451a7d..2fc173b 100644 --- a/lib/alog/connection.ex +++ b/lib/alog/connection.ex @@ -29,6 +29,65 @@ defmodule Alog.Connection do @impl true defdelegate ddl_logs(result), to: EAPC + @impl true + def all(query) do + iodata_query = EAPC.all(query) + + query = iodata_query + |> IO.iodata_to_binary() + |> alogify_all_query() + + query + end + + defp alogify_all_query(query) do + query_data = get_query_data(query) + # if all query is called during migration, some column used in the + # alogify version might not be yet defined. + # Return the "normal" query + if (query_data["table_name"] == "\"schema_migrations\"") do + query + else + subquery = IO.iodata_to_binary( + [ "SELECT DISTINCT ON (#{query_data["table_as"]}.\"entry_id\" ) ", + query_data["subquery_fields"], + get_deleted_field(query_data), + " FROM ", + query_data["table_name"], " AS ", query_data["table_as"], + query_data["rest_query"], + " ORDER BY #{query_data["table_as"]}.\"entry_id\", #{query_data["table_as"]}.\"inserted_at\" DESC" + ] + ) + + IO.iodata_to_binary( + ["SELECT ", query_data["field_names"], " FROM (", subquery, ") AS alogsubquery WHERE (NOT alogsubquery.\"deleted\")"] + ) + end + end + + defp get_query_data(query) do + data = Regex.named_captures(~r/(\bSELECT\b)\s(?.*)\sFROM\s(?.*)\sas\s(?.*)(?.*)/i, query) + data = Map.put(data, "field_names", Regex.replace(~r/#{data["table_as"]}/, data["fields"], "alogsubquery")) + + subquery_fields = data["fields"] + |> String.split(",") + |> Enum.map(fn f -> + field_name = Regex.replace(~r/#{data["table_as"]}./, f, "") + f <> " AS #{field_name}" + end) + |> Enum.join(", ") + + Map.put(data, "subquery_fields", subquery_fields) + end + + defp get_deleted_field(query_data) do + if String.contains?(query_data["subquery_fields"], "#{query_data["table_as"]}.\"deleted\"") do + "" + else + ", #{query_data["table_as"]}.\"deleted\" AS \"deleted\"" + end + end + @impl true def execute_ddl({c, %Ecto.Migration.Table{} = table, columns}) when c in [:create, :create_if_not_exists] do diff --git a/test/all_test.exs b/test/all_test.exs index 1184943..cb8c043 100644 --- a/test/all_test.exs +++ b/test/all_test.exs @@ -1,31 +1,14 @@ defmodule AlogTest.AllTest do use Alog.TestApp.DataCase - # alias Alog.TestApp.{User, Helpers} - # - # describe "all/0:" do - # test "succeeds" do - # {:ok, _} = %User{} |> User.changeset(Helpers.user_1_params()) |> User.insert() - # {:ok, _} = %User{} |> User.changeset(Helpers.user_2_params()) |> User.insert() - # - # assert length(User.all()) == 2 - # end - # - # test "does not include old items" do - # {:ok, user} = %User{} |> User.changeset(Helpers.user_1_params()) |> User.insert() - # {:ok, _} = %User{} |> User.changeset(Helpers.user_2_params()) |> User.insert() - # {:ok, _} = user |> User.changeset(%{postcode: "W2 3EC"}) |> User.update() - # - # assert length(User.all()) == 2 - # end - # - # test "all return inserted_at original value" do - # {:ok, user} = %User{} |> User.changeset(Helpers.user_3_params()) |> User.insert() - # {:ok, user_updated} = user |> User.changeset(%{postcode: "W2 3EC"}) |> User.update() - # - # [user_all] = User.all() - # assert user_all.inserted_at == user.inserted_at - # assert user_all.postcode == user_updated.postcode - # end - # end + alias Alog.TestApp.{Comment} + + describe "all/0:" do + test "succeeds" do + {:ok, _comment} = %Comment{comment: "Hello Rob"} |> Repo.insert() + {:ok, _} = %Comment{comment: "Hello Dan"} |> Repo.insert() + + assert length(Repo.all(Comment)) == 2 + end + end end