/*!
  @file           DBMSrvKnl_Session.hpp
  @author         Bernd Vorsprach - bernd.vorsprach@sap.com
  @brief          DBMServer to Kernel Communication - Specification

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2003-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



\endif
*/

#ifndef _DBMSrvKnl_Session_HPP_
#define _DBMSrvKnl_Session_HPP_

/*
  -----------------------------------------------------------------------------
  includes
  -----------------------------------------------------------------------------
 */
#include "SAPDB/DBM/Srv/DBMSrv_Common.hpp"
#include "SAPDB/ToolsCommon/Tools_DynamicUTF8String.hpp"

/*
  -----------------------------------------------------------------------------
  forward declarations
  -----------------------------------------------------------------------------
 */
struct tsp1_packet;
struct tsp1_param_info;
class  PIn_ReplySegment;

/*! @brief field value */
class DBMSrv_SQLField {
private:
  friend class DBMSrv_SQLRecord;
  friend class DBMSrvKnl_Session;

  /*! @brief   data type */
  typedef enum {
    typeInt,
    typeString
  } DataType;


  /*! @ brief constructor */
  DBMSrv_SQLField(tsp1_param_info * aInfo, DataType aType) { pInfo  = aInfo;
                                                             oType  = aType;
                                                             iValue = 0;
                                                             sValue = "";
                                                             bNull  = false;} 

  /*! @brief member for paraminfo */
  tsp1_param_info *       pInfo;
  /*! @ brief member fro requested type */
  DataType                oType;
  /*! @ brief member for integer */
  SAPDB_Int4              iValue;
  /*! @ brief member for string */
  Tools_DynamicUTF8String sValue;
  /*! @ brief null flag */
  bool                    bNull;

}; // end class DBMSrv_SQLField

/*!
  @brief     Kernel session object

  One object of this class represents a kernel session

 */
class DBMSrvKnl_Session {

public:
  /*! @brief   task type */
  typedef enum {
    taskUnknown,
    taskNormal,
    taskFallback,
    taskEvent
  } TaskType;
 
  /*! @brief   result type */
  typedef enum {
    resultUnknown,
    resultNothing,
    resultError,
    resultMessage,
    resultUtility,
    resultSQL
  } ResultType;

  /*! @brief   Constructor */
  DBMSrvKnl_Session 
    (  );

  /*! @brief   Destructor */
  ~DBMSrvKnl_Session 
    (  );

  /*! @brief   connect to user task */
  bool NormalConnect
    ( const char * szDB,
      const char * szUser,
      const char * szPassword );

  /*! @brief   connect to  fallback task */
  bool FallbackConnect
    ( const char * szDB,
      const char * szUser,
      const char * szPassword );

  /*! @brief   connect to  event task */
  bool EventConnect
    ( const char * szDB );

  /*! @brief   execute a statement */
  bool Execute
    ( const char * szCommand,
      ResultType & oResultType );

  /*! @brief   execute a statement */
  bool Execute
    ( const char * szCommand );

  /*! @brief   execute a statement */
  bool ExecuteWithoutCommit
    ( const char      * szCommand );

  /*! @brief   execute a request with statement */
  bool Request
    ( const char * szCommand );

  /*! @brief   receive a answer after request */
  bool Receive
    ( ResultType & oResultType );

  /*! @brief   release a connection */
  bool Release
    ( );

  /*! @brief Returns the last message */
  const SAPDBErr_MessageList & LastMessage
    ( ) 
    {return this->oMessageList;}

  /*! @brief Returns the kernel message */
  const SAPDBErr_MessageList KernelMessage
    ( );

  /*! @brief get connect flag */
  bool IsConnected
    ( ) 
    {return this->bConnected;}

  /*! @brief parameter count of answer */
  SAPDB_Int4 ParamCount
    ();

  /*! @brief parameter info of answer */
  tsp1_param_info * ParamInfo
    ( );
 
  /*! @brief name of a field */
  Tools_DynamicUTF8String FieldName 
    ( const SAPDB_Int4     nField );

  /*! @brief get a field value */
  bool GetValue
    ( const SAPDB_Int4     nField,
      DBMSrv_SQLField    & oField );

private:
  /*! @brief   connect to  a task */
  bool Connect
    (TaskType     oTaskType,
     const char * szDB );

  /*! @brief   connect connect user to session */
  bool ConnectUser
    ( const char * szUser,
      const char * szPassword );

  /*! @brief   reset all members of the object */
  void Reset();

  /*! @brief   fetch record*/
  bool FetchRecord
    ( bool & bEnd,
      bool   bFirst = false );

  /*! @brief   send request to kernel */
  bool Request
    ( SAPDB_Int4 nRequestLength );

  /*! @brief   receive answer from kernel */
  tsp1_packet * Receive
    ( );

  void ReadErrorText
    ( PIn_ReplySegment & oSegment );

  /*! @brief Messagelist object */
  SAPDBErr_MessageList   oMessageList;
  /*! @brief   kernel session handle */
  SAPDB_Int4             nSessionHandle;
  /*! @brief   size of paket */
  SAPDB_Int4             nPacketSize;
  /*! @brief   request packet */
  tsp1_packet         *  pPacket;
  /*! @brief   receive packet */
  tsp1_packet         *  pReceivePacket;
  /*! @brief   unicode flag */
  SAPDB_Int4             nUnicode;
  /*! @brief   username     */
  tsp00_KnlIdentifierc  szUser;
  /*! @brief   password     */
  tsp00_Namec           szPwd;
  /*! @brief   connect flag */
  bool                  bConnected;
  /*! @brief   auto commit flag */
  bool                  bAutoCommit;

