4102 lines
122 KiB
C
Executable File
4102 lines
122 KiB
C
Executable File
/********************************************************************
|
|
* Obiview functions *
|
|
********************************************************************/
|
|
|
|
/**
|
|
* @file obiview.c
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
* @date 16 December 2015
|
|
* @brief Obiview functions.
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <inttypes.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
//#include <ctype.h>
|
|
|
|
#include "obiview.h"
|
|
#include "obidms.h"
|
|
#include "obidmscolumn.h"
|
|
#include "obidmscolumn_idx.h"
|
|
#include "obidmscolumn_blob.h"
|
|
#include "obidmscolumn_bool.h"
|
|
#include "obidmscolumn_char.h"
|
|
#include "obidmscolumn_float.h"
|
|
#include "obidmscolumn_int.h"
|
|
#include "obidmscolumn_qual.h"
|
|
#include "obidmscolumn_seq.h"
|
|
#include "obidmscolumn_str.h"
|
|
#include "obidmscolumn_array.h"
|
|
#include "obierrno.h"
|
|
#include "obidebug.h"
|
|
#include "obilittlebigman.h"
|
|
#include "hashtable.h"
|
|
#include "linked_list.h"
|
|
#include "utils.h"
|
|
#include "obiblob.h"
|
|
#include "libjson/json_utils.h"
|
|
|
|
|
|
#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?)
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* D E C L A R A T I O N O F T H E P R I V A T E F U N C T I O N S
|
|
*
|
|
**************************************************************************/
|
|
|
|
|
|
/**
|
|
* Internal function building the file name where the informations about a finished, read-only obiview are stored.
|
|
*
|
|
* @warning The returned pointer has to be freed by the caller.
|
|
*
|
|
* @param view_name The name of the view.
|
|
*
|
|
* @returns A pointer to the file name.
|
|
* @retval NULL if an error occurred.
|
|
*
|
|
* @since June 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* build_obiview_file_name(const char* view_name);
|
|
|
|
|
|
/**
|
|
* Internal function building the file name where the informations about an unfinished, writable obiview are stored.
|
|
*
|
|
* @warning The returned pointer has to be freed by the caller.
|
|
*
|
|
* @param view_name The name of the view.
|
|
*
|
|
* @returns A pointer to the file name.
|
|
* @retval NULL if an error occurred.
|
|
*
|
|
* @since February 2017
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* build_unfinished_obiview_file_name(const char* view_name);
|
|
|
|
|
|
/**
|
|
* Internal function checking if a view is finished.
|
|
*
|
|
* @param dms The DMS.
|
|
* @param view_name The name of the view.
|
|
*
|
|
* @retval 1 if the view is finished.
|
|
* @retval 0 if the view is not finished.
|
|
* @retval -1 if the view does not exist or if an error occurred.
|
|
*
|
|
* @since October 2018
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int view_is_finished(OBIDMS_p dms, const char* view_name);
|
|
|
|
|
|
/**
|
|
* Internal function calculating the initial size of the file where the informations about an obiview are stored.
|
|
*
|
|
* @returns The initial size of the file in bytes, rounded to a multiple of page size.
|
|
*
|
|
* @since June 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static size_t get_platform_view_file_size(void);
|
|
|
|
|
|
/**
|
|
* @brief Internal function enlarging a view file.
|
|
*
|
|
* @param view A pointer on the view.
|
|
* @param new_size The new size needed, in bytes (not necessarily rounded to a page size multiple).
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since August 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int enlarge_view_file(Obiview_p view, size_t new_size);
|
|
|
|
|
|
/**
|
|
* @brief Internal function creating a file containing all the informations on a view.
|
|
*
|
|
* The file is named with the name of the view.
|
|
*
|
|
* @param dms The DMS to which the view belongs.
|
|
* @param view_name The name of 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 int create_obiview_file(OBIDMS_p dms, const char* view_name);
|
|
|
|
|
|
/**
|
|
* @brief Internal function to update the column references of a view.
|
|
*
|
|
* The column references stored in the mapped view infos structures are updated
|
|
* to match the columns opened in the opened view structure.
|
|
*
|
|
* @warning The column pointer array should be up to date before using this function.
|
|
* @warning Aliases are not updated by this function and have to be edited separately.
|
|
* This function simply reads the column pointer array associated with the view
|
|
* and fills the column names and versions in the column reference array accordingly,
|
|
* without touching the alias.
|
|
* That means that for example if there is a shift in the column pointer array, this
|
|
* function should not be used.
|
|
*
|
|
* @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 int update_column_refs(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function creating the column dictionary associated with a view.
|
|
*
|
|
* The column dictionary is built from the column references array, and associates each column alias
|
|
* with the pointer on the column.
|
|
*
|
|
* @warning The column reference array and the column pointer array should be up to date before using this function.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int create_column_dict(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function updating the column dictionary associated with a view.
|
|
*
|
|
* The column dictionary is built from the column references array, and associates each column alias
|
|
* with the pointer on the column.
|
|
*
|
|
* @warning The column reference array and the column pointer array should be up to date before using this function.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int update_column_dict(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function updating the column reference array and the column dictionary associated with a view.
|
|
*
|
|
* The column reference array is updated from the column pointer array, then the column dictionary that
|
|
* and associates each column alias with the pointer on the column is updated from the column reference array.
|
|
*
|
|
* @warning The column pointer array should be up to date before using this function.
|
|
* @warning Aliases are not updated by this function and have to be edited separately.
|
|
* This function simply reads the column pointer array associated with the view
|
|
* and fills the column names and versions in the column reference array accordingly,
|
|
* without touching the alias.
|
|
* That means that for example if there is a shift in the column pointer array, this
|
|
* function should not be used.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int update_column_refs_and_dict(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function to update the line count in the context of a view.
|
|
*
|
|
* All columns of the view are enlarged to contain at least the new line count.
|
|
*
|
|
* @warning The view must be writable.
|
|
*
|
|
* @param view A pointer on the view.
|
|
* @param line_count The new line count.
|
|
*
|
|
* @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 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int update_lines(Obiview_p view, index_t line_count);
|
|
|
|
|
|
/**
|
|
* @brief Internal function to clone a column in the context of a view.
|
|
*
|
|
* Used to edit a closed column.
|
|
*
|
|
* Clones with the right line selection and replaces the cloned columns with the new ones in the view.
|
|
* If there is a line selection, all columns have to be cloned, otherwise only the column of interest is cloned.
|
|
*
|
|
* @param view A pointer on the view.
|
|
* @param column_name The name of the column in the view that should be cloned.
|
|
* @param clone_associated Whether to clone the associated column
|
|
* (should always be true except when calling from the function itself to avoid infinite recursion).
|
|
*
|
|
* @returns A pointer on the new column.
|
|
* @retval NULL if an error occurred.
|
|
*
|
|
* @since February 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name, bool clone_associated);
|
|
|
|
|
|
/**
|
|
* @brief Saves a view, updating its informations in the view file.
|
|
*
|
|
* @warning The view must be writable.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @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 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int save_view(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Rename a view file once the view is finished, replacing the '*.obiview_unfinished' extension with '*.obiview'.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @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)
|
|
*/
|
|
static int rename_finished_view(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Finishes a view: check the predicates, save all the informations, rename the view file.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @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)
|
|
*/
|
|
static int finish_view(Obiview_p view);
|
|
|
|
/**
|
|
* @brief Closes an opened view.
|
|
*
|
|
* @warning Doesn't save the view.
|
|
*
|
|
* @param view A pointer on the view.
|
|
*
|
|
* @returns A value indicating the success of the operation.
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @see obi_save_and_close_view()
|
|
* @since February 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int close_view(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function preparing to set a value in a column, in the context of a view.
|
|
*
|
|
* The function checks that the view is not read-only, clones the column or all columns if needed,
|
|
* and updates the line count if needed.
|
|
*
|
|
* @param view The view.
|
|
* @param column_pp A pointer on the pointer on the column, to allow replacing the column if it is cloned.
|
|
* @param line_nb_p A pointer on the index of the line that will be modified, to allow replacing it if needed.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since April 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, index_t* line_nb_p);
|
|
|
|
|
|
/**
|
|
* @brief Internal function preparing to get a value from a column, in the context of a view.
|
|
*
|
|
* The function checks that the line index is not beyond the current line count of the view,
|
|
* and modifies it if there is a line selection associated with the view.
|
|
*
|
|
* @param view The view.
|
|
* @param line_nb_p A pointer on the index of the line, to allow replacing it if needed.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if an error occurred.
|
|
*
|
|
* @since April 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p);
|
|
|
|
|
|
/****** PREDICATE FUNCTIONS *******/
|
|
|
|
/**
|
|
* @brief Internal function checking if a view has a NUC_SEQUENCE_COLUMN column.
|
|
*
|
|
* The function checks that the view has a column with the name attributed to obligatory
|
|
* nucleotide sequence columns.
|
|
*
|
|
* @param view The view.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_has_nuc_sequence_column(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking if a view has a QUALITY_COLUMN column.
|
|
*
|
|
* The function checks that the view has a column with the name attributed to obligatory
|
|
* quality columns.
|
|
*
|
|
* @param view The view.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_has_quality_column(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking if a view has a ID_COLUMN column.
|
|
*
|
|
* The function checks that the view has a column with the name attributed to obligatory
|
|
* id columns.
|
|
*
|
|
* @param view The view.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_has_id_column(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking if a view has a DEFINITION_COLUMN column.
|
|
*
|
|
* The function checks that the view has a column with the name attributed to obligatory
|
|
* definition columns.
|
|
*
|
|
* @param view The view.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_has_definition_column(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking that all the quality columns of a view and their associated sequence columns
|
|
* correspond properly:
|
|
* - when a line is defined for either column, it must also be defined for the other column
|
|
* - when a line is defined, the lengths of the sequence and of the quality must be equal
|
|
*
|
|
* @param view The view.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_check_qual_match_seqs(Obiview_p view);
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking one predicate function on a view.
|
|
*
|
|
* @param view The view.
|
|
* @param predicate_function The predicate function to use.
|
|
*
|
|
* @returns A character string describing the predicate.
|
|
* @retval NULL if the predicate is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static char* view_check_one_predicate(Obiview_p view, char* (*predicate_function)(Obiview_p view));
|
|
|
|
|
|
/**
|
|
* @brief Internal function checking all the predicates associated with a view.
|
|
*
|
|
* @param view The view.
|
|
* @param write Whether the verified predicates should be written in the view comments.
|
|
*
|
|
* @retval 0 if the operation was successfully completed.
|
|
* @retval -1 if at least one of the predicates is false or if there was an error.
|
|
*
|
|
* @since July 2016
|
|
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
|
*/
|
|
static int view_check_all_predicates(Obiview_p view, bool write);
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* D E F I N I T I O N O F T H E P R I V A T E F U N C T I O N S
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static char* build_obiview_file_name(const char* view_name)
|
|
{
|
|
char* file_name;
|
|
|
|
// Build file name
|
|
file_name = (char*) malloc((strlen(view_name) + 8 + 1)*sizeof(char));
|
|
if (file_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view file name");
|
|
return NULL;
|
|
}
|
|
if (sprintf(file_name, "%s.obiview", view_name) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nProblem building an obiview file name");
|
|
return NULL;
|
|
}
|
|
|
|
return file_name;
|
|
}
|
|
|
|
|
|
static char* build_unfinished_obiview_file_name(const char* view_name)
|
|
{
|
|
char* file_name;
|
|
|
|
// Build file name
|
|
file_name = (char*) malloc((strlen(view_name) + 19 + 1)*sizeof(char));
|
|
if (file_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view file name");
|
|
return NULL;
|
|
}
|
|
if (sprintf(file_name, "%s.obiview_unfinished", view_name) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nProblem building an unfinished obiview file name");
|
|
return NULL;
|
|
}
|
|
|
|
return file_name;
|
|
}
|
|
|
|
|
|
static int view_is_finished(OBIDMS_p dms, const char* view_name)
|
|
{
|
|
struct dirent* dp;
|
|
char* file_name;
|
|
|
|
// Check finished views
|
|
// Create file name
|
|
file_name = build_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, file_name) == 0)
|
|
{
|
|
free(file_name);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Check unfinished views
|
|
// Create file name
|
|
file_name = build_unfinished_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, file_name) == 0)
|
|
{
|
|
free(file_name);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static size_t get_platform_view_file_size()
|
|
{
|
|
size_t obiview_size;
|
|
size_t rounded_obiview_size;
|
|
double multiple;
|
|
|
|
obiview_size = sizeof(Obiview_infos_t);
|
|
|
|
multiple = ceil((double) (obiview_size) / (double) getpagesize());
|
|
|
|
rounded_obiview_size = multiple * getpagesize();
|
|
|
|
return rounded_obiview_size;
|
|
}
|
|
|
|
|
|
static int enlarge_view_file(Obiview_p view, size_t new_size)
|
|
{
|
|
int obiview_file_descriptor;
|
|
double multiple;
|
|
size_t rounded_new_size;
|
|
char* file_name;
|
|
|
|
// Create file name
|
|
file_name = build_unfinished_obiview_file_name((view->infos)->name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
// Open view file
|
|
obiview_file_descriptor = openat((view->dms)->view_dir_fd, file_name, O_RDWR, 0777);
|
|
if (obiview_file_descriptor < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError opening a view file");
|
|
free(file_name);
|
|
return -1;
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Round new size to a multiple of page size // TODO make function in utils
|
|
multiple = ceil((double) new_size / (double) getpagesize());
|
|
rounded_new_size = multiple * getpagesize();
|
|
|
|
// Unmap the entire file before truncating it (WSL requirement)
|
|
if (munmap(view->infos, (view->infos)->file_size) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError munmapping a view file when enlarging");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
// Enlarge the file
|
|
if (ftruncate(obiview_file_descriptor, rounded_new_size) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError enlarging a view file");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
// Remap the file
|
|
view->infos = mmap(NULL,
|
|
rounded_new_size,
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_SHARED,
|
|
obiview_file_descriptor,
|
|
0
|
|
);
|
|
if (view->infos == MAP_FAILED)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError re-mmapping a view file after enlarging the file");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
// Set new size
|
|
(view->infos)->file_size = rounded_new_size;
|
|
|
|
if (close(obiview_file_descriptor) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError closing a view file");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int create_obiview_file(OBIDMS_p dms, const char* view_name)
|
|
{
|
|
char* file_name;
|
|
int obiview_file_descriptor;
|
|
size_t file_size;
|
|
|
|
// Create file name
|
|
file_name = build_unfinished_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
// Create file
|
|
obiview_file_descriptor = openat(dms->view_dir_fd, file_name, O_RDWR | O_CREAT | O_EXCL, 0777);
|
|
if (obiview_file_descriptor < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError creating an obiview file");
|
|
free(file_name);
|
|
return -1;
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Truncate file to the initial size
|
|
file_size = get_platform_view_file_size();
|
|
|
|
if (ftruncate(obiview_file_descriptor, file_size) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError truncating an obiview file to the right size");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
// Write file size
|
|
if (write(obiview_file_descriptor, &file_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t)))
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError writing the file size in an obiview file");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
if (close(obiview_file_descriptor) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError closing a view file");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int update_column_refs(Obiview_p view)
|
|
{
|
|
int i;
|
|
OBIDMS_column_p column;
|
|
|
|
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");
|
|
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)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError creating a column dictionary");
|
|
return -1;
|
|
}
|
|
|
|
// Rebuild the dictionary from the column references and the column pointer array associated with the view
|
|
for (i=0; i < (view->infos)->column_count; i++)
|
|
{
|
|
// Check that each alias is unique
|
|
if (ht_get(view->column_dict, (((view->infos)->column_references)[i]).alias) != NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError: the name/alias identifying a column in a view is not unique: %s", (((view->infos)->column_references)[i]).alias);
|
|
return -1;
|
|
}
|
|
|
|
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");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int update_column_dict(Obiview_p view)
|
|
{
|
|
// Re-initialize the dictionary to rebuild it from scratch
|
|
ht_free(view->column_dict);
|
|
|
|
if (create_column_dict(view) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int update_column_refs_and_dict(Obiview_p 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;
|
|
OBIDMS_column_p column;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to update the line count of all columns in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
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 (!(column->writable))
|
|
{
|
|
column = clone_column_in_view(view, (((view->infos)->column_references)[i]).alias, true);
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "\nError cloning a column in a view when updating its line count");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Enlarge the column if needed
|
|
while (line_count > (column->header)->line_count)
|
|
{
|
|
if (obi_enlarge_column(column) < 0)
|
|
return -1;
|
|
}
|
|
|
|
// Set the number of lines used to the new view line count
|
|
(column->header)->lines_used = line_count;
|
|
}
|
|
|
|
(view->infos)->line_count = line_count;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name, bool clone_associated)
|
|
{
|
|
int i, j;
|
|
OBIDMS_column_p column = NULL;
|
|
OBIDMS_column_p new_column = NULL;
|
|
OBIDMS_column_p column_buffer;
|
|
OBIDMS_column_p associated_cloned_column = NULL;
|
|
char* associated_column_alias = NULL;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to delete a column in a read-only view");
|
|
return NULL;
|
|
}
|
|
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
if ((view->line_selection != NULL) || (!strcmp((((view->infos)->column_references)[i]).alias, column_name)))
|
|
{ // 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 = *((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
|
|
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;
|
|
}
|
|
|
|
// Look for associated column to clone and reassociate
|
|
if ((column_buffer->header->associated_column).column_name[0] != '\0')
|
|
{
|
|
// Get the associated column alias
|
|
j=0;
|
|
while (((strcmp((((view->infos)->column_references)[j]).column_refs.column_name, (column_buffer->header->associated_column).column_name)) ||
|
|
((((view->infos)->column_references)[j]).column_refs.version != (column_buffer->header->associated_column).version)) &&
|
|
j<(view->infos)->column_count) // TODO function for that
|
|
j++;
|
|
|
|
if (j == (view->infos)->column_count) // not found
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nCould not find associated column when cloning a column for editing");
|
|
return NULL;
|
|
}
|
|
|
|
// No line selection: only this column is cloned, clone and reassociate the associated column
|
|
if ((view->line_selection == NULL) && clone_associated)
|
|
{
|
|
associated_column_alias = (((view->infos)->column_references)[j]).alias;
|
|
// Clone the associated column
|
|
associated_cloned_column = clone_column_in_view(view, associated_column_alias, false);
|
|
// Reassociate both ways
|
|
strcpy((associated_cloned_column->header->associated_column).column_name, column->header->name);
|
|
(associated_cloned_column->header->associated_column).version = column->header->version;
|
|
strcpy((column->header->associated_column).column_name, associated_cloned_column->header->name);
|
|
(column->header->associated_column).version = associated_cloned_column->header->version;
|
|
}
|
|
else
|
|
{
|
|
// Line selection: all columns are cloned, check if associated column has been cloned previously (it precedes this one in the list) to reassociate
|
|
if (j < i)
|
|
{
|
|
// Get pointer to associated column
|
|
associated_cloned_column = *((OBIDMS_column_p*)ll_get(view->columns, j));
|
|
if (associated_cloned_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;
|
|
}
|
|
// Reassociate both ways
|
|
strcpy((associated_cloned_column->header->associated_column).column_name, column->header->name);
|
|
(associated_cloned_column->header->associated_column).version = column->header->version;
|
|
strcpy((column->header->associated_column).column_name, associated_cloned_column->header->name);
|
|
(column->header->associated_column).version = associated_cloned_column->header->version;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close old cloned column
|
|
obi_close_column(column_buffer);
|
|
|
|
if (!strcmp((((view->infos)->column_references)[i]).alias, column_name))
|
|
// Get the column to return
|
|
new_column = column;
|
|
}
|
|
}
|
|
|
|
// Close old line selection
|
|
if (view->line_selection != NULL)
|
|
{
|
|
obi_close_column(view->line_selection);
|
|
view->line_selection = NULL;
|
|
// Update line selection reference
|
|
(((view->infos)->line_selection).column_name)[0] = '\0';
|
|
((view->infos)->line_selection).version = -1;
|
|
}
|
|
|
|
// Update column refs and dict
|
|
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 new_column;
|
|
}
|
|
|
|
|
|
static int save_view(Obiview_p view)
|
|
{
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to save a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// Store reference for the line selection associated with that view if there is one
|
|
if (view->line_selection != NULL) // Unnecessary in theory, the line selection references are already saved
|
|
{
|
|
strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name);
|
|
((view->infos)->line_selection).version = ((view->line_selection)->header)->version;
|
|
(view->infos)->all_lines = false;
|
|
}
|
|
else // Necessary because line selection could have been deleted if a column was cloned
|
|
{
|
|
(((view->infos)->line_selection).column_name)[0] = '\0';
|
|
((view->infos)->line_selection).version = -1;
|
|
(view->infos)->all_lines = true;
|
|
}
|
|
|
|
if (update_column_refs(view) < 0)
|
|
{
|
|
obidebug(1, "\nError updating column references when saving a view");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int rename_finished_view(Obiview_p view)
|
|
{
|
|
char* old_name;
|
|
char* new_name;
|
|
char* path_old_name;
|
|
char* path_new_name;
|
|
char* full_path_old_name;
|
|
char* full_path_new_name;
|
|
|
|
old_name = build_unfinished_obiview_file_name((view->infos)->name);
|
|
new_name = build_obiview_file_name((view->infos)->name);
|
|
|
|
path_old_name = malloc(MAX_PATH_LEN);
|
|
path_new_name = malloc(MAX_PATH_LEN);
|
|
|
|
strcpy(path_old_name, "VIEWS/");
|
|
strcat(path_old_name, old_name);
|
|
|
|
strcpy(path_new_name, "VIEWS/");
|
|
strcat(path_new_name, new_name);
|
|
|
|
full_path_old_name = obi_dms_get_full_path(view->dms, path_old_name);
|
|
full_path_new_name = obi_dms_get_full_path(view->dms, path_new_name);
|
|
|
|
if (rename(full_path_old_name, full_path_new_name) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError renaming the file of a finished view: %s", full_path_new_name);
|
|
free(old_name);
|
|
free(new_name);
|
|
return -1;
|
|
}
|
|
|
|
free(old_name);
|
|
free(new_name);
|
|
free(path_new_name);
|
|
free(path_old_name);
|
|
free(full_path_old_name);
|
|
free(full_path_new_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int finish_view(Obiview_p view)
|
|
{
|
|
int i;
|
|
OBIDMS_column_p column;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to save a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// Add count column if it's a NUC_SEQ_VIEW with no count column (and there's no MERGED_sample column) // TODO discuss
|
|
if ((!strcmp((view->infos)->view_type, VIEW_TYPE_NUC_SEQS)) && (!obi_view_column_exists(view, COUNT_COLUMN))
|
|
&& (!obi_view_column_exists(view, "MERGED_sample"))) // TODO should eventually compute from merged samples?
|
|
{
|
|
if (obi_create_auto_count_column(view) < 0)
|
|
{
|
|
obidebug(1, "\nError creating an automatic count column when finishing a view");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Add id column if it's a NUC_SEQ_VIEW with no id column // TODO discuss
|
|
if ((!strcmp((view->infos)->view_type, VIEW_TYPE_NUC_SEQS)) && (!obi_view_column_exists(view, ID_COLUMN)))
|
|
{
|
|
if (obi_create_auto_id_column(view, NULL) < 0)
|
|
{
|
|
obidebug(1, "\nError creating an automatic id column when finishing a view");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Check predicates
|
|
if (view_check_all_predicates(view, true) < 0)
|
|
{
|
|
obidebug(1, "\nView predicates not respected, view rollbacked");
|
|
obi_rollback_view(view); // TODO discuss, maybe never call from C layer
|
|
return -1;
|
|
}
|
|
|
|
if (save_view(view) < 0)
|
|
return -1;
|
|
|
|
// Add the time in the view comments
|
|
time_t t;
|
|
t = time(&t);
|
|
if (obi_view_add_comment(view, "Date created", strtok(ctime(&t), "\n")) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError adding the date of creation when finishing a view");
|
|
return -1;
|
|
}
|
|
|
|
if (rename_finished_view(view) < 0)
|
|
return -1;
|
|
|
|
// Flag the columns as finished
|
|
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 flag it as finished when finishing a view");
|
|
return -1;
|
|
}
|
|
if (column->writable)
|
|
(column->header)->finished = true;
|
|
}
|
|
|
|
// Flag the line selection column as finished
|
|
if (view->line_selection != NULL)
|
|
{
|
|
column = view->line_selection;
|
|
if (column->writable)
|
|
(column->header)->finished = true;
|
|
}
|
|
|
|
// Flag the view as finished
|
|
(view->infos)->finished = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
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++)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Close line selection if there is one
|
|
if (view->line_selection != NULL)
|
|
{
|
|
if (obi_close_column(view->line_selection) < 0)
|
|
{
|
|
obidebug(1, "\nError closing a line selection while closing a view");
|
|
ret_value = -1;
|
|
}
|
|
}
|
|
|
|
// Free the linked list of column pointers
|
|
ll_free(view->columns);
|
|
|
|
// Free the column dictionary
|
|
ht_free(view->column_dict);
|
|
|
|
// Unmap view file
|
|
if (obi_view_unmap_file(view->dms, view->infos) < 0)
|
|
{
|
|
obidebug(1, "\nError unmaping a view file while closing a view");
|
|
ret_value = -1;
|
|
}
|
|
|
|
free(view);
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
static int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, index_t* line_nb_p)
|
|
{
|
|
int i;
|
|
char* column_name = NULL;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obidebug(1, "\nError trying to set a value in a column in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// If there is a line selection associated with the view or if the column
|
|
// is read-only, all columns or this column respectively must be cloned
|
|
if ((view->line_selection != NULL) || (!((*column_pp)->writable)))
|
|
{
|
|
// Get the name/alias of the column from the pointer
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
if (obi_view_get_column(view, (((view->infos)->column_references)[i]).alias) == *column_pp)
|
|
column_name = (((view->infos)->column_references)[i]).alias;
|
|
}
|
|
if (column_name == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to clone a column in a view: column alias not found from pointer");
|
|
return -1;
|
|
}
|
|
|
|
(*column_pp) = clone_column_in_view(view, column_name, true);
|
|
if ((*column_pp) == NULL)
|
|
{
|
|
obidebug(1, "\nError trying to clone a column to modify it");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (((*line_nb_p)+1) > (view->infos)->line_count)
|
|
{
|
|
if (update_lines(view, ((*line_nb_p)+1)) < 0)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p)
|
|
{
|
|
if (((*line_nb_p)+1) > ((view->infos)->line_count))
|
|
{
|
|
obi_set_errno(OBICOL_UNKNOWN_ERROR);
|
|
obidebug(1, "\nError trying to get a value that is beyond the current line count of the view");
|
|
return -1;
|
|
}
|
|
|
|
if (view->line_selection != NULL)
|
|
(*line_nb_p) = *(((index_t*) ((view->line_selection)->data)) + (*line_nb_p));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/****** PREDICATE FUNCTIONS *******/
|
|
|
|
static char* view_has_nuc_sequence_column(Obiview_p view)
|
|
{
|
|
char* predicate;
|
|
|
|
predicate = (char*) malloc((strlen("The view has an associated nucleotide sequence column.") + 1) * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(predicate, "The view has an associated nucleotide sequence column.");
|
|
|
|
if (obi_view_get_column(view, NUC_SEQUENCE_COLUMN) != NULL)
|
|
return predicate;
|
|
else
|
|
{
|
|
obidebug(1, "\nError checking the predicate: %s", predicate);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static char* view_has_quality_column(Obiview_p view)
|
|
{
|
|
char* predicate;
|
|
|
|
predicate = (char*) malloc((strlen("The view has an associated sequence quality column.") + 1) * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(predicate, "The view has an associated sequence quality column.");
|
|
|
|
if (obi_view_get_column(view, QUALITY_COLUMN) != NULL)
|
|
return predicate;
|
|
else
|
|
{
|
|
obidebug(1, "\nError checking the predicate: %s", predicate);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static char* view_has_id_column(Obiview_p view)
|
|
{
|
|
char* predicate;
|
|
|
|
predicate = (char*) malloc((strlen("The view has an associated identifier column.") + 1) * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(predicate, "The view has an associated identifier column.");
|
|
|
|
if (obi_view_get_column(view, ID_COLUMN) != NULL)
|
|
return predicate;
|
|
else
|
|
{
|
|
obidebug(1, "\nError checking the predicate: %s", predicate);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static char* view_has_definition_column(Obiview_p view)
|
|
{
|
|
char* predicate;
|
|
|
|
predicate = (char*) malloc((strlen("The view has an associated definition column.") + 1) * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(predicate, "The view has an associated definition column.");
|
|
|
|
if (obi_view_get_column(view, DEFINITION_COLUMN) != NULL)
|
|
return predicate;
|
|
else
|
|
{
|
|
obidebug(1, "\nError checking the predicate: %s", predicate);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static char* view_check_qual_match_seqs(Obiview_p view)
|
|
{
|
|
index_t i, j, k;
|
|
index_t nb_elements_per_line;
|
|
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;
|
|
bool at_least_one_qual_col;
|
|
|
|
// Go through all columns in the view and check the predicate for all quality columns
|
|
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 view %s", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
|
|
// Check if it's a quality column
|
|
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 = 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)
|
|
{
|
|
obidebug(1, "\nError checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
|
|
// Close and reopen indexers to remap them properly, because in writable mode they are mostly unmapped
|
|
if (obi_close_indexer(qual_column->indexer) < 0)
|
|
{
|
|
obidebug(1, "\nError closing the quality indexer when checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
qual_column->indexer = obi_open_avl_group(view->dms, (qual_column->header)->indexer_name);
|
|
if (qual_column->indexer == NULL)
|
|
{
|
|
obidebug(1, "\nError reopening the quality indexer when checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
if (obi_close_indexer(seq_column->indexer) < 0)
|
|
{
|
|
obidebug(1, "\nError closing the sequence indexer when checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
seq_column->indexer = obi_open_avl_group(view->dms, (seq_column->header)->indexer_name);
|
|
if (seq_column->indexer == NULL)
|
|
{
|
|
obidebug(1, "\nError reopening the sequence indexer when checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
|
|
nb_elements_per_line = (qual_column->header)->nb_elements_per_line;
|
|
// Check that the quality and the sequence columns have the same number of elements per line
|
|
if (nb_elements_per_line != (seq_column->header)->nb_elements_per_line)
|
|
{
|
|
obidebug(1, "\nError checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
|
|
// Check each sequence and its quality
|
|
for (j=0; j < (view->infos)->line_count; j++)
|
|
{
|
|
for (k=0; k < nb_elements_per_line; k++)
|
|
{
|
|
qual = obi_get_qual_int_with_elt_idx_and_col_p_in_view(view, qual_column, j, k, &qual_len);
|
|
seq = obi_get_seq_with_elt_idx_and_col_p_in_view(view, seq_column, j, k);
|
|
if ((qual != OBIQual_int_NA) && (seq != OBISeq_NA))
|
|
{
|
|
// Test that the lengths of the quality and the sequence are equal
|
|
if ((size_t)qual_len != strlen(seq))
|
|
{
|
|
obidebug(1, "\nError checking the predicate for view %s: The sequences and sequence quality arrays match (index %lld, seq=%s, quality length = %d).", (view->infos)->name, j, seq, qual_len);
|
|
return NULL;
|
|
}
|
|
}
|
|
// Test if one value is NA and not the other
|
|
else if (((qual == OBIQual_int_NA) && (seq != OBISeq_NA)) || ((qual != OBIQual_int_NA) && (seq == OBISeq_NA)))
|
|
{
|
|
obidebug(1, "\nError checking the predicate for view %s: The sequences and sequence quality arrays match.", (view->infos)->name);
|
|
return NULL;
|
|
}
|
|
free(seq);
|
|
}
|
|
}
|
|
|
|
obi_close_column(seq_column);
|
|
}
|
|
}
|
|
|
|
if (at_least_one_qual_col)
|
|
{
|
|
predicate = (char*) malloc((strlen("The sequences and sequence quality arrays match.") + 1) * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
strcpy(predicate, "The sequences and sequence quality arrays match.");
|
|
}
|
|
else
|
|
{
|
|
predicate = (char*) malloc(1 * sizeof(char));
|
|
if (predicate == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for predicate character string.");
|
|
return NULL;
|
|
}
|
|
strcpy(predicate, "");
|
|
}
|
|
|
|
return predicate;
|
|
}
|
|
|
|
|
|
static char* view_check_one_predicate(Obiview_p view, char* (*predicate_function)(Obiview_p view))
|
|
{
|
|
return predicate_function(view);
|
|
}
|
|
|
|
|
|
static int view_check_all_predicates(Obiview_p view, bool write)
|
|
{
|
|
int i;
|
|
char* predicate = NULL;
|
|
|
|
for (i=0; i < view->nb_predicates; i++)
|
|
{
|
|
// Check predicate
|
|
predicate = view_check_one_predicate(view, (view->predicate_functions)[i]);
|
|
if (predicate == NULL)
|
|
{
|
|
// TODO discuss what to do
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
if ((write) && (predicate[0]!='\0'))
|
|
{
|
|
// Add predicate in comments
|
|
if (obi_view_add_comment(view, PREDICATE_KEY, predicate) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError adding a verified predicate (%s) in the comments of a view.", predicate);
|
|
free(predicate);
|
|
return -1;
|
|
}
|
|
}
|
|
free(predicate);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// TODO predicate function that goes through each line / each elements
|
|
|
|
|
|
/**********************************************************************
|
|
*
|
|
* D E F I N I T I O N O F T H E P U B L I C F U N C T I O N S
|
|
*
|
|
**********************************************************************/
|
|
|
|
|
|
bool obi_view_exists(OBIDMS_p dms, const char* view_name)
|
|
{
|
|
struct dirent* dp;
|
|
char* file_name;
|
|
|
|
// Check finished views
|
|
// Create file name
|
|
file_name = build_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, file_name) == 0)
|
|
{
|
|
free(file_name);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Check unfinished views
|
|
// Create file name
|
|
file_name = build_unfinished_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, file_name) == 0)
|
|
{
|
|
free(file_name);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments)
|
|
{
|
|
Obiview_p view;
|
|
int i;
|
|
index_t line_nb;
|
|
OBIDMS_column_p column;
|
|
int comments_ok;
|
|
|
|
// Check that the DMS is a valid pointer
|
|
if (dms == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError creating a view: DMS pointer is NULL");
|
|
return NULL;
|
|
}
|
|
|
|
// Check that the view name pointer is valid
|
|
if (view_name == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError creating a view: view name is NULL");
|
|
return NULL;
|
|
}
|
|
|
|
// Check uniqueness of name
|
|
if (obi_view_exists(dms, view_name))
|
|
{
|
|
obi_set_errno(OBIVIEW_ALREADY_EXISTS_ERROR);
|
|
obidebug(1, "\nName of new view ('%s') already exists", view_name);
|
|
return NULL;
|
|
}
|
|
|
|
// Check that the view name is not 'taxonomy' (used for URIs)
|
|
if (strcmp(view_name, "taxonomy") == 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nView name can not be 'taxonomy'");
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate memory for view structure
|
|
view = (Obiview_p) malloc(sizeof(Obiview_t));
|
|
if (view == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view");
|
|
return NULL;
|
|
}
|
|
|
|
view->dms = dms;
|
|
view->read_only = false;
|
|
|
|
// Create view file
|
|
if (create_obiview_file(dms, view_name) < 0)
|
|
{
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Map view file
|
|
view->infos = obi_view_map_file(dms, view_name, false);
|
|
if (view->infos == NULL)
|
|
{
|
|
obidebug(1, "\nError mapping the informations of a new view");
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Flag the view as being a work in progress
|
|
(view->infos)->finished = false;
|
|
|
|
// Write used size in view file for initial structure
|
|
(view->infos)->used_size = sizeof(Obiview_infos_t);
|
|
|
|
// Clone view to clone if there is one
|
|
if (view_to_clone != NULL)
|
|
{
|
|
if ((view_to_clone->infos)->finished == false)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nA view can not be cloned if it is not finished");
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
// If the view to clone has an associated line selection and there is no new line selection, open the associated line selection
|
|
if ((view_to_clone->line_selection != NULL) && (line_selection == NULL))
|
|
{
|
|
view->line_selection = obi_open_column(dms, ((view_to_clone->line_selection)->header)->name, ((view_to_clone->line_selection)->header)->version);
|
|
if (view->line_selection == NULL)
|
|
{
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
(view->infos)->line_count = (view_to_clone->infos)->line_count;
|
|
}
|
|
// If there is a new line selection, build it by combining it with the one from the view to clone if there is one
|
|
else if (line_selection != NULL)
|
|
{
|
|
view->line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, NULL);
|
|
if ((view->line_selection) == NULL)
|
|
{
|
|
obidebug(1, "\nError creating a column corresponding to a line selection");
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
(view->infos)->all_lines = false;
|
|
(view->infos)->line_count = 0;
|
|
i = 0;
|
|
for (i=0; line_selection[i] != -1; i++)
|
|
{
|
|
line_nb = line_selection[i];
|
|
|
|
if (line_nb > (view_to_clone->infos)->line_count)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to select a line for a new view that is beyond the line count of the view to clone");
|
|
obi_close_column(view->line_selection);
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
if (view_to_clone->line_selection != NULL)
|
|
line_nb = obi_column_get_index_with_elt_idx(view_to_clone->line_selection, line_nb, 0);
|
|
|
|
if (obi_column_set_index_with_elt_idx(view->line_selection, ((view->line_selection)->header)->lines_used, 0, line_nb) < 0)
|
|
{
|
|
obi_close_column(view->line_selection);
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Update view line count
|
|
((view->infos)->line_count)++;
|
|
}
|
|
}
|
|
else // If there is no line selection associated with the view to clone or the new view
|
|
{
|
|
view->line_selection = NULL;
|
|
(view->infos)->all_lines = true;
|
|
(view->infos)->line_count = (view_to_clone->infos)->line_count;
|
|
}
|
|
|
|
// Fill informations
|
|
strcpy((view->infos)->view_type, (view_to_clone->infos)->view_type);
|
|
strcpy((view->infos)->created_from, (view_to_clone->infos)->name);
|
|
}
|
|
|
|
// Else, fill empty view structure
|
|
else
|
|
{
|
|
(view->infos)->column_count = 0;
|
|
(view->infos)->line_count = 0;
|
|
(view->infos)->all_lines = true;
|
|
((view->infos)->created_from)[0] = '\0';
|
|
((view->infos)->view_type)[0] = '\0';
|
|
view->line_selection = NULL;
|
|
view->columns = NULL;
|
|
}
|
|
|
|
// Fill last informations
|
|
strcpy((view->infos)->name, view_name);
|
|
(view->infos)->creation_date = time(NULL);
|
|
|
|
// Fill automatic predicate functions
|
|
view->nb_predicates = 1;
|
|
view->predicate_functions = malloc((view->nb_predicates) * sizeof(char* (*) (Obiview_p)));
|
|
if (view->predicate_functions == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for view predicates");
|
|
return NULL;
|
|
}
|
|
(view->predicate_functions)[0] = view_check_qual_match_seqs;
|
|
|
|
// Write comments
|
|
// Comments must be a json string, even empty
|
|
if ((strcmp(comments, "") == 0) || (comments == NULL))
|
|
comments_ok = obi_view_write_comments(view, "{}");
|
|
else
|
|
comments_ok = obi_view_write_comments(view, comments);
|
|
if (comments_ok < 0)
|
|
{
|
|
obidebug(1, "\nError writing comments when creating a view");
|
|
close_view(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Add the comment specifying the name of the cloned view if there is one
|
|
if (view_to_clone != NULL)
|
|
{
|
|
if (obi_view_add_comment(view, "Cloned from", (view_to_clone->infos)->name) < 0)
|
|
{
|
|
obidebug(1, "\nError adding comment about cloned view when creating a view");
|
|
close_view(view);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Store reference for line selection
|
|
if (view->line_selection == NULL)
|
|
{
|
|
(((view->infos)->line_selection).column_name)[0] = '\0';
|
|
((view->infos)->line_selection).version = -1;
|
|
}
|
|
else
|
|
{
|
|
strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name);
|
|
((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)
|
|
{
|
|
close_view(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Once the view has been created with all its elements and informations, add the columns if the view is cloned from another view
|
|
if (view_to_clone != NULL)
|
|
{
|
|
(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,
|
|
(column->header)->name,
|
|
(column->header)->version,
|
|
(((view_to_clone->infos)->column_references)[i]).alias,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
NULL,
|
|
NULL,
|
|
-1,
|
|
NULL,
|
|
false)
|
|
< 0)
|
|
{
|
|
obidebug(1, "\nError adding a column in a new view from a view to clone");
|
|
if (view->line_selection != NULL)
|
|
obi_close_column(view->line_selection);
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection, const char* comments)
|
|
{
|
|
Obiview_p view;
|
|
Obiview_p view_to_clone;
|
|
|
|
view_to_clone = obi_open_view(dms, view_to_clone_name);
|
|
if (view_to_clone == NULL)
|
|
return NULL;
|
|
view = obi_new_view(dms, view_name, view_to_clone, line_selection, comments);
|
|
|
|
close_view(view_to_clone);
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments, bool quality_column, bool create_default_columns)
|
|
{
|
|
Obiview_p view;
|
|
OBIDMS_column_p associated_nuc_column;
|
|
OBIDMS_column_p associated_qual_column;
|
|
int nb_predicates;
|
|
|
|
if (view_to_clone != NULL)
|
|
{ // Check that the view to clone is already a NUC_SEQS view
|
|
if (strcmp((view_to_clone->infos)->view_type, VIEW_TYPE_NUC_SEQS))
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "Trying to clone a non-NUC SEQS view to create a NUC SEQS view");
|
|
return NULL;
|
|
}
|
|
// Check if there is a quality column
|
|
if (obi_view_get_column(view_to_clone, QUALITY_COLUMN) != NULL)
|
|
quality_column = true;
|
|
else
|
|
quality_column = false;
|
|
}
|
|
|
|
view = obi_new_view(dms, view_name, view_to_clone, line_selection, comments);
|
|
if (view == NULL)
|
|
return NULL;
|
|
|
|
strcpy((view->infos)->view_type, VIEW_TYPE_NUC_SEQS);
|
|
|
|
if ((view_to_clone == NULL) && create_default_columns)
|
|
{
|
|
// Adding sequence column
|
|
if (obi_view_add_column(view, NUC_SEQUENCE_COLUMN, -1, NULL, OBI_SEQ, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, "{}", true) < 0) // discuss using same indexer "NUC_SEQ_INDEXER"
|
|
{
|
|
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
|
|
return NULL;
|
|
}
|
|
// Adding id column
|
|
if (obi_view_add_column(view, ID_COLUMN, -1, NULL, OBI_STR, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, "{}", true) < 0)
|
|
{
|
|
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
|
|
return NULL;
|
|
}
|
|
// Adding definition column
|
|
if (obi_view_add_column(view, DEFINITION_COLUMN, -1, NULL, OBI_STR, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, "{}", true) < 0)
|
|
{
|
|
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
|
|
return NULL;
|
|
}
|
|
// Adding quality column
|
|
if (quality_column)
|
|
{
|
|
associated_nuc_column = obi_view_get_column(view, NUC_SEQUENCE_COLUMN);
|
|
if (obi_view_add_column(view, QUALITY_COLUMN, -1, NULL, OBI_QUAL, 0, 1, NULL, false, false, false, false, NULL, (associated_nuc_column->header)->name, (associated_nuc_column->header)->version, "{}", true) < 0) // TODO discuss automatic association
|
|
{
|
|
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
|
|
return NULL;
|
|
}
|
|
// Associating both ways: associating nuc sequences column to quality column
|
|
associated_qual_column = obi_view_get_column(view, QUALITY_COLUMN);
|
|
strcpy((associated_nuc_column->header->associated_column).column_name, associated_qual_column->header->name);
|
|
(associated_nuc_column->header->associated_column).version = associated_qual_column->header->version;
|
|
}
|
|
}
|
|
|
|
// Add predicate functions specific to the view type
|
|
// TODO macros?
|
|
|
|
// if (quality_column) TODO
|
|
// nb_predicates = view->nb_predicates + 4;
|
|
// else
|
|
nb_predicates = view->nb_predicates + 3;
|
|
|
|
if (view->nb_predicates == 0)
|
|
view->predicate_functions = malloc(nb_predicates * sizeof(char* (*) (Obiview_p)));
|
|
else
|
|
view->predicate_functions = realloc(view->predicate_functions, nb_predicates * sizeof(char* (*) (Obiview_p)));
|
|
|
|
if (view->predicate_functions == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for view predicates");
|
|
return NULL;
|
|
}
|
|
|
|
(view->predicate_functions)[(view->nb_predicates)] = view_has_nuc_sequence_column;
|
|
(view->predicate_functions)[(view->nb_predicates) + 1] = view_has_id_column;
|
|
(view->predicate_functions)[(view->nb_predicates) + 2] = view_has_definition_column;
|
|
// if (quality_column) # TODO fix by triggering predicate deleting if quality deleting. Commented bc for example with obi annotate, clone view so clone predicate, then modify seq, so quality is deleted, and predicate boom
|
|
// (view->predicate_functions)[(view->nb_predicates) + 3] = view_has_quality_column;
|
|
|
|
view->nb_predicates = nb_predicates;
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection, const char* comments)
|
|
{
|
|
Obiview_p view;
|
|
Obiview_p view_to_clone;
|
|
|
|
view_to_clone = obi_open_view(dms, view_to_clone_name);
|
|
if (view_to_clone == NULL)
|
|
return NULL;
|
|
view = obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false, false);
|
|
|
|
close_view(view_to_clone);
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
Obiview_p obi_clone_view(OBIDMS_p dms, Obiview_p view_to_clone, const char* view_name, index_t* line_selection, const char* comments)
|
|
{
|
|
if (view_to_clone == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError: pointer on view to clone is NULL");
|
|
return NULL;
|
|
}
|
|
|
|
if (strcmp((view_to_clone->infos)->view_type, VIEW_TYPE_NUC_SEQS) == 0)
|
|
return obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false, false);
|
|
else // Non-typed view
|
|
return obi_new_view(dms, view_name, view_to_clone, line_selection, comments);
|
|
}
|
|
|
|
|
|
Obiview_p obi_clone_view_from_name(OBIDMS_p dms, const char* view_to_clone_name, const char* view_name, index_t* line_selection, const char* comments)
|
|
{
|
|
Obiview_p view;
|
|
Obiview_p view_to_clone;
|
|
|
|
view_to_clone = obi_open_view(dms, view_to_clone_name);
|
|
if (view_to_clone == NULL)
|
|
{
|
|
obidebug(1, "\nError: could not open view to clone");
|
|
return NULL;
|
|
}
|
|
|
|
view = obi_clone_view(dms, view_to_clone, view_name, line_selection, comments);
|
|
|
|
close_view(view_to_clone);
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name, bool finished)
|
|
{
|
|
char* file_name;
|
|
Obiview_infos_p view_infos;
|
|
int obiview_file_descriptor;
|
|
size_t file_size;
|
|
int open_flag;
|
|
int mmap_flag;
|
|
|
|
// Create file name
|
|
if (finished)
|
|
file_name = build_obiview_file_name(view_name);
|
|
else
|
|
file_name = build_unfinished_obiview_file_name(view_name);
|
|
if (file_name == NULL)
|
|
return NULL;
|
|
|
|
// Set flags (read-only or not)
|
|
if (finished)
|
|
{
|
|
open_flag = O_RDONLY;
|
|
mmap_flag = PROT_READ;
|
|
}
|
|
else
|
|
{
|
|
open_flag = O_RDWR;
|
|
mmap_flag = PROT_READ | PROT_WRITE;
|
|
}
|
|
|
|
// Open view file
|
|
obiview_file_descriptor = openat(dms->view_dir_fd, file_name, open_flag, 0777);
|
|
if (obiview_file_descriptor < 0)
|
|
{
|
|
if (errno == ENOENT)
|
|
{
|
|
obidebug(1, "\nError opening an obiview file: View %s does not exist", view_name);
|
|
}
|
|
else
|
|
{
|
|
obidebug(1, "\nError opening an obiview file");
|
|
}
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
free(file_name);
|
|
return NULL;
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Get file size
|
|
if (read(obiview_file_descriptor, &file_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t)))
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError reading the file size in an obiview file");
|
|
close(obiview_file_descriptor);
|
|
return NULL;
|
|
}
|
|
|
|
// Map the view infos structure
|
|
view_infos = mmap(NULL,
|
|
file_size,
|
|
mmap_flag,
|
|
MAP_SHARED,
|
|
obiview_file_descriptor,
|
|
0
|
|
);
|
|
if (view_infos == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError mapping an obiview file");
|
|
return NULL;
|
|
}
|
|
|
|
if (close(obiview_file_descriptor) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError closing a view file");
|
|
return NULL;
|
|
}
|
|
|
|
return view_infos;
|
|
}
|
|
|
|
|
|
int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos)
|
|
{
|
|
char* file_name;
|
|
int obiview_file_descriptor;
|
|
size_t file_size;
|
|
|
|
// Get file name
|
|
if (view_infos->finished)
|
|
file_name = build_obiview_file_name(view_infos->name);
|
|
else
|
|
file_name = build_unfinished_obiview_file_name(view_infos->name);
|
|
if (file_name == NULL)
|
|
return -1;
|
|
|
|
// Open view file
|
|
obiview_file_descriptor = openat(dms->view_dir_fd, file_name, O_RDONLY, 0777);
|
|
if (obiview_file_descriptor < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError opening an obiview file (%s) >%s<", file_name, dms->dms_name);
|
|
free(file_name);
|
|
return -1;
|
|
}
|
|
|
|
free(file_name);
|
|
|
|
// Unmap the view infos structure
|
|
file_size = view_infos->file_size;
|
|
if (munmap(view_infos, file_size) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError unmapping an obiview file");
|
|
close(obiview_file_descriptor);
|
|
return -1;
|
|
}
|
|
|
|
if (close(obiview_file_descriptor) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError closing a view file");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name)
|
|
{
|
|
Obiview_p view;
|
|
const char* column_name;
|
|
obiversion_t column_version;
|
|
OBIDMS_column_p column_pointer;
|
|
int i;
|
|
|
|
// Check that the DMS is a valid pointer
|
|
if (dms == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError opening a view: DMS pointer is NULL");
|
|
return NULL;
|
|
}
|
|
|
|
// Check that the view name pointer is valid
|
|
if (view_name == NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError opening a view: view name is NULL");
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate the memory for the view structure
|
|
view = (Obiview_p) malloc(sizeof(Obiview_t));
|
|
if (view == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view");
|
|
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)
|
|
{
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
|
|
// Open the line selection associated with the view
|
|
if ((view->infos)->all_lines)
|
|
view->line_selection = NULL;
|
|
else
|
|
{
|
|
view->line_selection = obi_open_column(dms, ((view->infos)->line_selection).column_name, ((view->infos)->line_selection).version);
|
|
if (view->line_selection == NULL)
|
|
{
|
|
obidebug(1, "\nError opening a line selection for a view");
|
|
obi_view_unmap_file(view->dms, view->infos);
|
|
free(view);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Open the columns to read
|
|
for (i=0; i < ((view->infos)->column_count); i++)
|
|
{
|
|
column_name = ((((view->infos)->column_references)[i]).column_refs).column_name;
|
|
column_version = ((((view->infos)->column_references)[i]).column_refs).version;
|
|
|
|
column_pointer = obi_open_column(dms, column_name, column_version);
|
|
if (column_pointer == NULL)
|
|
{
|
|
obidebug(1, "\nError opening a column for a view: column %d: %s, version %d", i, column_name, column_version);
|
|
close_view(view);
|
|
return NULL;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Create the column dictionary associating each column alias with its pointer
|
|
if (create_column_dict(view) < 0)
|
|
{
|
|
obidebug(1, "\nError creating the column dictionary when opening a view");
|
|
close_view(view);
|
|
return NULL;
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
// TODO return a pointer on the column?
|
|
int obi_view_add_column(Obiview_p view,
|
|
char* column_name,
|
|
obiversion_t version_number,
|
|
const char* alias,
|
|
OBIType_t data_type,
|
|
index_t nb_lines,
|
|
index_t nb_elements_per_line,
|
|
char* elements_names,
|
|
bool elt_names_formatted,
|
|
bool dict_column,
|
|
bool tuples,
|
|
bool to_eval,
|
|
const char* indexer_name,
|
|
const char* associated_column_name,
|
|
obiversion_t associated_column_version,
|
|
const char* comments,
|
|
bool create) // all infos for creation or open
|
|
{
|
|
int i;
|
|
OBIDMS_column_p column;
|
|
OBIDMS_column_p column_buffer;
|
|
|
|
//for ( ; *column_name; ++column_name) *column_name = tolower(*column_name);
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to add a column in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// If there is a line selection , clone the columns to delete the line selection
|
|
if (create && (view->line_selection != NULL))
|
|
{
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
{ // Clone with the right line selection and replace for all columns
|
|
// Save pointer to close column after cloning
|
|
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
|
|
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);
|
|
}
|
|
}
|
|
|
|
// Close old line selection
|
|
if (view->line_selection != NULL)
|
|
{
|
|
obi_close_column(view->line_selection);
|
|
view->line_selection = NULL;
|
|
// Update line selection reference
|
|
(((view->infos)->line_selection).column_name)[0] = '\0';
|
|
((view->infos)->line_selection).version = -1;
|
|
}
|
|
}
|
|
|
|
// Update the line count if needed
|
|
if (create)
|
|
{
|
|
if ((view->infos)->line_count > nb_lines)
|
|
nb_lines = (view->infos)->line_count;
|
|
else if (nb_lines > (view->infos)->line_count)
|
|
update_lines(view, nb_lines);
|
|
}
|
|
|
|
// Open or create the column
|
|
if (create)
|
|
{ // Create column
|
|
column = obi_create_column(view->dms, column_name, data_type, nb_lines, nb_elements_per_line, elements_names, elt_names_formatted, dict_column, tuples, to_eval, indexer_name, associated_column_name, associated_column_version, comments);
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "\nError creating a column to add to a view");
|
|
return -1;
|
|
}
|
|
(column->header)->lines_used = nb_lines;
|
|
}
|
|
else
|
|
{ // Open column
|
|
column = obi_open_column(view->dms, column_name, version_number);
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "\nError opening a column to add to a view: %s, version %d", column_name, version_number);
|
|
return -1;
|
|
}
|
|
// - If there is a line selection:
|
|
// - The column's lines_used attribute must be at least the view's line count
|
|
// - If there is no line selection:
|
|
// - If it's the first column in the view:
|
|
// - The view's line count is set to the column's lines_used attribute
|
|
// - If it's not the first column in the view:
|
|
// - The column's lines_used attribute must be equal to the view's line count
|
|
if ((view->line_selection != NULL) && ((column->header)->lines_used < (view->infos)->line_count))
|
|
{ // - If there is a line selection, the column's lines_used attribute must be at least the view's line count
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError adding an existing column to a view: the column's lines_used attribute (%lld) must be equal to or greater than the view's line count (%lld)", (column->header)->lines_used, (view->infos)->line_count);
|
|
return -1;
|
|
}
|
|
else if (view->line_selection == NULL)
|
|
{ // If there is no line selection:
|
|
if ((view->infos)->column_count == 0) // If it's the first column in the view:
|
|
(view->infos)->line_count = (column->header)->lines_used; // The view's line count is set to the column's lines_used attribute
|
|
else if ((column->header)->lines_used != (view->infos)->line_count)
|
|
{ // If it's not the first column in the view, the column's lines_used attribute must be equal to the view's line count
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError adding an existing column to a view: the column's lines_used attribute (%lld) must be equal to the view's line count (%lld)", (column->header)->lines_used, (view->infos)->line_count);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Store column pointer in the view structure
|
|
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.
|
|
if ((alias == NULL) || (*alias == '\0'))
|
|
alias = column_name;
|
|
|
|
// Save column alias
|
|
strcpy((((view->infos)->column_references)[(view->infos)->column_count]).alias, alias);
|
|
|
|
// Update column count in view
|
|
(view->infos)->column_count++;
|
|
|
|
// Update column references and dictionary
|
|
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++)
|
|
// {
|
|
// fprintf(stderr, "\n\n2305 alias: %s", (((view->infos)->column_references)[i]).alias);
|
|
// fprintf(stderr, "\npointer: %x\n", obi_view_get_column(view, (((view->infos)->column_references)[i]).alias));
|
|
// }
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_view_delete_column(Obiview_p view, const char* column_name, bool delete_file)
|
|
{
|
|
int i;
|
|
bool found;
|
|
OBIDMS_column_p column;
|
|
char* col_to_delete_path;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to delete a column in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
found = false;
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
if ((!found) && (!strcmp((((view->infos)->column_references)[i]).alias, column_name)))
|
|
{
|
|
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;
|
|
}
|
|
// Keep column path if need to delete the file
|
|
if (delete_file)
|
|
{
|
|
col_to_delete_path = obi_column_full_path(view->dms, column->header->name, column->header->version);
|
|
if (col_to_delete_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column file path when deleting a column");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
obi_close_column(column);
|
|
|
|
// Delete file if needed
|
|
if (delete_file)
|
|
{
|
|
if (remove(col_to_delete_path) < 0)
|
|
{
|
|
obi_set_errno(OBICOL_UNKNOWN_ERROR);
|
|
obidebug(1, "\nError deleting a column file when deleting unfinished columns: file %s", col_to_delete_path);
|
|
return -1;
|
|
}
|
|
free(col_to_delete_path);
|
|
}
|
|
|
|
view->columns = ll_delete(view->columns, i);
|
|
// TODO how do we check for error? NULL can be empty list
|
|
found = true;
|
|
}
|
|
if (found)
|
|
{
|
|
if (i != (((view->infos)->column_count) - 1)) // not the last one
|
|
{ // 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
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to delete a column: column not found");
|
|
return -1;
|
|
}
|
|
|
|
((view->infos)->column_count)--;
|
|
|
|
// Update column dictionary
|
|
update_column_dict(view);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name)
|
|
{
|
|
OBIDMS_column_p* column_pp;
|
|
column_pp = (OBIDMS_column_p*)(ht_get(view->column_dict, column_name));
|
|
if (column_pp == NULL)
|
|
return NULL;
|
|
return (*column_pp);
|
|
}
|
|
|
|
|
|
OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const char* column_name)
|
|
{
|
|
return (OBIDMS_column_p*)(ht_get(view->column_dict, column_name));
|
|
}
|
|
|
|
|
|
bool obi_view_column_exists(Obiview_p view, const char* column_name)
|
|
{
|
|
if (obi_view_get_column(view, column_name) == NULL)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
|
|
int obi_view_create_column_alias(Obiview_p view, const char* current_name, const char* alias)
|
|
{
|
|
int i;
|
|
bool found;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to change a column alias in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// Check that the new alias is unique
|
|
if (ht_get(view->column_dict, alias) != NULL)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError: the new name/alias identifying a column in a view is not unique");
|
|
return -1;
|
|
}
|
|
|
|
// Set the new alias in the column references
|
|
found = false;
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
if (!strcmp((((view->infos)->column_references)[i]).alias, current_name))
|
|
{
|
|
strcpy((((view->infos)->column_references)[i]).alias, alias);
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
if (found == false)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError: can't find the column '%s' to change its alias", current_name);
|
|
return -1;
|
|
}
|
|
|
|
// Update the column dictionary
|
|
update_column_dict(view);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
char* obi_view_formatted_infos(Obiview_p view, bool detailed)
|
|
{
|
|
int i;
|
|
char* view_infos = NULL;
|
|
char* view_name = NULL;
|
|
time_t creation_date;
|
|
char* creation_date_str = NULL;
|
|
index_t line_count;
|
|
char line_count_str[256];
|
|
OBIDMS_column_p column;
|
|
char* column_alias = NULL;
|
|
char* column_infos = NULL;
|
|
char* comments = NULL;
|
|
|
|
// View name
|
|
view_name = (view->infos)->name;
|
|
view_infos = (char*) malloc((strlen("# View name:\n")+strlen(view_name)+1) * sizeof(char));
|
|
strcpy(view_infos, "# View name:\n");
|
|
strcat(view_infos, view_name);
|
|
|
|
// Date created
|
|
if (view->read_only) // Date not saved until view is finished writing
|
|
{
|
|
creation_date = (view->infos)->creation_date;
|
|
creation_date_str = ctime(&creation_date);
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen("\n# Date created:\n")+strlen(creation_date_str)+1) * sizeof(char));
|
|
strcat(view_infos, "\n# Date created:\n");
|
|
strcat(view_infos, creation_date_str);
|
|
}
|
|
|
|
// Line count
|
|
line_count = (view->infos)->line_count;
|
|
snprintf(line_count_str, sizeof line_count_str, "%lld", line_count);
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen("\n# Line count:\n")+strlen(line_count_str)+1) * sizeof(char));
|
|
strcat(view_infos, "# Line count:\n");
|
|
strcat(view_infos, line_count_str);
|
|
|
|
// Columns: go through each, print their alias then their infos
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen("\n# Columns:")+1) * sizeof(char));
|
|
strcat(view_infos, "\n# Columns:");
|
|
for (i=0; i<((view->infos)->column_count); i++)
|
|
{
|
|
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column from the linked list of column pointers of a view to format view infos");
|
|
return NULL;
|
|
}
|
|
|
|
// Column alias
|
|
column_alias = (((view->infos)->column_references)[i]).alias;
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen("\n")+strlen(column_alias)+strlen(", ")+1) * sizeof(char));
|
|
strcat(view_infos, "\n");
|
|
strcat(view_infos, column_alias);
|
|
strcat(view_infos, ", ");
|
|
|
|
// Column infos
|
|
column_infos = obi_column_formatted_infos(column, detailed);
|
|
if (column_infos == NULL)
|
|
{
|
|
obidebug(1, "\nError getting column infos to format view infos");
|
|
return NULL;
|
|
}
|
|
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen(column_infos)+1) * sizeof(char));
|
|
strcat(view_infos, column_infos);
|
|
free(column_infos);
|
|
}
|
|
|
|
// Get commments if detailed informations required
|
|
if (detailed)
|
|
{
|
|
comments = (view->infos)->comments;
|
|
if (strlen(comments)>2) // Add all comments if not empty
|
|
{
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen("\n# Comments:\n")+strlen(comments)+1) * sizeof(char));
|
|
if (view_infos == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for formatted view infos");
|
|
return NULL;
|
|
}
|
|
|
|
strcat(view_infos, "\n# Comments:\n");
|
|
strcat(view_infos, comments);
|
|
}
|
|
}
|
|
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+2) * sizeof(char));
|
|
strcat(view_infos, "\n");
|
|
|
|
return view_infos;
|
|
}
|
|
|
|
|
|
char* obi_view_formatted_infos_one_line(Obiview_p view)
|
|
{
|
|
int i;
|
|
char* view_infos = NULL;
|
|
char* view_name = NULL;
|
|
time_t creation_date;
|
|
char* creation_date_str = NULL;
|
|
index_t line_count;
|
|
char line_count_str[256];
|
|
|
|
// View name
|
|
view_name = (view->infos)->name;
|
|
view_infos = (char*) malloc((strlen(" # ")+strlen(view_name)+2) * sizeof(char));
|
|
strcpy(view_infos, " # ");
|
|
strcat(view_infos, view_name);
|
|
strcat(view_infos, ":");
|
|
|
|
// Date created
|
|
if (view->read_only) // Date not saved until view is finished writing
|
|
{
|
|
creation_date = (view->infos)->creation_date;
|
|
creation_date_str = ctime(&creation_date);
|
|
// Delete \n added by ctime
|
|
creation_date_str[strlen(creation_date_str)-1] = '\0';
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen(" Date created: ")+strlen(creation_date_str)+1) * sizeof(char));
|
|
strcat(view_infos, " Date created: ");
|
|
strcat(view_infos, creation_date_str);
|
|
}
|
|
|
|
// Line count
|
|
line_count = (view->infos)->line_count;
|
|
snprintf(line_count_str, sizeof line_count_str, "%lld", line_count);
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+strlen(" ; Line count: ")+strlen(line_count_str)+1) * sizeof(char));
|
|
strcat(view_infos, " ; Line count: ");
|
|
strcat(view_infos, line_count_str);
|
|
|
|
view_infos = realloc(view_infos, (strlen(view_infos)+2) * sizeof(char));
|
|
strcat(view_infos, "\n");
|
|
|
|
return view_infos;
|
|
}
|
|
|
|
|
|
int obi_view_write_comments(Obiview_p view, const char* comments)
|
|
{
|
|
size_t new_size;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to write comments in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
if (comments == NULL)
|
|
return 0; // TODO or error? discuss
|
|
|
|
new_size = sizeof(Obiview_infos_t) + strlen(comments) + 1;
|
|
|
|
// Check if the file has to be enlarged
|
|
if (new_size >= (view->infos)->file_size)
|
|
{
|
|
if (enlarge_view_file(view, new_size) < 0)
|
|
return -1;
|
|
}
|
|
|
|
strcpy((view->infos)->comments, comments);
|
|
|
|
(view->infos)->used_size = new_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_view_add_comment(Obiview_p view, const char* key, const char* value)
|
|
{
|
|
char* new_comments = NULL;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to add a comment to a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
new_comments = obi_add_comment((view->infos)->comments, key, value);
|
|
if (new_comments == NULL)
|
|
{
|
|
obidebug(1, "\nError adding a comment to a view, key: %s, value: %s", key, value);
|
|
return -1;
|
|
}
|
|
|
|
if (obi_view_write_comments(view, new_comments) < 0)
|
|
{
|
|
obidebug(1, "\nError adding a comment to a view, key: %s, value: %s", key, value);
|
|
return -1;
|
|
}
|
|
|
|
free(new_comments);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_save_and_close_view(Obiview_p view)
|
|
{
|
|
// Finish and save the view if it is not read-only
|
|
if ( ! (view->read_only))
|
|
if (finish_view(view) < 0)
|
|
return -1;
|
|
|
|
if (close_view(view) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_dms_has_unfinished_views(OBIDMS_p dms)
|
|
{
|
|
struct dirent* dp;
|
|
int i;
|
|
char* full_path;
|
|
char* relative_path;
|
|
Obiview_infos_p view_infos;
|
|
char* view_name;
|
|
int ret_value;
|
|
|
|
ret_value = 0;
|
|
|
|
// Look for unfinished views and delete them
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
i=0;
|
|
while ((dp->d_name)[i] != '.')
|
|
i++;
|
|
relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(dp->d_name) + 2);
|
|
strcpy(relative_path, VIEW_DIR_NAME);
|
|
strcat(relative_path, "/");
|
|
strcat(relative_path, dp->d_name);
|
|
full_path = obi_dms_get_full_path(dms, relative_path);
|
|
free(relative_path);
|
|
if (full_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting the full path to a view file when cleaning unfinished views");
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
|
|
if (strcmp((dp->d_name)+i, ".obiview_unfinished") == 0)
|
|
ret_value = 1;
|
|
|
|
else if (strcmp((dp->d_name)+i, ".obiview") == 0)
|
|
{ // Check if the view was properly flagged as finished
|
|
view_name = (char*) malloc((i+1) * sizeof(char));
|
|
if (view_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view name when deleting unfinished views: file %s", dp->d_name);
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
strncpy(view_name, dp->d_name, i);
|
|
view_name[i] = '\0';
|
|
view_infos = obi_view_map_file(dms, view_name, true);
|
|
if (view_infos == NULL)
|
|
{
|
|
obidebug(1, "\nError reading a view file when deleting unfinished views: file %s", dp->d_name);
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
if (view_infos->finished == false)
|
|
ret_value = 1;
|
|
}
|
|
}
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
int obi_clean_unfinished_views(OBIDMS_p dms)
|
|
{
|
|
struct dirent* dp;
|
|
int i;
|
|
char* full_path;
|
|
char* relative_path;
|
|
Obiview_infos_p view_infos;
|
|
char* view_name;
|
|
int ret_value;
|
|
char* to_delete[1000];
|
|
int d;
|
|
|
|
ret_value = 0;
|
|
d = 0;
|
|
|
|
// Look for unfinished views and delete them
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
i=0;
|
|
while (strncmp((dp->d_name)+i, ".obiview", 8))
|
|
i++;
|
|
relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(dp->d_name) + 2);
|
|
strcpy(relative_path, VIEW_DIR_NAME);
|
|
strcat(relative_path, "/");
|
|
strcat(relative_path, dp->d_name);
|
|
full_path = obi_dms_get_full_path(dms, relative_path);
|
|
free(relative_path);
|
|
if (full_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting the full path to a view file when cleaning unfinished views");
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
if (strcmp((dp->d_name)+i, ".obiview_unfinished") == 0)
|
|
{
|
|
// Add to the list of files to delete (deleting in loop not safe)
|
|
to_delete[d] = full_path;
|
|
d++;
|
|
}
|
|
else if (strcmp((dp->d_name)+i, ".obiview") == 0)
|
|
{ // Check if the view was properly flagged as finished
|
|
view_name = (char*) malloc((i+1) * sizeof(char));
|
|
if (view_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view name when deleting unfinished views: file %s", dp->d_name);
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
strncpy(view_name, dp->d_name, i);
|
|
view_name[i] = '\0';
|
|
view_infos = obi_view_map_file(dms, view_name, true);
|
|
if (view_infos == NULL)
|
|
{
|
|
obidebug(1, "\nError reading a view file when deleting unfinished views: file %s", dp->d_name);
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
if (view_infos->finished == false)
|
|
{
|
|
// Add to the list of files to delete (deleting in loop not safe)
|
|
to_delete[d] = full_path;
|
|
d++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0; i<d; i++)
|
|
{
|
|
if (remove(to_delete[i]) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError deleting a view file when deleting unfinished views: file %s", to_delete[i]);
|
|
ret_value = -1;
|
|
}
|
|
free(to_delete[i]);
|
|
}
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
int obi_rollback_view(Obiview_p view)
|
|
{
|
|
int i;
|
|
int ret_value;
|
|
int n;
|
|
struct dirent* dp;
|
|
OBIDMS_column_p column;
|
|
char* column_file_path;
|
|
char* column_dir_name;
|
|
char* column_dir_path;
|
|
char* view_file_name;
|
|
char* view_relative_path;
|
|
char* view_full_path;
|
|
|
|
ret_value = 0;
|
|
|
|
// Don't rollback if view finished
|
|
if (view->read_only)
|
|
return ret_value;
|
|
|
|
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 rollbacking the view");
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
|
|
// Delete the column file if it was created by the view (it was if it is writable)
|
|
if (column->writable)
|
|
{
|
|
// Build file and dir paths
|
|
column_file_path = obi_column_full_path(view->dms, (column->header)->name, (column->header)->version);
|
|
if (column_file_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column file path when rollbacking a view");
|
|
ret_value = -1;
|
|
continue;
|
|
}
|
|
column_dir_name = obi_build_column_directory_name((column->header)->name);
|
|
if (column_dir_name == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column directory name when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
column_dir_path = obi_dms_get_full_path(view->dms, column_dir_name);
|
|
if (column_dir_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column directory path when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
|
|
// Try to close the column (?)
|
|
if (obi_close_column(column) < 0)
|
|
ret_value = -1;
|
|
|
|
// Delete the column file
|
|
if (remove(column_file_path) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError deleting a column file when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
|
|
// Delete column dir if it's empty TODO doesn't happen because version file
|
|
n = count_dir(column_dir_path);
|
|
if (n == 0)
|
|
{
|
|
if (remove(column_dir_path) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError deleting a column directory when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
}
|
|
free(column_file_path);
|
|
free(column_dir_name);
|
|
free(column_dir_path);
|
|
}
|
|
}
|
|
// Delete line selection if there is one
|
|
if (view->line_selection != NULL)
|
|
{
|
|
column = view->line_selection;
|
|
if (column->writable)
|
|
{
|
|
// Build file and dir paths
|
|
column_file_path = obi_column_full_path(view->dms, (column->header)->name, (column->header)->version);
|
|
if (column_file_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column file path when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
column_dir_name = obi_build_column_directory_name((column->header)->name);
|
|
if (column_dir_name == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column directory name when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
column_dir_path = obi_dms_get_full_path(view->dms, column_dir_name);
|
|
if (column_dir_path == NULL)
|
|
{
|
|
obidebug(1, "\nError getting a column directory path when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
|
|
// Try to close the column (?)
|
|
if (obi_close_column(column) < 0)
|
|
ret_value = -1;
|
|
|
|
// Delete the column file
|
|
if (remove(column_file_path) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError deleting a column file when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
|
|
// Delete column dir if it's empty TODO doesn't happen because version file
|
|
n = count_dir(column_dir_path);
|
|
if (n == 0)
|
|
{
|
|
if (remove(column_dir_path) < 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError deleting a column directory when rollbacking a view");
|
|
ret_value = -1;
|
|
}
|
|
}
|
|
free(column_file_path);
|
|
free(column_dir_name);
|
|
free(column_dir_path);
|
|
}
|
|
}
|
|
|
|
// Delete view file
|
|
view_file_name = (char*) malloc(strlen((view->infos)->name) + strlen(".obiview_unfinished") + 1);
|
|
if (view_file_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view file name");
|
|
ret_value = -1;
|
|
}
|
|
else
|
|
{
|
|
strcpy(view_file_name, (view->infos)->name);
|
|
strcat(view_file_name, ".obiview_unfinished");
|
|
rewinddir((view->dms)->view_directory);
|
|
while ((dp = readdir((view->dms)->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, view_file_name) == 0)
|
|
{
|
|
view_relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(view_file_name) + 2);
|
|
strcpy(view_relative_path, VIEW_DIR_NAME);
|
|
strcat(view_relative_path, "/");
|
|
strcat(view_relative_path, view_file_name);
|
|
view_full_path = obi_dms_get_full_path(view->dms, view_relative_path);
|
|
remove(view_full_path);
|
|
free(view_relative_path);
|
|
free(view_full_path);
|
|
}
|
|
}
|
|
free(view_file_name);
|
|
}
|
|
|
|
// Free the linked list of column pointers
|
|
ll_free(view->columns);
|
|
|
|
// Free the column dictionary
|
|
ht_free(view->column_dict);
|
|
free(view);
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
int obi_delete_view(OBIDMS_p dms, const char* view_name)
|
|
{
|
|
char* view_file_name;
|
|
char* view_relative_path;
|
|
char* view_full_path;
|
|
struct dirent* dp;
|
|
int finished_view;
|
|
|
|
// Check that the view exists
|
|
if (obi_view_exists(dms, view_name) == false)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to delete a view: view '%s' does not exist", view_name);
|
|
return -1;
|
|
}
|
|
|
|
// Check that the view is finished
|
|
finished_view = view_is_finished(dms, view_name);
|
|
if (finished_view == -1)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to check if view '%s' is finished", view_name);
|
|
return -1;
|
|
}
|
|
|
|
if (finished_view == 0)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to delete a view: view '%s' is not finished", view_name);
|
|
return -1;
|
|
}
|
|
|
|
// Delete view file
|
|
view_file_name = (char*) malloc(strlen(view_name) + strlen(".obiview") + 1);
|
|
if (view_file_name == NULL)
|
|
{
|
|
obi_set_errno(OBI_MALLOC_ERROR);
|
|
obidebug(1, "\nError allocating memory for a view file name");
|
|
return -1;
|
|
}
|
|
|
|
strcpy(view_file_name, view_name);
|
|
strcat(view_file_name, ".obiview");
|
|
rewinddir(dms->view_directory);
|
|
while ((dp = readdir(dms->view_directory)) != NULL)
|
|
{
|
|
if ((dp->d_name)[0] == '.')
|
|
continue;
|
|
if (strcmp(dp->d_name, view_file_name) == 0)
|
|
{
|
|
view_relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(view_file_name) + 2);
|
|
strcpy(view_relative_path, VIEW_DIR_NAME);
|
|
strcat(view_relative_path, "/");
|
|
strcat(view_relative_path, view_file_name);
|
|
view_full_path = obi_dms_get_full_path(dms, view_relative_path);
|
|
remove(view_full_path);
|
|
free(view_relative_path);
|
|
free(view_full_path);
|
|
}
|
|
}
|
|
free(view_file_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_create_auto_count_column(Obiview_p view)
|
|
{
|
|
index_t i;
|
|
OBIDMS_column_p column;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to create an automatic count column in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
if (obi_view_add_column(view, COUNT_COLUMN, -1, NULL, OBI_INT, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, "{}", true) < 0)
|
|
{
|
|
obidebug(1, "Error adding an automatic count column in a view");
|
|
return -1;
|
|
}
|
|
|
|
column = obi_view_get_column(view, COUNT_COLUMN);
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "Error adding an automatic count column in a view");
|
|
return -1;
|
|
}
|
|
|
|
// Fill the column with 1s
|
|
for (i=0; i < (view->infos)->line_count; i++)
|
|
{
|
|
if (obi_set_int_with_elt_idx_and_col_p_in_view(view, column, i, 0, 1) < 0)
|
|
{
|
|
obidebug(1, "Error adding an automatic count column in a view");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int obi_create_auto_id_column(Obiview_p view, const char* prefix)
|
|
{
|
|
index_t i;
|
|
OBIDMS_column_p column;
|
|
char* id;
|
|
|
|
// Check that the view is not read-only
|
|
if (view->read_only)
|
|
{
|
|
obi_set_errno(OBIVIEW_ERROR);
|
|
obidebug(1, "\nError trying to create an automatic count column in a read-only view");
|
|
return -1;
|
|
}
|
|
|
|
// Delete old ID column if it exists
|
|
if (obi_view_get_column(view, ID_COLUMN) != NULL)
|
|
{
|
|
if (obi_view_delete_column(view, ID_COLUMN, false) < 0)
|
|
{
|
|
obidebug(1, "Error deleting an ID column to replace it in a view");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Create the new ID column
|
|
if (obi_view_add_column(view, ID_COLUMN, -1, NULL, OBI_STR, 0, 1, NULL, false, false, false, false, NULL, NULL, -1, "{}", true) < 0)
|
|
{
|
|
obidebug(1, "Error adding an automatic ID column in a view");
|
|
return -1;
|
|
}
|
|
|
|
column = obi_view_get_column(view, ID_COLUMN);
|
|
if (column == NULL)
|
|
{
|
|
obidebug(1, "Error adding an automatic ID column in a view");
|
|
return -1;
|
|
}
|
|
|
|
// If prefix is NULL, use default prefix
|
|
if (prefix == NULL)
|
|
prefix = ID_PREFIX;
|
|
|
|
// Fill the column with automatic ids
|
|
for (i=0; i < (view->infos)->line_count; i++)
|
|
{
|
|
id = build_word_with_idx(prefix, i);
|
|
if (id == NULL)
|
|
{
|
|
obidebug(1, "Error building an id for an automatic ID column");
|
|
return -1;
|
|
}
|
|
if (obi_set_str_with_elt_idx_and_col_p_in_view(view, column, i, 0, id) < 0)
|
|
{
|
|
obidebug(1, "Error adding an automatic count column in a view");
|
|
return -1;
|
|
}
|
|
free(id);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// TODO Move to another file?
|
|
/*********** FOR BLOB COLUMNS ***********/
|
|
|
|
Obi_blob_p obi_get_blob_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIBlob_NA;
|
|
return obi_column_get_blob_with_elt_idx(column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
Obi_blob_p obi_get_blob_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column_p, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIBlob_NA;
|
|
return obi_get_blob_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
Obi_blob_p obi_get_blob_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIBlob_NA;
|
|
return obi_get_blob_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
Obi_blob_p obi_get_blob_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIBlob_NA;
|
|
return obi_get_blob_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/*********** FOR BOOL COLUMNS ***********/
|
|
|
|
int obi_set_bool_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, index_t element_idx, obibool_t value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column_p, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obibool_with_elt_idx(column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obibool_t obi_get_bool_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIBool_NA;
|
|
return obi_column_get_obibool_with_elt_idx(column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_bool_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, const char* element_name, obibool_t value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column_p, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_bool_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obibool_t obi_get_bool_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column_p, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column_p, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIBool_NA;
|
|
return obi_get_bool_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_bool_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, obibool_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_bool_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_bool_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, obibool_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_bool_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obibool_t obi_get_bool_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIBool_NA;
|
|
return obi_get_bool_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
obibool_t obi_get_bool_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIBool_NA;
|
|
return obi_get_bool_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR CHAR COLUMNS ***********/
|
|
|
|
int obi_set_char_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obichar_t value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obichar_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obichar_t obi_get_char_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIChar_NA;
|
|
return obi_column_get_obichar_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_char_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obichar_t value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_char_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obichar_t obi_get_char_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIChar_NA;
|
|
return obi_get_char_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_char_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, obichar_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_char_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_char_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, obichar_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_char_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obichar_t obi_get_char_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIChar_NA;
|
|
return obi_get_char_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
obichar_t obi_get_char_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIChar_NA;
|
|
return obi_get_char_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR FLOAT COLUMNS ***********/
|
|
|
|
int obi_set_float_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obifloat_t value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obifloat_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obifloat_t obi_get_float_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIFloat_NA;
|
|
return obi_column_get_obifloat_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_float_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obifloat_t value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_float_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obifloat_t obi_get_float_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIFloat_NA;
|
|
return obi_get_float_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_float_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, obifloat_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_float_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_float_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, obifloat_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_float_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obifloat_t obi_get_float_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIFloat_NA;
|
|
return obi_get_float_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
obifloat_t obi_get_float_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIFloat_NA;
|
|
return obi_get_float_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR INT COLUMNS ***********/
|
|
|
|
int obi_set_int_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obiint_t value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obiint_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obiint_t obi_get_int_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIInt_NA;
|
|
return obi_column_get_obiint_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_int_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obiint_t value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_int_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obiint_t obi_get_int_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIInt_NA;
|
|
return obi_get_int_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_int_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, obiint_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_int_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_int_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, obiint_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_int_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
obiint_t obi_get_int_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIInt_NA;
|
|
return obi_get_int_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
obiint_t obi_get_int_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIInt_NA;
|
|
return obi_get_int_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR QUAL COLUMNS ***********/
|
|
|
|
int obi_set_qual_char_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value, int offset)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obiqual_char_with_elt_idx(column, line_nb, element_idx, value, offset);
|
|
}
|
|
|
|
|
|
int obi_set_qual_int_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const uint8_t* value, int value_length)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obiqual_int_with_elt_idx(column, line_nb, element_idx, value, value_length);
|
|
}
|
|
|
|
|
|
char* obi_get_qual_char_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, int offset)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIQual_char_NA;
|
|
return obi_column_get_obiqual_char_with_elt_idx(column, line_nb, element_idx, offset);
|
|
}
|
|
|
|
|
|
const uint8_t* obi_get_qual_int_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, int* value_length)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIQual_int_NA;
|
|
return obi_column_get_obiqual_int_with_elt_idx(column, line_nb, element_idx, value_length);
|
|
}
|
|
|
|
|
|
int obi_set_qual_char_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value, int offset)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_qual_char_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value, offset);
|
|
}
|
|
|
|
|
|
int obi_set_qual_int_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const uint8_t* value, int value_length)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_qual_int_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value, value_length);
|
|
}
|
|
|
|
|
|
char* obi_get_qual_char_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, int offset)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIQual_char_NA;
|
|
return obi_get_qual_char_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, offset);
|
|
}
|
|
|
|
|
|
const uint8_t* obi_get_qual_int_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, int* value_length)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIQual_int_NA;
|
|
return obi_get_qual_int_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value_length);
|
|
}
|
|
|
|
|
|
int obi_set_qual_char_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, const char* value, int offset)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_qual_char_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value, offset);
|
|
}
|
|
|
|
|
|
int obi_set_qual_char_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, const char* value, int offset)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_qual_char_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value, offset);
|
|
}
|
|
|
|
|
|
char* obi_get_qual_char_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, int offset)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIQual_char_NA;
|
|
return obi_get_qual_char_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, offset);
|
|
}
|
|
|
|
|
|
char* obi_get_qual_char_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, int offset)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIQual_char_NA;
|
|
return obi_get_qual_char_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, offset);
|
|
}
|
|
|
|
|
|
int obi_set_qual_int_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, const uint8_t* value, int value_length)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_qual_int_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value, value_length);
|
|
}
|
|
|
|
|
|
int obi_set_qual_int_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, const uint8_t* value, int value_length)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_qual_int_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value, value_length);
|
|
}
|
|
|
|
|
|
const uint8_t* obi_get_qual_int_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, int* value_length)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIQual_int_NA;
|
|
return obi_get_qual_int_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value_length);
|
|
}
|
|
|
|
|
|
const uint8_t* obi_get_qual_int_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, int* value_length)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIQual_int_NA;
|
|
return obi_get_qual_int_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value_length);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR SEQ COLUMNS ***********/
|
|
|
|
int obi_set_seq_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obiseq_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
char* obi_get_seq_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBISeq_NA;
|
|
return obi_column_get_obiseq_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_seq_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_seq_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
char* obi_get_seq_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBISeq_NA;
|
|
return obi_get_seq_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_seq_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, const char* value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_seq_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_seq_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, const char* value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_seq_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
char* obi_get_seq_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBISeq_NA;
|
|
return obi_get_seq_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
char* obi_get_seq_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBISeq_NA;
|
|
return obi_get_seq_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR STR COLUMNS ***********/
|
|
|
|
int obi_set_str_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_obistr_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
const char* obi_get_str_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIStr_NA;
|
|
return obi_column_get_obistr_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_str_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_str_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
const char* obi_get_str_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIStr_NA;
|
|
return obi_get_str_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_str_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, const char* value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_str_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_str_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, const char* value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_str_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
const char* obi_get_str_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIStr_NA;
|
|
return obi_get_str_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
const char* obi_get_str_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIStr_NA;
|
|
return obi_get_str_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR COLUMNS WITH INDEXED VALUES ***********/
|
|
|
|
|
|
int obi_set_index_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, index_t value)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_index_with_elt_idx(column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
index_t obi_get_index_with_elt_idx_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBIIdx_NA;
|
|
return obi_column_get_index_with_elt_idx(column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_index_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, index_t value)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return -1;
|
|
return obi_set_index_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
index_t obi_get_index_with_elt_name_and_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
|
|
{
|
|
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
|
|
if (element_idx == OBIIdx_NA)
|
|
return OBIIdx_NA;
|
|
return obi_get_index_with_elt_idx_and_col_p_in_view(view, column, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
int obi_set_index_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name, index_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_index_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name, value);
|
|
}
|
|
|
|
|
|
int obi_set_index_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx, index_t value)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_index_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx, value);
|
|
}
|
|
|
|
|
|
index_t obi_get_index_with_elt_idx_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, index_t element_idx)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIIdx_NA;
|
|
return obi_get_index_with_elt_idx_and_col_p_in_view(view, column_p, line_nb, element_idx);
|
|
}
|
|
|
|
|
|
index_t obi_get_index_with_elt_name_and_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const char* element_name)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBIIdx_NA;
|
|
return obi_get_index_with_elt_name_and_col_p_in_view(view, column_p, line_nb, element_name);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
/*********** FOR ARRAY COLUMNS ***********/
|
|
|
|
int obi_set_array_with_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const void* value, uint8_t elt_size, int32_t value_length)
|
|
{
|
|
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
|
|
return -1;
|
|
return obi_column_set_array(column, line_nb, value, elt_size, value_length);
|
|
}
|
|
|
|
|
|
const void* obi_get_array_with_col_p_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, int32_t* value_length_p)
|
|
{
|
|
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
|
|
return OBITuple_NA;
|
|
return obi_column_get_array(column, line_nb, value_length_p);
|
|
}
|
|
|
|
|
|
int obi_set_array_with_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, const void* value, uint8_t elt_size, int32_t value_length)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return -1;
|
|
return obi_set_array_with_col_p_in_view(view, column_p, line_nb, value, elt_size, value_length);
|
|
}
|
|
|
|
|
|
const void* obi_get_array_with_col_name_in_view(Obiview_p view, const char* column_name, index_t line_nb, int32_t* value_length_p)
|
|
{
|
|
OBIDMS_column_p column_p;
|
|
column_p = obi_view_get_column(view, column_name);
|
|
if (column_p == NULL)
|
|
return OBITuple_NA;
|
|
return obi_get_array_with_col_p_in_view(view, column_p, line_nb, value_length_p);
|
|
}
|
|
|
|
/****************************************/
|