Skip to content

Commit 4e08d72

Browse files
author
morten.lund@maskon.no
committed
Partitioning of resource
1 parent 37dd643 commit 4e08d72

File tree

2 files changed

+56
-21
lines changed

2 files changed

+56
-21
lines changed

lib/migration_generator/phase.ex

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,26 @@ defmodule AshPostgres.MigrationGenerator.Phase do
33

44
defmodule Create do
55
@moduledoc false
6-
defstruct [:table, :schema, :multitenancy, partitioning: nil, operations: [], commented?: false]
6+
defstruct [
7+
:table,
8+
:schema,
9+
:multitenancy,
10+
partitioning: nil,
11+
operations: [],
12+
commented?: false
13+
]
714

815
import AshPostgres.MigrationGenerator.Operation.Helper, only: [as_atom: 1]
916

10-
def up(%{schema: schema, table: table, operations: operations, multitenancy: multitenancy, partitioning: partitioning}) do
17+
def up(%{
18+
schema: schema,
19+
table: table,
20+
operations: operations,
21+
multitenancy: multitenancy,
22+
partitioning: partitioning
23+
}) do
1124
if multitenancy.strategy == :context do
12-
arguments = arguments([prefix("prefix()"), options(partitioning: partitioning)])
25+
arguments = arguments([prefix(true), options(partitioning: partitioning)])
1326

1427
"create table(:#{as_atom(table)}, primary_key: false#{arguments}) do\n" <>
1528
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
@@ -38,14 +51,15 @@ defmodule AshPostgres.MigrationGenerator.Phase do
3851
end
3952
end
4053

41-
def arguments(["",""]), do: ""
54+
def arguments([nil, nil]), do: ""
4255
def arguments(arguments), do: ", " <> Enum.join(Enum.reject(arguments, &is_nil(&1)), ",")
4356

44-
def prefix(nil), do: nil
45-
def prefix(schema), do: "prefix: #{schema}"
57+
def prefix(true), do: "prefix: prefix()"
58+
def prefix(schema) when is_binary(schema) and schema != "", do: "prefix: \"#{schema}\""
59+
def prefix(_), do: nil
4660

4761
def options(_options, _acc \\ [])
48-
def options([], []), do: ""
62+
def options([], []), do: nil
4963
def options([], acc), do: "options: \"#{Enum.join(acc, " ")}\""
5064

5165
def options([{:partitioning, %{method: method, attribute: attribute}} | rest], acc) do
@@ -55,7 +69,7 @@ defmodule AshPostgres.MigrationGenerator.Phase do
5569
|> options(acc ++ [option])
5670
end
5771

58-
def options([_| rest], acc) do
72+
def options([_ | rest], acc) do
5973
options(rest, acc)
6074
end
6175
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)