///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoFieldValue.cc
// -----------------
// Cego database table field value implementation
//                                                         
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2010 Bjoern Lemke
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// IMPLEMENTATION MODULE
//
// Class: CegoFieldValue
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////



#include <lfc/Exception.h>
#include <lfc/Datetime.h>
#include <lfc/BigInteger.h>
#include <lfc/BigDecimal.h>
#include <lfc/Tokenizer.h>

#include "CegoFieldValue.h"
#include "CegoTypeConverter.h"
#include "CegoDefs.h"

#include <string.h>
#include <strings.h>
#include <stdlib.h>

char __caseSensitiveFlag = 0;
char __quoteEscapeFlag = 0;
Chain __dateFormatString(DTFORMAT);

CegoFieldValue::CegoFieldValue(const CegoFieldValue& fv)
{
    _type = fv._type;
    _len = fv._len;    
    _isLocalCopy = fv._isLocalCopy;

    if ( fv._type != NULL_TYPE )
    {
    
	if (_isLocalCopy && fv._pV)
	{
	    _pV = malloc(_len);
	    memcpy(_pV, fv._pV, _len);
	}
	else
	{
	    _pV = fv._pV;
	}
    }
    else
    {
	_pV = 0;
    }
}

CegoFieldValue::CegoFieldValue()
{
    _type = NULL_TYPE;
    _pV = 0;
    _len = 0;
    _isLocalCopy = false;
}

CegoFieldValue::CegoFieldValue(CegoDataType type, void* pValue, int len, bool isLocalCopy)
{ 
    _type = type;
    _pV = pValue;
    _len = len;
    _isLocalCopy = isLocalCopy;
}

CegoFieldValue::CegoFieldValue(CegoDataType type, const Chain& v)
{
    if ( v.length() < 2 )
    {
	_type = NULL_TYPE;
	_pV = 0;
	_len = 0;
    }
    else
    {
	
	_type = type;
	_isLocalCopy = true;
	switch ( type )
	{
	case INT_TYPE:
	{
	    _len = sizeof(int);
	    _pV = malloc(_len);
	    int i = v.asInteger();
	    memcpy(_pV, &i, _len);
	    break;
	}
	case LONG_TYPE:
	{
	    _len = sizeof(long);
	    _pV = malloc(_len);
	    long l = v.asLong();
	    memcpy(_pV, &l, _len);
	    break;
	}
	case VARCHAR_TYPE:
	case BIGINT_TYPE:
	case DECIMAL_TYPE:
	case FIXED_TYPE:
	{
	    _len = v.length();
	    _pV = malloc(_len);
	    memcpy(_pV, (char*)v, _len);
	    break;
	}
	case DATETIME_TYPE:
	{
	    _len = sizeof(int);
	    _pV = malloc(_len);
	    
	    if ( v == Chain("sysdate") )
	    {    
		Datetime dt;
		*(int*)_pV = dt.asInt();
	    }
	    else
	    {
		Datetime dt(v, Chain(__dateFormatString));
		*(int*)_pV = dt.asInt();	    
	    }
	    
	    break;
	}
	
	case FLOAT_TYPE:
	{
	    _len = sizeof(float);
	    _pV = malloc(_len);
	    float f = v.asFloat();
	    memcpy(_pV, &f, _len);
	    break;
	}
	case DOUBLE_TYPE:
	{
	    _len = sizeof(double);
	    _pV = malloc(_len);
	    double d = v.asDouble();
	    memcpy(_pV, &d, _len);
	    break;
	}
	case BOOL_TYPE:
	{
	    _len = sizeof(char);
	    _pV = malloc(_len);
	    if ( v.asBool() )
		*(char*)_pV = 1;
	    else
		*(char*)_pV = 0;
	    break;
	}
	case SMALLINT_TYPE:
	{
	    _len = sizeof(short);
	    _pV = malloc(_len);
	    short d = v.asShort();
	    memcpy(_pV, &d, _len);	
	    break;
	}
	case TINYINT_TYPE:
	{
	    _len = sizeof(char);
	    _pV = malloc(_len);
	    char d = v.asChar();
	    memcpy(_pV, &d, _len);
	    break;
	}
	case BLOB_TYPE:
	{
	    _len = 2 * sizeof(int);
	    _pV = malloc(_len);
	    Tokenizer tok(v, Chain(BLOBSEP));
	    Chain fstr;
	    Chain pstr;
	    int fileId;
	    int pageId;
	    if ( tok.nextToken(fstr) )
	    {
		fileId = fstr.asInteger();
		memcpy(_pV, &fileId, sizeof(int));
	    }
	    if ( tok.nextToken(pstr) )
	    {
		pageId = pstr.asInteger();
		memcpy( (void*)((long)_pV + sizeof(int)), &pageId, sizeof(int));
	    }
	    
	    break;
	    
	}
	case NULL_TYPE:
	{
	    _pV = 0;
	    _len = 0;
	    break;
	}
	}
    }
}

CegoFieldValue::~CegoFieldValue()
{  
    if (_isLocalCopy && _pV)
    {
	free(_pV);
    }
}

void CegoFieldValue::setType(const CegoDataType t)
{
    _type = t;
}

const CegoDataType CegoFieldValue::getType() const
{
    return _type;
}

void* CegoFieldValue::getValue() const
{
    return _pV;
}

int CegoFieldValue::getLength() const
{
    return _len;
}

