#ifndef _CEGOSELECT_H_INCLUDED_
#define _CEGOSELECT_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoSelect.h
// ------------
// Cego select query handling
//
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoSelect
// 
// Description: This class implements the SQL select query algorithm for the Cego database system 
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// base includes
#include <lfcbase/ListT.h>
#include <lfcbase/SetT.h>

// xml includes
#include <lfcxml/Element.h>

// cego includes
#include "CegoProcBlock.h"
#include "CegoDefs.h"
#include "CegoFactor.h"
#include "CegoDistManager.h"
#include "CegoDistCursor.h"
#include "CegoField.h"
#include "CegoPredDesc.h"
#include "CegoCondDesc.h"
#include "CegoContentObject.h"
#include "CegoOrderSpace.h"
#include "CegoGroupSpace.h"
#include "CegoHavingDesc.h"
#include "CegoTerm.h"
#include "CegoExpr.h"
#include "CegoContentObject.h"
#include "CegoQueryCache.h"

class CegoProcBlock;

class CegoSelect {
    
public:

    enum SelectMode { SIMPLE, PLAIN, AGGREGATION, GROUPING };
	
    CegoSelect(char* buf, CegoDistManager* pGTM, int tabSetId);
    CegoSelect(Element* pSelectElement, CegoDistManager* pGTM);
    CegoSelect(ListT<CegoContentObject*>& coList,
	       ListT<CegoExpr*>& exprList, 
	       CegoPredDesc* pPred,
	       ListT<CegoAttrDesc*> *pGroupList,
	       CegoHavingDesc* pHaving,
	       ListT<CegoExpr*> *pOrderList,
	       ListT<CegoOrderNode::Ordering>* pOrderOptList,
	       bool isDistinct,
	       int rowLimit,
	       CegoDistManager* pGTM);

    ~CegoSelect();

    void setTableManager(CegoDistManager* pGTM);

    void setUnionSelect(CegoSelect* pUnion);

    void cleanUp();
    void prepare();
    void reset(bool doRelease);

    Element* getPlan();

    bool nextTuple(ListT<CegoField>& jfl);

    bool isCacheEnabled() const;
    bool isCached() const;
    Chain getQueryId() const;
    
    void getObjectList( SetT<CegoObject>& objList ) const;
    
    void checkValidRef();
    void setParentJoinBuf(ListT<CegoField>** pParentJoinBuf = 0);
    void setProcBlock(CegoProcBlock *pBlock);

    int evalExtTableReferences(CegoContentObject* pCO, const ListT<CegoField>& fl);

    CegoPredDesc* getPredicate();

    bool hasAliasReference() const;
    void getSchema(ListT<CegoField>& schema);
    Chain toChain(const Chain& indent = Chain("")) const;
    Chain dbFormat(CegoDatabaseFormater *pForm) const;
    
    Element* toElement() const;
    void fromElement(Element *pSelectElement, CegoDistManager* pGTM);
    
    ListT<CegoAttrDesc*> getAttrRefList() const;
    void getFieldList(ListT<CegoField>& fl) const;

    void encode(char *buf);
    void decode(char *buf, CegoDistManager* pGTM, int tabSetId);
    int getEncodingLength() const;
    
    void setViewCond( CegoAttrCond& attrCond, ListT<CegoField> **pFLA);
    
    void setTabSetId(int tabSetId);

    int getExtRefCount() const;

    CegoSelect* clone( bool isAttrRef = false);
    
private:

    int evalTableReferences(CegoContentObject* pCO, const ListT<CegoField>& fl);

    bool isPrepared() const;
    void analyzeJoin();

    void evalSchema();
    
    bool nextAggTuple(ListT<CegoField>& jfl);
    bool nextOrderedTuple(ListT<CegoField>& jfl);
    bool nextResultTuple(ListT<CegoField>& jfl, ListT<CegoField>& ofl);

    bool nextGroupedTuple(ListT<CegoField>& jfl);
    bool nextJoinTuple(ListT<CegoField>& jfl, ListT<CegoField>& ofl);
    void createConjunctionList(CegoPredDesc* pPred);
    void consolidateConjunctionList();

    void evalReferences();

