Support for utf-8 text. Blobs as separate entities
This commit is contained in:
@@ -310,6 +310,8 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned
|
|||||||
double the_double;
|
double the_double;
|
||||||
char the_atom[MAX_ATOM_LENGTH+1];
|
char the_atom[MAX_ATOM_LENGTH+1];
|
||||||
ErlNifBinary the_blob;
|
ErlNifBinary the_blob;
|
||||||
|
int arity;
|
||||||
|
const ERL_NIF_TERM* tuple;
|
||||||
|
|
||||||
if(enif_get_int(env, cell, &the_int))
|
if(enif_get_int(env, cell, &the_int))
|
||||||
return sqlite3_bind_int(stmt, i, the_int);
|
return sqlite3_bind_int(stmt, i, the_int);
|
||||||
@@ -325,13 +327,22 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned
|
|||||||
return sqlite3_bind_text(stmt, i, the_atom, strlen(the_atom), SQLITE_TRANSIENT);
|
return sqlite3_bind_text(stmt, i, the_atom, strlen(the_atom), SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(enif_inspect_iolist_as_binary(env, cell, &the_blob)) {
|
/* Bind as text assume it is utf-8 encoded text */
|
||||||
/* Bind lists which have the same length as the binary as text. */
|
if(enif_inspect_iolist_as_binary(env, cell, &the_blob))
|
||||||
if(enif_is_list(env, cell) && (strnlen((char *) the_blob.data, the_blob.size) == the_blob.size)) {
|
return sqlite3_bind_text(stmt, i, (char *) the_blob.data, the_blob.size, SQLITE_TRANSIENT);
|
||||||
return sqlite3_bind_text(stmt, i, (char *) the_blob.data, the_blob.size, SQLITE_TRANSIENT);
|
|
||||||
}
|
/* Check for blob tuple */
|
||||||
|
if(enif_get_tuple(env, cell, &arity, &tuple)) {
|
||||||
return sqlite3_bind_blob(stmt, i, the_blob.data, the_blob.size, SQLITE_TRANSIENT);
|
if(arity != 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(enif_get_atom(env, tuple[0], the_atom, sizeof(the_atom), ERL_NIF_LATIN1)) {
|
||||||
|
if(0 == strncmp("blob", the_atom, strlen("blob"))) {
|
||||||
|
if(enif_inspect_iolist_as_binary(env, tuple[1], &the_blob)) {
|
||||||
|
return sqlite3_bind_blob(stmt, i, the_blob.data, the_blob.size, SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@@ -396,12 +407,14 @@ make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
|
|||||||
case SQLITE_FLOAT:
|
case SQLITE_FLOAT:
|
||||||
return enif_make_double(env, sqlite3_column_double(statement, i));
|
return enif_make_double(env, sqlite3_column_double(statement, i));
|
||||||
case SQLITE_BLOB:
|
case SQLITE_BLOB:
|
||||||
return make_binary(env, sqlite3_column_blob(statement, i), sqlite3_column_bytes(statement, i));
|
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:
|
case SQLITE_NULL:
|
||||||
return make_atom(env, "undefined");
|
return make_atom(env, "undefined");
|
||||||
case SQLITE_TEXT:
|
case SQLITE_TEXT:
|
||||||
/* TODO, make some tests to see what happens when you insert a utf-8 string */
|
return make_binary(env, sqlite3_column_text(statement, i),
|
||||||
return enif_make_string(env, (char *) sqlite3_column_text(statement, i), ERL_NIF_LATIN1);
|
sqlite3_column_bytes(statement, i));
|
||||||
default:
|
default:
|
||||||
return make_atom(env, "should_not_happen");
|
return make_atom(env, "should_not_happen");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ prepare_test() ->
|
|||||||
ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db),
|
ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db),
|
||||||
|
|
||||||
%% Check if the values are there.
|
%% Check if the values are there.
|
||||||
[{"one", 2}, {"hello4", 13}] = esqlite3:q("select * from test_table order by two", Db),
|
[{<<"one">>, 2}, {<<"hello4">>, 13}] = esqlite3:q("select * from test_table order by two", Db),
|
||||||
esqlite3:exec("commit;", Db),
|
esqlite3:exec("commit;", Db),
|
||||||
esqlite3:close(Db),
|
esqlite3:close(Db),
|
||||||
|
|
||||||
@@ -62,28 +62,36 @@ bind_test() ->
|
|||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
esqlite3:bind(Statement, ["three", 4]),
|
esqlite3:bind(Statement, ["three", 4]),
|
||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
esqlite3:bind(Statement, [<<"five">>, 6]),
|
esqlite3:bind(Statement, ["five", 6]),
|
||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text
|
esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text
|
||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
esqlite3:bind(Statement, [[<<"nine">>], 10]), % iolist bound as text
|
esqlite3:bind(Statement, [<<"nine">>, 10]), % iolist bound as text
|
||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
esqlite3:bind(Statement, [[<<"eleven">>, 0], 12]), % iolist bound as blob with trailing eos.
|
esqlite3:bind(Statement, [{blob, [<<"eleven">>, 0]}, 12]), % iolist bound as blob with trailing eos.
|
||||||
esqlite3:step(Statement),
|
esqlite3:step(Statement),
|
||||||
|
|
||||||
?assertEqual([{"one", 2}],
|
%% utf-8
|
||||||
|
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)),
|
esqlite3:q("select one, two from test_table where two = '2'", Db)),
|
||||||
?assertEqual([{"three", 4}],
|
?assertEqual([{<<"three">>, 4}],
|
||||||
esqlite3:q("select one, two from test_table where two = 4", Db)),
|
esqlite3:q("select one, two from test_table where two = 4", Db)),
|
||||||
?assertEqual([{<<"five">>, 6}],
|
?assertEqual([{<<"five">>, 6}],
|
||||||
esqlite3:q("select one, two from test_table where two = 6", Db)),
|
esqlite3:q("select one, two from test_table where two = 6", Db)),
|
||||||
?assertEqual([{"seven", 8}],
|
?assertEqual([{<<"seven">>, 8}],
|
||||||
esqlite3:q("select one, two from test_table where two = 8", Db)),
|
esqlite3:q("select one, two from test_table where two = 8", Db)),
|
||||||
?assertEqual([{"nine", 10}],
|
?assertEqual([{<<"nine">>, 10}],
|
||||||
esqlite3:q("select one, two from test_table where two = 10", Db)),
|
esqlite3:q("select one, two from test_table where two = 10", Db)),
|
||||||
?assertEqual([{<<$e,$l,$e,$v,$e,$n,0>>, 12}],
|
?assertEqual([{{blob, <<$e,$l,$e,$v,$e,$n,0>>}, 12}],
|
||||||
esqlite3:q("select one, two from test_table where two = 12", Db)),
|
esqlite3:q("select one, two from test_table where two = 12", Db)),
|
||||||
|
|
||||||
|
%% utf-8
|
||||||
|
?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() ->
|
bind_for_queries_test() ->
|
||||||
@@ -97,12 +105,8 @@ bind_for_queries_test() ->
|
|||||||
[test_table], Db)),
|
[test_table], Db)),
|
||||||
?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
||||||
["test_table"], Db)),
|
["test_table"], Db)),
|
||||||
|
?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
||||||
%% Bound as blob... sqlite can't find the table then.
|
|
||||||
?assertEqual([{0}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
|
||||||
[<<"test_table">>], Db)),
|
[<<"test_table">>], Db)),
|
||||||
|
|
||||||
%% As list it is matched as text.
|
|
||||||
?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
?assertEqual([{1}], esqlite3:q(<<"SELECT count(type) FROM sqlite_master WHERE type='table' AND name=?;">>,
|
||||||
[[<<"test_table">>]], Db)),
|
[[<<"test_table">>]], Db)),
|
||||||
|
|
||||||
@@ -142,10 +146,10 @@ foreach_test() ->
|
|||||||
|
|
||||||
esqlite3:foreach(F, "select * from test_table;", Db),
|
esqlite3:foreach(F, "select * from test_table;", Db),
|
||||||
|
|
||||||
10 = get("hello1"),
|
10 = get(<<"hello1">>),
|
||||||
11 = get("hello2"),
|
11 = get(<<"hello2">>),
|
||||||
12 = get("hello3"),
|
12 = get(<<"hello3">>),
|
||||||
13 = get("hello4"),
|
13 = get(<<"hello4">>),
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@@ -161,17 +165,18 @@ map_test() ->
|
|||||||
|
|
||||||
F = fun(Row) -> Row end,
|
F = fun(Row) -> Row end,
|
||||||
|
|
||||||
[{"hello1",10},{"hello2",11},{"hello3",12},{"hello4",13}] = esqlite3:map(F, "select * from test_table", Db),
|
[{<<"hello1">>,10},{<<"hello2">>,11},{<<"hello3">>,12},{<<"hello4">>,13}]
|
||||||
|
= esqlite3:map(F, "select * from test_table", Db),
|
||||||
|
|
||||||
%% Test that when the row-names are added..
|
%% Test that when the row-names are added..
|
||||||
Assoc = fun(Names, Row) ->
|
Assoc = fun(Names, Row) ->
|
||||||
lists:zip(tuple_to_list(Names), tuple_to_list(Row))
|
lists:zip(tuple_to_list(Names), tuple_to_list(Row))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
[[{one,"hello1"},{two,10}],
|
[[{one,<<"hello1">>},{two,10}],
|
||||||
[{one,"hello2"},{two,11}],
|
[{one,<<"hello2">>},{two,11}],
|
||||||
[{one,"hello3"},{two,12}],
|
[{one,<<"hello3">>},{two,12}],
|
||||||
[{one,"hello4"},{two,13}]] = esqlite3:map(Assoc, "select * from test_table", Db),
|
[{one,<<"hello4">>},{two,13}]] = esqlite3:map(Assoc, "select * from test_table", Db),
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@@ -188,15 +193,6 @@ error1_msg_test() ->
|
|||||||
{error, {cantopen, _Msg3}} = esqlite3:open("/dit/bestaat/niet"),
|
{error, {cantopen, _Msg3}} = esqlite3:open("/dit/bestaat/niet"),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user