From 390aab9592fd0d369d5ea13e6ee55d6bd165bab6 Mon Sep 17 00:00:00 2001 From: exAspArk Date: Thu, 17 Jan 2019 12:05:47 -0500 Subject: [PATCH] Fix finding values for limit and offset with where arrays, close #170 --- lib/mongo_ecto/normalized_query.ex | 39 +++++++++++++++++++++++++----- test/mongo_ecto_test.exs | 11 +++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/lib/mongo_ecto/normalized_query.ex b/lib/mongo_ecto/normalized_query.ex index 6d20576..8c13aad 100644 --- a/lib/mongo_ecto/normalized_query.ex +++ b/lib/mongo_ecto/normalized_query.ex @@ -345,8 +345,21 @@ defmodule Mongo.Ecto.NormalizedQuery do defp offset_limit(nil, _params, _pk, _query, _where), do: nil - defp offset_limit(%Query.QueryExpr{expr: expr}, params, pk, query, where), - do: value(expr, params, pk, query, where) + defp offset_limit(%Query.QueryExpr{expr: expr}, params, pk, %Query{wheres: wheres} = query, where) do + case expr do + {:^, l, [idx]} -> + param_offset = + Enum.reduce(wheres, 0, fn %Query.BooleanExpr{expr: expr}, acc -> + _from..to = pair_param_range(expr) + acc + to + end) + + value({:^, l, [idx + param_offset]}, params, pk, query, where) + + _ -> + value(expr, params, pk, query, where) + end + end defp primary_key(nil), do: nil @@ -466,9 +479,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_param_range() |> Enum.map(&elem(params, &1)) |> Enum.map(&value(&1, params, pk, query, place)) @@ -483,9 +497,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_param_range() |> Enum.map(&elem(params, &1)) |> Enum.map(&value(&1, params, pk, query, place)) @@ -545,4 +560,16 @@ defmodule Mongo.Ecto.NormalizedQuery do defp error(place) do raise ArgumentError, "Invalid expression for MongoDB adapter in #{place}" end + + defp pair_param_range({:in, _, [_, {:^, _, [ix, len]}]}) do + ix..(ix + len - 1) + end + + defp pair_param_range({:not, _, [{:in, _, [_, {:^, _, [ix, len]}]}]}) do + ix..(ix + len - 1) + end + + defp pair_param_range(expr) do + 0..0 + end end diff --git a/test/mongo_ecto_test.exs b/test/mongo_ecto_test.exs index 28cf4bf..c94b868 100644 --- a/test/mongo_ecto_test.exs +++ b/test/mongo_ecto_test.exs @@ -91,6 +91,17 @@ 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{}) + ids = [post1.id, post2.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")])