#ifndef _CEGOTABLEMANAGER_H_INCLUDED_
#define _CEGOTABLEMANAGER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoTableManager.h
// ------------------
// Cego table manager class definition
// 
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2025 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoTableManager
// 
// Description: Basic table management
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

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

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

// cego includes
#include "CegoDataType.h"
#include "CegoTupleState.h"
#include "CegoField.h"
#include "CegoPredicate.h"
#include "CegoQueryHelper.h"
#include "CegoLockHandler.h"
#include "CegoAlterDesc.h"
#include "CegoDefs.h"
#include "CegoProcedure.h"
#include "CegoView.h"
#include "CegoSystemObject.h"
#include "CegoBTreeValue.h"
#include "CegoTrigger.h"
#include "CegoObjectCursor.h"

class CegoDbThreadPool;
class CegoTransactionManager;

class CegoTableManager : public CegoSystemObject {

public:

    enum IsolationLevel { READ_COMMITTED, READ_UNCOMMITTED };

    CegoTableManager(CegoDatabaseManager *pDBMng);
    ~CegoTableManager();

    void setThreadId(unsigned long long tid);
    unsigned long long getThreadId() const;
    void setAppend(bool doAppend);
    void createBasicTableSet(const Chain& tableSet);
    void dropTableSet(const Chain& tableSet);
    void reorgTableSet(const Chain& tableSet);
    void stopTableSet(const Chain& tableSet, bool archComplete);
    void resetTableSet(const Chain& tableSet);
    void beginBackup(const Chain& tableSet, const Chain& msg);
    void endBackup(const Chain& tableSet, const Chain&msg, bool keepTicket = true);
    void resetBUStat(const Chain& tableSet);
    void syncTableSet(const Chain& tableSet, const Chain& msg, const Chain& escCommand, unsigned timeout);
    // void logTo(const Chain& tableSet);
    void addDataFile(const Chain& tableSet, const Chain& type, unsigned fileId, const Chain& dataFile, unsigned fileSize);
    // transaction methods
    void setIsolationLevel(IsolationLevel level);
    IsolationLevel getIsolationLevel() const;
    void setAutoCommit(bool autoCommit);
    bool getAutoCommit() const;
    void lockTable(unsigned tabSetId, const Chain& tableName);
    void unlockTable(unsigned tabSetId, const Chain& tableName);
    void beginTransaction(unsigned tabSetId, bool doLog);
    void getTransactionAffectedTables(unsigned tabSetId, SetT<Chain>& tableList);
    unsigned long long commitTransactionSynced(unsigned tabSetId);
    unsigned long long commitTableTransaction(unsigned tabSetId, bool doLog);
    unsigned long long rollbackTableTransaction(unsigned tabSetId, bool doLog);
    unsigned long long rollbackTransactionSynced(unsigned tabSetId);
    unsigned long long getTID(unsigned tabSetId);
    void setTAStep(unsigned tabSetId, unsigned long long tastep);
    unsigned long long getTAStep(unsigned tabSetId);
    void setTID(unsigned tabSetId, unsigned long long tid);
    void getTupleInfo(unsigned tabSetId, const CegoDataPointer dp, unsigned long long &tid, unsigned long long &tastep, CegoTupleState &ts);
    void setTupleInfo(unsigned tabSetId, const CegoDataPointer dp, unsigned long long tid, unsigned long long tastep, CegoTupleState ts);
    // table methods
    CegoTableObject createDataTable(unsigned tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoField>& fl, bool useColumnId = false);
    void alterDataTableSynced(CegoTableObject& oe, const ListT<CegoAlterDesc>& alterList);
    void alterDataTable(unsigned tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoAlterDesc>& alterList);
    void renameObject(unsigned tabSetId, const Chain& objName,  CegoObject::ObjectType type, const Chain& newObjName);
    void reorgObjectSynced(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);
    void reorgTable(unsigned tabSetId, const Chain& tableName);
    void invalidateIndexForTable(unsigned tabSetId, const Chain& tableName);
    void insertDataTable(CegoTableObject& oe,
			 ListT<CegoField>& fvl,
			 CegoDataPointer& dp, 
			 bool doLogging, bool flushLog);
    void insertDataTable(CegoTableObject& oe,  ListT<CegoField>& fvl, 
			 const ListT<CegoTableObject>& idxList,
			 const ListT<CegoBTreeObject>& btreeList,
			 const ListT<CegoKeyObject>& keyList,
			 const ListT<CegoCheckObject>& checkList,
			 const CegoDataPointer& sysEntry,
			 const Chain& virginIndex,
			 CegoDataPointer& dp, 
			 bool doLogging, bool doAppend, bool increaseStep, bool flushLog);
    unsigned long long deleteDataTable(CegoTableObject& oe, CegoPredicate* pPred, CegoProcBlock* pBlock, bool isSynced);
    unsigned long long deleteDataTable(CegoTableObject& oe,
				       const ListT<CegoTableObject>& idxList,
				       const ListT<CegoBTreeObject>& btreeList,
				       const ListT<CegoKeyObject>& keyList,
				       CegoPredicate* pPred, CegoProcBlock* pBlock, bool isSynced);
    void deleteDataTableEntrySynced(unsigned tabSetId, 
				    const Chain& tableName,
				    CegoObject::ObjectType type, 
				    const CegoDataPointer& dp,
				    const ListT<CegoField>& fvl, 
				    const ListT<CegoTableObject>& idxList,
				    const ListT<CegoBTreeObject>& btreeList,
				    const ListT<CegoKeyObject>& keyList,
				    bool doCheckKey, 
				    bool doIgnoreIndexError,
				    bool isSynced);
    bool deleteDataTableEntry(unsigned tabSetId, 
			      const Chain& tableName,
			      CegoObject::ObjectType type, 
			      const CegoDataPointer& dp,
			      const ListT<CegoField>& fvl,
			      const ListT<CegoTableObject>& idxList,
			      const ListT<CegoBTreeObject>& btreeList,
			      const ListT<CegoKeyObject>& keyList,
			      bool doCheckKey = true, 
			      bool doIgnoreIndexError = false);
    unsigned long long updateDataTable(unsigned tabSetId,
				       const Chain& tableName,
				       const Chain& tableAlias,
				       CegoPredicate* pPred,
				       const ListT<CegoField>& updList,
				       ListT<CegoExpr*>& exprList,
				       bool returnOnFirst,
				       ListT<CegoField>& returnList,
				       CegoProcBlock* pBlock = 0);
    unsigned long long updateDataTable(unsigned tabSetId, 
				       const Chain& tableName,
				       const Chain& tableAlias,				       
				       const ListT<CegoTableObject>& idxList, 
				       const ListT<CegoBTreeObject>& btreeList, 
				       const ListT<CegoKeyObject>& keyList, 
				       const ListT<CegoCheckObject>& checkList,				       
				       CegoPredicate* pPred,
				       const ListT<CegoField>& updList, 
				       ListT<CegoExpr*>& exprList,
				       bool returnOnFirst,
				       ListT<CegoField>& returnList, 
				       CegoProcBlock* pBlock);
    void truncateTable(unsigned tabSetId, const Chain& tableName);
    void dropObjectSynced(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);
    void dropTable(unsigned tabSetId, 
		   const Chain& tableName);
    void dropIndex(unsigned tabSetId, const Chain& idxName);
    void dropBTree(unsigned tabSetId, const Chain& btreeName);
    void dropView(unsigned tabSetId, const Chain& viewName);
    void dropProcedure(unsigned tabSetId, const Chain& procName);
    void dropFKey(unsigned tabSetId, const Chain& fkey);
    void dropCheck(unsigned tabSetId, const Chain& check);
    void dropTrigger(unsigned tabSetId, const Chain& trigger);
    void dropAlias(unsigned tabSetId, const Chain& aliasName);
    void correctTableSet(unsigned tabSetId, bool doSync);
    void correctIndexForTable(unsigned tabSetId, const Chain& tableName, bool doSync, bool doForce);
    unsigned cleanTableSet(unsigned tabSetId);
    // utility cursor for native table traverse
    bool getFirstTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp);
    bool getNextTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp);
    // index and key creation
    void createIndexTableSynced(unsigned tabSetId, const Chain& indexName, const Chain& tableName, CegoObject::ObjectType type, ListT<CegoField>& idxList, bool isCached);
    void createPrimaryIndexTable(unsigned tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema);
    void createIndexTable(unsigned tabSetId, const Chain& indexName, const Chain& tabName, const ListT<CegoField>& schema, CegoObject::ObjectType type, bool isCached);
    void createBTree(unsigned tabSetId, const Chain& btreeName, const Chain& tableName, const ListT<CegoField>& schema, CegoObject::ObjectType type, bool doSync, bool isCached);
    void createAVLIndexTable(unsigned tabSetId, const Chain& indexName, const Chain& tableName, const ListT<CegoField>& schema, CegoObject::ObjectType type);
    void createForeignKey(unsigned tabSetId, const Chain& fkey, const Chain& tableName, const ListT<CegoField>& keyList, const Chain& refTable, const ListT<CegoField>& refList);
    void createCheck(unsigned tabSetId, const Chain& checkName, const Chain& tableName, CegoPredicate *pPredDesc);
    void createTrigger(unsigned tabSetId, const Chain& triggerName,
		       bool isBefore, bool isOnInsert, bool isOnUpdate, bool isOnDelete,
		       const Chain& tableName, const Chain& triggerText);
    void createAlias(unsigned tabSetId, const Chain& aliasName, const Chain& tableName, const ListT<CegoAttrAlias>& aliasList);
    // info methods
    void getPoolInfo(CegoTableObject& oe, ListT< ListT<CegoFieldValue> > &info);
    void getSystemInfo(const Chain& tableSet, CegoTableObject& oe,  ListT< ListT<CegoFieldValue> > &fa, Chain& format);

    void regDataFiles(const Chain& tableSet);    
    void abort();
    void proceed();
    bool isAborted() const;
    void addCompProcedure(unsigned tabSetId, CegoProcedure *pProc);
    void removeCompProcedure(unsigned tabSetId, const Chain& procName);
    bool checkCompProcedure(unsigned tabSetId, const Chain& procName);
    CegoProcedure* getCompProcedure(unsigned tabSetId, const Chain& procName);
    void addCompView(unsigned tabSetId, CegoView *pView);
    void removeCompView(unsigned tabSetId, const Chain& viewName);
    bool checkCompView(unsigned tabSetId, const Chain& viewName);
    CegoView* getCompView(unsigned tabSetId, const Chain& viewName);
    void addCompTrigger(unsigned tabSetId, CegoTrigger *pTrigger);
    void removeCompTrigger(unsigned tabSetId, const Chain& triggerName);
    bool checkCompTrigger(unsigned tabSetId, const Chain& triggerName);
    CegoTrigger* getCompTrigger(unsigned tabSetId, const Chain& triggerName);
    void removeAllComp(unsigned tabSetId);    
    void getTSLockStat(unsigned tabSetId, Chain& lockName, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);
    void getLHLockStat(unsigned long long lockId, Chain& lockName, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);
    void getLHAggLockStat(const Chain& lockName, unsigned& numLock, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);
    void extractIndexValue(const ListT<CegoField>& tableSchema, const ListT<CegoField>& indexSchema, char* p, unsigned len, unsigned& idxLen);
    void increaseBlobRef(unsigned tabSetId, PageIdType pageId);
    void decreaseBlobRef(unsigned tabSetId, PageIdType pageId);
    void increaseClobRef(unsigned tabSetId, PageIdType pageId);
    void decreaseClobRef(unsigned tabSetId, PageIdType pageId);
    unsigned char* getBlobData(unsigned tabSetId, PageIdType pageId, unsigned long long& blobSize);
    char* getClobData(unsigned tabSetId, PageIdType pageId, unsigned long long& clobSize);
    void putBlobData(unsigned tabSetId, unsigned char* data, unsigned long long blobSize, PageIdType& pageId);
    void putClobData(unsigned tabSetId, char* data, unsigned long long clobSize, PageIdType& pageId);
    CegoTransactionManager* getTransactionManager();
    void setPoolSyncInfo(CegoDbThreadPool *pPool, unsigned thrIdx);
    // debugging methods
    void dumpObject(const Chain& tableSet, const Chain& tableName, CegoObject::ObjectType type, Chain& chainDump);
    void dumpObject(unsigned tabSetId, const Chain& tableName, CegoObject::ObjectType type, Chain& chainDump);
    void extractTicket(const Chain& tableSet);
    
