///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoAttrComp.cc
// ---------------
// Cego database table attribute comparison description
//      
// Design and Implementation by Bjoern Lemke
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// IMPLEMENTATION MODULE
//
// Class: CegoAttrComp
//
// Description: Attribute comparison utility class
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// CEGO INCLUDES
#include "CegoAttrComp.h"
#include "CegoQueryHelper.h"

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

CegoAttrComp::CegoAttrComp()
{
    _compMode = UNDEF;
    _pMatcher = 0;
    _pos=0;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName)
{
    _tableName = tableName;
    _attrName = attrName;
    _compMode = UNDEF;
    _pMatcher = 0;
    _pos=0;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, CegoComparison comp, const CegoFieldValue& fv)
{
    _tableName = tableName;
    _attrName = attrName;
    _comp = comp;
    _fv = fv;
    _compMode = VAL;
    _isSetup = false;
    _pMatcher = 0;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, CegoComparison comp, const CegoAttrDesc& attrDesc)
{
    _tableName = tableName;
    _attrName = attrName;
    _comp = comp;
    _attrDesc = attrDesc;
    _compMode = ATTR;
    _pMatcher = 0;
    _isSetup = false;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, const CegoFieldValue& fv, const CegoFieldValue& fv2)
{
    _tableName = tableName;
    _attrName = attrName;
    _fv = fv;
    _fv2 = fv2;
    _compMode = BTWN;
    _btwnMode = VALUE2VALUE;
    _pMatcher = 0;
    _isSetup = true;
    _isSetup2 = true;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, const CegoAttrDesc& attrDesc, const CegoFieldValue& fv2)
{
    _tableName = tableName;
    _attrName = attrName;
    _attrDesc = attrDesc;
    _fv2 = fv2;
    _compMode = BTWN;
    _btwnMode = ATTR2VALUE;
    _pMatcher = 0;
    _isSetup = false;
    _isSetup2 = true;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, const CegoFieldValue& fv, const CegoAttrDesc& attrDesc2)
{
    _tableName = tableName;
    _attrName = attrName;
    _fv = fv;
    _attrDesc2 = attrDesc2;
    _compMode = BTWN;
    _btwnMode = VALUE2ATTR;
    _pMatcher = 0;
    _isSetup = true;
    _isSetup2 = false;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;    
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, const CegoAttrDesc& attrDesc, const CegoAttrDesc& attrDesc2)
{
    _tableName = tableName;
    _attrName = attrName;
    _attrDesc = attrDesc;
    _attrDesc2 = attrDesc2;
    _compMode = BTWN;
    _btwnMode = ATTR2ATTR;
    _pMatcher = 0;
    _isSetup = false;
    _isSetup2 = false;
    _pos=0;
    _isParentSetup = false;
    _posSetup=false;
}

CegoAttrComp::CegoAttrComp(const Chain& tableName, const Chain& attrName, const Chain& pattern, bool isNot, bool isCaseSensitive)
{
    _tableName = tableName;
    _attrName = attrName;
    _pattern = pattern;
    
    if ( ! isNot && isCaseSensitive)
	_compMode = ISLIKE;
    else if ( isNot && isCaseSensitive)
	_compMode = ISNOTLIKE;
    else if ( ! isNot && ! isCaseSensitive)
	_compMode = ISNCLIKE;
    else if ( isNot && ! isCaseSensitive)
	_compMode = ISNOTNCLIKE;
    
    _pMatcher = 0;
    _pos=0;
}

CegoAttrComp::~CegoAttrComp()
{
    if ( _pMatcher )
	delete _pMatcher;
}

CegoAttrComp::CompMode CegoAttrComp::getCompMode() const
{
    return _compMode;
}

unsigned CegoAttrComp::getPos() const
{
    return _pos;
}

void CegoAttrComp::setPos(unsigned pos)
{
    _pos = pos;
}

void CegoAttrComp::setTableName(const Chain& tableName)
{
    _tableName = tableName;
}

const Chain& CegoAttrComp::getTableName() const
{
    return _tableName;
}

void CegoAttrComp::setAttrName(const Chain& attrName)
{
    _attrName = attrName;
}

const Chain& CegoAttrComp::getAttrName() const
{
    return _attrName;
}

CegoComparison CegoAttrComp::getComparison() const
{
    return _comp;
}