bool CegoFieldValue::castTo(CegoDataType t)
{
    if ( _type == t )
	return true;

    if ( _pV == 0 )
    {
	_type = t;
	return true;
    }

    if ( _isLocalCopy == false && _pV != 0)
    {
	void* pV = _pV;
	_pV = malloc(_len);
	memcpy(_pV, pV, _len);
	_isLocalCopy = true;
    }
    
    if ( _type == INT_TYPE && t == LONG_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	free(_pV);
	
	long longVal=(long)intVal;
	
	_len = sizeof(long);
	_pV = malloc(_len);
	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == INT_TYPE)
    {
	long longVal;
	memcpy(&longVal, _pV, sizeof(long));
	free(_pV);
	
	int intVal=(int)longVal;
	
	_len = sizeof(int);
	_pV = malloc(_len);
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == INT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	free(_pV);
	
	if ( intVal == 0 )
	{
	    Datetime dt;
	    intVal = dt.asInt();
	}
	
	_len = sizeof(int);
	_pV = malloc(_len);
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }

    else if ( _type == INT_TYPE && t == BIGINT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	free(_pV);
	
	Chain bival(intVal);	
	_len = bival.length();
	_pV = malloc(_len);
	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == BIGINT_TYPE)
    {
	long longVal;
	memcpy(&longVal, _pV, sizeof(long));
	free(_pV);
	
	Chain bival(longVal);	
	_len = bival.length();
	_pV = malloc(_len);
	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == BOOL_TYPE)
    {

	Chain boolVal = Chain((char*)_pV);
	free(_pV);

	_len = sizeof(char);
	_pV = malloc(_len);
	if ( boolVal.asBool() )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;

	_type = BOOL_TYPE;
	return true;
	
    }
    else if ( _type == DECIMAL_TYPE && t == FIXED_TYPE)
    {
	_type = FIXED_TYPE;
	return true;	
    }
    else if ( _type == FLOAT_TYPE && t == FIXED_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));
	free(_pV);

	Chain flval( f );
	// cout << "flval = " << flval << endl;
	_len = flval.length();
	_pV = malloc(_len);
	_type = FIXED_TYPE;
	memcpy(_pV, (char*)flval, _len);
	return true;	
    }
    else if ( _type == FLOAT_TYPE && t == DECIMAL_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));
	free(_pV);

	Chain flval( f );
	// cout << "flval = " << flval << endl;
	_len = flval.length();
	_pV = malloc(_len);
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)flval, _len);
	return true;	
    }

    else if ( _type == VARCHAR_TYPE && t == FIXED_TYPE)
    {	
	// we construct big decimal to check format
	BigDecimal d = BigDecimal( Chain((char*)_pV) );	
	_type = FIXED_TYPE;
	return true;	
    }
    else if ( _type == INT_TYPE && t == FIXED_TYPE)
    {

	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	free(_pV);
	
	Chain bival(intVal);
	bival += Chain(".0");

	_len = bival.length();
	_pV = malloc(_len);
	_type = FIXED_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
	
    }
    else if ( _type == INT_TYPE && t == DECIMAL_TYPE)
    {

	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	free(_pV);
	
	Chain decval(intVal);
	decval += Chain(".0");

	_len = decval.length();
	_pV = malloc(_len);
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)decval, _len);
	return true;
	
    }

    return false;
    
}

void CegoFieldValue::setValue(void* pV)
{
    _pV = pV;
}

void CegoFieldValue::setLength(int len)
{
    _len = len;
}

CegoFieldValue& CegoFieldValue::operator = ( const CegoFieldValue& fv)
{
    _type = fv._type;
    _len = fv._len;
    
    if (_isLocalCopy && _pV)
	free (_pV);
    
    _isLocalCopy = fv._isLocalCopy;

    if (_isLocalCopy && fv._pV)
    {
	_pV = malloc(_len);
	memcpy(_pV, fv._pV, _len);
    }
    else
    {
	_pV = fv._pV;
    }
    return (*this);
}

bool CegoFieldValue::operator == ( const CegoFieldValue& fv) const
{

    if ( ( _type == NULL_TYPE && fv._type == NULL_TYPE )
	 || ( _type == NULL_TYPE && fv._pV == 0 )
	 || ( _pV == 0 && fv._type == NULL_TYPE ) )
    {
	return true;
    }
    if (_type == NULL_TYPE || fv._type == NULL_TYPE)
    {
	return false;
    }
    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return isEqual(fv2);
	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == true )
	    return fv2.isEqual(fv);
	       
	Chain msg = Chain("Mismatched datatypes ") + CEGO_TYPE_MAP[_type]
	    + Chain(" and ") + CEGO_TYPE_MAP[fv._type];
	throw Exception(EXLOC , msg);
	

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return isEqual(fv);
}


bool CegoFieldValue::operator != ( const CegoFieldValue& fv) const
{
    
    if ( ( _type == NULL_TYPE && fv._type == NULL_TYPE )
	 || ( _type == NULL_TYPE && fv._pV == 0 )
	 || ( _pV == 0 && fv._type == NULL_TYPE ) )
    {
	return false;
    }
    if (_type == NULL_TYPE || fv._type == NULL_TYPE)
    {
	return true;
    }
    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return ! isEqual(fv2);

	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == false )
	    return ! fv2.isEqual(fv);
	
	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }
    
    return ! isEqual(fv);
}


bool CegoFieldValue::operator < ( const CegoFieldValue& fv) const
{
    if (_type == NULL_TYPE && fv._type != NULL_TYPE)
    {
	return true;
    }
    if ( fv._type == NULL_TYPE )
    {
	return false;
    }
    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return isLess(fv2);

	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == true )
	    return fv2.isLess(fv);
	
	Chain msg = Chain("Mismatched Datatypes ") + CEGO_TYPE_MAP[_type] + Chain(" != ") + CEGO_TYPE_MAP[fv._type];
	throw Exception(EXLOC , msg);

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }
    
    return isLess(fv);
}


bool CegoFieldValue::operator > ( const CegoFieldValue& fv) const 
{

    if ( _type == NULL_TYPE )
    {
	return false;
    }
    if ( fv._type == NULL_TYPE && _type != NULL_TYPE )
    {
	return true;
    }

    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return isMore(fv2);
	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == true )
	    return fv2.isMore(fv);

	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }
    
    return isMore(fv);

}


bool CegoFieldValue::operator <= ( const CegoFieldValue& fv) const
{

    if (_type == NULL_TYPE)
    {
	return true;
    }   
    if ( _type != NULL_TYPE && fv._type == NULL_TYPE)
    {
	return false;
    }
    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return isLessEqual(fv2);

	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == true )
	    return fv2.isLessEqual(fv);

	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }
    
    return isLessEqual(fv);

}

