-module(glite). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glite.gleam"). -export([connect/1, disconnect/1, exec/3, exec_many/3, 'query'/3, last_insert_rowid/1, int/1, float/1, text/1, blob/1, bool/1, null/0, nullable/2, transaction/2, query_with/4, query_one/4]). -export_type([response/1, connection/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type response(GIA) :: {response, list(GIA), integer()}. -opaque connection() :: {connection, gleam@erlang@process:subject(glite@internal@connection_actor:message()), glite@config:config()}. -file("src/glite.gleam", 52). ?DOC( " Open a SQLite database and return a connection handle.\n" " The connection is managed by an OTP actor process.\n" ). -spec connect(glite@config:config()) -> {ok, connection()} | {error, glite@error:error()}. connect(Config) -> case glite@internal@connection_actor:start(Config) of {ok, Started} -> {ok, {connection, erlang:element(3, Started), Config}}; {error, init_timeout} -> {error, {connection_error, <<"Connection initialization timed out"/utf8>>}}; {error, {init_failed, Reason}} -> {error, {connection_error, Reason}}; {error, {init_exited, _}} -> {error, {connection_error, <<"Connection process exited during init"/utf8>>}} end. -file("src/glite.gleam", 64). ?DOC(" Close the database connection and stop the actor.\n"). -spec disconnect(connection()) -> nil. disconnect(Conn) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {disconnect, Reply} end ). -file("src/glite.gleam", 76). ?DOC( " Execute a statement that does not return rows (CREATE, INSERT, UPDATE, DELETE).\n" " Returns the number of rows affected.\n" ). -spec exec(connection(), binary(), list(glite@value:value())) -> {ok, integer()} | {error, glite@error:error()}. exec(Conn, Sql, Params) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {exec, Sql, Params, Reply} end ). -file("src/glite.gleam", 89). ?DOC( " Execute a statement many times with different parameter sets.\n" " Prepares once, then binds+steps for each param set efficiently.\n" " Returns the total number of rows affected.\n" ). -spec exec_many(connection(), binary(), list(list(glite@value:value()))) -> {ok, integer()} | {error, glite@error:error()}. exec_many(Conn, Sql, Params_list) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {exec_many, Sql, Params_list, Reply} end ). -file("src/glite.gleam", 100). ?DOC(" Execute a query and return raw results (column names + rows of Values).\n"). -spec 'query'(connection(), binary(), list(glite@value:value())) -> {ok, glite@connection:query_result()} | {error, glite@error:error()}. 'query'(Conn, Sql, Params) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {'query', Sql, Params, Reply} end ). -file("src/glite.gleam", 170). ?DOC(" Get the last insert rowid.\n"). -spec last_insert_rowid(connection()) -> integer(). last_insert_rowid(Conn) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {last_insert_rowid, Reply} end ). -file("src/glite.gleam", 181). ?DOC(" Create an integer parameter.\n"). -spec int(integer()) -> glite@value:value(). int(Val) -> {integer, Val}. -file("src/glite.gleam", 186). ?DOC(" Create a float parameter.\n"). -spec float(float()) -> glite@value:value(). float(Val) -> {real, Val}. -file("src/glite.gleam", 191). ?DOC(" Create a text/string parameter.\n"). -spec text(binary()) -> glite@value:value(). text(Val) -> {text, Val}. -file("src/glite.gleam", 196). ?DOC(" Create a blob (binary data) parameter.\n"). -spec blob(bitstring()) -> glite@value:value(). blob(Val) -> {blob, Val}. -file("src/glite.gleam", 201). ?DOC(" Create a boolean parameter (stored as Integer 0/1).\n"). -spec bool(boolean()) -> glite@value:value(). bool(Val) -> case Val of true -> {integer, 1}; false -> {integer, 0} end. -file("src/glite.gleam", 209). ?DOC(" Create a NULL parameter.\n"). -spec null() -> glite@value:value(). null() -> null. -file("src/glite.gleam", 214). ?DOC(" Create a nullable parameter from an Option value.\n"). -spec nullable(gleam@option:option(GJD), fun((GJD) -> glite@value:value())) -> glite@value:value(). nullable(Val, To_param) -> case Val of {some, V} -> To_param(V); none -> null end. -file("src/glite.gleam", 225). -spec exec_sql(connection(), binary()) -> {ok, nil} | {error, glite@error:error()}. exec_sql(Conn, Sql) -> gleam@erlang@process:call( erlang:element(2, Conn), erlang:element(3, erlang:element(3, Conn)), fun(Reply) -> {exec_sql, Sql, Reply} end ). -file("src/glite.gleam", 146). ?DOC( " Execute a function within a transaction.\n" " Automatically BEGINs, and COMMITs on Ok or ROLLBACKs on Error.\n" ). -spec transaction( connection(), fun((connection()) -> {ok, GIY} | {error, glite@error:error()}) ) -> {ok, GIY} | {error, glite@error:error()}. transaction(Conn, F) -> case exec_sql(Conn, <<"BEGIN"/utf8>>) of {error, E} -> {error, E}; {ok, _} -> case F(Conn) of {ok, Val} -> case exec_sql(Conn, <<"COMMIT"/utf8>>) of {ok, _} -> {ok, Val}; {error, E@1} -> {error, E@1} end; {error, E@2} -> _ = exec_sql(Conn, <<"ROLLBACK"/utf8>>), {error, E@2} end end. -file("src/glite.gleam", 231). -spec decode_rows( list(list(glite@value:value())), glite@decode:row_decoder(GJJ), list(GJJ) ) -> {ok, list(GJJ)} | {error, glite@error:error()}. decode_rows(Rows, Decoder, Acc) -> case Rows of [] -> {ok, lists:reverse(Acc)}; [Row | Rest] -> case glite@decode:run(Decoder, Row) of {ok, Val} -> decode_rows(Rest, Decoder, [Val | Acc]); {error, E} -> {error, E} end end. -file("src/glite.gleam", 111). ?DOC(" Execute a query and decode each row using the provided decoder.\n"). -spec query_with( connection(), binary(), list(glite@value:value()), glite@decode:row_decoder(GIO) ) -> {ok, response(GIO)} | {error, glite@error:error()}. query_with(Conn, Sql, Params, Decoder) -> case 'query'(Conn, Sql, Params) of {ok, Result} -> case decode_rows(erlang:element(3, Result), Decoder, []) of {ok, Decoded} -> {ok, {response, Decoded, erlang:length(Decoded)}}; {error, E} -> {error, E} end; {error, E@1} -> {error, E@1} end. -file("src/glite.gleam", 128). ?DOC(" Execute a query and return the first decoded row, or error if no rows.\n"). -spec query_one( connection(), binary(), list(glite@value:value()), glite@decode:row_decoder(GIU) ) -> {ok, GIU} | {error, glite@error:error()}. query_one(Conn, Sql, Params, Decoder) -> case query_with(Conn, Sql, Params, Decoder) of {ok, Response} -> case erlang:element(2, Response) of [First | _] -> {ok, First}; [] -> {error, {decode_error, <<"Expected at least one row, got none"/utf8>>}} end; {error, E} -> {error, E} end.