void CegoAttrComp::setComparison(CegoComparison comp)
{
    _comp = comp;
}

void CegoAttrComp::setFieldValue(const CegoFieldValue& fv)
{
    _fv = fv;
}

void CegoAttrComp::setFieldValue2(const CegoFieldValue& fv)
{
    _fv2 = fv;
}

const CegoFieldValue& CegoAttrComp::getFieldValue() const
{
    return _fv;
}

const CegoFieldValue& CegoAttrComp::getFieldValue2() const
{
    return _fv2;
}

void CegoAttrComp::setAttrDesc(const CegoAttrDesc& attrDesc)
{
    _attrDesc = attrDesc;
}

const CegoAttrDesc& CegoAttrComp::getAttrDesc() const
{
    return _attrDesc;
}

void CegoAttrComp::setAttrDesc2(const CegoAttrDesc& attrDesc)
{
    _attrDesc2 = attrDesc;
}

const CegoAttrDesc& CegoAttrComp::getAttrDesc2() const
{
    return _attrDesc2;
}

bool CegoAttrComp::isNullComp() const
{
    return ( _compMode == VAL && _fv.isNull() );
}

bool CegoAttrComp::isSetup()
{
    if ( _compMode == ATTR )
	return _isSetup;
    if ( _compMode == BTWN )
	return _isSetup && _isSetup2;
    // in any other case, not relevant
    return true;
}

const Chain& CegoAttrComp::getPattern() const
{
    return _pattern;
}

Matcher* CegoAttrComp::getMatcher()
{
    if ( _pMatcher == 0)
    {
	Chain regexPattern;
	
	if ( _compMode == ISLIKE
	     || _compMode == ISNOTLIKE )	
	    regexPattern = CegoQueryHelper::sql2Regex(_pattern);
	else
	    regexPattern = CegoQueryHelper::sql2Regex(_pattern.toLower());
	
	_pMatcher = new Matcher(regexPattern);
	_pMatcher->prepare();	
    }
    return _pMatcher;
}

void CegoAttrComp::reset()
{
    if ( _compMode == ATTR )
	_isSetup=false;
    else if ( _compMode == BTWN )
    {
	if ( _btwnMode == VALUE2VALUE )
	{
	    _isSetup=true;
	    _isSetup2=true;
	}
	else if ( _btwnMode == VALUE2ATTR )
	{
	    _isSetup=true;
	    _isSetup2=false;
	}
	else if ( _btwnMode == ATTR2VALUE )
	{
	    _isSetup=false;
	    _isSetup2=true;
	}
	else if ( _btwnMode == ATTR2ATTR )
	{
	    _isSetup=false;
	    _isSetup2=false;
	}
    }
}

bool CegoAttrComp::setup(const ListT<CegoField>& fl)
{
    if ( _compMode == ATTR )
    {
	CegoField* pF = fl.First();
	while ( pF && _isSetup == false )
	{	
	    if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
		 && _attrDesc.getAttrName() == pF->getAttrName() )
	    {
		_isSetup=true;
		_fv = pF->getValue();
	    }
	    pF = fl.Next();
	}
	return _isSetup;
    }
    else if ( _compMode == BTWN )
    {
	CegoField* pF = fl.First();
	while ( pF && _isSetup == false )
	{	
	    if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
		 && _attrDesc.getAttrName() == pF->getAttrName() )
	    {
		_isSetup=true;
		_fv = pF->getValue();
	    }
	    pF = fl.Next();
	}
	pF = fl.First();
	while ( pF && _isSetup2 == false )
	{	
	    if ( ( _attrDesc2.getTableName() == pF->getTableName() || _attrDesc2.getTableName()== pF->getTableAlias() )
		 && _attrDesc2.getAttrName() == pF->getAttrName() )
	    {
		_isSetup2=true;
		_fv2 = pF->getValue();
	    }
	    pF = fl.Next();
	}
	return _isSetup && _isSetup2;
    }
    else
    {
	throw Exception(EXLOC, Chain("Cannot setup attribute comparison"));
    }
}

