Support for 64-bit integers works
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
#include "sqlite3_drv.h"
|
#include "sqlite3_drv.h"
|
||||||
|
|
||||||
// Callback Array
|
// MSVC needs "__inline" instead of "inline" in C-source files.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
static ErlDrvEntry basic_driver_entry = {
|
static ErlDrvEntry basic_driver_entry = {
|
||||||
NULL, /* init */
|
NULL, /* init */
|
||||||
start, /* startup (defined below) */
|
start, /* startup (defined below) */
|
||||||
@@ -28,6 +32,10 @@ DRIVER_INIT(basic_driver) {
|
|||||||
return &basic_driver_entry;
|
return &basic_driver_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 void free_ptr_list(ptr_list *list);
|
||||||
|
|
||||||
// Driver Start
|
// Driver Start
|
||||||
static ErlDrvData start(ErlDrvPort port, char* cmd) {
|
static ErlDrvData start(ErlDrvPort port, char* cmd) {
|
||||||
sqlite3_drv_t* retval = (sqlite3_drv_t*) driver_alloc(sizeof(sqlite3_drv_t));
|
sqlite3_drv_t* retval = (sqlite3_drv_t*) driver_alloc(sizeof(sqlite3_drv_t));
|
||||||
@@ -54,8 +62,8 @@ static ErlDrvData start(ErlDrvPort port, char* cmd) {
|
|||||||
sqlite3_open(db_name, &db);
|
sqlite3_open(db_name, &db);
|
||||||
status = sqlite3_errcode(db);
|
status = sqlite3_errcode(db);
|
||||||
|
|
||||||
if(status != SQLITE_OK) {
|
if (status != SQLITE_OK) {
|
||||||
fprintf(retval->log, "ERROR: Unabled to open file: %s because %s\n\n", DB_PATH, sqlite3_errmsg(db));
|
fprintf(retval->log, "ERROR: Unable to open file: %s because %s\n\n", db_name, sqlite3_errmsg(db));
|
||||||
} else {
|
} else {
|
||||||
fprintf(retval->log, "Opened file %s\n", db_name);
|
fprintf(retval->log, "Opened file %s\n", db_name);
|
||||||
}
|
}
|
||||||
@@ -65,15 +73,13 @@ 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
|
||||||
|
|
||||||
#define STR_(ARG) #ARG
|
|
||||||
#define STR(ARG) STR_(ARG)
|
|
||||||
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");
|
||||||
retval->atom_null = driver_mk_atom (STR (NULL_ATOM));
|
retval->atom_null = driver_mk_atom ("null");
|
||||||
retval->atom_id = driver_mk_atom ("id");
|
retval->atom_id = driver_mk_atom ("id");
|
||||||
retval->atom_ok = driver_mk_atom ("ok");
|
retval->atom_ok = driver_mk_atom ("ok");
|
||||||
retval->atom_unknown_cmd = driver_mk_atom ("uknown_command");
|
retval->atom_unknown_cmd = driver_mk_atom ("unknown_command");
|
||||||
|
|
||||||
fflush (retval->log);
|
fflush (retval->log);
|
||||||
return (ErlDrvData) retval;
|
return (ErlDrvData) retval;
|
||||||
@@ -85,7 +91,7 @@ static void stop(ErlDrvData handle) {
|
|||||||
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) handle;
|
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) handle;
|
||||||
|
|
||||||
sqlite3_close(driver_data->db);
|
sqlite3_close(driver_data->db);
|
||||||
fclose (driver_data->log);
|
fclose(driver_data->log);
|
||||||
driver_data->log = 0;
|
driver_data->log = 0;
|
||||||
|
|
||||||
driver_free(driver_data);
|
driver_free(driver_data);
|
||||||
@@ -93,7 +99,7 @@ static void stop(ErlDrvData handle) {
|
|||||||
|
|
||||||
// Handle input from Erlang VM
|
// Handle input from Erlang VM
|
||||||
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
|
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
|
||||||
int len, char **rbuf, int rlen) {
|
int len, char **rbuf, int rlen) {
|
||||||
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) drv_data;
|
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) drv_data;
|
||||||
|
|
||||||
switch(command) {
|
switch(command) {
|
||||||
@@ -149,6 +155,7 @@ static int sql_exec(sqlite3_drv_t *drv, char *command, int command_size) {
|
|||||||
} else {
|
} else {
|
||||||
sql_exec_async(async_command);
|
sql_exec_async(async_command);
|
||||||
ready_async((ErlDrvData)drv, (ErlDrvThreadData)async_command);
|
ready_async((ErlDrvData)drv, (ErlDrvThreadData)async_command);
|
||||||
|
sql_free_async(async_command);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -161,12 +168,7 @@ static void sql_free_async(void *_async_command)
|
|||||||
|
|
||||||
async_command->driver_data->async_handle = 0;
|
async_command->driver_data->async_handle = 0;
|
||||||
|
|
||||||
if (async_command->int64s) {
|
free_ptr_list(async_command->ptrs);
|
||||||
free(async_command->int64s);
|
|
||||||
}
|
|
||||||
if (async_command->floats) {
|
|
||||||
free(async_command->floats);
|
|
||||||
}
|
|
||||||
for (i = 0; i < async_command->binaries_count; i++) {
|
for (i = 0; i < async_command->binaries_count; i++) {
|
||||||
driver_free_binary(async_command->binaries[i]);
|
driver_free_binary(async_command->binaries[i]);
|
||||||
}
|
}
|
||||||
@@ -192,11 +194,7 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
char *rest = NULL;
|
char *rest = NULL;
|
||||||
sqlite3_stmt *statement = async_command->statement;
|
sqlite3_stmt *statement = async_command->statement;
|
||||||
|
|
||||||
sqlite3_int64 *int64s = NULL;
|
ptr_list *ptrs = NULL;
|
||||||
int int64_count = 0;
|
|
||||||
|
|
||||||
double *floats = NULL;
|
|
||||||
int float_count = 0;
|
|
||||||
|
|
||||||
ErlDrvBinary **binaries = NULL;
|
ErlDrvBinary **binaries = NULL;
|
||||||
int binaries_count = 0;
|
int binaries_count = 0;
|
||||||
@@ -246,25 +244,25 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
// fflush (drv->log);
|
// fflush (drv->log);
|
||||||
switch (sqlite3_column_type(statement, i)) {
|
switch (sqlite3_column_type(statement, i)) {
|
||||||
case SQLITE_INTEGER: {
|
case SQLITE_INTEGER: {
|
||||||
int64_count++;
|
ErlDrvSInt64 *int64_ptr = malloc(sizeof(ErlDrvSInt64));
|
||||||
int64s = realloc(int64s, sizeof(sqlite3_int64) * int64_count);
|
*int64_ptr = (ErlDrvSInt64) sqlite3_column_int64(statement, i);
|
||||||
int64s[int64_count - 1] = sqlite3_column_int64(statement, i);
|
ptrs = add_to_ptr_list(ptrs, int64_ptr);
|
||||||
|
|
||||||
term_count += 2;
|
term_count += 2;
|
||||||
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
||||||
dataset[term_count - 2] = ERL_DRV_INT64;
|
dataset[term_count - 2] = ERL_DRV_INT64;
|
||||||
dataset[term_count - 1] = (ErlDrvTermData)&int64s[int64_count - 1];
|
dataset[term_count - 1] = (ErlDrvTermData) int64_ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLITE_FLOAT: {
|
case SQLITE_FLOAT: {
|
||||||
float_count++;
|
double *float_ptr = malloc(sizeof(double));
|
||||||
floats = realloc(floats, sizeof(double) * float_count);
|
*float_ptr = sqlite3_column_double(statement, i);
|
||||||
floats[float_count - 1] = sqlite3_column_double(statement, i);
|
ptrs = add_to_ptr_list(ptrs, float_ptr);
|
||||||
|
|
||||||
term_count += 2;
|
term_count += 2;
|
||||||
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
dataset = realloc(dataset, sizeof(*dataset) * term_count);
|
||||||
dataset[term_count - 2] = ERL_DRV_FLOAT;
|
dataset[term_count - 2] = ERL_DRV_FLOAT;
|
||||||
dataset[term_count - 1] = (ErlDrvTermData)&floats[float_count - 1];
|
dataset[term_count - 1] = (ErlDrvTermData) float_ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLITE_BLOB:
|
case SQLITE_BLOB:
|
||||||
@@ -301,7 +299,7 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
row_count++;
|
row_count++;
|
||||||
}
|
}
|
||||||
async_command->row_count = row_count;
|
async_command->row_count = row_count;
|
||||||
async_command->floats = floats;
|
async_command->ptrs = ptrs;
|
||||||
async_command->binaries = binaries;
|
async_command->binaries = binaries;
|
||||||
async_command->binaries_count = binaries_count;
|
async_command->binaries_count = binaries_count;
|
||||||
|
|
||||||
@@ -382,12 +380,66 @@ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data)
|
|||||||
sql_free_async(async_command);
|
sql_free_async(async_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unknown Command
|
||||||
// Unkown Command
|
|
||||||
static int unknown(sqlite3_drv_t *drv, char *command, int command_size) {
|
static int unknown(sqlite3_drv_t *drv, char *command, int command_size) {
|
||||||
// Return {error, unkown_command}
|
// Return {error, unknown_command}
|
||||||
ErlDrvTermData spec[] = {ERL_DRV_ATOM, drv->atom_error,
|
ErlDrvTermData spec[] = {ERL_DRV_ATOM, drv->atom_error,
|
||||||
ERL_DRV_ATOM, drv->atom_unknown_cmd,
|
ERL_DRV_ATOM, drv->atom_unknown_cmd,
|
||||||
ERL_DRV_TUPLE, 2};
|
ERL_DRV_TUPLE, 2};
|
||||||
return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
|
return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int print_dataset(ErlDrvTermData *dataset, int term_count) {
|
||||||
|
ErlDrvTermData lastData = *dataset;
|
||||||
|
ErlDrvTermData newData;
|
||||||
|
int i;
|
||||||
|
printf("dataset (%d terms):\n", term_count);
|
||||||
|
for (i = 1; i < term_count; i++) {
|
||||||
|
dataset++;
|
||||||
|
newData = *dataset;
|
||||||
|
switch (lastData) {
|
||||||
|
case ERL_DRV_INT:
|
||||||
|
printf("int: %ld\n", (ErlDrvSInt) newData);
|
||||||
|
break;
|
||||||
|
case ERL_DRV_INT64:
|
||||||
|
printf("int64: %p:%lld\n", (void *) newData, *(ErlDrvSInt64 *) newData);
|
||||||
|
break;
|
||||||
|
case ERL_DRV_FLOAT:
|
||||||
|
printf("int64: %p:%f\n", (void *) newData, *(double *) newData);
|
||||||
|
break;
|
||||||
|
// case ERL_DRV_TUPLE:
|
||||||
|
// printf("tuple of size %d\n", (int) newData);
|
||||||
|
// break;
|
||||||
|
// case ERL_DRV_LIST:
|
||||||
|
// printf("list of length %d\n", (int) newData);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastData = newData;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ptr_list *add_to_ptr_list(ptr_list *list, void *value_ptr) {
|
||||||
|
ptr_list* new_node = malloc(sizeof(ptr_list));
|
||||||
|
new_node->head = value_ptr;
|
||||||
|
new_node->tail = NULL;
|
||||||
|
if (list) {
|
||||||
|
list->tail = new_node;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void free_ptr_list(ptr_list *list) {
|
||||||
|
ptr_list* tail;
|
||||||
|
while (list) {
|
||||||
|
tail = list->tail;
|
||||||
|
free(list->head);
|
||||||
|
free(list);
|
||||||
|
list = tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
// (160 bits for SHA1 hash)
|
// (160 bits for SHA1 hash)
|
||||||
#define KEY_SIZE 20
|
#define KEY_SIZE 20
|
||||||
|
|
||||||
|
typedef struct ptr_list {
|
||||||
|
void *head;
|
||||||
|
struct ptr_list *tail;
|
||||||
|
} ptr_list;
|
||||||
|
|
||||||
// Define struct to hold state across calls
|
// Define struct to hold state across calls
|
||||||
typedef struct sqlite3_drv_t {
|
typedef struct sqlite3_drv_t {
|
||||||
ErlDrvPort port;
|
ErlDrvPort port;
|
||||||
@@ -45,10 +50,9 @@ typedef struct async_sqlite3_command {
|
|||||||
ErlDrvTermData *dataset;
|
ErlDrvTermData *dataset;
|
||||||
int term_count;
|
int term_count;
|
||||||
int row_count;
|
int row_count;
|
||||||
double *floats;
|
ptr_list *ptrs;
|
||||||
int binaries_count;
|
int binaries_count;
|
||||||
ErlDrvBinary **binaries;
|
ErlDrvBinary **binaries;
|
||||||
sqlite3_int64 *int64s;
|
|
||||||
} async_sqlite3_command;
|
} async_sqlite3_command;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user