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

// base includes
#include <lfc/BigDecimal.h>
#include <lfc/Datetime.h>

// cego includes
#include "CegoQueryHelper.h"
#include "CegoXMLdef.h"
#include "CegoSelect.h"
#include "CegoTypeConverter.h"

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

CegoQueryHelper::CegoQueryHelper()
{
}

CegoQueryHelper::~CegoQueryHelper()
{
}

bool CegoQueryHelper::evalPredicate(ListT<CegoField>* pParentJoinBuf,
				    int parentJoinBufPos,
				    int parentJoinBufSize,
				    ListT<CegoField>* joinBuf,
				    int pos,
				    int size, 
				    CegoPredDesc* pP, 
				    CegoProcBlock *pBlock)
{

    if (pP == 0)
	return true;

    CegoCondDesc* pC = pP->getCondition();
    if (pC)
    {
	switch ( pC->getCondType() )
	{
	case CegoCondDesc::AND:
	    return ( evalPredicate(pParentJoinBuf, 
				   parentJoinBufPos,
				   parentJoinBufSize,
				   joinBuf,
				   pos,
				   size, 
				   pC->Left(), 
				   pBlock) 
		     && evalPredicate(pParentJoinBuf,
				      parentJoinBufPos,
				      parentJoinBufSize,
				      joinBuf,
				      pos,
				      size, 
				      pC->Right(),
				      pBlock));
	case CegoCondDesc::OR:
	    return ( evalPredicate(pParentJoinBuf,
				   parentJoinBufPos,
				   parentJoinBufSize, 
				   joinBuf,
				   pos,
				   size, 
				   pC->Left(),
				   pBlock) 
		     || evalPredicate(pParentJoinBuf,
				      parentJoinBufPos,
				      parentJoinBufSize,
				      joinBuf,
				      pos,
				      size, 
				      pC->Right(),
				      pBlock));
	default:
	    break;	
	}
    } 
    else 
    {
	if ( pP->getMode() == CegoPredDesc::NOTPRED )
	{
	    bool np = evalPredicate(pParentJoinBuf,
				    parentJoinBufPos,
				    parentJoinBufSize,
				    joinBuf,
				    pos,
				    size,
				    pP->getNotPred(),
				    pBlock);
	    if ( np )
	    {
		return false;
	    }
	    return true;
	}
	else
	{

	    ListT<CegoField>* flArray;
	    int flSize;
	    bool isAllocated = false;

	    if ( pParentJoinBuf )
	    {
		flSize = parentJoinBufSize + size;
		flArray = new ListT<CegoField>[flSize];
		isAllocated = true;
		
		for ( int i=0; i<parentJoinBufSize; i++)
		    flArray[i] = pParentJoinBuf[parentJoinBufPos + i];
		for ( int i=0; i<size; i++)
		    flArray[parentJoinBufSize + i] = joinBuf[pos + i];		
	    }
	    else
	    {
		flArray = joinBuf + pos;
		flSize = size;
	    }
	    
	    bool retVal = false;
	    
	    switch ( pP->getMode() )
	    {
		
	    case CegoPredDesc::EXPRCOMP:
	    {
		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr2()->setFieldListArray(flArray, flSize);
		
		pP->getExpr1()->setBlock(pBlock);
		pP->getExpr2()->setBlock(pBlock);

		// cout << "Eval : " << pP->getExpr1()->evalFieldValue() << " comp " << pP->getExpr2()->evalFieldValue() << endl;
		
		retVal = evalFields(pP->getComparison(), pP->getExpr1()->evalFieldValue(), pP->getExpr2()->evalFieldValue());

		break;
	    }    
	    case CegoPredDesc::BETWEEN:
	    {
		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr2()->setFieldListArray(flArray, flSize);
		pP->getExpr3()->setFieldListArray(flArray, flSize);
		    
		pP->getExpr1()->setBlock(pBlock);
		pP->getExpr2()->setBlock(pBlock);
		pP->getExpr3()->setBlock(pBlock);

			       
		// cout << " Eval " << pP->getExpr1()->evalFieldValue() << " is btwn " <<  pP->getExpr2()->evalFieldValue() << " and "  << pP->getExpr3()->evalFieldValue() << endl;

		retVal = evalBetween(pP->getExpr1()->evalFieldValue(), pP->getExpr2()->evalFieldValue(), pP->getExpr3()->evalFieldValue());
		break;
	    }    		
	    case CegoPredDesc::NULLCOMP:
	    {	  
		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr1()->setBlock(pBlock);
		
		if ( pP->getExpr1()->evalFieldValue().isNull() )
		{
		    retVal = true;
		}
		else
		{
		    retVal = false;
		}
		break;
	    }
	    case CegoPredDesc::NOTNULLCOMP:
	    {	
		
		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr1()->setBlock(pBlock);
		
		if ( pP->getExpr1()->evalFieldValue().isNull() )
		{
		    retVal = false;
		}
		else
		{
		    retVal = true;
		}
		break;
	    }
	    case CegoPredDesc::EXISTSCOMP:
	    {
		
		CegoSelect* pSelect = pP->getSelectQuery();

		pSelect->reset(true);		
		pSelect->setParentJoinBuf(flArray, flSize);
				
		ListT<CegoField> fl;
		
		if ( pSelect->nextTuple(fl) )
		{
		    retVal= true;
		}
		else
		{
		    retVal = false;
		}
		// pSelect->reset();
		break;
	    }
	    case CegoPredDesc::ISLIKE:
	    case CegoPredDesc::ISNOTLIKE:
	    {
		
		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr1()->setBlock(pBlock);
		
		if ( pP->getMode() == CegoPredDesc::ISLIKE )
		    retVal = pP->match(pP->getExpr1()->evalFieldValue());
		else
		    retVal =  ! pP->match(pP->getExpr1()->evalFieldValue());
		
		break;
	    }
	    case CegoPredDesc::INSUB:
	    case CegoPredDesc::NOTINSUB:
	    {

		pP->getExpr1()->setFieldListArray(flArray, flSize);
		pP->getExpr1()->setBlock(pBlock);
		
		CegoSelect* pSelect = pP->getSelectQuery();

		pSelect->reset(true);
				
		pSelect->setParentJoinBuf(flArray, flSize);
		pSelect->setProcBlock(pBlock);
		
		pSelect->setCaching(true);
			       
		ListT<CegoField> fl;
				
		if ( pP->getMode() == CegoPredDesc::INSUB )
		{		   		   
		    retVal = false;
		    while ( pSelect->nextTuple(fl) && retVal == false )
		    {
			CegoField *pSF = fl.First();

			if ( (CegoFieldValue)pSF->getValue() == (CegoFieldValue)pP->getExpr1()->evalFieldValue() )
			    retVal = true;
		    }
		}
		else
		{ 
		    retVal = true;
		    while ( pSelect->nextTuple(fl) && retVal == true )
		    {
			CegoField *pSF = fl.First();
			if ( (CegoFieldValue)pSF->getValue() == (CegoFieldValue)pP->getExpr1()->evalFieldValue() )
			    retVal = false;
		    }
		}
		
		// in case of caching, we have to read to the end to fill up cache
		if ( pSelect->isCached() == false )
		{
		    while ( pSelect->nextTuple(fl));
		}

		break;    
	    }
	    default:
		break;
	    }
	    if ( isAllocated == true )
		delete[] flArray;
	    return retVal;
	}
    }
    return false;
}

