Packages

A fun, friendly, and type-safe ORM for Gleam! Compose type-safe SQL queries, generate decoders and types from schemas, and with a fun CLI!

Current section

Files

Jump to
funsies src funsies@query@yummy.erl
Raw

src/funsies@query@yummy.erl

-module(funsies@query@yummy).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([equals/3, 'not'/1, 'or'/1, 'and'/1, wb/1, new/1, select/1, where/2, order_by/3, to_sql/1, insert/2, w/1, to_insert_sql/1]).
-export_type([query_builder/0, where_builder/0, value/0, eq/0]).
-type query_builder() :: {query_builder,
funsies@schema:table(),
list(binary()),
list(eq()),
list(binary()),
list(binary()),
list(value())}.
-type where_builder() :: {where_builder, funsies@schema:table(), list(eq())}.
-type value() :: {int_value, integer()} |
{string_value, binary()} |
{bool_value, boolean()} |
{error_value, binary()}.
-type eq() :: {equals, binary(), value()} |
{'not', eq()} |
{'or', eq(), eq()} |
{'and', eq(), eq()}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 58).
-spec wrap_value(gleam@dynamic:dynamic_()) -> value().
wrap_value(Value) ->
case gleam@dynamic:bool(Value) of
{ok, Value@1} ->
{bool_value, Value@1};
{error, _} ->
case gleam@dynamic:int(Value) of
{ok, Value@2} ->
{int_value, Value@2};
{error, _} ->
case gleam@dynamic:string(Value) of
{ok, Value@3} ->
{string_value, Value@3};
{error, _} ->
{error_value, <<"Not a supported value!"/utf8>>}
end
end
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 76).
-spec to_string(value()) -> binary().
to_string(Value) ->
case Value of
{string_value, Value@1} ->
<<<<"'"/utf8, Value@1/binary>>/binary, "'"/utf8>>;
{int_value, Value@2} ->
gleam@int:to_string(Value@2);
{bool_value, Value@3} ->
gleam@bool:to_string(Value@3);
{error_value, Value@4} ->
erlang:error(#{gleam_error => panic,
message => <<"`panic` expression evaluated."/utf8>>,
module => <<"funsies/query/yummy"/utf8>>,
function => <<"to_string"/utf8>>,
line => 81})
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 85).
-spec is_right_value(value(), value()) -> boolean().
is_right_value(Value, Target) ->
case {Value, Target} of
{{int_value, _}, {int_value, _}} ->
true;
{{string_value, _}, {string_value, _}} ->
true;
{{bool_value, _}, {bool_value, _}} ->
true;
{_, _} ->
false
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 94).
-spec is_col_type(funsies@schema:table(), binary(), value()) -> boolean().
is_col_type(Table, Col, Value) ->
_assert_subject = gleam@list:find(
erlang:element(3, Table),
fun(C) -> erlang:element(2, C) =:= Col end
),
{ok, Col@1} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"funsies/query/yummy"/utf8>>,
function => <<"is_col_type"/utf8>>,
line => 95})
end,
case Col@1 of
{string_column, _, _} ->
is_right_value(Value, {string_value, <<"Test"/utf8>>});
{bool_column, _} ->
is_right_value(Value, {bool_value, true});
{foreign_key_column, _, _, _, _} ->
is_right_value(Value, {int_value, 1});
{int_column, _} ->
is_right_value(Value, {int_value, 1});
{serial_column, _} ->
is_right_value(Value, {int_value, 1})
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 111).
-spec equals(where_builder(), binary(), any()) -> where_builder().
equals(Builder, Col, Value) ->
Wrapped_value = wrap_value(gleam_stdlib:identity(Value)),
case is_col_type(erlang:element(2, Builder), Col, Wrapped_value) of
true ->
{where_builder,
erlang:element(2, Builder),
lists:append(
erlang:element(3, Builder),
[{equals, Col, Wrapped_value}]
)};
false ->
{where_builder,
erlang:element(2, Builder),
lists:append(
erlang:element(3, Builder),
[{equals, Col, {error_value, <<"Type mismatch"/utf8>>}}]
)}
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 130).
-spec 'not'(where_builder()) -> where_builder().
'not'(Builder) ->
case gleam@queue:pop_back(gleam@queue:from_list(erlang:element(3, Builder))) of
{ok, {Eq, Rest}} ->
{where_builder,
erlang:element(2, Builder),
lists:append(gleam@queue:to_list(Rest), [{'not', Eq}])};
_ ->
Builder
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 138).
-spec 'or'(where_builder()) -> where_builder().
'or'(Builder) ->
case gleam@queue:pop_back(gleam@queue:from_list(erlang:element(3, Builder))) of
{ok, {Eq1, Rest1}} ->
case gleam@queue:pop_back(Rest1) of
{ok, {Eq2, Rest2}} ->
{where_builder,
erlang:element(2, Builder),
lists:append(
gleam@queue:to_list(Rest2),
[{'or', Eq1, Eq2}]
)};
_ ->
Builder
end;
_ ->
Builder
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 155).
-spec 'and'(where_builder()) -> where_builder().
'and'(Builder) ->
case gleam@queue:pop_back(gleam@queue:from_list(erlang:element(3, Builder))) of
{ok, {Eq1, Rest1}} ->
case gleam@queue:pop_back(Rest1) of
{ok, {Eq2, Rest2}} ->
{where_builder,
erlang:element(2, Builder),
lists:append(
gleam@queue:to_list(Rest2),
[{'and', Eq1, Eq2}]
)};
_ ->
Builder
end;
_ ->
Builder
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 172).
-spec wb(funsies@schema:table()) -> where_builder().
wb(Table) ->
{where_builder, Table, []}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 193).
-spec build(gleam@queue:queue(eq()), list(binary())) -> {ok, list(binary())} |
{error, binary()}.
build(Clauses, Acc) ->
case gleam@queue:pop_back(Clauses) of
{ok, {{equals, Col, Val}, Rest}} ->
case Val of
{error_value, Err} ->
{error, Err};
_ ->
build(
Rest,
lists:append(
Acc,
[<<<<Col/binary, " = "/utf8>>/binary,
(to_string(Val))/binary>>]
)
)
end;
{ok, {{'not', Eq}, Rest@1}} ->
case build(gleam@queue:from_list([Eq]), []) of
{ok, Not_clause_list} ->
Not_clause = <<<<"NOT ("/utf8,
(gleam@string:join(
Not_clause_list,
<<" AND "/utf8>>
))/binary>>/binary,
")"/utf8>>,
build(Rest@1, lists:append(Acc, [Not_clause]));
{error, E} ->
{error, E}
end;
{ok, {{'or', Eq1, Eq2}, Rest@2}} ->
case build(gleam@queue:from_list([Eq1, Eq2]), []) of
{ok, Or_clause_list} ->
Or_clause = <<<<"("/utf8,
(gleam@string:join(Or_clause_list, <<" OR "/utf8>>))/binary>>/binary,
")"/utf8>>,
build(Rest@2, lists:append(Acc, [Or_clause]));
{error, E@1} ->
{error, E@1}
end;
{ok, {{'and', Eq1@1, Eq2@1}, Rest@3}} ->
case build(gleam@queue:from_list([Eq1@1, Eq2@1]), []) of
{ok, And_clause_list} ->
And_clause = <<<<"("/utf8,
(gleam@string:join(
And_clause_list,
<<" AND "/utf8>>
))/binary>>/binary,
")"/utf8>>,
build(Rest@3, lists:append(Acc, [And_clause]));
{error, E@2} ->
{error, E@2}
end;
_ ->
{ok, Acc}
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 176).
-spec build_where(where_builder()) -> {ok, binary()} | {error, binary()}.
build_where(Builder) ->
Clauses = gleam@queue:from_list(erlang:element(3, Builder)),
Built_clauses_result = build(Clauses, []),
case Built_clauses_result of
{ok, Built_clauses} ->
case gleam@list:is_empty(Built_clauses) of
true ->
{ok, <<""/utf8>>};
false ->
{ok,
<<" WHERE "/utf8,
(gleam@string:join(Built_clauses, <<" AND "/utf8>>))/binary>>}
end;
{error, E} ->
{error, E}
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 235).
-spec new(funsies@schema:table()) -> query_builder().
new(Table) ->
{query_builder, Table, [], [], [], [], []}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 240).
-spec select(query_builder()) -> query_builder().
select(Builder) ->
{query_builder,
erlang:element(2, Builder),
gleam@list:map(
erlang:element(3, erlang:element(2, Builder)),
fun(C) -> erlang:element(2, C) end
),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder)}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 252).
-spec where(query_builder(), where_builder()) -> query_builder().
where(Builder, Condition) ->
{query_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
lists:append(erlang:element(4, Builder), erlang:element(3, Condition)),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder)}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 265).
-spec order_by(query_builder(), binary(), binary()) -> query_builder().
order_by(Builder, Column, Direction) ->
{query_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
lists:append(
erlang:element(5, Builder),
[<<<<Column/binary, " "/utf8>>/binary, Direction/binary>>]
),
erlang:element(6, Builder),
erlang:element(7, Builder)}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 281).
-spec to_sql(query_builder()) -> {ok, binary()} | {error, binary()}.
to_sql(Builder) ->
Base_query = <<<<<<"SELECT "/utf8,
(gleam@string:join(erlang:element(3, Builder), <<", "/utf8>>))/binary>>/binary,
" FROM "/utf8>>/binary,
(erlang:element(2, erlang:element(2, Builder)))/binary>>,
Where_sql = build_where(
{where_builder, erlang:element(2, Builder), erlang:element(4, Builder)}
),
Order_by_sql = case erlang:element(5, Builder) of
[] ->
{ok, <<""/utf8>>};
Clauses ->
{ok,
<<" ORDER BY "/utf8,
(gleam@string:join(Clauses, <<", "/utf8>>))/binary>>}
end,
case {Where_sql, Order_by_sql} of
{{ok, Where_clause}, {ok, Order_clause}} ->
{ok,
<<<<<<Base_query/binary, Where_clause/binary>>/binary,
Order_clause/binary>>/binary,
";"/utf8>>};
{{error, E}, _} ->
{error, E};
{_, {error, E@1}} ->
{error, E@1}
end.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 307).
-spec insert(query_builder(), list(value())) -> query_builder().
insert(Builder, Values) ->
{query_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
gleam@list:map(
erlang:element(3, erlang:element(2, Builder)),
fun(C) -> erlang:element(2, C) end
),
Values}.
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 325).
-spec w(any()) -> value().
w(V) ->
wrap_value(gleam_stdlib:identity(V)).
-file("/Users/ashercohen/Desktop/ASHERSOPRO/funsies/src/funsies/query/yummy.gleam", 330).
-spec to_insert_sql(query_builder()) -> {ok, binary()} | {error, binary()}.
to_insert_sql(Builder) ->
case {gleam@list:is_empty(erlang:element(6, Builder)),
gleam@list:is_empty(erlang:element(7, Builder))} of
{true, false} ->
{error, <<"Insert columns and values cannot be empty"/utf8>>};
{false, true} ->
{error, <<"Insert columns and values cannot be empty"/utf8>>};
{true, true} ->
{error, <<"Empty"/utf8>>};
{_, _} ->
Columns_sql = gleam@string:join(
erlang:element(6, Builder),
<<", "/utf8>>
),
Values_sql = gleam@string:join(
gleam@list:map(erlang:element(7, Builder), fun to_string/1),
<<", "/utf8>>
),
{ok,
<<<<<<<<<<<<"INSERT INTO "/utf8,
(erlang:element(
2,
erlang:element(2, Builder)
))/binary>>/binary,
" ("/utf8>>/binary,
Columns_sql/binary>>/binary,
") VALUES ("/utf8>>/binary,
Values_sql/binary>>/binary,
");"/utf8>>}
end.