-module(glite@connection). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glite/connection.gleam"). -export([ffi_changes/1, ffi_last_insert_rowid/1, close/1, 'query'/3, changes/1, last_insert_rowid/1, execute_many/3, exec_sql/2, execute/3, open/1]). -export_type([db_handle/0, stmt_handle/0, step_result/0, query_result/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 db_handle() :: any(). -type stmt_handle() :: any(). -type step_result() :: {row, list(glite@value:value())} | done. -type query_result() :: {query_result, list(binary()), list(list(glite@value:value()))}. -file("src/glite/connection.gleam", 66). -spec ffi_changes(db_handle()) -> integer(). ffi_changes(Db) -> glite_ffi:changes(Db). -file("src/glite/connection.gleam", 69). -spec ffi_last_insert_rowid(db_handle()) -> integer(). ffi_last_insert_rowid(Db) -> glite_ffi:last_insert_rowid(Db). -file("src/glite/connection.gleam", 84). ?DOC(" Close a database handle\n"). -spec close(db_handle()) -> {ok, nil} | {error, glite@error:error()}. close(Db) -> case glite_ffi:close(Db) of {ok, _} -> {ok, nil}; {error, Reason} -> {error, {connection_error, Reason}} end. -file("src/glite/connection.gleam", 114). ?DOC(" Execute a query and return columns + rows\n"). -spec 'query'(db_handle(), binary(), list(glite@value:value())) -> {ok, query_result()} | {error, glite@error:error()}. 'query'(Db, Sql, Params) -> case glite_ffi:query_all(Db, Sql, Params) of {ok, {Columns, Rows}} -> {ok, {query_result, Columns, Rows}}; {error, Reason} -> {error, {sqlite_error, 0, Reason}} end. -file("src/glite/connection.gleam", 126). ?DOC(" Get the number of rows affected by the last INSERT/UPDATE/DELETE\n"). -spec changes(db_handle()) -> integer(). changes(Db) -> glite_ffi:changes(Db). -file("src/glite/connection.gleam", 131). ?DOC(" Get the rowid of the last inserted row\n"). -spec last_insert_rowid(db_handle()) -> integer(). last_insert_rowid(Db) -> glite_ffi:last_insert_rowid(Db). -file("src/glite/connection.gleam", 138). ?DOC( " Execute a statement many times with different parameter sets.\n" " Prepares once, then binds+steps for each param set in one FFI call.\n" " Returns the total number of rows affected.\n" ). -spec execute_many(db_handle(), binary(), list(list(glite@value:value()))) -> {ok, integer()} | {error, glite@error:error()}. execute_many(Db, Sql, Params_list) -> case glite_ffi:execute_many(Db, Sql, Params_list) of {ok, Total} -> {ok, Total}; {error, Reason} -> {error, {sqlite_error, 0, Reason}} end. -file("src/glite/connection.gleam", 150). ?DOC(" Execute raw SQL without parameters or results (for PRAGMAs, DDL, etc.)\n"). -spec exec_sql(db_handle(), binary()) -> {ok, nil} | {error, glite@error:error()}. exec_sql(Db, Sql) -> case glite_ffi:exec_sql(Db, Sql) of {ok, _} -> {ok, nil}; {error, Reason} -> {error, {sqlite_error, 0, Reason}} end. -file("src/glite/connection.gleam", 161). -spec bind_params(stmt_handle(), list(glite@value:value())) -> {ok, nil} | {error, glite@error:error()}. bind_params(Stmt, Params) -> case gleam@list:is_empty(Params) of true -> {ok, nil}; false -> case glite_ffi:bind(Stmt, Params) of {ok, _} -> {ok, nil}; {error, Reason} -> {error, {encode_error, Reason}} end end. -file("src/glite/connection.gleam", 182). -spec step_until_done(stmt_handle()) -> {ok, nil} | {error, glite@error:error()}. step_until_done(Stmt) -> case glite_ffi:step(Stmt, []) of {ok, done} -> {ok, nil}; {ok, {row, _}} -> step_until_done(Stmt); {error, Reason} -> {error, {sqlite_error, 0, Reason}} end. -file("src/glite/connection.gleam", 172). -spec bind_and_step_exec(stmt_handle(), list(glite@value:value())) -> {ok, nil} | {error, glite@error:error()}. bind_and_step_exec(Stmt, Params) -> case bind_params(Stmt, Params) of {error, E} -> {error, E}; {ok, _} -> step_until_done(Stmt) end. -file("src/glite/connection.gleam", 97). ?DOC( " Execute a statement that does not return rows.\n" " Returns the number of rows affected.\n" ). -spec execute(db_handle(), binary(), list(glite@value:value())) -> {ok, integer()} | {error, glite@error:error()}. execute(Db, Sql, Params) -> case glite_ffi:prepare(Db, Sql) of {error, Reason} -> {error, {sqlite_error, 0, Reason}}; {ok, Stmt} -> case bind_and_step_exec(Stmt, Params) of {ok, _} -> {ok, glite_ffi:changes(Db)}; {error, E} -> {error, E} end end. -file("src/glite/connection.gleam", 240). -spec apply_custom_pragmas(db_handle(), list({binary(), binary()})) -> {ok, db_handle()} | {error, glite@error:error()}. apply_custom_pragmas(Db, Pragmas) -> case Pragmas of [] -> {ok, Db}; [{Name, Val} | Rest] -> case exec_sql( Db, <<<<<<"PRAGMA "/utf8, Name/binary>>/binary, "="/utf8>>/binary, Val/binary>> ) of {error, E} -> {error, E}; {ok, _} -> apply_custom_pragmas(Db, Rest) end end. -file("src/glite/connection.gleam", 229). -spec apply_foreign_keys(db_handle(), glite@config:config()) -> {ok, db_handle()} | {error, glite@error:error()}. apply_foreign_keys(Db, Config) -> Fk = case erlang:element(7, Config) of true -> <<"ON"/utf8>>; false -> <<"OFF"/utf8>> end, case exec_sql(Db, <<"PRAGMA foreign_keys="/utf8, Fk/binary>>) of {error, E} -> {error, E}; {ok, _} -> apply_custom_pragmas(Db, erlang:element(8, Config)) end. -file("src/glite/connection.gleam", 217). -spec apply_synchronous(db_handle(), glite@config:config()) -> {ok, db_handle()} | {error, glite@error:error()}. apply_synchronous(Db, Config) -> Mode = case erlang:element(6, Config) of full -> <<"FULL"/utf8>>; normal -> <<"NORMAL"/utf8>>; sync_off -> <<"OFF"/utf8>> end, case exec_sql(Db, <<"PRAGMA synchronous="/utf8, Mode/binary>>) of {error, E} -> {error, E}; {ok, _} -> apply_foreign_keys(Db, Config) end. -file("src/glite/connection.gleam", 204). -spec apply_journal_mode(db_handle(), glite@config:config()) -> {ok, db_handle()} | {error, glite@error:error()}. apply_journal_mode(Db, Config) -> Mode = case erlang:element(5, Config) of wal -> <<"wal"/utf8>>; delete -> <<"delete"/utf8>>; memory -> <<"memory"/utf8>>; off -> <<"off"/utf8>> end, case exec_sql(Db, <<"PRAGMA journal_mode="/utf8, Mode/binary>>) of {error, E} -> {error, E}; {ok, _} -> apply_synchronous(Db, Config) end. -file("src/glite/connection.gleam", 195). -spec apply_pragmas(db_handle(), glite@config:config()) -> {ok, db_handle()} | {error, glite@error:error()}. apply_pragmas(Db, Config) -> case exec_sql( Db, <<"PRAGMA busy_timeout="/utf8, (erlang:integer_to_binary(erlang:element(4, Config)))/binary>> ) of {error, E} -> {error, E}; {ok, _} -> apply_journal_mode(Db, Config) end. -file("src/glite/connection.gleam", 76). ?DOC(" Open a database and apply configuration PRAGMAs\n"). -spec open(glite@config:config()) -> {ok, db_handle()} | {error, glite@error:error()}. open(Config) -> case glite_ffi:open(erlang:element(2, Config)) of {error, Reason} -> {error, {connection_error, Reason}}; {ok, Db} -> apply_pragmas(Db, Config) end.