Added linked lists to handle lists of column pointers in views (not
tested)
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
../../../src/dna_seq_indexer.c
|
||||
../../../src/encode.c
|
||||
../../../src/hashtable.c
|
||||
../../../src/linked_list.c
|
||||
../../../src/murmurhash2.c
|
||||
../../../src/obi_align.c
|
||||
../../../src/obiavl.c
|
||||
|
167
src/linked_list.c
Normal file
167
src/linked_list.c
Normal file
@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
* Linked list source file *
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file linked_list.c
|
||||
* @author Celine Mercier
|
||||
* @date February 22th 2017
|
||||
* @brief Source file for linked list functions.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new node.
|
||||
*
|
||||
* @warning The returned pointer has to be freed by the caller.
|
||||
*
|
||||
* @returns A pointer on the new node.
|
||||
* @retval NULL if an error occurred.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
static Linked_list_node_p create_node();
|
||||
|
||||
|
||||
static Linked_list_node_p create_node()
|
||||
{
|
||||
Linked_list_node_p node;
|
||||
|
||||
node = malloc(sizeof(Linked_list_node_t));
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
node->value = NULL;
|
||||
node->previous = NULL;
|
||||
node->next = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// Add a value at the end of a linked list
|
||||
Linked_list_node_p ll_add(Linked_list_node_p head, void* value)
|
||||
{
|
||||
Linked_list_node_p node = head;
|
||||
Linked_list_node_p new_node = NULL;
|
||||
|
||||
// First node
|
||||
if (head == NULL)
|
||||
{
|
||||
head = create_node();
|
||||
if (head == NULL)
|
||||
return NULL;
|
||||
head->value = value;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
while (node->next != NULL)
|
||||
node = node->next;
|
||||
|
||||
new_node = create_node();
|
||||
if (new_node == NULL)
|
||||
return NULL;
|
||||
node->next = new_node;
|
||||
new_node->previous = node;
|
||||
new_node->value = value;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
// Set a value at a given index of the list
|
||||
int ll_set(Linked_list_node_p head, int idx, void* value)
|
||||
{
|
||||
int i = 0;
|
||||
Linked_list_node_p node = head;
|
||||
|
||||
while ((node != NULL) && (i < idx))
|
||||
{
|
||||
node = node->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (node == NULL) // End of list reached before index
|
||||
return -1;
|
||||
|
||||
node->value = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Get a node with its index
|
||||
Linked_list_node_p ll_get(Linked_list_node_p head, int idx)
|
||||
{
|
||||
int i = 0;
|
||||
Linked_list_node_p node = head;
|
||||
|
||||
while ((node != NULL) && (i < idx))
|
||||
{
|
||||
node = node->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// Delete a node
|
||||
Linked_list_node_p ll_delete(Linked_list_node_p head, int idx) // TODO or with value?
|
||||
{
|
||||
int i = 0;
|
||||
Linked_list_node_p node = head;
|
||||
|
||||
while ((node != NULL) && (i < idx))
|
||||
{
|
||||
node = node->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (node == NULL) // Node didn't exist
|
||||
return NULL;
|
||||
|
||||
if (node->previous != NULL)
|
||||
(node->previous)->next = node->next;
|
||||
else // deleting head node: head changes
|
||||
head = node->next;
|
||||
|
||||
if (node->next != NULL)
|
||||
(node->next)->previous = node->previous;
|
||||
|
||||
free(node);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
// Free the linked list
|
||||
void ll_free(Linked_list_node_p head)
|
||||
{
|
||||
Linked_list_node_p node = head;
|
||||
Linked_list_node_p previous = head;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
previous = node;
|
||||
node = node->next;
|
||||
free(previous);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get the index of a node from its value (TODO useless?) -- kinda assumes unique values
|
||||
//int ll_get_index(Linked_list_node_p head, void* value)
|
||||
//{
|
||||
//
|
||||
//}
|
113
src/linked_list.h
Normal file
113
src/linked_list.h
Normal file
@ -0,0 +1,113 @@
|
||||
/****************************************************************************
|
||||
* Linked list header file *
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file linked_list.h
|
||||
* @author Celine Mercier
|
||||
* @date February 22th 2017
|
||||
* @brief Header file for linked list functions.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LINKED_LIST_H_
|
||||
#define LINKED_LIST_H_
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Structure for a node in a double linked chain.
|
||||
*/
|
||||
typedef struct Linked_list_node {
|
||||
void* value; /**< A pointer (the value kept).
|
||||
*/
|
||||
struct Linked_list_node* next; /**< A pointer on the next node.
|
||||
*/
|
||||
struct Linked_list_node* previous; /**< A pointer on the previous node.
|
||||
*/
|
||||
} Linked_list_node_t, *Linked_list_node_p;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a new node at the end of a linked list.
|
||||
*
|
||||
* Works even if it is the first node.
|
||||
*
|
||||
* @param head A pointer on the first node of the linked list, or NULL if the list is empty.
|
||||
* @param value The value to associate with the node.
|
||||
*
|
||||
* @returns A pointer on the new head node of the linked list.
|
||||
* @retval NULL if an error occurred.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
Linked_list_node_p ll_add(Linked_list_node_p head, void* value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets a value at a given index of the list.
|
||||
*
|
||||
* @param head A pointer on the first node of the linked list, or NULL if the list is empty.
|
||||
* @param idx The index of the node at which the value should be changed.
|
||||
* @param value The new value to associate with the node.
|
||||
*
|
||||
* @returns A value indicating the success of the operation.
|
||||
* @retval 0 if the operation was successfully completed.
|
||||
* @retval -1 if an error occurred.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
int ll_set(Linked_list_node_p head, int idx, void* value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets a node from its index.
|
||||
*
|
||||
* @warning The pointer returned is a pointer on the node and not on the value.
|
||||
*
|
||||
* @param head A pointer on the first node of the linked list, or NULL if the list is empty.
|
||||
* @param idx The index of the node to retrieve.
|
||||
*
|
||||
* @returns A pointer on the retrieved node.
|
||||
* @retval NULL if an error occurred.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
Linked_list_node_p ll_get(Linked_list_node_p head, int idx);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes a node.
|
||||
*
|
||||
* @param head A pointer on the first node of the linked list.
|
||||
* @param idx The index of the node to delete.
|
||||
*
|
||||
* @returns A pointer on the new head node of the linked list.
|
||||
* @retval NULL if an error occurred.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
Linked_list_node_p ll_delete(Linked_list_node_p head, int idx);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Frees all the nodes of a linked list.
|
||||
*
|
||||
* @param head A pointer on the first node of the linked list.
|
||||
*
|
||||
* @since February 2017
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
void ll_free(Linked_list_node_p head);
|
||||
|
||||
|
||||
#endif /* LINKED_LIST_H_ */
|
||||
|
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "obidmscolumn.h"
|
||||
#include "obierrno.h"
|
||||
#include "hashtable.h"
|
||||
#include "linked_list.h"
|
||||
#include "obiblob.h"
|
||||
|
||||
|
||||
@ -105,25 +106,25 @@ typedef struct Obiview_infos {
|
||||
* @brief Structure for an opened view.
|
||||
*/
|
||||
typedef struct Obiview {
|
||||
Obiview_infos_p infos; /**< A pointer on the mapped view informations.
|
||||
Obiview_infos_p infos; /**< A pointer on the mapped view informations.
|
||||
*/
|
||||
OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs.
|
||||
OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs.
|
||||
*/
|
||||
bool read_only; /**< Whether the view is read-only or can be modified.
|
||||
bool read_only; /**< Whether the view is read-only or can be modified.
|
||||
*/
|
||||
OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection
|
||||
OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection
|
||||
* associated with the view if there is one.
|
||||
* This line selection is read-only, and when a line from the view is read,
|
||||
* it is this line selection that is used.
|
||||
*/
|
||||
OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; /**< Array of pointers on all the columns of the view.
|
||||
Linked_list_node_p columns; /**< Double linked chain containing the pointers on all the columns of the view.
|
||||
*/
|
||||
hashtable_p column_dict; /**< Hash table storing the pairs of column names or aliases with the associated
|
||||
hashtable_p column_dict; /**< Hash table storing the pairs of column names or aliases with the associated
|
||||
* pointers on column pointers (OBIDMS_column_p*).
|
||||
*/
|
||||
int nb_predicates; /**< Number of predicates to test when closing the view.
|
||||
*/
|
||||
char* (**predicate_functions)(struct Obiview* view); /**< Array of pointers on all predicate functions to test when closing the view.
|
||||
int nb_predicates; /**< Number of predicates to test when closing the view.
|
||||
*/
|
||||
char* (**predicate_functions)(struct Obiview* view); /**< Array of pointers on all predicate functions to test when closing the view.
|
||||
*/
|
||||
} Obiview_t, *Obiview_p;
|
||||
|
||||
|
Reference in New Issue
Block a user