CegoQueryHelper::AttrCondMatch CegoQueryHelper::checkAttrCond(CegoAttrCond& ac, 
							    CegoPredDesc* pP, 
							    const ListT<CegoField>& schema,
							    ListT<CegoField>* flArray, 
							    int flSize, 
							    CegoProcBlock *pBlock)
{
    AttrCondMatch m = evalAttrCond(ac, pP, schema, flArray, flSize, pBlock);
    if ( ac.numComp() == 0 )
	m = INAPP;

    return m;
}


CegoQueryHelper::AttrCondMatch CegoQueryHelper::evalAttrCond(CegoAttrCond& ac, 
							     CegoPredDesc* pP, 
							     const ListT<CegoField>& schema,
							     ListT<CegoField>* flArray, 
							     int flSize, 
							     CegoProcBlock *pBlock)
{
    
    if (pP->getCondition())
    {
	return evalAttrCondbyCondition(ac, pP->getCondition(), schema, flArray, flSize, pBlock);
    }
    else if (pP->getMode() == CegoPredDesc::EXPRCOMP)
    {


	CegoAttrDesc* pAttrDesc1;
	CegoAttrDesc* pAttrDesc2;
	
	pAttrDesc1 = pP->getExpr1()->checkAttr();
	pAttrDesc2 = pP->getExpr2()->checkAttr();
	ListT<CegoAttrDesc*> attrRefList1 = pP->getExpr1()->getAttrRefList();
	ListT<CegoAttrDesc*> attrRefList2 = pP->getExpr2()->getAttrRefList();

	if ( pAttrDesc1 && pAttrDesc2 )
	{

	    CegoField* pF = schema.First();
	    
	    while (pF)
	    {
		if ( ((Chain)pAttrDesc1->getTableName() == (Chain)pF->getTableName() ||
		      (Chain)pAttrDesc1->getTableName() == (Chain)pF->getTableAlias() ||
		      pAttrDesc1->getTableName() == Chain())
		     && (Chain)pAttrDesc1->getAttrName() == (Chain)pF->getAttrName() )
		{					   
		    for ( int i=0; i<flSize; i++)
		    {
			CegoField* pFB = flArray[i].First();
			while (pFB)
			{
			    if (((Chain)pAttrDesc2->getTableName() == (Chain)pFB->getTableName() ||
				 (Chain)pAttrDesc2->getTableName() == (Chain)pFB->getTableAlias() ||
				 pAttrDesc2->getTableName() == Chain())
				&& (Chain)pAttrDesc2->getAttrName() == (Chain)pFB->getAttrName())
			    {
				ac.add(CegoAttrComp(pF->getAttrName(), 
						    pP->getComparison(),
						    *pAttrDesc2));
			    }
			    pFB = flArray[i].Next();
			}
		    }
		}

		if ( ((Chain)pAttrDesc2->getTableName() == (Chain)pF->getTableName() ||
		      (Chain)pAttrDesc2->getTableName() == (Chain)pF->getTableAlias() ||
		      pAttrDesc2->getTableName() == Chain())
		     && (Chain)pAttrDesc2->getAttrName() == (Chain)pF->getAttrName() )
		{			
		    for ( int i=0; i<flSize; i++)
		    {
			CegoField* pFB = flArray[i].First();
			while (pFB)			   			    
			{
			    if (((Chain)pAttrDesc1->getTableName() == (Chain)pFB->getTableName() ||
				 (Chain)pAttrDesc1->getTableName() == (Chain)pFB->getTableAlias() ||
				 pAttrDesc1->getTableName() == Chain())
				&& (Chain)pAttrDesc1->getAttrName() == (Chain)pFB->getAttrName())
			    {
				ac.add(CegoAttrComp(pF->getAttrName(), 
						    pP->getComparison(),
						    *pAttrDesc1));
			    }
			    pFB = flArray[i].Next();
			}
		    }
		}
		pF = schema.Next();
	    }
	}
	else if ( pAttrDesc1 && attrRefList2.Size() == 0 )
	{

	    CegoField* pF = schema.First();   
	    while (pF)
	    { 
		if ((pAttrDesc1->getTableName() == (Chain)pF->getTableName() ||
		     pAttrDesc1->getTableName() == (Chain)pF->getTableAlias() ||
		     pAttrDesc1->getTableName() == Chain())
		    && pAttrDesc1->getAttrName() == (Chain)pF->getAttrName())
		{
		    pP->getExpr2()->setBlock(pBlock);
		    ac.add(CegoAttrComp(pF->getAttrName(),
					pP->getComparison(),
					pP->getExpr2()->evalFieldValue()));
		}
		pF = schema.Next();
	    }
	}
	else if ( pAttrDesc2 && attrRefList1.Size() == 0 )    
	{
	    CegoField* pF = schema.First();	    
	    while (pF)
	    {
		
		if ((pAttrDesc2->getTableName() == (Chain)pF->getTableName() ||
		     pAttrDesc2->getTableName() == (Chain)pF->getTableAlias() ||
		     pAttrDesc2->getTableName() == Chain())
		    && pAttrDesc2->getAttrName() == (Chain)pF->getAttrName())
		{
		    pP->getExpr1()->setBlock(pBlock);
		    ac.add(CegoAttrComp(pF->getAttrName(),
					pP->getComparison(),
					pP->getExpr1()->evalFieldValue()));
		}
		pF = schema.Next();
	    }
	}
	else
	{
	    return PARTIAL;
	}
    }
    else if (pP->getMode() == CegoPredDesc::BETWEEN)
    {
	
	CegoAttrDesc* pAttrDesc1 = pP->getExpr1()->checkAttr();
	CegoAttrDesc* pAttrDesc2 = pP->getExpr2()->checkAttr();
	CegoAttrDesc* pAttrDesc3 = pP->getExpr3()->checkAttr();

	ListT<CegoAttrDesc*> attrRefList1 = pP->getExpr1()->getAttrRefList();
	ListT<CegoAttrDesc*> attrRefList2 = pP->getExpr2()->getAttrRefList();
	ListT<CegoAttrDesc*> attrRefList3 = pP->getExpr3()->getAttrRefList();

	if ( pAttrDesc1 && attrRefList2.Size() == 0 && attrRefList3.Size() == 0 )
	{

	    CegoField* pF = schema.First(); 
	    while (pF)
	    {		
		if ((pAttrDesc1->getTableName() == (Chain)pF->getTableName() ||
		     pAttrDesc1->getTableName() == (Chain)pF->getTableAlias() ||
		     pAttrDesc1->getTableName() == Chain())
		    && pAttrDesc1->getAttrName() == (Chain)pF->getAttrName())
		{
		    pP->getExpr2()->setBlock(pBlock);
		    pP->getExpr3()->setBlock(pBlock);

		    ac.add(CegoAttrComp(pF->getAttrName(),
					pP->getExpr2()->evalFieldValue(),
					pP->getExpr3()->evalFieldValue()));
		}
		pF = schema.Next();
	    }	    
	}
	else
	{
	    return PARTIAL;
	}
    }
    else if (pP->getMode() == CegoPredDesc::ISLIKE)
    {
	CegoAttrDesc* pAttrDesc;	
	pAttrDesc = pP->getExpr1()->checkAttr();
	if ( pAttrDesc  )
	{
	    ac.add(CegoAttrComp(pAttrDesc->getAttrName(), pP->getPattern(), false));
	}
	else
	{
	    return PARTIAL;	    
	}
    }
    else if (pP->getMode() == CegoPredDesc::ISNOTLIKE)
    {
	CegoAttrDesc* pAttrDesc;	
	pAttrDesc = pP->getExpr1()->checkAttr();
	if ( pAttrDesc  )
	{
	    ac.add(CegoAttrComp(pAttrDesc->getAttrName(), pP->getPattern(), true));
	}
	else
	{
	    return PARTIAL;
	}
    }
    else
    {
	return PARTIAL;
    }

    return COMPLETE;
}

