-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 ).