Formatting
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// MSVC needs "__inline" instead of "inline" in C-source files.
|
// MSVC needs "__inline" instead of "inline" in C-source files.
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# define inline __inline
|
#define inline __inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@@ -75,8 +75,7 @@ static inline int sql_is_insert(const char *sql) {
|
|||||||
int i;
|
int i;
|
||||||
char *insert = "insert";
|
char *insert = "insert";
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if ((tolower(sql[i]) != insert[i]) && (sql[i] != ' '))
|
if ((tolower(sql[i]) != insert[i]) && (sql[i] != ' ')) { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -87,37 +86,37 @@ static void fprint_dataset(FILE* log, ErlDrvTermData* dataset, int term_count);
|
|||||||
|
|
||||||
// required because driver_free(_binary) are macros in Windows
|
// required because driver_free(_binary) are macros in Windows
|
||||||
static void driver_free_fun(void *ptr) {
|
static void driver_free_fun(void *ptr) {
|
||||||
driver_free(ptr);
|
driver_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void driver_free_binary_fun(void *ptr) {
|
static void driver_free_binary_fun(void *ptr) {
|
||||||
driver_free_binary((ErlDrvBinary *) ptr);
|
driver_free_binary((ErlDrvBinary *) ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErlDrvEntry sqlite3_driver_entry = {
|
static ErlDrvEntry sqlite3_driver_entry = {
|
||||||
NULL, /* init */
|
NULL, /* init */
|
||||||
start, /* startup (defined below) */
|
start, /* startup (defined below) */
|
||||||
stop, /* shutdown (defined below) */
|
stop, /* shutdown (defined below) */
|
||||||
NULL, /* output */
|
NULL, /* output */
|
||||||
NULL, /* ready_input */
|
NULL, /* ready_input */
|
||||||
NULL, /* ready_output */
|
NULL, /* ready_output */
|
||||||
"sqlite3_drv", /* the name of the driver */
|
"sqlite3_drv", /* the name of the driver */
|
||||||
NULL, /* finish */
|
NULL, /* finish */
|
||||||
NULL, /* handle */
|
NULL, /* handle */
|
||||||
control, /* control */
|
control, /* control */
|
||||||
NULL, /* timeout */
|
NULL, /* timeout */
|
||||||
NULL, /* outputv */
|
NULL, /* outputv */
|
||||||
ready_async, /* ready_async (defined below) */
|
ready_async, /* ready_async (defined below) */
|
||||||
NULL, /* flush */
|
NULL, /* flush */
|
||||||
NULL, /* call */
|
NULL, /* call */
|
||||||
NULL, /* event */
|
NULL, /* event */
|
||||||
ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */
|
ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */
|
||||||
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */
|
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */
|
||||||
ERL_DRV_EXTENDED_MINOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */
|
ERL_DRV_EXTENDED_MINOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */
|
||||||
ERL_DRV_FLAG_USE_PORT_LOCKING, /* ERL_DRV_FLAGs */
|
ERL_DRV_FLAG_USE_PORT_LOCKING, /* ERL_DRV_FLAGs */
|
||||||
NULL /* handle2 */,
|
NULL /* handle2 */,
|
||||||
NULL /* process_exit */,
|
NULL /* process_exit */,
|
||||||
NULL /* stop_select */
|
NULL /* stop_select */
|
||||||
};
|
};
|
||||||
|
|
||||||
DRIVER_INIT(sqlite3_driver) {
|
DRIVER_INIT(sqlite3_driver) {
|
||||||
@@ -204,29 +203,27 @@ static ErlDrvData start(ErlDrvPort port, char* cmd) {
|
|||||||
|
|
||||||
// Driver Stop
|
// Driver Stop
|
||||||
static void stop(ErlDrvData handle) {
|
static void stop(ErlDrvData handle) {
|
||||||
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) handle;
|
sqlite3_drv_t* drv = (sqlite3_drv_t*) handle;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int close_result;
|
int close_result;
|
||||||
|
|
||||||
if (driver_data->prepared_stmts) {
|
if (drv->prepared_stmts) {
|
||||||
for (i = 0; i < driver_data->prepared_count; i++) {
|
for (i = 0; i < drv->prepared_count; i++) {
|
||||||
sqlite3_finalize(driver_data->prepared_stmts[i]);
|
sqlite3_finalize(drv->prepared_stmts[i]);
|
||||||
}
|
}
|
||||||
driver_free(driver_data->prepared_stmts);
|
driver_free(drv->prepared_stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
close_result = sqlite3_close(driver_data->db);
|
close_result = sqlite3_close(drv->db);
|
||||||
if (close_result != SQLITE_OK) {
|
if (close_result != SQLITE_OK) {
|
||||||
//ERROR((driver_data->log,
|
fprintf(stderr, "Failed to close DB %s, some resources aren't finalized!", sqlite3_db_filename(drv->db, "main"));
|
||||||
// "ERROR: Failed to close DB, some resources aren't finalized!"));
|
|
||||||
fprintf(stderr, "ERROR: Failed to close DB, some resources aren't finalized!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver_data->log && (driver_data->log != stderr)) {
|
if (drv->log && (drv->log != stderr)) {
|
||||||
fclose(driver_data->log);
|
fclose(drv->log);
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_free(driver_data);
|
driver_free(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int output_error(sqlite3_drv_t *drv, int error_code, const char *error);
|
static inline int output_error(sqlite3_drv_t *drv, int error_code, const char *error);
|
||||||
@@ -235,46 +232,46 @@ static inline int output_error(sqlite3_drv_t *drv, int error_code, const char *e
|
|||||||
static ErlDrvSSizeT control(
|
static ErlDrvSSizeT control(
|
||||||
ErlDrvData drv_data, unsigned int command, char *buf,
|
ErlDrvData drv_data, unsigned int command, char *buf,
|
||||||
ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) {
|
ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) {
|
||||||
sqlite3_drv_t* driver_data = (sqlite3_drv_t*) drv_data;
|
sqlite3_drv_t* drv = (sqlite3_drv_t*) drv_data;
|
||||||
if (len > INT_MAX) {
|
if (len > INT_MAX) {
|
||||||
output_error(driver_data, SQLITE_MISUSE, "Command size doesn't fit into int type");
|
output_error(drv, SQLITE_MISUSE, "Command size doesn't fit into int type");
|
||||||
} else {
|
} else {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case CMD_SQL_EXEC:
|
case CMD_SQL_EXEC:
|
||||||
sql_exec(driver_data, buf, (int) len);
|
sql_exec(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_SQL_BIND_AND_EXEC:
|
case CMD_SQL_BIND_AND_EXEC:
|
||||||
sql_bind_and_exec(driver_data, buf, (int) len);
|
sql_bind_and_exec(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARE:
|
case CMD_PREPARE:
|
||||||
prepare(driver_data, buf, (int) len);
|
prepare(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_BIND:
|
case CMD_PREPARED_BIND:
|
||||||
prepared_bind(driver_data, buf, (int) len);
|
prepared_bind(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_STEP:
|
case CMD_PREPARED_STEP:
|
||||||
prepared_step(driver_data, buf, (int) len);
|
prepared_step(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_RESET:
|
case CMD_PREPARED_RESET:
|
||||||
prepared_reset(driver_data, buf, (int) len);
|
prepared_reset(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_CLEAR_BINDINGS:
|
case CMD_PREPARED_CLEAR_BINDINGS:
|
||||||
prepared_clear_bindings(driver_data, buf, (int) len);
|
prepared_clear_bindings(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_FINALIZE:
|
case CMD_PREPARED_FINALIZE:
|
||||||
prepared_finalize(driver_data, buf, (int) len);
|
prepared_finalize(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_PREPARED_COLUMNS:
|
case CMD_PREPARED_COLUMNS:
|
||||||
prepared_columns(driver_data, buf, (int) len);
|
prepared_columns(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_SQL_EXEC_SCRIPT:
|
case CMD_SQL_EXEC_SCRIPT:
|
||||||
sql_exec_script(driver_data, buf, (int) len);
|
sql_exec_script(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
case CMD_ENABLE_LOAD_EXTENSION:
|
case CMD_ENABLE_LOAD_EXTENSION:
|
||||||
enable_load_extension(driver_data, buf, (int) len);
|
enable_load_extension(drv, buf, (int) len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unknown(driver_data, buf, (int) len);
|
unknown(drv, buf, (int) len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -295,7 +292,7 @@ static inline int return_error(
|
|||||||
ERL_DRV_TUPLE, (ErlDrvTermData) 3);
|
ERL_DRV_TUPLE, (ErlDrvTermData) 3);
|
||||||
// int i;
|
// int i;
|
||||||
// for (i = 0; i < *term_count_p; i++) {
|
// for (i = 0; i < *term_count_p; i++) {
|
||||||
// printf("%d\n", (*dataset_p)[i]);
|
// printf("%d\n", (*dataset_p)[i]);
|
||||||
// }
|
// }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -362,7 +359,7 @@ static int enable_load_extension(sqlite3_drv_t* drv, char *buf, int len) {
|
|||||||
static inline async_sqlite3_command *make_async_command_statement(
|
static inline async_sqlite3_command *make_async_command_statement(
|
||||||
sqlite3_drv_t *drv, sqlite3_stmt *statement, int finalize) {
|
sqlite3_drv_t *drv, sqlite3_stmt *statement, int finalize) {
|
||||||
async_sqlite3_command *result =
|
async_sqlite3_command *result =
|
||||||
(async_sqlite3_command *) driver_alloc(sizeof(async_sqlite3_command));
|
(async_sqlite3_command *) driver_alloc(sizeof(async_sqlite3_command));
|
||||||
memset(result, 0, sizeof(async_sqlite3_command));
|
memset(result, 0, sizeof(async_sqlite3_command));
|
||||||
|
|
||||||
result->driver_data = drv;
|
result->driver_data = drv;
|
||||||
@@ -375,7 +372,7 @@ static inline async_sqlite3_command *make_async_command_statement(
|
|||||||
static inline async_sqlite3_command *make_async_command_script(
|
static inline async_sqlite3_command *make_async_command_script(
|
||||||
sqlite3_drv_t *drv, char *script, int script_length) {
|
sqlite3_drv_t *drv, char *script, int script_length) {
|
||||||
async_sqlite3_command *result =
|
async_sqlite3_command *result =
|
||||||
(async_sqlite3_command *) driver_alloc(sizeof(async_sqlite3_command));
|
(async_sqlite3_command *) driver_alloc(sizeof(async_sqlite3_command));
|
||||||
char *script_copy = driver_alloc(sizeof(char) * script_length);
|
char *script_copy = driver_alloc(sizeof(char) * script_length);
|
||||||
memset(result, 0, sizeof(async_sqlite3_command));
|
memset(result, 0, sizeof(async_sqlite3_command));
|
||||||
memcpy(script_copy, script, sizeof(char) * script_length);
|
memcpy(script_copy, script, sizeof(char) * script_length);
|
||||||
@@ -464,8 +461,7 @@ static inline int decode_and_bind_param(
|
|||||||
ei_decode_atom(buffer, p_index, char_buf_val);
|
ei_decode_atom(buffer, p_index, char_buf_val);
|
||||||
if (strncmp(char_buf_val, "null", 5) == 0) {
|
if (strncmp(char_buf_val, "null", 5) == 0) {
|
||||||
result = sqlite3_bind_null(statement, param_index);
|
result = sqlite3_bind_null(statement, param_index);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
output_error(drv, SQLITE_MISUSE, "Non-null atom as parameter");
|
output_error(drv, SQLITE_MISUSE, "Non-null atom as parameter");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -518,6 +514,7 @@ static int bind_parameters(
|
|||||||
long param_index_long;
|
long param_index_long;
|
||||||
char param_name[MAXATOMLEN + 1]; // parameter names shouldn't be longer than 256!
|
char param_name[MAXATOMLEN + 1]; // parameter names shouldn't be longer than 256!
|
||||||
char *acc_string;
|
char *acc_string;
|
||||||
|
|
||||||
result = ei_decode_list_header(buffer, p_index, &cur_list_size);
|
result = ei_decode_list_header(buffer, p_index, &cur_list_size);
|
||||||
if (result) {
|
if (result) {
|
||||||
// probably all parameters are integers between 0 and 255
|
// probably all parameters are integers between 0 and 255
|
||||||
@@ -535,11 +532,13 @@ static int bind_parameters(
|
|||||||
driver_free(acc_string);
|
driver_free(acc_string);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < cur_list_size; i++) {
|
for (i = 0; i < cur_list_size; i++) {
|
||||||
if (*p_index >= buffer_size) {
|
if (*p_index >= buffer_size) {
|
||||||
return output_error(drv, SQLITE_ERROR,
|
return output_error(drv, SQLITE_ERROR,
|
||||||
"error while binding parameters");
|
"error while binding parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_get_type(buffer, p_index, p_type, p_size);
|
ei_get_type(buffer, p_index, p_type, p_size);
|
||||||
if (*p_type == ERL_SMALL_TUPLE_EXT) {
|
if (*p_type == ERL_SMALL_TUPLE_EXT) {
|
||||||
int old_index = *p_index;
|
int old_index = *p_index;
|
||||||
@@ -567,8 +566,7 @@ static int bind_parameters(
|
|||||||
*p_index = old_index;
|
*p_index = old_index;
|
||||||
param_indices_are_explicit = 0;
|
param_indices_are_explicit = 0;
|
||||||
goto IMPLICIT_INDEX; // yuck
|
goto IMPLICIT_INDEX; // yuck
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
param_index = sqlite3_bind_parameter_index(statement, param_name);
|
param_index = sqlite3_bind_parameter_index(statement, param_name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -582,12 +580,11 @@ static int bind_parameters(
|
|||||||
param_index = sqlite3_bind_parameter_index(statement, param_name);
|
param_index = sqlite3_bind_parameter_index(statement, param_name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return output_error(
|
return output_error(drv, SQLITE_MISMATCH,
|
||||||
drv, SQLITE_MISMATCH,
|
"parameter index must be given as integer, atom, or string");
|
||||||
"parameter index must be given as integer, atom, or string");
|
|
||||||
}
|
}
|
||||||
result = decode_and_bind_param(
|
result = decode_and_bind_param(
|
||||||
drv, buffer, p_index, statement, param_index, p_type, p_size);
|
drv, buffer, p_index, statement, param_index, p_type, p_size);
|
||||||
if (result != SQLITE_OK) {
|
if (result != SQLITE_OK) {
|
||||||
return result; // error has already been output
|
return result; // error has already been output
|
||||||
}
|
}
|
||||||
@@ -595,13 +592,12 @@ static int bind_parameters(
|
|||||||
else {
|
else {
|
||||||
IMPLICIT_INDEX:
|
IMPLICIT_INDEX:
|
||||||
if (param_indices_are_explicit) {
|
if (param_indices_are_explicit) {
|
||||||
return output_error(
|
return output_error(drv, SQLITE_MISUSE,
|
||||||
drv, SQLITE_MISUSE,
|
"parameters without indices shouldn't follow indexed or named parameters");
|
||||||
"parameters without indices shouldn't follow indexed or named parameters");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = decode_and_bind_param(
|
result = decode_and_bind_param(
|
||||||
drv, buffer, p_index, statement, param_index, p_type, p_size);
|
drv, buffer, p_index, statement, param_index, p_type, p_size);
|
||||||
if (result != SQLITE_OK) {
|
if (result != SQLITE_OK) {
|
||||||
return result; // error has already been output
|
return result; // error has already been output
|
||||||
}
|
}
|
||||||
@@ -683,7 +679,7 @@ static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buffer, int buffer_size)
|
|||||||
|
|
||||||
static void sql_free_async(void *_async_command) {
|
static void sql_free_async(void *_async_command) {
|
||||||
async_sqlite3_command *async_command =
|
async_sqlite3_command *async_command =
|
||||||
(async_sqlite3_command *) _async_command;
|
(async_sqlite3_command *) _async_command;
|
||||||
driver_free(async_command->dataset);
|
driver_free(async_command->dataset);
|
||||||
|
|
||||||
async_command->driver_data->async_handle = 0;
|
async_command->driver_data->async_handle = 0;
|
||||||
@@ -722,7 +718,7 @@ static int sql_exec_one_statement(
|
|||||||
append_to_dataset(2, *dataset_p, *term_count_p, ERL_DRV_ATOM, drv->atom_columns);
|
append_to_dataset(2, *dataset_p, *term_count_p, ERL_DRV_ATOM, drv->atom_columns);
|
||||||
base_term_count = *term_count_p;
|
base_term_count = *term_count_p;
|
||||||
get_columns(
|
get_columns(
|
||||||
drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, ptrs_p, dataset_p);
|
drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, ptrs_p, dataset_p);
|
||||||
EXTEND_DATASET_PTR(4);
|
EXTEND_DATASET_PTR(4);
|
||||||
append_to_dataset(4, *dataset_p, base_term_count + column_count * 3 + 7,
|
append_to_dataset(4, *dataset_p, base_term_count + column_count * 3 + 7,
|
||||||
ERL_DRV_TUPLE, (ErlDrvTermData) 2, ERL_DRV_ATOM, drv->atom_rows);
|
ERL_DRV_TUPLE, (ErlDrvTermData) 2, ERL_DRV_ATOM, drv->atom_rows);
|
||||||
@@ -794,15 +790,15 @@ static int sql_exec_one_statement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (next_row != SQLITE_DONE) {
|
if (next_row != SQLITE_DONE) {
|
||||||
if (column_count == 0) {
|
if (column_count == 0) {
|
||||||
return_error(drv, next_row, sqlite3_errmsg(drv->db),
|
return_error(drv, next_row, sqlite3_errmsg(drv->db),
|
||||||
dataset_p, term_count_p,
|
dataset_p, term_count_p,
|
||||||
term_allocated_p, &async_command->error_code);
|
term_allocated_p, &async_command->error_code);
|
||||||
async_command->finalize_statement_on_free = 1;
|
async_command->finalize_statement_on_free = 1;
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
has_error = 1;
|
has_error = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column_count > 0) {
|
if (column_count > 0) {
|
||||||
@@ -842,8 +838,7 @@ static int sql_exec_one_statement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sql_exec_async(void *_async_command) {
|
static void sql_exec_async(void *_async_command) {
|
||||||
async_sqlite3_command *async_command =
|
async_sqlite3_command *async_command = (async_sqlite3_command *) _async_command;
|
||||||
(async_sqlite3_command *) _async_command;
|
|
||||||
|
|
||||||
sqlite3_stmt *statement = NULL;
|
sqlite3_stmt *statement = NULL;
|
||||||
int result;
|
int result;
|
||||||
@@ -906,8 +901,7 @@ static void sql_exec_async(void *_async_command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sql_step_async(void *_async_command) {
|
static void sql_step_async(void *_async_command) {
|
||||||
async_sqlite3_command *async_command =
|
async_sqlite3_command *async_command = (async_sqlite3_command *) _async_command;
|
||||||
(async_sqlite3_command *) _async_command;
|
|
||||||
int term_count = 0;
|
int term_count = 0;
|
||||||
int term_allocated = 0;
|
int term_allocated = 0;
|
||||||
ErlDrvTermData *dataset = NULL;
|
ErlDrvTermData *dataset = NULL;
|
||||||
@@ -1024,8 +1018,7 @@ POPULATE_COMMAND:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data) {
|
static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data) {
|
||||||
async_sqlite3_command *async_command =
|
async_sqlite3_command *async_command = (async_sqlite3_command *) thread_data;
|
||||||
(async_sqlite3_command *) thread_data;
|
|
||||||
sqlite3_drv_t *drv = async_command->driver_data;
|
sqlite3_drv_t *drv = async_command->driver_data;
|
||||||
|
|
||||||
int res =
|
int res =
|
||||||
@@ -1063,10 +1056,10 @@ static int prepare(sqlite3_drv_t *drv, char *command, int command_size) {
|
|||||||
|
|
||||||
if (drv->prepared_count >= drv->prepared_alloc) {
|
if (drv->prepared_count >= drv->prepared_alloc) {
|
||||||
drv->prepared_alloc =
|
drv->prepared_alloc =
|
||||||
(drv->prepared_alloc != 0) ? 2*drv->prepared_alloc : 4;
|
(drv->prepared_alloc != 0) ? 2*drv->prepared_alloc : 4;
|
||||||
drv->prepared_stmts =
|
drv->prepared_stmts =
|
||||||
driver_realloc(drv->prepared_stmts,
|
driver_realloc(drv->prepared_stmts,
|
||||||
drv->prepared_alloc * sizeof(sqlite3_stmt *));
|
drv->prepared_alloc * sizeof(sqlite3_stmt *));
|
||||||
}
|
}
|
||||||
drv->prepared_stmts[drv->prepared_count] = statement;
|
drv->prepared_stmts[drv->prepared_count] = statement;
|
||||||
drv->prepared_count++;
|
drv->prepared_count++;
|
||||||
@@ -1108,7 +1101,7 @@ static int prepared_bind(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
|
|||||||
|
|
||||||
statement = drv->prepared_stmts[prepared_index];
|
statement = drv->prepared_stmts[prepared_index];
|
||||||
result =
|
result =
|
||||||
bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size);
|
bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size);
|
||||||
if (result == SQLITE_OK) {
|
if (result == SQLITE_OK) {
|
||||||
return output_ok(drv);
|
return output_ok(drv);
|
||||||
} else {
|
} else {
|
||||||
@@ -1146,7 +1139,7 @@ static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
|
|||||||
column_count = sqlite3_column_count(statement);
|
column_count = sqlite3_column_count(statement);
|
||||||
|
|
||||||
get_columns(
|
get_columns(
|
||||||
drv, statement, column_count, 2, &term_count, &term_allocated, &ptrs, &dataset);
|
drv, statement, column_count, 2, &term_count, &term_allocated, &ptrs, &dataset);
|
||||||
EXTEND_DATASET_DIRECT(2);
|
EXTEND_DATASET_DIRECT(2);
|
||||||
append_to_dataset(2, dataset, term_count, ERL_DRV_TUPLE, (ErlDrvTermData) 2);
|
append_to_dataset(2, dataset, term_count, ERL_DRV_TUPLE, (ErlDrvTermData) 2);
|
||||||
|
|
||||||
@@ -1270,13 +1263,13 @@ static int prepared_finalize(sqlite3_drv_t *drv, char *buffer, int buffer_size)
|
|||||||
|
|
||||||
// Unknown Command
|
// Unknown 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 {Port, error, unknown_command}
|
// Return {Port, error, -1, unknown_command}
|
||||||
ErlDrvTermData spec[] = {
|
ErlDrvTermData spec[] = {
|
||||||
ERL_DRV_PORT, driver_mk_port(drv->port),
|
ERL_DRV_PORT, driver_mk_port(drv->port),
|
||||||
ERL_DRV_ATOM, drv->atom_error,
|
ERL_DRV_ATOM, drv->atom_error,
|
||||||
ERL_DRV_INT, (ErlDrvTermData) ((ErlDrvSInt) -1),
|
ERL_DRV_INT, (ErlDrvTermData) ((ErlDrvSInt) -1),
|
||||||
ERL_DRV_ATOM, drv->atom_unknown_cmd,
|
ERL_DRV_ATOM, drv->atom_unknown_cmd,
|
||||||
ERL_DRV_TUPLE, 4
|
ERL_DRV_TUPLE, 4
|
||||||
};
|
};
|
||||||
return
|
return
|
||||||
#ifdef PRE_R16B
|
#ifdef PRE_R16B
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ typedef struct async_sqlite3_command {
|
|||||||
static ErlDrvData start(ErlDrvPort port, char* cmd);
|
static ErlDrvData start(ErlDrvPort port, char* cmd);
|
||||||
static void stop(ErlDrvData handle);
|
static void stop(ErlDrvData handle);
|
||||||
static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
|
static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
|
||||||
ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
|
ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
|
||||||
static int sql_exec(sqlite3_drv_t *drv, char *buf, int len);
|
static int sql_exec(sqlite3_drv_t *drv, char *buf, int len);
|
||||||
static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buf, int len);
|
static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buf, int len);
|
||||||
static int sql_exec_script(sqlite3_drv_t *drv, char *buf, int len);
|
static int sql_exec_script(sqlite3_drv_t *drv, char *buf, int len);
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ write(Db, Tbl, Data) ->
|
|||||||
%% @end
|
%% @end
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec write_timeout(db(), table_id(), [{column_id(), sql_value()}], timeout()) ->
|
-spec write_timeout(db(), table_id(), [{column_id(), sql_value()}], timeout()) ->
|
||||||
sql_non_query_result().
|
sql_non_query_result().
|
||||||
write_timeout(Db, Tbl, Data, Timeout) ->
|
write_timeout(Db, Tbl, Data, Timeout) ->
|
||||||
gen_server:call(Db, {write, Tbl, Data}, Timeout).
|
gen_server:call(Db, {write, Tbl, Data}, Timeout).
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ write_many(Db, Tbl, Data) ->
|
|||||||
%% @end
|
%% @end
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec write_many_timeout(db(), table_id(), [[{column_id(), sql_value()}]], timeout()) ->
|
-spec write_many_timeout(db(), table_id(), [[{column_id(), sql_value()}]], timeout()) ->
|
||||||
[sql_result()].
|
[sql_result()].
|
||||||
write_many_timeout(Db, Tbl, Data, Timeout) ->
|
write_many_timeout(Db, Tbl, Data, Timeout) ->
|
||||||
gen_server:call(Db, {write_many, Tbl, Data}, Timeout).
|
gen_server:call(Db, {write_many, Tbl, Data}, Timeout).
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ write_many_timeout(Db, Tbl, Data, Timeout) ->
|
|||||||
%% @end
|
%% @end
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec update(table_id(), {column_id(), sql_value()}, [{column_id(), sql_value()}]) ->
|
-spec update(table_id(), {column_id(), sql_value()}, [{column_id(), sql_value()}]) ->
|
||||||
sql_non_query_result().
|
sql_non_query_result().
|
||||||
update(Tbl, {Key, Value}, Data) ->
|
update(Tbl, {Key, Value}, Data) ->
|
||||||
update(?MODULE, Tbl, {Key, Value}, Data).
|
update(?MODULE, Tbl, {Key, Value}, Data).
|
||||||
|
|
||||||
@@ -1137,10 +1137,10 @@ wait_result(Port) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
parse_table_info(Info) ->
|
parse_table_info(Info) ->
|
||||||
Info1 = re:replace(Info, <<"CHECK \\('(bin|lst|am)'='(bin|lst|am)'\\)\\)">>, "", [{return, list}]),
|
Info1 = re:replace(Info, <<"CHECK \\('(bin|lst|am)'='(bin|lst|am)'\\)\\)">>, "", [{return, list}]),
|
||||||
{_, [$(|Rest]} = lists:splitwith(fun(C) -> C =/= $( end, Info1),
|
{_, [$(|Rest]} = lists:splitwith(fun(C) -> C =/= $( end, Info1),
|
||||||
%% remove ) at the end
|
%% remove ) at the end
|
||||||
Rest1 = list_init(Rest),
|
Rest1 = list_init(Rest),
|
||||||
Cols = string:tokens(Rest1, ","),
|
Cols = string:tokens(Rest1, ","),
|
||||||
build_table_info(lists:map(fun(X) ->
|
build_table_info(lists:map(fun(X) ->
|
||||||
string:tokens(X, " ")
|
string:tokens(X, " ")
|
||||||
@@ -1159,14 +1159,14 @@ build_constraints(["PRIMARY", "KEY" | Tail]) ->
|
|||||||
{Constraint, Rest} = build_primary_key_constraint(Tail),
|
{Constraint, Rest} = build_primary_key_constraint(Tail),
|
||||||
[Constraint | build_constraints(Rest)];
|
[Constraint | build_constraints(Rest)];
|
||||||
build_constraints(["UNIQUE" | Tail]) ->
|
build_constraints(["UNIQUE" | Tail]) ->
|
||||||
[unique | build_constraints(Tail)];
|
[unique | build_constraints(Tail)];
|
||||||
build_constraints(["NOT", "NULL" | Tail]) ->
|
build_constraints(["NOT", "NULL" | Tail]) ->
|
||||||
[not_null | build_constraints(Tail)];
|
[not_null | build_constraints(Tail)];
|
||||||
build_constraints(["DEFAULT", DefaultValue | Tail]) ->
|
build_constraints(["DEFAULT", DefaultValue | Tail]) ->
|
||||||
[{default, sqlite3_lib:sql_to_value(DefaultValue)} | build_constraints(Tail)];
|
[{default, sqlite3_lib:sql_to_value(DefaultValue)} | build_constraints(Tail)];
|
||||||
build_constraints(["CHECK", _ | Tail]) ->
|
build_constraints(["CHECK", _ | Tail]) ->
|
||||||
%% currently ignored
|
%% currently ignored
|
||||||
build_constraints(Tail).
|
build_constraints(Tail).
|
||||||
% build_constraints(["REFERENCES", Check | Tail]) -> ...
|
% build_constraints(["REFERENCES", Check | Tail]) -> ...
|
||||||
|
|
||||||
build_primary_key_constraint(Tokens) -> build_primary_key_constraint(Tokens, []).
|
build_primary_key_constraint(Tokens) -> build_primary_key_constraint(Tokens, []).
|
||||||
@@ -1184,15 +1184,15 @@ build_primary_key_constraint(Tail, Acc) ->
|
|||||||
|
|
||||||
cast_table_name(Bin, SQL) ->
|
cast_table_name(Bin, SQL) ->
|
||||||
case re:run(SQL,<<"CHECK \\('(bin|lst|am)'='(bin|lst|am)'\\)\\)">>,[{capture,all_but_first,binary}]) of
|
case re:run(SQL,<<"CHECK \\('(bin|lst|am)'='(bin|lst|am)'\\)\\)">>,[{capture,all_but_first,binary}]) of
|
||||||
{match, [<<"bin">>, <<"bin">>]} ->
|
{match, [<<"bin">>, <<"bin">>]} ->
|
||||||
Bin;
|
Bin;
|
||||||
{match, [<<"lst">>, <<"lst">>]} ->
|
{match, [<<"lst">>, <<"lst">>]} ->
|
||||||
unicode:characters_to_list(Bin, latin1);
|
unicode:characters_to_list(Bin, latin1);
|
||||||
{match, [<<"am">>, <<"am">>]} ->
|
{match, [<<"am">>, <<"am">>]} ->
|
||||||
binary_to_atom(Bin, latin1);
|
binary_to_atom(Bin, latin1);
|
||||||
_ ->
|
_ ->
|
||||||
%% backwards compatible
|
%% backwards compatible
|
||||||
binary_to_atom(Bin, latin1)
|
binary_to_atom(Bin, latin1)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
list_init([_]) -> [];
|
list_init([_]) -> [];
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ bin_to_hex(Binary) -> << <<(half_byte_to_hex(X)):8>> || <<X:4>> <= Binary>>.
|
|||||||
update_set_sql(Data) ->
|
update_set_sql(Data) ->
|
||||||
ColValueToSqlFun =
|
ColValueToSqlFun =
|
||||||
fun({Col, Value}) ->
|
fun({Col, Value}) ->
|
||||||
[atom_to_list(Col), " = ", value_to_sql(Value)]
|
[atom_to_list(Col), " = ", value_to_sql(Value)]
|
||||||
end,
|
end,
|
||||||
map_intersperse(ColValueToSqlFun, Data, ", ").
|
map_intersperse(ColValueToSqlFun, Data, ", ").
|
||||||
|
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ script_test() ->
|
|||||||
?assertEqual(
|
?assertEqual(
|
||||||
[{columns,["id"]},{rows,[{1},{2}]}],
|
[{columns,["id"]},{rows,[{1},{2}]}],
|
||||||
sqlite3:read_all(script, person)),
|
sqlite3:read_all(script, person)),
|
||||||
Script2 = "select * from person; update person set id=3 where id=2",
|
Script2 = "select * from person; update person set id=3 where id=2",
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
[[{columns,["id"]},{rows,[{1},{2}]}], ok],
|
[[{columns,["id"]},{rows,[{1},{2}]}], ok],
|
||||||
sqlite3:sql_exec_script(script, Script2)),
|
sqlite3:sql_exec_script(script, Script2)),
|
||||||
@@ -311,26 +311,26 @@ script_test() ->
|
|||||||
sqlite3:close(script).
|
sqlite3:close(script).
|
||||||
|
|
||||||
large_offset() ->
|
large_offset() ->
|
||||||
drop_table_if_exists(ct, large_offset),
|
drop_table_if_exists(ct, large_offset),
|
||||||
ok = sqlite3:create_table(ct, large_offset, [{id, integer}]),
|
ok = sqlite3:create_table(ct, large_offset, [{id, integer}]),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
[{columns, ["id"]}, {rows, []}, {error, 20, _}],
|
[{columns, ["id"]}, {rows, []}, {error, 20, _}],
|
||||||
sqlite3:sql_exec(ct, "select * from large_offset limit 1 offset 9223372036854775808")).
|
sqlite3:sql_exec(ct, "select * from large_offset limit 1 offset 9223372036854775808")).
|
||||||
|
|
||||||
issue13() ->
|
issue13() ->
|
||||||
drop_table_if_exists(ct, issue13),
|
drop_table_if_exists(ct, issue13),
|
||||||
ok = sqlite3:create_table(ct, issue13, [{foo, integer}]),
|
ok = sqlite3:create_table(ct, issue13, [{foo, integer}]),
|
||||||
sqlite3:write_many(ct, issue13,
|
sqlite3:write_many(ct, issue13,
|
||||||
[[{foo, X}] || X <- [-1, 0, 127, 128, 255, 256]]),
|
[[{foo, X}] || X <- [-1, 0, 127, 128, 255, 256]]),
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
||||||
sqlite3:sql_exec(ct, "select foo from issue13 where foo > 128;")),
|
sqlite3:sql_exec(ct, "select foo from issue13 where foo > 128;")),
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
||||||
sqlite3:sql_exec(ct, "select foo from issue13 where foo > ?;", [128.0])),
|
sqlite3:sql_exec(ct, "select foo from issue13 where foo > ?;", [128.0])),
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
[{columns, ["foo"]}, {rows, [{255}, {256}]}],
|
||||||
sqlite3:sql_exec(ct, "select foo from issue13 where foo > ?;", [128])).
|
sqlite3:sql_exec(ct, "select foo from issue13 where foo > ?;", [128])).
|
||||||
|
|
||||||
enable_load_extension() ->
|
enable_load_extension() ->
|
||||||
?assertEqual(ok, sqlite3:enable_load_extension(ct, 1)).
|
?assertEqual(ok, sqlite3:enable_load_extension(ct, 1)).
|
||||||
|
|||||||
Reference in New Issue
Block a user