CegoQueryHelper::AttrCondMatch CegoQueryHelper::evalAttrCondbyCondition(CegoAttrCond& ac,
						       CegoCondDesc* pC,
						       const ListT<CegoField>& schema,
						       ListT<CegoField>* flArray, 
						       int flSize, 
						       CegoProcBlock* pBlock)
{
    
    if ( pC->getCondType() == CegoCondDesc::OR)
    {
	return INAPP;	
    }

    AttrCondMatch m1, m2;
    m1 = COMPLETE;
    m2 = COMPLETE;
    if ( pC->Left() )
    {
	m1 = evalAttrCond(ac, pC->Left(), schema, flArray, flSize, pBlock);
    }
    if ( pC->Right() )
    {
	m2 = evalAttrCond(ac, pC->Right(), schema, flArray, flSize, pBlock);
    }
    
    if ( m1 == INAPP || m2 == INAPP )
	return INAPP;
    if ( m1 == PARTIAL || m2 == PARTIAL )
	return PARTIAL;
    
    return COMPLETE;
}

void CegoQueryHelper::makeCNF(CegoCondDesc* pC)
{
    if ( pC )
    {
	if (pC->Left()->getCondition())
	{
	    makeCNF(pC->Left()->getCondition());
	}
	if (pC->Right()->getCondition())
	{
	    makeCNF(pC->Right()->getCondition());
	}
	if ( pC->getCondType() == CegoCondDesc::AND )
	{
	    // nothing to do
	} 
	else if ( pC->getCondType() == CegoCondDesc::OR )
	{
	    if ( pC->Left()->getCondition() )
	    {
		CegoCondDesc *pLC = pC->Left()->getCondition();
		if (pLC->getCondType() == CegoCondDesc::AND)
		{
		    pC->setCondType(CegoCondDesc::AND);
		    CegoCondDesc* pNC = new CegoCondDesc(CegoCondDesc::OR);
		    pNC->setLeft(pLC->Right());
		    pNC->setRight(pC->Right());
		    CegoPredDesc* pNP = new CegoPredDesc(pNC);
		    pC->setRight(pNP);
		    pLC->setCondType(CegoCondDesc::OR);
		    
		    pLC->setRight(pNC->Right()->clone());
		    
		    makeCNF(pC->Left()->getCondition());
		    makeCNF(pC->Right()->getCondition());
		}
		else
		{
		    makeCNF(pC->Left()->getCondition());
		}
		
	    } 
	    else if ( pC->Right()->getCondition() )
	    {
		CegoCondDesc *pRC = pC->Right()->getCondition();
		if (pRC->getCondType() == CegoCondDesc::AND)
		{
		    pC->setCondType(CegoCondDesc::AND);
		    CegoCondDesc* pNC = new CegoCondDesc(CegoCondDesc::OR);
		    pNC->setLeft(pC->Left());
		    pNC->setRight(pRC->Left());
		    CegoPredDesc* pNP = new CegoPredDesc(pNC);
		    pC->setLeft(pNP);
		    pRC->setCondType(CegoCondDesc::OR);
		    pRC->setLeft(pNC->Left()->clone());	    
		    
		    makeCNF(pC->Left()->getCondition());
		    makeCNF(pC->Right()->getCondition());
		}
		else
		{
		    makeCNF(pC->Right()->getCondition());
		}
		
	    }
	}
    }
}

Chain CegoQueryHelper::condToChain(CegoCondDesc* pC, int depth)
{
    Chain s;
    if (pC->Left())
    {
	s = predToChain(pC->Left(), depth+1);
	for (int i=0;i<depth;i++)
	    s += Chain(" ");
	switch(pC->getCondType())
	{
	case CegoCondDesc::AND:
	    s += Chain(" AND ");
	    break;
	case CegoCondDesc::OR:
	    s += Chain(" OR ");
	    break;
	default:
	    break;
	}
	s += predToChain(pC->Right(), depth+1);
    }
    return s;
}