bool CegoAttrComp::setup(ListT<CegoField>** pJoinBuf, unsigned offset)
{
    unsigned i = offset;

    if ( _compMode == ATTR )
    {
	if ( _posSetup )
        {
	    _fv = (*pJoinBuf[i + _xpos-1])[_ypos-1].getValue();
	    _isSetup = true;
        }
        else
        {
	    _xpos=0;
	    while ( pJoinBuf[i] && _isSetup == false )
	    {
		_ypos=0;
		CegoField* pF = pJoinBuf[i]->First();
		while (pF && _isSetup == false)
		{	
		    if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
			 && _attrDesc.getAttrName() == pF->getAttrName() )
		    {
			_isSetup = true;
			_posSetup = true;
			_fv = pF->getValue();
		    }
		    pF = pJoinBuf[i]->Next();
		    _ypos++;
		}
		i++;
		_xpos++;
	    }
	}
	return _isSetup;
    }
    else if ( _compMode == BTWN )
    {	
	if ( _posSetup )
        {
	    if ( _btwnMode == ATTR2VALUE || _btwnMode == ATTR2ATTR )
	    {
		_fv = (*pJoinBuf[i + _xpos-1])[_ypos-1].getValue();
		_isSetup = true;
	    }
	    if ( _btwnMode == VALUE2ATTR || _btwnMode == ATTR2ATTR )
	    {
		_fv2 = (*pJoinBuf[i + _xpos2-1])[_ypos2-1].getValue();
		_isSetup2 = true;
	    }
        }
	else
	{
	    // we start with value 1, since setup condition interferes
	    _xpos=1;
	    _xpos2=1;
	    
	    while ( pJoinBuf[i] && ( _isSetup == false || _isSetup2 == false ) )
	    {
		_ypos=0;
		CegoField* pF = pJoinBuf[i]->First();
		while (pF && _isSetup == false)
		{
		    if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
			 && _attrDesc.getAttrName() == pF->getAttrName() )
		    {
			_isSetup = true;		    
			_fv = pF->getValue();
		    }
		    pF = pJoinBuf[i]->Next();
		    _ypos++;
		}
		_ypos2=0;
		pF = pJoinBuf[i]->First();
		while (pF && _isSetup2 == false)
		{
		    if ( ( _attrDesc2.getTableName() == pF->getTableName() || _attrDesc2.getTableName()== pF->getTableAlias() )
			 && _attrDesc2.getAttrName() == pF->getAttrName() )
		    {
			_isSetup2 = true;		    
			_fv2 = pF->getValue();
		    }
		    pF = pJoinBuf[i]->Next();
		    _ypos2++;
		}
		i++;
		
		if ( _isSetup == false )
		    _xpos++;
		if ( _isSetup2 == false )
		    _xpos2++;		
	    }	    
	    _posSetup = _isSetup && _isSetup2;
	}	
	return _posSetup;
    }
    else
    {
	throw Exception(EXLOC, Chain("Cannot setup attribute comparison"));
    }
}

CegoAttrComp& CegoAttrComp::operator = ( const CegoAttrComp& ac)
{
    _tableName = ac._tableName;
    _attrName = ac._attrName;
    _comp = ac._comp;
    _fv = ac._fv;
    _fv2 = ac._fv2;
    _attrDesc = ac._attrDesc;
    _attrDesc2 = ac._attrDesc2;
    _compMode = ac._compMode;
    _btwnMode = ac._btwnMode;
    _isSetup = ac._isSetup;
    _isSetup2 = ac._isSetup2;
    _posSetup = ac._posSetup;
    _isParentSetup = ac._isParentSetup;
    _xpos = ac._xpos;
    _xpos2 = ac._xpos2;
    _ypos = ac._ypos;
    _ypos2 = ac._ypos2;    
    _pattern = ac._pattern;
    _pMatcher = 0;
    _pos = ac._pos;
    return (*this);
}
    
