Current section

Files

Jump to
squirrel src squirrel@internal@query.erl
Raw

src/squirrel@internal@query.erl

-module(squirrel@internal@query).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([add_types/3, string/1, var/2, list/1, 'fun'/3, record/2, decoder/2, pipe_call/3, to_function/1, from_file/1]).
-export_type(['query'/0, typed_query/0]).
-type 'query'() :: {'query', binary(), binary(), binary()}.
-type typed_query() :: {typed_query,
binary(),
binary(),
binary(),
list(squirrel@internal@gleam:type()),
list(squirrel@internal@gleam:field())}.
-spec add_types(
'query'(),
list(squirrel@internal@gleam:type()),
list(squirrel@internal@gleam:field())
) -> typed_query().
add_types(Query, Params, Returns) ->
{'query', File, Name, Content} = Query,
{typed_query, File, Name, Content, Params, Returns}.
-spec take_name(bitstring(), bitstring(), integer()) -> binary().
take_name(Original, String, Size) ->
case String of
<<>> ->
_assert_subject = gleam_stdlib:bit_array_slice(Original, 0, Size),
{ok, Name} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"take_name"/utf8>>,
line => 95})
end,
_assert_subject@1 = gleam@bit_array:to_string(Name),
{ok, Name@1} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"take_name"/utf8>>,
line => 96})
end,
gleam@string:trim(Name@1);
<<"\n"/utf8, _/bitstring>> ->
_assert_subject = gleam_stdlib:bit_array_slice(Original, 0, Size),
{ok, Name} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"take_name"/utf8>>,
line => 95})
end,
_assert_subject@1 = gleam@bit_array:to_string(Name),
{ok, Name@1} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"take_name"/utf8>>,
line => 96})
end,
gleam@string:trim(Name@1);
<<_, Rest/bitstring>> ->
take_name(Original, Rest, Size + 1);
_ ->
erlang:error(#{gleam_error => panic,
message => <<"non byte aligned Gleam String"/utf8>>,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"take_name"/utf8>>,
line => 100})
end.
-spec name_comment(bitstring()) -> {ok, binary()} | {error, nil}.
name_comment(String) ->
case String of
<<" "/utf8, Rest/bitstring>> ->
name_comment(Rest);
<<"\t"/utf8, Rest/bitstring>> ->
name_comment(Rest);
<<"\r"/utf8, Rest/bitstring>> ->
name_comment(Rest);
<<"name:"/utf8, Rest@1/bitstring>> ->
{ok, take_name(Rest@1, Rest@1, 0)};
<<_, _/bitstring>> ->
{error, nil};
<<>> ->
{error, nil};
_ ->
erlang:error(#{gleam_error => panic,
message => <<"non byte aligned Gleam String"/utf8>>,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"name_comment"/utf8>>,
line => 88})
end.
-spec gleam_type_to_decoder(squirrel@internal@gleam:type()) -> binary().
gleam_type_to_decoder(Type_) ->
case Type_ of
{list, Type_@1} ->
<<<<"decode.list("/utf8, (gleam_type_to_decoder(Type_@1))/binary>>/binary,
")"/utf8>>;
int ->
<<"decode.int"/utf8>>;
float ->
<<"decode.float"/utf8>>;
bool ->
<<"decode.bool"/utf8>>;
string ->
<<"decode.string"/utf8>>;
{option, Type_@2} ->
<<<<"decode.option("/utf8, (gleam_type_to_decoder(Type_@2))/binary>>/binary,
")"/utf8>>
end.
-spec gleam_type_to_encoder(squirrel@internal@gleam:type(), binary()) -> binary().
gleam_type_to_encoder(Type_, Name) ->
case Type_ of
{list, Type_@1} ->
<<<<"pgo.array(list.map(name, fn(a) {"/utf8,
(gleam_type_to_encoder(Type_@1, <<"a"/utf8>>))/binary>>/binary,
"}))"/utf8>>;
{option, Type_@2} ->
<<<<<<<<"pgo.nullable(fn(a) {"/utf8,
(gleam_type_to_encoder(Type_@2, <<"a"/utf8>>))/binary>>/binary,
"}, "/utf8>>/binary,
Name/binary>>/binary,
")"/utf8>>;
int ->
<<<<"pgo.int("/utf8, Name/binary>>/binary, ")"/utf8>>;
float ->
<<<<"pgo.float("/utf8, Name/binary>>/binary, ")"/utf8>>;
bool ->
<<<<"pgo.bool("/utf8, Name/binary>>/binary, ")"/utf8>>;
string ->
<<<<"pgo.text("/utf8, Name/binary>>/binary, ")"/utf8>>
end.
-spec string(binary()) -> glam@doc:document().
string(Content) ->
Escaped_string = begin
_pipe = Content,
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>),
glam@doc:from_string(_pipe@2)
end,
_pipe@3 = [glam@doc:from_string(<<"\""/utf8>>),
Escaped_string,
glam@doc:from_string(<<"\""/utf8>>)],
glam@doc:concat(_pipe@3).
-spec var(binary(), glam@doc:document()) -> glam@doc:document().
var(Name, Body) ->
_pipe@3 = [glam@doc:from_string(
<<<<"let "/utf8, Name/binary>>/binary, " ="/utf8>>
),
begin
_pipe = [{break, <<" "/utf8>>, <<""/utf8>>}, Body],
_pipe@1 = glam@doc:concat(_pipe),
_pipe@2 = glam@doc:group(_pipe@1),
glam@doc:nest(_pipe@2, 2)
end],
glam@doc:concat(_pipe@3).
-spec block(list(glam@doc:document())) -> glam@doc:document().
block(Body) ->
_pipe@2 = [glam@doc:from_string(<<"{"/utf8>>),
begin
_pipe = [{line, 1} | Body],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:nest(_pipe@1, 2)
end,
{line, 1},
glam@doc:from_string(<<"}"/utf8>>)],
_pipe@3 = glam@doc:concat(_pipe@2),
glam@doc:force_break(_pipe@3).
-spec call_block(binary(), list(glam@doc:document())) -> glam@doc:document().
call_block(Function, Body) ->
_pipe = [glam@doc:from_string(<<Function/binary, "("/utf8>>),
block(Body),
glam@doc:from_string(<<")"/utf8>>)],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:group(_pipe@1).
-spec comma_list(binary(), list(glam@doc:document()), binary()) -> glam@doc:document().
comma_list(Open, Content, Close) ->
_pipe@3 = [glam@doc:from_string(Open),
begin
_pipe = [{break, <<""/utf8>>, <<""/utf8>>},
glam@doc:join(
Content,
glam@doc:break(<<", "/utf8>>, <<","/utf8>>)
)],
_pipe@1 = glam@doc:concat(_pipe),
_pipe@2 = glam@doc:group(_pipe@1),
glam@doc:nest(_pipe@2, 2)
end,
glam@doc:break(<<""/utf8>>, <<","/utf8>>),
glam@doc:from_string(Close)],
_pipe@4 = glam@doc:concat(_pipe@3),
glam@doc:group(_pipe@4).
-spec list(list(glam@doc:document())) -> glam@doc:document().
list(Elems) ->
comma_list(<<"["/utf8>>, Elems, <<"]"/utf8>>).
-spec 'fun'(binary(), list(binary()), list(glam@doc:document())) -> glam@doc:document().
'fun'(Name, Args, Body) ->
Args@1 = gleam@list:map(Args, fun glam@doc:from_string/1),
_pipe@1 = [glam@doc:from_string(<<"pub fn "/utf8, Name/binary>>),
comma_list(<<"("/utf8>>, Args@1, <<") "/utf8>>),
block(
[begin
_pipe = Body,
glam@doc:join(_pipe, glam@doc:lines(2))
end]
),
{line, 1}],
_pipe@2 = glam@doc:concat(_pipe@1),
glam@doc:group(_pipe@2).
-spec call(binary(), list(glam@doc:document())) -> glam@doc:document().
call(Function, Args) ->
_pipe = [glam@doc:from_string(Function),
comma_list(<<"("/utf8>>, Args, <<")"/utf8>>)],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:group(_pipe@1).
-spec pretty_gleam_type(squirrel@internal@gleam:type()) -> glam@doc:document().
pretty_gleam_type(Type_) ->
case Type_ of
{list, Type_@1} ->
call(<<"List"/utf8>>, [pretty_gleam_type(Type_@1)]);
{option, Type_@2} ->
call(<<"Option"/utf8>>, [pretty_gleam_type(Type_@2)]);
int ->
glam@doc:from_string(<<"Int"/utf8>>);
float ->
glam@doc:from_string(<<"Float"/utf8>>);
bool ->
glam@doc:from_string(<<"Bool"/utf8>>);
string ->
glam@doc:from_string(<<"String"/utf8>>)
end.
-spec record(binary(), list(squirrel@internal@gleam:field())) -> glam@doc:document().
record(Name, Fields) ->
Fields@1 = gleam@list:map(
Fields,
fun(Field) ->
_pipe = [glam@doc:from_string(
<<(erlang:element(2, Field))/binary, ": "/utf8>>
),
pretty_gleam_type(erlang:element(3, Field))],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:group(_pipe@1)
end
),
_pipe@4 = [glam@doc:from_string(
<<<<"pub type "/utf8, Name/binary>>/binary, " {"/utf8>>
),
begin
_pipe@2 = [{line, 1}, call(Name, Fields@1)],
_pipe@3 = glam@doc:concat(_pipe@2),
glam@doc:nest(_pipe@3, 2)
end,
{line, 1},
glam@doc:from_string(<<"}"/utf8>>)],
_pipe@5 = glam@doc:concat(_pipe@4),
glam@doc:group(_pipe@5).
-spec decoder(binary(), list(squirrel@internal@gleam:field())) -> glam@doc:document().
decoder(Constructor, Returns) ->
Parameters = gleam@list:map(
Returns,
fun(Field) ->
glam@doc:from_string(
<<<<"use "/utf8, (erlang:element(2, Field))/binary>>/binary,
" <- decode.parameter"/utf8>>
)
end
),
Pipes = gleam@list:index_map(
Returns,
fun(Field@1, I) ->
Position = begin
_pipe = gleam@int:to_string(I),
glam@doc:from_string(_pipe)
end,
Decoder = begin
_pipe@1 = gleam_type_to_decoder(erlang:element(3, Field@1)),
glam@doc:from_string(_pipe@1)
end,
call(<<"|> decode.field"/utf8>>, [Position, Decoder])
end
),
Labelled_names = gleam@list:map(
Returns,
fun(Field@2) ->
glam@doc:from_string(
<<<<(erlang:element(2, Field@2))/binary, ": "/utf8>>/binary,
(erlang:element(2, Field@2))/binary>>
)
end
),
_pipe@2 = [call_block(
<<"decode.into"/utf8>>,
[glam@doc:join(Parameters, {line, 1}),
{line, 1},
call(Constructor, Labelled_names)]
),
{line, 1},
glam@doc:join(Pipes, {line, 1})],
_pipe@3 = glam@doc:concat(_pipe@2),
glam@doc:group(_pipe@3).
-spec pipe_call(binary(), glam@doc:document(), list(glam@doc:document())) -> glam@doc:document().
pipe_call(Function, First, Rest) ->
_pipe = [First, {line, 1}, call(<<"|> "/utf8, Function/binary>>, Rest)],
glam@doc:concat(_pipe).
-spec to_function(typed_query()) -> binary().
to_function(Query) ->
{typed_query, File, Name, Content, Params, Returns} = Query,
Arg_name = fun(I) ->
<<"arg_"/utf8, (gleam@int:to_string(I + 1))/binary>>
end,
Inputs = gleam@list:index_map(Params, fun(_, I@1) -> Arg_name(I@1) end),
Inputs_encoders = gleam@list:index_map(
Params,
fun(P, I@2) -> _pipe = gleam_type_to_encoder(P, Arg_name(I@2)),
glam@doc:from_string(_pipe) end
),
Record_doc = <<<<<<<<"/// A row you get from running the `"/utf8,
Name/binary>>/binary,
"` query
/// defined in `"/utf8>>/binary,
File/binary>>/binary,
"`.
///
/// > 🐿️ This type definition was generated automatically using v1.0.0 of the
/// > [squirrel package](link!!).
///"/utf8>>,
Fun_doc = <<<<<<<<"/// Runs the `"/utf8, Name/binary>>/binary,
"` query
/// defined in `"/utf8>>/binary,
File/binary>>/binary,
"`.
///
/// > 🐿️ This function was generated automatically using v1.0.0 of the
/// > [squirrel package](link!!).
///"/utf8>>,
Name@1 = squirrel@internal@gleam:to_function_name(Name),
Constructor_name = <<(justin:pascal_case(Name@1))/binary, "Row"/utf8>>,
_pipe@1 = [glam@doc:from_string(Record_doc),
{line, 1},
record(Constructor_name, Returns),
glam@doc:lines(2),
glam@doc:from_string(Fun_doc),
{line, 1},
'fun'(
Name@1,
[<<"db"/utf8>> | Inputs],
[var(<<"decoder"/utf8>>, decoder(Constructor_name, Returns)),
pipe_call(
<<"pgo.execute"/utf8>>,
string(Content),
[glam@doc:from_string(<<"db"/utf8>>),
list(Inputs_encoders),
glam@doc:from_string(<<"decode.from(decoder, _)"/utf8>>)]
)]
)],
_pipe@2 = glam@doc:concat(_pipe@1),
glam@doc:to_string(_pipe@2, 80).
-spec parse_query(
binary(),
bitstring(),
bitstring(),
binary(),
integer(),
integer(),
list('query'())
) -> list('query'()).
parse_query(File, Original, String, Name, Start, Position, Queries) ->
case String of
<<>> ->
_assert_subject = gleam_stdlib:bit_array_slice(
Original,
Start,
Position - Start
),
{ok, Query} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_query"/utf8>>,
line => 115})
end,
_assert_subject@1 = gleam@bit_array:to_string(Query),
{ok, Content} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_query"/utf8>>,
line => 116})
end,
Query@1 = {'query', File, Name, Content},
lists:reverse([Query@1 | Queries]);
<<"--"/utf8, Rest/bitstring>> ->
case name_comment(Rest) of
{error, _} ->
parse_query(
File,
Original,
Rest,
Name,
Start,
Position + 2,
Queries
);
{ok, _} ->
_assert_subject@2 = gleam_stdlib:bit_array_slice(
Original,
Start,
Position - Start
),
{ok, Query@2} = case _assert_subject@2 of
{ok, _} -> _assert_subject@2;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@2,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_query"/utf8>>,
line => 127})
end,
_assert_subject@3 = gleam@bit_array:to_string(Query@2),
{ok, Content@1} = case _assert_subject@3 of
{ok, _} -> _assert_subject@3;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@3,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_query"/utf8>>,
line => 129})
end,
Query@3 = {'query', File, Name, Content@1},
parse_queries(
File,
Original,
String,
Position,
[Query@3 | Queries]
)
end;
<<_, Rest@1/bitstring>> ->
parse_query(
File,
Original,
Rest@1,
Name,
Start,
Position + 1,
Queries
);
_ ->
erlang:error(#{gleam_error => panic,
message => <<"non byte aligned Gleam String"/utf8>>,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_query"/utf8>>,
line => 138})
end.
-spec parse_queries(
binary(),
bitstring(),
bitstring(),
integer(),
list('query'())
) -> list('query'()).
parse_queries(File, Original, String, Position, Queries) ->
case String of
<<>> ->
lists:reverse(Queries);
<<"--"/utf8, Rest/bitstring>> ->
case name_comment(Rest) of
{error, _} ->
parse_queries(File, Original, Rest, Position + 2, Queries);
{ok, Name} ->
parse_query(
File,
Original,
Rest,
Name,
Position,
Position + 2,
Queries
)
end;
<<_, Rest@1/bitstring>> ->
parse_queries(File, Original, Rest@1, Position + 1, Queries);
_ ->
erlang:error(#{gleam_error => panic,
message => <<"non byte aligned Gleam String"/utf8>>,
module => <<"squirrel/internal/query"/utf8>>,
function => <<"parse_queries"/utf8>>,
line => 73})
end.
-spec from_file(binary()) -> {ok, list('query'())} |
{error, simplifile:file_error()}.
from_file(File) ->
gleam@result:map(
simplifile:read(File),
fun(Content) ->
Content@1 = <<Content/binary>>,
parse_queries(File, Content@1, Content@1, 0, [])
end
).