From 6f160bee4d90c3a9e5c96d2a30f01c915893dd2c Mon Sep 17 00:00:00 2001 From: Thomas Schmidleithner Date: Mon, 24 Aug 2020 00:54:48 +0200 Subject: [PATCH] Support schema prefixes (#91) * Support schema prefixes * Fix format * Code review changes * Remove prefix from comments and key_values migrations --- lib/scrivener/paginater/ecto/query.ex | 13 ++++--- priv/repo/migrations/04_create_schemas.exs | 17 +++++++++ priv/repo/migrations/05_create_users.exs | 13 +++++++ test/scrivener/paginator/ecto/prefix_test.exs | 36 +++++++++++++++++++ test/support/user.ex | 7 ++++ 5 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 priv/repo/migrations/04_create_schemas.exs create mode 100644 priv/repo/migrations/05_create_users.exs create mode 100644 test/scrivener/paginator/ecto/prefix_test.exs create mode 100644 test/support/user.ex diff --git a/lib/scrivener/paginater/ecto/query.ex b/lib/scrivener/paginater/ecto/query.ex index 313a6d6..f648e46 100644 --- a/lib/scrivener/paginater/ecto/query.ex +++ b/lib/scrivener/paginater/ecto/query.ex @@ -14,7 +14,9 @@ defimpl Scrivener.Paginater, for: Ecto.Query do options: options }) do total_entries = - Keyword.get_lazy(options, :total_entries, fn -> total_entries(query, repo, caller) end) + Keyword.get_lazy(options, :total_entries, fn -> + total_entries(query, repo, caller, options) + end) total_pages = total_pages(total_entries, page_size) allow_overflow_page_number = Keyword.get(options, :allow_overflow_page_number, false) @@ -35,20 +37,23 @@ defimpl Scrivener.Paginater, for: Ecto.Query do defp entries(query, repo, page_number, _, page_size, caller, options) do offset = Keyword.get_lazy(options, :offset, fn -> page_size * (page_number - 1) end) + prefix = options[:prefix] query |> offset(^offset) |> limit(^page_size) - |> repo.all(caller: caller) + |> repo.all(caller: caller, prefix: prefix) end - defp total_entries(query, repo, caller) do + defp total_entries(query, repo, caller, options) do + prefix = options[:prefix] + total_entries = query |> exclude(:preload) |> exclude(:order_by) |> aggregate() - |> repo.one(caller: caller) + |> repo.one(caller: caller, prefix: prefix) total_entries || 0 end diff --git a/priv/repo/migrations/04_create_schemas.exs b/priv/repo/migrations/04_create_schemas.exs new file mode 100644 index 0000000..3f4de5e --- /dev/null +++ b/priv/repo/migrations/04_create_schemas.exs @@ -0,0 +1,17 @@ +defmodule TestRepo.Migrations.CreateSchemas do + use Ecto.Migration + + @prefixes ["tenant_1", "tenant_2"] + + def up do + for prefix <- @prefixes do + execute "CREATE SCHEMA #{prefix}" + end + end + + def down do + for prefix <- @prefixes do + execute "DROP SCHEMA #{prefix}" + end + end +end diff --git a/priv/repo/migrations/05_create_users.exs b/priv/repo/migrations/05_create_users.exs new file mode 100644 index 0000000..b811c40 --- /dev/null +++ b/priv/repo/migrations/05_create_users.exs @@ -0,0 +1,13 @@ +defmodule TestRepo.Migrations.CreateUsers do + use Ecto.Migration + + @prefixes ["tenant_1", "tenant_2"] + + def change do + for prefix <- @prefixes do + create table(:users, prefix: prefix) do + add :email, :string + end + end + end +end diff --git a/test/scrivener/paginator/ecto/prefix_test.exs b/test/scrivener/paginator/ecto/prefix_test.exs new file mode 100644 index 0000000..0b3bb9b --- /dev/null +++ b/test/scrivener/paginator/ecto/prefix_test.exs @@ -0,0 +1,36 @@ +defmodule Scrivener.Paginator.Ecto.PrefixTest do + use Scrivener.Ecto.TestCase + + alias Scrivener.Ecto.User + + defp create_users(number, prefix) do + Enum.map(1..number, fn i -> + %User{email: "user_#{i}@#{prefix}.com"} + |> Scrivener.Ecto.Repo.insert!(prefix: prefix) + end) + end + + @schema_tenant_1 "tenant_1" + @schema_tenant_2 "tenant_2" + + describe "prefix" do + test "can specify prefix" do + create_users(6, @schema_tenant_1) + create_users(2, @schema_tenant_2) + + page_tenant_1 = Scrivener.Ecto.Repo.paginate(User, options: [prefix: @schema_tenant_1]) + + assert page_tenant_1.page_size == 5 + assert page_tenant_1.page_number == 1 + assert page_tenant_1.total_entries == 6 + assert page_tenant_1.total_pages == 2 + + page_tenant_2 = Scrivener.Ecto.Repo.paginate(User, options: [prefix: @schema_tenant_2]) + + assert page_tenant_2.page_size == 5 + assert page_tenant_2.page_number == 1 + assert page_tenant_2.total_entries == 2 + assert page_tenant_2.total_pages == 1 + end + end +end diff --git a/test/support/user.ex b/test/support/user.ex new file mode 100644 index 0000000..3071e0d --- /dev/null +++ b/test/support/user.ex @@ -0,0 +1,7 @@ +defmodule Scrivener.Ecto.User do + use Ecto.Schema + + schema "users" do + field(:email, :string) + end +end