Added linked lists to handle lists of column pointers in views (not
tested)
This commit is contained in:
226
src/obiview.c
226
src/obiview.c
@ -32,6 +32,7 @@
|
||||
#include "obidebug.h"
|
||||
#include "obilittlebigman.h"
|
||||
#include "hashtable.h"
|
||||
#include "linked_list.h"
|
||||
#include "utils.h"
|
||||
#include "obiblob.h"
|
||||
|
||||
@ -169,10 +170,13 @@ static int create_obiview_file(OBIDMS_p dms, const char* view_name);
|
||||
*
|
||||
* @param view A pointer on the view.
|
||||
*
|
||||
* @retval 0 if the operation was successfully completed.
|
||||
* @retval -1 if an error occurred.
|
||||
*
|
||||
* @since June 2016
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
static void update_column_refs(Obiview_p view);
|
||||
static int update_column_refs(Obiview_p view);
|
||||
|
||||
|
||||
/**
|
||||
@ -763,21 +767,32 @@ static int create_obiview_file(OBIDMS_p dms, const char* view_name)
|
||||
}
|
||||
|
||||
|
||||
static void update_column_refs(Obiview_p view)
|
||||
static int update_column_refs(Obiview_p view)
|
||||
{
|
||||
int i;
|
||||
OBIDMS_column_p column;
|
||||
|
||||
for (i=0; i < (view->infos)->column_count; i++)
|
||||
{
|
||||
strcpy(((((view->infos)->column_references)[i]).column_refs).column_name, (((view->columns)[i])->header)->name);
|
||||
((((view->infos)->column_references)[i]).column_refs).version = (((view->columns)[i])->header)->version;
|
||||
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column from the linked list of column pointers of a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(((((view->infos)->column_references)[i]).column_refs).column_name, (column->header)->name);
|
||||
((((view->infos)->column_references)[i]).column_refs).version = (column->header)->version;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int create_column_dict(Obiview_p view)
|
||||
{
|
||||
int i;
|
||||
OBIDMS_column_p* column_pp;
|
||||
|
||||
view->column_dict = ht_create(MAX_NB_OPENED_COLUMNS);
|
||||
if (view->column_dict == NULL)
|
||||
@ -798,7 +813,15 @@ static int create_column_dict(Obiview_p view)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ht_set(view->column_dict, (((view->infos)->column_references)[i]).alias, (view->columns)+i) < 0)
|
||||
column_pp = (OBIDMS_column_p*) ll_get(view->columns, i);
|
||||
if (column_pp == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column from the linked list of column pointers of a view when creating a column dictionary");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ht_set(view->column_dict, (((view->infos)->column_references)[i]).alias, column_pp) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError adding a column in a column dictionary");
|
||||
@ -824,14 +847,16 @@ static int update_column_dict(Obiview_p view)
|
||||
|
||||
static int update_column_refs_and_dict(Obiview_p view)
|
||||
{
|
||||
update_column_refs(view);
|
||||
if (update_column_refs(view) < 0)
|
||||
return -1;
|
||||
return update_column_dict(view);
|
||||
}
|
||||
|
||||
|
||||
static int update_lines(Obiview_p view, index_t line_count)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
OBIDMS_column_p column;
|
||||
|
||||
// Check that the view is not read-only
|
||||
if (view->read_only)
|
||||
@ -843,8 +868,16 @@ static int update_lines(Obiview_p view, index_t line_count)
|
||||
|
||||
for (i=0; i<((view->infos)->column_count); i++)
|
||||
{
|
||||
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column from the linked list of column pointers of a view when updating view lines");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clone the column first if needed
|
||||
if (!(((view->columns)[i])->writable))
|
||||
if (!(column->writable))
|
||||
{
|
||||
if (clone_column_in_view(view, (((view->infos)->column_references)[i]).alias) < 0)
|
||||
{
|
||||
@ -853,13 +886,13 @@ static int update_lines(Obiview_p view, index_t line_count)
|
||||
}
|
||||
}
|
||||
// Enlarge the column if needed
|
||||
while (line_count > (((view->columns)[i])->header)->line_count)
|
||||
while (line_count > (column->header)->line_count)
|
||||
{
|
||||
if (obi_enlarge_column(((view->columns)[i])) < 0)
|
||||
if (obi_enlarge_column(column) < 0)
|
||||
return -1;
|
||||
}
|
||||
// Set the number of lines used to the new view line count
|
||||
(((view->columns)[i])->header)->lines_used = line_count;
|
||||
(column->header)->lines_used = line_count;
|
||||
}
|
||||
|
||||
(view->infos)->line_count = line_count;
|
||||
@ -872,6 +905,7 @@ static OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_n
|
||||
{
|
||||
int i;
|
||||
OBIDMS_column_p column = NULL;
|
||||
OBIDMS_column_p new_column = NULL;
|
||||
OBIDMS_column_p column_buffer;
|
||||
bool found;
|
||||
|
||||
@ -890,24 +924,37 @@ static OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_n
|
||||
{ // Clone with the right line selection and replace (for all columns if there is a line selection)
|
||||
|
||||
// Save pointer to close column after cloning
|
||||
column_buffer = (view->columns)[i];
|
||||
column_buffer = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column_buffer == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column to clone from the linked list of column pointers of a view");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Clone and replace the column in the view
|
||||
(view->columns)[i] = obi_clone_column(view->dms, view->line_selection, (((view->columns)[i])->header)->name, (((view->columns)[i])->header)->version, 1);
|
||||
if ((view->columns)[i] == NULL)
|
||||
column = obi_clone_column(view->dms, view->line_selection, (column_buffer->header)->name, (column_buffer->header)->version, true);
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError cloning a column to replace in a view");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Change the pointer in the linked list of column pointers
|
||||
if (ll_set(view->columns, i, column) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError changing the column pointer of a cloned column in the linked list of column pointers of a view");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Close old cloned column
|
||||
obi_close_column(column_buffer);
|
||||
|
||||
if (!strcmp((((view->infos)->column_references)[i]).alias, column_name))
|
||||
{ // Found the column to return
|
||||
column = (view->columns)[i];
|
||||
}
|
||||
// Found the column to return
|
||||
new_column = column;
|
||||
}
|
||||
}
|
||||
|
||||
@ -922,9 +969,13 @@ static OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_n
|
||||
}
|
||||
|
||||
// Update column refs and dict
|
||||
update_column_refs_and_dict(view);
|
||||
if (update_column_refs_and_dict(view) < 0)
|
||||
{
|
||||
obidebug(1, "\nError updating columns references and dictionary after cloning a column in a view");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return column;
|
||||
return new_column;
|
||||
}
|
||||
|
||||
|
||||
@ -952,7 +1003,11 @@ static int save_view(Obiview_p view)
|
||||
(view->infos)->all_lines = true;
|
||||
}
|
||||
|
||||
update_column_refs(view);
|
||||
if (update_column_refs(view) < 0)
|
||||
{
|
||||
obidebug(1, "\nError updating column references when saving a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1044,12 +1099,20 @@ static int close_view(Obiview_p view)
|
||||
{
|
||||
int i;
|
||||
int ret_value;
|
||||
OBIDMS_column_p column;
|
||||
|
||||
ret_value = 0;
|
||||
|
||||
for (i=0; i < ((view->infos)->column_count); i++)
|
||||
{
|
||||
if (obi_close_column((view->columns)[i]) < 0)
|
||||
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column to close from the linked list of column pointers of a view");
|
||||
return -1;
|
||||
}
|
||||
if (obi_close_column(column) < 0)
|
||||
{
|
||||
obidebug(1, "\nError closing a column while closing a view");
|
||||
ret_value = -1;
|
||||
@ -1066,6 +1129,9 @@ static int close_view(Obiview_p view)
|
||||
}
|
||||
}
|
||||
|
||||
// Free the linked list of column pointers
|
||||
ll_free(view->columns);
|
||||
|
||||
// Free the column dictionary
|
||||
ht_free(view->column_dict);
|
||||
|
||||
@ -1251,6 +1317,7 @@ static char* view_check_qual_match_seqs(Obiview_p view)
|
||||
int qual_len;
|
||||
const uint8_t* qual;
|
||||
char* seq;
|
||||
OBIDMS_column_p column;
|
||||
OBIDMS_column_p qual_column;
|
||||
OBIDMS_column_p seq_column;
|
||||
char* predicate;
|
||||
@ -1260,12 +1327,20 @@ static char* view_check_qual_match_seqs(Obiview_p view)
|
||||
at_least_one_qual_col = false;
|
||||
for (i=0; i < ((view->infos)->column_count); i++)
|
||||
{
|
||||
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column to clone from the linked list of column pointers of a view");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if it's a quality column
|
||||
if ((((view->columns)[i])->header)->returned_data_type == OBI_QUAL)
|
||||
if ((column->header)->returned_data_type == OBI_QUAL)
|
||||
{
|
||||
at_least_one_qual_col = true;
|
||||
// Check that the quality arrays match the sequences of the associated column
|
||||
qual_column = (view->columns)[i];
|
||||
qual_column = column;
|
||||
seq_column = obi_open_column(view->dms, ((qual_column->header)->associated_column).column_name, ((qual_column->header)->associated_column).version);
|
||||
if (seq_column == NULL)
|
||||
{
|
||||
@ -1281,7 +1356,7 @@ static char* view_check_qual_match_seqs(Obiview_p view)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check each sequence and its sequence
|
||||
// Check each sequence and its quality
|
||||
for (j=0; j < (view->infos)->line_count; j++)
|
||||
{
|
||||
for (k=0; k < nb_elements_per_line; k++)
|
||||
@ -1434,6 +1509,7 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
int i;
|
||||
index_t line_nb;
|
||||
char* clone_comment;
|
||||
OBIDMS_column_p column;
|
||||
|
||||
// Check that the DMS is a valid pointer
|
||||
if (dms == NULL)
|
||||
@ -1600,10 +1676,10 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
(view->infos)->column_count = 0;
|
||||
(view->infos)->line_count = 0;
|
||||
(view->infos)->all_lines = true;
|
||||
view->line_selection = NULL;
|
||||
((view->infos)->created_from)[0] = '\0';
|
||||
((view->infos)->view_type)[0] = '\0';
|
||||
//view->columns = NULL; // TODO
|
||||
view->line_selection = NULL;
|
||||
view->columns = NULL;
|
||||
}
|
||||
|
||||
// Fill last informations
|
||||
@ -1641,6 +1717,9 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
((view->infos)->line_selection).version = ((view->line_selection)->header)->version;
|
||||
}
|
||||
|
||||
// Initialize linked list of column pointers
|
||||
view->columns = NULL;
|
||||
|
||||
// Create the column dictionary (hash table) associating column names (or aliases) to column pointers
|
||||
if (create_column_dict(view) < 0)
|
||||
{
|
||||
@ -1654,9 +1733,16 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
(view->infos)->column_count = 0;
|
||||
for (i=0; i<((view_to_clone->infos)->column_count); i++)
|
||||
{
|
||||
column = *((OBIDMS_column_p*)ll_get(view_to_clone->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column from the linked list of column pointers of a view");
|
||||
return NULL;
|
||||
}
|
||||
if (obi_view_add_column(view,
|
||||
(((view_to_clone->columns)[i])->header)->name,
|
||||
(((view_to_clone->columns)[i])->header)->version,
|
||||
(column->header)->name,
|
||||
(column->header)->version,
|
||||
(((view_to_clone->infos)->column_references)[i]).alias,
|
||||
0,
|
||||
0,
|
||||
@ -1964,6 +2050,13 @@ Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize view informations
|
||||
view->dms = dms;
|
||||
view->read_only = true;
|
||||
view->nb_predicates = 0;
|
||||
view->predicate_functions = NULL;
|
||||
view->columns = NULL;
|
||||
|
||||
// Map view file
|
||||
view->infos = obi_view_map_file(dms, view_name, true);
|
||||
if ((view->infos) == NULL)
|
||||
@ -2000,15 +2093,15 @@ Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name)
|
||||
close_view(view);
|
||||
return NULL;
|
||||
}
|
||||
(view->columns)[i] = column_pointer;
|
||||
|
||||
view->columns = ll_add(view->columns, column_pointer);
|
||||
if (view->columns == NULL)
|
||||
{
|
||||
obidebug(1, "\nError adding a column in the column linked list of a view: column %d: %s, version %d", i, column_name, column_version);
|
||||
close_view(view);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
view->dms = dms;
|
||||
view->read_only = true;
|
||||
view->nb_predicates = 0;
|
||||
view->predicate_functions = NULL;
|
||||
|
||||
// Create the column dictionary associating each column alias with its pointer
|
||||
if (create_column_dict(view) < 0)
|
||||
{
|
||||
@ -2054,16 +2147,31 @@ int obi_view_add_column(Obiview_p view,
|
||||
{
|
||||
{ // Clone with the right line selection and replace for all columns
|
||||
// Save pointer to close column after cloning
|
||||
column_buffer = (view->columns)[i];
|
||||
column_buffer = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column_buffer == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column to clone from the linked list of column pointers of a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clone and replace the column in the view
|
||||
(view->columns)[i] = obi_clone_column(view->dms, view->line_selection, (((view->columns)[i])->header)->name, (((view->columns)[i])->header)->version, 1);
|
||||
if ((view->columns)[i] == NULL)
|
||||
column = obi_clone_column(view->dms, view->line_selection, (column_buffer->header)->name, (column_buffer->header)->version, 1);
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError cloning a column to replace in a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Change the pointer in the linked list of column pointers
|
||||
if (ll_set(view->columns, i, column) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError changing the column pointer of a cloned column in the linked list of column pointers of a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Close old cloned column
|
||||
obi_close_column(column_buffer);
|
||||
}
|
||||
@ -2120,7 +2228,14 @@ int obi_view_add_column(Obiview_p view,
|
||||
}
|
||||
|
||||
// Store column pointer in the view structure
|
||||
(view->columns)[(view->infos)->column_count] = column;
|
||||
view->columns = ll_add(view->columns, column);
|
||||
if (view->columns == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError adding a column in the linked list of column pointers of a view: column %s, version %d", column_name, version_number);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// If an alias is not defined, it's the original name of the column. // TODO discuss
|
||||
if (alias == NULL)
|
||||
@ -2133,7 +2248,11 @@ int obi_view_add_column(Obiview_p view,
|
||||
(view->infos)->column_count++;
|
||||
|
||||
// Update column references and dictionary
|
||||
update_column_refs_and_dict(view);
|
||||
if (update_column_refs_and_dict(view) < 0)
|
||||
{
|
||||
obidebug(1, "\nError updating column references and dictionary after adding a column to a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// // Print dict
|
||||
// for (i=0; i<((view->infos)->column_count); i++)
|
||||
@ -2150,6 +2269,7 @@ int obi_view_delete_column(Obiview_p view, const char* column_name)
|
||||
{
|
||||
int i;
|
||||
bool found;
|
||||
OBIDMS_column_p column;
|
||||
|
||||
// Check that the view is not read-only
|
||||
if (view->read_only)
|
||||
@ -2162,22 +2282,40 @@ int obi_view_delete_column(Obiview_p view, const char* column_name)
|
||||
found = false;
|
||||
for (i=0; i<((view->infos)->column_count); i++)
|
||||
{
|
||||
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
||||
if (column == NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError getting a column from the linked list of column pointers of a view when deleting a column from a view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((!found) && (!strcmp((((view->infos)->column_references)[i]).alias, column_name)))
|
||||
{
|
||||
obi_close_column((view->columns)[i]);
|
||||
obi_close_column(column);
|
||||
view->columns = ll_delete(view->columns, i);
|
||||
if (view->columns != NULL)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError trying to delete a column: column not found in linked list of column pointers");
|
||||
return -1;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
if (i != (((view->infos)->column_count) - 1)) // not the last one
|
||||
{ // Shift the pointer and the references
|
||||
(view->columns)[i] = (view->columns)[i+1];
|
||||
{ // Shift the references
|
||||
strcpy((((view->infos)->column_references)[i]).alias, (((view->infos)->column_references)[i+1]).alias);
|
||||
strcpy(((((view->infos)->column_references)[i]).column_refs).column_name, ((((view->infos)->column_references)[i+1]).column_refs).column_name);
|
||||
((((view->infos)->column_references)[i]).column_refs).version = ((((view->infos)->column_references)[i+1]).column_refs).version;
|
||||
}
|
||||
else // Last column
|
||||
(view->columns)[i] = NULL;
|
||||
{
|
||||
strcpy((((view->infos)->column_references)[i]).alias, "");
|
||||
strcpy(((((view->infos)->column_references)[i]).column_refs).column_name, "");
|
||||
((((view->infos)->column_references)[i]).column_refs).version = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user