Chain CegoQueryHelper::predToChain(CegoPredDesc* pP, int depth)
{
    Chain s;

    s += pP->toChain(); 
        
    if (pP->getCondition())
    {
	s = condToChain(pP->getCondition(), depth+1);
    }
    else
    {
	for (int i=0;i<depth;i++)
	    s+= Chain(" ");
	
    }
    return s;
    
}

bool CegoQueryHelper::evalFields(CegoComparison comp, const CegoFieldValue& f1, const CegoFieldValue& f2)
{

    switch (comp)
    {
    case EQUAL:
	return ( f1 == f2 );
    case NOT_EQUAL:
	return ( f1 != f2 );
    case LESS_THAN:
	return ( f1 < f2 );
    case MORE_THAN:
	return ( f1 > f2 );
    case LESS_EQUAL_THAN:
	return ( f1 <= f2 );
    case MORE_EQUAL_THAN:
	return ( f1 >= f2 );
    }
}

bool CegoQueryHelper::evalBetween(const CegoFieldValue& f1, const CegoFieldValue& f2, const CegoFieldValue& f3)
{

    if ( f2 <= f1 && f1 <= f3 )
	return true;
    return false;
}

void CegoQueryHelper::aggregateTuple(ListT<CegoField>& aggTuple, CegoExpr* pExpr)
{

    ListT<CegoAggregation*> aggList = pExpr->getAggregationList();
    
    CegoAggregation **pAgg = aggList.First();
    
    while ( pAgg )
    {
	aggregateTuple(aggTuple, *pAgg);	
	pAgg = aggList.Next();
    }
}

void CegoQueryHelper::aggregateTuple(ListT<CegoField>& aggTuple, CegoAggregation* pAgg)
{
    
    CegoField f;
    CegoFieldValue fv;
    
    CegoExpr *pAE = pAgg->getExpr();
    
    if ( pAE == 0 )
    {
	f.setAttrName(Chain("*"));
	fv.setType(INT_TYPE);
    }
    else
    {

	pAE->setFieldListArray( &aggTuple, 1 );
	fv = pAE->evalFieldValue();
		
	if ( fv.getValue() == 0 && pAgg->getType() != CegoAggregation::MIN )
	{
	    switch ( fv.getType() )
	    {
	    case INT_TYPE:
	    {			
		fv = CegoFieldValue(INT_TYPE, Chain("0"));
		break;
	    }
	    case VARCHAR_TYPE:
	    {
		fv = CegoFieldValue(VARCHAR_TYPE, Chain(""));
		break;
	    }
	    case DECIMAL_TYPE:
	    {
		fv = CegoFieldValue(DECIMAL_TYPE, Chain("0.0"));
		break;		   
	    }
	    case FIXED_TYPE:
	    {
		fv = CegoFieldValue(FIXED_TYPE, Chain("0.0"));
		break;		   
	    }
	    case NULL_TYPE:
	    {
		// nothing to to
		break;
	    }
	    default:
	    {
		Chain msg = Chain("Aggregation not supported on datatype <") + CEGO_TYPE_MAP[ (int) fv.getType()] + Chain(">");
		throw Exception(EXLOC, msg);
		break;
	    }
	    }
	}
    }
        
    switch ( pAgg->getType() )
    {
	
    case CegoAggregation::COUNT:
    {
	if ( pAgg->getFieldValue().getValue() == 0 )
	{
	    pAgg->setFieldValue( CegoFieldValue(INT_TYPE, Chain("1")) );
	}
	else
	{
	    // int *pI = (int*)(pAgg->getFieldValue().getValue());
	    // (*pI)++;
	    int i;
	    memcpy(&i, pAgg->getFieldValue().getValue(), sizeof(int));
	    i++;
	    memcpy(pAgg->getFieldValue().getValue(), &i, sizeof(int));
	}
	break;
    }
    case CegoAggregation::SUM:
    case CegoAggregation::AVG:
    {
	if ( fv.getType() == VARCHAR_TYPE )
	{
	    Chain msg = Chain("Aggregation not supported on datatype <") + CEGO_TYPE_MAP[ (int) fv.getType()] + Chain(">");
	    throw Exception(EXLOC, msg);
	}

	if ( pAgg->getFieldValue().getValue() == 0 )
	{
	    pAgg->getFieldValue() = fv;
	}
	else
	{
	    pAgg->getFieldValue() = pAgg->getFieldValue() + fv;
	}    		   
	break;
    }
    case CegoAggregation::MIN:
    {
	if ( pAgg->getFieldValue().getValue() == 0 )
	{
	    pAgg->getFieldValue() = fv;
	}
	else
	{		
	    if ( (CegoFieldValue)pAgg->getFieldValue() > fv )
	    {
		pAgg->getFieldValue() = fv;
	    }
	}    		   
	break;
    }	    
    case CegoAggregation::MAX:
    {
	if ( pAgg->getFieldValue().getValue() == 0 )
	{
	    pAgg->getFieldValue() = fv;
	}
	else
	{		
	    if ( (CegoFieldValue)pAgg->getFieldValue() < fv )
	    {
		pAgg->getFieldValue() = fv;
	    }
	}    		   
	break;
    }		
    }    
}

void CegoQueryHelper::prepareFieldValue(CegoField* pFV, CegoFieldValue& fv, int pos)
{
    if ( pFV->isNullable() == false && fv.isNull() )
    {
	throw Exception(EXLOC, Chain("Invalid null value for attribute <") 
			+ pFV->getAttrName() 
			+ Chain("> in value list"));	
    }
    if ( fv.getType() != NULL_TYPE && pFV->getType() != fv.getType() )	
    {
 
	if ( fv.castTo(pFV->getType()) == false )
	{
	    throw Exception(EXLOC, Chain("Mismatched datatype <") 
			    + CEGO_TYPE_MAP[(int)fv.getType()] 
			    + Chain("> for attribute ") + pFV->getAttrName() 
			    + ", expected <" 
			    + CEGO_TYPE_MAP[(int)pFV->getType()] + ">");
	}
    }
    
    if ( fv.getValue() != 0 )
    {
	if ( pFV->getType() == FIXED_TYPE )
	{		
	    BigDecimal d ( fv.valAsChain() );
	    if ( d.getScale() != pFV->getLength())
		throw Exception(EXLOC, "Mismatched decimal scale in value list");
	}
	
	if ( pFV->getType() == VARCHAR_TYPE  
	     && pFV->getLength() < fv.getLength() )
	{
	    Chain shrinkVal ( (char*) fv.getValue() );
	    fv = CegoFieldValue(VARCHAR_TYPE, shrinkVal.subChain(1, pFV->getLength()));
	}
	
	if ( pFV->getType() == DATETIME_TYPE )
	{
	    int val;
	    memcpy(&val, fv.getValue(), sizeof(int));
	    if  (val == 0 ) 
	    {
		Datetime n;
		int dtval = n.asInt();
		memcpy(fv.getValue(), &dtval, sizeof(int));	   	    
	    }
	}
    }
}

void CegoQueryHelper::encodeFL(const ListT<CegoField>& fvl, char* &pBufBase, int &buflen)
{

    CegoField* pF = fvl.First();
    while (pF)
    {
	buflen += sizeof(CegoDataType); // datatype
	buflen += sizeof(int); // datatype len

	buflen += sizeof(int); // defaultvalue len

	if ( pF->getValue().getLength() > 0 )
	    buflen += pF->getValue().getLength();

	buflen += sizeof(char); // isNullable
	buflen += sizeof(int); // attr length
	buflen += pF->getAttrName().length(); // attr

	pF = fvl.Next();
    }
    
    pBufBase = (char*) malloc(buflen);
    
    if (pBufBase == 0)
    {
	throw Exception(EXLOC, "malloc system error");	
    }

    char *pBuf = pBufBase;

    pF = fvl.First();
    while (pF)
    {
	int attrLength =  pF->getAttrName().length();
	CegoDataType dt = pF->getType();
		
	memcpy( pBuf, &dt, sizeof(CegoDataType));
	pBuf += sizeof(CegoDataType);

        int dtlen = pF->getLength();

	memcpy( pBuf, &dtlen, sizeof(int));
	pBuf += sizeof(int);
	
	int deflen = pF->getValue().getLength();

	memcpy( pBuf, &deflen, sizeof(int));
	pBuf += sizeof(int);

	if ( deflen > 0 )
	{
	    memcpy( pBuf, pF->getValue().getValue(), deflen);
	    pBuf += deflen;
	}
	
	char isNullable = 0;
	if ( pF->isNullable() )
	    isNullable = 1;

	memcpy( pBuf, &isNullable, sizeof(char));
	pBuf += sizeof(char);
	
	memcpy( pBuf, &attrLength, sizeof(int));
	pBuf += sizeof(int);

	memcpy( pBuf, (char*)pF->getAttrName(), attrLength);
	pBuf += attrLength;

	pF = fvl.Next();

    }
}

void CegoQueryHelper::decodeFL(ListT<CegoField>& fvl, char* pc, int len)
{


    char *pBase = pc;

    while (pc - pBase < len)
    {

	CegoDataType dt;
	memcpy(&dt, pc, sizeof(CegoDataType));
	pc += sizeof(CegoDataType);

	int dtlen;
	memcpy( &dtlen, pc, sizeof(int));
	pc += sizeof(int);

	CegoFieldValue defVal;

	int deflen;
	memcpy( &deflen, pc, sizeof(int));
	pc += sizeof(int);
	if ( deflen > 0 )
	{
	    defVal = CegoFieldValue(dt, pc, deflen, false);
	    pc += deflen;
	}

	char isNullable;
	memcpy(&isNullable, pc, sizeof(char));
	pc += sizeof(char);

	int attrLength;
	memcpy( &attrLength, pc, sizeof(int));
	pc += sizeof(int);
	
	Chain attrName(pc, attrLength-1);
	pc += attrLength;

	Chain n;

	fvl.Insert(CegoField(n,n, attrName, dt, dtlen, defVal, isNullable));
		
    }
}

void CegoQueryHelper::encodeFVL(int tid, int tastep, CegoTupleState ts, const ListT<CegoField>& fvl, char* &pBufBase, int &buflen)
{
    ListT<CegoBlob> blobList;
    encodeFVL(tid, tastep, ts, fvl, blobList, pBufBase, buflen);
}

void CegoQueryHelper::encodeFVL(int tid, int tastep, CegoTupleState ts, const ListT<CegoField>& fvl, const ListT<CegoBlob>& blobList, char* &pBufBase, int &buflen)
{

    buflen = sizeof(int); // for tid
    buflen += sizeof(int); // for tastep
    buflen += sizeof(CegoTupleState); // for tuplestate

    int blobIdx = 0;
    CegoField* pF = fvl.First();
    while (pF)
    {

	int l =  pF->getValue().getLength();
	CegoDataType dt = pF->getValue().getType();
	
	// force null type in case of fv length and value constraints 
	if ( l == 0 || pF->getValue().getValue() == 0 )
	    dt = NULL_TYPE;
		
	if ( dt != NULL_TYPE )
	{
	    buflen += sizeof(int); // id
	    buflen += sizeof(CegoDataType);


	    if ( dt == BLOB_TYPE && blobList.Size() > 0)
	    {
		
		buflen += sizeof(long); // blobsize
		buflen += blobList[blobIdx].getSize();
		blobIdx++;
	    }
	    else
	    {
		
		if ( dt == VARCHAR_TYPE 
		     || dt == BIGINT_TYPE
		     || dt == DECIMAL_TYPE 
		     || dt == FIXED_TYPE )
		{
		    buflen += sizeof(int);
		}
		
		buflen += pF->getValue().getLength();
	    }
	}
	pF = fvl.Next();
    }

    buflen += sizeof(int); // terminating id

    pBufBase = (char*) malloc(buflen);
    
    if (pBufBase == 0)
    {
	throw Exception(EXLOC, "malloc system error");	
    }

    char *pBuf = pBufBase;

    memcpy( pBuf, &tid, sizeof(int));
    pBuf += sizeof(int);

    memcpy( pBuf, &tastep, sizeof(int));
    pBuf += sizeof(int);

    memcpy( pBuf, &ts, sizeof(CegoTupleState));
    pBuf += sizeof(CegoTupleState);

    blobIdx = 0;
    pF = fvl.First();
    while (pF)
    {
	int id =  pF->getId();
	int l =  pF->getValue().getLength();
	CegoDataType dt = pF->getValue().getType();

	// cout << "Encoding id " << id << endl;
	// force null type in case of fv length and value constraints 
	if ( l == 0 || pF->getValue().getValue() == 0 )
	    dt = NULL_TYPE;
	
	if ( dt != NULL_TYPE )
	{
	    
	    // cout << "ID = " << id << " Encoding value " << pF->getValue().valAsChain() << endl;

	    memcpy( pBuf, &id, sizeof(int));
	    pBuf += sizeof(int);
	    
	    memcpy( pBuf, &dt, sizeof(CegoDataType));
	    pBuf += sizeof(CegoDataType);
	    
	    if ( dt == BLOB_TYPE && blobList.Size() > 0)
	    {
		long blobSize = blobList[blobIdx].getSize();
		memcpy( pBuf, &blobSize, sizeof(long));
		pBuf += sizeof(long);
		memcpy( pBuf, blobList[blobIdx].getBufPtr(), blobList[blobIdx].getSize());
		pBuf += blobList[blobIdx].getSize();
	    }
	    else
	    {
		if ( dt == VARCHAR_TYPE 
		     || dt == BIGINT_TYPE 
		     || dt == DECIMAL_TYPE
		     || dt == FIXED_TYPE)
		{
		    memcpy( pBuf, &l, sizeof(int));
		    pBuf += sizeof(int);
		}
		
		memcpy( pBuf, pF->getValue().getValue(), l);	
		
		pBuf += l;
	    }
	}
	
	pF = fvl.Next();
    }

    int termId=0;
    memcpy( pBuf, &termId, sizeof(int));
    // pBuf += sizeof(int);
}

void CegoQueryHelper::decodeFVL(ListT<CegoField>* fvlArray, int pos, char* pc, int len, int &tid, int &tastep, CegoTupleState& ts)
{
    decodeFVL(fvlArray[pos], pc, len, tid, tastep, ts, true);
}

void CegoQueryHelper::decodeFVL(ListT<CegoField>& fvl, char* pc, int len, int &tid, int &tastep, CegoTupleState& ts, bool doReset)
{


    if ( doReset )
    {
	// make sure no field values are set    
	CegoField* pF = fvl.First(); 
	while ( pF )
	{
	    CegoFieldValue nullValue;
	    pF->setValue(nullValue);
	    pF = fvl.Next();	
	}
    }

    char* pBase = pc;
    
    memcpy(&tid, pc, sizeof(int));
    pc += sizeof(int);

    memcpy(&tastep, pc, sizeof(int));
    pc += sizeof(int);

    memcpy(&ts, pc, sizeof(CegoTupleState));
    pc += sizeof(CegoTupleState);

    bool eot = false;


    CegoField* pF = fvl.First(); 

    while (pc - pBase < len && eot == false && pF)
    {
	int id;     
	memcpy(&id, pc, sizeof(int));

	// cout << "Decoding id " << id << endl;

	// cout << "PF Id =  " << pF->getId() << endl;

	while ( pF && id > pF->getId() )
	{
	    pF = fvl.Next();
	}
	if ( pF == 0 )
	    return;
	
	pc += sizeof(int);
	
	CegoDataType dt;
	memcpy(&dt, pc, sizeof(CegoDataType));
	
	pc += sizeof(CegoDataType);
	
	int flen;
	
	if (dt == VARCHAR_TYPE
	    || dt == BIGINT_TYPE
	    || dt == DECIMAL_TYPE
	    || dt == FIXED_TYPE )
	{
	    memcpy(&flen, pc, sizeof(int));
	    pc += sizeof(int);
	}
	else
	{
	    CegoTypeConverter tc;
	    flen = tc.getTypeLen(dt);	    
	}
		
	if (pF->getId() == id )
	{
	    pF->getValue().setType(dt);
	    pF->getValue().setLength(flen);
	    // pF->setId(id);
	    
	    if ( flen > 0)
		pF->getValue().setValue(pc);
	    else
		pF->getValue().setValue(0);
	    pF->getValue().setLocalCopy(false);
	    
	    // cout << "Decoded valued " << pF->getValue() << endl;
	    
	    pF = fvl.Next();
	}
	
	if ( flen > 0 )
	{	    
	    pc += flen;
	}
    }
    /*
    if ( pF )
    {
	cout << "Decoding not complete !!!!!!! => " << pF->getId() << endl;
    }
    */
}



void CegoQueryHelper::decodeFVL(ListT<CegoField>& fvl, ListT<CegoBlob>& blobList, char* pc, int len, int &tid, int &tastep, CegoTupleState& ts)
{
    
    // make sure no field values are set
    CegoField* pF = fvl.First(); 
    while ( pF )
    {
	CegoFieldValue nullValue;
	pF->setValue(nullValue);
	pF = fvl.Next();	
    }

    char* pBase = pc;
    
    memcpy(&tid, pc, sizeof(int));
    pc += sizeof(int);

    memcpy(&tastep, pc, sizeof(int));
    pc += sizeof(int);

    memcpy(&ts, pc, sizeof(CegoTupleState));
    pc += sizeof(CegoTupleState);

    bool eot = false;
    while (pc - pBase < len && eot == false )
    {
	int id;
	memcpy(&id, pc, sizeof(int));

	if ( id > 0 )
	{
	    pc += sizeof(int);
	    
	    CegoDataType dt;
	    memcpy(&dt, pc, sizeof(CegoDataType));
	    pc += sizeof(CegoDataType);
	    
	    int flen=0;
	    long blobSize=0;
	    
	    if (dt == VARCHAR_TYPE
		|| dt == BIGINT_TYPE
		|| dt == DECIMAL_TYPE
		|| dt == FIXED_TYPE )	    
	    {
		memcpy(&flen, pc, sizeof(int));
		pc += sizeof(int);
	    }
	    else if (dt == BLOB_TYPE )
	    {
		memcpy(&blobSize, pc, sizeof(long));
		pc += sizeof(long);
	    }
	    else
	    {
		CegoTypeConverter tc;
		flen = tc.getTypeLen(dt);
	    }
	    
	    bool found = false;
	    CegoField* pF = fvl.First(); 
	    while (pF && ! found )
	    {
		if (pF->getId() == id )
		{
		    if ( dt == BLOB_TYPE )
		    {
			pF->getValue().setType(dt);
			unsigned char *blobBuf = (unsigned char*)malloc(blobSize);
			memcpy(blobBuf, pc, blobSize);
			blobList.Insert( CegoBlob(0,0, blobBuf, blobSize) );
		    }
		    else
		    {
			
			pF->getValue().setType(dt);
			pF->getValue().setLength(flen);
			pF->setId(id);
			
			if ( flen > 0)
			    pF->getValue().setValue(pc);
			else
			    pF->getValue().setValue(0);
			pF->getValue().setLocalCopy(false);
			
			
		    }
		    found = true;
		}
		pF = fvl.Next();
	    }
	    if ( blobSize > 0 )
	    {
		pc += blobSize;
	    }
	    if ( flen > 0 )
	    {
		pc += flen;
	    }
	}
	else
	{
	    eot = true;
	}
    }
}

void CegoQueryHelper::decodeNativeFVL(ListT<CegoFieldValue>& fvl, ListT<CegoBlob>& blobList, char* pc, int len, int &tid, int& tastep, CegoTupleState& ts)
{
		
    char* pBase = pc;

    memcpy(&tid, pc, sizeof(int));    
    pc = pc + sizeof(int);

    memcpy(&tastep, pc, sizeof(int));    
    pc = pc + sizeof(int);

    memcpy(&ts, pc, sizeof(CegoTupleState));
    pc = pc + sizeof(CegoTupleState);


    bool eot = false;    
    while (pc - pBase < len && eot == false)
    {		    
	int id;
	memcpy(&id, pc, sizeof(int));

	if ( id > 0 )
	{       
	    pc += sizeof(int);
	    
	    CegoDataType dt;
	    memcpy(&dt, pc, sizeof(CegoDataType));
	    
	    pc += sizeof(CegoDataType);
	    
	    int flen=0;
	    long blobSize=0;
	    
	    if (dt == VARCHAR_TYPE
		|| dt == BIGINT_TYPE
		|| dt == DECIMAL_TYPE
		|| dt == FIXED_TYPE )	    
	    {
		memcpy(&flen, pc, sizeof(int));
		pc += sizeof(int);
	    }
	    else if (dt == BLOB_TYPE )
	    {
		memcpy(&blobSize, pc, sizeof(long));
		pc += sizeof(long);
	    }
	    else
	    {
		CegoTypeConverter tc;
		flen = tc.getTypeLen(dt);
	    }
	    
	    if ( dt == BLOB_TYPE )
	    {
		CegoFieldValue fv(dt, Chain("[0,0]"));
		unsigned char *blobBuf = (unsigned char*)malloc(blobSize);
		memcpy(blobBuf, pc, blobSize);
		blobList.Insert( CegoBlob(0,0, blobBuf, blobSize) );
		
		fvl.Insert(fv);
	    }
	    else
	    {
		CegoFieldValue fv(dt, pc, flen);
		fvl.Insert(fv);
	    }
	    
	    if ( blobSize > 0 )
	    {
		pc += blobSize;
	    }
	    if ( flen > 0 )
	    {
		pc += flen;
	    }
	}   
	else
	{
	    eot = true;
	}
    }
}

void CegoQueryHelper::encodeUpdRec(const Chain& tableAlias,
				   CegoPredDesc* pPred,
				   const ListT<CegoField>& updList,
				   const ListT<CegoExpr*>& exprList,
				   CegoProcBlock* pBlock,
				   char* &pBuf, int &buflen)
{

    char* updBuf;
    int updBufLen = 0;
    char* predBuf;
    int predBufLen = 0;
    char* expBuf;
    int expBufLen = 0;

    if ( pPred )
    {
	if ( pBlock ) 
	    pPred->setBlock(pBlock);
	predBufLen = pPred->getEncodingLength() + sizeof(char);
	predBuf = (char*)malloc( predBufLen );
	char* pP = predBuf;
	char c = 1;
	memcpy(pP, &c, sizeof(char));
	pP = pP + sizeof(char);
	pPred->encode(pP);
	
    }
    else
    {
	char c = 0;
	predBufLen = sizeof(char);
	predBuf = (char*)malloc( predBufLen);
	memcpy(predBuf, &c, sizeof(char));
    }

    encodeFL(updList, updBuf, updBufLen);

    expBufLen = 0;
    CegoExpr **pExpr = exprList.First();
    while ( pExpr )
    {
	expBufLen += (*pExpr)->getEncodingLength();
	pExpr = exprList.Next();
    }
    expBuf = (char*)malloc( expBufLen );
    char *pExpBuf = expBuf;
    pExpr = exprList.First();
    while ( pExpr )
    {
	int len = (*pExpr)->getEncodingLength();
	(*pExpr)->encode(pExpBuf);
	pExpBuf += len;
	pExpr = exprList.Next();
    }

    int aliasLen = tableAlias.length();

    buflen = predBufLen
	+ sizeof(int) + aliasLen
	+ sizeof(int) + updBufLen +
	+ sizeof(int) + expBufLen;

    pBuf = (char*)malloc(buflen);

    char* pBP = pBuf;

    memcpy(pBP, &aliasLen, sizeof(int));
    pBP = pBP + sizeof(int);

    memcpy( pBP, (char*)tableAlias, aliasLen);
    pBP = pBP + aliasLen;

    memcpy(pBP, predBuf, predBufLen);
    pBP = pBP + predBufLen;
    
    memcpy(pBP, &updBufLen, sizeof(int));
    pBP = pBP + sizeof(int);

    memcpy(pBP, updBuf, updBufLen);
    pBP = pBP + updBufLen;

    memcpy(pBP, &expBufLen, sizeof(int));
    pBP = pBP + sizeof(int);

    memcpy(pBP, expBuf, expBufLen);
    pBP = pBP + expBufLen;

    free ( predBuf );
    free ( updBuf );
    free ( expBuf );

}

