Current section
Files
Jump to
Current section
Files
src/parrot@codegen.erl
-module(parrot@codegen).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([gleam_type_to_string/1, sqlc_type_to_gleam/1, gen_column_name/2, gen_query_type/1, gen_query_function/1, gen_query_decoder/1, comment_dont_edit/0, gen_gleam_module/1, codegen_from_config/1]).
-export_type([gleam_type/0]).
-type gleam_type() :: gleam_string |
gleam_int |
gleam_float |
gleam_bool |
gleam_timestamp |
gleam_dynamic.
-file("src/parrot/codegen.gleam", 70).
-spec gleam_type_to_string(gleam_type()) -> binary().
gleam_type_to_string(Gleamtype) ->
case Gleamtype of
gleam_bool ->
<<"Bool"/utf8>>;
gleam_float ->
<<"Float"/utf8>>;
gleam_int ->
<<"Int"/utf8>>;
gleam_string ->
<<"String"/utf8>>;
gleam_timestamp ->
<<"Timestamp"/utf8>>;
gleam_dynamic ->
<<"decode.Dynamic"/utf8>>
end.
-file("src/parrot/codegen.gleam", 81).
-spec sqlc_type_to_gleam(binary()) -> gleam_type().
sqlc_type_to_gleam(Sqltype) ->
Sqltype@1 = case Sqltype of
<<"pg_catalog."/utf8, X/binary>> ->
X;
X@1 ->
X@1
end,
case string:lowercase(Sqltype@1) of
<<"int"/utf8, _/binary>> ->
gleam_int;
<<"integer"/utf8>> ->
gleam_int;
<<"bigint"/utf8>> ->
gleam_int;
<<"bigserial"/utf8>> ->
gleam_int;
<<"float"/utf8>> ->
gleam_float;
<<"decimal"/utf8>> ->
gleam_float;
<<"real"/utf8>> ->
gleam_float;
<<"numeric"/utf8>> ->
gleam_float;
<<"double precision"/utf8>> ->
gleam_float;
<<"smallserial"/utf8>> ->
gleam_float;
<<"serial"/utf8>> ->
gleam_float;
<<"bigserial"/utf8>> ->
gleam_float;
<<"text"/utf8>> ->
gleam_string;
<<"varchar"/utf8>> ->
gleam_string;
<<"uuid"/utf8>> ->
gleam_string;
<<"datetime"/utf8>> ->
gleam_timestamp;
<<"timestamp"/utf8>> ->
gleam_timestamp;
_ ->
gleam_dynamic
end.
-file("src/parrot/codegen.gleam", 102).
-spec gen_column_name(
parrot@internal@sqlc:'query'(),
parrot@internal@sqlc:table_column()
) -> binary().
gen_column_name(Query, Col) ->
Occ = begin
_pipe = erlang:element(6, Query),
gleam@list:count(
_pipe,
fun(Col2) -> erlang:element(2, Col) =:= erlang:element(2, Col2) end
)
end,
Result = case Occ of
0 ->
erlang:error(#{gleam_error => panic,
message => <<"could not find column name"/utf8>>,
module => <<"parrot/codegen"/utf8>>,
function => <<"gen_column_name"/utf8>>,
line => 107});
1 ->
erlang:element(2, Col);
_ ->
case erlang:element(15, Col) of
none ->
erlang:element(2, Col);
{some, T} ->
<<<<(erlang:element(4, T))/binary, "_"/utf8>>/binary,
(erlang:element(2, Col))/binary>>
end
end,
parrot@internal@string_case:snake_case(Result).
-file("src/parrot/codegen.gleam", 119).
-spec gen_query_type(parrot@internal@sqlc:'query'()) -> binary().
gen_query_type(Query) ->
Name = parrot@internal@string_case:pascal_case(erlang:element(3, Query)),
Args = begin
_pipe = erlang:element(6, Query),
_pipe@1 = gleam@list:map(
_pipe,
fun(Col) ->
Gleam_type = sqlc_type_to_gleam(
erlang:element(4, erlang:element(16, Col))
),
Col_type = gleam_type_to_string(Gleam_type),
Col_type@1 = case erlang:element(3, Col) of
true ->
Col_type;
false ->
<<<<"Option("/utf8, Col_type/binary>>/binary, ")"/utf8>>
end,
Col_name = gen_column_name(Query, Col),
<<<<Col_name/binary, ": "/utf8>>/binary, Col_type@1/binary>>
end
),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Str) -> <<" "/utf8, Str/binary>> end
),
gleam@string:join(_pipe@2, <<",\n"/utf8>>)
end,
_pipe@3 = [<<<<"pub type "/utf8, Name/binary>>/binary, " {"/utf8>>,
<<<<" "/utf8, Name/binary>>/binary, "("/utf8>>,
Args,
<<" )"/utf8>>,
<<"}"/utf8>>],
gleam@string:join(_pipe@3, <<"\n"/utf8>>).
-file("src/parrot/codegen.gleam", 141).
-spec gen_query_function(parrot@internal@sqlc:'query'()) -> binary().
gen_query_function(Query) ->
Fn_name = parrot@internal@string_case:snake_case(erlang:element(3, Query)),
Def_fn_args = begin
_pipe = erlang:element(9, Query),
_pipe@1 = gleam@list:map(
_pipe,
fun(P) ->
Gleam_type = sqlc_type_to_gleam(
erlang:element(4, erlang:element(16, erlang:element(3, P)))
),
<<<<(erlang:element(2, erlang:element(3, P)))/binary,
": "/utf8>>/binary,
(gleam_type_to_string(Gleam_type))/binary>>
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
Def_return_params = case erlang:element(9, Query) of
[] ->
<<"Nil"/utf8>>;
Args ->
<<<<"["/utf8,
(begin
_pipe@2 = Args,
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Arg) ->
Arg_type = sqlc_type_to_gleam(
erlang:element(
4,
erlang:element(
16,
erlang:element(3, Arg)
)
)
),
Param = case Arg_type of
gleam_int ->
<<"sql.ParamInt"/utf8>>;
gleam_string ->
<<"sql.ParamString"/utf8>>;
gleam_float ->
<<"sql.ParamFloat"/utf8>>;
gleam_bool ->
<<"sql.ParamBool"/utf8>>;
gleam_timestamp ->
<<"sql.ParamTimestamp"/utf8>>;
gleam_dynamic ->
<<"sql.ParamDynamic"/utf8>>
end,
<<<<<<Param/binary, "("/utf8>>/binary,
(erlang:element(
2,
erlang:element(3, Arg)
))/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end)/binary>>/binary,
"]"/utf8>>
end,
Def_fn = <<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary, "("/utf8>>/binary,
Def_fn_args/binary>>/binary,
")"/utf8>>,
Def_sql = <<<<"let sql = \""/utf8, (erlang:element(2, Query))/binary>>/binary,
"\""/utf8>>,
Def_return = <<<<"#(sql, "/utf8, Def_return_params/binary>>/binary,
")"/utf8>>,
_pipe@4 = [<<Def_fn/binary, "{"/utf8>>,
<<" "/utf8, Def_sql/binary>>,
<<" "/utf8, Def_return/binary>>,
<<"}"/utf8>>],
gleam@string:join(_pipe@4, <<"\n"/utf8>>).
-file("src/parrot/codegen.gleam", 181).
-spec gen_query_decoder(parrot@internal@sqlc:'query'()) -> binary().
gen_query_decoder(Query) ->
case erlang:length(erlang:element(6, Query)) of
0 ->
<<""/utf8>>;
_ ->
Type_name = parrot@internal@string_case:pascal_case(
erlang:element(3, Query)
),
Fn_name = <<(parrot@internal@string_case:snake_case(
erlang:element(3, Query)
))/binary,
"_decoder"/utf8>>,
Decoder_fields = begin
_pipe = erlang:element(6, Query),
_pipe@1 = gleam@list:index_map(
_pipe,
fun(Col, Index) ->
Col_type = sqlc_type_to_gleam(
erlang:element(4, erlang:element(16, Col))
),
Decoder_type = case Col_type of
gleam_int ->
<<"decode.int"/utf8>>;
gleam_string ->
<<"decode.string"/utf8>>;
gleam_bool ->
<<"decode.bool"/utf8>>;
gleam_float ->
<<"decode.float"/utf8>>;
gleam_timestamp ->
<<"sql.datetime_decoder()"/utf8>>;
gleam_dynamic ->
<<"decode.dynamic"/utf8>>
end,
Decoder = case erlang:element(3, Col) of
true ->
Decoder_type;
false ->
<<<<"decode.optional("/utf8,
Decoder_type/binary>>/binary,
")"/utf8>>
end,
Col_name = gen_column_name(Query, Col),
<<<<<<<<<<<<" use "/utf8, Col_name/binary>>/binary,
" <- decode.field("/utf8>>/binary,
(erlang:integer_to_binary(Index))/binary>>/binary,
", "/utf8>>/binary,
Decoder/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Constructor_args = begin
_pipe@2 = erlang:element(6, Query),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Col@1) ->
<<(gen_column_name(Query, Col@1))/binary, ": "/utf8>>
end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end,
Success_line = <<<<<<<<" decode.success("/utf8, Type_name/binary>>/binary,
"("/utf8>>/binary,
Constructor_args/binary>>/binary,
"))"/utf8>>,
<<<<<<<<<<<<<<<<"\n\npub fn "/utf8, Fn_name/binary>>/binary,
"() -> decode.Decoder("/utf8>>/binary,
Type_name/binary>>/binary,
") {\n"/utf8>>/binary,
Decoder_fields/binary>>/binary,
"\n"/utf8>>/binary,
Success_line/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/parrot/codegen.gleam", 52).
-spec gen_query(parrot@internal@sqlc:'query'()) -> binary().
gen_query(Query) ->
Type_str = case erlang:length(erlang:element(6, Query)) of
0 ->
<<""/utf8>>;
_ ->
<<(gen_query_type(Query))/binary, "\n\n"/utf8>>
end,
<<<<Type_str/binary, (gen_query_function(Query))/binary>>/binary,
(gen_query_decoder(Query))/binary>>.
-file("src/parrot/codegen.gleam", 280).
-spec comment_dont_edit() -> binary().
comment_dont_edit() ->
_pipe = <<"
//// Code generated by parrot. DO NOT EDIT.
////
"/utf8>>,
parrot@internal@lib:dedent(_pipe).
-file("src/parrot/codegen.gleam", 238).
-spec gen_gleam_module(parrot@internal@sqlc:sqlc()) -> binary().
gen_gleam_module(Schema) ->
Queries = begin
_pipe = erlang:element(6, Schema),
_pipe@1 = gleam@list:map(_pipe, fun gen_query/1),
gleam@string:join(_pipe@1, <<"\n\n"/utf8>>)
end,
Uses_timestamp = gleam@list:any(
erlang:element(6, Schema),
fun(Query) ->
Col_ts = gleam@list:any(
erlang:element(6, Query),
fun(Col) ->
case sqlc_type_to_gleam(
erlang:element(4, erlang:element(16, Col))
) of
gleam_timestamp ->
true;
_ ->
false
end
end
),
Param_ts = gleam@list:any(
erlang:element(9, Query),
fun(Param) ->
case sqlc_type_to_gleam(
erlang:element(
4,
erlang:element(16, erlang:element(3, Param))
)
) of
gleam_timestamp ->
true;
_ ->
false
end
end
),
gleam@bool:'or'(Col_ts, Param_ts)
end
),
Timestamp_import = case Uses_timestamp of
false ->
<<""/utf8>>;
true ->
<<"import gleam/time/timestamp.{type Timestamp}\n"/utf8>>
end,
Imports = <<<<<<<<<<"import gleam/option.{type Option}"/utf8, "\n"/utf8>>/binary,
"import gleam/dynamic/decode"/utf8>>/binary,
"\n"/utf8>>/binary,
Timestamp_import/binary>>/binary,
"import parrot/sql"/utf8>>,
<<<<<<<<(comment_dont_edit())/binary, "\n\n"/utf8>>/binary, Imports/binary>>/binary,
"\n\n"/utf8>>/binary,
Queries/binary>>.
-file("src/parrot/codegen.gleam", 18).
-spec codegen_from_config(parrot@config:config()) -> {ok, nil} | {error, nil}.
codegen_from_config(Config) ->
parrot@internal@lib:try_nil(
parrot@config:get_json_file(Config),
fun(Json_string) ->
parrot@internal@lib:try_nil(
gleam@json:parse(
Json_string,
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
),
fun(Dyn_json) ->
_assert_subject = parrot@internal@sqlc:decode_sqlc(Dyn_json),
{ok, Parsed} = 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 => <<"parrot/codegen"/utf8>>,
function => <<"codegen_from_config"/utf8>>,
line => 23})
end,
gleam@list:each(
erlang:element(6, Parsed),
fun(Query) ->
gleam@list:each(
erlang:element(6, Query),
fun(Col) ->
case sqlc_type_to_gleam(
erlang:element(
4,
erlang:element(16, Col)
)
) of
gleam_dynamic ->
gleam_stdlib:println(
parrot@internal@colored:yellow(
<<"unknown column type: "/utf8,
(erlang:element(
4,
erlang:element(
16,
Col
)
))/binary>>
)
);
_ ->
nil
end
end
)
end
),
gleam_stdlib:println(<<""/utf8>>),
Module_contents = gen_gleam_module(Parsed),
_ = begin
_pipe = parrot@config:get_module_directory(Config),
simplifile:create_directory_all(_pipe)
end,
_ = simplifile:write(
parrot@config:get_module_path(Config),
Module_contents
),
{ok, nil}
end
)
end
).