bool CegoFieldValue::operator >= ( const CegoFieldValue& fv) const
{

    if (_type == NULL_TYPE)
    {
	return true;
    }   
    if ( _type != NULL_TYPE && fv._type == NULL_TYPE)
    {
	return false;
    }
    if (_type != fv._type )
    {
	CegoFieldValue fv2 = fv;
	if ( fv2.castTo(_type) == true )
	    return isMoreEqual(fv2);

	fv2 = *this;
	if ( fv2.castTo(fv.getType()) == true )
	    return fv2.isMoreEqual(fv);

	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (_pV == 0 || fv._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }
    
    return isMoreEqual(fv);

}


CegoFieldValue::Comparison CegoFieldValue::comp( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if (i1 < i2)
	    return LESS;
	if ( i1 > i2)
	    return MORE;
	return EQUAL;
	
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	if (i1 < i2)
	    return LESS;
	if ( i1 > i2)
	    return MORE;
	return EQUAL;
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));

	if (l1 < l2)
	    return LESS;
	if ( l1 > l2)
	    return MORE;
	return EQUAL;

    }
    case VARCHAR_TYPE:
    {

	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 < s2);
	else
	    return ( s1.toUpper() < s2.toUpper());

	*/
	int i;
	if ( __caseSensitiveFlag == 1 )
	    i = strcmp((char*)_pV, (char*)fv._pV);
	else
	    i = strcasecmp((char*)_pV, (char*)fv._pV);
	
	if ( i < 0 )
	    return LESS;
	if ( i > 0 )
	    return MORE;
	return EQUAL;

    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);

	if ( b1 < b2 )
	    return LESS;
	if ( b1 > b2 )
	    return MORE;
	return EQUAL;

    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));

	if ( bi1 < bi2 )
	    return LESS;
	if ( bi1 > bi2 )
	    return MORE;
	return EQUAL;
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));

	if ( f1 < f2 )
	    return LESS;
	if ( f1 > f2 )
	    return MORE;
	return EQUAL;

    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));	

	if ( d1 < d2 )
	    return LESS;
	if ( d1 > d2 )
	    return MORE;
	return EQUAL;

    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));

	if ( d1 < d2 )
	    return LESS;
	if ( d1 > d2 )
	    return MORE;
	return EQUAL;

    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));

	if ( s1 < s2 )
	    return LESS;
	if ( s1 > s2 )
	    return MORE;
	return EQUAL;

    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);

	if ( c1 < c2 )
	    return LESS;
	if ( c1 > c2 )
	    return MORE;
	return EQUAL;

    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}


bool CegoFieldValue::isEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;

	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));

	return (i1 == i2);
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	return (i1 == i2);
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));
	return (l1 == l2);
    }
    case VARCHAR_TYPE:
    {

	
	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 == s2);
	else
	    return ( s1.toUpper() == s2.toUpper());

	*/
	
	if ( __caseSensitiveFlag == 1 )
	    return ( strcmp((char*)_pV, (char*)fv._pV) == 0 );
	else
	    return ( strcasecmp((char*)_pV, (char*)fv._pV) == 0 );
	
    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);
	return (b1 == b2);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 == bi2);
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));
	return (f1 == f2);
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));
	return (d1 == d2);
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 == d2);
    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));
	return (s1 == s2);
    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);
	return (c1 == c2);
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isLess( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	return (i1 < i2);
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	return (i1 < i2);
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));
	return (l1 < l2);
    }
    case VARCHAR_TYPE:
    {

	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 < s2);
	else
	    return ( s1.toUpper() < s2.toUpper());

	*/

	if ( __caseSensitiveFlag == 1 )
	    return ( strcmp((char*)_pV, (char*)fv._pV) < 0 );
	else
	    return ( strcasecmp((char*)_pV, (char*)fv._pV) < 0 );
	
    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);
	return (b1 < b2);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 < bi2);
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));
	return (f1 < f2);
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));	
	return (d1 < d2);
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 < d2);
    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));
	return (s1 < s2);
    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);
	return (c1 < c2);
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isMore( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	// return false;
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	return (i1 > i2);
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	return (i1 > i2);
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));
	return (l1 > l2);
    }
    case VARCHAR_TYPE:
    {

	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 > s2);
	else
	    return ( s1.toUpper() > s2.toUpper());

	*/

	if ( __caseSensitiveFlag == 1 )
	    return ( strcmp((char*)_pV, (char*)fv._pV) > 0 );
	else
	    return ( strcasecmp((char*)_pV, (char*)fv._pV) > 0 );
       
    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);
	return (b1 > b2);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 > bi2);
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));
	return (f1> f2);
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));	
	return (d1 > d2);
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 > d2);
    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));
	return (s1 > s2);
    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);
	return (c1 > c2);
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isLessEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	return (i1 <= i2);
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	return (i1 <= i2);
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));
	return (l1 <= l2);
    }
    case VARCHAR_TYPE:
    {

	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 <= s2);
	else
	    return ( s1.toUpper() <= s2.toUpper());

	*/

	if ( __caseSensitiveFlag == 1 )
	    return ( strcmp((char*)_pV, (char*)fv._pV) <= 0 );
	else
	    return ( strcasecmp((char*)_pV, (char*)fv._pV) <= 0 );
    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);
	return (b1 <= b2);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 <= bi2);
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));
	return (f1 <= f2);
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));	
	return (d1 <= d2);
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 <= d2);
    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));
	return (s1 <= s2);
    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);
	return (c1 <= c2);
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isMoreEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	return (i1 >= i2);
    }
    case DATETIME_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv._pV, sizeof(int));
	if ( i1 == 0 )
	{
	    Datetime dt;
	    i1 = dt.asInt();
	}
	if ( i2 == 0 )
	{
	    Datetime dt;
	    i2 = dt.asInt();
	}
	return (i1 >= i2);
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv._pV, sizeof(long));
	return (l1 >= l2);
    }
    case VARCHAR_TYPE:
    {

	/*
	Chain s1 =  Chain((char*)_pV);
	Chain s2 = Chain((char*)(fv._pV));
	if ( __caseSensitiveFlag == 1 )
	    return ( s1 >= s2);
	else
	    return ( s1.toUpper() >= s2.toUpper());
	*/

	if ( __caseSensitiveFlag == 1 )
	    return ( strcmp((char*)_pV, (char*)fv._pV) >= 0 );
	else
	    return ( strcasecmp((char*)_pV, (char*)fv._pV) >= 0 );

    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(_pV);
	char b2 = *(char*)(fv._pV);
	return (b1 >= b2);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 >= bi2);
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv._pV, sizeof(float));
	return (f1>= f2);
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv._pV, sizeof(double));	
	return (d1 >= d2);
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 >= d2);
    }
    case SMALLINT_TYPE:
    {
	short s1,s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv._pV, sizeof(short));
	return (s1 >= s2);
    }
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv._pV);
	return (c1 >= c2);
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}

CegoFieldValue operator + ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{
    if ( fv1._type == NULL_TYPE ) 
    {
	return fv2;
	// throw Exception(EXLOC , "Cannot operate on null value");
    }
    if ( fv2._type == NULL_TYPE )
    {
	return fv1;
    }

    if (fv1._type != fv2._type)
    {
	CegoFieldValue fv3 = fv2;
	if ( fv3.castTo(fv1.getType()) == true )
	    return fv1.add(fv3);
	
	fv3 = fv1;
	if ( fv3.castTo(fv2.getType()) == true )
	    return fv2.add(fv3);
	    
	throw Exception(EXLOC , "Incompatible Datatypes");
	
    }
    if (fv1._pV == 0 || fv2._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return fv1.add(fv2);

}

CegoFieldValue CegoFieldValue::add( const CegoFieldValue& fv2 ) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv2._pV, sizeof(int));
	int* pI = new int;
	*pI = i1 + i2;
	CegoFieldValue fv3(_type, pI, sizeof(int), true);
	return fv3;
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv2._pV, sizeof(long));
	long* pL = new long;
	*pL = l1 + l2;
	CegoFieldValue fv3(_type, pL, sizeof(long), true);
	return fv3;
    }
    case VARCHAR_TYPE:
    {
	Chain s1 = Chain((char*)(_pV));
	Chain s2 = Chain((char*)(fv2._pV));
	Chain m =  s1 + s2;
	CegoFieldValue fv3(_type, m);
	return fv3;
    }
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Operation not supported");
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)(_pV)) );
	BigInteger bi2 =  BigInteger( Chain((char*)(fv2._pV)) );
	BigInteger bi3 = bi1.add(bi2);	
	CegoFieldValue fv3(_type, bi3.toChain());
	return fv3;
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)(_pV)) );
	BigDecimal d2 =  BigDecimal( Chain((char*)(fv2._pV)) );

	BigDecimal d3 = d1.add(d2);

	CegoFieldValue fv3(_type, d3.toChain());
	return fv3;
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv2._pV, sizeof(float));	
	float* pF = new float;
	*pF = f1 + f2;
	CegoFieldValue fv3(_type, pF, sizeof(float), true);
	return fv3;
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv2._pV, sizeof(double));
	double* pD = new double;
	*pD = d1 + d2;
	CegoFieldValue fv3(_type, pD, sizeof(double), true);
	return fv3;
    }
    case SMALLINT_TYPE:
    {
	short s1, s2;
	memcpy(&s1,_pV, sizeof(short));
	memcpy(&s2, fv2._pV, sizeof(short));	
	short* pS = new short;
	*pS = s1 + s2;
	CegoFieldValue fv3(_type, pS, sizeof(short), true);
	return fv3;
    }	
    case TINYINT_TYPE:
    {	
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv2._pV);	
	char* pC = new char;
	*pC = c1 + c2;
	CegoFieldValue fv3(_type, pC, sizeof(char), true);
	return fv3;
    }
    default:	
	throw Exception(EXLOC, "Unknown Type");
    }
}

CegoFieldValue operator - ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{

    if ( fv2._type == NULL_TYPE )
    {
	return fv1;
    }

    if ( fv1._type == NULL_TYPE )
    {
	return fv2.negate();
    }

    if (fv1._type != fv2._type)
    {
	CegoFieldValue fv3 = fv2;
	if ( fv3.castTo(fv1.getType()) == true )
	    return fv1.sub(fv3);

	fv3 = fv1;
	if ( fv3.castTo(fv2.getType()) == true )
	    return fv3.sub(fv2);

	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (fv1._pV == 0 || fv2._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return fv1.sub(fv2);
}

CegoFieldValue CegoFieldValue::sub( const CegoFieldValue& fv2 ) const
{
    
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv2._pV, sizeof(int));	
	int* pI = new int;
	*pI = i1 - i2;
	CegoFieldValue fv3(_type, pI, sizeof(int), true);
	return fv3;
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv2._pV, sizeof(long));
	long* pL = new long;
	*pL = l1 - l2;
	CegoFieldValue fv3(_type, pL, sizeof(long), true);
	return fv3;
    }
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Operation not supported");	
    }
    case BIGINT_TYPE:
    {
	
	BigInteger bi1 = BigInteger ( Chain((char*)(_pV)) );
	BigInteger bi2 = BigInteger ( Chain((char*)(fv2._pV)) );
	
	BigInteger bi3 =  bi1.sub(bi2);
	
	CegoFieldValue fv3(_type, bi3.toChain());
	
	return fv3;
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	
	BigDecimal d1 = BigDecimal( Chain((char*)(_pV)) );
	BigDecimal d2 =  BigDecimal( Chain((char*)(fv2._pV)) );

	BigDecimal d3 = d1.sub(d2);
	
	CegoFieldValue fv3(_type, d3.toChain());
	
	return fv3;
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv2._pV, sizeof(float));	
	float* pF = new float;
	*pF = f1 - f2;
	CegoFieldValue fv3(_type, pF, sizeof(float), true);
	return fv3;
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv2._pV, sizeof(double));	
	double* pD = new double;
	*pD = d1 - d2;
	CegoFieldValue fv3(_type, pD, sizeof(double), true);
	return fv3;
    }
    case SMALLINT_TYPE:
    {
	short s1, s2;
	memcpy(&s1, _pV, sizeof(short));
	memcpy(&s2, fv2._pV, sizeof(short));	
	short* pS = new short;
	*pS = s1 - s2;
	CegoFieldValue fv3(_type, pS, sizeof(short), true);
	return fv3;
    }	
    case TINYINT_TYPE:
    {
	
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv2._pV);
	
	char* pC = new char;
	*pC = c1 - c2;
	CegoFieldValue fv3(_type, pC, sizeof(char), true);
	return fv3;
    }
    
    default:

	throw Exception(EXLOC, "Unknown Type");
	
    }
}

