Added bind blob & text

This commit is contained in:
Maas-Maarten Zeeman
2022-05-22 16:54:21 +02:00
parent 20af1ea0bd
commit c5f33d31bd
4 changed files with 110 additions and 47 deletions

View File

@@ -486,37 +486,23 @@ make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
int type = sqlite3_column_type(statement, i);
switch(type) {
case SQLITE_NULL:
return make_atom(env, "undefined");
case SQLITE_INTEGER:
return enif_make_int64(env, sqlite3_column_int64(statement, i));
case SQLITE_FLOAT:
return enif_make_double(env, sqlite3_column_double(statement, i));
case SQLITE_BLOB:
return enif_make_tuple2(env, make_atom(env, "blob"),
make_binary(env, sqlite3_column_blob(statement, i),
sqlite3_column_bytes(statement, i)));
case SQLITE_NULL:
return make_atom(env, "undefined");
return make_binary(env, sqlite3_column_blob(statement, i),
sqlite3_column_bytes(statement, i));
case SQLITE_TEXT:
return make_binary(env, sqlite3_column_text(statement, i),
sqlite3_column_bytes(statement, i));
}
return enif_raise_exception(env, make_atom(env, "internal_error"));
}
/*
static ERL_NIF_TERM
do_reset(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt)
{
int rc = sqlite3_reset(stmt);
if(rc != SQLITE_OK)
return make_sqlite3_error_tuple(env, rc, db);
return make_atom(env, "ok");
}
*/
/*
static ERL_NIF_TERM
do_backup_init(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg)
@@ -1136,6 +1122,82 @@ esqlite_bind_double(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return make_atom(env, "ok");
}
static ERL_NIF_TERM
esqlite_bind_text(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
esqlite3_stmt *stmt;
int index;
ErlNifBinary text;
if(argc != 3) {
return enif_make_badarg(env);
}
if(!enif_get_resource(env, argv[0], esqlite3_stmt_type, (void **) &stmt)) {
return enif_make_badarg(env);
}
if(!stmt->statement) {
return enif_raise_exception(env, make_atom(env, "no_prepared_statement"));
}
if(!enif_get_int(env, argv[1], &index)) {
return enif_make_badarg(env);
}
if(!enif_inspect_iolist_as_binary(env, argv[1], &text)) {
return enif_make_badarg(env);
}
/*
* Don't do any checks on the input data, sqlite handes all kinds of input. It is
* garbage-in, garbage-out.
*
*/
int rc = sqlite3_bind_text64(stmt->statement, index, text.data, text.size, SQLITE_TRANSIENT, SQLITE_UTF8);
if(rc != SQLITE_OK) {
return make_sqlite3_error_tuple(env, rc);
}
return make_atom(env, "ok");
}
static ERL_NIF_TERM
esqlite_bind_blob(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
esqlite3_stmt *stmt;
int index;
ErlNifBinary blob;
if(argc != 3) {
return enif_make_badarg(env);
}
if(!enif_get_resource(env, argv[0], esqlite3_stmt_type, (void **) &stmt)) {
return enif_make_badarg(env);
}
if(!stmt->statement) {
return enif_raise_exception(env, make_atom(env, "no_prepared_statement"));
}
if(!enif_get_int(env, argv[1], &index)) {
return enif_make_badarg(env);
}
if(!enif_inspect_iolist_as_binary(env, argv[1], &blob)) {
return enif_make_badarg(env);
}
int rc = sqlite3_bind_blob64(stmt->statement, index, blob.data, blob.size, SQLITE_TRANSIENT);
if(rc != SQLITE_OK) {
return make_sqlite3_error_tuple(env, rc);
}
return make_atom(env, "ok");
}
static ERL_NIF_TERM
esqlite_bind_null(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
@@ -1543,22 +1605,21 @@ static ErlNifFunc nif_funcs[] = {
{"bind_int", 3, esqlite_bind_int},
{"bind_int64", 3, esqlite_bind_int64},
{"bind_double", 3, esqlite_bind_double},
{"bind_text", 3, esqlite_bind_text},
{"bind_blob", 3, esqlite_bind_blob},
{"bind_null", 2, esqlite_bind_null},
/*
{"bind_text", 3, esqlite_bind_blob},
{"bind_blob", 3, esqlite_bind_blob},
{"bind_null", 2, esqlite_bind_blob},
*/
{"step", 1, esqlite_step},
{"reset", 1, esqlite_reset},
/*
Other interesting additions... trace.
wal_hook triggered after every commit.
also interesting commit and rollback_hooks
* Other interesting additions... trace.
* wal_hook triggered after every commit.
* also interesting commit and rollback_hooks
*/
{"interrupt", 1, esqlite_interrupt, ERL_NIF_DIRTY_JOB_IO_BOUND},
@@ -1567,9 +1628,6 @@ static ErlNifFunc nif_funcs[] = {
{"changes", 1, esqlite_changes},
/*
{"exec", 4, esqlite_exec, ERL_NIF_DIRTY_JOB_IO_BOUND},
{"backup_init", 6, esqlite_backup_init},
{"backup_step", 5, esqlite_backup_step},
{"backup_remaining", 4, esqlite_backup_remaining},

View File

@@ -22,13 +22,13 @@
open/1, close/1,
%% db connection functions
set_update_hook/2,
get_autocommit/1,
last_insert_rowid/1,
changes/1,
%% queries
exec/2,
prepare/2,
prepare/3,
@@ -41,13 +41,13 @@
bind_int64/3,
bind_double/3,
% bind_text/3,
% bind_blob/3,
bind_blob/3,
bind_null/2,
step/1,
reset/1
%
% fetchone/1,
% fetchall/1, fetchall/2, fetchall/3,
%
@@ -63,7 +63,6 @@
-define(DEFAULT_TIMEOUT, infinity).
-define(DEFAULT_CHUNK_SIZE, 5000).
-define(SQLITE_PREPARE_PERSISTENT, 16#01).
-define(SQLITE_PREPARE_NO_VTAB, 16#04).
@@ -391,6 +390,14 @@ bind_int64(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
bind_double(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
esqlite3_nif:bind_double(Stmt, Index, Value).
-spec bind_blob(Statement, Index, Value) -> BindResult
when Statement :: esqlite3_stmt(),
Index :: integer(),
Value :: iodata(),
BindResult :: ok | {error, _}.
bind_blob(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
esqlite3_nif:bind_blob(Stmt, Index, Value).
-spec bind_null(Statement, Index) -> BindResult
when Statement :: esqlite3_stmt(),
Index :: integer(),

View File

@@ -37,8 +37,8 @@
bind_int/3,
bind_int64/3,
bind_double/3,
%bind_text/3,
%bind_blob/3,
bind_text/3,
bind_blob/3,
bind_null/2,
step/1,
@@ -46,15 +46,6 @@
reset/1,
interrupt/1
% exec/4,
% changes/3,
%
% multi_step/5,
% reset/4,
% finalize/4,
% bind/5,
% column_types/4,
% backup_init/6,
% backup_step/5,
@@ -137,6 +128,12 @@ bind_int64(_Statement, _Index, _Value) ->
bind_double(_Statement, _Index, _Value) ->
erlang:nif_error(nif_library_not_loaded).
bind_blob(_Statement, _Index, _Value) ->
erlang:nif_error(nif_library_not_loaded).
bind_text(_Statement, _Index, _Value) ->
erlang:nif_error(nif_library_not_loaded).
bind_null(_Statement, _Index) ->
erlang:nif_error(nif_library_not_loaded).

View File

@@ -23,12 +23,13 @@ close_test() ->
ok = esqlite3:close(C),
%% Check if functions still return sensible values.
% {error, closed} = esqlite3:set_update_hook(self(), C),
{error, closed} = esqlite3:set_update_hook(C, self()),
{error, closed} = esqlite3:changes(C),
{error, closed} = esqlite3:get_autocommit(C),
{error, closed} = esqlite3:last_insert_rowid(C),
?assertEqual({error, {misuse, invoked_incorrectly}}, esqlite3:exec(C, "create table test(one, two, three)")),
?assertEqual({error, {misuse, invoked_incorrectly}},
esqlite3:exec(C, "create table test(one, two, three)")),
ok.