Skip to content

Commit c57d5e0

Browse files
author
morten.lund@maskon.no
committed
Partitioning of resource
1 parent aeeacc6 commit c57d5e0

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

lib/migration_generator/phase.ex

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ defmodule AshPostgres.MigrationGenerator.Phase do
2020
repo: repo
2121
}) do
2222
if multitenancy.strategy == :context do
23-
arguments = arguments([prefix("prefix()"), options(partitioning: partitioning)])
23+
arguments = arguments([prefix(true), options(partitioning: partitioning)])
2424

2525
"create table(:#{as_atom(table)}, primary_key: false#{arguments}) do\n" <>
2626
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
@@ -64,14 +64,15 @@ defmodule AshPostgres.MigrationGenerator.Phase do
6464
end
6565
end
6666

67-
def arguments(["",""]), do: ""
67+
def arguments([nil, nil]), do: ""
6868
def arguments(arguments), do: ", " <> Enum.join(Enum.reject(arguments, &is_nil(&1)), ",")
6969

70-
def prefix(nil), do: nil
71-
def prefix(schema), do: "prefix: #{schema}"
70+
def prefix(true), do: "prefix: prefix()"
71+
def prefix(schema) when is_binary(schema) and schema != "", do: "prefix: \"#{schema}\""
72+
def prefix(_), do: nil
7273

7374
def options(_options, _acc \\ [])
74-
def options([], []), do: ""
75+
def options([], []), do: nil
7576
def options([], acc), do: "options: \"#{Enum.join(acc, " ")}\""
7677

7778
def options([{:partitioning, %{method: method, attribute: attribute}} | rest], acc) do
@@ -81,7 +82,7 @@ defmodule AshPostgres.MigrationGenerator.Phase do
8182
|> options(acc ++ [option])
8283
end
8384

84-
def options([_| rest], acc) do
85+
def options([_ | rest], acc) do
8586
options(rest, acc)
8687
end
8788
end

lib/partitioning.ex

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,33 @@ defmodule AshPostgres.Partitioning do
2929
"""
3030
def exists?(resource, opts) do
3131
repo = AshPostgres.DataLayer.Info.repo(resource)
32-
key = Keyword.fetch!(opts, :key)
33-
table = AshPostgres.DataLayer.Info.table(resource)
34-
partition_name = table <> "_" <> "#{key}"
32+
partition_name = partition_name(resource, opts)
3533

36-
partition_exists?(repo, resource, partition_name)
34+
partition_exists?(repo, resource, partition_name, opts)
3735
end
3836

3937
# TBI
40-
defp create_range_partition(repo, resource, opts) do
38+
defp create_range_partition(_repo, _resource, _opts) do
4139
end
4240

4341
defp create_list_partition(repo, resource, opts) do
4442
key = Keyword.fetch!(opts, :key)
4543
table = AshPostgres.DataLayer.Info.table(resource)
46-
partition_name = table <> "_" <> "#{key}"
44+
partition_name = partition_name(resource, opts)
45+
46+
schema =
47+
Keyword.get(opts, :tenant)
48+
|> tenant_schema(resource)
4749

48-
if partition_exists?(repo, resource, partition_name) do
50+
if partition_exists?(repo, resource, partition_name, opts) do
4951
{:error, :allready_exists}
5052
else
5153
Ecto.Adapters.SQL.query(
5254
repo,
53-
"CREATE TABLE #{partition_name} PARTITION OF public.#{table} FOR VALUES IN (#{key})"
55+
"CREATE TABLE \"#{schema}\".\"#{partition_name}\" PARTITION OF \"#{schema}\".\"#{table}\" FOR VALUES IN ('#{key}')"
5456
)
5557

56-
if partition_exists?(repo, resource, partition_name) do
58+
if partition_exists?(repo, resource, partition_name, opts) do
5759
:ok
5860
else
5961
{:error, "Unable to create partition"}
@@ -62,18 +64,37 @@ defmodule AshPostgres.Partitioning do
6264
end
6365

6466
# TBI
65-
defp create_hash_partition(repo, resource, opts) do
67+
defp create_hash_partition(_repo, _resource, _opts) do
6668
end
6769

68-
defp partition_exists?(repo, resource, parition_name) do
70+
defp partition_exists?(repo, resource, parition_name, opts) do
71+
schema =
72+
Keyword.get(opts, :tenant)
73+
|> tenant_schema(resource)
74+
6975
%Postgrex.Result{} =
7076
result =
7177
repo
7278
|> Ecto.Adapters.SQL.query!(
73-
"select table_name from information_schema.tables t where t.table_schema = 'public' and t.table_name = $1",
74-
[parition_name]
79+
"select table_name from information_schema.tables t where t.table_schema = $1 and t.table_name = $2",
80+
[schema, parition_name]
7581
)
7682

7783
result.num_rows > 0
7884
end
85+
86+
defp partition_name(resource, opts) do
87+
key = Keyword.fetch!(opts, :key)
88+
table = AshPostgres.DataLayer.Info.table(resource)
89+
"#{table}_#{key}"
90+
end
91+
92+
defp tenant_schema(tenant, resource) do
93+
tenant
94+
|> Ash.ToTenant.to_tenant(resource)
95+
|> case do
96+
nil -> "public"
97+
tenant -> tenant
98+
end
99+
end
79100
end

0 commit comments

Comments
 (0)