CegoFieldValue operator * ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{

    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Cannot operate on null value");
    }
    if (fv1._type != fv2._type)
    {
	CegoFieldValue fv3 = fv2;
	if ( fv3.castTo(fv1.getType()) == true )
	    return fv1.mul(fv3);

	fv3 = fv1;
	if ( fv3.castTo(fv2.getType()) == true )
	    return fv2.mul(fv3);

	throw Exception(EXLOC , "Incompatible Datatypes");


    }
    if (fv1._pV == 0 || fv2._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return fv1.mul(fv2);
}


CegoFieldValue CegoFieldValue::mul( const CegoFieldValue& fv2 ) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv2._pV, sizeof(int));		
	int* pI = new int;
	*pI = i1 * i2;
	CegoFieldValue fv3(_type, pI, sizeof(int), true);
	return fv3;
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv2._pV, sizeof(long));
	long* pL = new long;
	*pL = l1 * l2;
	CegoFieldValue fv3(_type, pL, sizeof(long), true);
	return fv3;
    }
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Operation not supported");	
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger ( Chain((char*)(_pV)) );
	BigInteger bi2 = BigInteger ( Chain((char*)(fv2._pV)) );	
	BigInteger bi3 =  bi1.mul(bi2);
	CegoFieldValue fv3(_type, bi3.toChain());
	return fv3;
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)(_pV)) );
	BigDecimal d2 =  BigDecimal( Chain((char*)(fv2._pV)) );	
	BigDecimal d3 = d1.mul(d2);
	CegoFieldValue fv3(_type, d3.toChain());
	return fv3;
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv2._pV, sizeof(float));	
	float* pF = new float;
	*pF = f1 * f2;
	CegoFieldValue fv3(_type, pF, sizeof(float), true);
	return fv3;
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv2._pV, sizeof(double));	
	double* pD = new double;
	*pD = d1 * d2;
	CegoFieldValue fv3(_type, pD, sizeof(double), true);
	return fv3;
    }
    case SMALLINT_TYPE:
    {
	short s1, s2;
	memcpy(&s1, _pV, sizeof(short));
	memcpy(&s2, fv2._pV, sizeof(short));
	short* pS = new short;
	*pS = s1 * s2;
	CegoFieldValue fv3(_type, pS, sizeof(short), true);
	return fv3;
    }	
    case TINYINT_TYPE:
    {	
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv2._pV);	
	char* pC = new char;
	*pC = c1 * c2;
	CegoFieldValue fv3(_type, pC, sizeof(char), true);
	return fv3;
    }
    default:	
	throw Exception(EXLOC, "Unknown Type");
    }
}



CegoFieldValue operator / ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{

    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Cannot operate on null value");
    }
    if (fv1._type != fv2._type)
    {
	CegoFieldValue fv3 = fv2;
	if ( fv3.castTo(fv1.getType()) == true )
	    return fv1.div(fv3);
	
	fv3 = fv1;
	if ( fv3.castTo(fv2.getType()) == true )
	    return fv3.div(fv2);

	throw Exception(EXLOC , "Incompatible Datatypes");


    }
    if (fv1._pV == 0 || fv2._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return fv1.div(fv2);
}

CegoFieldValue CegoFieldValue::div( const CegoFieldValue& fv2 ) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	if (_pV && fv2._pV)
	{
	    int i1, i2;
	    memcpy(&i1, _pV, sizeof(int));
	    memcpy(&i2, fv2._pV, sizeof(int));		   
	    int* pI = new int;
	    if ( i2 == 0 )
		throw Exception(EXLOC , "Division by zero");
	    *pI = i1 / i2;
	    CegoFieldValue fv3(_type, pI, sizeof(int), true);
	    return fv3;
	}
	else
	{
	    CegoFieldValue fv3(_type, 0, sizeof(int), true);
	    return fv3;	    
	}
    }
    case LONG_TYPE:
    {
	if (_pV && fv2._pV)
	{
	    long l1, l2;
	    memcpy(&l1, _pV, sizeof(long));
	    memcpy(&l2, fv2._pV, sizeof(long));		   
	    long* pL = new long;

	    if ( l2 == 0 )
		throw Exception(EXLOC , "Division by zero");

	    *pL = l1 / l2;
	    CegoFieldValue fv3(_type, pL, sizeof(long), true);
	    return fv3;
	}
	else
	{
	    CegoFieldValue fv3(_type, 0, sizeof(long), true);
	    return fv3;	    
	}
    }
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Operation not supported");	
    }
    case BIGINT_TYPE:
    {
	
	BigInteger bi1 = BigInteger ( Chain((char*)(_pV)) );
	BigInteger bi2 = BigInteger ( Chain((char*)(fv2._pV)) );
	
	BigInteger bi3 =  bi1.div(bi2);
	
	CegoFieldValue fv3(_type, bi3.toChain());
	
	return fv3;
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	
	BigDecimal d1 = BigDecimal( Chain((char*)(_pV)) );
	BigDecimal d2 =  BigDecimal( Chain((char*)(fv2._pV)) );
	
	// cout << "div : " << d1 << " / " << d2 << endl;

	BigDecimal d3 = d1.div(d2);
	
	// cout << "res =  " << d3  << endl;
	CegoFieldValue fv3(_type, d3.toChain());
	
	return fv3;
    }
    case FLOAT_TYPE:
    {
	float f1, f2;
	memcpy(&f1, _pV, sizeof(float));
	memcpy(&f2, fv2._pV, sizeof(float));	
	float* pF = new float;

	if ( f2 == 0 )
	    throw Exception(EXLOC , "Division by zero");

	*pF = f1 / f2;
	CegoFieldValue fv3(_type, pF, sizeof(float), true);
	return fv3;
    }
    case DOUBLE_TYPE:
    {
	double d1, d2;
	memcpy(&d1, _pV, sizeof(double));
	memcpy(&d2, fv2._pV, sizeof(double));	
	double* pD = new double;

	if ( d2 == 0 )
	    throw Exception(EXLOC , "Division by zero");

	*pD = d1 / d2;
	CegoFieldValue fv3(_type, pD, sizeof(double), true);
	return fv3;
    }
    case SMALLINT_TYPE:
    {
	short s1, s2;
	memcpy(&s1, _pV, sizeof(short));
	memcpy(&s2, fv2._pV, sizeof(short));	
	short* pS = new short;

	if ( s2 == 0 )
	    throw Exception(EXLOC , "Division by zero");

	*pS = s1 / s2;
	CegoFieldValue fv3(_type, pS, sizeof(short), true);
	return fv3;
    }	
    case TINYINT_TYPE:
    {
	char c1 = *(char*)(_pV);
	char c2 = *(char*)(fv2._pV);	
	char* pC = new char;

	if ( c2 == 0 )
	    throw Exception(EXLOC , "Division by zero");

	*pC = c1 / c2;
	CegoFieldValue fv3(_type, pC, sizeof(char), true);
	return fv3;
    }
    default:	
	throw Exception(EXLOC, "Unknown Type");
    }
}



