get column types
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,15 +1,9 @@
|
|||||||
.rebar
|
.rebar
|
||||||
|
|
||||||
rebar
|
rebar
|
||||||
|
|
||||||
ebin
|
ebin
|
||||||
|
|
||||||
priv
|
priv
|
||||||
|
|
||||||
.eunit/*
|
.eunit/*
|
||||||
|
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
|
|
||||||
*~
|
*~
|
||||||
|
_build
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ typedef enum {
|
|||||||
cmd_step,
|
cmd_step,
|
||||||
cmd_reset,
|
cmd_reset,
|
||||||
cmd_column_names,
|
cmd_column_names,
|
||||||
|
cmd_column_types,
|
||||||
cmd_close,
|
cmd_close,
|
||||||
cmd_stop,
|
cmd_stop,
|
||||||
cmd_insert
|
cmd_insert
|
||||||
@@ -567,6 +568,37 @@ do_column_names(ErlNifEnv *env, sqlite3_stmt *stmt)
|
|||||||
return column_names;
|
return column_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
do_column_types(ErlNifEnv *env, sqlite3_stmt *stmt)
|
||||||
|
{
|
||||||
|
int i, size;
|
||||||
|
const char *type;
|
||||||
|
ERL_NIF_TERM *array;
|
||||||
|
ERL_NIF_TERM column_types;
|
||||||
|
|
||||||
|
size = sqlite3_column_count(stmt);
|
||||||
|
if(size <= 0)
|
||||||
|
return make_error_tuple(env, "no_columns");
|
||||||
|
|
||||||
|
array = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * size);
|
||||||
|
if(!array)
|
||||||
|
return make_error_tuple(env, "no_memory");
|
||||||
|
|
||||||
|
for(i = 0; i < size; i++) {
|
||||||
|
type = sqlite3_column_decltype(stmt, i);
|
||||||
|
if(type == NULL) {
|
||||||
|
free(array);
|
||||||
|
return make_error_tuple(env, "sqlite3_malloc_failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
array[i] = make_atom(env, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
column_types = enif_make_tuple_from_array(env, array, size);
|
||||||
|
free(array);
|
||||||
|
return column_types;
|
||||||
|
}
|
||||||
|
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
|
do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
|
||||||
{
|
{
|
||||||
@@ -600,6 +632,8 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn)
|
|||||||
return do_bind(cmd->env, conn->db, cmd->stmt, cmd->arg);
|
return do_bind(cmd->env, conn->db, cmd->stmt, cmd->arg);
|
||||||
case cmd_column_names:
|
case cmd_column_names:
|
||||||
return do_column_names(cmd->env, cmd->stmt);
|
return do_column_names(cmd->env, cmd->stmt);
|
||||||
|
case cmd_column_types:
|
||||||
|
return do_column_types(cmd->env, cmd->stmt);
|
||||||
case cmd_close:
|
case cmd_close:
|
||||||
return do_close(cmd->env, conn, cmd->arg);
|
return do_close(cmd->env, conn, cmd->arg);
|
||||||
case cmd_insert:
|
case cmd_insert:
|
||||||
@@ -990,6 +1024,44 @@ esqlite_column_names(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
return push_command(env, stmt->connection, cmd);
|
return push_command(env, stmt->connection, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the column types of the prepared statement.
|
||||||
|
*/
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
esqlite_column_types(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
|
{
|
||||||
|
esqlite_statement *stmt;
|
||||||
|
esqlite_command *cmd = NULL;
|
||||||
|
ErlNifPid pid;
|
||||||
|
|
||||||
|
if(argc != 3)
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
if(!enif_get_resource(env, argv[0], esqlite_statement_type, (void **) &stmt))
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
if(!enif_is_ref(env, argv[1]))
|
||||||
|
return make_error_tuple(env, "invalid_ref");
|
||||||
|
if(!enif_get_local_pid(env, argv[2], &pid))
|
||||||
|
return make_error_tuple(env, "invalid_pid");
|
||||||
|
if(!stmt->statement)
|
||||||
|
return make_error_tuple(env, "no_prepared_statement");
|
||||||
|
|
||||||
|
cmd = command_create();
|
||||||
|
if(!cmd)
|
||||||
|
return make_error_tuple(env, "command_create_failed");
|
||||||
|
|
||||||
|
cmd->type = cmd_column_types;
|
||||||
|
cmd->ref = enif_make_copy(cmd->env, argv[1]);
|
||||||
|
cmd->pid = pid;
|
||||||
|
cmd->stmt = stmt->statement;
|
||||||
|
|
||||||
|
if(!stmt->connection)
|
||||||
|
return make_error_tuple(env, "no_connection");
|
||||||
|
if(!stmt->connection->commands)
|
||||||
|
return make_error_tuple(env, "no_command_queue");
|
||||||
|
|
||||||
|
return push_command(env, stmt->connection, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close the database
|
* Close the database
|
||||||
*/
|
*/
|
||||||
@@ -1065,6 +1137,7 @@ static ErlNifFunc nif_funcs[] = {
|
|||||||
// TODO: {"esqlite_bind", 3, esqlite_bind_named},
|
// TODO: {"esqlite_bind", 3, esqlite_bind_named},
|
||||||
{"bind", 4, esqlite_bind},
|
{"bind", 4, esqlite_bind},
|
||||||
{"column_names", 3, esqlite_column_names},
|
{"column_names", 3, esqlite_column_names},
|
||||||
|
{"column_types", 3, esqlite_column_types},
|
||||||
{"close", 3, esqlite_close}
|
{"close", 3, esqlite_close}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
fetchone/1,
|
fetchone/1,
|
||||||
fetchall/1,
|
fetchall/1,
|
||||||
column_names/1, column_names/2,
|
column_names/1, column_names/2,
|
||||||
|
column_types/1, column_types/2,
|
||||||
close/1, close/2]).
|
close/1, close/2]).
|
||||||
|
|
||||||
-export([q/2, q/3, map/3, foreach/3]).
|
-export([q/2, q/3, map/3, foreach/3]).
|
||||||
@@ -305,6 +306,18 @@ column_names(Stmt, Timeout) ->
|
|||||||
ok = esqlite3_nif:column_names(Stmt, Ref, self()),
|
ok = esqlite3_nif:column_names(Stmt, Ref, self()),
|
||||||
receive_answer(Ref, Timeout).
|
receive_answer(Ref, Timeout).
|
||||||
|
|
||||||
|
%% @doc Return the column types of the prepared statement.
|
||||||
|
%%
|
||||||
|
-spec column_types(statement()) -> tuple(atom()).
|
||||||
|
column_types(Stmt) ->
|
||||||
|
column_types(Stmt, ?DEFAULT_TIMEOUT).
|
||||||
|
|
||||||
|
-spec column_types(statement(), timeout()) -> tuple(atom()).
|
||||||
|
column_types(Stmt, Timeout) ->
|
||||||
|
Ref = make_ref(),
|
||||||
|
ok = esqlite3_nif:column_types(Stmt, Ref, self()),
|
||||||
|
receive_answer(Ref, Timeout).
|
||||||
|
|
||||||
%% @doc Close the database
|
%% @doc Close the database
|
||||||
%%
|
%%
|
||||||
%% @spec close(connection()) -> ok | {error, error_message()}
|
%% @spec close(connection()) -> ok | {error, error_message()}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
finalize/3,
|
finalize/3,
|
||||||
bind/4,
|
bind/4,
|
||||||
column_names/3,
|
column_names/3,
|
||||||
|
column_types/3,
|
||||||
close/3
|
close/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@@ -116,6 +117,12 @@ bind(_Stmt, _Ref, _Dest, _Args) ->
|
|||||||
column_names(_Stmt, _Ref, _Dest) ->
|
column_names(_Stmt, _Ref, _Dest) ->
|
||||||
exit(nif_library_not_loaded).
|
exit(nif_library_not_loaded).
|
||||||
|
|
||||||
|
%% @doc Retrieve the column types of the prepared statement
|
||||||
|
%%
|
||||||
|
%% @spec column_types(statement(), reference(), pid()) -> {ok, tuple()} | {error, message()}
|
||||||
|
column_types(_Stmt, _Ref, _Dest) ->
|
||||||
|
exit(nif_library_not_loaded).
|
||||||
|
|
||||||
%% @doc Close the connection.
|
%% @doc Close the connection.
|
||||||
%%
|
%%
|
||||||
%% @spec close(connection(), reference(), pid()) -> ok | {error, message()}
|
%% @spec close(connection(), reference(), pid()) -> ok | {error, message()}
|
||||||
|
|||||||
@@ -180,6 +180,26 @@ column_names_test() ->
|
|||||||
|
|
||||||
ok.
|
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),
|
||||||
|
{'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.
|
||||||
|
|
||||||
reset_test() ->
|
reset_test() ->
|
||||||
{ok, Db} = esqlite3:open(":memory:"),
|
{ok, Db} = esqlite3:open(":memory:"),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user