diff --git a/lib/mongo_ecto/normalized_query.ex b/lib/mongo_ecto/normalized_query.ex index 6d20576..6b60a61 100644 --- a/lib/mongo_ecto/normalized_query.ex +++ b/lib/mongo_ecto/normalized_query.ex @@ -345,6 +345,22 @@ defmodule Mongo.Ecto.NormalizedQuery do defp offset_limit(nil, _params, _pk, _query, _where), do: nil + defp offset_limit( + %Query.QueryExpr{expr: {:^, l, [idx]} = expr}, + params, + pk, + %Query{wheres: wheres} = query, + where + ) do + param_offset = + Enum.reduce(wheres, 0, fn %Query.BooleanExpr{expr: expr}, acc -> + _from..to = pair_params_range(expr) + acc + to + end) + + value({:^, l, [idx + param_offset]}, params, pk, query, where) + end + defp offset_limit(%Query.QueryExpr{expr: expr}, params, pk, query, where), do: value(expr, params, pk, query, where) @@ -466,9 +482,10 @@ defmodule Mongo.Ecto.NormalizedQuery do {field(left, pk, query, place), ["$in": []]} end - defp pair({:in, _, [left, {:^, _, [ix, len]}]}, params, pk, query, place) do + defp pair({:in, _, [left, _]} = expr, params, pk, query, place) do args = - ix..(ix + len - 1) + expr + |> pair_params_range() |> Enum.map(&elem(params, &1)) |> Enum.map(&value(&1, params, pk, query, place)) @@ -483,9 +500,10 @@ defmodule Mongo.Ecto.NormalizedQuery do {field(left, pk, query, place), [{binary_op(op), value(right, params, pk, query, place)}]} end - defp pair({:not, _, [{:in, _, [left, {:^, _, [ix, len]}]}]}, params, pk, query, place) do + defp pair({:not, _, [{:in, _, [left, _]}]} = expr, params, pk, query, place) do args = - ix..(ix + len - 1) + expr + |> pair_params_range() |> Enum.map(&elem(params, &1)) |> Enum.map(&value(&1, params, pk, query, place)) @@ -545,4 +563,8 @@ defmodule Mongo.Ecto.NormalizedQuery do defp error(place) do raise ArgumentError, "Invalid expression for MongoDB adapter in #{place}" end + + defp pair_params_range({:in, _, [_, {:^, _, [ix, len]}]}), do: ix..(ix + len - 1) + defp pair_params_range({:not, _, [{:in, _, [_, {:^, _, [ix, len]}]}]}), do: ix..(ix + len - 1) + defp pair_params_range(expr), do: 0..0 end diff --git a/test/mongo_ecto_test.exs b/test/mongo_ecto_test.exs index 28cf4bf..9cf65f0 100644 --- a/test/mongo_ecto_test.exs +++ b/test/mongo_ecto_test.exs @@ -91,6 +91,18 @@ defmodule Mongo.EctoTest do assert 10 == TestRepo.one(query) end + test "where in ids + dynamic limit + dynamic offset" do + post1 = TestRepo.insert!(%Post{}) + post2 = TestRepo.insert!(%Post{}) + post3 = TestRepo.insert!(%Post{}) + ids = [post1.id, post2.id, post3.id] + limit = 1 + offset = 1 + + query = from p in Post, where: p.id in ^ids, limit: ^limit, offset: ^offset + assert TestRepo.all(query) == [post2] + end + # test "partial update in map" do # post = TestRepo.insert!(%Post{meta: %{author: %{name: "michal"}, other: "value"}}) # TestRepo.update_all(Post, set: [meta: change_map("author.name", "michal")])