-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 => <>, 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 => <>, 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, []).