mirror of
https://github.com/ash-project/ash_postgres.git
synced 2024-09-19 13:03:14 +12:00
chore: perf fixes, build, and test
This commit is contained in:
parent
f80b157d06
commit
9191bd3269
7 changed files with 68 additions and 89 deletions
|
@ -25,8 +25,8 @@ defmodule AshPostgres.Igniter do
|
|||
{igniter, {:ok, value}} when is_binary(value) or is_nil(value) ->
|
||||
{:ok, igniter, value}
|
||||
|
||||
_ ->
|
||||
:error
|
||||
{igniter, _} ->
|
||||
{:error, igniter}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,8 +37,8 @@ defmodule AshPostgres.Igniter do
|
|||
{igniter, {:ok, value}} when is_atom(value) ->
|
||||
{:ok, igniter, value}
|
||||
|
||||
_ ->
|
||||
:error
|
||||
{igniter, _} ->
|
||||
{:error, igniter}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do
|
|||
|
||||
@shortdoc "Generates or updates resources based on a database schema"
|
||||
|
||||
@doc """
|
||||
@moduledoc """
|
||||
#{@shortdoc}
|
||||
|
||||
## Example
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
defmodule AshPostgres.ResourceGenerator do
|
||||
@moduledoc false
|
||||
alias AshPostgres.ResourceGenerator.Spec
|
||||
|
||||
require Logger
|
||||
|
@ -6,26 +7,9 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
def generate(igniter, repos, domain, opts \\ []) do
|
||||
{igniter, resources} = Ash.Resource.Igniter.list_resources(igniter)
|
||||
|
||||
resources =
|
||||
Task.async_stream(resources, fn resource ->
|
||||
{resource, AshPostgres.Igniter.repo(igniter, resource),
|
||||
AshPostgres.Igniter.table(igniter, resource)}
|
||||
end)
|
||||
|> Enum.map(fn {:ok, {resource, repo, table}} ->
|
||||
repo =
|
||||
case repo do
|
||||
{:ok, _igniter, repo} -> repo
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
table =
|
||||
case table do
|
||||
{:ok, _igniter, table} -> table
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
{resource, repo, table}
|
||||
end)
|
||||
# This is a hack. We should be looking at compiled resources
|
||||
# unlikely to ever matter given how this task will be used though.
|
||||
resources = Enum.filter(resources, &Code.ensure_loaded?/1)
|
||||
|
||||
igniter = Igniter.include_all_elixir_files(igniter)
|
||||
|
||||
|
@ -140,8 +124,6 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
end
|
||||
|
||||
defp check_constraints(%{check_constraints: check_constraints}, _) do
|
||||
IO.inspect(check_constraints)
|
||||
|
||||
check_constraints =
|
||||
Enum.map_join(check_constraints, "\n", fn check_constraint ->
|
||||
"""
|
||||
|
@ -158,9 +140,8 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
|
||||
defp skip_unique_indexes(%{indexes: indexes}) do
|
||||
indexes
|
||||
|> Enum.filter(& &1.unique?)
|
||||
|> Enum.filter(fn %{columns: columns} ->
|
||||
Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
|> Enum.filter(fn %{unique?: unique?, columns: columns} ->
|
||||
unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
end)
|
||||
|> Enum.reject(&index_as_identity?/1)
|
||||
|> case do
|
||||
|
@ -176,9 +157,8 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
|
||||
defp identity_index_names(%{indexes: indexes}) do
|
||||
indexes
|
||||
|> Enum.filter(& &1.unique?)
|
||||
|> Enum.filter(fn %{columns: columns} ->
|
||||
Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
|> Enum.filter(fn %{unique?: unique?, columns: columns} ->
|
||||
unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
end)
|
||||
|> case do
|
||||
[] ->
|
||||
|
@ -195,9 +175,8 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
|
||||
defp add_identities(str, %{indexes: indexes}) do
|
||||
indexes
|
||||
|> Enum.filter(& &1.unique?)
|
||||
|> Enum.filter(fn %{columns: columns} ->
|
||||
Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
|> Enum.filter(fn %{unique?: unique?, columns: columns} ->
|
||||
unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1))
|
||||
end)
|
||||
|> Enum.map(fn index ->
|
||||
name = index.name
|
||||
|
@ -431,10 +410,8 @@ defmodule AshPostgres.ResourceGenerator do
|
|||
defp custom_indexes(table_spec, true) do
|
||||
table_spec.indexes
|
||||
|> Enum.reject(fn index ->
|
||||
!index.unique? || (&index_as_identity?/1)
|
||||
end)
|
||||
|> Enum.reject(fn index ->
|
||||
Enum.any?(index.columns, &String.contains?(&1, "("))
|
||||
!index.unique? || (&index_as_identity?/1) ||
|
||||
Enum.any?(index.columns, &String.contains?(&1, "("))
|
||||
end)
|
||||
|> case do
|
||||
[] ->
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
defmodule AshPostgres.ResourceGenerator.SensitiveData do
|
||||
@moduledoc false
|
||||
# I got this from ChatGPT, but this is a best effort transformation
|
||||
# anyway.
|
||||
@sensitive_patterns [
|
||||
|
@ -65,7 +66,7 @@ defmodule AshPostgres.ResourceGenerator.SensitiveData do
|
|||
~r/.*_token/i
|
||||
]
|
||||
|
||||
def is_sensitive?(column_name) do
|
||||
def sensitive?(column_name) do
|
||||
Enum.any?(@sensitive_patterns, fn pattern ->
|
||||
Regex.match?(pattern, column_name)
|
||||
end)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
defmodule AshPostgres.ResourceGenerator.Spec do
|
||||
@moduledoc false
|
||||
require Logger
|
||||
|
||||
defstruct [
|
||||
|
@ -15,6 +16,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
]
|
||||
|
||||
defmodule Attribute do
|
||||
@moduledoc false
|
||||
defstruct [
|
||||
:name,
|
||||
:type,
|
||||
|
@ -31,6 +33,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
end
|
||||
|
||||
defmodule ForeignKey do
|
||||
@moduledoc false
|
||||
defstruct [
|
||||
:constraint_name,
|
||||
:match_type,
|
||||
|
@ -44,14 +47,17 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
end
|
||||
|
||||
defmodule Index do
|
||||
@moduledoc false
|
||||
defstruct [:name, :columns, :unique?, :nulls_distinct, :where_clause, :using, :include]
|
||||
end
|
||||
|
||||
defmodule CheckConstraint do
|
||||
@moduledoc false
|
||||
defstruct [:name, :column, :expression]
|
||||
end
|
||||
|
||||
defmodule Relationship do
|
||||
@moduledoc false
|
||||
defstruct [
|
||||
:name,
|
||||
:type,
|
||||
|
@ -71,7 +77,6 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
Ecto.Migrator.with_repo(repo, fn repo ->
|
||||
repo
|
||||
|> table_specs(opts)
|
||||
|> verify_found_tables(opts)
|
||||
|> Enum.group_by(&Enum.take(&1, 2), fn [_, _, field, type, default, size, allow_nil?] ->
|
||||
name = Macro.underscore(field)
|
||||
|
||||
|
@ -421,39 +426,6 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
raise "Unexpected character: #{inspect(other)} at #{inspect(stack)} with #{inspect(field)} - #{inspect(acc)}"
|
||||
end
|
||||
|
||||
defp verify_found_tables(specs, opts) do
|
||||
if opts[:tables] do
|
||||
not_found =
|
||||
Enum.reject(opts[:tables], fn table ->
|
||||
if String.ends_with?(table, ".") do
|
||||
true
|
||||
else
|
||||
case String.split(table, ".") do
|
||||
[schema, table] ->
|
||||
Enum.any?(specs, fn spec ->
|
||||
Enum.at(spec, 0) == table and Enum.at(spec, 1) == schema
|
||||
end)
|
||||
|
||||
[table] ->
|
||||
Enum.any?(specs, fn spec ->
|
||||
Enum.at(spec, 0) == table
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
case not_found do
|
||||
[] ->
|
||||
specs
|
||||
|
||||
tables ->
|
||||
raise "The following tables did not exist: #{inspect(tables)}"
|
||||
end
|
||||
else
|
||||
specs
|
||||
end
|
||||
end
|
||||
|
||||
defp build_attributes(attributes, table_name, schema, repo, opts) do
|
||||
attributes
|
||||
|> set_primary_key(table_name, schema, repo)
|
||||
|
@ -546,9 +518,9 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
|> Enum.flat_map(fn {repo, specs} ->
|
||||
do_add_relationships(
|
||||
specs,
|
||||
Enum.flat_map(resources, fn {resource, resource_repo, table} ->
|
||||
if resource_repo == repo do
|
||||
[{resource, table}]
|
||||
Enum.flat_map(resources, fn resource ->
|
||||
if AshPostgres.DataLayer.Info.repo(resource) == repo do
|
||||
[{resource, AshPostgres.DataLayer.Info.table(resource)}]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
@ -918,7 +890,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|
|||
Enum.map(attributes, fn attribute ->
|
||||
%{
|
||||
attribute
|
||||
| sensitive?: AshPostgres.ResourceGenerator.SensitiveData.is_sensitive?(attribute.name)
|
||||
| sensitive?: AshPostgres.ResourceGenerator.SensitiveData.sensitive?(attribute.name)
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -3,6 +3,7 @@ defmodule AshPostgres.RelWithParentFilterTest do
|
|||
|
||||
setup do
|
||||
AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS example_table")
|
||||
|
||||
AshPostgres.TestRepo.query!("CREATE TABLE example_table (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
|
@ -10,18 +11,45 @@ defmodule AshPostgres.RelWithParentFilterTest do
|
|||
email VARCHAR(255)
|
||||
)")
|
||||
|
||||
on_exit(fn ->
|
||||
AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS example_table")
|
||||
end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "a resource is generated from a table" do
|
||||
Igniter.new()
|
||||
|> Igniter.compose_task("ash_postgres.gen.resources", [
|
||||
"MyApp.Accounts",
|
||||
"--tables",
|
||||
"example_table",
|
||||
"--yes"
|
||||
])
|
||||
resource =
|
||||
Igniter.new()
|
||||
|> Igniter.compose_task("ash_postgres.gen.resources", [
|
||||
"MyApp.Accounts",
|
||||
"--tables",
|
||||
"example_table",
|
||||
"--yes"
|
||||
])
|
||||
|> Igniter.prepare_for_write()
|
||||
|> Map.get(:rewrite)
|
||||
|> Rewrite.source!("lib/my_app/accounts/example_table.ex")
|
||||
|> Rewrite.Source.get(:content)
|
||||
|
||||
assert String.trim(resource) ==
|
||||
String.trim("""
|
||||
defmodule MyApp.Accounts.ExampleTable do
|
||||
use Ash.Resource,
|
||||
domain: MyApp.Accounts,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
|
||||
postgres do
|
||||
table "example_table"
|
||||
repo AshPostgres.TestRepo
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:name, :string)
|
||||
attribute(:age, :integer)
|
||||
|
||||
attribute :email, :string do
|
||||
sensitive?(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
""")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,6 +50,7 @@ defmodule HasNoComments do
|
|||
end
|
||||
|
||||
defmodule CiCategory do
|
||||
@moduledoc false
|
||||
use Ash.Type.NewType,
|
||||
subtype_of: :ci_string
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue