///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoFieldValue.cc
// -----------------
// Field value implementation
//
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// IMPLEMENTATION MODULE
//
// Class: CegoFieldValue
//
// Description: Data field value which can contain all supported data types
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// LFC INCLUDES
#include <lfcbase/Exception.h>
#include <lfcbase/Datetime.h>
#include <lfcbase/BigInteger.h>
#include <lfcbase/BigDecimal.h>
#include <lfcbase/Tokenizer.h>
#include <lfcbase/ThreadLock.h>

// CEGO INCLUDES
#include "CegoFieldValue.h"
#include "CegoDefs.h"
#include "CegoDatabaseFormater.h"
#include "CegoTypeConverter.h"

// POSIX INCLUDES
#include <string.h>
#include <strings.h>
#include <stdlib.h>

long long __recoveryTS = 0;

char __currencySymbol;
char __decimalPoint;
char __caseSensitiveFlag = 0;
char __quoteEscapeFlag = 0;
Chain __dateTimeFormat;
ListT<Chain> __dateFormatList;
ThreadLock __dateFormatLock("DATEFORMAT");
BigDecimal::RoundMode __roundMode = BigDecimal::DOWN;

#define FLOAT_TO_LONG(x) ((x)>=0?(long long)((x)+0.5):(long long)((x)-0.5))
#define FLOAT_TO_INT(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5))
#define FLOAT_TO_SHORT(x) ((x)>=0?(short)((x)+0.5):(short)((x)-0.5))
#define FLOAT_TO_CHAR(x) ((x)>=0?(char)((x)+0.5):(char)((x)-0.5))

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

    if ( fv._type != NULL_TYPE )
    {    
	if (_isLocalCopy && fv._pV)
	{
	    if ( _len <= STATICFIELDBUF )
		_pV = _staticBuf;
	    else
		_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, unsigned 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 = _staticBuf; 
	    int i = v.asInteger();
	    memcpy(_pV, &i, _len);
	    break;
	}
	case LONG_TYPE:
	{
	    _len = sizeof(long long);
	    _pV = _staticBuf;	    
	    long long l = v.asLongLong();
	    memcpy(_pV, &l, _len);
	    break;
	}
	case VARCHAR_TYPE:
	case BIGINT_TYPE:
	case DECIMAL_TYPE:
	{
	    _len = v.length();
	    if ( _len <= STATICFIELDBUF )
		_pV = _staticBuf;
	    else
		_pV = malloc(_len);
	    memcpy(_pV, (char*)v, _len);
	    break;
	}
	case DATETIME_TYPE:
	{
	    _len = sizeof(long long);
	    _pV = _staticBuf;
	    
	    if ( v == Chain("sysdate") )
	    {    
		Datetime dt;
		*(long long*)_pV = dt.asLong();
	    }
	    else
	    {
		Datetime dt(v, Chain(__dateTimeFormat));
		*(long long*)_pV = dt.asLong();
	    }	    
	    break;
	}	
	case FLOAT_TYPE:
	{
	    _len = sizeof(float);
	    _pV = _staticBuf;
	   
	    Chain normFloat = v;
	    normFloatValue(normFloat);
	    	    
	    float f = normFloat.asFloat();
	    memcpy(_pV, &f, _len);
	    break;
	}
	case DOUBLE_TYPE:
	{
	    _len = sizeof(double);
	    _pV = _staticBuf;

	    Chain normDouble = v;
	    normFloatValue(normDouble);

	    double d = normDouble.asDouble();
	    memcpy(_pV, &d, _len);
	    break;
	}
	case BOOL_TYPE:
	{
	    _len = sizeof(char);
	    _pV = _staticBuf;
	    if ( v.asBool() )
		*(char*)_pV = 1;
	    else
		*(char*)_pV = 0;
	    break;
	}
	case SMALLINT_TYPE:
	{
	    _len = sizeof(short);
	    _pV = _staticBuf;
	    short d = v.asShort();
	    memcpy(_pV, &d, _len);	
	    break;
	}
	case TINYINT_TYPE:
	{
	    _len = sizeof(char);
	    _pV = _staticBuf;
	    char d = (char)v.asInteger();
	    memcpy(_pV, &d, _len);
	    break;
	}
	case BLOB_TYPE:
	case CLOB_TYPE:
	{
	    _len = sizeof(PageIdType);
	    _pV = _staticBuf;
	    Tokenizer tok(v, Chain(LOBSEP));
	    Chain pstr;
	    PageIdType pageId;
	    if ( tok.nextToken(pstr) )
	    {
		pageId = pstr.asUnsignedLongLong();
		memcpy(_pV, &pageId, sizeof(PageIdType));
	    }	    
	    break;	    
	}
	case NULL_TYPE:
	{
	    _pV = 0;
	    _len = 0;
	    break;
	}
	case PAGEID_TYPE:
	{
	    throw Exception(EXLOC, "Cannot handle pageid type"); 
	}
	}
    }
}

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

Chain CegoFieldValue::getId() const
{
    if ( _type == DATETIME_TYPE )
	return valAsChain(true);
    else
	// to distinguish null comparison x = null and x = 'null'
	return toChain();
}

void CegoFieldValue::setNull()
{
    if ( _isLocalCopy && _pV && _pV != _staticBuf )
	free (_pV);
    _type = NULL_TYPE;
    _pV = 0;
    _len = 0;
    _isLocalCopy = false;    
}

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

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

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

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

unsigned CegoFieldValue::getDim() const
{
    unsigned dim = 0;
    
    switch (_type )
    {
    case INT_TYPE:
	dim = 0;
	break;
    case LONG_TYPE:
	dim = 0;
	break;
    case DATETIME_TYPE:
	dim = 0;
	break;
    case BOOL_TYPE:
	dim = 0;
	break;
    case SMALLINT_TYPE:
	dim = 0;
	break;
    case TINYINT_TYPE:
	dim = 0;
	break;
    // for all variable not floating types, we return 0
    case VARCHAR_TYPE:
    case BIGINT_TYPE:
    case BLOB_TYPE:
    case CLOB_TYPE:
    case NULL_TYPE:
    case PAGEID_TYPE:
    {
	dim = 0;
	break;
    }
    case DECIMAL_TYPE:
    {
	Chain decVal(Chain((char*)_pV));	       
	unsigned long pos;
	decVal.posStr(Chain("."), pos);	    
	dim = decVal.length() - pos - 1;
	break;
    }   
    case FLOAT_TYPE:
    {
	dim = 0;
	break;
    }    
    case DOUBLE_TYPE:
    {
	dim = 0;
	break;
    }
    }
    return dim;
}

