mirror of
https://github.com/ash-project/ash_postgres.git
synced 2024-09-19 13:03:14 +12:00
improvement: custom-extension implementation (#162)
* improvement: custom-extension implementation * improvement: allow adding custom-extension by module's reference and fixes formatting * ci: fixes formatter
This commit is contained in:
parent
7ce33cac2c
commit
4a02d8c6ad
11 changed files with 159 additions and 22 deletions
20
lib/custom_extension.ex
Normal file
20
lib/custom_extension.ex
Normal file
|
@ -0,0 +1,20 @@
|
|||
defmodule AshPostgres.CustomExtension do
|
||||
@moduledoc """
|
||||
A custom extension implementation.
|
||||
"""
|
||||
|
||||
@callback install(version :: integer) :: String.t()
|
||||
|
||||
@callback uninstall(version :: integer) :: String.t()
|
||||
|
||||
defmacro __using__(name: name, latest_version: latest_version) do
|
||||
quote do
|
||||
@behaviour AshPostgres.CustomExtension
|
||||
|
||||
@extension_name unquote(name)
|
||||
@extension_latest_version unquote(latest_version)
|
||||
|
||||
def extension, do: {@extension_name, @extension_latest_version, &install/1, &uninstall/1}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1106,8 +1106,7 @@ defmodule AshPostgres.Expr do
|
|||
Map.get(first_relationship, :manual) ->
|
||||
{module, opts} = first_relationship.manual
|
||||
|
||||
[pkey_attr | _] =
|
||||
Ash.Resource.Info.primary_key(first_relationship.destination)
|
||||
[pkey_attr | _] = Ash.Resource.Info.primary_key(first_relationship.destination)
|
||||
|
||||
pkey_attr = Ash.Resource.Info.attribute(first_relationship.destination, pkey_attr)
|
||||
|
||||
|
|
19
lib/join.ex
19
lib/join.ex
|
@ -264,16 +264,15 @@ defmodule AshPostgres.Join do
|
|||
)
|
||||
end
|
||||
|
||||
parent_bindings =
|
||||
%{
|
||||
base_bindings
|
||||
| resource: relationship.source,
|
||||
calculations: %{},
|
||||
parent_resources: [],
|
||||
aggregate_defs: %{},
|
||||
context: relationship.context,
|
||||
current: parent_binding + 1
|
||||
}
|
||||
parent_bindings = %{
|
||||
base_bindings
|
||||
| resource: relationship.source,
|
||||
calculations: %{},
|
||||
parent_resources: [],
|
||||
aggregate_defs: %{},
|
||||
context: relationship.context,
|
||||
current: parent_binding + 1
|
||||
}
|
||||
|
||||
parent_bindings =
|
||||
if bindings do
|
||||
|
|
|
@ -180,10 +180,25 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
{other, other.installed}
|
||||
end
|
||||
|
||||
to_install = List.wrap(repo.installed_extensions()) -- List.wrap(installed_extensions)
|
||||
requesteds =
|
||||
repo.installed_extensions()
|
||||
|> Enum.map(fn
|
||||
extension_module when is_atom(extension_module) ->
|
||||
{ext_name, version, _up_fn, _down_fn} = extension = extension_module.extension()
|
||||
|
||||
{"#{ext_name}_v#{version}", extension}
|
||||
|
||||
extension_name ->
|
||||
{extension_name, extension_name}
|
||||
end)
|
||||
|
||||
to_install =
|
||||
if "ash-functions" in repo.installed_extensions() &&
|
||||
requesteds
|
||||
|> Enum.filter(fn {name, _extension} -> !Enum.member?(installed_extensions, name) end)
|
||||
|> Enum.map(fn {_name, extension} -> extension end)
|
||||
|
||||
to_install =
|
||||
if "ash-functions" in requesteds &&
|
||||
extensions_snapshot[:ash_functions_version] !=
|
||||
@latest_ash_functions_version do
|
||||
Enum.uniq(["ash-functions" | to_install])
|
||||
|
@ -197,6 +212,10 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
else
|
||||
{module, migration_name} =
|
||||
case to_install do
|
||||
[{ext_name, version, _up_fn, _down_fn}] ->
|
||||
{"install_#{ext_name}_v#{version}",
|
||||
"#{timestamp(true)}_install_#{ext_name}_v#{version}_extension"}
|
||||
|
||||
[single] ->
|
||||
{"install_#{single}", "#{timestamp(true)}_install_#{single}_extension"}
|
||||
|
||||
|
@ -222,6 +241,9 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
"ash-functions" ->
|
||||
install_ash_functions(extensions_snapshot[:ash_functions_version])
|
||||
|
||||
{_ext_name, version, up_fn, _down_fn} when is_function(up_fn, 1) ->
|
||||
up_fn.(version)
|
||||
|
||||
extension ->
|
||||
"execute(\"CREATE EXTENSION IF NOT EXISTS \\\"#{extension}\\\"\")"
|
||||
end)
|
||||
|
@ -231,6 +253,9 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
"ash-functions" ->
|
||||
"execute(\"DROP FUNCTION IF EXISTS ash_elixir_and(BOOLEAN, ANYCOMPATIBLE), ash_elixir_and(ANYCOMPATIBLE, ANYCOMPATIBLE), ash_elixir_or(ANYCOMPATIBLE, ANYCOMPATIBLE), ash_elixir_or(BOOLEAN, ANYCOMPATIBLE)\")"
|
||||
|
||||
{_ext_name, version, _up_fn, down_fn} when is_function(down_fn, 1) ->
|
||||
down_fn.(version)
|
||||
|
||||
extension ->
|
||||
"# execute(\"DROP EXTENSION IF EXISTS \\\"#{extension}\\\"\")"
|
||||
end)
|
||||
|
@ -257,12 +282,14 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
end
|
||||
"""
|
||||
|
||||
installed = Enum.map(requesteds, fn {name, _extension} -> name end)
|
||||
|
||||
snapshot_contents =
|
||||
Jason.encode!(
|
||||
%{
|
||||
installed: repo.installed_extensions()
|
||||
installed: installed
|
||||
}
|
||||
|> set_ash_functions(repo.installed_extensions()),
|
||||
|> set_ash_functions(installed),
|
||||
pretty: true
|
||||
)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"ash-functions",
|
||||
"uuid-ossp",
|
||||
"pg_trgm",
|
||||
"citext"
|
||||
"citext",
|
||||
"demo-functions_v1"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
defmodule AshPostgres.TestRepo.Migrations.InstallDemoFunctionsV0 do
|
||||
@moduledoc """
|
||||
Installs any extensions that are mentioned in the repo's `installed_extensions/0` callback
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
execute("""
|
||||
CREATE OR REPLACE FUNCTION ash_demo_functions()
|
||||
RETURNS boolean AS $$ SELECT TRUE $$
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE;
|
||||
""")
|
||||
end
|
||||
|
||||
def down do
|
||||
# Uncomment this if you actually want to uninstall the extensions
|
||||
# when this migration is rolled back:
|
||||
execute("""
|
||||
DROP FUNCTION IF EXISTS ash_demo_functions()
|
||||
""")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
defmodule AshPostgres.TestRepo.Migrations.InstallDemoFunctionsV1 do
|
||||
@moduledoc """
|
||||
Installs any extensions that are mentioned in the repo's `installed_extensions/0` callback
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
execute("""
|
||||
CREATE OR REPLACE FUNCTION ash_demo_functions()
|
||||
RETURNS boolean AS $$ SELECT FALSE $$
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE;
|
||||
""")
|
||||
end
|
||||
|
||||
def down do
|
||||
# Uncomment this if you actually want to uninstall the extensions
|
||||
# when this migration is rolled back:
|
||||
execute("""
|
||||
DROP FUNCTION IF EXISTS ash_demo_functions()
|
||||
""")
|
||||
end
|
||||
end
|
38
test/support/test_custom_extension.ex
Normal file
38
test/support/test_custom_extension.ex
Normal file
|
@ -0,0 +1,38 @@
|
|||
defmodule AshPostgres.TestCustomExtension do
|
||||
@moduledoc false
|
||||
|
||||
use AshPostgres.CustomExtension, name: "demo-functions", latest_version: 1
|
||||
|
||||
@impl true
|
||||
def install(0) do
|
||||
"""
|
||||
execute(\"\"\"
|
||||
CREATE OR REPLACE FUNCTION ash_demo_functions()
|
||||
RETURNS boolean AS $$ SELECT TRUE $$
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE;
|
||||
\"\"\")
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def install(1) do
|
||||
"""
|
||||
execute(\"\"\"
|
||||
CREATE OR REPLACE FUNCTION ash_demo_functions()
|
||||
RETURNS boolean AS $$ SELECT FALSE $$
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE;
|
||||
\"\"\")
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def uninstall(_version) do
|
||||
"""
|
||||
execute(\"\"\"
|
||||
DROP FUNCTION IF EXISTS ash_demo_functions()
|
||||
\"\"\")
|
||||
"""
|
||||
end
|
||||
end
|
|
@ -8,7 +8,7 @@ defmodule AshPostgres.TestNoSandboxRepo do
|
|||
end
|
||||
|
||||
def installed_extensions do
|
||||
["ash-functions", "uuid-ossp", "pg_trgm", "citext"] --
|
||||
["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] --
|
||||
Application.get_env(:ash_postgres, :no_extensions, [])
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule AshPostgres.TestRepo do
|
|||
end
|
||||
|
||||
def installed_extensions do
|
||||
["ash-functions", "uuid-ossp", "pg_trgm", "citext"] --
|
||||
["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] --
|
||||
Application.get_env(:ash_postgres, :no_extensions, [])
|
||||
end
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"ash_functions_version": 1,
|
||||
"installed": [
|
||||
"ash-functions",
|
||||
"uuid-ossp",
|
||||
"pg_trgm",
|
||||
"citext"
|
||||
],
|
||||
"ash_functions_version": 1
|
||||
"citext",
|
||||
"demo-functions_v1"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue