Can distinguish blobs from text when retrieving data from DB

This commit is contained in:
Alexey Romanov
2010-11-22 18:20:57 +03:00
parent 6d9819c7c1
commit 7cb0ab538e
3 changed files with 48 additions and 26 deletions

View File

@@ -36,7 +36,7 @@ DRIVER_INIT(basic_driver) {
static int print_dataset(ErlDrvTermData *dataset, int term_count); static int print_dataset(ErlDrvTermData *dataset, int term_count);
static inline ptr_list *add_to_ptr_list(ptr_list *list, void *value_ptr); static inline ptr_list *add_to_ptr_list(ptr_list *list, void *value_ptr);
static inline void free_ptr_list(ptr_list *list); static inline void free_ptr_list(ptr_list *list, void(* free_head)(void *));
// Driver Start // Driver Start
static ErlDrvData start(ErlDrvPort port, char* cmd) { static ErlDrvData start(ErlDrvPort port, char* cmd) {
@@ -77,6 +77,7 @@ static ErlDrvData start(ErlDrvPort port, char* cmd) {
retval->db = db; retval->db = db;
retval->key = 42; //FIXME: Just a magic number, make real key retval->key = 42; //FIXME: Just a magic number, make real key
retval->atom_blob = driver_mk_atom("blob");
retval->atom_error = driver_mk_atom("error"); retval->atom_error = driver_mk_atom("error");
retval->atom_columns = driver_mk_atom("columns"); retval->atom_columns = driver_mk_atom("columns");
retval->atom_rows = driver_mk_atom("rows"); retval->atom_rows = driver_mk_atom("rows");
@@ -364,13 +365,16 @@ static void sql_free_async(void *_async_command) {
async_command->driver_data->async_handle = 0; async_command->driver_data->async_handle = 0;
free_ptr_list(async_command->ptrs); free_ptr_list(async_command->ptrs, &free);
for (i = 0; i < async_command->binaries_count; i++) {
driver_free_binary(async_command->binaries[i]); free_ptr_list(async_command->binaries, &driver_free_binary);
}
if (async_command->binaries) { // for (i = 0; i < async_command->binaries_count; i++) {
free(async_command->binaries); // driver_free_binary(async_command->binaries[i]);
} // }
// if (async_command->binaries) {
// free(async_command->binaries);
// }
if (async_command->statement) { if (async_command->statement) {
sqlite3_finalize(async_command->statement); sqlite3_finalize(async_command->statement);
} }
@@ -393,8 +397,7 @@ static void sql_exec_async(void *_async_command) {
ptr_list *ptrs = NULL; ptr_list *ptrs = NULL;
ErlDrvBinary **binaries = NULL; ptr_list *binaries = NULL;
int binaries_count = 0;
int i; int i;
column_count = sqlite3_column_count(statement); column_count = sqlite3_column_count(statement);
@@ -475,16 +478,37 @@ static void sql_exec_async(void *_async_command) {
dataset[term_count - 1] = (ErlDrvTermData) float_ptr; dataset[term_count - 1] = (ErlDrvTermData) float_ptr;
break; break;
} }
case SQLITE_BLOB: case SQLITE_BLOB: {
int bytes = sqlite3_column_bytes(statement, i);
ErlDrvBinary* binary = driver_alloc_binary(bytes);
binary->orig_size = bytes;
memcpy(binary->orig_bytes,
sqlite3_column_blob(statement, i), bytes);
binaries = add_to_ptr_list(binaries, binary);
term_count += 8;
if (term_count > term_allocated) {
term_allocated =
(term_count >= term_allocated*2) ? term_count : term_allocated*2;
dataset = realloc(dataset, sizeof(*dataset) * term_allocated);
}
dataset[term_count - 8] = ERL_DRV_ATOM;
dataset[term_count - 7] = drv->atom_blob;
dataset[term_count - 6] = ERL_DRV_BINARY;
dataset[term_count - 5] = (ErlDrvTermData) binary;
dataset[term_count - 4] = bytes;
dataset[term_count - 3] = 0;
dataset[term_count - 2] = ERL_DRV_TUPLE;
dataset[term_count - 1] = 2;
break;
}
case SQLITE_TEXT: { case SQLITE_TEXT: {
int bytes = sqlite3_column_bytes(statement, i); int bytes = sqlite3_column_bytes(statement, i);
binaries_count++; ErlDrvBinary* binary = driver_alloc_binary(bytes);
binaries = binary->orig_size = bytes;
realloc(binaries, sizeof(*binaries) * binaries_count); memcpy(binary->orig_bytes,
binaries[binaries_count - 1] = driver_alloc_binary(bytes);
binaries[binaries_count - 1]->orig_size = bytes;
memcpy(binaries[binaries_count - 1]->orig_bytes,
sqlite3_column_blob(statement, i), bytes); sqlite3_column_blob(statement, i), bytes);
binaries = add_to_ptr_list(binaries, binary);
term_count += 4; term_count += 4;
if (term_count > term_allocated) { if (term_count > term_allocated) {
@@ -493,8 +517,7 @@ static void sql_exec_async(void *_async_command) {
dataset = realloc(dataset, sizeof(*dataset) * term_allocated); dataset = realloc(dataset, sizeof(*dataset) * term_allocated);
} }
dataset[term_count - 4] = ERL_DRV_BINARY; dataset[term_count - 4] = ERL_DRV_BINARY;
dataset[term_count - 3] = dataset[term_count - 3] = (ErlDrvTermData) binary;
(ErlDrvTermData) binaries[binaries_count - 1];
dataset[term_count - 2] = bytes; dataset[term_count - 2] = bytes;
dataset[term_count - 1] = 0; dataset[term_count - 1] = 0;
break; break;
@@ -526,7 +549,6 @@ static void sql_exec_async(void *_async_command) {
async_command->row_count = row_count; async_command->row_count = row_count;
async_command->ptrs = ptrs; async_command->ptrs = ptrs;
async_command->binaries = binaries; async_command->binaries = binaries;
async_command->binaries_count = binaries_count;
if (next_row == SQLITE_BUSY) { if (next_row == SQLITE_BUSY) {
return_error(drv, "SQLite3 database is busy", &async_command->dataset, return_error(drv, "SQLite3 database is busy", &async_command->dataset,
@@ -666,11 +688,11 @@ static inline ptr_list *add_to_ptr_list(ptr_list *list, void *value_ptr) {
} }
} }
static inline void free_ptr_list(ptr_list *list) { static inline void free_ptr_list(ptr_list *list, void(* free_head)(void *)) {
ptr_list* tail; ptr_list* tail;
while (list) { while (list) {
tail = list->tail; tail = list->tail;
free(list->head); (*free_head)(list->head);
free(list); free(list);
list = tail; list = tail;
} }

View File

@@ -36,6 +36,7 @@ typedef struct sqlite3_drv_t {
struct sqlite3 *db; struct sqlite3 *db;
long async_handle; long async_handle;
FILE *log; FILE *log;
ErlDrvTermData atom_blob;
ErlDrvTermData atom_error; ErlDrvTermData atom_error;
ErlDrvTermData atom_columns; ErlDrvTermData atom_columns;
ErlDrvTermData atom_rows; ErlDrvTermData atom_rows;
@@ -52,8 +53,7 @@ typedef struct async_sqlite3_command {
int term_count; int term_count;
int row_count; int row_count;
ptr_list *ptrs; ptr_list *ptrs;
int binaries_count; ptr_list *binaries;
ErlDrvBinary **binaries;
} async_sqlite3_command; } async_sqlite3_command;

View File

@@ -122,7 +122,7 @@ parametrized() ->
[null, 1.0, {blob, <<1,0,0>>}]), [null, 1.0, {blob, <<1,0,0>>}]),
?assertEqual( ?assertEqual(
[{columns, ["i", "d", "b"]}, [{columns, ["i", "d", "b"]},
{rows, [{null, 1.0, <<1,0,0>>}]}], {rows, [{null, 1.0, {blob, <<1,0,0>>}}]}],
sqlite3:read_all(ct, user1)). sqlite3:read_all(ct, user1)).
blob() -> blob() ->
@@ -130,7 +130,7 @@ blob() ->
sqlite3:create_table(ct, blobs, [{blob_col, blob}]), sqlite3:create_table(ct, blobs, [{blob_col, blob}]),
sqlite3:write(ct, blobs, [{blob_col, {blob, <<0,255,1,2>>}}]), sqlite3:write(ct, blobs, [{blob_col, {blob, <<0,255,1,2>>}}]),
?assertEqual( ?assertEqual(
[{columns, ["blob_col"]}, {rows, [{<<0,255,1,2>>}]}], [{columns, ["blob_col"]}, {rows, [{{blob, <<0,255,1,2>>}}]}],
sqlite3:read_all(ct, blobs)). sqlite3:read_all(ct, blobs)).
escaping() -> escaping() ->