#ifndef _CEGOQUERYHELPER_H_INCLUDED_
#define _CEGOQUERYHELPER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoQueryHelper.h
// -----------------
// Cego query helper
//
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoQueryHelper
// 
// Description: The CegoQueryHelper class provides several utility methods with are used for tuple retrieval and evalution
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

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

// cego includes
#include "CegoAttrCond.h"
#include "CegoPredDesc.h"
#include "CegoCondDesc.h"
#include "CegoField.h"
#include "CegoFieldValue.h"
#include "CegoProcBlock.h"
#include "CegoExpr.h"
#include "CegoBlob.h"
#include "CegoClob.h"
#include "CegoTupleState.h"
#include "CegoAttrAlias.h"
#include "CegoAliasObject.h"

class CegoQueryHelper {
    
public:

    enum AttrCondMatch { INAPP, PARTIAL, COMPLETE };

    CegoQueryHelper();
    ~CegoQueryHelper();

    // makes conjunctive normal form for the given condition
    static void makeCNF(CegoCondDesc *pC);

    static void createConjunctionList(CegoPredDesc* pPred, ListT<CegoPredDesc*>* pConjunctionList);

    // evaluates the given predicate with the given join buffers and returns the logical result
    static bool evalPredicate(ListT<CegoField>** pParentList,
		       int parentJoinBufPos,
		       ListT<CegoField>** pJoinBuf,
		       int pos,
		       CegoPredDesc* pP, 
		       CegoProcBlock *pBlock = 0 );

    // filters a normalized attribute condition from the given predicate
    static AttrCondMatch checkAttrCond(CegoAttrCond& ac,
		      CegoPredDesc* pP, 
		      const ListT<CegoField>& schema,
		      ListT<CegoField>* flArray, 
		      int flSize, 
		      CegoProcBlock *pBlock);

    // internal debugging methods, not used by any class
    static Chain condToChain(CegoCondDesc* pC, int depth);
    static Chain predToChain(CegoPredDesc* pP, int depth);
    
    // for grouping and aggregation queries, these methods are used by CegoSelect and CegoGroupSpace
    static void aggregateTuple(ListT<CegoField>& aggTuple, CegoExpr* pExpr);
    static void aggregateTuple(ListT<CegoField>& aggTuple, CegoAggregation* pAgg);

    // the given field value is checked for type information of the given field and casted if required 
    static void prepareFieldValue(CegoField* pFV, CegoFieldValue& fv, CegoTableManager* pTM, int tabSetId);


    static bool checkIndexForPredicate(int tabSetId, CegoDistManager* pGTM, CegoPredDesc *pPred);
    
    // field list encoding and decoding methods
    static void encodeFL(const ListT<CegoField>& fvl, char* &pBufBase, int &buflen);    
    static void decodeFL(ListT<CegoField>& fvl, char* pc, int len);

    static int encodeFVL(unsigned long long tid, unsigned long long tastep, CegoTupleState ts, const ListT<CegoField>& fvl, char* &pBufBase, int& buflen);
    static int encodeFVL(unsigned long long tid, unsigned long long tastep, CegoTupleState ts, const ListT<CegoField>& fvl, const ListT<CegoBlob>& blobList, const ListT<CegoClob>& clobList, char* &pBufBase, int& buflen);

    static int skipTupleHeader();

    static int encodeTupleHeader(unsigned long long tid, unsigned long long tastep, CegoTupleState ts, char* p);
    static int decodeTupleHeader(unsigned long long& tid, unsigned long long& tastep, CegoTupleState& ts, char* p);

    static void decodeFVL(ListT<CegoField>& fvl, char* pc, int len);
    static void decodeFVL(ListT<CegoField>& fvl, ListT<CegoBlob>& blobList, ListT<CegoClob>& clobList, char* pc, int len);
    static void decodeNativeFVL(ListT<CegoFieldValue>& fvl, ListT<CegoBlob>& blobList, ListT<CegoClob>& clobList, char* pc, int len);
    
    static void decodeUpdRec(Chain& tableAlias,
			     CegoPredDesc* &pPred, 
			     ListT<CegoField>& updList, 
			     ListT<CegoExpr*>& exprList,
			     char* pBuf, int buflen,
			     CegoDistManager* pGTM, int tabSetId); 
    
    static void encodeUpdRec(const Chain& tableAlias,
			     CegoPredDesc* pPred, 
			     const ListT<CegoField>& updList,
			     const ListT<CegoExpr*>& exprList,
			     const ListT<CegoBlob>& blobList,
			     const ListT<CegoClob>& clobList,			     
			     CegoProcBlock* pBlock,
			     char* &pBuf, int &buflen);

    static void decodeDelRec(Chain& tableAlias,
			     CegoPredDesc* &pPred,
			     char* pBuf, int buflen,
			     CegoDistManager *pGTM, int tabSetId);
    
    static void encodeDelRec(const Chain& tableAlias,
			     CegoPredDesc* pPred,
			     CegoProcBlock* pBlock,
			     char* &pBuf, int &buflen);

    static void mapAliasSchema(ListT<CegoField>& schema, const ListT<CegoAttrAlias>& aliasList);
    static void mapAliasPredicate(CegoPredDesc* pPred, const Chain& tableAlias, const ListT<CegoAttrAlias>& aliasList);

    static CegoAttrCond mapAttrCond(const CegoAttrCond& attrCond, CegoAliasObject* pAO);

    static void mapFLA(ListT<CegoField>* pFLAmap, ListT<CegoField>** pFLA, int offset, int size, CegoAliasObject* pAO);
    static void propFLA(ListT<CegoField>* pFLAprop, ListT<CegoField>** pFLA, int offset, int size, CegoAliasObject* pAO);

    static int maxFieldSize(CegoField *pF);
    
private:

    static bool evalFields(CegoComparison comp, const CegoFieldValue& f1, const CegoFieldValue& f2);
    static bool evalBetween(const CegoFieldValue& f1, const CegoFieldValue& f2, const CegoFieldValue& f3);
    
    static void createConjunctionList(CegoPredDesc* pPred, ListT<CegoPredDesc*>& conjunctionList);

    static bool string2Clob(CegoField* pFV, CegoFieldValue& fv, CegoTableManager* pTM, int tabSetId);

    static AttrCondMatch evalAttrCond(CegoAttrCond& ac,		      
		      CegoPredDesc* pP, 
		      const ListT<CegoField>& schema,
		      ListT<CegoField>* flArray, 
		      int flSize, 
		      CegoProcBlock *pBlock);
    
    static AttrCondMatch evalAttrCondbyCondition(CegoAttrCond& ac,
					  CegoCondDesc* pC,
					  const ListT<CegoField>& schema,
					  ListT<CegoField>* flArray, 
					  int flSize,
					  CegoProcBlock* pBlock);
    
    static int max(int i1, int i2, int i3, int i4);
};

#endif
