From 8752bffec19a0ed07ed357159403b3f32ddf0810 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Mon, 17 Sep 2012 10:32:16 +0400 Subject: [PATCH] Copy column names to driver-allocated memory. Fixes issue #14 by copying out column names before memory can be overwritten by another statement. --- c_src/sqlite3_drv.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/c_src/sqlite3_drv.c b/c_src/sqlite3_drv.c index e9dd5b7..a09fbef 100644 --- a/c_src/sqlite3_drv.c +++ b/c_src/sqlite3_drv.c @@ -507,7 +507,7 @@ static int bind_parameters( static void get_columns( sqlite3_drv_t *drv, sqlite3_stmt *statement, int column_count, int base, - int *p_term_count, int *p_term_allocated, ErlDrvTermData **p_dataset) { + int *p_term_count, int *p_term_allocated, ptr_list** p_ptrs, ErlDrvTermData **p_dataset) { int i; *p_term_count += column_count * 3 + 3; @@ -516,12 +516,16 @@ static void get_columns( *p_dataset = driver_realloc(*p_dataset, sizeof(ErlDrvTermData) * *p_term_allocated); } for (i = 0; i < column_count; i++) { - char *column_name = (char *) sqlite3_column_name(statement, i); - TRACE((drv->log, "Column: %s\n", column_name)); + const char *column_name = sqlite3_column_name(statement, i); + size_t column_name_length = strlen(column_name); + char *column_name_copy = driver_alloc(sizeof(char *) * (column_name_length + 1)); + strcpy(column_name_copy, column_name); + *p_ptrs = add_to_ptr_list(*p_ptrs, column_name_copy); + TRACE((drv->log, "Column: %s\n", column_name_copy)); (*p_dataset)[base + (i * 3)] = ERL_DRV_STRING; - (*p_dataset)[base + (i * 3) + 1] = (ErlDrvTermData) column_name; - (*p_dataset)[base + (i * 3) + 2] = strlen(column_name); + (*p_dataset)[base + (i * 3) + 1] = (ErlDrvTermData) column_name_copy; + (*p_dataset)[base + (i * 3) + 2] = column_name_length; } (*p_dataset)[base + column_count * 3 + 0] = ERL_DRV_NIL; (*p_dataset)[base + column_count * 3 + 1] = ERL_DRV_LIST; @@ -620,7 +624,7 @@ static int sql_exec_one_statement( (*dataset_p)[*term_count_p - 1] = drv->atom_columns; base_term_count = *term_count_p; get_columns( - drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, dataset_p); + drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, ptrs_p, dataset_p); *term_count_p += 4; if (*term_count_p > *term_allocated_p) { *term_allocated_p = max(*term_count_p, *term_allocated_p*2); @@ -1138,6 +1142,7 @@ static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) { int index = 0, term_count = 0, term_allocated = 0, column_count; sqlite3_stmt *statement; ErlDrvTermData *dataset = NULL; + ptr_list* ptrs = NULL; ei_decode_version(buffer, &index, NULL); ei_decode_long(buffer, &index, &long_prepared_index); @@ -1165,11 +1170,13 @@ static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) { column_count = sqlite3_column_count(statement); get_columns( - drv, statement, column_count, 2, &term_count, &term_allocated, &dataset); + drv, statement, column_count, 2, &term_count, &term_allocated, &ptrs, &dataset); dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 1] = 2; - return driver_output_term(drv->port, dataset, term_count); + driver_output_term(drv->port, dataset, term_count); + free_ptr_list(ptrs, driver_free_fun); + return 0; } static int prepared_step(sqlite3_drv_t *drv, char *buffer, int buffer_size) {