CegoFieldValue operator | ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{

    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Cannot operate on null value");
    }
    if (fv1._type != fv2._type)
    {
	CegoFieldValue fv3 = fv2;
	if ( fv3.castTo(fv1.getType()) == true )
	    return fv1.concat(fv3);

	fv3 = fv1;
	if ( fv3.castTo(fv2.getType()) == true )
	    return fv3.concat(fv2);

	throw Exception(EXLOC , "Incompatible Datatypes");

    }
    if (fv1._pV == 0 || fv2._pV == 0)
    {
	throw Exception(EXLOC , "Undefined field value");
    }

    return fv1.concat(fv2);
}

CegoFieldValue CegoFieldValue::concat( const CegoFieldValue& fv2 ) const
{
	
    switch (_type ) 
    {
    case INT_TYPE:
    {
	int i1, i2;
	memcpy(&i1, _pV, sizeof(int));
	memcpy(&i2, fv2._pV, sizeof(int));
	CegoFieldValue fv3(VARCHAR_TYPE, Chain(i1) + Chain(i2) ) ;
	return fv3;
    }
    case LONG_TYPE:
    {
	long l1, l2;
	memcpy(&l1, _pV, sizeof(long));
	memcpy(&l2, fv2._pV, sizeof(long));
	CegoFieldValue fv3(VARCHAR_TYPE, Chain(l1) + Chain(l2) ) ;
	return fv3;
    }
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    {
	Chain c1 = Chain((char*)(_pV));
	Chain c2 = Chain((char*)(fv2._pV));
	CegoFieldValue fv3(VARCHAR_TYPE, c1 + c2 ) ;
	return fv3;
    }
    default:
	throw Exception(EXLOC, "Unknown Type");
    }
}


CegoFieldValue CegoFieldValue::negate() const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	int i;
	memcpy(&i, _pV, sizeof(int));
	int* pI = new int;
	*pI = (-1) * i;
	CegoFieldValue fv3(_type, pI, sizeof(int), true);
	return fv3;
    }
    case LONG_TYPE:
    {
	long l;
	memcpy(&l, _pV, sizeof(long));
	long* pL = new long;
	*pL = (-1) * l;
	CegoFieldValue fv3(_type, pL, sizeof(long), true);
	return fv3;
    }
    case BIGINT_TYPE:
    {
	BigInteger bi = BigInteger( Chain((char*)(_pV)) );
	bi.negate();
	CegoFieldValue fv3(_type, bi.toChain());
	return fv3;
    }
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {
	BigDecimal bd = BigDecimal( Chain((char*)(_pV)) );
	bd.negate();
	CegoFieldValue fv3(_type, bd.toChain());
	return fv3;
    }
    case FLOAT_TYPE:
    {
	float f;
	memcpy(&f, _pV, sizeof(float));
	float* pF = new float;
	*pF = (-1.0) * f;
	CegoFieldValue fv3(_type, pF, sizeof(float), true);
	return fv3;
    }
    case DOUBLE_TYPE:
    {
	double d;
	memcpy(&d, _pV, sizeof(double));
	double* pD = new double;
	*pD = (-1.0) * d;
	CegoFieldValue fv3(_type, pD, sizeof(double), true);
	return fv3;
    }
    case SMALLINT_TYPE:
    {
	short s;
	memcpy(&s,_pV, sizeof(short));
	short* pS = new short;
	*pS = (-1) * s;
	CegoFieldValue fv3(_type, pS, sizeof(short), true);
	return fv3;
    }	
    case TINYINT_TYPE:
    {	
	char c = *(char*)(_pV);
	char* pC = new char;
	*pC = (-1) * c;
	CegoFieldValue fv3(_type, pC, sizeof(char), true);
	return fv3;
    }
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Cannot negate date type");
    }
    default:	
	throw Exception(EXLOC, "Unknown Type");
    }
}

void CegoFieldValue::setLocalCopy(bool isLocal)
{
    _isLocalCopy = isLocal;
}

bool CegoFieldValue::isLocalCopy() const
{
    return _isLocalCopy;
}

void CegoFieldValue::getLocalCopy(const CegoFieldValue& fv)
{
    _type = fv._type;
    _len = fv._len;
    if (_isLocalCopy && _pV)
	free (_pV);
    _pV = malloc(_len);
    memcpy(_pV, fv._pV, _len);
    _isLocalCopy = true;
}

bool CegoFieldValue::isNull() const
{
    if ( _type == NULL_TYPE || _pV == 0 )
	return true;
    return false;
}

