working, returning ID, etc
This commit is contained in:
@@ -2,7 +2,7 @@ GCC=gcc
|
|||||||
LDFLAGS=-shared -L/usr/local/lib -lsqlite3 -bundle -flat_namespace -undefined suppress -fPIC -lerl_interface -L/usr/local/lib/erlang/lib/erl_interface-3.6.1/lib -lei
|
LDFLAGS=-shared -L/usr/local/lib -lsqlite3 -bundle -flat_namespace -undefined suppress -fPIC -lerl_interface -L/usr/local/lib/erlang/lib/erl_interface-3.6.1/lib -lei
|
||||||
SRCS=sqlite3_drv.c sqlite3_drv.h
|
SRCS=sqlite3_drv.c sqlite3_drv.h
|
||||||
OUTPUT=sqlite3_drv.so
|
OUTPUT=sqlite3_drv.so
|
||||||
CFLAGS=-o ../ebin/${OUTPUT} -I/usr/local/lib/erlang/usr/include/ -I/usr/local/lib/erlang/lib/erl_interface-3.6.1/include/ -arch i386 -arch x86_64
|
CFLAGS=-o ../ebin/${OUTPUT} -I/usr/local/lib/erlang/usr/include/ -I/usr/local/lib/erlang/lib/erl_interface-3.6.1/include/ -arch x86_64
|
||||||
|
|
||||||
all: ../ebin/${OUTPUT}
|
all: ../ebin/${OUTPUT}
|
||||||
|
|
||||||
|
|||||||
@@ -76,15 +76,17 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int return_error(sqlite3_drv_t *drv, const char *error) {
|
static inline int return_error(sqlite3_drv_t *drv, const char *error, ErlDrvTermData **spec, int *terms_count) {
|
||||||
ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"),
|
*spec = (ErlDrvTermData *)calloc(7, sizeof(ErlDrvTermData));
|
||||||
ERL_DRV_STRING, (ErlDrvTermData)error, strlen(error),
|
(*spec)[0] = ERL_DRV_ATOM;
|
||||||
ERL_DRV_TUPLE, 2};
|
(*spec)[1] = driver_mk_atom("error");
|
||||||
|
(*spec)[2] = ERL_DRV_STRING;
|
||||||
return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
|
(*spec)[3] = (ErlDrvTermData)error;
|
||||||
if (error) {
|
(*spec)[4] = strlen(error);
|
||||||
// sqlite3_free((char *)error);
|
(*spec)[5] = ERL_DRV_TUPLE;
|
||||||
}
|
(*spec)[6] = 2;
|
||||||
|
*terms_count = 7;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sql_exec(sqlite3_drv_t *drv, char *command, int command_size) {
|
static int sql_exec(sqlite3_drv_t *drv, char *command, int command_size) {
|
||||||
@@ -95,17 +97,22 @@ static int sql_exec(sqlite3_drv_t *drv, char *command, int command_size) {
|
|||||||
|
|
||||||
result = sqlite3_prepare_v2(drv->db, command, command_size, &statement, (const char **)&rest);
|
result = sqlite3_prepare_v2(drv->db, command, command_size, &statement, (const char **)&rest);
|
||||||
if(result != SQLITE_OK) {
|
if(result != SQLITE_OK) {
|
||||||
return return_error(drv, sqlite3_errmsg(drv->db));
|
ErlDrvTermData *dataset;
|
||||||
|
int term_count;
|
||||||
|
return_error(drv, sqlite3_errmsg(drv->db), &dataset, &term_count);
|
||||||
|
driver_output_term(drv->port, dataset, term_count);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async_sqlite3_command *async_command = (async_sqlite3_command *)calloc(1, sizeof(async_sqlite3_command));
|
async_sqlite3_command *async_command = (async_sqlite3_command *)calloc(1, sizeof(async_sqlite3_command));
|
||||||
async_command->driver_data = drv;
|
async_command->driver_data = drv;
|
||||||
async_command->statement = statement;
|
async_command->statement = statement;
|
||||||
|
|
||||||
fprintf(stderr, "Driver async: %d %p\n", SQLITE_VERSION_NUMBER, async_command->statement);
|
// fprintf(stderr, "Driver async: %d %p\n", SQLITE_VERSION_NUMBER, async_command->statement);
|
||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
sql_exec_async(async_command);
|
sql_exec_async(async_command);
|
||||||
|
ready_async((ErlDrvData)drv, (ErlDrvThreadData)async_command);
|
||||||
} else {
|
} else {
|
||||||
drv->async_handle = driver_async(drv->port, &drv->key, sql_exec_async, async_command, sql_free_async);
|
drv->async_handle = driver_async(drv->port, &drv->key, sql_exec_async, async_command, sql_free_async);
|
||||||
}
|
}
|
||||||
@@ -129,7 +136,9 @@ static void sql_free_async(void *_async_command)
|
|||||||
if(async_command->binaries) {
|
if(async_command->binaries) {
|
||||||
free(async_command->binaries);
|
free(async_command->binaries);
|
||||||
}
|
}
|
||||||
sqlite3_finalize(async_command->statement);
|
if (async_command->statement) {
|
||||||
|
sqlite3_finalize(async_command->statement);
|
||||||
|
}
|
||||||
free(async_command);
|
free(async_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,9 +192,9 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
dataset[base + 2 + column_count*2 + 6] = driver_mk_atom("rows");
|
dataset[base + 2 + column_count*2 + 6] = driver_mk_atom("rows");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fprintf(stderr, "Exec: %s\n", sqlite3_sql(statement));
|
fprintf(stderr, "Exec: %s\n", sqlite3_sql(statement));
|
||||||
while (column_count > 0 && (next_row = sqlite3_step(statement)) == SQLITE_ROW) {
|
|
||||||
|
while ((next_row = sqlite3_step(statement)) == SQLITE_ROW) {
|
||||||
|
|
||||||
for (i = 0; i < column_count; i++) {
|
for (i = 0; i < column_count; i++) {
|
||||||
// fprintf(stderr, "Column %d type: %d\n", i, sqlite3_column_type(statement, i));
|
// fprintf(stderr, "Column %d type: %d\n", i, sqlite3_column_type(statement, i));
|
||||||
@@ -237,11 +246,21 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
|
|
||||||
row_count++;
|
row_count++;
|
||||||
}
|
}
|
||||||
|
async_command->row_count = row_count;
|
||||||
|
async_command->floats = floats;
|
||||||
|
async_command->binaries = binaries;
|
||||||
|
async_command->binaries_count = binaries_count;
|
||||||
|
|
||||||
|
|
||||||
if (next_row == SQLITE_BUSY) {
|
if (next_row == SQLITE_BUSY) {
|
||||||
sqlite3_finalize(statement);
|
return_error(drv, "SQLite3 database is busy", &async_command->dataset, &async_command->term_count);
|
||||||
return_error(drv, "SQLite3 database is busy");
|
return;
|
||||||
}
|
}
|
||||||
|
if (next_row != SQLITE_DONE) {
|
||||||
|
return_error(drv, sqlite3_errmsg(drv->db), &async_command->dataset, &async_command->term_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (column_count > 0) {
|
if (column_count > 0) {
|
||||||
term_count += 3;
|
term_count += 3;
|
||||||
@@ -262,15 +281,26 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
dataset[term_count - 2] = ERL_DRV_LIST;
|
dataset[term_count - 2] = ERL_DRV_LIST;
|
||||||
dataset[term_count - 1] = 3;
|
dataset[term_count - 1] = 3;
|
||||||
|
|
||||||
} else {
|
} else if (strcasestr(sqlite3_sql(statement), "INSERT")) {
|
||||||
|
|
||||||
sqlite3_last_insert_rowid(drv->db);
|
long long rowid = sqlite3_last_insert_rowid(drv->db);
|
||||||
term_count += 4;
|
term_count += 6;
|
||||||
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
||||||
dataset[term_count - 4] = ERL_DRV_ATOM;
|
dataset[term_count - 6] = ERL_DRV_ATOM;
|
||||||
dataset[term_count - 3] = driver_mk_atom("ok");
|
dataset[term_count - 5] = driver_mk_atom("id");
|
||||||
|
dataset[term_count - 4] = ERL_DRV_INT;
|
||||||
|
dataset[term_count - 3] = rowid;
|
||||||
dataset[term_count - 2] = ERL_DRV_TUPLE;
|
dataset[term_count - 2] = ERL_DRV_TUPLE;
|
||||||
dataset[term_count - 1] = 1;
|
dataset[term_count - 1] = 2;
|
||||||
|
} else {
|
||||||
|
term_count += 6;
|
||||||
|
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
||||||
|
dataset[term_count - 6] = ERL_DRV_ATOM;
|
||||||
|
dataset[term_count - 5] = driver_mk_atom("ok");
|
||||||
|
dataset[term_count - 4] = ERL_DRV_INT;
|
||||||
|
dataset[term_count - 3] = next_row;
|
||||||
|
dataset[term_count - 2] = ERL_DRV_TUPLE;
|
||||||
|
dataset[term_count - 1] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
term_count += 2;
|
term_count += 2;
|
||||||
@@ -283,10 +313,6 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
|
|
||||||
async_command->dataset = dataset;
|
async_command->dataset = dataset;
|
||||||
async_command->term_count = term_count;
|
async_command->term_count = term_count;
|
||||||
async_command->row_count = row_count;
|
|
||||||
async_command->floats = floats;
|
|
||||||
async_command->binaries = binaries;
|
|
||||||
async_command->binaries_count = binaries_count;
|
|
||||||
fprintf(stderr, "Total term count: %p %d, rows count: %dx%d\n", statement, term_count, column_count, row_count);
|
fprintf(stderr, "Total term count: %p %d, rows count: %dx%d\n", statement, term_count, column_count, row_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
test.erl
7
test.erl
@@ -4,13 +4,14 @@
|
|||||||
-record(user, {name, age, wage}).
|
-record(user, {name, age, wage}).
|
||||||
|
|
||||||
test() ->
|
test() ->
|
||||||
|
file:delete("store.db"),
|
||||||
sqlite3:open(ct),
|
sqlite3:open(ct),
|
||||||
sqlite3:create_table(ct, user, [{name, text}, {age, integer}, {wage, integer}]),
|
sqlite3:create_table(ct, user, [{name, text}, {age, integer}, {wage, integer}]),
|
||||||
[user] = sqlite3:list_tables(ct),
|
[user] = sqlite3:list_tables(ct),
|
||||||
[{name, text}, {age, integer}, {wage, integer}] = sqlite3:table_info(ct, user),
|
[{name, text}, {age, integer}, {wage, integer}] = sqlite3:table_info(ct, user),
|
||||||
sqlite3:write(ct, user, [{name, "abby"}, {age, 20}, {wage, 2000}]),
|
{id, Id1} = sqlite3:write(ct, user, [{name, "abby"}, {age, 20}, {wage, 2000}]),
|
||||||
sqlite3:write(ct, user, [{name, "marge"}, {age, 30}, {wage, 3000}]),
|
{id, Id2} = sqlite3:write(ct, user, [{name, "marge"}, {age, 30}, {wage, 3000}]),
|
||||||
sqlite3:sql_exec(ct, "select * from user;"),
|
[{columns, [name, age, wage]}, {rows, [{<<"abby">>, 20, 2000}, {<<"marge">>, 30, 3000}]}] = sqlite3:sql_exec(ct, "select * from user;"),
|
||||||
sqlite3:read(ct, user, {name, "abby"}),
|
sqlite3:read(ct, user, {name, "abby"}),
|
||||||
sqlite3:delete(ct, user, {name, "abby"}),
|
sqlite3:delete(ct, user, {name, "abby"}),
|
||||||
sqlite3:drop_table(ct, user),
|
sqlite3:drop_table(ct, user),
|
||||||
|
|||||||
Reference in New Issue
Block a user