/*!
  \file lib/db/dbmi_base/column.c
  
  \brief DBMI Library (base) - columns management
  
  (C) 1999-2009, 2011 by the GRASS Development Team
  
  This program is free software under the GNU General Public License
  (>=v2). Read the file COPYING that comes with GRASS for details.
  
  \author Joel Jones (CERL/UIUC), Radim Blazek
  \author Doxygenized by Martin Landa <landa.martin gmail.com> (2011)
*/

#include <stdlib.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/dbmi.h>

/*!
  \brief Returns column value for given column structure

  \param column pointer to dbColumn

  \return pointer to dbValue
*/
dbValue *db_get_column_value(dbColumn *column)
{
    return &column->value;
}

/*!
  \brief Returns column default value for given column structure
   
  \param column pointer to dbColumn
  
  \return pointer to dbValue
*/
dbValue *db_get_column_default_value(dbColumn * column)
{
    return &column->defaultValue;
}

/*!
  \brief Define column sqltype for column

  The function db_sqltype_name() returns sqltype description.

  \code
  #define DB_SQL_TYPE_UNKNOWN          0
  
  #define DB_SQL_TYPE_CHARACTER        1
  #define DB_SQL_TYPE_SMALLINT         2
  #define DB_SQL_TYPE_INTEGER          3
  #define DB_SQL_TYPE_REAL             4
  #define DB_SQL_TYPE_DOUBLE_PRECISION 6
  #define DB_SQL_TYPE_DECIMAL          7
  #define DB_SQL_TYPE_NUMERIC          8
  #define DB_SQL_TYPE_DATE             9
  #define DB_SQL_TYPE_TIME            10
  #define DB_SQL_TYPE_TIMESTAMP       11
  #define DB_SQL_TYPE_INTERVAL        12
  #define DB_SQL_TYPE_TEXT            13
  
  #define DB_SQL_TYPE_SERIAL          21
  \endcode

  \param column pointer to dbColumn
  \param sqltype SQL data type (see list)
*/
void db_set_column_sqltype(dbColumn *column, int sqltype)
{
    column->sqlDataType = sqltype;
}

/*!
  \brief Set column host data type

  \param column pointer to dbColumn
  \param type data type
*/
void db_set_column_host_type(dbColumn * column, int type)
{
    column->hostDataType = type;
}

/*!
  \brief Get column scale

  \param column pointer to dbColumn

  \return scale
*/
int db_get_column_scale(dbColumn * column)
{
    return column->scale;
}

/*!
  \brief Set column scale

  \param column pointer to dbColumn
  \param scale  column scale value
*/
void db_set_column_scale(dbColumn * column, int scale)
{
    column->scale = scale;
}

/*!
  \brief Get column precision

  \param column pointer to dbColumn
  
  \return precision
*/
int db_get_column_precision(dbColumn * column)
{
    return column->precision;
}

/*!
  \brief Set column precision

  \param column pointer to dbColumn
  \param precision value
*/
void db_set_column_precision(dbColumn * column, int precision)
{
    column->precision = precision;
}

/*!
  \brief Returns column sqltype for column

  The function db_sqltype_name() returns sqltype description.
  
  \param column pointer to dbColumn
  
  \return sql data type (see include/dbmi.h)
*/
int db_get_column_sqltype(dbColumn *column)
{
    return column->sqlDataType;
}

/*!
  \brief Get column host type

  \param column pointer to dbColumn
  
  \return data type (see include/dbmi.h)
*/
int db_get_column_host_type(dbColumn * column)
{
    return column->hostDataType;
}

/*!
  \brief Set default value identificator

  \param column pointer to dbColumn
*/
void db_set_column_has_defined_default_value(dbColumn * column)
{
    column->hasDefaultValue = 1;
}

/*!
  \brief Unset default value identificator

  \todo Replace by db_unset_column_has_default_value() ?

  \param column pointer to dbColumn
*/
void db_set_column_has_undefined_default_value(dbColumn * column)
{
    column->hasDefaultValue = 0;
}

/*!
  \brief Unset default value identificator

  \param column pointer to dbColumn
*/
void db_unset_column_has_default_value(dbColumn * column)
{
    column->hasDefaultValue = 0;
}

/*!
  \brief Check if column has defined default value

  \param column pointer to dbColumn

  \return 1 if true
  \return 0 if false
*/
int db_test_column_has_default_value(dbColumn * column)
{
    return (column->hasDefaultValue != 0);
}

/*!
  \brief Check if column has defined default value

  \param column pointer to dbColumn

  \return 1 if true
  \return 0 if false
*/
int db_test_column_has_defined_default_value(dbColumn * column)
{
    return (column->hasDefaultValue);
}

/*!
  \brief Check if column has defined default value

  \param column pointer to dbColumn

  \return 1 if false
  \return 0 if true
*/
int db_test_column_has_undefined_default_value(dbColumn * column)
{
    return (!column->hasDefaultValue);
}

/*!
  \brief Set default value to be used

  \param column pointer to dbColumn
*/
void db_set_column_use_default_value(dbColumn * column)
{
    column->useDefaultValue = 1;
}

/*!
  \brief Unset default value to be used

  \param column pointer to dbColumn
*/
void db_unset_column_use_default_value(dbColumn * column)
{
    column->useDefaultValue = 0;
}

