Current section
Files
Jump to
Current section
Files
src/galchemy@orm@declarative.erl
-module(galchemy@orm@declarative).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src\\galchemy\\orm\\declarative.gleam").
-export([model_/4, identity/2, nullable/1, default/2, primary_key/1, unique/1, pair/2, belongs_to/5, has_many/5, small_int/1, int/1, big_int/1, text/1, varchar/2, bool/1, float/1, real/1, numeric/3, timestamp/1, timestamptz/1, date/1, time_of_day/1, timetz/1, uuid/1, json/1, jsonb/1, bytea/1, array/2, custom/2, custom_with/2, to_metadata/1, to_table_schema/1, to_snapshot/1]).
-export_type([column/0, relation_definition/0, relation_kind/0, model/0, declarative_error/0]).
-type column() :: {column,
binary(),
galchemy@schema@model:column_type(),
boolean(),
gleam@option:option(binary()),
boolean(),
boolean()}.
-type relation_definition() :: {relation_definition,
binary(),
binary(),
relation_kind(),
galchemy@schema@relation:table_ref(),
list(galchemy@schema@relation:column_pair())}.
-type relation_kind() :: belongs_to | has_many.
-type model() :: {model,
galchemy@schema@relation:table_ref(),
list(column()),
gleam@option:option(list(binary())),
list(relation_definition())}.
-type declarative_error() :: {duplicate_column,
galchemy@schema@relation:table_ref(),
binary()} |
{duplicate_relation, galchemy@schema@relation:table_ref(), binary()} |
{missing_identity, galchemy@schema@relation:table_ref()} |
{unknown_identity_column, galchemy@schema@relation:table_ref(), binary()} |
{unknown_local_column, galchemy@schema@relation:table_ref(), binary()}.
-file("src\\galchemy\\orm\\declarative.gleam", 51).
-spec model_(binary(), binary(), list(column()), list(relation_definition())) -> model().
model_(Schema_name, Table_name, Columns, Relations) ->
{model,
galchemy@schema@relation:table_ref(Schema_name, Table_name),
Columns,
none,
Relations}.
-file("src\\galchemy\\orm\\declarative.gleam", 65).
-spec identity(model(), list(binary())) -> model().
identity(Next_model, Columns) ->
{model,
erlang:element(2, Next_model),
erlang:element(3, Next_model),
{some, Columns},
erlang:element(5, Next_model)}.
-file("src\\galchemy\\orm\\declarative.gleam", 157).
-spec nullable(column()) -> column().
nullable(Next_column) ->
{column,
erlang:element(2, Next_column),
erlang:element(3, Next_column),
true,
erlang:element(5, Next_column),
erlang:element(6, Next_column),
erlang:element(7, Next_column)}.
-file("src\\galchemy\\orm\\declarative.gleam", 161).
-spec default(column(), binary()) -> column().
default(Next_column, Sql) ->
{column,
erlang:element(2, Next_column),
erlang:element(3, Next_column),
erlang:element(4, Next_column),
{some, Sql},
erlang:element(6, Next_column),
erlang:element(7, Next_column)}.
-file("src\\galchemy\\orm\\declarative.gleam", 165).
-spec primary_key(column()) -> column().
primary_key(Next_column) ->
{column,
erlang:element(2, Next_column),
erlang:element(3, Next_column),
erlang:element(4, Next_column),
erlang:element(5, Next_column),
true,
erlang:element(7, Next_column)}.
-file("src\\galchemy\\orm\\declarative.gleam", 169).
-spec unique(column()) -> column().
unique(Next_column) ->
{column,
erlang:element(2, Next_column),
erlang:element(3, Next_column),
erlang:element(4, Next_column),
erlang:element(5, Next_column),
erlang:element(6, Next_column),
true}.
-file("src\\galchemy\\orm\\declarative.gleam", 173).
-spec pair(binary(), binary()) -> galchemy@schema@relation:column_pair().
pair(Local_column, Related_column) ->
galchemy@schema@relation:pair(Local_column, Related_column).
-file("src\\galchemy\\orm\\declarative.gleam", 177).
-spec belongs_to(
binary(),
binary(),
binary(),
binary(),
list(galchemy@schema@relation:column_pair())
) -> relation_definition().
belongs_to(Name, Foreign_key_name, Related_schema, Related_table, Column_pairs) ->
{relation_definition,
Name,
Foreign_key_name,
belongs_to,
galchemy@schema@relation:table_ref(Related_schema, Related_table),
Column_pairs}.
-file("src\\galchemy\\orm\\declarative.gleam", 193).
-spec has_many(
binary(),
binary(),
binary(),
binary(),
list(galchemy@schema@relation:column_pair())
) -> relation_definition().
has_many(Name, Foreign_key_name, Related_schema, Related_table, Column_pairs) ->
{relation_definition,
Name,
Foreign_key_name,
has_many,
galchemy@schema@relation:table_ref(Related_schema, Related_table),
Column_pairs}.
-file("src\\galchemy\\orm\\declarative.gleam", 250).
-spec column(binary(), galchemy@schema@model:column_type()) -> column().
column(Name, Data_type) ->
{column, Name, Data_type, false, none, false, false}.
-file("src\\galchemy\\orm\\declarative.gleam", 69).
-spec small_int(binary()) -> column().
small_int(Name) ->
column(Name, small_int_type).
-file("src\\galchemy\\orm\\declarative.gleam", 73).
-spec int(binary()) -> column().
int(Name) ->
column(Name, integer_type).
-file("src\\galchemy\\orm\\declarative.gleam", 77).
-spec big_int(binary()) -> column().
big_int(Name) ->
column(Name, big_int_type).
-file("src\\galchemy\\orm\\declarative.gleam", 81).
-spec text(binary()) -> column().
text(Name) ->
column(Name, text_type).
-file("src\\galchemy\\orm\\declarative.gleam", 85).
-spec varchar(binary(), gleam@option:option(integer())) -> column().
varchar(Name, Length) ->
column(Name, {var_char_type, Length}).
-file("src\\galchemy\\orm\\declarative.gleam", 89).
-spec bool(binary()) -> column().
bool(Name) ->
column(Name, boolean_type).
-file("src\\galchemy\\orm\\declarative.gleam", 93).
-spec float(binary()) -> column().
float(Name) ->
column(Name, double_precision_type).
-file("src\\galchemy\\orm\\declarative.gleam", 97).
-spec real(binary()) -> column().
real(Name) ->
column(Name, real_type).
-file("src\\galchemy\\orm\\declarative.gleam", 101).
-spec numeric(
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> column().
numeric(Name, Precision, Scale) ->
column(Name, {numeric_type, Precision, Scale}).
-file("src\\galchemy\\orm\\declarative.gleam", 109).
-spec timestamp(binary()) -> column().
timestamp(Name) ->
column(Name, {timestamp_type, false}).
-file("src\\galchemy\\orm\\declarative.gleam", 113).
-spec timestamptz(binary()) -> column().
timestamptz(Name) ->
column(Name, {timestamp_type, true}).
-file("src\\galchemy\\orm\\declarative.gleam", 117).
-spec date(binary()) -> column().
date(Name) ->
column(Name, date_type).
-file("src\\galchemy\\orm\\declarative.gleam", 121).
-spec time_of_day(binary()) -> column().
time_of_day(Name) ->
column(Name, {time_type, false}).
-file("src\\galchemy\\orm\\declarative.gleam", 125).
-spec timetz(binary()) -> column().
timetz(Name) ->
column(Name, {time_type, true}).
-file("src\\galchemy\\orm\\declarative.gleam", 129).
-spec uuid(binary()) -> column().
uuid(Name) ->
column(Name, uuid_type).
-file("src\\galchemy\\orm\\declarative.gleam", 133).
-spec json(binary()) -> column().
json(Name) ->
column(Name, json_type).
-file("src\\galchemy\\orm\\declarative.gleam", 137).
-spec jsonb(binary()) -> column().
jsonb(Name) ->
column(Name, jsonb_type).
-file("src\\galchemy\\orm\\declarative.gleam", 141).
-spec bytea(binary()) -> column().
bytea(Name) ->
column(Name, bytea_type).
-file("src\\galchemy\\orm\\declarative.gleam", 145).
-spec array(binary(), galchemy@schema@model:column_type()) -> column().
array(Name, Item_type) ->
column(Name, {array_type, Item_type}).
-file("src\\galchemy\\orm\\declarative.gleam", 149).
-spec custom(binary(), binary()) -> column().
custom(Name, Type_name) ->
column(Name, {custom_type, Type_name}).
-file("src\\galchemy\\orm\\declarative.gleam", 153).
-spec custom_with(binary(), galchemy@orm@codec:custom_codec(any())) -> column().
custom_with(Name, Next_type) ->
column(Name, {custom_type, galchemy@orm@codec:sql_type_name(Next_type)}).
-file("src\\galchemy\\orm\\declarative.gleam", 278).
-spec validate_columns(
galchemy@schema@relation:table_ref(),
list(column()),
list(binary())
) -> {ok, nil} | {error, declarative_error()}.
validate_columns(Table, Columns, Known) ->
case Columns of
[] ->
{ok, nil};
[Next_column | Rest] ->
case gleam@list:contains(Known, erlang:element(2, Next_column)) of
true ->
{error,
{duplicate_column,
Table,
erlang:element(2, Next_column)}};
false ->
validate_columns(
Table,
Rest,
[erlang:element(2, Next_column) | Known]
)
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 414).
-spec unique_columns(list(column())) -> list(binary()).
unique_columns(Columns) ->
gleam@list:filter_map(
Columns,
fun(Next_column) -> case erlang:element(7, Next_column) of
true ->
{ok, erlang:element(2, Next_column)};
false ->
{error, nil}
end end
).
-file("src\\galchemy\\orm\\declarative.gleam", 395).
-spec inferred_identity(list(column())) -> list(binary()).
inferred_identity(Columns) ->
Primary_keys = gleam@list:filter_map(
Columns,
fun(Next_column) -> case erlang:element(6, Next_column) of
true ->
{ok, erlang:element(2, Next_column)};
false ->
{error, nil}
end end
),
case Primary_keys of
[] ->
case unique_columns(Columns) of
[First | _] ->
[First];
[] ->
[]
end;
_ ->
Primary_keys
end.
-file("src\\galchemy\\orm\\declarative.gleam", 384).
-spec identity_columns(model()) -> {ok, list(binary())} |
{error, declarative_error()}.
identity_columns(Next_model) ->
case erlang:element(4, Next_model) of
{some, Columns} ->
{ok, Columns};
none ->
case inferred_identity(erlang:element(3, Next_model)) of
[] ->
{error, {missing_identity, erlang:element(2, Next_model)}};
Columns@1 ->
{ok, Columns@1}
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 423).
-spec column_schemas(
list(column()),
integer(),
list(galchemy@schema@model:column_schema())
) -> list(galchemy@schema@model:column_schema()).
column_schemas(Columns, Ordinal_position, Acc) ->
case Columns of
[] ->
lists:reverse(Acc);
[Next_column | Rest] ->
column_schemas(
Rest,
Ordinal_position + 1,
[{column_schema,
erlang:element(2, Next_column),
erlang:element(3, Next_column),
erlang:element(4, Next_column),
erlang:element(5, Next_column),
Ordinal_position} |
Acc]
)
end.
-file("src\\galchemy\\orm\\declarative.gleam", 444).
-spec primary_key_schema(model()) -> gleam@option:option(galchemy@schema@model:primary_key()).
primary_key_schema(Next_model) ->
Primary_keys = gleam@list:filter_map(
erlang:element(3, Next_model),
fun(Next_column) -> case erlang:element(6, Next_column) of
true ->
{ok, erlang:element(2, Next_column)};
false ->
{error, nil}
end end
),
case Primary_keys of
[] ->
none;
Columns ->
{some,
{primary_key,
<<(erlang:element(3, erlang:element(2, Next_model)))/binary,
"_pkey"/utf8>>,
Columns}}
end.
-file("src\\galchemy\\orm\\declarative.gleam", 463).
-spec unique_constraints(model()) -> list(galchemy@schema@model:unique_constraint()).
unique_constraints(Next_model) ->
_pipe = unique_columns(erlang:element(3, Next_model)),
gleam@list:map(
_pipe,
fun(Column_name) ->
{unique_constraint,
<<<<<<(erlang:element(3, erlang:element(2, Next_model)))/binary,
"_"/utf8>>/binary,
Column_name/binary>>/binary,
"_key"/utf8>>,
[Column_name]}
end
).
-file("src\\galchemy\\orm\\declarative.gleam", 473).
-spec relation_metadata(list(relation_definition())) -> list(galchemy@schema@relation:relation()).
relation_metadata(Relations) ->
gleam@list:map(
Relations,
fun(Next_relation) -> case erlang:element(4, Next_relation) of
belongs_to ->
galchemy@schema@relation:belongs_to(
erlang:element(2, Next_relation),
erlang:element(3, Next_relation),
erlang:element(5, Next_relation),
erlang:element(6, Next_relation)
);
has_many ->
galchemy@schema@relation:has_many(
erlang:element(2, Next_relation),
erlang:element(3, Next_relation),
erlang:element(5, Next_relation),
erlang:element(6, Next_relation)
)
end end
).
-file("src\\galchemy\\orm\\declarative.gleam", 496).
-spec foreign_keys(list(relation_definition())) -> list(galchemy@schema@model:foreign_key()).
foreign_keys(Relations) ->
gleam@list:filter_map(
Relations,
fun(Next_relation) -> case erlang:element(4, Next_relation) of
belongs_to ->
{ok,
{foreign_key,
erlang:element(3, Next_relation),
gleam@list:map(
erlang:element(6, Next_relation),
fun(Next_pair) ->
erlang:element(2, Next_pair)
end
),
erlang:element(2, erlang:element(5, Next_relation)),
erlang:element(3, erlang:element(5, Next_relation)),
gleam@list:map(
erlang:element(6, Next_relation),
fun(Next_pair@1) ->
erlang:element(3, Next_pair@1)
end
)}};
has_many ->
{error, nil}
end end
).
-file("src\\galchemy\\orm\\declarative.gleam", 530).
-spec has_column(list(column()), binary()) -> boolean().
has_column(Columns, Column_name) ->
case Columns of
[] ->
false;
[Next_column | Rest] ->
case erlang:element(2, Next_column) =:= Column_name of
true ->
true;
false ->
has_column(Rest, Column_name)
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 323).
-spec validate_relation_columns(
galchemy@schema@relation:table_ref(),
list(column()),
list(galchemy@schema@relation:column_pair())
) -> {ok, nil} | {error, declarative_error()}.
validate_relation_columns(Table, Columns, Pairs) ->
case Pairs of
[] ->
{ok, nil};
[Next_pair | Rest] ->
case has_column(Columns, erlang:element(2, Next_pair)) of
true ->
validate_relation_columns(Table, Columns, Rest);
false ->
{error,
{unknown_local_column,
Table,
erlang:element(2, Next_pair)}}
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 368).
-spec validate_identity_columns_rest(
galchemy@schema@relation:table_ref(),
list(column()),
list(binary())
) -> {ok, nil} | {error, declarative_error()}.
validate_identity_columns_rest(Table, Columns, Identity_columns) ->
case Identity_columns of
[] ->
{ok, nil};
[Next_column | Rest] ->
case has_column(Columns, Next_column) of
true ->
validate_identity_columns_rest(Table, Columns, Rest);
false ->
{error, {unknown_identity_column, Table, Next_column}}
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 352).
-spec validate_identity_columns(
galchemy@schema@relation:table_ref(),
list(column()),
list(binary())
) -> {ok, nil} | {error, declarative_error()}.
validate_identity_columns(Table, Columns, Identity_columns) ->
case Identity_columns of
[] ->
{error, {missing_identity, Table}};
[Next_column | Rest] ->
case has_column(Columns, Next_column) of
true ->
validate_identity_columns_rest(Table, Columns, Rest);
false ->
{error, {unknown_identity_column, Table, Next_column}}
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 340).
-spec validate_identity(model()) -> {ok, nil} | {error, declarative_error()}.
validate_identity(Next_model) ->
case erlang:element(4, Next_model) of
none ->
case inferred_identity(erlang:element(3, Next_model)) of
[] ->
{error, {missing_identity, erlang:element(2, Next_model)}};
_ ->
{ok, nil}
end;
{some, Columns} ->
validate_identity_columns(
erlang:element(2, Next_model),
erlang:element(3, Next_model),
Columns
)
end.
-file("src\\galchemy\\orm\\declarative.gleam", 542).
-spec result_try(
{ok, LUO} | {error, LUP},
fun((LUO) -> {ok, LUS} | {error, LUP})
) -> {ok, LUS} | {error, LUP}.
result_try(Value, Next) ->
case Value of
{ok, Inner} ->
Next(Inner);
{error, Error} ->
{error, Error}
end.
-file("src\\galchemy\\orm\\declarative.gleam", 294).
-spec validate_relations(
galchemy@schema@relation:table_ref(),
list(column()),
list(relation_definition()),
list(binary())
) -> {ok, nil} | {error, declarative_error()}.
validate_relations(Table, Columns, Relations, Known) ->
case Relations of
[] ->
{ok, nil};
[Next_relation | Rest] ->
case gleam@list:contains(Known, erlang:element(2, Next_relation)) of
true ->
{error,
{duplicate_relation,
Table,
erlang:element(2, Next_relation)}};
false ->
result_try(
validate_relation_columns(
Table,
Columns,
erlang:element(6, Next_relation)
),
fun(_) ->
validate_relations(
Table,
Columns,
Rest,
[erlang:element(2, Next_relation) | Known]
)
end
)
end
end.
-file("src\\galchemy\\orm\\declarative.gleam", 261).
-spec validate(model()) -> {ok, model()} | {error, declarative_error()}.
validate(Next_model) ->
result_try(
validate_columns(
erlang:element(2, Next_model),
erlang:element(3, Next_model),
[]
),
fun(_) ->
result_try(
validate_relations(
erlang:element(2, Next_model),
erlang:element(3, Next_model),
erlang:element(5, Next_model),
[]
),
fun(_) ->
result_try(
validate_identity(Next_model),
fun(_) -> {ok, Next_model} end
)
end
)
end
).
-file("src\\galchemy\\orm\\declarative.gleam", 209).
-spec to_metadata(model()) -> {ok, galchemy@orm@metadata:model_metadata()} |
{error, declarative_error()}.
to_metadata(Next_model) ->
result_try(
validate(Next_model),
fun(Validated_model) ->
result_try(
identity_columns(Validated_model),
fun(Next_identity) ->
{ok,
{model_metadata,
erlang:element(2, Validated_model),
Next_identity,
gleam@list:map(
erlang:element(3, Validated_model),
fun(Next_column) ->
erlang:element(2, Next_column)
end
),
relation_metadata(
erlang:element(5, Validated_model)
)}}
end
)
end
).
-file("src\\galchemy\\orm\\declarative.gleam", 225).
-spec to_table_schema(model()) -> {ok, galchemy@schema@model:table_schema()} |
{error, declarative_error()}.
to_table_schema(Next_model) ->
result_try(
validate(Next_model),
fun(Validated_model) ->
{ok,
{table_schema,
erlang:element(2, erlang:element(2, Validated_model)),
erlang:element(3, erlang:element(2, Validated_model)),
column_schemas(erlang:element(3, Validated_model), 1, []),
primary_key_schema(Validated_model),
unique_constraints(Validated_model),
foreign_keys(erlang:element(5, Validated_model)),
[]}}
end
).
-file("src\\galchemy\\orm\\declarative.gleam", 517).
-spec table_schemas(list(model()), list(galchemy@schema@model:table_schema())) -> {ok,
list(galchemy@schema@model:table_schema())} |
{error, declarative_error()}.
table_schemas(Models, Acc) ->
case Models of
[] ->
{ok, Acc};
[Next_model | Rest] ->
result_try(
to_table_schema(Next_model),
fun(Next_table) -> table_schemas(Rest, [Next_table | Acc]) end
)
end.
-file("src\\galchemy\\orm\\declarative.gleam", 243).
-spec to_snapshot(list(model())) -> {ok,
galchemy@schema@model:schema_snapshot()} |
{error, declarative_error()}.
to_snapshot(Models) ->
result_try(
table_schemas(Models, []),
fun(Tables) -> {ok, {schema_snapshot, lists:reverse(Tables)}} end
).