void CegoQueryHelper::decodeUpdRec(Chain& tableAlias,
				   CegoPredDesc* &pPred, 
				   ListT<CegoField>& updList, 
				   ListT<CegoExpr*>& exprList,
				   char* pBuf, int buflen,
				   CegoDistManager *pGTM)
{

    int aliasLen;
    memcpy(&aliasLen, pBuf, sizeof(int));
    pBuf += sizeof(int);

    tableAlias = Chain(pBuf, aliasLen-1);
    pBuf += aliasLen;
    
    char c = 0;
    memcpy(&c, pBuf, sizeof(char));
    pBuf += sizeof(char);

    if ( c == 1 )
    {
	pPred = new CegoPredDesc(pBuf, pGTM);
	pBuf += pPred->getEncodingLength();
    }
    else
    {
	pPred = 0;
    }

    int updBufLen;
    memcpy(&updBufLen, pBuf, sizeof(int));
    pBuf += sizeof(int);

    decodeFL(updList, pBuf, updBufLen);

    pBuf += updBufLen;

    int expBufLen;
    memcpy(&expBufLen, pBuf, sizeof(int));
    pBuf += sizeof(int);

    int pos = 0;
    while ( pos < expBufLen  )
    {
	CegoExpr *pExpr = new CegoExpr(pBuf, pGTM);

	int len = pExpr->getEncodingLength();
	pos += len;
	pBuf += len;

	exprList.Insert(pExpr);

    }
}

void CegoQueryHelper::encodeDelRec(const Chain& tableAlias,
				   CegoPredDesc* pPred,
				   CegoProcBlock* pBlock,
				   char* &pBuf, int &buflen)

{

    char* predBuf;
    int predBufLen = 0;

    if ( pPred )
    {
	if ( pBlock ) 
	    pPred->setBlock(pBlock);
	predBufLen = pPred->getEncodingLength() + sizeof(char);
	predBuf = (char*)malloc( predBufLen );
	char* pP = predBuf;
	char c = 1;
	memcpy(pP, &c, sizeof(char));
	pP = pP + sizeof(char);
	pPred->encode(pP);
	
    }
    else
    {
	char c = 0;
	predBufLen = sizeof(char);
	predBuf = (char*)malloc( predBufLen);
	memcpy(predBuf, &c, sizeof(char));
    }

    int aliasLen = tableAlias.length();

    buflen = predBufLen
	+ sizeof(int) + aliasLen;
    
    pBuf = (char*)malloc(buflen);

    char* pBP = pBuf;

    memcpy(pBP, &aliasLen, sizeof(int));
    pBP = pBP + sizeof(int);

    memcpy( pBP, (char*)tableAlias, aliasLen);
    pBP = pBP + aliasLen;

    memcpy(pBP, predBuf, predBufLen);
    pBP = pBP + predBufLen;
    
    free ( predBuf );

}

void CegoQueryHelper::decodeDelRec(Chain& tableAlias,
				   CegoPredDesc* &pPred,
				   char* pBuf, int buflen,
				   CegoDistManager *pGTM)
{        
    int aliasLen;
    memcpy(&aliasLen, pBuf, sizeof(int));
    pBuf += sizeof(int);
    
    tableAlias = Chain(pBuf, aliasLen-1);
    pBuf += aliasLen;
    
    char c = 0;
    memcpy(&c, pBuf, sizeof(char));
    pBuf += sizeof(char);

    if ( c == 1 )
    {
	pPred = new CegoPredDesc(pBuf, pGTM);
	pBuf += pPred->getEncodingLength();
    }
    else
    {
	pPred = 0;
    }

}


void CegoQueryHelper::evalSelection(ListT<CegoExpr*>& exprList, ListT<CegoField>* joinBuf, int jbufSize, bool isAgg, ListT<CegoField>& ol) 
{

    if ( exprList.isEmpty() )
    {
	
	for ( int i = 0; 
	      i < jbufSize; 
	      i++ )
	{
	    CegoField* pF = joinBuf[i].First();
	    while ( pF ) 
	    {				
		ol.Insert(*pF);
		pF = joinBuf[i].Next();
	    }
	}
	return;
    }

    if ( isAgg )
    {
	CegoExpr** pExpr = exprList.First();
	while ( pExpr )
	{
	    
	    (*pExpr)->setFieldListArray( joinBuf, jbufSize);
	    
	    ListT<CegoField> fl = (*pExpr)->getFieldList();

	    CegoField *pF = fl.First();
	    while ( pF )
	    {
		int i =0;	       
		CegoField *pJF = 0;
		while ( i < jbufSize && pJF == 0 )
		{
		    CegoField *pJF = joinBuf[i].Find(*pF);
		    if ( pJF )
		    {
			pF->setValue(pJF->getValue());			
		    }	       
		    i++;
		}
		
		pF = fl.Next();
	    }
	    
	    ol = ol + fl;

	    pExpr = exprList.Next();
	}
    }
    else
    {

	CegoExpr** pExpr = exprList.First();
	while ( pExpr )
	{

	    CegoAttrDesc* pAttrDesc = (*pExpr)->checkAttr();
	    if ( pAttrDesc )
	    {
		if ( pAttrDesc->getAttrName() == Chain(SELECTION_WILDCARD))
		{
		    
		    int i=0;
		    while ( i < jbufSize )
		    {		    
			CegoField *pF = joinBuf[i].First();
			while ( pF )
			{
			    if ( (Chain)pF->getTableName() ==  (Chain)pAttrDesc->getTableName()
				 || (Chain)pF->getTableAlias() ==  (Chain)pAttrDesc->getTableName() )
			    {			    
				ol.Insert(*pF);
			    }
			    pF = joinBuf[i].Next();
			}
			i++;
		    }
		}
		else
		{
		    (*pExpr)->setFieldListArray( joinBuf, jbufSize);
		    CegoField f = (*pExpr)->evalField();
		    f.setValue ( (*pExpr)->evalFieldValue() ); 
		    ol.Insert ( f );
		}
	    }	
	    else
	    {
		(*pExpr)->setFieldListArray( joinBuf, jbufSize);
		CegoField f = (*pExpr)->evalField();
		f.setValue ( (*pExpr)->evalFieldValue() ); 
		ol.Insert ( f );
	    }
	    pExpr = exprList.Next();
	}
    }
       
    return;
    
}

void CegoQueryHelper::createConjunctionList(CegoPredDesc* pPred, ListT<CegoPredDesc*>& conjunctionList)
{
    if (pPred)
    {
	CegoCondDesc* pC = pPred->getCondition();	
	if (pC)
	{
	    if (pC->getCondType() == CegoCondDesc::AND)
	    {
		createConjunctionList(pC->Left(), conjunctionList);
		createConjunctionList(pC->Right(), conjunctionList);
	    }
	    else
	    {
		conjunctionList.Insert(pPred);
	    }
	}
	else
	{
	    conjunctionList.Insert(pPred);
	}
    }
}

