#ifndef JOIN_JOINOPERATOR_HPP
#define JOIN_JOINOPERATOR_HPP
/*!
 * @file
 * @brief realizes binary left linear join operator
 *
 * @author GertG
 * @ingroup Join
 *
 * @par last changed by:
 * <br>
 * $Author: d024980 $ $DateTime: 2006/08/14 15:36:46 $
 *
 * @sa Join_Execute.cpp
 */
/*

    ========== 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



*/
#include "Join/Join_Types.hpp"
#include "Join/Join_IOperator.hpp"
#include "SQLManager/SQLMan_Context.hpp"
#include "gak68.h"
#include "vak001.h"
#include "gkb07.h"
#include "gsp00.h"
#include "ggg07.h"
#include "ggg00.h"
#include "hbd01.h"

//! realizes binary left linear join operator
class Join_JoinOperator: public IOperator 
{
public:
    //! @name constructor / destructor
    //@{
    //! constructor
    Join_JoinOperator(
        SQLMan_Context&             acv,
        tak_dml_info&               dmli,
        const tak_parskey&          parsk,
        const tak68_joinview_rec&   jvrec,
        const pasbool               use_old_rescnt,
        const pasbool               del_parsinfos,
        const tak68_sequence&       sequence,
        const SAPDB_Int4            act_join );

    //! destructor
    virtual ~Join_JoinOperator();
    //@}
    
    //! @name record stream manipulation functions
    //@{
    //! open operator with keys given by strategy information
    virtual tgg00_BasisError Open();

    //! open stream operator and limit stream with start/stop key
    virtual tgg00_BasisError Open(
            const Join_TwoKeys& startkeys, 
            const Join_TwoKeys& stopkeys );

    //! get next record from stream
    virtual tgg00_BasisError Next( tgg00_Rec*& recptr);

    //! close operator
    virtual void Close();

    //! get result record template; invalidate every record pointer
    void GetRecordTemplate( tgg00_Rec*& record );
    //@}

    //! @name operator/record properties
    //@{
    //! return key length of result records in stream
    SAPDB_UInt2 GetKeyLength() const { return m_ResultKeyLen; }

    //! return length of result records in stream
    SAPDB_UInt2 GetRecordLength() const { return m_JoinDesc.gi_result_info.n_res_rec_len; }
    //
    //! get result NULL record 
    virtual tgg00_BasisError GetNullRecord( tgg00_Rec*& recptr );
    //@}
    
protected:
    virtual tgg00_BasisError next( tgg00_Rec* *records )
    {
        return e_not_implemented;
    }

    virtual tgg00_BasisError get_null_record( tgg00_Rec* *records )
    {
        return e_not_implemented;
    }
    
private:

    // member types
    enum mt_build_type { join_result, join_auxfile };
    enum mt_scan_stat { never_scanned, while_scanning, already_scanned };
    enum mt_roj_action { add_record, delete_record };
    enum mt_table_pos { left_table, right_table };

    // member methods
    //! return key length of joined records
    SAPDB_UInt2 join_keylen() const { return m_JoinDesc.gi_result_info.n_key_len; }

    //! return length of joined records
    SAPDB_UInt2 join_reclen() const { return m_JoinDesc.gi_result_info.n_rec_len; }
    
    tgg00_BasisError extract_joininfo( 
            SAPDB_Int4 act_join,
            SAPDB_Bool is_last_join );
    tgg00_BasisError create_filter( SAPDB_Bool );
    SAPDB_Bool join( tgg00_BasisError& );
    tgg00_BasisError prepare_right_key();
    tgg00_BasisError build_join_rec( mt_build_type = join_result );
    void convert_key( tgg00_Lkey& ) const;
    SAPDB_Bool filter( tgg00_Rec*, tgg00_BasisError& );
    tgg00_BasisError init() {
        if ( m_JoinDesc.gi_linkrec.kbjr_right_oj )
            // create auxiliary RIGHT OUTER JOIN file
            b01tcreate_file( m_acv.TransContext(), m_AuxRightOuterJoinFile );
        m_TableForRightOuterJoinScanStat       = never_scanned;
        m_AuxRightOuterJoinFilePos.tpsPno_gg00 = NIL_PAGE_NO_GG00;
        m_AppendRightOuterJoinRecords = false;
        m_AuxRightOuterJoinKey.len()  = 0;
        return m_acv.TransContext().trError_gg00;
    }
    tgg00_BasisError get_roj_record( tgg00_Rec*& );
    tgg00_BasisError update_roj_auxfile( mt_roj_action );
    SAPDB_UInt4 get_AuxRightOuterKeyLen();

    IOperator* AccessOperatorFactory(
        SQLMan_Context&    acv,
        const SAPDB_UInt4& buffersize,
        const SAPDB_UInt4& expectedRecordCount,
        const SAPDB_Int4&  maxServerTasks,
        const SAPDB_UInt2 tabno);

    // member variables
    IOperator           *m_LeftOp, *m_RightOp;
    tgg00_Rec           *m_LeftRec, *m_RightRec, *m_JoinRec, *m_NullRec;
    tgg00_StackList     *m_Filter;
    SAPDB_Bool          m_GetLeftTupel;
    SAPDB_Bool          m_LeftRecChanged;
    SAPDB_Bool          m_LeftRecInserted;
    pasbool             m_IsDescendingIndex;
    SAPDB_Int4          m_RightRecConvArrCnt;
    SAPDB_Int4          m_JoinLenPart;
    SAPDB_Int2          m_LastRightDefBytePos;
    tgg07_StratEnum     m_RightAccessStrat;
    SAPDB_Bool          m_AppendRightOuterJoinRecords;
    SAPDB_Int4          m_RightAccessInvLen;
    tkb07_conv_arr      m_RightRecConvArr;              // 1536 byte
    tgg07_get_param     m_JoinDesc;                     // 16524 bytes
    SAPDB_UInt4         m_AuxRightOuterKeyLen;
    tgg00_StackDesc     m_FilterDesc;                   // 72 byte
    tgg00_SelectFieldsParam m_SelFields;                // 2268 byte
    SAPDB_UInt4         m_JoinRecBufferSize;
    tgg00_FileId        m_AuxRightOuterJoinFile;        // 40 byte
    tgg00_FilePos       m_AuxRightOuterJoinFilePos;     // 8 byte
    tgg00_Lkey          m_AuxRightOuterJoinKey;         // 1032 byte
    mt_scan_stat        m_TableForRightOuterJoinScanStat;
    SAPDB_Bool          m_OutputFilter;
    SAPDB_Int4          m_ResultKeyLen;
};

#endif