/*!
  \brief Checks if default value is used

  \param column pointer to dbColumn

  \return 1 if true
  \return 0 if false
*/
int db_test_column_use_default_value(dbColumn * column)
{
    return (column->useDefaultValue != 0);
}

/*!
  \brief Set null value to be allowed

  \param column pointer to dbColumn
*/
void db_set_column_null_allowed(dbColumn * column)
{
    column->nullAllowed = 1;
}

/*!
  \brief Unset null value to be allowed

  \param column pointer to dbColumn
*/
void db_unset_column_null_allowed(dbColumn * column)
{
    column->nullAllowed = 0;
}

/*!
  \brief Checks if null value is allowed

  \param column pointer to dbColumn

  \return 1 if true
  \return 0 if false
 */
int db_test_column_null_allowed(dbColumn * column)
{
    return (column->nullAllowed != 0);
}

/*!
  \brief Get column's length

  \param column pointer to dbColumn

  \return length
*/
int db_get_column_length(dbColumn * column)
{
    return column->dataLen;
}

/*!
  \brief Set column's length

  \param column pointer to dbColumn
  \param length value
*/
void db_set_column_length(dbColumn * column, int length)
{
    column->dataLen = length;
}

/*!
  \brief Set select privileges to be granted

  \param column pointer to dbColumn
*/
void db_set_column_select_priv_granted(dbColumn * column)
{
    column->select = DB_GRANTED;
}

/*!
  \brief Unset select privileges

  \param column pointer to dbColumn
*/
void db_set_column_select_priv_not_granted(dbColumn * column)
{
    column->select = DB_NOT_GRANTED;
}

/*!
  \brief Get select privileges

  \param column pointer to dbColumn

  \return privileges
*/
int db_get_column_select_priv(dbColumn * column)
{
    return column->select;
}

/*!
  \brief Set update privileges to be granted

  \param column pointer to dbColumn
*/
void db_set_column_update_priv_granted(dbColumn * column)
{
    column->update = DB_GRANTED;
}

/*!
  \brief Unset update privileges

  \param column pointer to dbColumn
*/
void db_set_column_update_priv_not_granted(dbColumn * column)
{
    column->update = DB_NOT_GRANTED;
}

/*!
  \brief Get update privileges

  \param column pointer to dbColumn

  \return privileges
*/
int db_get_column_update_priv(dbColumn * column)
{
    return column->update;
}

/*!
  \brief Initialize dbColumn

  \param column pointer to dbColumn to be initialized
*/
void db_init_column(dbColumn * column)
{
    db_zero((void *)column, sizeof(dbColumn));
    db_init_string(&column->columnName);
    db_init_string(&column->description);
    db_init_string(&column->value.s);
    db_init_string(&column->defaultValue.s);
}

/*!
  \brief Set column name

  \param column pointer to dbColumn
  \param name   column name

  \return DB_OK on success
  \return error code on failure
*/
int db_set_column_name(dbColumn * column, const char *name)
{
    return db_set_string(&column->columnName, name);
}

/*!
  \brief Returns column name for given column

  \param column pointer to dbColumn

  \return pointer to string with column name
*/
const char *db_get_column_name(dbColumn * column)
{
    return db_get_string(&column->columnName);
}

/*!
  \brief Set column description

  \param column pointer to dbColumn
  \param description column's description

  \return DB_OK on success
  \return error code on failure
 */
int db_set_column_description(dbColumn * column, const char *description)
{
    return db_set_string(&column->description, description);
}

/*!
  \brief Returns column description for given column

  \param column pointer to dbColumn

  \return pointer to string with column's description
*/
const char *db_get_column_description(dbColumn * column)
{
    return db_get_string(&column->description);
}

/*!
  \brief Frees column structure

  \param column pointer to dbColumn 
*/
void db_free_column(dbColumn * column)
{
    db_free_string(&column->columnName);
    db_free_string(&column->value.s);
    /* match init? */
    db_free_string(&column->description);
    db_free_string(&column->defaultValue.s);
}


/*!
  \brief Copy a db column from source to destination
  
  \param src The column to copy from
  \param dest An allocated column to copy to which will be
  initialized. In case dest is NULL a new column will be allocated
  and returned
  \return The pointer of copied/allocated column
*/
dbColumn *db_copy_column(dbColumn *dest, dbColumn *src)
{
    dbColumn *new = dest;

    if(new == NULL)
        new = (dbColumn *) db_calloc(sizeof(dbColumn), 1);
    else
        db_init_column(new);

    db_copy_string(&new->columnName, &src->columnName);
    db_copy_string(&new->description, &src->description);
    db_copy_value(&new->defaultValue, &src->defaultValue);
    db_copy_value(&new->value, &src->value);
    new->dataLen = src->dataLen;
    new->hasDefaultValue = src->hasDefaultValue;
    new->hostDataType = src->hostDataType;
    new->nullAllowed = src->nullAllowed;
    new->precision = src->precision;
    new->scale = src->scale;
    new->select = src->select;
    new->sqlDataType = src->sqlDataType;
    new->update = src->update;
    new->useDefaultValue = src->useDefaultValue;
    
    return new;
}
