-module(gdo@statement).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gdo/statement.gleam").
-export([prepare/1, sql/1, placeholder_style/1, bind/3, uses_parameters/1, validate_params/2, exec/2, execute/2, query_all/2, query_one/2, query_all_as/3, query_one_as/3]).
-export_type([placeholder_style/0, statement_backend/0, scan_state/0, placeholder_summary/0, statement/0]).
-type placeholder_style() :: no_parameters |
positional_parameters |
named_parameters.
-type statement_backend() :: unbound |
{bound, gdo@driver:driver_contract(), gdo@driver:driver_statement_state()}.
-type scan_state() :: normal |
in_single_quoted_string |
in_double_quoted_string |
in_line_comment |
in_block_comment.
-type placeholder_summary() :: {placeholder_summary, boolean(), boolean()}.
-opaque statement() :: {statement,
binary(),
placeholder_style(),
statement_backend()}.
-file("src/gdo/statement.gleam", 295).
-spec set_has_named(placeholder_summary()) -> placeholder_summary().
set_has_named(Summary) ->
{placeholder_summary, Has_positional, _} = Summary,
{placeholder_summary, Has_positional, true}.
-file("src/gdo/statement.gleam", 307).
-spec is_ascii_letter(integer()) -> boolean().
is_ascii_letter(Codepoint) ->
((Codepoint >= 65) andalso (Codepoint =< 90)) orelse ((Codepoint >= 97)
andalso (Codepoint =< 122)).
-file("src/gdo/statement.gleam", 312).
-spec ascii_codepoint(binary()) -> {ok, integer()} | {error, nil}.
ascii_codepoint(Grapheme) ->
case gleam@string:to_utf_codepoints(Grapheme) of
[Codepoint] ->
{ok, gleam_stdlib:identity(Codepoint)};
_ ->
{error, nil}
end.
-file("src/gdo/statement.gleam", 300).
-spec is_identifier_start(binary()) -> boolean().
is_identifier_start(Grapheme) ->
case ascii_codepoint(Grapheme) of
{ok, Codepoint} ->
is_ascii_letter(Codepoint) orelse (Codepoint =:= 95);
{error, _} ->
false
end.
-file("src/gdo/statement.gleam", 290).
-spec set_has_positional(placeholder_summary()) -> placeholder_summary().
set_has_positional(Summary) ->
{placeholder_summary, _, Has_named} = Summary,
{placeholder_summary, true, Has_named}.
-file("src/gdo/statement.gleam", 237).
-spec scan_placeholders(list(binary()), scan_state(), placeholder_summary()) -> placeholder_summary().
scan_placeholders(Graphemes, State, Summary) ->
case Graphemes of
[] ->
Summary;
[<<"'"/utf8>>, <<"'"/utf8>> | Rest] when State =:= in_single_quoted_string ->
scan_placeholders(Rest, in_single_quoted_string, Summary);
[<<"\""/utf8>>, <<"\""/utf8>> | Rest@1] when State =:= in_double_quoted_string ->
scan_placeholders(Rest@1, in_double_quoted_string, Summary);
[<<"'"/utf8>> | Rest@2] ->
case State of
normal ->
scan_placeholders(Rest@2, in_single_quoted_string, Summary);
in_single_quoted_string ->
scan_placeholders(Rest@2, normal, Summary);
_ ->
scan_placeholders(Rest@2, State, Summary)
end;
[<<"\""/utf8>> | Rest@3] ->
case State of
normal ->
scan_placeholders(Rest@3, in_double_quoted_string, Summary);
in_double_quoted_string ->
scan_placeholders(Rest@3, normal, Summary);
_ ->
scan_placeholders(Rest@3, State, Summary)
end;
[<<"-"/utf8>>, <<"-"/utf8>> | Rest@4] when State =:= normal ->
scan_placeholders(Rest@4, in_line_comment, Summary);
[<<"/"/utf8>>, <<"*"/utf8>> | Rest@5] when State =:= normal ->
scan_placeholders(Rest@5, in_block_comment, Summary);
[<<"*"/utf8>>, <<"/"/utf8>> | Rest@6] when State =:= in_block_comment ->
scan_placeholders(Rest@6, normal, Summary);
[<<"\n"/utf8>> | Rest@7] when State =:= in_line_comment ->
scan_placeholders(Rest@7, normal, Summary);
[<<"?"/utf8>> | Rest@8] when State =:= normal ->
scan_placeholders(Rest@8, normal, set_has_positional(Summary));
[<<":"/utf8>>, Next | Rest@9] ->
case {State, is_identifier_start(Next)} of
{normal, true} ->
scan_placeholders(Rest@9, normal, set_has_named(Summary));
{_, _} ->
scan_placeholders([Next | Rest@9], State, Summary)
end;
[_ | Rest@10] ->
scan_placeholders(Rest@10, State, Summary)
end.
-file("src/gdo/statement.gleam", 220).
-spec infer_placeholder_style(binary()) -> {ok, placeholder_style()} |
{error, gdo@error:error()}.
infer_placeholder_style(Sql) ->
{placeholder_summary, Has_positional, Has_named} = begin
_pipe = Sql,
_pipe@1 = gleam@string:to_graphemes(_pipe),
scan_placeholders(_pipe@1, normal, {placeholder_summary, false, false})
end,
case {Has_positional, Has_named} of
{true, true} ->
{error,
{invalid_configuration,
<<"Cannot mix positional and named parameters in the same statement."/utf8>>}};
{true, false} ->
{ok, positional_parameters};
{false, true} ->
{ok, named_parameters};
{false, false} ->
{ok, no_parameters}
end.
-file("src/gdo/statement.gleam", 45).
-spec prepare(binary()) -> {ok, statement()} | {error, gdo@error:error()}.
prepare(Sql) ->
Trimmed_sql = gleam@string:trim(Sql),
case gleam@string:is_empty(Trimmed_sql) of
true ->
{error, {invalid_configuration, <<"SQL cannot be empty."/utf8>>}};
false ->
case infer_placeholder_style(Trimmed_sql) of
{ok, Placeholder_style} ->
{ok, {statement, Trimmed_sql, Placeholder_style, unbound}};
{error, Error} ->
{error, Error}
end
end.
-file("src/gdo/statement.gleam", 59).
-spec sql(statement()) -> binary().
sql(Statement) ->
{statement, Sql, _, _} = Statement,
Sql.
-file("src/gdo/statement.gleam", 64).
-spec placeholder_style(statement()) -> placeholder_style().
placeholder_style(Statement) ->
{statement, _, Placeholder_style, _} = Statement,
Placeholder_style.
-file("src/gdo/statement.gleam", 69).
-spec bind(
statement(),
gdo@driver:driver_contract(),
gdo@driver:driver_statement_state()
) -> statement().
bind(Statement, Contract, Statement_state) ->
{statement, Sql, Placeholder_style, _} = Statement,
{statement, Sql, Placeholder_style, {bound, Contract, Statement_state}}.
-file("src/gdo/statement.gleam", 82).
-spec uses_parameters(statement()) -> boolean().
uses_parameters(Statement) ->
case placeholder_style(Statement) of
no_parameters ->
false;
_ ->
true
end.
-file("src/gdo/statement.gleam", 89).
-spec validate_params(statement(), list(gdo@value:param())) -> {ok, nil} |
{error, gdo@error:error()}.
validate_params(Statement, Params) ->
case placeholder_style(Statement) of
no_parameters ->
case Params of
[] ->
{ok, nil};
_ ->
{error,
{invalid_configuration,
<<"This statement does not accept parameters."/utf8>>}}
end;
positional_parameters ->
case gleam@list:any(Params, fun(Param) -> case Param of
{named, _, _} ->
true;
{positional, _} ->
false
end end) of
true ->
{error,
{invalid_configuration,
<<"Positional statements require positional parameters only."/utf8>>}};
false ->
{ok, nil}
end;
named_parameters ->
case gleam@list:any(Params, fun(Param@1) -> case Param@1 of
{positional, _} ->
true;
{named, _, _} ->
false
end end) of
true ->
{error,
{invalid_configuration,
<<"Named statements require named parameters only."/utf8>>}};
false ->
{ok, nil}
end
end.
-file("src/gdo/statement.gleam", 215).
-spec backend(statement()) -> statement_backend().
backend(Statement) ->
{statement, _, _, Backend} = Statement,
Backend.
-file("src/gdo/statement.gleam", 137).
-spec exec(statement(), list(gdo@value:param())) -> {ok,
gdo@result:execution_result()} |
{error, gdo@error:error()}.
exec(Statement, Params) ->
case validate_params(Statement, Params) of
{ok, _} ->
case backend(Statement) of
{bound, Contract, Statement_state} ->
gdo@driver:exec(Contract, Statement_state, Params);
unbound ->
{ok, gdo@result:execution_result(0, none)}
end;
{error, Error} ->
{error, Error}
end.
-file("src/gdo/statement.gleam", 153).
-spec execute(statement(), list(gdo@value:param())) -> {ok,
gdo@result:execution_result()} |
{error, gdo@error:error()}.
execute(Statement, Params) ->
exec(Statement, Params).
-file("src/gdo/statement.gleam", 160).
-spec query_all(statement(), list(gdo@value:param())) -> {ok,
gdo@result:query_result()} |
{error, gdo@error:error()}.
query_all(Statement, Params) ->
case validate_params(Statement, Params) of
{ok, _} ->
case backend(Statement) of
{bound, Contract, Statement_state} ->
gdo@driver:query_all(Contract, Statement_state, Params);
unbound ->
{ok, gdo@result:empty_query_result()}
end;
{error, Error} ->
{error, Error}
end.
-file("src/gdo/statement.gleam", 175).
-spec query_one(statement(), list(gdo@value:param())) -> {ok,
gleam@option:option(gdo@row:row())} |
{error, gdo@error:error()}.
query_one(Statement, Params) ->
case query_all(Statement, Params) of
{ok, Query_result} ->
{ok, gdo@result:first(Query_result)};
{error, Error} ->
{error, Error}
end.
-file("src/gdo/statement.gleam", 185).
-spec query_all_as(
statement(),
list(gdo@value:param()),
fun((gdo@row:row()) -> {ok, LNT} | {error, gdo@error:error()})
) -> {ok, list(LNT)} | {error, gdo@error:error()}.
query_all_as(Statement, Params, Decoder) ->
case query_all(Statement, Params) of
{ok, Query_result} ->
gleam@list:try_map(
gdo@result:rows(Query_result),
fun(Current_row) -> gdo@decode:decode(Current_row, Decoder) end
);
{error, Error} ->
{error, Error}
end.
-file("src/gdo/statement.gleam", 199).
-spec query_one_as(
statement(),
list(gdo@value:param()),
fun((gdo@row:row()) -> {ok, LNZ} | {error, gdo@error:error()})
) -> {ok, gleam@option:option(LNZ)} | {error, gdo@error:error()}.
query_one_as(Statement, Params, Decoder) ->
case query_one(Statement, Params) of
{ok, {some, Current_row}} ->
case gdo@decode:decode(Current_row, Decoder) of
{ok, Decoded} ->
{ok, {some, Decoded}};
{error, Error} ->
{error, Error}
end;
{ok, none} ->
{ok, none};
{error, Error@1} ->
{error, Error@1}
end.