-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.