Chain CegoFieldValue::toChain() const
{

    Chain s;

    if ( _type == NULL_TYPE || _type == BLOB_TYPE )
    {
	s = Chain("null");
    }
    else
    {
	if ( _pV == 0 )
	{
	    s = Chain("null");
	    return s;
	}
	switch (_type)
	{
	case INT_TYPE:
	{
	    int i;
	    memcpy(&i, _pV, sizeof(int));
	    s = Chain( i );
	    break;
	}   
	case LONG_TYPE:
	{
	    long l;
	    memcpy(&l, _pV, sizeof(long));
	    s = Chain("(long)") + Chain( l );
	    break;
	}   
	case VARCHAR_TYPE:	    
	{   
	    Chain val((char*)_pV);

	    // escape backslashes
	    Chain bval;
	    val.replaceAll(Chain("\\"), Chain("\\\\"), bval);

	    // escape newlines
	    Chain nval;
	    bval.replaceAll(Chain("\n"), Chain("\\n"), nval);

	    // escape quotes
	    Chain qval;
	    if ( __quoteEscapeFlag )
	    {
		nval.replaceAll(Chain("'"), Chain("''"), qval);
	    }
	    else
	    {
		nval.replaceAll(Chain("'"), Chain("\\'"), qval);
	    }

	    s = Chain("'") + qval + Chain("'");
	    break;
	}   
	case BOOL_TYPE:
	{   
	    char b = *(char*)(_pV);
	    if ( b == 1 )
		s = Chain("true");
	    else
		s = Chain("false");
	    break;
	}    
	case DATETIME_TYPE:
	{
	    int i;
	    memcpy(&i, _pV, sizeof(int));
	    if ( i == 0 )
	    {
		s = Chain("sysdate");
	    }
	    else
	    {
		Datetime dt ( i );
		s = Chain("date('") + __dateFormatString + Chain("','") + dt.asChain(__dateFormatString) + Chain("')");
	    }
	    break;
	}
	case BIGINT_TYPE:
	{
	    BigInteger bi( Chain((char*)_pV) );
	    s =  Chain("(bigint)") +  bi.toChain();
	    break;
	}
	case DECIMAL_TYPE:
	{
	    BigDecimal d( Chain((char*)_pV) );
	    s = Chain("(decimal)") + d.toChain();
	    break;	    
	}
	case FIXED_TYPE:
	{
	    BigDecimal d( Chain((char*)_pV) );
	    s = Chain("(fixed)") + d.toChain();
	    break;
	}
	case FLOAT_TYPE:
	{
	    float f;
	    memcpy(&f, _pV, sizeof(float));
	    s = Chain( f );
	    break;
	}
	case DOUBLE_TYPE:
	{
	    double d;
	    memcpy(&d, _pV, sizeof(double));
	    s = Chain("(double)") + Chain( d );
	    break;
	}
	case SMALLINT_TYPE:
	{
	    short st;
	    memcpy(&st, _pV, sizeof(short));
	    s = Chain("(smallint)") + Chain( st );
	    break;
	}
	case TINYINT_TYPE:
	{
	    s = Chain("(tinyint)") + Chain( *(char*)(_pV) );
	    break;
	}
	case BLOB_TYPE:
	case NULL_TYPE:
	    // already handled
	    break;	    
	}
    }
    return s;
}


Chain CegoFieldValue::typeToChain() const
{

    Chain s;

    switch ( _type )
    {
    case NULL_TYPE:
    {
	s = Chain("null");
	break;
    }
    case VARCHAR_TYPE:
    case FIXED_TYPE:
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    {
	s = CEGO_TYPE_MAP[_type] + Chain("(") + Chain(_len) + Chain(")");
	break;
    }
    default:
    {
	s = CEGO_TYPE_MAP[_type];
	break;
    }
    }

    return s;
}


Chain CegoFieldValue::valAsChain(bool doEval) const
{

    Chain s;

    if ( _type == NULL_TYPE )
    {
	s = Chain("null");
    }
    else
    {
	if ( _pV == 0 )
	{
	    s = Chain("null");
	    return s;
	}
	switch (_type)
	{
	case INT_TYPE:
	{
	    int i;
	    memcpy(&i, _pV, sizeof(int));
	    s = Chain( i );
	    break;
	}   
	case LONG_TYPE:
	{
	    long l;
	    memcpy(&l, _pV, sizeof(long));
	    s = Chain( l );
	    break;
	}   
	case VARCHAR_TYPE:	    
	case BIGINT_TYPE:
	case DECIMAL_TYPE:
	case FIXED_TYPE:
	{   
	    s = Chain((char*)_pV);
	    break;
	}   
	case BOOL_TYPE:
	{   
	    char b = *(char*)(_pV);
	    if ( b == 1 )
		s = Chain("true");
	    else
		s = Chain("false");
	    break;
	}    
	case DATETIME_TYPE:
	{
	    int i;
	    memcpy(&i, _pV, sizeof(int));

	    if ( i == 0 )
	    {
		if ( doEval )
		{
		    Datetime dt;
		    s = dt.asChain();
		}
		else
		{
		    s = Chain("sysdate");
		}
	    }
	    else
	    {
		Datetime dt(i);
		s = dt.asChain();
	    }
	    break;
	}
	case FLOAT_TYPE:
	{
	    float f;
	    memcpy(&f, _pV, sizeof(float));
	    s = Chain( f );
	    break;
	}
	case DOUBLE_TYPE:
	{
	    double d;
	    memcpy(&d, _pV, sizeof(double));
	    s = Chain( d );
	    break;
	}
	case SMALLINT_TYPE:
	{
	    short st;
	    memcpy(&st, _pV, sizeof(short));
	    s = Chain( st );
	    break;
	}
	case TINYINT_TYPE:
	{
	    s = Chain( *(char*)(_pV) );
	    break;
	}
	case BLOB_TYPE:
	{
	    int f, p;
	    memcpy(&f, _pV, sizeof(int));
	    memcpy(&p, (void*)((long)_pV + sizeof(int)), sizeof(int));

	    s = Chain("[") + Chain( f ) + Chain(",") + Chain(p) + Chain("]");
	    break;

	}
	case NULL_TYPE:
	    // already handled
	    break;
	}
    }
    return s;
}

long CegoFieldValue::asLong() const
{
    CegoFieldValue fv = *this;

    if ( fv.castTo(LONG_TYPE) == false )
	throw Exception(EXLOC, Chain("Cannot get long value"));
    
    long l;
    memcpy(&l, fv.getValue(), sizeof(long));
    return l;
}

