Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions lib/ecto/query/builder/windows.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,21 @@ defmodule Ecto.Query.Builder.Windows do
defp escape_frame({:fragment, _, _} = fragment, params_acc, vars, env) do
Builder.escape(fragment, :any, params_acc, vars, env)
end
defp escape_frame(other, _, _, _) do
Builder.error!("expected a dynamic or fragment in `:frame`, got: `#{inspect other}`")

defp escape_frame(other, params_acc, vars, env) do
macro_env =
case env do
{env, _} -> env
env -> env
end

case Macro.expand_once(other, macro_env) do
^other ->
Builder.error!("expected a dynamic or fragment in `:frame`, got: `#{inspect other}`")

expanded ->
escape_frame(expanded, params_acc, vars, env)
end
end

defp error!(other) do
Expand Down
32 changes: 32 additions & 0 deletions test/ecto/query/builder/windows_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ defmodule Ecto.Query.Builder.WindowsTest do

import Ecto.Query

defmacrop rows_between_preceding(count) do
quote do
fragment(unquote("ROWS BETWEEN #{count} PRECEDING AND CURRENT ROW"))
end
end

defmacro invalid_frame do
quote do
[rows: -3, exclude: :current]
end
end

describe "escape" do
test "handles expressions and params" do
assert {Macro.escape(quote(do: [partition_by: [&0.y()]])), [], {[], %{}}} ==
Expand Down Expand Up @@ -63,6 +75,26 @@ defmodule Ecto.Query.Builder.WindowsTest do
query = "q" |> windows([p], w: [frame: fragment("FOOBAR")])
assert query.windows[:w].expr[:frame] == {:fragment, [], [raw: "FOOBAR"]}
end

test "defines frame with macro that expands to fragment" do
query = "q" |> windows([p], w: [frame: rows_between_preceding(6)])

assert query.windows[:w].expr[:frame] ==
{:fragment, [], [raw: "ROWS BETWEEN 6 PRECEDING AND CURRENT ROW"]}
end

test "raises on frame macro that does not expand to fragment" do
assert_raise Ecto.Query.CompileError, ~r"expected a dynamic or fragment in `:frame`", fn ->
Code.eval_quoted(
quote do
import Ecto.Query
import unquote(__MODULE__)

"q" |> windows([p], w: [frame: invalid_frame()])
end
)
end
end
end

describe "at runtime" do
Expand Down
Loading