  friend class DBMSrv_SQLRecord;
}; // end class DBMSrvKnl_Session

/*! @brief SQL Record Object */
class DBMSrv_SQLRecord {

  public:
    /*! @brief constructor
        @param  oSession [IN]  - kernel session object
     */
    DBMSrv_SQLRecord  ( DBMSrvKnl_Session & oSession );

    /*! @brief constructor
        @param  aRecord  [IN]  - an other record object
     */
    DBMSrv_SQLRecord  ( const DBMSrv_SQLRecord  & aRecord  );

    /*! @brief destructor */
    ~DBMSrv_SQLRecord  ( );

    /*! @brief assignment operator
        @param  aRecord  [IN]  - an other record object
     */
    DBMSrv_SQLRecord & operator = (const DBMSrv_SQLRecord & aRecord);

    /*! @brief      returns a field contents

                    If there no valid conversion from DB datatype to SAPDB_Int4
                    or any other error occured a value of 0 will be returned.
                    Check also isNull() and fieldType() if you won't trust this 
                    behavior.

        @param      nField  [IN] - number of field

        @return     field value
     */
    SAPDB_Int4  fieldAsInt ( const SAPDB_Int4 nField  );

    /*! @brief      returns a field contents

                    If there no valid conversion from DB datatype to SAPDB_Int4
                    or any other error occured a value of 0 will be returned.
                    Check also isNull() and fieldType() if you won't trust this 
                    behavior.

        @param      szField [IN] - name of field

        @return     field value
     */
    SAPDB_Int4  fieldAsInt ( const Tools_DynamicUTF8String & szField );

    /*! @brief      returns a field contents

                    If there no valid conversion from DB datatype to _TCHAR *
                    or any other error occured a empty String will be returned.
                    Check also isNull() and fieldType() if you won't trust this 
                    behavior.

                    The return value is a temporarely allocated buffer. It will 
                    only valid until the next call of fieldAsChar or until the 
                    destruction of the object.

      @param        nField       [IN] - number of field
      @param        cStringQuote [in] - character for quoting strings
                                        0 means no quoting
      @return       field value
     */
    Tools_DynamicUTF8String fieldAsChar ( const SAPDB_Int4 nField,
                                          const char       cStringQuote = 0);

    /*! @brief      returns a field contents

                    If there no valid conversion from DB datatype to _TCHAR *
                    or any other error occured a empty String will be returned.
                    Check also isNull() and fieldType() if you won't trust this 
                    behavior.

                    The return value is a temporarely allocated buffer. It will 
                    only valid until the next call of fieldAsChar or until the 
                    destruction of the object.

      @param        szField      [IN] - name of field
      @param        cStringQuote [in] - character for quoting strings
                                        0 means no quoting
      @return       field value
     */
    Tools_DynamicUTF8String fieldAsChar ( const Tools_DynamicUTF8String & szField,
                                          const char                      cStringQuote = 0);

    /*! @brief      returns a field type
        @param      nField       [IN] - number of field
        @return     field type
     */
    tsp00_DataType fieldType ( const SAPDB_Int4  nField  );

    /*! @brief      returns a field type
        @param      szField      [IN] - name of field
        @return     field type
     */
    tsp00_DataType fieldType ( const Tools_DynamicUTF8String &  szField );

    /*! @brief      returns a the nullvalue flag
        @param      nField       [IN] - number of field
        @return     true if null, otherwise false
     */
    bool isNull ( const SAPDB_Int4 nField  );

    /*! @brief      returns a the nullvalue flag
        @param      szField      [IN] - name of field
        @return     true if null, otherwise false
     */
    bool isNull ( const Tools_DynamicUTF8String &  szField );

    /*! @brief      check the existence of a field
        @param      nField       [IN] - number of field
        @return     true if null, otherwise false
     */
    bool exists ( const SAPDB_Int4 nField  );

    /*! @brief      check the existence of a field
        @param      szField      [IN] - name of field
        @return     true if null, otherwise false
     */
    bool exists ( const Tools_DynamicUTF8String &  szField );

    /*! @brief      returns a field name

        @param      nField  [IN] - number of field, enumeration of fileds is 
                                   starting with 1

                    This is a temporarely allocated buffer. It will only valid
                    until the next call of fieldName or until the destruction 
                    of the object.

        @return     field name
     */
    Tools_DynamicUTF8String fieldName ( const SAPDB_Int4 nField  );

    /*! @brief      returns a field number
        @param      szField  [IN] - name of field
        @return     field number
     */
    SAPDB_Int4 fieldNumber ( const Tools_DynamicUTF8String & szField  );

    /*! @brief      gets the nex record
        @param      bEnd [OUT] - no record available
        @return     success or not
     */
    bool getNextRecord ( bool & bEnd );

    /*! @brief      returns the number of fields
        @return     number of fields
     */
    SAPDB_Int4 fields ( );

  private:
    /*! @brief check for string */
    bool IsString 
      ( tsp00_DataType aDataType );
    /*! @brief private member */
    DBMSrvKnl_Session & oKernelSession;
    /*! @brief private member */
    SAPDB_Int4             nParamCount;
    /*! @brief private member */
    tsp1_param_info *      pParamInfo;

}; // end class DBMSrv_SQLRecord

#endif /* _DBMSrvKnl_Session_HPP_ */