void CegoFieldValue::encode(char *buf)
{
    
    char* pE = (char*)buf;
    
    memcpy( pE, &_type, sizeof(CegoDataType));
    pE = pE + sizeof(CegoDataType);

    switch (_type )
    {
    case INT_TYPE:
    {
	memcpy(pE, _pV, sizeof(int));
	pE = pE + sizeof(int);
	break;
    }   
    case LONG_TYPE:
    {
	memcpy(pE, _pV, sizeof(long));
	pE = pE + sizeof(long);
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {   
	memcpy(pE, &_len, sizeof(int));
	pE = pE + sizeof(int);
	memcpy(pE, _pV, _len);
	pE = pE + _len;
	break;
    }   
    case BOOL_TYPE:
    {   
	memcpy(pE, _pV, 1);
	pE = pE + 1;
	break;
    }    
    case DATETIME_TYPE:
    {
	memcpy(pE, _pV, sizeof(int));
	pE = pE + sizeof(int);
	break;
    }
    case FLOAT_TYPE:
    {
	memcpy(pE, _pV, sizeof(float));
	pE = pE + sizeof(float);
	break;
    }
    case DOUBLE_TYPE:
    {
	memcpy(pE, _pV, sizeof(double));
	pE = pE + sizeof(double);
	break;
    }
    case SMALLINT_TYPE:
    {
	memcpy(pE, _pV, sizeof(short));
	pE = pE + sizeof(short);
	break;
    }
    case TINYINT_TYPE:
    {
	memcpy(pE, _pV, 1);
	pE = pE + 1;
	break;
    }
    case BLOB_TYPE:
    {   
	memcpy(pE, _pV, 2 * sizeof(int));
	pE = pE + 2 * sizeof(int);
	break;
    }   
    case NULL_TYPE:
	break;

    }
}

void CegoFieldValue::decode(char *buf)
{

    char* pE = (char*)buf;
    
    memcpy( &_type, pE, sizeof(CegoDataType));
    pE = pE + sizeof(CegoDataType);

    switch (_type )
    {
    case INT_TYPE:
    {
	_len = sizeof(int);
	_pV = malloc(_len);
	memcpy(_pV, pE, sizeof(int));
	pE = pE + sizeof(int);
	break;
    }   
    case LONG_TYPE:
    {
	_len = sizeof(long);
	_pV = malloc(_len);
	memcpy(_pV, pE, _len);
	pE = pE + _len;
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {   
	memcpy(&_len, pE, sizeof(int));
	pE = pE + sizeof(int);
	_pV = malloc(_len);
	memcpy(_pV, pE, _len);
	pE = pE + _len;
	break;
    }   
    case BOOL_TYPE:
    {   
	_len = sizeof(char);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }    
    case DATETIME_TYPE:
    {
	_len = sizeof(int);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case FLOAT_TYPE:
    {
	_len = sizeof(float);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case DOUBLE_TYPE:
    {
	_len = sizeof(double);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case SMALLINT_TYPE:
    {
	_len = sizeof(short);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case TINYINT_TYPE:
    {
	_len = sizeof(char);
	_pV = malloc(_len);
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case BLOB_TYPE:
    {
	_len = 2 * sizeof(int);
	_pV = malloc(_len);
	memcpy(_pV, pE, 2 * sizeof(int));
	pE = pE + 2 * sizeof(int);
	break;
    }   
    case NULL_TYPE:
	break;
    }
}

int CegoFieldValue::getEncodingLength() const
{

    int len = 0;
    
    len += sizeof(CegoDataType);

    switch (_type )
    {
    case INT_TYPE:
    {
	len += sizeof(int);
	break;
    }   
    case LONG_TYPE:
    {
	len += sizeof(long);
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    case FIXED_TYPE:
    {   	
	len += _len + sizeof(int);
	break;
    }   
    case BOOL_TYPE:
    {   
	len += 1;
	break;
    }    
    case DATETIME_TYPE:
    {
	len += sizeof(int);
	break;
    }
    case FLOAT_TYPE:
    {
	len += sizeof(float);
	break;
    }
    case DOUBLE_TYPE:
    {
	len += sizeof(double);
	break;
    }
    case SMALLINT_TYPE:
    {
	len += sizeof(short);
	break;
    }
    case TINYINT_TYPE:
    {
	len += 1;
	break;
    }
    case BLOB_TYPE:
    {
	len += 2 * sizeof(int);
	break;
    }   
    case NULL_TYPE:
	break;
    }
    
    return len;
}

ostream& operator << (ostream& s, const CegoFieldValue& fv)
{

    if ( fv._type == NULL_TYPE )
    {
	s << "null";
	return s;
    }

    if ( fv._pV == 0 )
    {
	s << "null";
	return s;
    }
    switch (fv._type)
    {
    case INT_TYPE:
    {
	int i;
	memcpy(&i, fv._pV, sizeof(int));
	s << i;
	break;
    }
    case LONG_TYPE:
    {
	long l;
	memcpy(&l, fv._pV, sizeof(long));
	s << l;
	break;
    }
    case VARCHAR_TYPE:
	s <<  Chain((char*)fv._pV);
	break;
    case BOOL_TYPE:
	s << *(char*)(fv._pV);
	break;
    case DATETIME_TYPE:
    {
	int i;
	memcpy(&i, fv._pV, sizeof(int));
	Datetime dt ( i );
	s << dt.asChain();
	break;
    }
    case BIGINT_TYPE:
    {
	BigInteger bi((char*)(fv._pV));
	s << bi.toChain();
	break;	
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d((char*)(fv._pV));
	s << Chain("(decimal)") << d.toChain();
	break;
    }
    case FIXED_TYPE:
    {
	BigDecimal d((char*)(fv._pV));
	s <<  Chain("(fixed)") << d.toChain();
	break;	
    }
    case DOUBLE_TYPE:
    {
	double d;
	memcpy(&d, fv._pV, sizeof(double));
	s << d;
	break;
    }
    case FLOAT_TYPE:
    {
	float f;
	memcpy(&f, fv._pV, sizeof(float));
	s << f;
	break;
    }
    case SMALLINT_TYPE:
    {
	short sv;
	memcpy(&sv, fv._pV, sizeof(short));
	s << sv;
	break;
    }
    case TINYINT_TYPE:
    {
	double t;
	memcpy(&t, fv._pV, sizeof(char));
	s << t;
	break;
    }
    case BLOB_TYPE:
    {
	s << fv.valAsChain();
	break;
    }
    default:
	s << "Datatype not supported yet";
    }
    return s;
}
