-module(sg_engine). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([root_sign_in/2, exec/1, execute_transaction/2, create_database/1, create_namespace/1, use_namespace/1, use_database/1, find_field/1, emit_fields/2, create_table_schemafull/2, create_table_schemaless/2, add_field/3, add_default_field/4, generate/1]). -spec build_request(binary(), binary(), gleam@http:method()) -> gleam@http@request:request(binary()). build_request(Base, Endpoint, Method) -> _assert_subject = gleam@http@request:to(<>), {ok, Request} = 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 => <<"sg_engine"/utf8>>, function => <<"build_request"/utf8>>, line => 19}) end, gleam@http@request:set_method(Request, Method). -spec with_token(gleam@http@request:request(binary()), binary()) -> gleam@http@request:request(binary()). with_token(Request, Token) -> _pipe = Request, gleam@http@request:prepend_header( _pipe, <<"Authorization"/utf8>>, <<"Bearer "/utf8, Token/binary>> ). -spec with_header(gleam@http@request:request(binary()), binary(), binary()) -> gleam@http@request:request(binary()). with_header(Request, Key, Value) -> _pipe = Request, gleam@http@request:prepend_header(_pipe, Key, Value). -spec execute_request(gleam@http@request:request(binary())) -> {ok, gleam@http@response:response(binary())} | {error, gleam@hackney:error()}. execute_request(Request) -> _pipe = Request, gleam@hackney:send(_pipe). -spec root_sign_in(binary(), binary()) -> {ok, binary()} | {error, binary()}. root_sign_in(Username, Password) -> Error_msg = <<"Failed to Sign In!"/utf8>>, Request = begin _pipe = build_request( <<"http://localhost:8000/"/utf8>>, <<"signin"/utf8>>, post ), _pipe@1 = gleam@http@request:prepend_header( _pipe, <<"Accept"/utf8>>, <<"application/json"/utf8>> ), gleam@http@request:set_body( _pipe@1, <<<<<<<<"{ \"user\":\""/utf8, Username/binary>>/binary, "\", \"pass\":\""/utf8>>/binary, Password/binary>>/binary, "\"}"/utf8>> ) end, Response = execute_request(Request), case Response of {ok, Resp} -> case erlang:element(2, Resp) of 200 -> Token_json = begin _pipe@2 = erlang:element(4, Resp), _pipe@3 = gleam@string:replace( _pipe@2, <<"}"/utf8>>, <<""/utf8>> ), _pipe@4 = gleam@string:replace( _pipe@3, <<"\""/utf8>>, <<""/utf8>> ), _pipe@5 = gleam@string:split(_pipe@4, <<","/utf8>>), gleam@list:filter(_pipe@5, fun(X) -> _pipe@6 = X, gleam_stdlib:contains_string( _pipe@6, <<"token"/utf8>> ) end) end, case begin _pipe@7 = Token_json, gleam@list:first(_pipe@7) end of {ok, X@1} -> case begin _pipe@8 = gleam@string:split(X@1, <<":"/utf8>>), gleam@list:last(_pipe@8) end of {ok, X@2} -> {ok, X@2}; {error, _} -> {error, Error_msg} end; _ -> {error, Error_msg} end; _ -> {error, Error_msg} end; {error, _} -> {error, Error_msg} end. -spec exec(list({ok, binary()} | {error, binary()})) -> nil. exec(Lines) -> _pipe = Lines, gleam@list:each(_pipe, fun(Res) -> case Res of {ok, X} -> gleam@io:println(X); {error, X@1} -> gleam@io:print_error(X@1) end end). -spec inner_iterate( list({ok, binary()} | {error, binary()}), list({ok, binary()} | {error, binary()}) ) -> list({ok, binary()} | {error, binary()}). inner_iterate(Statements, Acc) -> case Statements of [Head | Rest] -> case Head of {ok, X} -> inner_iterate(Rest, [{ok, X} | Acc]); {error, X@1} -> inner_iterate(Rest, [{error, X@1} | Acc]) end; [] -> Acc end. -spec iterate(list({ok, binary()} | {error, binary()})) -> list({ok, binary()} | {error, binary()}). iterate(Statements) -> inner_iterate( begin _pipe = Statements, lists:reverse(_pipe) end, [] ). -spec execute_transaction(list({ok, binary()} | {error, binary()}), binary()) -> {ok, binary()} | {error, binary()}. execute_transaction(Statements, Token) -> Generated_lines = begin _pipe = [{ok, <<"BEGIN TRANSACTION;"/utf8>>}], _pipe@1 = lists:append(_pipe, Statements), _pipe@2 = lists:append(_pipe@1, [{ok, <<"COMMIT TRANSACTION;"/utf8>>}]), iterate(_pipe@2) end, Errors = begin _pipe@3 = Generated_lines, gleam@list:filter(_pipe@3, fun(A) -> case A of {error, _} -> true; _ -> false end end) end, case erlang:length(Errors) of X when X > 0 -> Errors; _ -> _pipe@4 = Generated_lines, gleam@list:map(_pipe@4, fun(X@1) -> case X@1 of {ok, Val} -> {ok, Val}; _ -> {ok, <<""/utf8>>} end end) end, Error_msg = <<"Failed to Sign In!"/utf8>>, Body = gleam@list:fold(Statements, <<""/utf8>>, fun(A@1, B) -> case B of {ok, X@2} -> <>; _ -> <<""/utf8>> end end), gleam@io:debug(Body), Request = begin _pipe@5 = build_request( <<"http://localhost:8000/"/utf8>>, <<"sql"/utf8>>, post ), _pipe@6 = gleam@http@request:prepend_header( _pipe@5, <<"Accept"/utf8>>, <<"application/json"/utf8>> ), _pipe@7 = with_token(_pipe@6, Token), gleam@http@request:set_body(_pipe@7, Body) end, Response = execute_request(Request), case Response of {ok, Resp} -> case erlang:element(2, Resp) of 200 -> {ok, erlang:element(4, Resp)}; _ -> {error, Error_msg} end; {error, _} -> {error, Error_msg} end. -spec create_database(binary()) -> {ok, binary()} | {error, binary()}. create_database(Name) -> {ok, <<<<"DEFINE DATABASE "/utf8, Name/binary>>/binary, ";"/utf8>>}. -spec create_namespace(binary()) -> {ok, binary()} | {error, binary()}. create_namespace(Name) -> {ok, <<<<"DEFINE NAMESPACE "/utf8, Name/binary>>/binary, ";"/utf8>>}. -spec use_namespace(binary()) -> {ok, binary()} | {error, binary()}. use_namespace(Name) -> {ok, <<<<"USE NAMESPACE "/utf8, Name/binary>>/binary, ";"/utf8>>}. -spec use_database(binary()) -> {ok, binary()} | {error, binary()}. use_database(Name) -> {ok, <<<<"USE db "/utf8, Name/binary>>/binary, ";"/utf8>>}. -spec find_field(types:field_type()) -> binary(). find_field(X) -> case X of int -> <<"int"/utf8>>; float -> <<"float"/utf8>>; decimal -> <<"decimal"/utf8>>; string -> <<"string"/utf8>>; boolean -> <<"bool"/utf8>>; date_time -> <<"datetime"/utf8>>; record -> <<"record"/utf8>>; object -> <<"object"/utf8>>; {set, X@1} -> <<<<"Set<"/utf8, (find_field(X@1))/binary>>/binary, ">"/utf8>>; {option, X@2} -> find_field(X@2); {array, X@3} -> <<<<"array<"/utf8, (find_field(X@3))/binary>>/binary, ">"/utf8>>; {geometry, Shape} -> <<"geometry"/utf8, (case Shape of feature -> <<""/utf8>>; point -> <<""/utf8>>; multi_point -> <<""/utf8>>; line_string -> <<""/utf8>>; multi_line -> <<""/utf8>>; polygon -> <<""/utf8>>; multi_polygon -> <<""/utf8>>; collection -> <<"> end)/binary>>; none -> <<"NONE"/utf8>>; _ -> <<""/utf8>> end. -spec emit_fields( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}), binary() ) -> list({ok, binary()} | {error, binary()}). emit_fields(X, Table) -> _pipe = X, _pipe@1 = lists:reverse(_pipe), gleam@list:map(_pipe@1, fun(Entity) -> case Entity of {<<""/utf8>>, none, {ok, X@1}} -> {ok, X@1}; {Name, Field_type, {ok, Default}} -> Ft = find_field(Field_type), {ok, <<<<<<<<<<<<<<<<"DEFINE FIELD "/utf8, Name/binary>>/binary, " ON TABLE "/utf8>>/binary, Table/binary>>/binary, " TYPE "/utf8>>/binary, Ft/binary>>/binary, " "/utf8>>/binary, Default/binary>>/binary, ";"/utf8>>}; {Field, _, {error, _}} -> {error, <<"FAILED::: DEFINE FIELD FOR "/utf8, Field/binary>>} end end). -spec create_table_schemafull( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}), binary() ) -> {ok, types:table_entity()} | {error, list({ok, binary()} | {error, binary()})}. create_table_schemafull(Entity_definition, Name) -> Res = emit_fields( begin _pipe = Entity_definition, lists:append( _pipe, [{<<""/utf8>>, none, {ok, <<<<"DEFINE TABLE IF NOT EXISTS "/utf8, Name/binary>>/binary, " schemafull;"/utf8>>}}] ) end, Name ), case begin _pipe@1 = Res, gleam@list:any(_pipe@1, fun gleam@result:is_error/1) end of true -> {error, Res}; false -> {ok, {table, Name, Entity_definition, Res}} end. -spec create_table_schemaless( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}), binary() ) -> {ok, types:table_entity()} | {error, list({ok, binary()} | {error, binary()})}. create_table_schemaless(Entity_definition, Name) -> Res = emit_fields( begin _pipe = Entity_definition, lists:append( _pipe, [{<<""/utf8>>, none, {ok, <<<<"DEFINE TABLE IF NOT EXISTS "/utf8, Name/binary>>/binary, " schemaless;"/utf8>>}}] ) end, Name ), case begin _pipe@1 = Res, gleam@list:any(_pipe@1, fun gleam@result:is_error/1) end of true -> {error, Res}; false -> {ok, {table, Name, Entity_definition, Res}} end. -spec add_field( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}), binary(), types:field_type() ) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}). add_field(E, Field, Field_type) -> [{Field, Field_type, {ok, <<""/utf8>>}} | E]. -spec add_default_field( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}), binary(), types:field_type(), types:default_field_type() ) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}). add_default_field(E, Field, Field_type, D) -> Res = case {Field_type, D} of {string, {default_string, X}} -> {ok, <<<<"\""/utf8, X/binary>>/binary, "\""/utf8>>}; {int, {default_int, X@1}} -> {ok, gleam@int:to_string(X@1)}; {_, _} -> {error, <<<<"Field: "/utf8, Field/binary>>/binary, " does not support the supplied default value for its type"/utf8>>} end, Fullfield = case Res of {ok, X@2} -> {Field, Field_type, {ok, <<"Default "/utf8, X@2/binary>>}}; {error, X@3} -> {Field, Field_type, {error, X@3}} end, [Fullfield | E]. -spec generate( list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}) ) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}). generate(E) -> gleam@io:debug(E).