diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index 13a2057..5dd7378 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -812,7 +812,7 @@ esqlite_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return enif_raise_exception(env, make_atom(env, "not_thread_safe")); } - int size = enif_get_string(env, argv[1], filename, MAX_PATHNAME, ERL_NIF_LATIN1); + int size = enif_get_string(env, argv[0], filename, MAX_PATHNAME, ERL_NIF_LATIN1); if(size <= 0) { return make_error_tuple(env, "invalid_filename"); } diff --git a/src/esqlite3.erl b/src/esqlite3.erl index 0102230..ab93360 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -19,7 +19,8 @@ %% higher-level export -export([ - open/1, close/1 + open/1, close/1, + prepare/2 % set_update_hook/2, set_update_hook/3, % exec/2, exec/3, exec/4, @@ -27,7 +28,6 @@ % insert/2, insert/3, % last_insert_rowid/1, % get_autocommit/1, get_autocommit/2, -% prepare/2, prepare/3, % step/1, step/2, % reset/1, % bind/2, bind/3, @@ -160,7 +160,8 @@ close(#esqlite3{db=Connection}) -> %%q(Sql, Args, Connection) -> % q(Sql, Args, Connection, ?DEFAULT_TIMEOUT). % -%%% @doc Execute statement, bind args and return a list with tuples as result restricted by timeout. + +%% @doc Execute statement, bind args and return a list with tuples as result restricted by timeout. %-spec q(sql(), list(), connection(), timeout()) -> list(row()) | {error, _}. %q(Sql, [], Connection, Timeout) -> % case prepare(Sql, Connection, Timeout) of @@ -376,18 +377,27 @@ close(#esqlite3{db=Connection}) -> % ok = esqlite3_nif:get_autocommit(RawConnection, Ref, self()), % receive_answer(RawConnection, Ref, Timeout). % + %% @doc Compile a SQL statement. Returns a cached compiled statement which can be used in %% queries. %% -%-spec prepare(sql(), connection()) -> {ok, statement()} | {error, _}. -%prepare(Sql, Connection) -> -% prepare(Sql, Connection, ?DEFAULT_TIMEOUT). +-spec prepare(Connection, Sql) -> PrepareResult + when Connection :: esqlite3(), + Sql :: sql(), + PrepareResult :: {ok, esqlite3_stmt()} | {error, _}. +prepare(#esqlite3{db=Connection}, Sql) -> + case esqlite3_nif:prepare(Connection, Sql) of + {ok, Stmt} -> + {ok, #esqlite3_stmt{db=Connection, stmt=Stmt}}; + {error, _}=Error -> + Error + end. + %% @doc Like prepare/2, but with an extra timeout value. %-spec prepare(sql(), connection(), timeout()) -> {ok, statement()} | {error, _}. %prepare(Sql, #connection{raw_connection=RawConnection}, Timeout) -> % Ref = make_ref(), -% ok = esqlite3_nif:prepare(RawConnection, Ref, self(), Sql), % case receive_answer(RawConnection, Ref, Timeout) of % {ok, Stmt} when is_reference(Stmt) -> % {ok, #statement{raw_statement=Stmt, raw_connection=RawConnection}}; diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index 8a0aab4..e2b2050 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -19,23 +19,42 @@ close_test() -> {ok, C} = esqlite3:open(":memory:"), ok = esqlite3:close(C), + %% Double close should also work. + ok = esqlite3:close(C), + + ok. + + %% Check if functions still return sensible values. - {error, closed} = esqlite3:set_update_hook(self(), C), - {error, closed} = esqlite3:changes(C), - {error, closed} = esqlite3:get_autocommit(C), - {error, closed} = esqlite3:last_insert_rowid(C), +% {error, closed} = esqlite3:set_update_hook(self(), C), +% {error, closed} = esqlite3:changes(C), +% {error, closed} = esqlite3:get_autocommit(C), +% {error, closed} = esqlite3:last_insert_rowid(C), - {error, _} = esqlite3:exec("create table test(one, two, three)", C), +% {error, _} = esqlite3:exec("create table test(one, two, three)", C), - ok. +% ok. -iodata_test() -> + +prepare_test() -> {ok, C} = esqlite3:open(":memory:"), - {error, no_iodata} = esqlite3:exec(1000, C), - {error, no_iodata} = esqlite3:insert(1000, C), - + ?assertMatch({ok, {esqlite3_stmt, _, _}}, esqlite3:prepare(C, "select 1")), + ok = esqlite3:close(C), ok. +prepare_after_close_test() -> + {ok, C} = esqlite3:open(":memory:"), + ok = esqlite3:close(C), + ?assertMatch({error, {misuse, _}}, esqlite3:prepare(C, "select 1")), + ok. + + +%iodata_test() -> +% {ok, C} = esqlite3:open(":memory:"), +% {error, no_iodata} = esqlite3:exec(1000, C), +% {error, no_iodata} = esqlite3:insert(1000, C), + +% ok. open_multiple_same_databases_test() -> cleanup(), @@ -53,529 +72,529 @@ open_multiple_different_databases_test() -> cleanup(), ok. -get_autocommit_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), - true = esqlite3:get_autocommit(Db), - ok = esqlite3:exec("BEGIN;", Db), - false = esqlite3:get_autocommit(Db), - ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), - ok = esqlite3:exec("COMMIT;", Db), - true = esqlite3:get_autocommit(Db), - ok. +%get_autocommit_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), +% true = esqlite3:get_autocommit(Db), +% ok = esqlite3:exec("BEGIN;", Db), +% false = esqlite3:get_autocommit(Db), +% ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), +% ok = esqlite3:exec("COMMIT;", Db), +% true = esqlite3:get_autocommit(Db), +% ok. -last_insert_rowid_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), - ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), - {ok, 1} = esqlite3:last_insert_rowid(Db), - ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is another test');", Db), - {ok, 2} = esqlite3:last_insert_rowid(Db), - ok. +%last_insert_rowid_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), +% ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), +% {ok, 1} = esqlite3:last_insert_rowid(Db), +% ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is another test');", Db), +% {ok, 2} = esqlite3:last_insert_rowid(Db), +% ok. -update_hook_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:set_update_hook(self(), Db), - ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), - ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), - ok = receive {insert, "test", 1} -> ok after 150 -> no_message end, - ok = esqlite3:exec("UPDATE test SET val = 'a new test' WHERE id = 1;", Db), - ok = receive {update, "test", 1} -> ok after 150 -> no_message end, - ok = esqlite3:exec("DELETE FROM test WHERE id = 1;", Db), - ok = receive {delete, "test", 1} -> ok after 150 -> no_message end, - ok. +%update_hook_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:set_update_hook(self(), Db), +% ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), +% ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), +% ok = receive {insert, "test", 1} -> ok after 150 -> no_message end, +% ok = esqlite3:exec("UPDATE test SET val = 'a new test' WHERE id = 1;", Db), +% ok = receive {update, "test", 1} -> ok after 150 -> no_message end, +% ok = esqlite3:exec("DELETE FROM test WHERE id = 1;", Db), +% ok = receive {delete, "test", 1} -> ok after 150 -> no_message end, +% ok. -simple_query_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - {ok, 1} = esqlite3:changes(Db), +%simple_query_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% {ok, 1} = esqlite3:changes(Db), +% +% ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), +% {ok, 1} = esqlite3:changes(Db), +% ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), +% {ok, 1} = esqlite3:changes(Db), +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% {ok, 1} = esqlite3:changes(Db), +% ok = esqlite3:exec("commit;", Db), +% ok = esqlite3:exec("select * from test_table;", Db), +% +% ok = esqlite3:exec("delete from test_table;", Db), +% {ok, 4} = esqlite3:changes(Db), - ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), - {ok, 1} = esqlite3:changes(Db), - ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), - {ok, 1} = esqlite3:changes(Db), - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), - {ok, 1} = esqlite3:changes(Db), - ok = esqlite3:exec("commit;", Db), - ok = esqlite3:exec("select * from test_table;", Db), - - ok = esqlite3:exec("delete from test_table;", Db), - {ok, 4} = esqlite3:changes(Db), - - ok. - -prepare_test() -> - {ok, Db} = esqlite3:open(":memory:"), - esqlite3:exec("begin;", Db), - esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - {ok, Statement} = esqlite3:prepare("insert into test_table values('one', 2)", Db), - - '$done' = esqlite3:step(Statement), - {ok, 1} = esqlite3:changes(Db), - - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% ok. +%prepare_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% esqlite3:exec("begin;", Db), +% esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% {ok, Statement} = esqlite3:prepare("insert into test_table values('one', 2)", Db), +% +% '$done' = esqlite3:step(Statement), +% {ok, 1} = esqlite3:changes(Db), +% +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% %% Check if the values are there. - [{<<"one">>, 2}, {<<"hello4">>, 13}] = esqlite3:q("select * from test_table order by two", Db), - esqlite3:exec("commit;", Db), - esqlite3:close(Db), +% [{<<"one">>, 2}, {<<"hello4">>, 13}] = esqlite3:q("select * from test_table order by two", Db), +% esqlite3:exec("commit;", Db), +% esqlite3:close(Db), - ok. +% ok. -bind_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("commit;", Db), - - %% Create a prepared statement - {ok, Statement} = esqlite3:prepare("insert into test_table values(?1, ?2)", Db), - esqlite3:bind(Statement, [one, 2]), - esqlite3:step(Statement), - esqlite3:bind(Statement, ["three", 4]), - esqlite3:step(Statement), - esqlite3:bind(Statement, ["five", 6]), - esqlite3:step(Statement), - esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text - esqlite3:step(Statement), - esqlite3:bind(Statement, [<<"nine">>, 10]), % iolist bound as text - esqlite3:step(Statement), - esqlite3:bind(Statement, [{blob, [<<"eleven">>, 0]}, 12]), % iolist bound as blob with trailing eos. - esqlite3:step(Statement), - esqlite3:bind(Statement, ["empty", undefined]), % 'undefined' is converted to SQL null - esqlite3:step(Statement), +%bind_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("commit;", Db), +% +% %% Create a prepared statement +% {ok, Statement} = esqlite3:prepare("insert into test_table values(?1, ?2)", Db), +%% esqlite3:bind(Statement, [one, 2]), +% esqlite3:step(Statement), +% esqlite3:bind(Statement, ["three", 4]), +% esqlite3:step(Statement), +% esqlite3:bind(Statement, ["five", 6]), +% esqlite3:step(Statement), +% esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text +% esqlite3:step(Statement), +% esqlite3:bind(Statement, [<<"nine">>, 10]), % iolist bound as text +% esqlite3:step(Statement), +% esqlite3:bind(Statement, [{blob, [<<"eleven">>, 0]}, 12]), % iolist bound as blob with trailing eos. +% esqlite3:step(Statement), +% esqlite3:bind(Statement, ["empty", undefined]), % 'undefined' is converted to SQL null +% esqlite3:step(Statement), %% int64 - esqlite3:bind(Statement, [int64, 308553449069486081]), - esqlite3:step(Statement), - +% esqlite3:bind(Statement, [int64, 308553449069486081]), +% esqlite3:step(Statement), +% %% negative int64 - esqlite3:bind(Statement, [negative_int64, -308553449069486081]), - esqlite3:step(Statement), +% esqlite3:bind(Statement, [negative_int64, -308553449069486081]), +% esqlite3:step(Statement), %% utf-8 - esqlite3:bind(Statement, [[<<228,184,138,230,181,183>>], 100]), - esqlite3:step(Statement), +% esqlite3:bind(Statement, [[<<228,184,138,230,181,183>>], 100]), +% esqlite3:step(Statement), - ?assertEqual([{<<"one">>, 2}], - esqlite3:q("select one, two from test_table where two = '2'", Db)), - ?assertEqual([{<<"three">>, 4}], - esqlite3:q("select one, two from test_table where two = 4", Db)), - ?assertEqual([{<<"five">>, 6}], - esqlite3:q("select one, two from test_table where two = 6", Db)), - ?assertEqual([{<<"seven">>, 8}], - esqlite3:q("select one, two from test_table where two = 8", Db)), - ?assertEqual([{<<"nine">>, 10}], - esqlite3:q("select one, two from test_table where two = 10", Db)), - ?assertEqual([{{blob, <<$e,$l,$e,$v,$e,$n,0>>}, 12}], - esqlite3:q("select one, two from test_table where two = 12", Db)), - ?assertEqual([{<<"empty">>, undefined}], - esqlite3:q("select one, two from test_table where two is null", Db)), +% ?assertEqual([{<<"one">>, 2}], +% esqlite3:q("select one, two from test_table where two = '2'", Db)), +% ?assertEqual([{<<"three">>, 4}], +% esqlite3:q("select one, two from test_table where two = 4", Db)), +% ?assertEqual([{<<"five">>, 6}], +% esqlite3:q("select one, two from test_table where two = 6", Db)), +% ?assertEqual([{<<"seven">>, 8}], +% esqlite3:q("select one, two from test_table where two = 8", Db)), +% ?assertEqual([{<<"nine">>, 10}], +% esqlite3:q("select one, two from test_table where two = 10", Db)), +% ?assertEqual([{{blob, <<$e,$l,$e,$v,$e,$n,0>>}, 12}], +% esqlite3:q("select one, two from test_table where two = 12", Db)), +% ?assertEqual([{<<"empty">>, undefined}], +% esqlite3:q("select one, two from test_table where two is null", Db)), - ?assertEqual([{<<"int64">>, 308553449069486081}], - esqlite3:q("select one, two from test_table where one = 'int64';", Db)), - ?assertEqual([{<<"negative_int64">>, -308553449069486081}], - esqlite3:q("select one, two from test_table where one = 'negative_int64';", Db)), +% ?assertEqual([{<<"int64">>, 308553449069486081}], +% esqlite3:q("select one, two from test_table where one = 'int64';", Db)), +% ?assertEqual([{<<"negative_int64">>, -308553449069486081}], +% esqlite3:q("select one, two from test_table where one = 'negative_int64';", Db)), %% utf-8 - ?assertEqual([{<<228,184,138,230,181,183>>, 100}], - esqlite3:q("select one, two from test_table where two = 100", Db)), +% ?assertEqual([{<<228,184,138,230,181,183>>, 100}], +% esqlite3:q("select one, two from test_table where two = 100", Db)), +% +% ok. - ok. +%bind_for_queries_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("commit;", Db), -bind_for_queries_test() -> - {ok, Db} = esqlite3:open(":memory:"), +% ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, +% [test_table], Db)), +% ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, +% ["test_table"], Db)), +% ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, +% [<<"test_table">>], Db)), +% ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, +% [[<<"test_table">>]], Db)), +% +% ok. - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("commit;", Db), - - ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, - [test_table], Db)), - ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, - ["test_table"], Db)), - ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, - [<<"test_table">>], Db)), - ?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>, - [[<<"test_table">>]], Db)), - - ok. - -column_names_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 20);", Db), - ok = esqlite3:exec("commit;", Db), +%column_names_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 20);", Db), +% ok = esqlite3:exec("commit;", Db), %% All columns - {ok, Stmt} = esqlite3:prepare("select * from test_table", Db), - {one, two} = esqlite3:column_names(Stmt), - {row, {<<"hello1">>, 10}} = esqlite3:step(Stmt), - {one, two} = esqlite3:column_names(Stmt), - {row, {<<"hello2">>, 20}} = esqlite3:step(Stmt), - {one, two} = esqlite3:column_names(Stmt), - '$done' = esqlite3:step(Stmt), - {one, two} = esqlite3:column_names(Stmt), +% {ok, Stmt} = esqlite3:prepare("select * from test_table", Db), +% {one, two} = esqlite3:column_names(Stmt), +% {row, {<<"hello1">>, 10}} = esqlite3:step(Stmt), +% {one, two} = esqlite3:column_names(Stmt), +% {row, {<<"hello2">>, 20}} = esqlite3:step(Stmt), +% {one, two} = esqlite3:column_names(Stmt), +% '$done' = esqlite3:step(Stmt), +% {one, two} = esqlite3:column_names(Stmt), %% One column - {ok, Stmt2} = esqlite3:prepare("select two from test_table", Db), - {two} = esqlite3:column_names(Stmt2), - {row, {10}} = esqlite3:step(Stmt2), - {two} = esqlite3:column_names(Stmt2), - {row, {20}} = esqlite3:step(Stmt2), - {two} = esqlite3:column_names(Stmt2), - '$done' = esqlite3:step(Stmt2), - {two} = esqlite3:column_names(Stmt2), +% {ok, Stmt2} = esqlite3:prepare("select two from test_table", Db), +% {two} = esqlite3:column_names(Stmt2), +% {row, {10}} = esqlite3:step(Stmt2), +% {two} = esqlite3:column_names(Stmt2), +% {row, {20}} = esqlite3:step(Stmt2), +% {two} = esqlite3:column_names(Stmt2), +% '$done' = esqlite3:step(Stmt2), +% {two} = esqlite3:column_names(Stmt2), %% No columns - {ok, Stmt3} = esqlite3:prepare("values(1);", Db), - {column1} = esqlite3:column_names(Stmt3), - {row, {1}} = esqlite3:step(Stmt3), - {column1} = esqlite3:column_names(Stmt3), +% {ok, Stmt3} = esqlite3:prepare("values(1);", Db), +% {column1} = esqlite3:column_names(Stmt3), +% {row, {1}} = esqlite3:step(Stmt3), +% {column1} = esqlite3:column_names(Stmt3), %% Things get a bit weird when you retrieve the column name %% when calling an aggragage function. - {ok, Stmt4} = esqlite3:prepare("select date('now');", Db), - {'date(\'now\')'} = esqlite3:column_names(Stmt4), - {row, {Date}} = esqlite3:step(Stmt4), - true = is_binary(Date), +%% {ok, Stmt4} = esqlite3:prepare("select date('now');", Db), +% {'date(\'now\')'} = esqlite3:column_names(Stmt4), +% {row, {Date}} = esqlite3:step(Stmt4), +% true = is_binary(Date), %% Some statements have no column names - {ok, Stmt5} = esqlite3:prepare("create table dummy(a, b, c);", Db), - {} = esqlite3:column_names(Stmt5), - - ok. - -column_types_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 20);", Db), - ok = esqlite3:exec("commit;", Db), +% {ok, Stmt5} = esqlite3:prepare("create table dummy(a, b, c);", Db), +% {} = esqlite3:column_names(Stmt5), +% +% ok. +%column_types_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 20);", Db), +% ok = esqlite3:exec("commit;", Db), +% %% All columns - {ok, Stmt} = esqlite3:prepare("select * from test_table", Db), - ?assertEqual({'varchar(10)', 'INT'}, esqlite3:column_types(Stmt)), - {row, {<<"hello1">>, 10}} = esqlite3:step(Stmt), - {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), - {row, {<<"hello2">>, 20}} = esqlite3:step(Stmt), - {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), - '$done' = esqlite3:step(Stmt), - {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), +% {ok, Stmt} = esqlite3:prepare("select * from test_table", Db), +% ?assertEqual({'varchar(10)', 'INT'}, esqlite3:column_types(Stmt)), +% {row, {<<"hello1">>, 10}} = esqlite3:step(Stmt), +% {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), +% {row, {<<"hello2">>, 20}} = esqlite3:step(Stmt), +% {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), +% '$done' = esqlite3:step(Stmt), +% {'varchar(10)', 'INT'} = esqlite3:column_types(Stmt), +% +% %% Some statements have no column types +% {ok, Stmt2} = esqlite3:prepare("create table dummy(a, b, c);", Db), +% {} = esqlite3:column_types(Stmt2), +% +% ok. +% +%nil_column_types_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table t1(c1 variant);", Db), +% ok = esqlite3:exec("commit;", Db), - %% Some statements have no column types - {ok, Stmt2} = esqlite3:prepare("create table dummy(a, b, c);", Db), - {} = esqlite3:column_types(Stmt2), +% {ok, Stmt} = esqlite3:prepare("select c1 + 1, c1 from t1", Db), +% {nil, variant} = esqlite3:column_types(Stmt), +% ok. - ok. - -nil_column_types_test() -> - {ok, Db} = esqlite3:open(":memory:"), - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table t1(c1 variant);", Db), - ok = esqlite3:exec("commit;", Db), - - {ok, Stmt} = esqlite3:prepare("select c1 + 1, c1 from t1", Db), - {nil, variant} = esqlite3:column_types(Stmt), - ok. - -reset_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - {ok, Stmt} = esqlite3:prepare("select * from (values (1), (2));", Db), - {row, {1}} = esqlite3:step(Stmt), - - ok = esqlite3:reset(Stmt), - {row, {1}} = esqlite3:step(Stmt), - {row, {2}} = esqlite3:step(Stmt), - '$done' = esqlite3:step(Stmt), - - % After a done the statement is automatically reset. - {row, {1}} = esqlite3:step(Stmt), - - % Calling reset multiple times... - ok = esqlite3:reset(Stmt), - ok = esqlite3:reset(Stmt), - ok = esqlite3:reset(Stmt), - ok = esqlite3:reset(Stmt), +%reset_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% {ok, Stmt} = esqlite3:prepare("select * from (values (1), (2));", Db), +% {row, {1}} = esqlite3:step(Stmt), +% +% ok = esqlite3:reset(Stmt), +% {row, {1}} = esqlite3:step(Stmt), +% {row, {2}} = esqlite3:step(Stmt), +% '$done' = esqlite3:step(Stmt), +% +% % After a done the statement is automatically reset. +% {row, {1}} = esqlite3:step(Stmt), +% +% % Calling reset multiple times... +% ok = esqlite3:reset(Stmt), +% ok = esqlite3:reset(Stmt), +% ok = esqlite3:reset(Stmt), +% ok = esqlite3:reset(Stmt), +% % The statement should still be reset. - {row, {1}} = esqlite3:step(Stmt), +% {row, {1}} = esqlite3:step(Stmt), +% +% ok. +% +%foreach_test() -> +% {ok, Db} = esqlite3:open(":memory:"), - ok. +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), +% ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% +% ok = esqlite3:exec("commit;", Db), -foreach_test() -> - {ok, Db} = esqlite3:open(":memory:"), +% F = fun(Row) -> +% case Row of +% {Key, Value} -> +% put(Key, Value); +% _ -> +% ok +% end +% end, +% +% esqlite3:foreach(F, "select * from test_table;", Db), +% +% 10 = get(<<"hello1">>), +% 11 = get(<<"hello2">>), +% 12 = get(<<"hello3">>), +% 13 = get(<<"hello4">>), +% +% ok. +% +%bind_for_foreach_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), +% ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% ok = esqlite3:exec("commit;", Db), - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% F = fun(Row) -> +% case Row of +% {Key, Value} -> +% put(Key, Value); +%% _ -> +% ok +% end +% end, - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), - ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% esqlite3:foreach(F, "select * from test_table where one = ?;", ["hello1"], Db), +% +% 10 = get(<<"hello1">>), +% +% ok. - ok = esqlite3:exec("commit;", Db), +%map_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +%% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), +% ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% ok = esqlite3:exec("commit;", Db), - F = fun(Row) -> - case Row of - {Key, Value} -> - put(Key, Value); - _ -> - ok - end - end, - - esqlite3:foreach(F, "select * from test_table;", Db), - - 10 = get(<<"hello1">>), - 11 = get(<<"hello2">>), - 12 = get(<<"hello3">>), - 13 = get(<<"hello4">>), - - ok. - -bind_for_foreach_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), - ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), - ok = esqlite3:exec("commit;", Db), - - F = fun(Row) -> - case Row of - {Key, Value} -> - put(Key, Value); - _ -> - ok - end - end, - - esqlite3:foreach(F, "select * from test_table where one = ?;", ["hello1"], Db), - - 10 = get(<<"hello1">>), - - ok. - -map_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), - ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), - ok = esqlite3:exec("commit;", Db), - - F = fun(Row) -> Row end, - - [{<<"hello1">>,10}, - {<<"hello2">>,11}, - {<<"hello3">>,12}, - {<<"hello4">>,13}] = esqlite3:map(F, "select * from test_table", Db), +% F = fun(Row) -> Row end, +% +% [{<<"hello1">>,10}, +% {<<"hello2">>,11}, +% {<<"hello3">>,12}, +% {<<"hello4">>,13}] = esqlite3:map(F, "select * from test_table", Db), %% Test that when the row-names are added.. - Assoc = fun(Names, Row) -> - lists:zip(tuple_to_list(Names), tuple_to_list(Row)) - end, +% Assoc = fun(Names, Row) -> +% lists:zip(tuple_to_list(Names), tuple_to_list(Row)) +% end, +% +% [[{one,<<"hello1">>},{two,10}], +% [{one,<<"hello2">>},{two,11}], +% [{one,<<"hello3">>},{two,12}], +% [{one,<<"hello4">>},{two,13}]] = esqlite3:map(Assoc, "select * from test_table", Db), +% +% ok. - [[{one,<<"hello1">>},{two,10}], - [{one,<<"hello2">>},{two,11}], - [{one,<<"hello3">>},{two,12}], - [{one,<<"hello4">>},{two,13}]] = esqlite3:map(Assoc, "select * from test_table", Db), +%bind_for_map_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% ok = esqlite3:exec("begin;", Db), +% ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), +% ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), +% ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), +% ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), +% ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), +% ok = esqlite3:exec("commit;", Db), - ok. - -bind_for_map_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - ok = esqlite3:exec("begin;", Db), - ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), - ok = esqlite3:exec("insert into test_table values('hello1', 10);", Db), - ok = esqlite3:exec("insert into test_table values('hello2', 11);", Db), - ok = esqlite3:exec("insert into test_table values('hello3', 12);", Db), - ok = esqlite3:exec("insert into test_table values('hello4', 13);", Db), - ok = esqlite3:exec("commit;", Db), - - F = fun(Row) -> Row end, - - [{<<"hello1">>,10}] - = esqlite3:map(F, "select * from test_table where one = ?", ["hello1"], Db), - - %% Test that when the row-names are added.. - Assoc = fun(Names, Row) -> - lists:zip(tuple_to_list(Names), tuple_to_list(Row)) - end, - - [[{one,<<"hello1">>},{two,10}]] = esqlite3:map(Assoc, "select * from test_table where one = ?", ["hello1"], Db), - - ok. +% F = fun(Row) -> Row end, +% +% [{<<"hello1">>,10}] +% = esqlite3:map(F, "select * from test_table where one = ?", ["hello1"], Db), +% +% %% Test that when the row-names are added.. +% Assoc = fun(Names, Row) -> +% lists:zip(tuple_to_list(Names), tuple_to_list(Row)) +% end, +% +% [[{one,<<"hello1">>},{two,10}]] = esqlite3:map(Assoc, "select * from test_table where one = ?", ["hello1"], Db), +% +% ok. -error1_msg_test() -> - {ok, Db} = esqlite3:open(":memory:"), - +%error1_msg_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% %% Not sql. - {error, {sqlite_error, _Msg1}} = esqlite3:exec("dit is geen sql", Db), - - %% Database test does not exist. - {error, {sqlite_error, _Msg2}} = esqlite3:exec("select * from test;", Db), - - %% Opening non-existant database. - {error, {cantopen, _Msg3}} = esqlite3:open("/dit/bestaat/niet"), - - ok. - -prepare_and_close_connection_test() -> - {ok, Db} = esqlite3:open(":memory:"), - - [] = esqlite3:q("create table test(one, two, three)", Db), - ok = esqlite3:exec(["insert into test values(1,2,3);"], Db), - {ok, Stmt} = esqlite3:prepare("select * from test", Db), - - %% The prepated statment works. - {row, {1,2,3}} = esqlite3:step(Stmt), - '$done' = esqlite3:step(Stmt), - - ok = esqlite3:close(Db), - - ok = esqlite3:reset(Stmt), +% {error, {sqlite_error, _Msg1}} = esqlite3:exec("dit is geen sql", Db), +% +% %% Database test does not exist. +% {error, {sqlite_error, _Msg2}} = esqlite3:exec("select * from test;", Db), +% +% %% Opening non-existant database. +% {error, {cantopen, _Msg3}} = esqlite3:open("/dit/bestaat/niet"), +% +% ok. +%prepare_and_close_connection_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% +% [] = esqlite3:q("create table test(one, two, three)", Db), +% ok = esqlite3:exec(["insert into test values(1,2,3);"], Db), +% {ok, Stmt} = esqlite3:prepare("select * from test", Db), +% +% %% The prepated statment works. +% {row, {1,2,3}} = esqlite3:step(Stmt), +% '$done' = esqlite3:step(Stmt), +% +% ok = esqlite3:close(Db), +% +% ok = esqlite3:reset(Stmt), +% %% Internally sqlite3_close_v2 is used by the nif. This will destruct the %% connection when the last perpared statement is finalized - {row, {1,2,3}} = esqlite3:step(Stmt), - '$done' = esqlite3:step(Stmt), +% {row, {1,2,3}} = esqlite3:step(Stmt), +% '$done' = esqlite3:step(Stmt), - ok. +% ok. -backup_test() -> - cleanup(), +%backup_test() -> +% cleanup(), +% +% {ok, Dest} = esqlite3:open(?DB1), +% {ok, Source} = esqlite3:open(?DB2), +% +% {ok, Backup} = esqlite3:backup_init(Dest, "main", Source, "main"), +% {ok, 0} = esqlite3:backup_remaining(Backup), +% {ok, 0} = esqlite3:backup_pagecount(Backup), +% done = esqlite3:backup_step(Backup, 1), +% +% cleanup(), +% +% ok. - {ok, Dest} = esqlite3:open(?DB1), - {ok, Source} = esqlite3:open(?DB2), +%backup1_test() -> +% cleanup(), +% +% {ok, Dest} = esqlite3:open(?DB1), +% {ok, Source} = esqlite3:open(?DB2), - {ok, Backup} = esqlite3:backup_init(Dest, "main", Source, "main"), - {ok, 0} = esqlite3:backup_remaining(Backup), - {ok, 0} = esqlite3:backup_pagecount(Backup), - done = esqlite3:backup_step(Backup, 1), +% [] = esqlite3:q("create table test(one, two)", Source), +% [] = esqlite3:q("begin;", Source), +% [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), +% [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), +% [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), +% [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), +% [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), +% [] = esqlite3:q("commit;", Source), +% +% [{5}] = esqlite3:q("select count(*) from test", Source), +% {error, {sqlite_error, "no such table: test"}} = esqlite3:q("select count(*) from test", Dest), - cleanup(), +% {ok, Backup} = esqlite3:backup_init(Dest, "main", Source, "main"), - ok. - -backup1_test() -> - cleanup(), - - {ok, Dest} = esqlite3:open(?DB1), - {ok, Source} = esqlite3:open(?DB2), - - [] = esqlite3:q("create table test(one, two)", Source), - [] = esqlite3:q("begin;", Source), - [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), - [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), - [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), - [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), - [] = esqlite3:q("insert into test values(randomblob(10000), randomblob(10000));", Source), - [] = esqlite3:q("commit;", Source), - - [{5}] = esqlite3:q("select count(*) from test", Source), - {error, {sqlite_error, "no such table: test"}} = esqlite3:q("select count(*) from test", Dest), - - {ok, Backup} = esqlite3:backup_init(Dest, "main", Source, "main"), - - {ok, 0} = esqlite3:backup_remaining(Backup), - {ok, 0} = esqlite3:backup_pagecount(Backup), +% {ok, 0} = esqlite3:backup_remaining(Backup), +% {ok, 0} = esqlite3:backup_pagecount(Backup), %% Backup 1 page. - ok = esqlite3:backup_step(Backup, 1), - - {ok, 26} = esqlite3:backup_remaining(Backup), - {ok, 27} = esqlite3:backup_pagecount(Backup), +% ok = esqlite3:backup_step(Backup, 1), +% +% {ok, 26} = esqlite3:backup_remaining(Backup), +% {ok, 27} = esqlite3:backup_pagecount(Backup), %% Do all the remaining pages. - done = esqlite3:backup_step(Backup, -1), +%% done = esqlite3:backup_step(Backup, -1), - {ok, 0} = esqlite3:backup_remaining(Backup), - {ok, 27} = esqlite3:backup_pagecount(Backup), +% {ok, 0} = esqlite3:backup_remaining(Backup), +% {ok, 27} = esqlite3:backup_pagecount(Backup), - ok = esqlite3:backup_finish(Backup), - - [{5}] = esqlite3:q("select count(*) from test", Dest), - - cleanup(), - - ok. +% ok = esqlite3:backup_finish(Backup), +% +% [{5}] = esqlite3:q("select count(*) from test", Dest), +% +% cleanup(), +% +% ok. -sqlite_version_test() -> - {ok, Db} = esqlite3:open(":memory:"), - {ok, Stmt} = esqlite3:prepare("select sqlite_version() as sqlite_version;", Db), - {sqlite_version} = esqlite3:column_names(Stmt), - ?assertEqual({row, {<<"3.38.0">>}}, esqlite3:step(Stmt)), - ok. +%sqlite_version_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% {ok, Stmt} = esqlite3:prepare("select sqlite_version() as sqlite_version;", Db), +% {sqlite_version} = esqlite3:column_names(Stmt), +%% ?assertEqual({row, {<<"3.38.0">>}}, esqlite3:step(Stmt)), +% ok. -sqlite_source_id_test() -> - {ok, Db} = esqlite3:open(":memory:"), - {ok, Stmt} = esqlite3:prepare("select sqlite_source_id() as sqlite_source_id;", Db), - {sqlite_source_id} = esqlite3:column_names(Stmt), - ?assertEqual({row, {<<"2022-02-22 18:58:40 40fa792d359f84c3b9e9d6623743e1a59826274e221df1bde8f47086968a1bab">>}}, - esqlite3:step(Stmt)), - ok. +%sqlite_source_id_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% {ok, Stmt} = esqlite3:prepare("select sqlite_source_id() as sqlite_source_id;", Db), +% {sqlite_source_id} = esqlite3:column_names(Stmt), +% ?assertEqual({row, {<<"2022-02-22 18:58:40 40fa792d359f84c3b9e9d6623743e1a59826274e221df1bde8f47086968a1bab">>}}, +% esqlite3:step(Stmt)), +% ok. -interrupt_on_timeout_test() -> - {ok, Db} = esqlite3:open(":memory:"), - CreateTableQuery = "CREATE TABLE all_numbers_in_the_world (number int not null);", - ok = esqlite3:exec(CreateTableQuery, Db), - VeryLongQuery = " - WITH RECURSIVE - for(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM for WHERE i < 10000000) - INSERT INTO all_numbers_in_the_world SELECT i FROM for; - ", - try - ok = esqlite3:exec(VeryLongQuery, [], Db, 10) - catch - {error, timeout, _} -> - ?assertMatch([{0}], esqlite3:q("SELECT COUNT(*) FROM all_numbers_in_the_world", Db)), - %% There is now a stale answer, because the recursive query was interrupted. - receive - {esqlite3, _, {error, {interrupt, "interrupted"}}} -> - ok - end - end. +%interrupt_on_timeout_test() -> +% {ok, Db} = esqlite3:open(":memory:"), +% CreateTableQuery = "CREATE TABLE all_numbers_in_the_world (number int not null);", +% ok = esqlite3:exec(CreateTableQuery, Db), +% VeryLongQuery = " +% WITH RECURSIVE +% for(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM for WHERE i < 10000000) +% INSERT INTO all_numbers_in_the_world SELECT i FROM for; +% ", +% try +% ok = esqlite3:exec(VeryLongQuery, [], Db, 10) +% catch +% {error, timeout, _} -> +% ?assertMatch([{0}], esqlite3:q("SELECT COUNT(*) FROM all_numbers_in_the_world", Db)), +% %% There is now a stale answer, because the recursive query was interrupted. +% receive +% {esqlite3, _, {error, {interrupt, "interrupted"}}} -> +% ok +% end +% end. -garbage_collect_test() -> - F = fun() -> - {ok, Db} = esqlite3:open(":memory:"), - [] = esqlite3:q("create table test(one, two, three)", Db), - [] = esqlite3:q("insert into test values(1, '2', 3.0)", Db), - {ok, Stmt} = esqlite3:prepare("select * from test", Db), - {row, {1, <<"2">>, 3.0}} = esqlite3:step(Stmt), - '$done' = esqlite3:step(Stmt), - ok = esqlite3:close(Db) - end, - - [spawn(F) || _X <- lists:seq(0,30)], - receive after 500 -> ok end, - erlang:garbage_collect(), - - [spawn(F) || _X <- lists:seq(0,30)], - receive after 500 -> ok end, - erlang:garbage_collect(), +%garbage_collect_test() -> +% F = fun() -> +% {ok, Db} = esqlite3:open(":memory:"), +% [] = esqlite3:q("create table test(one, two, three)", Db), +% [] = esqlite3:q("insert into test values(1, '2', 3.0)", Db), +% {ok, Stmt} = esqlite3:prepare("select * from test", Db), +% {row, {1, <<"2">>, 3.0}} = esqlite3:step(Stmt), +% '$done' = esqlite3:step(Stmt), +% ok = esqlite3:close(Db) +% end, +% +% [spawn(F) || _X <- lists:seq(0,30)], +% receive after 500 -> ok end, +% erlang:garbage_collect(), +% +% [spawn(F) || _X <- lists:seq(0,30)], +% receive after 500 -> ok end, +% erlang:garbage_collect(), - ok. +% ok. %% %% Helpers