    void filterRefs(ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);   
    void filterFacRef(CegoFactor *pFac, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    void filterExprRef(CegoExpr *pExpr, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    void filterTermRef(CegoTerm *pTerm, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    void filterPredRef(CegoPredDesc *pP, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    void filterCondRef(CegoCondDesc* pC, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    void filterAttrRef(CegoAttrDesc* pAttrDesc, ListT<CegoField>& inSchema, ListT<CegoField>& outSchema);
    
    // the evalSelection finalizes the selection procedure by evaluating the expressions defined in 
    // the selection part. Either these are plain attributes, expressions or aggregation functions 
    // the result is given in the outList parameter
    void evalSelection(ListT<CegoExpr*>& exprList, ListT<CegoField>** joinBuf, ListT<CegoField>& ol);

    void buildJoinTables();
    void buildJoinRefs();
    void buildJoinConditions();

    void getPredObjectList(CegoPredDesc *pPred, ListT<CegoContentObject*>& objectList);
    void getCondObjectList(CegoCondDesc* pC, ListT<CegoContentObject*>& objectList);

    void initAggregation();
    void aggregateTuple(ListT<CegoField>& aggTuple);
    void evalAggregation(ListT<CegoField>& resultList);

    void prepareOrder();

    // no more used for performance reasons
    // void clearCache();
    
    bool matchFieldValue(const CegoFieldValue& fv1, const CegoFieldValue& fv2, CegoComparison comp);    
    void setAggregationValue(CegoExpr *pExpr, ListT<CegoField>& jfl);

    void addObject4CO(CegoContentObject *pCO, SetT<CegoObject>& objList) const;

    void setExtRefCount(int refCount);
	
    ListT<CegoPredDesc*> _viewConjunctionList;
    ListT<CegoPredDesc*> _conjunctionList;

    ListT<CegoExpr*> _exprList;
    CegoPredDesc* _pPred;
    ListT<CegoPredDesc*> _joinPredList;

    CegoDistManager* _pGTM;
    
    ListT<CegoContentObject*> _coList;
    ListT<CegoContentObject*> _joinList;

    ListT<CegoField> _joinFields;

    int _joinLevel;
    int _joinSize;

    int _dcount;

    ListT<CegoField>* _joinBuf[TABMNG_MAXJOINLEVEL];
    ListT<CegoField>**  _pParentJoinBuf;

    CegoDistCursor*_pTC[TABMNG_MAXJOINLEVEL];

    CegoAttrCond _attrCond[TABMNG_MAXJOINLEVEL];
    bool _attrCondFlag[TABMNG_MAXJOINLEVEL];
    CegoPredDesc* _attrPred[TABMNG_MAXJOINLEVEL];
    bool _firstTuple[TABMNG_MAXJOINLEVEL];

    CegoDatabaseManager *_pDBMng;

    int _aggregationCount;
    int _nextAid;
    int _tabSetId;

    ListT<CegoAttrDesc*>* _pGroupList;
    ListT<CegoExpr*>* _pNativeOrderList;
    ListT<CegoExpr*>* _pOrderList;
    ListT<CegoOrderNode::Ordering>* _pNativeOrderOptList;
    ListT<CegoOrderNode::Ordering>* _pOrderOptList;
    
    CegoProcBlock *_pBlock;

    enum SelectMode _selectMode;
    bool _aggDone;
    bool _orderingDone;
    bool _groupingDone;
    bool _simpleDone;
    bool _isDistinct;

    ListT<CegoField> _orderedSchema;
    ListT<CegoField> _dfl;
    ListT<CegoField> _evalSchema;

    bool _cacheEnabled;
    CegoQueryCache *_pCache;
    ListT<CegoField> _cacheSchema;
    CegoFieldValue*** _pCacheArray;
    ListT< ListT<CegoFieldValue> >* _pCacheList;
    int _cacheRows;
    unsigned long _cacheEntrySize;
    bool _isCached;
    Chain _viewCondId;
    Chain _queryId;
        
    CegoOrderCursor *_pOrderCursor;
    CegoOrderSpace* _pOrderSpace;

    CegoGroupCursor *_pGroupCursor;
    CegoGroupSpace* _pGroupSpace;

    CegoHavingDesc* _pHaving;

    bool _isPrepared;
    int _rowCount;
    int _rowLimit;

    bool _checkUnion;
    CegoSelect* _pUnionSelect;

    int _extRefCount;

    unsigned long _modId;
};

#endif




