Current section
Files
Jump to
Current section
Files
src/galchemy@orm@loading.erl
-module(galchemy@orm@loading).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src\\galchemy\\orm\\loading.gleam").
-export([joinedload/2, selectinload/2, 'query'/1, apply/3, selectin_queries/2]).
-export_type([loader_option/0, select_in_plan/0, applied_options/0, loading_error/0]).
-type loader_option() :: {joined_load, binary(), galchemy@orm@query:model_ref()} |
{select_in_load, binary(), galchemy@orm@query:model_ref()}.
-type select_in_plan() :: {select_in_plan,
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref()}.
-type applied_options() :: {applied_options,
galchemy@ast@expression:select_query(),
list(select_in_plan())}.
-type loading_error() :: {query_error, galchemy@orm@query:query_error()} |
{missing_parent_field,
galchemy@schema@relation:table_ref(),
binary(),
binary()}.
-file("src\\galchemy\\orm\\loading.gleam", 38).
-spec joinedload(binary(), galchemy@orm@query:model_ref()) -> loader_option().
joinedload(Relation_name, Related_model) ->
{joined_load, Relation_name, Related_model}.
-file("src\\galchemy\\orm\\loading.gleam", 45).
-spec selectinload(binary(), galchemy@orm@query:model_ref()) -> loader_option().
selectinload(Relation_name, Related_model) ->
{select_in_load, Relation_name, Related_model}.
-file("src\\galchemy\\orm\\loading.gleam", 60).
-spec 'query'(applied_options()) -> galchemy@ast@expression:select_query().
'query'(Applied) ->
erlang:element(2, Applied).
-file("src\\galchemy\\orm\\loading.gleam", 306).
-spec relation_plan(
galchemy@orm@query:model_ref(),
binary(),
galchemy@orm@query:model_ref()
) -> {ok, galchemy@schema@relation:relation()} |
{error, galchemy@orm@query:query_error()}.
relation_plan(Parent_model, Relation_name, Related_model) ->
case galchemy@orm@metadata:relation_named(
erlang:element(2, Parent_model),
Relation_name
) of
none ->
{error,
{unknown_relation,
erlang:element(2, erlang:element(2, Parent_model)),
Relation_name}};
{some, Next_relation} ->
case erlang:element(5, Next_relation) =:= erlang:element(
2,
erlang:element(2, Related_model)
) of
true ->
{ok, Next_relation};
false ->
{error,
{related_table_mismatch,
erlang:element(2, Next_relation),
erlang:element(5, Next_relation),
erlang:element(2, erlang:element(2, Related_model))}}
end
end.
-file("src\\galchemy\\orm\\loading.gleam", 330).
-spec find_field(list(galchemy@session@unit_of_work:field_value()), binary()) -> gleam@option:option(galchemy@ast@expression:sql_value()).
find_field(Fields, Column_name) ->
case Fields of
[] ->
none;
[Field_value | Rest] ->
case erlang:element(2, Field_value) =:= Column_name of
true ->
{some, erlang:element(3, Field_value)};
false ->
find_field(Rest, Column_name)
end
end.
-file("src\\galchemy\\orm\\loading.gleam", 289).
-spec parent_field_value(
galchemy@orm@query:model_ref(),
binary(),
galchemy@orm@entity:entity(),
binary()
) -> {ok, galchemy@ast@expression:sql_value()} | {error, loading_error()}.
parent_field_value(Parent_model, Relation_name, Parent, Column_name) ->
case find_field(galchemy@orm@entity:fields(Parent), Column_name) of
{some, Value} ->
{ok, Value};
none ->
{error,
{missing_parent_field,
erlang:element(2, erlang:element(2, Parent_model)),
Relation_name,
Column_name}}
end.
-file("src\\galchemy\\orm\\loading.gleam", 345).
-spec map_query_error({ok, PCB} | {error, galchemy@orm@query:query_error()}) -> {ok,
PCB} |
{error, loading_error()}.
map_query_error(Value) ->
case Value of
{ok, Inner} ->
{ok, Inner};
{error, Error} ->
{error, {query_error, Error}}
end.
-file("src\\galchemy\\orm\\loading.gleam", 354).
-spec result_try(
{ok, PCG} | {error, PCH},
fun((PCG) -> {ok, PCK} | {error, PCH})
) -> {ok, PCK} | {error, PCH}.
result_try(Value, Next) ->
case Value of
{ok, Inner} ->
Next(Inner);
{error, Error} ->
{error, Error}
end.
-file("src\\galchemy\\orm\\loading.gleam", 71).
-spec apply_loop(
galchemy@ast@expression:select_query(),
galchemy@orm@query:model_ref(),
list(loader_option()),
list(select_in_plan())
) -> {ok, applied_options()} | {error, loading_error()}.
apply_loop(Query, Parent_model, Options, Select_in) ->
case Options of
[] ->
{ok, {applied_options, Query, lists:reverse(Select_in)}};
[Next_option | Rest] ->
case Next_option of
{joined_load, Relation_name, Related_model} ->
result_try(
begin
_pipe = galchemy@orm@query:left_join_relation(
Query,
Parent_model,
Relation_name,
Related_model
),
map_query_error(_pipe)
end,
fun(Next_query) ->
apply_loop(
Next_query,
Parent_model,
Rest,
Select_in
)
end
);
{select_in_load, Relation_name@1, Related_model@1} ->
result_try(
begin
_pipe@1 = relation_plan(
Parent_model,
Relation_name@1,
Related_model@1
),
map_query_error(_pipe@1)
end,
fun(Next_relation) ->
apply_loop(
Query,
Parent_model,
Rest,
[{select_in_plan,
Parent_model,
Next_relation,
Related_model@1} |
Select_in]
)
end
)
end
end.
-file("src\\galchemy\\orm\\loading.gleam", 52).
-spec apply(
galchemy@ast@expression:select_query(),
galchemy@orm@query:model_ref(),
list(loader_option())
) -> {ok, applied_options()} | {error, loading_error()}.
apply(Query, Parent_model, Options) ->
apply_loop(Query, Parent_model, Options, []).
-file("src\\galchemy\\orm\\loading.gleam", 265).
-spec pair_predicate(
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref(),
galchemy@orm@entity:entity(),
galchemy@schema@relation:column_pair()
) -> {ok, galchemy@ast@expression:predicate()} | {error, loading_error()}.
pair_predicate(Parent_model, Next_relation, Related_model, Parent, Next_pair) ->
result_try(
parent_field_value(
Parent_model,
erlang:element(2, Next_relation),
Parent,
erlang:element(2, Next_pair)
),
fun(Value) ->
{ok,
{comparison,
{column_expr,
{column_meta,
erlang:element(3, Related_model),
erlang:element(3, Next_pair)}},
eq,
{value_expr, Value}}}
end
).
-file("src\\galchemy\\orm\\loading.gleam", 234).
-spec parent_predicate_rest(
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref(),
galchemy@orm@entity:entity(),
list(galchemy@schema@relation:column_pair()),
galchemy@ast@expression:predicate()
) -> {ok, galchemy@ast@expression:predicate()} | {error, loading_error()}.
parent_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Parent,
Pairs,
Acc
) ->
case Pairs of
[] ->
{ok, Acc};
[Next_pair | Rest] ->
result_try(
pair_predicate(
Parent_model,
Next_relation,
Related_model,
Parent,
Next_pair
),
fun(Next_predicate) ->
parent_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Parent,
Rest,
{'and', Acc, Next_predicate}
)
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 205).
-spec parent_predicate(
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref(),
galchemy@orm@entity:entity()
) -> {ok, galchemy@ast@expression:predicate()} | {error, loading_error()}.
parent_predicate(Parent_model, Next_relation, Related_model, Parent) ->
case erlang:element(6, Next_relation) of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"relation metadata requires at least one column pair"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"galchemy/orm/loading"/utf8>>,
function => <<"parent_predicate"/utf8>>,
line => 212});
[First_pair | Rest] ->
result_try(
pair_predicate(
Parent_model,
Next_relation,
Related_model,
Parent,
First_pair
),
fun(Initial) ->
parent_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Parent,
Rest,
Initial
)
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 177).
-spec selectin_predicate_rest(
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref(),
list(galchemy@orm@entity:entity()),
galchemy@ast@expression:predicate()
) -> {ok, galchemy@ast@expression:predicate()} | {error, loading_error()}.
selectin_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Parents,
Acc
) ->
case Parents of
[] ->
{ok, Acc};
[Next_parent | Rest] ->
result_try(
parent_predicate(
Parent_model,
Next_relation,
Related_model,
Next_parent
),
fun(Next_predicate) ->
selectin_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Rest,
{'or', Acc, Next_predicate}
)
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 150).
-spec selectin_predicate(
galchemy@orm@query:model_ref(),
galchemy@schema@relation:relation(),
galchemy@orm@query:model_ref(),
list(galchemy@orm@entity:entity())
) -> {ok, galchemy@ast@expression:predicate()} | {error, loading_error()}.
selectin_predicate(Parent_model, Next_relation, Related_model, Parents) ->
case Parents of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"selectin predicate requires at least one parent"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"galchemy/orm/loading"/utf8>>,
function => <<"selectin_predicate"/utf8>>,
line => 157});
[First_parent | Rest] ->
result_try(
parent_predicate(
Parent_model,
Next_relation,
Related_model,
First_parent
),
fun(Initial) ->
selectin_predicate_rest(
Parent_model,
Next_relation,
Related_model,
Rest,
Initial
)
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 128).
-spec selectin_query(select_in_plan(), list(galchemy@orm@entity:entity())) -> {ok,
galchemy@ast@query:'query'()} |
{error, loading_error()}.
selectin_query(Plan, Parents) ->
case Parents of
[] ->
{ok,
{select, galchemy@orm@query:select_all(erlang:element(4, Plan))}};
_ ->
result_try(
selectin_predicate(
erlang:element(2, Plan),
erlang:element(3, Plan),
erlang:element(4, Plan),
Parents
),
fun(Where_) ->
{ok,
{select,
begin
_pipe = galchemy@orm@query:select_all(
erlang:element(4, Plan)
),
galchemy@orm@query:where_(_pipe, Where_)
end}}
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 114).
-spec build_selectin_queries(
list(select_in_plan()),
list(galchemy@orm@entity:entity()),
list(galchemy@ast@query:'query'())
) -> {ok, list(galchemy@ast@query:'query'())} | {error, loading_error()}.
build_selectin_queries(Plans, Parents, Acc) ->
case Plans of
[] ->
{ok, lists:reverse(Acc)};
[Next_plan | Rest] ->
result_try(
selectin_query(Next_plan, Parents),
fun(Next_query) ->
build_selectin_queries(Rest, Parents, [Next_query | Acc])
end
)
end.
-file("src\\galchemy\\orm\\loading.gleam", 64).
-spec selectin_queries(applied_options(), list(galchemy@orm@entity:entity())) -> {ok,
list(galchemy@ast@query:'query'())} |
{error, loading_error()}.
selectin_queries(Applied, Parents) ->
build_selectin_queries(erlang:element(3, Applied), Parents, []).