ash_sqlite/lib/custom_index.ex

110 lines
2.6 KiB
Elixir
Raw Normal View History

2023-09-23 14:52:22 +12:00
defmodule AshSqlite.CustomIndex do
@moduledoc "Represents a custom index on the table backing a resource"
@fields [
:table,
:fields,
:name,
:unique,
:using,
:where,
:include,
:message
]
defstruct @fields
def fields, do: @fields
@schema [
fields: [
type: {:wrap_list, {:or, [:atom, :string]}},
doc: "The fields to include in the index."
],
name: [
type: :string,
doc: "the name of the index. Defaults to \"\#\{table\}_\#\{column\}_index\"."
],
unique: [
type: :boolean,
doc: "indicates whether the index should be unique.",
default: false
],
using: [
type: :string,
doc: "configures the index type."
],
where: [
type: :string,
doc: "specify conditions for a partial index."
],
message: [
type: :string,
doc: "A custom message to use for unique indexes that have been violated"
],
include: [
type: {:list, :string},
doc:
"specify fields for a covering index. This is not supported by all databases. For more information on SQLite support, please read the official docs."
]
]
def schema, do: @schema
# sobelow_skip ["DOS.StringToAtom"]
def transform(%__MODULE__{fields: fields} = index) do
index = %{
index
| fields:
Enum.map(fields, fn field ->
if is_atom(field) do
field
else
String.to_atom(field)
end
end)
}
cond do
index.name ->
if Regex.match?(~r/^[0-9a-zA-Z_]+$/, index.name) do
{:ok, index}
else
{:error,
"Custom index name #{index.name} is not valid. Must have letters, numbers and underscores only"}
end
mismatched_field =
Enum.find(index.fields, fn field ->
!Regex.match?(~r/^[0-9a-zA-Z_]+$/, to_string(field))
end) ->
{:error,
"""
Custom index field #{mismatched_field} contains invalid index name characters.
A name must be set manually, i.e
`name: "your_desired_index_name"`
Index names must have letters, numbers and underscores only
"""}
true ->
{:ok, index}
end
end
def name(_resource, %{name: name}) when is_binary(name) do
name
end
# sobelow_skip ["DOS.StringToAtom"]
def name(table, %{fields: fields}) do
[table, fields, "index"]
|> List.flatten()
|> Enum.map(&to_string(&1))
|> Enum.map(&String.replace(&1, ~r"[^\w_]", "_"))
|> Enum.map_join("_", &String.replace_trailing(&1, "_", ""))
|> String.to_atom()
end
end