2021-09-21 08:38:36 +12:00
defmodule AshPostgres.CustomIndex do
@moduledoc false
2023-04-27 14:23:43 +12:00
@fields [
2021-09-21 08:38:36 +12:00
:table ,
:fields ,
:name ,
:unique ,
:concurrently ,
:using ,
:prefix ,
:where ,
2022-11-26 08:06:22 +13:00
:include ,
:message
2021-09-21 08:38:36 +12:00
]
2023-04-27 14:23:43 +12:00
defstruct @fields
def fields , do : @fields
2021-09-21 08:38:36 +12:00
@schema [
fields : [
2022-11-26 08:06:22 +13:00
type : { :list , { :or , [ :atom , :string ] } } ,
2021-09-21 08:38:36 +12:00
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
] ,
concurrently : [
type : :boolean ,
doc : " indicates whether the index should be created/dropped concurrently. " ,
default : false
] ,
using : [
type : :string ,
doc : " configures the index type. "
] ,
prefix : [
type : :string ,
doc : " specify an optional prefix for the index. "
] ,
where : [
type : :string ,
doc : " specify conditions for a partial index. "
] ,
2022-11-26 08:06:22 +13:00
message : [
type : :string ,
doc : " A custom message to use for unique indexes that have been violated "
] ,
2021-09-21 08:38:36 +12:00
include : [
type : { :list , :string } ,
doc :
" specify fields for a covering index. This is not supported by all databases. For more information on PostgreSQL support, please read the official docs. "
]
]
def schema , do : @schema
2022-11-26 08:06:22 +13:00
# sobelow_skip ["DOS.StringToAtom"]
def transform ( % __MODULE__ { fields : fields } = index ) do
2023-06-06 17:33:50 +12:00
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
2022-11-26 08:06:22 +13:00
end
2021-09-21 08:38:36 +12:00
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 _] " , " _ " ) )
2022-01-25 11:59:31 +13:00
|> Enum . map_join ( " _ " , & String . replace_trailing ( &1 , " _ " , " " ) )
2021-09-21 08:38:36 +12:00
|> String . to_atom ( )
end
end