if Code.ensure_loaded?(Ecto.Query.API) do
defmodule Tempus.Ecto.Query.API do
@moduledoc """
Provides several helpers to query DB for the `Tempus.Slot` type.
Under the hood it delegates to
[`Ecto.Query.API.fragment/1`](https://hexdocs.pm/ecto/Ecto.Query.API.html#fragment/1-defining-custom-functions-using-macros-and-fragment),
but might be helpful for compile-type sanity check for typos and
better language server support.
It is also designed to be an implementation-agnostic, meaning one can use
these helpers without a necessity to explicitly specify a backing type.
The default implementation recommends a `Composite` adapter, which is used by default.
To use it with, say, `MySQL`, one should implement this behaviour for `MySQL` and declare
the implementation as `use Tempus.Ecto.Query.API, adapter: MyImpl.MySQL.Adapter`
Although the library provides the MySQL adapter too (`Tempus.Ecto.Query.API.Map.MySQL`,)
but it is not actively maintained, so use it on your own.
If for some reason you use `Map` type with `Postgres`, helpers are still available
with `use Tempus.Ecto.Query.API, adapter: Tempus.Ecto.Query.API.Map.Postgres`
"""
@doc """
Native implementation of how to retrieve `from` part of the slot from the DB.
For `Postgres`, it delegates to the function on the composite type,
for other implementation it should return a `Ecto.Query.API.fragment/1`.
"""
@macrocallback slot_from(Macro.t()) :: Macro.t()
@doc """
Native implementation of how to retrieve `to` part of the slot from the DB.
For `Postgres`, it delegates to the function on the composite type,
for other implementation it should return a `Ecto.Query.API.fragment/1`.
"""
@macrocallback slot_to(Macro.t()) :: Macro.t()
@doc false
defmacro __using__(opts \\ [])
defmacro __using__([]),
do: do_using(Tempus.Ecto.Query.API.Composite)
@doc false
defmacro __using__(adapter: adapter),
do: do_using(adapter)
defp do_using(adapter) do
quote do
import unquote(adapter)
import Tempus.Ecto.Query.API
end
end
@doc """
`Ecto.Query.API` helper, allowing to filter records having the same currency.
_Example:_
```elixir
iex>
...> Occasion
...> |> where([o], started_after(o.initial, ^~U[2023-01-01 00:00:00Z]))
...> |> select([o], o.initial)
...> |> Repo.all()
[%Tempus.Slot{from: ~U[2023-04-07 00:00:00Z], to: ~U[2023-04-10 23:59:59.999999Z]}]
```
"""
defmacro started_after(field, dt) do
quote do: slot_from(unquote(field)) > ^unquote(dt)
end
end
end