protected:

    CegoTransactionManager *_pTM;
	
    void resetTemp(const Chain& tableSet);
    void finishOpenTransaction(unsigned tabSetId);
    
    unsigned long long _threadId;
    bool _doAppend;
    
private:


    void renameTable(unsigned tabSetId, const Chain& tableName, const Chain& newTableName);
    void renameIndex(unsigned tabSetId, const Chain& idxName, CegoObject::ObjectType type, const Chain& newIdxName);
    void renameBTree(unsigned tabSetId, const Chain& btreeName, CegoObject::ObjectType type, const Chain& newBTreeName);
    void renameKey(unsigned tabSetId, const Chain& keyName, const Chain& newKeyName);
    void renameCheck(unsigned tabSetId, const Chain& checkName, const Chain& newCheckName);
    void renameTrigger(unsigned tabSetId, const Chain& triggerName, const Chain& newTriggerName);
    void renameRBO(unsigned tabSetId, const Chain& rboName, const Chain& newRboName);
    bool updateTuple(CegoTableObject& oe, const Chain& tableAlias,
		     const CegoDataPointer& sysEntry, const CegoDataPointer& dp, 
		     ListT<CegoField>& fl,
		     const ListT<CegoField>& nfvl,
		     ListT<CegoExpr*>& exprList,
		     ListT<CegoField>& updSchema, 
		     const ListT<CegoTableObject>& idxList,
		     const ListT<CegoBTreeObject>& btreeList,
		     const ListT<CegoKeyObject>& keyList,
		     const ListT<CegoCheckObject>& checkList,
		     const Chain& virginIndex,
		     bool doAppend, 
		     CegoProcBlock* pBlock);
    void checkTypes(const ListT<CegoField>& fl, const ListT<CegoField>& nfl);    
    void checkIntegrity(unsigned tabSetId, const Chain& tableName,
			const ListT<CegoTableObject>& idxList,
			const ListT<CegoBTreeObject>& btreeList,
			const ListT<CegoKeyObject>& keyList,
			const ListT<CegoCheckObject>& checkList,
			const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    void getKeyAndIdxRef(unsigned tabSetId, const Chain& tableName, const Chain& attrName, ListT<CegoKeyObject>& refKeyList, ListT<CegoTableObject>& refIdxList, ListT<CegoBTreeObject>& refBTreeList);
    void checkKeyIntegrity(const ListT<CegoKeyObject>& keyList, unsigned tabSetId, const Chain& tableName, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    void checkIndexIntegrity(const ListT<CegoTableObject>& idxList, unsigned tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    void checkBTreeIntegrity(const ListT<CegoBTreeObject>& btreeList, unsigned tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    void checkCheckIntegrity(const ListT<CegoCheckObject>& checkList, const ListT<CegoField>& nfvl);
    bool checkNullValue(unsigned tabSetId, const Chain& tableName, const CegoField& f);
    bool keyReferenceExists(unsigned tabSetId, const Chain& tableName, const ListT<CegoField>& fl, const ListT<CegoKeyObject>& keyList);
    const CegoFieldValue& getIndexSearchValue(const ListT<CegoField>& idxSchema, const ListT<CegoField>& nfvl);
    void getBlobs(unsigned tabSetId, const ListT<CegoField>& fvl, ListT<CegoBlob>& blobList);
    void getClobs(unsigned tabSetId, const ListT<CegoField>& fvl, ListT<CegoClob>& clobList);
    void getBlobs(unsigned tabSetId, ListT<CegoExpr*>& exprList, CegoProcBlock* pBlock, ListT<CegoBlob>& blobList);
    void getClobs(unsigned tabSetId, ListT<CegoExpr*>& exprList, CegoProcBlock* pBlock, ListT<CegoClob>& clobList);
    void addBUStat(unsigned tabSetId, const Chain& butype, const Chain& msg);
    bool typeConversionAllowed(CegoDataType fromType, CegoDataType toType);
    void getClobForExprList(unsigned tabSetId, ListT<CegoExpr*>& exprList, ListT<CegoClob>& clobList);
    void poolP();
    void poolV();

    unsigned long long _tid[TABMNG_MAXTABSET];
    // tastep is an opertion counter inside a single transaction
    // it is used for object cursors to filter out the current transaction operation
    // but rather acces previous modified tuples ( condition : taset(tuple) < tastep(current) )
    unsigned long long _tastep[TABMNG_MAXTABSET];
    ListT<CegoField> _streamSchema;
    bool _isAborted;
    bool _autoCommit;
    unsigned _encBufLen;
    char *_pEncBuf;
    IsolationLevel _isolationLevel;
    ListT<CegoProcedure*> _procList[TABMNG_MAXTABSET];
    ListT<CegoView*> _viewList[TABMNG_MAXTABSET];
    ListT<CegoTrigger*> _triggerList[TABMNG_MAXTABSET];
    CegoDbThreadPool *_pPool;
    unsigned _thrIdx;
    
    unsigned long _modId;
};
#endif