bool CegoAttrComp::operator == ( const CegoAttrComp& ac) const
{       
    if ( _compMode != ac._compMode )
	return false;    
    if ( _compMode == ATTR )
	return ( _tableName == ac._tableName
		 && _attrName == ac._attrName
		 && _comp == ac._comp
		 && _attrDesc == ac._attrDesc);
    if ( _compMode == VAL )
    {
	// we don't compare the values ( _fv == ac._fv ), since CegoAttrCond::update sets it up 
	return ( _tableName == ac._tableName && _attrName == ac._attrName && _comp == ac._comp );
    }
    if ( _compMode == BTWN )
    {
	// we don't compare the values ( _fv == ac._fv && _fv2 == ac._fv2 ), since CegoAttrCond::update sets it up

	switch ( _btwnMode )
	{
	case VALUE2VALUE:
	    return ( _tableName == ac._tableName && _attrName == ac._attrName );
	case VALUE2ATTR:
	    return ( ( _tableName == ac._tableName && _attrName == ac._attrName ) && ( _attrDesc2 == ac._attrDesc2 ) );
	case ATTR2VALUE:
	    return ( ( _tableName == ac._tableName && _attrName == ac._attrName ) && ( _attrDesc == ac._attrDesc ) );
	case ATTR2ATTR:
	    return ( ( _tableName == ac._tableName && _attrName == ac._attrName )  && ( _attrDesc == ac._attrDesc ) && ( _attrDesc2 == ac._attrDesc2 ) );
	}
    }
    if ( _compMode == ISLIKE
	 || _compMode == ISNOTLIKE
	 || _compMode == ISNCLIKE
	 || _compMode == ISNOTNCLIKE ) 
	return ( _tableName == ac._tableName && _attrName == ac._attrName && _pattern == ac._pattern  );

    return false;
}

bool CegoAttrComp::operator < ( const CegoAttrComp& ac) const
{    
    if ( _pos < ac._pos )
	return true;
    if ( _pos > ac._pos )
	return false;

    if ( _tableName < ac._tableName )
	return true;
    if ( _tableName > ac._tableName )
	return false;

    if ( _attrName < ac._attrName )
	return true;
    if ( _attrName > ac._attrName )
	return false;

    if ( _compMode == VAL  )
    {	
	if ( _comp < ac._comp )
	    return true;
	if ( _comp > ac._comp )
	    return false;	
	return ( _fv < ac._fv );
    }
    else if ( _compMode == ATTR  )
    {
	if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
	    return true;
	if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
	    return false;
	return (Chain)_attrDesc.getAttrName() < (Chain)ac.getAttrDesc().getAttrName();
	    
    }
    else if ( _compMode == BTWN  )
    {
	if ( _btwnMode == VALUE2VALUE )
	{
	    if ( _fv < ac._fv )
		return true;
	    if ( _fv > ac._fv )
		return false;
	    return ( _fv2 < ac._fv2 );
	}
	else if ( _btwnMode == VALUE2ATTR )
	{
	    if ( (Chain)_attrDesc2.getTableName() < (Chain)ac.getAttrDesc2().getTableName() )
		return true;
	    if ( (Chain)_attrDesc2.getTableName() > (Chain)ac.getAttrDesc2().getTableName() )
		return false;
	    if ( (Chain)_attrDesc2.getAttrName() < (Chain)ac.getAttrDesc2().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc2.getAttrName() > (Chain)ac.getAttrDesc2().getAttrName() )
		return false;
	    if ( _fv < ac._fv )
		return true;
	    if ( _fv > ac._fv )
		return false;
	    return ( _fv2 < ac._fv2 );
	}
	else if ( _btwnMode == ATTR2VALUE )
	{
	    if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
		return true;
	    if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
		return false;
	    if ( (Chain)_attrDesc.getAttrName() < (Chain)ac.getAttrDesc().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc.getAttrName() > (Chain)ac.getAttrDesc().getAttrName() )
		return false;
	    if ( _fv < ac._fv )
		return true;
	    if ( _fv > ac._fv )
		return false;
	    return ( _fv2 < ac._fv2 );    
	}
	else // if ( _btwnMode == ATTR2ATTR )
	{
	    if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
		return true;
	    if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
		return false;
	    if ( (Chain)_attrDesc.getAttrName() < (Chain)ac.getAttrDesc().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc.getAttrName() > (Chain)ac.getAttrDesc().getAttrName() )
		return false;
	    if ( (Chain)_attrDesc2.getTableName() < (Chain)ac.getAttrDesc2().getTableName() )
		return true;
	    if ( (Chain)_attrDesc2.getTableName() > (Chain)ac.getAttrDesc2().getTableName() )
		return false;
	    if ( (Chain)_attrDesc2.getAttrName() < (Chain)ac.getAttrDesc2().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc2.getAttrName() > (Chain)ac.getAttrDesc2().getAttrName() )
		return false;
	    if ( _fv < ac._fv )
		return true;
	    if ( _fv > ac._fv )
		return false;
	    return ( _fv2 < ac._fv2 ); 	    
	}
    }
    else if ( _compMode == ISLIKE
	      || _compMode == ISNOTLIKE
	      || _compMode == ISNCLIKE
	      || _compMode == ISNOTNCLIKE ) 
    {	
	return ( _pattern < ac._pattern  );
    }
    else
    {	
	if ( _comp < ac._comp )
	    return true;
	if ( _comp > ac._comp )
	    return false;
	return ( _fv < ac._fv );	
    }
}	

