/*!
 * @brief types used by Join component
 *
 * @author ThomasA
 * @ingroup Join
 *
 * @par last changed by:
 * <br>
 * $Author: d026026 $ $DateTime: 2007/04/10 17:59:46 $
 *
 */
/*

    ========== licence begin  GPL
    Copyright (c) 2002-2005 SAP AG

    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
    of the License, 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; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*/


#ifndef JOIN_TYPES_HPP
#define JOIN_TYPES_HPP

#include "gsp00.h"
#include "ggg00.h"
#include "SAPDBCommon/SAPDB_RangeCode.hpp"
#include "SAPDBCommon/SAPDB_MemCopyMove.hpp"
#include "SAPDBCommon/SAPDB_AutoPtr.hpp"
#include "Container/Container_Vector.hpp"
#include "SQLManager/SQLMan_Context.hpp"

/*!
   @brief defines two key (base table key and inv key).  
 */
class Join_TwoKeys : public tgg00_TwoKeys
{
public :
    /*!
       @brief default constructor, initializes both key with length 0
     */
    Join_TwoKeys()
    {
        reckey.len()  = 0;
        listkey.len() = 0;
    }
    /*!
       @brief copy constructor
     */
    Join_TwoKeys(const Join_TwoKeys& source)
    {
        *this = source;
    }
    /*!
       @brief assignment operator, checks for admissable key length
     */
    inline void operator=(const Join_TwoKeys& source)
    {
        this->reckey.len() = source.reckey.len();
        if ((source.reckey.len() < -1) || (source.reckey.len() > (int) sizeof(this->reckey.k())))
        {
            tgg00_BasisError e = e_ok;
            // SAPDB_RangeMove will notice the error and will write a trace into knldiag
            SAPDB_RangeMove (__FILE__, 1, sizeof(source.reckey.k()), sizeof(this->reckey.k()), 
                &source.reckey.k(), 1, &this->reckey.k(), 1, source.reckey.len(), e);
            this->reckey.len()  = -1; 
            this->listkey.len() = -1;
            return;
        }
        if (source.reckey.len() > 0)  
        {
            SAPDB_MemCopyNoCheck (&this->reckey.k(), &source.reckey.k(), source.reckey.len()); 
        }
        this->listkey.len() = source.listkey.len();
        if ((source.listkey.len() < -1) || (source.listkey.len() > (int) sizeof(this->listkey.k())))
        {
            tgg00_BasisError e = e_ok;
            // SAPDB_RangeMove will notice the error and will write a trace into knldiag
            SAPDB_RangeMove (__FILE__, 2, sizeof(source.listkey.k()), sizeof(this->listkey.k()), 
                &source.listkey.k(), 1, &this->listkey.k(), 1, source.listkey.len(), e);
            this->listkey.len() = -1;
            return;
        }
        if (source.listkey.len() > 0) 
        {
            SAPDB_MemCopyNoCheck (&this->listkey.k(), &source.listkey.k(), source.listkey.len()); 
        }
    }
};

/*!
 * @brief defines an auto pointer for tgg00_StackList
 */
typedef SAPDB_AutoPtr<tgg00_StackList> Join_StackListPtr;

struct Join_RootPair { 
    Join_RootPair() :
        m_Root(0), m_RootCheck(0) {}
    Join_RootPair( SAPDB_Int4 root, tsp00_PageNo rootcheck) :
        m_Root(root), m_RootCheck(rootcheck) {}
    SAPDB_Int4 m_Root; tsp00_PageNo m_RootCheck; 
};

struct Join_AggregationContext {
    Join_AggregationContext(
            SQLMan_Context          &acv, 
            const tgg00_StackList   &rec_desc,
            const tgg00_FileId      &DistFileTemplate,
            const Container_Vector<Join_RootPair>& DistFileRoots ) :
    m_acv(acv),
    m_RecordDesc( rec_desc ), 
    m_DistinctFileId( DistFileTemplate ),
    m_DistinctFileRoot( DistFileRoots ),
    m_grouprec_changed( false )
    {}
        
    SQLMan_Context              &m_acv; 
    const tgg00_StackList       &m_RecordDesc;
    const tgg00_FileId          &m_DistinctFileId;
    const Container_Vector<Join_RootPair>  &m_DistinctFileRoot;
    bool                        m_grouprec_changed;
};

#endif
