Added step function in favour of multi_step
This commit is contained in:
@@ -40,6 +40,8 @@ typedef struct {
|
|||||||
/* prepared statement */
|
/* prepared statement */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sqlite3_stmt *statement;
|
sqlite3_stmt *statement;
|
||||||
|
|
||||||
|
int column_count;
|
||||||
} esqlite3_stmt;
|
} esqlite3_stmt;
|
||||||
|
|
||||||
/* data associated with ongoing backup */
|
/* data associated with ongoing backup */
|
||||||
@@ -590,7 +592,6 @@ make_binary(ErlNifEnv *env, const void *bytes, unsigned int size)
|
|||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
|
make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
|
||||||
{
|
{
|
||||||
@@ -610,78 +611,10 @@ make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
|
|||||||
case SQLITE_TEXT:
|
case SQLITE_TEXT:
|
||||||
return make_binary(env, sqlite3_column_text(statement, i),
|
return make_binary(env, sqlite3_column_text(statement, i),
|
||||||
sqlite3_column_bytes(statement, i));
|
sqlite3_column_bytes(statement, i));
|
||||||
default:
|
|
||||||
return make_atom(env, "should_not_happen");
|
|
||||||
}
|
}
|
||||||
}
|
return enif_raise_exception(env, make_atom(env, "internal_error"));
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
static ERL_NIF_TERM
|
|
||||||
make_row(ErlNifEnv *env, sqlite3_stmt *statement, ERL_NIF_TERM *array, int size)
|
|
||||||
{
|
|
||||||
if(!array)
|
|
||||||
return make_error_tuple(env, "no_memory");
|
|
||||||
|
|
||||||
for(int i = 0; i < size; i++)
|
|
||||||
array[i] = make_cell(env, statement, i);
|
|
||||||
|
|
||||||
return enif_make_tuple_from_array(env, array, size);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
static ERL_NIF_TERM
|
|
||||||
do_multi_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg)
|
|
||||||
{
|
|
||||||
ERL_NIF_TERM status;
|
|
||||||
ERL_NIF_TERM rows = enif_make_list_from_array(env, NULL, 0);
|
|
||||||
ERL_NIF_TERM *rowBuffer = NULL;
|
|
||||||
int rowBufferSize = 0;
|
|
||||||
|
|
||||||
int chunk_size = 0;
|
|
||||||
enif_get_int(env, arg, &chunk_size);
|
|
||||||
|
|
||||||
int rc = sqlite3_step(stmt);
|
|
||||||
while (rc == SQLITE_ROW && chunk_size-- > 0)
|
|
||||||
{
|
|
||||||
if (!rowBufferSize)
|
|
||||||
rowBufferSize = sqlite3_column_count(stmt);
|
|
||||||
if (rowBuffer == NULL)
|
|
||||||
rowBuffer = (ERL_NIF_TERM *) enif_alloc(sizeof(ERL_NIF_TERM)*rowBufferSize);
|
|
||||||
|
|
||||||
rows = enif_make_list_cell(env, make_row(env, stmt, rowBuffer, rowBufferSize), rows);
|
|
||||||
|
|
||||||
if (chunk_size > 0)
|
|
||||||
rc = sqlite3_step(stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case SQLITE_ROW:
|
|
||||||
status = make_atom(env, "rows");
|
|
||||||
break;
|
|
||||||
case SQLITE_BUSY:
|
|
||||||
status = make_atom(env, "$busy");
|
|
||||||
break;
|
|
||||||
case SQLITE_DONE:
|
|
||||||
//
|
|
||||||
// Automatically reset the statement after a done so
|
|
||||||
// column_names will work after the statement is done.
|
|
||||||
//
|
|
||||||
// Not resetting the statement can lead to vm crashes.
|
|
||||||
//
|
|
||||||
sqlite3_reset(stmt);
|
|
||||||
status = make_atom(env, "$done");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// We use prepare_v2, so any error code can be returned.
|
|
||||||
return make_sqlite3_error_tuple(env, rc, db);
|
|
||||||
}
|
|
||||||
|
|
||||||
enif_free(rowBuffer);
|
|
||||||
return enif_make_tuple2(env, status, rows);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
@@ -940,11 +873,13 @@ esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
{
|
{
|
||||||
esqlite3 *conn;
|
esqlite3 *conn;
|
||||||
|
|
||||||
if(argc != 2)
|
if(argc != 3) {
|
||||||
return enif_make_badarg(env);
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn))
|
if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) {
|
||||||
return enif_make_badarg(env);
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
ErlNifBinary bin;
|
ErlNifBinary bin;
|
||||||
esqlite3_stmt *stmt;
|
esqlite3_stmt *stmt;
|
||||||
@@ -957,17 +892,24 @@ esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
return enif_make_badarg(env);
|
return enif_make_badarg(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int prep_flags;
|
||||||
|
if(!enif_get_uint(env, argv[2], &prep_flags)) {
|
||||||
|
return make_error_tuple(env, "invalid_chunk_size");
|
||||||
|
}
|
||||||
|
|
||||||
stmt = enif_alloc_resource(esqlite3_stmt_type, sizeof(esqlite3_stmt));
|
stmt = enif_alloc_resource(esqlite3_stmt_type, sizeof(esqlite3_stmt));
|
||||||
if(!stmt) {
|
if(!stmt) {
|
||||||
return enif_raise_exception(env, make_atom(env, "no_memory"));
|
return enif_raise_exception(env, make_atom(env, "no_memory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(conn->db, (char *) bin.data, bin.size, &(stmt->statement), &tail);
|
rc = sqlite3_prepare_v3(conn->db, (char *) bin.data, bin.size, prep_flags, &(stmt->statement), &tail);
|
||||||
if(rc != SQLITE_OK) {
|
if(rc != SQLITE_OK) {
|
||||||
enif_release_resource(stmt);
|
enif_release_resource(stmt);
|
||||||
return make_sqlite3_error_tuple(env, rc);
|
return make_sqlite3_error_tuple(env, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stmt->column_count = sqlite3_column_count(stmt->statement);
|
||||||
|
|
||||||
esqlite_stmt = enif_make_resource(env, stmt);
|
esqlite_stmt = enif_make_resource(env, stmt);
|
||||||
enif_release_resource(stmt);
|
enif_release_resource(stmt);
|
||||||
|
|
||||||
@@ -1400,6 +1342,115 @@ esqlite_bind_int(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
return make_atom(env, "ok");
|
return make_atom(env, "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
esqlite_bind_int64(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
|
{
|
||||||
|
esqlite3_stmt *stmt;
|
||||||
|
int index;
|
||||||
|
ErlNifSInt64 value;
|
||||||
|
|
||||||
|
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_get_int64(env, argv[2], &value)) {
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = sqlite3_bind_int64(stmt->statement, index, value);
|
||||||
|
if(rc != SQLITE_OK) {
|
||||||
|
return make_sqlite3_error_tuple(env, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_atom(env, "ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
esqlite_bind_double(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
|
{
|
||||||
|
esqlite3_stmt *stmt;
|
||||||
|
int index;
|
||||||
|
double value;
|
||||||
|
|
||||||
|
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_get_double(env, argv[2], &value)) {
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = sqlite3_bind_double(stmt->statement, index, value);
|
||||||
|
if(rc != SQLITE_OK) {
|
||||||
|
return make_sqlite3_error_tuple(env, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_atom(env, "ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
esqlite_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
|
{
|
||||||
|
esqlite3_stmt *stmt;
|
||||||
|
|
||||||
|
if(argc != 1) {
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = sqlite3_step(stmt->statement);
|
||||||
|
switch(rc) {
|
||||||
|
case SQLITE_ROW:
|
||||||
|
{
|
||||||
|
ERL_NIF_TERM row = enif_make_list(env, 0);
|
||||||
|
for(int i=stmt->column_count; i-- > 0; ) {
|
||||||
|
row = enif_make_list_cell(env, make_cell(env, stmt->statement, i), row);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
case SQLITE_DONE:
|
||||||
|
/* since 3.6.23.1 it is no longer required to do an explict reset.
|
||||||
|
*/
|
||||||
|
return make_atom(env, "done");
|
||||||
|
case SQLITE_BUSY:
|
||||||
|
return make_atom(env, "busy");
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_sqlite3_error_tuple(env, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Backup functions
|
* Backup functions
|
||||||
@@ -1643,16 +1694,19 @@ static ErlNifFunc nif_funcs[] = {
|
|||||||
{"open", 1, esqlite_open, ERL_NIF_DIRTY_JOB_IO_BOUND},
|
{"open", 1, esqlite_open, ERL_NIF_DIRTY_JOB_IO_BOUND},
|
||||||
{"close", 1, esqlite_close, ERL_NIF_DIRTY_JOB_IO_BOUND},
|
{"close", 1, esqlite_close, ERL_NIF_DIRTY_JOB_IO_BOUND},
|
||||||
|
|
||||||
{"prepare", 2, esqlite_prepare},
|
{"prepare", 3, esqlite_prepare},
|
||||||
|
|
||||||
{"column_names", 1, esqlite_column_names},
|
{"column_names", 1, esqlite_column_names},
|
||||||
{"column_decltypes", 1, esqlite_column_decltypes},
|
{"column_decltypes", 1, esqlite_column_decltypes},
|
||||||
|
|
||||||
{"bind_int", 3, esqlite_bind_int},
|
{"bind_int", 3, esqlite_bind_int},
|
||||||
|
{"bind_int64", 3, esqlite_bind_int64},
|
||||||
|
{"bind_double", 3, esqlite_bind_double},
|
||||||
|
|
||||||
|
{"step", 1, esqlite_step},
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{"bind_int64", 3, esqlite_bind_blob},
|
|
||||||
{"bind_double", 3, esqlite_bind_blob},
|
|
||||||
{"bind_text", 3, esqlite_bind_blob},
|
{"bind_text", 3, esqlite_bind_blob},
|
||||||
{"bind_blob", 3, esqlite_bind_blob},
|
{"bind_blob", 3, esqlite_bind_blob},
|
||||||
{"bind_null", 2, esqlite_bind_blob},
|
{"bind_null", 2, esqlite_bind_blob},
|
||||||
@@ -1668,7 +1722,6 @@ static ErlNifFunc nif_funcs[] = {
|
|||||||
{"insert", 4, esqlite_insert},
|
{"insert", 4, esqlite_insert},
|
||||||
{"last_insert_rowid", 3, esqlite_last_insert_rowid},
|
{"last_insert_rowid", 3, esqlite_last_insert_rowid},
|
||||||
{"get_autocommit", 3, esqlite_get_autocommit},
|
{"get_autocommit", 3, esqlite_get_autocommit},
|
||||||
{"multi_step", 5, esqlite_multi_step, ERL_NIF_DIRTY_JOB_IO_BOUND},
|
|
||||||
{"reset", 4, esqlite_reset},
|
{"reset", 4, esqlite_reset},
|
||||||
|
|
||||||
// TODO: {"esqlite_bind", 3, esqlite_bind_named},
|
// TODO: {"esqlite_bind", 3, esqlite_bind_named},
|
||||||
|
|||||||
@@ -20,30 +20,41 @@
|
|||||||
%% higher-level export
|
%% higher-level export
|
||||||
-export([
|
-export([
|
||||||
open/1, close/1,
|
open/1, close/1,
|
||||||
|
|
||||||
prepare/2,
|
prepare/2,
|
||||||
|
prepare/3,
|
||||||
|
|
||||||
column_names/1,
|
column_names/1,
|
||||||
column_decltypes/1,
|
column_decltypes/1,
|
||||||
|
|
||||||
bind_int/3
|
bind_int/3,
|
||||||
|
bind_int64/3,
|
||||||
|
bind_double/3,
|
||||||
|
|
||||||
|
step/1
|
||||||
|
|
||||||
% set_update_hook/2, set_update_hook/3,
|
% set_update_hook/2, set_update_hook/3,
|
||||||
% exec/2, exec/3, exec/4,
|
% exec/2, exec/3, exec/4,
|
||||||
% changes/1, changes/2,
|
% changes/1, changes/2,
|
||||||
% insert/2, insert/3,
|
% insert/2, insert/3,
|
||||||
% last_insert_rowid/1,
|
% last_insert_rowid/1,
|
||||||
|
%
|
||||||
% get_autocommit/1, get_autocommit/2,
|
% get_autocommit/1, get_autocommit/2,
|
||||||
|
%
|
||||||
% step/1, step/2,
|
% step/1, step/2,
|
||||||
|
%
|
||||||
% reset/1,
|
% reset/1,
|
||||||
% bind/2, bind/3,
|
% bind/2, bind/3,
|
||||||
% fetchone/1,
|
% fetchone/1,
|
||||||
% fetchall/1, fetchall/2, fetchall/3,
|
% fetchall/1, fetchall/2, fetchall/3,
|
||||||
% column_types/1, column_types/2,
|
%
|
||||||
|
%
|
||||||
% backup_init/4, backup_init/5,
|
% backup_init/4, backup_init/5,
|
||||||
% backup_finish/1, backup_finish/2,
|
% backup_finish/1, backup_finish/2,
|
||||||
% backup_remaining/1, backup_remaining/2,
|
% backup_remaining/1, backup_remaining/2,
|
||||||
% backup_pagecount/1, backup_pagecount/2,
|
% backup_pagecount/1, backup_pagecount/2,
|
||||||
% backup_step/2, backup_step/3,
|
% backup_step/2, backup_step/3,
|
||||||
|
%
|
||||||
% flush/0
|
% flush/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@@ -52,6 +63,10 @@
|
|||||||
-define(DEFAULT_TIMEOUT, infinity).
|
-define(DEFAULT_TIMEOUT, infinity).
|
||||||
-define(DEFAULT_CHUNK_SIZE, 5000).
|
-define(DEFAULT_CHUNK_SIZE, 5000).
|
||||||
|
|
||||||
|
|
||||||
|
-define(SQLITE_PREPARE_PERSISTENT, 16#01).
|
||||||
|
-define(SQLITE_PREPARE_NO_VTAB, 16#04).
|
||||||
|
|
||||||
-record(esqlite3, {
|
-record(esqlite3, {
|
||||||
db :: esqlite3_nif:esqlite3()
|
db :: esqlite3_nif:esqlite3()
|
||||||
}).
|
}).
|
||||||
@@ -71,6 +86,8 @@
|
|||||||
%-type esqlite3_backup() :: #esqlite3_backup{}.
|
%-type esqlite3_backup() :: #esqlite3_backup{}.
|
||||||
-type sql() :: esqlite3_nif:sql().
|
-type sql() :: esqlite3_nif:sql().
|
||||||
|
|
||||||
|
-type prepare_flags() :: persistent | no_vtab.
|
||||||
|
|
||||||
%% erlang -> sqlite type conversions
|
%% erlang -> sqlite type conversions
|
||||||
%%
|
%%
|
||||||
%% 'undefined' -> null
|
%% 'undefined' -> null
|
||||||
@@ -85,7 +102,7 @@
|
|||||||
-type row() :: tuple(). % tuple of cell_type
|
-type row() :: tuple(). % tuple of cell_type
|
||||||
-type cell_type() :: undefined | integer() | binary() | float().
|
-type cell_type() :: undefined | integer() | binary() | float().
|
||||||
|
|
||||||
-export_type([esqlite3/0, esqlite3_stmt/0, sql/0, row/0, rowid/0, cell_type/0]).
|
-export_type([esqlite3/0, esqlite3_stmt/0, prepare_flags/0, sql/0, row/0, rowid/0, cell_type/0]).
|
||||||
|
|
||||||
%% @doc Opens a sqlite3 database mentioned in Filename.
|
%% @doc Opens a sqlite3 database mentioned in Filename.
|
||||||
%%
|
%%
|
||||||
@@ -389,8 +406,19 @@ close(#esqlite3{db=Connection}) ->
|
|||||||
when Connection :: esqlite3(),
|
when Connection :: esqlite3(),
|
||||||
Sql :: sql(),
|
Sql :: sql(),
|
||||||
PrepareResult :: {ok, esqlite3_stmt()} | {error, _}.
|
PrepareResult :: {ok, esqlite3_stmt()} | {error, _}.
|
||||||
prepare(#esqlite3{db=Connection}, Sql) ->
|
prepare(Connection, Sql) ->
|
||||||
case esqlite3_nif:prepare(Connection, Sql) of
|
prepare(Connection, Sql, []).
|
||||||
|
|
||||||
|
%% @doc Compile a SQL statement. Returns a cached compiled statement which can be used in
|
||||||
|
%% queries.
|
||||||
|
%%
|
||||||
|
-spec prepare(Connection, Sql, PrepareFlags) -> PrepareResult
|
||||||
|
when Connection :: esqlite3(),
|
||||||
|
Sql :: sql(),
|
||||||
|
PrepareFlags :: list(prepare_flags()),
|
||||||
|
PrepareResult :: {ok, esqlite3_stmt()} | {error, _}.
|
||||||
|
prepare(#esqlite3{db=Connection}, Sql, PrepareFlags) ->
|
||||||
|
case esqlite3_nif:prepare(Connection, Sql, props_to_prepare_flag(PrepareFlags)) of
|
||||||
{ok, Stmt} ->
|
{ok, Stmt} ->
|
||||||
{ok, #esqlite3_stmt{db=Connection, stmt=Stmt}};
|
{ok, #esqlite3_stmt{db=Connection, stmt=Stmt}};
|
||||||
{error, _}=Error ->
|
{error, _}=Error ->
|
||||||
@@ -405,6 +433,29 @@ prepare(#esqlite3{db=Connection}, Sql) ->
|
|||||||
bind_int(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
|
bind_int(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
|
||||||
esqlite3_nif:bind_int(Stmt, Index, Value).
|
esqlite3_nif:bind_int(Stmt, Index, Value).
|
||||||
|
|
||||||
|
-spec bind_int64(Statement, Index, Value) -> BindResult
|
||||||
|
when Statement :: esqlite3_stmt(),
|
||||||
|
Index :: integer(),
|
||||||
|
Value :: integer(),
|
||||||
|
BindResult :: ok | {error, _}.
|
||||||
|
bind_int64(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
|
||||||
|
esqlite3_nif:bind_int64(Stmt, Index, Value).
|
||||||
|
|
||||||
|
-spec bind_double(Statement, Index, Value) -> BindResult
|
||||||
|
when Statement :: esqlite3_stmt(),
|
||||||
|
Index :: integer(),
|
||||||
|
Value :: float(),
|
||||||
|
BindResult :: ok | {error, _}.
|
||||||
|
bind_double(#esqlite3_stmt{stmt=Stmt}, Index, Value) ->
|
||||||
|
esqlite3_nif:bind_double(Stmt, Index, Value).
|
||||||
|
|
||||||
|
-spec step(Statement) -> StepResult
|
||||||
|
when Statement :: esqlite3_stmt(),
|
||||||
|
StepResult:: ok | {error, _}.
|
||||||
|
step(#esqlite3_stmt{stmt=Stmt}) ->
|
||||||
|
esqlite3_nif:step(Stmt).
|
||||||
|
|
||||||
|
|
||||||
%% @doc Like prepare/2, but with an extra timeout value.
|
%% @doc Like prepare/2, but with an extra timeout value.
|
||||||
%-spec prepare(sql(), connection(), timeout()) -> {ok, statement()} | {error, _}.
|
%-spec prepare(sql(), connection(), timeout()) -> {ok, statement()} | {error, _}.
|
||||||
%prepare(Sql, #connection{raw_connection=RawConnection}, Timeout) ->
|
%prepare(Sql, #connection{raw_connection=RawConnection}, Timeout) ->
|
||||||
@@ -673,3 +724,25 @@ column_decltypes(#esqlite3_stmt{stmt=Stmt}) ->
|
|||||||
% after
|
% after
|
||||||
% 0 -> ok
|
% 0 -> ok
|
||||||
% end.
|
% end.
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% Helpers
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
props_to_prepare_flag(Props) ->
|
||||||
|
Flag = case proplists:get_value(no_vtab, Props, false) of
|
||||||
|
true -> ?SQLITE_PREPARE_NO_VTAB;
|
||||||
|
false -> 0
|
||||||
|
end,
|
||||||
|
case proplists:get_value(persistent, Props, false) of
|
||||||
|
true -> Flag bor ?SQLITE_PREPARE_PERSISTENT;
|
||||||
|
false -> Flag
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,16 @@
|
|||||||
-export([
|
-export([
|
||||||
open/1,
|
open/1,
|
||||||
close/1,
|
close/1,
|
||||||
prepare/2,
|
prepare/3,
|
||||||
|
|
||||||
column_names/1,
|
column_names/1,
|
||||||
column_decltypes/1,
|
column_decltypes/1,
|
||||||
|
|
||||||
bind_int/3,
|
bind_int/3,
|
||||||
|
bind_int64/3,
|
||||||
|
bind_double/3,
|
||||||
|
|
||||||
|
step/1,
|
||||||
|
|
||||||
interrupt/1
|
interrupt/1
|
||||||
% set_update_hook/4,
|
% set_update_hook/4,
|
||||||
@@ -87,18 +91,26 @@ close(_Db) ->
|
|||||||
|
|
||||||
%% @doc Compile a sql statement.
|
%% @doc Compile a sql statement.
|
||||||
%%
|
%%
|
||||||
-spec prepare(Connection, Sql) -> PrepareResult
|
-spec prepare(Connection, Sql, PrepareFlags) -> PrepareResult
|
||||||
when Connection :: esqlite3(),
|
when Connection :: esqlite3(),
|
||||||
Sql :: sql(),
|
Sql :: sql(),
|
||||||
|
PrepareFlags :: non_neg_integer(),
|
||||||
PrepareResult :: {ok, esqlite3_stmt()} | {error, _}.
|
PrepareResult :: {ok, esqlite3_stmt()} | {error, _}.
|
||||||
prepare(_Connection, _Sql) ->
|
prepare(_Connection, _Sql, _PrepareFlags) ->
|
||||||
erlang:nif_error(nif_library_not_loaded).
|
erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bind_int(_Statement, _Index, _Value) ->
|
bind_int(_Statement, _Index, _Value) ->
|
||||||
erlang:nif_error(nif_library_not_loaded).
|
erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|
||||||
|
bind_int64(_Statement, _Index, _Value) ->
|
||||||
|
erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|
||||||
|
bind_double(_Statement, _Index, _Value) ->
|
||||||
|
erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|
||||||
|
step(_Statement) ->
|
||||||
|
erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|
||||||
% -spec set_update_hook((), pid(), pid()) -> ok | {error, _}.
|
% -spec set_update_hook((), pid(), pid()) -> ok | {error, _}.
|
||||||
%set_update_hook(_Db, _Ref, _Dest, _Pid) ->
|
%set_update_hook(_Db, _Ref, _Dest, _Pid) ->
|
||||||
% erlang:nif_error(nif_library_not_loaded).
|
% erlang:nif_error(nif_library_not_loaded).
|
||||||
|
|||||||
@@ -78,6 +78,19 @@ column_decltypes_test() ->
|
|||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
step_test() ->
|
||||||
|
{ok, C} = esqlite3:open(":memory:"),
|
||||||
|
{ok, Stmt} = esqlite3:prepare(C, "select 1, 2, 3;" ),
|
||||||
|
|
||||||
|
?assertEqual([1,2,3], esqlite3:step(Stmt)),
|
||||||
|
?assertEqual(done, esqlite3:step(Stmt)),
|
||||||
|
|
||||||
|
%% After the done, the statement is reset and
|
||||||
|
?assertEqual([1,2,3], esqlite3:step(Stmt)),
|
||||||
|
?assertEqual(done, esqlite3:step(Stmt)),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
|
||||||
%iodata_test() ->
|
%iodata_test() ->
|
||||||
% {ok, C} = esqlite3:open(":memory:"),
|
% {ok, C} = esqlite3:open(":memory:"),
|
||||||
|
|||||||
Reference in New Issue
Block a user