bool CegoAttrComp::operator > ( const CegoAttrComp& ac) const
{
    if ( _pos > ac._pos )
	return true;
    if ( _pos < ac._pos )
	return false;

    if ( _tableName < ac._tableName )
	return false;
    if ( _tableName > ac._tableName )
	return true;

    if ( _attrName < ac._attrName )
	return false;
    if ( _attrName > ac._attrName )
	return true;

    if ( _compMode == VAL  )
    {
	if ( _comp < ac._comp )
	    return false;
	if ( _comp > ac._comp )
	    return true;
	return ( _fv > ac._fv );
    }
    if ( _compMode == ATTR  )
    {
	 if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
	     return true;
	 if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
	     return false;
	 return (Chain)_attrDesc.getAttrName() > (Chain)ac.getAttrDesc().getAttrName();

    }
    else if ( _compMode == BTWN  )
    {
	if ( _btwnMode == VALUE2VALUE )
	{
	    if ( _fv > ac._fv )
		return true;
	    if ( _fv < ac._fv )
		return false;
	    return ( _fv2 > ac._fv2 );
	}
	else if ( _btwnMode == VALUE2ATTR )
	{
	    if ( (Chain)_attrDesc2.getTableName() > (Chain)ac.getAttrDesc2().getTableName() )
		return true;
	    if ( (Chain)_attrDesc2.getTableName() < (Chain)ac.getAttrDesc2().getTableName() )
		return false;
	    if ( (Chain)_attrDesc2.getAttrName() > (Chain)ac.getAttrDesc2().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc2.getAttrName() < (Chain)ac.getAttrDesc2().getAttrName() )
		return false;
	    if ( _fv > ac._fv )
		return true;
	    if ( _fv < ac._fv )
		return false;
	    return ( _fv2 > ac._fv2 );
	}
	else if ( _btwnMode == ATTR2VALUE )
	{
	    if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
		return true;
	    if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
		return false;
	    if ( (Chain)_attrDesc.getAttrName() > (Chain)ac.getAttrDesc().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc.getAttrName() < (Chain)ac.getAttrDesc().getAttrName() )
		return false;
	    if ( _fv > ac._fv )
		return true;
	    if ( _fv < ac._fv )
		return false;
	    return ( _fv2 > ac._fv2 );    
	}
	else // if ( _btwnMode == ATTR2ATTR )
	{
	    if ( (Chain)_attrDesc.getTableName() > (Chain)ac.getAttrDesc().getTableName() )
		return true;
	    if ( (Chain)_attrDesc.getTableName() < (Chain)ac.getAttrDesc().getTableName() )
		return false;
	    if ( (Chain)_attrDesc.getAttrName() > (Chain)ac.getAttrDesc().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc.getAttrName() < (Chain)ac.getAttrDesc().getAttrName() )
		return false;
	    if ( (Chain)_attrDesc2.getTableName() > (Chain)ac.getAttrDesc2().getTableName() )
		return true;
	    if ( (Chain)_attrDesc2.getTableName() < (Chain)ac.getAttrDesc2().getTableName() )
		return false;
	    if ( (Chain)_attrDesc2.getAttrName() > (Chain)ac.getAttrDesc2().getAttrName() )
		return true;
	    if ( (Chain)_attrDesc2.getAttrName() < (Chain)ac.getAttrDesc2().getAttrName() )
		return false;
	    if ( _fv > ac._fv )
		return true;
	    if ( _fv < ac._fv )
		return false;
	    return ( _fv2 > ac._fv2 ); 	    
	}
    }
    else if ( _compMode == ISLIKE
	      || _compMode == ISNOTLIKE
	      || _compMode == ISNCLIKE 
	      || _compMode == ISNOTNCLIKE )
    {	
	return ( _pattern > ac._pattern  );
    }
    else
    {
	if ( _comp < ac._comp )
	    return false;
	if ( _comp > ac._comp )
	    return true;
	return ( _fv > ac._fv );		
    }
}	