bool CegoFieldValue::castTo(CegoDataType t, unsigned d)
{
    if ( _pV == 0 )
    {	
	return true;
    }

    if ( _type == t && getDim() == d )
	return true;
    
    if ( _isLocalCopy == false && _pV != 0)
    {
	void* pV = _pV;

	if ( _len <= STATICFIELDBUF )
	    _pV = _staticBuf;
	else
	    _pV = malloc(_len);
	memcpy(_pV, pV, _len);
	_isLocalCopy = true;
    }

    if ( _type == DECIMAL_TYPE && t == DECIMAL_TYPE)
    {
	// for fixed values, we have to check the correct dimension
	    
	Chain fixedVal((char*)_pV);

	unsigned localDim = getDim();
	if ( d != localDim )
	{
	    if ( d > localDim )
	    {
		unsigned diff = d - localDim;
		while ( diff > 0 )
		{
		    fixedVal = fixedVal + Chain("0");
		    diff --;
		}
	    }
	    else if ( d < localDim )
	    {
		unsigned diff = localDim - d;
		fixedVal = fixedVal.subChain(1, fixedVal.length() - ( diff + 1) );
	    }
	    
	    if ( _isLocalCopy && _pV && _pV != _staticBuf )
		free(_pV);
	    _pV = _staticBuf;
		
	    _len = fixedVal.length();
	    
	    if ( _len > STATICFIELDBUF )
	    {
		_isLocalCopy = true;
		_pV = malloc(_len);
	    }
	    memcpy(_pV, (char*)fixedVal, _len);
	}
	return true;
    }

    // for equal type, can can return now
    if ( _type == t )
    {
	return true;
    }

    ///////////////////
    // cast int to X //
    ///////////////////

    if ( _type == INT_TYPE && t == LONG_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long longVal=(long long)intVal;
	
	_len = sizeof(long long);
	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == VARCHAR_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )	
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal(intVal);
	_len = strVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}

	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == BOOL_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(char);

	if ( intVal > 0 )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;

	_type = BOOL_TYPE;
	return true;
    }
    else if ( _type == INT_TYPE && t == DATETIME_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long dateVal=(long long)intVal;
	
	_len = sizeof(long long);
	
	_type = DATETIME_TYPE;
	memcpy(_pV, &dateVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == BIGINT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	    
	Chain bival(intVal);	
	_len = bival.length();
       	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}

	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == FLOAT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	Chain floatChain(intVal);
	floatChain += Chain(__decimalPoint) + Chain("0");	
	float floatVal = floatChain.asFloat();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	_len = sizeof(float);	
	_type = FLOAT_TYPE;
	memcpy(_pV, &floatVal, _len);
	return true;	
    }
    else if ( _type == INT_TYPE && t == DOUBLE_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	Chain doubleChain(intVal);
	doubleChain += Chain(__decimalPoint) + Chain("0");	
	double doubleVal = doubleChain.asDouble();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(double);	
	_type = DOUBLE_TYPE;
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == DECIMAL_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	    
	Chain fixedVal(intVal);
	fixedVal += Chain(".");
	for ( int i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if (  _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == SMALLINT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	short shortVal=(short)intVal;
	_len = sizeof(short);
	
	_type = SMALLINT_TYPE;
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == INT_TYPE && t == TINYINT_TYPE)
    {
	int intVal;
	memcpy(&intVal, _pV, sizeof(int));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char tinyVal=(char)intVal;	
	_len = sizeof(char);	
	_type = TINYINT_TYPE;
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////
    // cast long to X //
    ////////////////////

    else if ( _type == LONG_TYPE && t == INT_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	int intVal=(int)longVal;
	_len = sizeof(int);	
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == VARCHAR_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal(longVal);
	_len = strVal.length();
	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == BOOL_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	_len = sizeof(char);
	if ( longVal > 0 )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;
	_type = BOOL_TYPE;
	return true;
    }
    else if ( _type == LONG_TYPE && t == DATETIME_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long dateVal = (long long)longVal;	
	_len = sizeof(long long);
	_type = DATETIME_TYPE;
	memcpy(_pV, &dateVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == BIGINT_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain bival(longVal);	
	_len = bival.length();
	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == FLOAT_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
		
	Chain floatChain(longVal);
	floatChain += Chain(__decimalPoint) + Chain("0");
	float floatVal = floatChain.asFloat();	

	_len = sizeof(float);
	_type = FLOAT_TYPE;
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == DOUBLE_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain doubleChain(longVal);
	doubleChain += Chain(__decimalPoint) + Chain("0");	
	double doubleVal = doubleChain.asDouble();	
	
	_len = sizeof(double);	
	_type = DOUBLE_TYPE;
	memcpy(_pV, &doubleVal, _len);
	return true;	
    }
    else if ( _type == LONG_TYPE && t == DECIMAL_TYPE)
    {	
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	    
	Chain fixedVal(longVal);
	fixedVal += Chain(".");
	for ( unsigned i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;	
    }
    else if ( _type == LONG_TYPE && t == SMALLINT_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
		
	short shortVal=(short)longVal;	
	_len = sizeof(short);
	_type = SMALLINT_TYPE;
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == LONG_TYPE && t == TINYINT_TYPE)
    {
	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char tinyVal=(char)longVal;	
	_len = sizeof(char);
	_type = TINYINT_TYPE;
	memcpy(_pV, &tinyVal, _len);
	return true;
    }
    
    ///////////////////////
    // cast varchar to X //
    ///////////////////////

    else if ( _type == VARCHAR_TYPE && t == INT_TYPE)
    {

	Chain strVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )	    
	    free(_pV);
	
	_pV = _staticBuf;
	    	
	int intVal=(int)strVal.asInteger();	
	_len = sizeof(int);
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == LONG_TYPE)
    {
	Chain strVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	long long longVal=(int)strVal.asLongLong();
	_len = sizeof(long long);
	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == BOOL_TYPE)
    {
	Chain strVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
			
	_len = sizeof(char);
	if ( strVal.asBool() )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;
	_type = BOOL_TYPE;
	return true;	
    }
    else if ( _type == VARCHAR_TYPE && t == DATETIME_TYPE)
    {
	Datetime dt;

	__dateFormatLock.readLock(DBM_LOCKTIMEOUT);
	try
	{
	    dt = Datetime(Chain((char*)_pV), __dateFormatList);
	}
	catch ( Exception e )
	{
	    __dateFormatLock.unlock();
	    throw Exception(EXLOC, Chain("Cannot cast date value"), e);   
	}
	__dateFormatLock.unlock();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
		
	_pV = _staticBuf;
	
	*(long long*)_pV = dt.asLong();	    
	_len = sizeof(long long);
	_type = DATETIME_TYPE;

	return true;	
    }
    else if ( _type == VARCHAR_TYPE && t == BIGINT_TYPE)
    {	
	// we construct big integer to check format
	BigInteger b = BigInteger( Chain((char*)_pV) );       
	_type = BIGINT_TYPE;
	return true;	
    }
    else if ( _type == VARCHAR_TYPE && t == FLOAT_TYPE)
    {	
	Chain strVal((char*)_pV);

	normFloatValue(strVal);
	
	float floatVal = strVal.asFloat();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	_type = FLOAT_TYPE;
	_len = sizeof(float);
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == DOUBLE_TYPE)
    {	
	Chain strVal((char*)_pV);
	normFloatValue(strVal);
	
	double doubleVal = strVal.asDouble();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_type = DOUBLE_TYPE;
	_len = sizeof(double);
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == DECIMAL_TYPE)
    {
	// we construct big decimal to check format
	BigDecimal decVal = BigDecimal( Chain((char*)_pV) );
	
	Chain normVal = decVal.scaleTo(d, __roundMode).toChain();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_type = DECIMAL_TYPE;
	_len = normVal.length();
	if ( _len <= STATICFIELDBUF )
	    _pV = _staticBuf;
	else
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}

	memcpy(_pV, (char*)normVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == SMALLINT_TYPE)
    {
	Chain strVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )	    
	    free(_pV);
	
	_pV = _staticBuf;
		
	short shortVal=(int)strVal.asShort();

	_type = SMALLINT_TYPE;
	_len = sizeof(short);
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == VARCHAR_TYPE && t == TINYINT_TYPE)
    {
	Chain strVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )	    
	    free(_pV);
	
	_pV = _staticBuf;
	
	char tinyVal=(char)strVal.asInteger();
	_type = TINYINT_TYPE;
	_len = sizeof(char);
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////////
    // cast bool to X //
    ////////////////////////

    else if ( _type == BOOL_TYPE && t == INT_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	int intVal = (int)boolVal;
	_type = INT_TYPE;
	_len = sizeof(int);

	memcpy(_pV, &intVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == LONG_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long  longVal = (long long)boolVal;
	_type = LONG_TYPE;
	_len = sizeof(long long);
	
	memcpy(_pV, &longVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == VARCHAR_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )    
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal;
	if ( boolVal > 0 )
	    strVal = Chain("true");
	else
	    strVal = Chain("false");

	_type = VARCHAR_TYPE;
	_len = strVal.length();
	
	memcpy(_pV, (char*)strVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == BIGINT_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain biVal;
	if ( boolVal > 0 )
	    biVal = Chain("1");
	else
	    biVal = Chain("0");
	
	_type = BIGINT_TYPE;
	_len = biVal.length();

	memcpy(_pV, (char*)biVal, _len);
	return true;
    }
    else if ( _type == BOOL_TYPE && t == FLOAT_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	float floatVal;
	if ( boolVal > 0 )
	    floatVal = 1.0;
	else
	    floatVal = 0.0;

	_type = FLOAT_TYPE;
	_len = sizeof(float);

	memcpy(_pV, &floatVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == DOUBLE_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	double doubleVal;
	if ( boolVal > 0 )
	    doubleVal = 1.0;
	else
	    doubleVal = 0.0;

	_type = DOUBLE_TYPE;
	_len = sizeof(double);

	memcpy(_pV, &doubleVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == DECIMAL_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain fixedVal;
	if ( boolVal > 0 )
	    fixedVal = Chain("1");
	else
	    fixedVal = Chain("0");

	fixedVal += Chain(".");
	for ( unsigned i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;	
    }
    else if ( _type == BOOL_TYPE && t == SMALLINT_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	short shortVal = (short)boolVal;
	_type = SMALLINT_TYPE;
	_len = sizeof(short);
	
	memcpy(_pV, &shortVal, _len);
	return true;		
    }
    else if ( _type == BOOL_TYPE && t == TINYINT_TYPE)
    {
	char boolVal;
	memcpy(&boolVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char tinyVal = (char)boolVal;
	_type = TINYINT_TYPE;
	_len = sizeof(char);
	
	memcpy(_pV, &tinyVal, _len);
	return true;		
    }
    
    ////////////////////////
    // cast datetime to X //
    ////////////////////////

    else if ( _type == DATETIME_TYPE && t == INT_TYPE)
    {
	int intVal;

	long long longVal;
	memcpy(&longVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	if ( longVal == 0 )
	{
	    Datetime dt;
	    intVal = (int)dt.asLong();
	}
	else
	{
	    intVal = (int)longVal;
	}
	
	_len = sizeof(int);
	
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == LONG_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}

	long long longVal = dateVal;
	_len = sizeof(long long);
	
	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == VARCHAR_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal;
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    strVal = dt.asChain(__dateTimeFormat);
	}
	else
	{
	    Datetime dt(dateVal);
	    strVal = dt.asChain(__dateTimeFormat);
	}
	
	_len = strVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}

	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == BOOL_TYPE)
    {
	// not supported
	return false;
    }
    else if ( _type == DATETIME_TYPE && t == BIGINT_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}
	
	Chain bival(dateVal);	
	_len = bival.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}

	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == FLOAT_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}

	Chain floatChain(dateVal);
	floatChain += Chain(__decimalPoint) + Chain("0");	
	float floatVal = floatChain.asFloat();	
	
	_len = sizeof(float);	
	_type = FLOAT_TYPE;
	memcpy(_pV, &floatVal, _len);
	return true;	
    }
    else if ( _type == DATETIME_TYPE && t == DOUBLE_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}
	Chain doubleChain(dateVal);
	doubleChain += Chain(__decimalPoint) + Chain("0");	
	double doubleVal = doubleChain.asDouble();	

	_len = sizeof(double);	
	_type = DOUBLE_TYPE;
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == DECIMAL_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}

	Chain fixedVal(dateVal);
	fixedVal += Chain(".");
	for ( unsigned i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == SMALLINT_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}
	
	short shortVal=(short)dateVal;
	_len = sizeof(short);
	
	_type = SMALLINT_TYPE;
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == DATETIME_TYPE && t == TINYINT_TYPE)
    {
	long long dateVal;
	memcpy(&dateVal, _pV, sizeof(long long));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	if ( dateVal == 0 )
	{
	    Datetime dt;
	    dateVal = dt.asLong();
	}

	char tinyVal=(char)dateVal;
	_len = sizeof(char);

	_type = TINYINT_TYPE;
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////////
    // cast bigint to X //
    ////////////////////////

    else if ( _type == BIGINT_TYPE && t == INT_TYPE)
    {
	Chain biVal((char*)_pV);
	int intVal = biVal.asInteger();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	_type = INT_TYPE;
	_len = sizeof(int);
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == BIGINT_TYPE && t == LONG_TYPE)
    {
	Chain biVal((char*)_pV);
	long long longVal = biVal.asLongLong();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

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

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char boolVal;
	if ( intVal > 0 )
	{
	    boolVal=1;
	}
	else
	{
	    boolVal=0;
	}
	
	_type = BOOL_TYPE;
	_len = sizeof(char);

	memcpy(_pV, &boolVal, _len);
	return true;
    }
    else if ( _type == BIGINT_TYPE && t == DATETIME_TYPE)
    {
	Chain biVal((char*)_pV);
	long long longVal = biVal.asLongLong();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	_type = DATETIME_TYPE;
	_len = sizeof(long long);
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == BIGINT_TYPE && t == FLOAT_TYPE)
    {	
	Chain biVal((char*)_pV);
	float floatVal = biVal.asFloat();	
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_type = FLOAT_TYPE;
	_len = sizeof(float);
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == BIGINT_TYPE && t == DOUBLE_TYPE)
    {	
	Chain biVal((char*)_pV);
	double doubleVal = biVal.asDouble();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;       

	_type = DOUBLE_TYPE;
	_len = sizeof(double);
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == BIGINT_TYPE && t == DECIMAL_TYPE)
    {
	Chain fixedVal((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	fixedVal += Chain(".");
	for ( unsigned i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;	
    }
    else if ( _type == BIGINT_TYPE && t == SMALLINT_TYPE)
    {
	Chain biVal((char*)_pV);
	short shortVal = biVal.asShort();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	_type = SMALLINT_TYPE;
	_len = sizeof(short);	
	memcpy(_pV, &shortVal, _len);
	return true;		
    }
    else if ( _type == BIGINT_TYPE && t == TINYINT_TYPE)
    {
	Chain biVal((char*)_pV);
	char tinyVal = (char)biVal.asInteger();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
		
	_pV = _staticBuf;

	_type = TINYINT_TYPE;
	_len = sizeof(char);	
	memcpy(_pV, &tinyVal, _len);
	return true;		
    }

    /////////////////////
    // cast float to X //
    /////////////////////

    else if ( _type == FLOAT_TYPE && t == INT_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	int intVal = FLOAT_TO_INT(f);
	_type = INT_TYPE;
	_len = sizeof(int);	
	
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == LONG_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long longVal = FLOAT_TO_LONG(f);
	_type = LONG_TYPE;
	_len = sizeof(long long);	

	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == VARCHAR_TYPE)
    {	
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
		
	Chain flVal( f );

	normFloatValue(flVal);
				    
	_len = flVal.length();
	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	    
	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)flVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == BOOL_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char boolVal;
	if ( f > 0.0 )
	{
	    boolVal = 1;
	}
	else
	{
	    boolVal = 0;
	}

	_type = BOOL_TYPE;
	_len = sizeof(char);	

	memcpy(_pV, &boolVal, _len);
	return true;	
    }
    else if ( _type == FLOAT_TYPE && t == DATETIME_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long dateVal = (long long)f;

	_type = DATETIME_TYPE;
	_len = sizeof(long long);	
	
	memcpy(_pV, &dateVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == BIGINT_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	int intVal = FLOAT_TO_INT(f);

	Chain biVal(intVal);
	_type = BIGINT_TYPE;
	_len = biVal.length();	
	
	memcpy(_pV, (char*)biVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == DOUBLE_TYPE)
    {	
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	double doubleVal = (double)f;
	_type = DOUBLE_TYPE;
	_len = sizeof(double);	
	
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == DECIMAL_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain fixedVal( f );
	
	denormFloatValue(fixedVal);

	unsigned long pos;
	if ( fixedVal.posStr(Chain("."), pos, 0, 1) )
	{
	    Chain normVal;
	    
	    // if precision of fixed is higher than the float value, we have to concat zero characters
	    if ( pos + d >= (unsigned)fixedVal.length() )
	    {
		normVal=fixedVal;
		unsigned long i=fixedVal.length();		
		while (i <= pos+d )
		{
		    normVal+=Chain("0");
		    i++;
		}
	    }
	    else
	    {		
		normVal = fixedVal.subChain(1, pos + d);
	    }
	    _len = normVal.length();
	
	    if ( _len > STATICFIELDBUF )
	    {
		_isLocalCopy = true;
		_pV = malloc(_len);
	    }

	    _type = DECIMAL_TYPE;
	    memcpy(_pV, (char*)normVal, _len);
	    return true;	
	}
	return false;
    }
    else if ( _type == FLOAT_TYPE && t == SMALLINT_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	short shortVal = FLOAT_TO_SHORT(f);
	_type = SMALLINT_TYPE;
	_len = sizeof(short);	
	
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == FLOAT_TYPE && t == TINYINT_TYPE)
    {
	float f;
	memcpy(&f, _pV, sizeof(float));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char tinyVal = (char)FLOAT_TO_CHAR(f);
	_type = TINYINT_TYPE;
	_len = sizeof(char);	

	memcpy(_pV, &tinyVal, _len);
	return true;
    }
    
    ////////////////////////
    // cast double to X //
    ////////////////////////

    else if ( _type == DOUBLE_TYPE && t == INT_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	int intVal = FLOAT_TO_INT(dVal);
	_type = INT_TYPE;
	_len = sizeof(int);	
	
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == LONG_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;

	long long longVal = FLOAT_TO_LONG(dVal);
	_type = LONG_TYPE;
	_len = sizeof(long long);	
	
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == VARCHAR_TYPE)
    {	
	double dVal;
	memcpy(&dVal, _pV, sizeof(dVal));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal( dVal );

	denormFloatValue(strVal);
				    
	_len = strVal.length();
	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}	    
	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == BOOL_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
		
	char boolVal;
	if ( dVal >= 0.0 )
	{
	    boolVal = 1;
	}
	else
	{
	    boolVal = 0;
	}

	_type = BOOL_TYPE;
	_len = sizeof(char);	
	
	memcpy(_pV, &boolVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == DATETIME_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;
	
	long long dateVal = (long long)dVal;
	_type = DATETIME_TYPE;
	_len = sizeof(long long);	
	
	memcpy(_pV, &dateVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == BIGINT_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	
	long long longVal = FLOAT_TO_LONG(dVal);
	Chain biVal(longVal);
	
	_type = BIGINT_TYPE;
	_len = biVal.length();
	
	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}       
	memcpy(_pV, (char*)biVal, _len);
	return true;	
    }
    else if ( _type == DOUBLE_TYPE && t == FLOAT_TYPE)
    {	
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	float fVal = (float)dVal;
	_type = FLOAT_TYPE;
	_len = sizeof(float);	
	
	memcpy(_pV, &fVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == DECIMAL_TYPE)
    {	
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	Chain fixedVal( dVal );

	denormFloatValue(fixedVal);
	
	unsigned long pos;
	if ( fixedVal.posStr(Chain("."), pos, 0, 1) )
	{
	    Chain normVal;

	    // if precision of fixed is higher than the float value, we have to concat zero characters
	    if ( pos + d >= (unsigned)fixedVal.length() )
	    {
		normVal=fixedVal;
		unsigned long i=fixedVal.length();		
		while (i <= pos+d )
		{
		    normVal+=Chain("0");
		    i++;
		}
	    }
	    else
	    {
		normVal = fixedVal.subChain(1, pos + d);
	    }
	    
	    _len = normVal.length();
	
	    if ( _len > STATICFIELDBUF )
	    {
		_isLocalCopy = true;
		_pV = malloc(_len);
	    }
	    
	    _type = DECIMAL_TYPE;
	    memcpy(_pV, (char*)normVal, _len);
	    return true;	
	}
	return false;
    }
    else if ( _type == DOUBLE_TYPE && t == SMALLINT_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	short shortVal = FLOAT_TO_SHORT(dVal);
	_type = SMALLINT_TYPE;
	_len = sizeof(short);	

	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == DOUBLE_TYPE && t == TINYINT_TYPE)
    {
	double dVal;
	memcpy(&dVal, _pV, sizeof(double));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	char tinyVal = FLOAT_TO_CHAR(dVal);
	_type = TINYINT_TYPE;
	_len = sizeof(char);	
	
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////////
    // cast decimal to X //
    ////////////////////////

    else if ( _type == DECIMAL_TYPE && t == INT_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	normFloatValue(fixedVal);
	
	// we cast from float to int
	int intVal = FLOAT_TO_INT(fixedVal.asDouble());
	
	_type = INT_TYPE;
	_len = sizeof(int);
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == LONG_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	normFloatValue(fixedVal);
	
	// we cast from double to long long
	long long longVal = FLOAT_TO_LONG(fixedVal.asDouble());
	
	_type = LONG_TYPE;
	_len = sizeof(long long);
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == VARCHAR_TYPE)
    {	
	// we construct big decimal to check format
	// BigDecimal d = BigDecimal( Chain((char*)_pV) );	
	_type = VARCHAR_TYPE;
	return true;	
    }
    else if ( _type == DECIMAL_TYPE && t == BOOL_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	normFloatValue(fixedVal);
	
	// we cast from float to char
	char boolVal = FLOAT_TO_CHAR(fixedVal.asDouble());
	if ( boolVal > 0 )
	    boolVal=1;
	else
	    boolVal=0;
       
	_type = BOOL_TYPE;
	_len = sizeof(char);
	memcpy(_pV, &boolVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == DATETIME_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	normFloatValue(fixedVal);
	
	// we cast from float to long long
	long long dateVal = (long long)FLOAT_TO_LONG(fixedVal.asDouble());

	_type = DATETIME_TYPE;
	_len = sizeof(long long);
	memcpy(_pV, &dateVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == BIGINT_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	unsigned long pos;
	if ( fixedVal.posStr(Chain("."), pos, 0, 1) )
	{
	    Chain biVal = fixedVal.subChain(1, pos-1);

	    _len = biVal.length();
	
	    if ( _len > STATICFIELDBUF )
	    {
		_isLocalCopy = true;
		_pV = malloc(_len);
	    }
	    
	    _type = BIGINT_TYPE;
	    memcpy(_pV, (char*)biVal, _len);
	    return true;
	}
	return false;
    }    
    else if ( _type == DECIMAL_TYPE && t == FLOAT_TYPE)
    {	
	Chain strVal((char*)_pV);

	normFloatValue(strVal);
	
	float floatVal = strVal.asFloat();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);
	
	_pV = _staticBuf;       

	_type = FLOAT_TYPE;
	_len = sizeof(float);
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == DOUBLE_TYPE)
    {	
	Chain strVal((char*)_pV);

	normFloatValue(strVal);
	
	double doubleVal = strVal.asDouble();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;       

	_type = DOUBLE_TYPE;
	_len = sizeof(double);
	memcpy(_pV, &doubleVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == DECIMAL_TYPE)
    {	
	_type = DECIMAL_TYPE;
	return true;	
    }
    else if ( _type == DECIMAL_TYPE && t == SMALLINT_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
		
	normFloatValue(fixedVal);
	
	// we cast from float to short
	short shortVal = FLOAT_TO_SHORT(fixedVal.asDouble());
	
	_type = SMALLINT_TYPE;
	_len = sizeof(short);
	memcpy(_pV, &shortVal, _len);
	return true;
    }
    else if ( _type == DECIMAL_TYPE && t == TINYINT_TYPE)
    {
	Chain fixedVal = Chain((char*)_pV);

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	normFloatValue(fixedVal);
	
	// we cast from float to char
	char tinyVal = FLOAT_TO_CHAR(fixedVal.asDouble());
	
	_type = TINYINT_TYPE;
	_len = sizeof(char);
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////////
    // cast smallint to X //
    ////////////////////////
    
    else if ( _type == SMALLINT_TYPE && t == INT_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	int intVal=(int)shortVal;
	_len = sizeof(int);
	
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == LONG_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
		
	long long longVal=(long long)shortVal;
	_len = sizeof(long long);

	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == VARCHAR_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal(shortVal);
	_len = strVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == BOOL_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	_len = sizeof(char);
	if ( shortVal > 0 )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;
	_type = BOOL_TYPE;
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == BIGINT_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	Chain bival(shortVal);	
	_len = bival.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == FLOAT_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));
	Chain floatChain(shortVal);
	floatChain += Chain(__decimalPoint) + Chain("0");
	float floatVal = floatChain.asFloat();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(float);
	_type = FLOAT_TYPE;
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == DOUBLE_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));
	Chain doubleChain(shortVal);
	doubleChain += Chain(__decimalPoint) + Chain("0");	
	double doubleVal = doubleChain.asDouble();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(double);	
	_type = DOUBLE_TYPE;
	memcpy(_pV, &doubleVal, _len);
	return true;	
    }
    else if ( _type == SMALLINT_TYPE && t == DECIMAL_TYPE)
    {     
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain fixedVal(shortVal);
	fixedVal += Chain(".");
	for ( unsigned i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;
    }
    else if ( _type == SMALLINT_TYPE && t == TINYINT_TYPE)
    {
	short shortVal;
	memcpy(&shortVal, _pV, sizeof(short));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	char tinyVal=(char)shortVal;	
	_len = sizeof(char);
	
	_type = TINYINT_TYPE;
	memcpy(_pV, &tinyVal, _len);
	return true;
    }

    ////////////////////////
    // cast tinyint to X //
    ////////////////////////
    
    else if ( _type == TINYINT_TYPE && t == INT_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	int intVal=(int)tinyVal;
	_len = sizeof(int);
	
	_type = INT_TYPE;
	memcpy(_pV, &intVal, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == LONG_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));
	
	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	long long longVal=(long long)tinyVal;
	_len = sizeof(long long);
	
	_type = LONG_TYPE;
	memcpy(_pV, &longVal, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == VARCHAR_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain strVal(tinyVal);
	_len = strVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = VARCHAR_TYPE;
	memcpy(_pV, (char*)strVal, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == BOOL_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(char);
	if ( tinyVal > 0 )
	    *(char*)_pV = 1;
	else
	    *(char*)_pV = 0;
	_type = BOOL_TYPE;
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == BIGINT_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain bival(tinyVal);	
	_len = bival.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = BIGINT_TYPE;
	memcpy(_pV, (char*)bival, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == FLOAT_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));
	Chain floatChain(tinyVal);
	floatChain += Chain(__decimalPoint) + Chain("0");
	float floatVal = floatChain.asFloat();

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(float);
	_type = FLOAT_TYPE;
	memcpy(_pV, &floatVal, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == DOUBLE_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));
	Chain doubleChain((int)tinyVal);
	doubleChain += Chain(__decimalPoint) + Chain("0");	
	double doubleVal = doubleChain.asDouble();	

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	_len = sizeof(double);	
	_type = DOUBLE_TYPE;
	memcpy(_pV, &doubleVal, _len);
	return true;	
    }
    else if ( _type == TINYINT_TYPE && t == DECIMAL_TYPE)
    {     
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;
	
	Chain fixedVal((int)tinyVal);
	fixedVal += Chain(".");
	for ( int i=0; i<d; i++ )
	    fixedVal += Chain("0");
	_len = fixedVal.length();

	if ( _len > STATICFIELDBUF )
	{
	    _isLocalCopy = true;
	    _pV = malloc(_len);
	}
	_type = DECIMAL_TYPE;
	memcpy(_pV, (char*)fixedVal, _len);
	return true;
    }
    else if ( _type == TINYINT_TYPE && t == SMALLINT_TYPE)
    {
	char tinyVal;
	memcpy(&tinyVal, _pV, sizeof(char));

	if ( _isLocalCopy && _pV && _pV != _staticBuf )
	    free(_pV);

	_pV = _staticBuf;

	short shortVal=(short)tinyVal;	
	_len = sizeof(short);
	
	_type = SMALLINT_TYPE;
	memcpy(_pV, &shortVal, _len);
	return true;
    }

    // otherwise not supported
    return false; 
}

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

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

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

    if (_isLocalCopy && fv._pV)
    {
	if ( _len <= STATICFIELDBUF )
	{
	    _pV = _staticBuf;
	}
	else
	{
	    _pV = malloc(_len);
	}

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

bool CegoFieldValue::operator == ( const CegoFieldValue& fv) const
{
    if ( isNull() && fv.isNull() )
	return true;
    if ( isNull() )
	return false;
    if ( fv.isNull() )
	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 ( isNull() && fv.isNull() )
	return false;
    if ( isNull() )
	return true;
    if ( fv.isNull() )
	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 ( isNull() && fv.isNull() )
	return false;
    if ( isNull() )
	return true;
    if ( fv.isNull() )
	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 ( isNull() && fv.isNull() )
	return false;
    if ( isNull() )
	return false;
    if ( fv.isNull() )
	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 ( isNull() && fv.isNull() )
	return true;
    if ( isNull() )
	return true;
    if ( fv.isNull() )
	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 ( isNull() && fv.isNull() )
	return true;
    if ( isNull() )
	return false;
    if ( fv.isNull() )
	return true;
       
    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
{
    if ( isNull() && fv.isNull() )
	return EQUAL;
    if ( isNull() )
	return LESS;
    if ( fv.isNull() )
	return MORE;
    
    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:
    {
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	if (d1 < d2)
	    return LESS;
	if ( d1 > d2)
	    return MORE;
	return EQUAL;
    }
    case LONG_TYPE:
    {
	long long l1, l2;
	memcpy(&l1, _pV, sizeof(long long));
	memcpy(&l2, fv._pV, sizeof(long long));

	if (l1 < l2)
	    return LESS;
	if ( l1 > l2)
	    return MORE;
	return EQUAL;
    }
    case VARCHAR_TYPE:
    {
	int i;

	if ( __caseSensitiveFlag == 2 )
	    i = strncasecmp((char*)_pV, (char*)fv._pV, fv._len);
	else
	    i = strncmp((char*)_pV, (char*)fv._pV, fv._len);
	
	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:
    {
	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:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

CegoFieldValue::Comparison CegoFieldValue::fastComp( CegoDataType t1, void* pV1, unsigned l1, CegoDataType t2, void* pV2, unsigned l2 )
{
    if ( ( t1 == NULL_TYPE || pV1 == 0 )
	 && ( t2 == NULL_TYPE || pV2 == 0 ) )
	return EQUAL;    
    if (  t1 == NULL_TYPE || pV1 == 0 )
	return LESS;
    if (  t2 == NULL_TYPE || pV2 == 0 )
	return MORE;

    // if types are different, we have to change to standard compare
    if ( t1 != t2 )
    {
        CegoFieldValue fv1 = CegoFieldValue(t1, pV1, l1, false);
        CegoFieldValue fv2 = CegoFieldValue(t2, pV2, l2, false);

	// we first have to try to cast to primary datatype t1
	// since this is the native btree data type ( used in CegoBTreeCursor::traceLog, fullMatch and inRange )
        if ( fv2.castTo(t1) == true )
	    return fv1.comp(fv2);

        if ( fv1.castTo(t2) == true )
            return fv1.comp( fv2 ); 
	
        throw Exception(EXLOC , "Incompatible Datatypes");
    }
    
    switch (t1)
    {
    case INT_TYPE:
    {	
	if ( *(int*)pV1 < *(int*)pV2)
	    return LESS;
	if ( *(int*)pV1 > *(int*)pV2)
	    return MORE;
	return EQUAL;	
    }
    case DATETIME_TYPE:
    {	
	if ( *(long long*)pV1 < *(long long*)pV2)
	    return LESS;
	if ( *(long long*)pV1 > *(long long*)pV2)
	    // if ( d1 > d2)
	    return MORE;
	return EQUAL;
    }
    case LONG_TYPE:
    {
	if ( *(long long*)pV1 < *(long long*)pV2)
	    return LESS;
	if ( *(long long*)pV1 > *(long long*)pV2)
	    return MORE;
	return EQUAL;
    }
    case VARCHAR_TYPE:
    {
	int i;

	if ( __caseSensitiveFlag == 2 )
	    i = strncasecmp((char*)pV1, (char*)pV2, l1);
	else
	    // i = strncmp((char*)pV1, (char*)pV2, l1);
	    i = memcmp((char*)pV1, (char*)pV2, l1 < l2 ? l1 : l2);
	
	if ( i < 0 )
	    return LESS;
	if ( i > 0 )
	    return MORE;
	return EQUAL;
    }
    case BOOL_TYPE:
    {
	char b1 = *(char*)(pV1);
	char b2 = *(char*)(pV2);

	if ( b1 < b2 )
	    return LESS;
	if ( b1 > b2 )
	    return MORE;
	return EQUAL;
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)pV1) );
	BigInteger bi2 = BigInteger( Chain((char*)pV2) );

	if ( bi1 < bi2 )
	    return LESS;
	if ( bi1 > bi2 )
	    return MORE;
	return EQUAL;
    }
    case FLOAT_TYPE:
    {
	if ( *(float*)pV1 < *(float*)pV2)
	    return LESS;
	if ( *(float*)pV1 > *(float*)pV2)
	    return MORE;
	return EQUAL;
    }
    case DOUBLE_TYPE:
    {
	if ( *(double*)pV1 < *(double*)pV2)
	    return LESS;
	if ( *(double*)pV1 > *(double*)pV2)
	    return MORE;
	return EQUAL;
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)pV1) );
	BigDecimal d2 = BigDecimal( Chain((char*)pV2) );

	if ( d1 < d2 )
	    return LESS;
	if ( d1 > d2 )
	    return MORE;
	return EQUAL;
    }
    case SMALLINT_TYPE:
    {
	if ( *(short*)pV1 < *(short*)pV2)
	    return LESS;
	if ( *(short*)pV1 > *(short*)pV2)
	    return MORE;
	return EQUAL;
    }
    case TINYINT_TYPE:
    {
	if ( *(char*)pV1 < *(char*)pV2)
	    return LESS;
	if ( *(char*)pV1 > *(char*)pV2)
	    return MORE;
	return EQUAL;
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	return ( *(int*)_pV == *(int*)fv._pV);
    }
    case DATETIME_TYPE:
    {
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	return (d1 == d2);	
    }
    case LONG_TYPE:
    {	
	return ( *(long long*)_pV == *(long long*)fv._pV);
    }
    case VARCHAR_TYPE:
    {	
	if ( __caseSensitiveFlag == 2 )
	    return ( strncasecmp((char*)_pV, (char*)fv._pV, fv._len) == 0 );
	else
	    return ( memcmp((char*)_pV, (char*)fv._pV, _len < fv._len ? _len : fv._len) == 0 );
    }
    case BOOL_TYPE:
    {
	return ( *(char*)_pV == *(char*)fv._pV);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 == bi2);
    }
    case FLOAT_TYPE:
    {
	return ( *(float*)_pV == *(float*)fv._pV);
    }
    case DOUBLE_TYPE:
    {
	return ( *(double*)_pV == *(double*)fv._pV);
    }
    case DECIMAL_TYPE:
    {	
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));	
	return (d1 == d2);
    }
    case SMALLINT_TYPE:
    {	
	return ( *(short*)_pV == *(short*)fv._pV);
    }
    case TINYINT_TYPE:
    {
	return ( *(char*)_pV == *(char*)fv._pV);
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isLess( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	return ( *(int*)_pV < *(int*)fv._pV);
    }
    case DATETIME_TYPE:
    {	
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	return (d1 < d2);
    }
    case LONG_TYPE:
    {
	return ( *(long long*)_pV < *(long long*)fv._pV);
    }
    case VARCHAR_TYPE:
    {
	if ( __caseSensitiveFlag == 2 )
	    return ( strncasecmp((char*)_pV, (char*)fv._pV, fv._len) < 0 );	
	else
	    return ( memcmp((char*)_pV, (char*)fv._pV, _len < fv._len ? _len : fv._len) < 0 );
    }
    case BOOL_TYPE:
    {
	return ( *(char*)_pV < *(char*)fv._pV);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 < bi2);
    }
    case FLOAT_TYPE:
    {
	return ( *(float*)_pV < *(float*)fv._pV);
    }
    case DOUBLE_TYPE:
    {
	return ( *(double*)_pV < *(double*)fv._pV);
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 < d2);
    }
    case SMALLINT_TYPE:
    {
	return ( *(short*)_pV < *(short*)fv._pV);
    }
    case TINYINT_TYPE:
    {
	return ( *(char*)_pV < *(char*)fv._pV);
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isMore( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	return ( *(int*)_pV > *(int*)fv._pV);
    }
    case DATETIME_TYPE:
    {	
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	return (d1 > d2);
    }
    case LONG_TYPE:
    {
	return ( *(long long*)_pV > *(long long*)fv._pV);
    }
    case VARCHAR_TYPE:
    {	
	if ( __caseSensitiveFlag == 2 )
	    return ( strncasecmp((char*)_pV, (char*)fv._pV, fv._len) > 0 );
	else
	    return ( memcmp((char*)_pV, (char*)fv._pV, _len < fv._len ? _len : fv._len) > 0 );       
    }
    case BOOL_TYPE:
    {
	return ( *(char*)_pV > *(char*)fv._pV);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 > bi2);
    }
    case FLOAT_TYPE:
    {
	return ( *(float*)_pV > *(float*)fv._pV);
    }
    case DOUBLE_TYPE:
    {
	return ( *(double*)_pV > *(double*)fv._pV);
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 > d2);
    }
    case SMALLINT_TYPE:
    {
	return ( *(short*)_pV > *(short*)fv._pV);
    }
    case TINYINT_TYPE:
    {
	return ( *(char*)_pV > *(char*)fv._pV);
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isLessEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	return ( *(int*)_pV <= *(int*)fv._pV);
    }
    case DATETIME_TYPE:
    {
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	return (d1 <= d2);
    }
    case LONG_TYPE:
    {
	return ( *(long long*)_pV <= *(long long*)fv._pV);
    }
    case VARCHAR_TYPE:
    {
	if ( __caseSensitiveFlag == 2 )
	    return ( strncasecmp((char*)_pV, (char*)fv._pV, fv._len) <= 0 );
	else
	    return ( memcmp((char*)_pV, (char*)fv._pV, _len < fv._len ? _len : fv._len) <= 0);
    }
    case BOOL_TYPE:
    {
	return ( *(char*)_pV <= *(char*)fv._pV);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 <= bi2);
    }
    case FLOAT_TYPE:
    {
	return ( *(float*)_pV <= *(float*)fv._pV);
    }
    case DOUBLE_TYPE:
    {
	return ( *(double*)_pV <= *(double*)fv._pV);
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 <= d2);
    }
    case SMALLINT_TYPE:
    {
	return ( *(short*)_pV <= *(short*)fv._pV);
    }
    case TINYINT_TYPE:
    {
	return ( *(char*)_pV <= *(char*)fv._pV);
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

bool CegoFieldValue::isMoreEqual( const CegoFieldValue& fv) const
{
    switch (_type)
    {
    case INT_TYPE:
    {
	return ( *(int*)_pV >= *(int*)fv._pV);
    }
    case DATETIME_TYPE:
    {	
	long long d1, d2;
	memcpy(&d1, _pV, sizeof(long long));
	memcpy(&d2, fv._pV, sizeof(long long));
	if ( d1 == 0 )
	{
	    Datetime dt;
	    d1 = dt.asLong();
	}
	if ( d2 == 0 )
	{
	    Datetime dt;
	    d2 = dt.asLong();
	}
	return (d1 >= d2);
    }
    case LONG_TYPE:
    {
	return ( *(long long*)_pV >= *(long long*)fv._pV);
    }
    case VARCHAR_TYPE:
    {
	if ( __caseSensitiveFlag == 2 )
	    return ( strncasecmp((char*)_pV, (char*)fv._pV, fv._len) >= 0 );
	else
	    return ( memcmp((char*)_pV, (char*)fv._pV, _len < fv._len ? _len : fv._len) >= 0 );
    }
    case BOOL_TYPE:
    {
	return ( *(char*)_pV >= *(char*)fv._pV);
    }
    case BIGINT_TYPE:
    {
	BigInteger bi1 = BigInteger( Chain((char*)_pV) );
	BigInteger bi2 = BigInteger( Chain((char*)(fv._pV) ));
	return (bi1 >= bi2);
    }
    case FLOAT_TYPE:
    {
	return ( *(float*)_pV >= *(float*)fv._pV);
    }
    case DOUBLE_TYPE:
    {	
	return ( *(double*)_pV >= *(double*)fv._pV);
    }
    case DECIMAL_TYPE:
    {
	BigDecimal d1 = BigDecimal( Chain((char*)_pV) );
	BigDecimal d2 = BigDecimal( Chain((char*)(fv._pV) ));
	return (d1 >= d2);
    }
    case SMALLINT_TYPE:
    {
	return ( *(short*)_pV >= *(short*)fv._pV);
    }
    case TINYINT_TYPE:
    {
	return ( *(char*)_pV >= *(char*)fv._pV);
    }
    default:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Unknown Type");
    }
}

CegoFieldValue operator + ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{
    if ( fv1._type == NULL_TYPE ) 
    {
	return fv2;
    }
    
    if ( fv2._type == NULL_TYPE )
    {
	return fv1;
    }

    if (fv1._type != fv2._type)
    {
	if ( fv1._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv2;
	    if ( fvc.castTo(fv1.getType(), fv1.getDim()) == true )
		return fv1.add(fvc);
	}
	else if ( fv2._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv1;
	    if ( fvc.castTo(fv2.getType(), fv2.getDim()) == true )
		return fvc.add(fv2);	   
	}
	else
	{
	    if ( fv1.getLength() > fv2.getLength() )
	    {
		CegoFieldValue fvc = fv2;
		if ( fvc.castTo(fv1.getType()) == true )
		    return fv1.add(fvc);
	    }
	    else
	    {
		CegoFieldValue fvc = fv1;
		if ( fvc.castTo(fv2.getType()) == true )
		    return fvc.add(fv2);
	    }
	}	
	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 long l1, l2;
	memcpy(&l1, _pV, sizeof(long long));
	memcpy(&l2, fv2._pV, sizeof(long long));
	long long* pL = new long long;
	*pL = l1 + l2;
	CegoFieldValue fv3(_type, pL, sizeof(long long), true);
	return fv3;
    }
    case VARCHAR_TYPE:
    {
	Chain s1 = Chain((char*)(_pV), _len - 1);
	Chain s2 = Chain((char*)(fv2._pV), fv2._len - 1);
	Chain m =  s1 + s2;
	CegoFieldValue fv3(_type, m);
	return fv3;
    }
    case BOOL_TYPE:
    case DATETIME_TYPE:
    {
	throw Exception(EXLOC, "Operation not supported for datatype");
    }
    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:
    {
	Chain f1((char*)(_pV));
	Chain f2((char*)(fv2._pV));
	
	unsigned long pos1;
	if ( f1.posStr(Chain("."), pos1) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f1 + Chain(">"));

	unsigned dim1 =  _len - pos1 - 1;

	unsigned long pos2;	
	if ( f2.posStr(Chain("."), pos2) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f2 + Chain(">"));

	unsigned dim2 = fv2._len - pos2 - 1;

	unsigned fixDim = dim1 > dim2 ? dim1 : dim2;
	
	BigDecimal d1 = BigDecimal(f1);
	BigDecimal d2 =  BigDecimal(f2);
	BigDecimal d3 = d1.add(d2);
	
	Chain f3 = d3.toChain();
	unsigned long pos3;
	if ( f3.posStr(Chain("."), pos3) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f3 + Chain(">"));

	unsigned long i = f3.length() - pos3 -1;

	while ( i < fixDim )
	{
	    f3 = f3 + Chain("0");
	    i++;
	}
	
	CegoFieldValue fv3(_type, f3);
	
	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:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	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)
    {
	if ( fv1._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv2;
	    if ( fvc.castTo(fv1.getType(), fv1.getDim()) == true )
		return fv1.sub(fvc);
	}
	else if ( fv2._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv1;
	    if ( fvc.castTo(fv2.getType(), fv2.getDim()) == true )
		return fvc.sub(fv2);	    
	}
	else
	{
	    if ( fv1.getLength() > fv2.getLength() )
	    {	    
		CegoFieldValue fvc = fv2;
		if ( fvc.castTo(fv1.getType()) == true )
		    return fv1.sub(fvc);
	    }
	    else
	    {
		CegoFieldValue fvc = fv1;
		if ( fvc.castTo(fv2.getType()) == true )
		    return fvc.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 long l1, l2;
	memcpy(&l1, _pV, sizeof(long long));
	memcpy(&l2, fv2._pV, sizeof(long long));
	long long* pL = new long long;
	*pL = l1 - l2;
	CegoFieldValue fv3(_type, pL, sizeof(long 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:
    {	
	Chain f1((char*)(_pV));
	Chain f2((char*)(fv2._pV));

	unsigned long pos1;
	if ( f1.posStr(Chain("."), pos1) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f1 + Chain(">"));

	unsigned dim1 =  _len - pos1 - 1;

	unsigned long pos2;
	if ( f2.posStr(Chain("."), pos2) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f2 + Chain(">"));

	unsigned dim2 = fv2._len - pos2 - 1;

	unsigned fixDim = dim1 > dim2 ? dim1 : dim2;

	BigDecimal d1 = BigDecimal(f1);
	BigDecimal d2 =  BigDecimal(f2);
	BigDecimal d3 = d1.sub(d2);

	Chain f3 = d3.toChain();
	unsigned long pos3;
	if ( f3.posStr(Chain("."), pos3) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f3 + Chain(">"));

	unsigned i = f3.length() - pos3 -1;

	while ( i < fixDim )
	{
	    f3 = f3 + Chain("0");
	    i++;
	}
	
	CegoFieldValue fv3(_type, f3);

	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:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:
	throw Exception(EXLOC, "Invalid type");	
    }
}

CegoFieldValue operator * ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{
    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Operator * not valid on null value");
    }
    if (fv1._type != fv2._type)
    {
	if ( fv1._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv2;
	    if ( fvc.castTo(fv1.getType(), fv1.getDim()) == true )
		return fv1.mul(fvc);
	}
	else if ( fv2._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv1;
	    if ( fvc.castTo(fv2.getType(), fv2.getDim()) == true )
		return fvc.mul(fv2);	    
	}
	else
	{	    
	    if ( fv1.getLength() > fv2.getLength() )
	    {
		CegoFieldValue fvc = fv2;
		if ( fvc.castTo(fv1.getType()) == true )
		{
		    // cout << "1 Case to " << fv1.mul(fvc) << endl; 
		    return fv1.mul(fvc);
		}
	    }
	    else
	    {
		CegoFieldValue fvc = fv1;
		if ( fvc.castTo(fv2.getType()) == true )
		{
		    // cout << "2 Case to " << fvc.mul(fv2) << endl; 
		    return fvc.mul(fv2);
		}
	    }
	}
	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 long l1, l2;
	memcpy(&l1, _pV, sizeof(long long));
	memcpy(&l2, fv2._pV, sizeof(long long));
	long long* pL = new long long;
	*pL = l1 * l2;
	CegoFieldValue fv3(_type, pL, sizeof(long long), true);
	return fv3;
    }
    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:
    {
	Chain f1((char*)(_pV));
	Chain f2((char*)(fv2._pV));
	       	
	BigDecimal d1 = BigDecimal(f1);
	BigDecimal d2 =  BigDecimal(f2);

	int decDim = d1.getScale() > d2.getScale() ? d1.getScale() : d2.getScale();
	
	BigDecimal d3 = d1.mul(d2).scaleTo(decDim, __roundMode);

	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:
    // case VARCHAR_TYPE:
    // case BOOL_TYPE:
    // case DATETIME_TYPE:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:	
	throw Exception(EXLOC, "Invalid type");
    }
}

CegoFieldValue operator / ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{
    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Operator / not valid on null value");
    }
    if (fv1._type != fv2._type)
    {
	if ( fv1._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv2;
	    if ( fvc.castTo(fv1.getType(), fv1.getDim()) == true )
		return fv1.div(fvc);
	}
	else if ( fv2._type == DECIMAL_TYPE )
	{
	    CegoFieldValue fvc = fv1;
	    if ( fvc.castTo(fv2.getType(), fv2.getDim()) == true )
		return fvc.div(fv2);	    
	}
	else
	{
	    if ( fv1.getLength() > fv2.getLength() )
	    {
		CegoFieldValue fvc = fv2;
		if ( fvc.castTo(fv1.getType()) == true )
		    return fv1.div(fvc);
	    }
	    else
	    {
		CegoFieldValue fvc = fv1;
		if ( fvc.castTo(fv2.getType()) == true )
		    return fvc.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 long l1, l2;
	    memcpy(&l1, _pV, sizeof(long long));
	    memcpy(&l2, fv2._pV, sizeof(long long));		   
	    long long* pL = new long long;

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

	    *pL = l1 / l2;
	    CegoFieldValue fv3(_type, pL, sizeof( long long), true);
	    return fv3;
	}
	else
	{
	    CegoFieldValue fv3(_type, 0, sizeof(long long), true);
	    return fv3;	    
	}
    }
    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:
    {
	Chain f1((char*)(_pV));
	Chain f2((char*)(fv2._pV));
	
	BigDecimal d1 = BigDecimal(f1);
	BigDecimal d2 =  BigDecimal(f2);

	unsigned decDim = d1.getScale() > d2.getScale() ? d1.getScale() : d2.getScale();
			
	BigDecimal d3 = d1.div(d2).scaleTo(decDim, __roundMode);

	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:
    // case VARCHAR_TYPE:
    // case BOOL_TYPE:
    // case DATETIME_TYPE:
    // case BLOB_TYPE:
    // case CLOB_TYPE:
    // case NULL_TYPE:
    // case PAGEID_TYPE:	
	throw Exception(EXLOC, "Invalid type");	
    }
}

CegoFieldValue operator | ( const CegoFieldValue& fv1, const CegoFieldValue& fv2 )
{
    if ( fv1._type == NULL_TYPE || fv2._type == NULL_TYPE)
    {
	throw Exception(EXLOC , "Operator | not valid 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 long l1, l2;
	memcpy(&l1, _pV, sizeof(long long));
	memcpy(&l2, fv2._pV, sizeof(long long));
	CegoFieldValue fv3(VARCHAR_TYPE, Chain(l1) + Chain(l2) ) ;
	return fv3;
    }
    case VARCHAR_TYPE:
    {
	Chain c1 = Chain((char*)(_pV), _len - 1);
	Chain c2 = Chain((char*)(fv2._pV), fv2._len - 1);
	CegoFieldValue fv3(VARCHAR_TYPE, c1 + c2 ) ;
	return fv3;
    }
    case BOOL_TYPE:
    {
	Chain c1 = Chain((char*)(_pV));
	Chain c2 = Chain((char*)(fv2._pV));
	CegoFieldValue fv3(VARCHAR_TYPE, c1 + c2 ) ;
	return fv3;	
    }
    default:
    /* case DECIMAL_TYPE:
    case BLOB_TYPE:
    case CLOB_TYPE:
    case SMALLINT_TYPE:
    case TINYINT_TYPE:
    case NULL_TYPE:
    case DATETIME_TYPE:
    case BIGINT_TYPE:
    case FLOAT_TYPE:
    case DOUBLE_TYPE:
    case PAGEID_TYPE: */
	throw Exception(EXLOC, "Invalid 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 long l;
	memcpy(&l, _pV, sizeof(long long));
	long long* pL = new long long;
	*pL = (-1) * l;
	CegoFieldValue fv3(_type, pL, sizeof(long 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:
    {
	Chain f((char*)(_pV));

	unsigned long pos;
	if ( f.posStr(Chain("."), pos) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + f + Chain(">"));

	int dim =  _len - pos - 1;

	BigDecimal bd = BigDecimal( Chain((char*)(_pV)) );
	bd.negate();

	Chain fn = bd.toChain();
	
	if ( fn.posStr(Chain("."), pos) == false )
	    throw Exception(EXLOC, Chain("Invalid decimal value <") + fn + Chain(">"));

	unsigned i = fn.length() - pos -1;

	while ( i < dim )
	{
	    fn = fn + Chain("0");
	    i++;
	}
	
	CegoFieldValue fv(_type, fn);
	return fv;
    }
    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;
    }
    default:
    /*
    case VARCHAR_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    case BLOB_TYPE:
    case CLOB_TYPE:
    case NULL_TYPE:
    case PAGEID_TYPE:
    */
	throw Exception(EXLOC, "Invalid type");
    }
}

void CegoFieldValue::normFloatValue(Chain& floatVal) const
{
    if ( __decimalPoint == ',' )
    {
	Chain normFloat;
	if ( floatVal.replace(".", ",", normFloat) )
	{
	    floatVal = normFloat;
	}
    }
}

void CegoFieldValue::denormFloatValue(Chain& floatVal) const
{
    if ( __decimalPoint == ',' )
    {
	Chain normFloat;
	if ( floatVal.replace(",", ".", normFloat) )
	{
	    floatVal = normFloat;
	}
    }
}

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

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

CegoFieldValue CegoFieldValue::getLocalCopy() const
{
    CegoFieldValue lc;
    lc._type = _type;
    lc._len = _len;

    if ( lc._len <= STATICFIELDBUF )
        lc._pV = lc._staticBuf;
    else
        lc._pV = malloc(lc._len);

    memcpy(lc._pV, _pV, _len);
    lc._isLocalCopy = true;
    return lc;
}

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

unsigned CegoFieldValue::size() const
{
    return sizeof(CegoDataType) + sizeof(void*) + _len + sizeof(bool) + STATICFIELDBUF;
}

Chain CegoFieldValue::toChain() const
{
    Chain s;

    if ( _type == NULL_TYPE || _type == BLOB_TYPE || _type == CLOB_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 long l;
	    memcpy(&l, _pV, sizeof(long long));
	    s = Chain("(long)") + Chain( l );
	    break;
	}   
	case VARCHAR_TYPE:	    
	{   
	    Chain val((char*)_pV, _len - 1);

	    // 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 > 0 )
		s = Chain("true");
	    else
		s = Chain("false");
	    break;
	}    
	case DATETIME_TYPE:
	{
	    long long l;
	    memcpy(&l, _pV, sizeof(long long));
	    if ( l == 0 )
	    {
		s = Chain("sysdate");
	    }
	    else
	    {
		Datetime dt ( l );
		// s = Chain("scandate('") + __dateTimeFormat + Chain("','") + dt.asChain(__dateTimeFormat) + Chain("')");
		// we just provide the datetime string value with cast operator in the appropriate format
		s = Chain("(datetime)'") + dt.asChain(__dateTimeFormat) + Chain("')");
	    }
	    break;
	}
	case BIGINT_TYPE:
	{
	    BigInteger bi( Chain((char*)_pV) );
	    s =  Chain("(bigint)") +  bi.toChain();
	    break;
	}
	case DECIMAL_TYPE:
	{	    
	    Chain f = Chain((char*)(_pV));
	    s = Chain("(decimal)") + f;
	    break;
	}
	case FLOAT_TYPE:
	{
	    float f;
	    memcpy(&f, _pV, sizeof(float));
	    
	    Chain normFloat(f);
	    denormFloatValue(normFloat);
	    s=normFloat;
	    
	    break;
	}
	case DOUBLE_TYPE:
	{
	    double d;
	    memcpy(&d, _pV, sizeof(double));

	    Chain normDouble(d);
	    denormFloatValue(normDouble);	   
	    s = Chain("(double)") + normDouble;
	    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 CLOB_TYPE:
	case NULL_TYPE:
	{
	    // already handled
	    break;
	}
	case PAGEID_TYPE:
	{
	    PageIdType p;
	    memcpy(&p, _pV, sizeof(PageIdType));
	    s = Chain( p );
	    break;
	}
	}
    }
    return s;
}

Chain CegoFieldValue::dbFormat(CegoDatabaseFormater *pForm) const
{
    return pForm->formatFieldValue(_type, _pV, _len);
}

Chain CegoFieldValue::typeToChain() const
{
    Chain s;

    switch ( _type )
    {
    case NULL_TYPE:
    {
	s = Chain("null");
	break;
    }
    case VARCHAR_TYPE:
    case BIGINT_TYPE:
    {
	s = CEGO_TYPE_MAP[_type] + Chain("(") + Chain(_len) + Chain(")");
	break;
    }
    case DECIMAL_TYPE:
    {
	s = CEGO_TYPE_MAP[_type] + Chain("(") + Chain(_len) + Chain(",") + Chain(getDim()) + Chain(")");
	break;
    }
	
    case INT_TYPE:
    case FLOAT_TYPE:
    case DOUBLE_TYPE:
    case SMALLINT_TYPE:
    case TINYINT_TYPE:
    case LONG_TYPE:
    case BOOL_TYPE:
    case DATETIME_TYPE:
    case BLOB_TYPE:
    case CLOB_TYPE:
    case PAGEID_TYPE:
    {
	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 long l;
	    memcpy(&l, _pV, sizeof(long long));
	    s = Chain( l );
	    break;
	}   
	case VARCHAR_TYPE:
	{	    
	    s = Chain((char*)_pV, _len - 1);
	    break;
	}
	case BIGINT_TYPE:
	case DECIMAL_TYPE:
	{   
	    s = Chain((char*)_pV);
	    break;
	}   
	case BOOL_TYPE:
	{   
	    char b = *(char*)(_pV);
	    if ( b > 0 )
		s = Chain("true");
	    else
		s = Chain("false");
	    break;
	}    
	case DATETIME_TYPE:
	{
	    long long l;
	    memcpy(&l, _pV, sizeof(long long));

	    if ( l == 0 )
	    {
		if ( doEval )
		{
		    Datetime dt;
		    s = dt.asChain(__dateTimeFormat);
		}
		else
		{
		    s = Chain("sysdate");
		}
	    }
	    else
	    {
		Datetime dt(l);
		s = dt.asChain(__dateTimeFormat);
	    }
	    break;
	}
	case FLOAT_TYPE:
	{
	    float f;
	    memcpy(&f, _pV, sizeof(float));

	    Chain normFloat(f);
	    denormFloatValue(normFloat);
	    s=normFloat;
	    break;
	}
	case DOUBLE_TYPE:
	{
	    double doubleVal;
	    memcpy(&doubleVal, _pV, sizeof(double));

	    Chain normDouble(doubleVal);
	    denormFloatValue(normDouble);
	    s=normDouble;
	    break;
	}
	case SMALLINT_TYPE:
	{
	    short st;
	    memcpy(&st, _pV, sizeof(short));
	    s = Chain( st );
	    break;
	}
	case TINYINT_TYPE:
	{
	    char c;
	    memcpy(&c, _pV, sizeof(char));
	    s = Chain( (int)c );
	    break;
	}
	case BLOB_TYPE:
	case CLOB_TYPE:
	{
	    PageIdType p;
	    memcpy(&p, _pV, sizeof(PageIdType));

	    s = Chain("[") + Chain(p) + Chain("]");
	    break;
	}
	case NULL_TYPE:
	{
	    // already handled
	    break;
	}
	case PAGEID_TYPE:
	{
	    PageIdType p;
	    memcpy(&p, _pV, sizeof(PageIdType));
	    s = Chain( p );
	    break;
	}   	
	}
    }
    return s;
}

int CegoFieldValue::asInteger() const
{
    CegoFieldValue fv = *this;

    if ( fv.castTo(INT_TYPE) == false )
	throw Exception(EXLOC, Chain("Cannot get integer value"));

    // in case of null value, we map value to zero
    if ( _pV == 0 )
	return 0;
    
    int i;
    memcpy(&i, fv.getValue(), sizeof(int));
    return i;
}

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

    if ( fv.castTo(LONG_TYPE) == false )
	throw Exception(EXLOC, Chain("Cannot get long value"));

    // in case of null value, we map value to zero
    if ( _pV == 0 )
	return 0;

    long long l;
    memcpy(&l, fv.getValue(), sizeof(long long));
    return l;
}

bool CegoFieldValue::asBool() const
{   
    if ( _type == BOOL_TYPE )
	return ( *(char*)_pV == 1);
    else
    {
	// in case of null value, we return false
	if ( _pV == 0 )
	    return false;
	
	CegoFieldValue fv = *this;

	if ( fv.castTo(BOOL_TYPE) == false )
	    throw Exception(EXLOC, Chain("Cannot cast to bool"));
		
	return fv.asBool();
    }
}

unsigned CegoFieldValue::usedMemory() const
{
    unsigned s = sizeof(CegoFieldValue);
    if ( _len > STATICFIELDBUF )
	s += _len;
    return s;
}

void CegoFieldValue::setup()
{
    if ( _type ==  DATETIME_TYPE )
    {
	long long l;
	memcpy(&l, _pV, sizeof(long long));
	if ( l == 0 && __recoveryTS > 0 )
	{
	    memcpy(_pV, &__recoveryTS, sizeof(long long));
	}
    }
}

void CegoFieldValue::encode(char *buf) const
{    
    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 long));
	pE = pE + sizeof(long long);
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_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(long long));
	pE = pE + sizeof(long long);
	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:
    case CLOB_TYPE:
    {   
	memcpy(pE, _pV, sizeof(PageIdType));
	pE = pE + sizeof(PageIdType);
	break;
    }   
    case NULL_TYPE:
    {
	break;
    }
    case PAGEID_TYPE:
    {
	memcpy(pE, _pV, sizeof(PageIdType));
	pE = pE + sizeof(PageIdType);
	break;	
    }
    }
}

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

    switch (_type )
    {
    case INT_TYPE:
    {
	_len = sizeof(int);
	_pV = _staticBuf;	
	memcpy(_pV, pE, sizeof(int));
	pE = pE + sizeof(int);
	break;
    }   
    case LONG_TYPE:
    {
	_len = sizeof(long long);
	_pV = _staticBuf;
	memcpy(_pV, pE, _len);
	pE = pE + _len;
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    {   
	memcpy(&_len, pE, sizeof(int));
	pE = pE + sizeof(int);

	if ( _len <= STATICFIELDBUF )
	    _pV = _staticBuf;
	else
	    _pV = malloc(_len);
      
	memcpy(_pV, pE, _len);
	pE = pE + _len;
	break;
    }   
    case BOOL_TYPE:
    {   
	_len = sizeof(char);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }    
    case DATETIME_TYPE:
    {
	_len = sizeof(long long);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case FLOAT_TYPE:
    {
	_len = sizeof(float);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case DOUBLE_TYPE:
    {
	_len = sizeof(double);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case SMALLINT_TYPE:
    {
	_len = sizeof(short);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case TINYINT_TYPE:
    {
	_len = sizeof(char);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    case BLOB_TYPE:
    case CLOB_TYPE:
    {
	_len = sizeof(PageIdType);
	_pV = _staticBuf;
	memcpy(_pV, pE, sizeof(PageIdType));
	pE = pE + sizeof(PageIdType);
	break;
    }   
    case NULL_TYPE:
    {
	_pV = 0;
	_len = 0;
	break;
    }
    case PAGEID_TYPE:
    {
    	_len = sizeof(PageIdType);
	_pV = _staticBuf;
	memcpy(_pV, pE,  _len);
	pE = pE + _len;
	break;
    }
    }
}

unsigned CegoFieldValue::getEncodingLength() const
{
    unsigned len = 0;
    
    len += sizeof(CegoDataType);

    switch (_type )
    {
    case INT_TYPE:
    {
	len += sizeof(int);
	break;
    }   
    case LONG_TYPE:
    {
	len += sizeof(long long);
	break;
    }
    case VARCHAR_TYPE:	    
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    {   	
	len += _len + sizeof(int);
	break;
    }   
    case BOOL_TYPE:
    {   
	len += 1;
	break;
    }    
    case DATETIME_TYPE:
    {
	len += sizeof(long long);
	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:
    case CLOB_TYPE:
    {
	len += sizeof(PageIdType);
	break;
    }   
    case NULL_TYPE:
    {
	break;
    }
    case PAGEID_TYPE:
    {
	len += sizeof(PageIdType);
	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 long l;
	memcpy(&l, fv._pV, sizeof(long long));
	s << l;
	break;
    }
    case VARCHAR_TYPE:
    {
	s <<  Chain((char*)fv._pV, fv._len - 1);
	break;
    }
    case BOOL_TYPE:
    {
	char b = *(char*)(fv._pV);
	if ( b > 0 )
	    s << "true";
	else
	    s << "false";
	break;
    }
    case DATETIME_TYPE:
    {
	long long l;
	memcpy(&l, fv._pV, sizeof(long long));
	Datetime dt ( l );
	s << dt.asChain();
	break;
    }
    case BIGINT_TYPE:
    {
	BigInteger bi((char*)(fv._pV));
	s << bi.toChain();
	break;	
    }
    case DECIMAL_TYPE:
    {
	Chain f = Chain((char*)(fv._pV));
	s <<  Chain("(decimal)") << f;
	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:
    case CLOB_TYPE:
    {
	s << fv.valAsChain();
	break;
    }
    case PAGEID_TYPE:
    {
	PageIdType p;
	memcpy(&p, fv._pV, sizeof(PageIdType));
	s << p;
	break;
    }
    case NULL_TYPE:
    {
	s << "null";
    }
    }
    return s;
}