Chain CegoAttrComp::getId() const
{
    Chain s;
    
    s = _tableName + Chain(".") + _attrName;
    
    if ( _compMode == BTWN )
    {	
	switch ( _btwnMode )
	{
	case VALUE2VALUE:
	    s += Chain("#btw#") + _fv.toChain() + Chain("#") + _fv2.toChain();
	    break;
	case VALUE2ATTR:
	    s += Chain("#btw#") + _fv.toChain() + Chain("#") + _attrDesc2.toChain();
	    break;
	case ATTR2VALUE:
	    s += Chain("#btw#") + _attrDesc.toChain() + Chain("#") + _fv2.toChain();
	    break;	    
	case ATTR2ATTR:
	    s += Chain("#btw#") + _attrDesc.toChain() + Chain("#") + _attrDesc2.toChain();
	    break;	    	    
	}
    }
    else if ( _compMode == ISLIKE )
    {
	s += Chain("lk'") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNOTLIKE )
    {
	s += Chain("nlk'") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNCLIKE )
    {
	s += Chain("nclk'") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNOTNCLIKE )
    {
	s += Chain("nnclk'") + _pattern + Chain("'"); 
    }
    
    else
    {
	switch ( _comp )
	{
	case EQUAL:
	    s += Chain("=");
	    break;
	case NOT_EQUAL:
	    s += Chain("!=");
	    break;
	case LESS_THAN:
	    s += Chain("<");
	    break;
	case MORE_THAN:
	    s += Chain(">");
	    break;
	case LESS_EQUAL_THAN:
	    s += Chain("<=");
	    break;
	case MORE_EQUAL_THAN:
	    s += Chain(">=");
	    break;
	}
	if ( _compMode == VAL )
	    s += _fv.toChain();
	else
	{
	    s += _attrDesc.toChain();
	    if ( _isSetup )
		s += _fv.toChain();
	    else
		s += Chain("#not setup#");
	}
    }
    return s;    
}

Chain CegoAttrComp::toChain() const
{
    Chain s;
    
    s = _tableName + "." + _attrName; //  + "(" + Chain(_pos) + ")";
    
    if ( _compMode == BTWN )
    {
	switch ( _btwnMode )
	{
	case VALUE2VALUE:
	    s += Chain(" between ") + _fv.toChain() + Chain(" and ") + _fv2.toChain();
	    break;
	case VALUE2ATTR:
	    s += Chain(" between ") + _fv.toChain() + Chain(" and ") + _attrDesc2.toChain();
	    break;
	case ATTR2VALUE:
	    s += Chain(" between ") + _attrDesc.toChain() + Chain(" and ") + _fv2.toChain();
	    break;	    
	case ATTR2ATTR:
	    s += Chain(" between ") + _attrDesc.toChain() + Chain(" and ") + _attrDesc2.toChain();
	    break;	    	    
	}
    }
    else if ( _compMode == ISLIKE )
    {
	s += Chain(" like '") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNOTLIKE )
    {
	s += Chain(" not like '") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNCLIKE )
    {
	s += Chain(" nclike '") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNOTNCLIKE )
    {
	s += Chain(" not nclike '") + _pattern + Chain("'"); 
    }

    else
    {
	switch ( _comp )
	{
	case EQUAL:
	    s += Chain(" = ");
	    break;
	case NOT_EQUAL:
	    s += Chain(" != ");
	    break;
	case LESS_THAN:
	    s += Chain(" < ");
	    break;
	case MORE_THAN:
	    s += Chain(" > ");
	    break;
	case LESS_EQUAL_THAN:
	    s += Chain(" <= ");
	    break;
	case MORE_EQUAL_THAN:
	    s += Chain(" >= ");
	    break;
	}
	if ( _compMode == VAL )
	    s += _fv.toChain();
	else
	{
	    s += _attrDesc.toChain();
	    if ( _isSetup )
		s += Chain("(") + _fv.toChain() + Chain(")");
	    else		
		s += Chain(" -> not setup ");
	}
    }
    return s;
}

ostream& operator << (ostream& s, const CegoAttrComp& ac)
{
    s << ac.toChain();
    return s;
}
