/*! @lastChanged: "1998-06-24  10:45"
 *
 * @file    :    vcn80.cpp
 * @purpose:     "utility and sql access"
 * @release:     7.1.0.0
 * @see:         "-.-"
 *
 * @copyright:   (c) 1998-2004 SAP AG"
 *
 * ==================================================================
 *
 * responsible:   Martin Reinecke (D024853 - Martin.Reinecke@SAP-AG.de)
 *                Bernd Vorsprach (D025588 - Bernd.Vorsprach@SAP-AG.de)
 *
 * created:       1998-03-19 by Martin Reinecke
 *
 * purpose:       utility connect/execute/release
 *
 * ==================================================================



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




 */

/* ------------------------------------------------------------------
 * includes
 * ------------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "vsp001.h"
#include "vsp009c.h"
#include "heo02.h"
#include "hsp02.h"

#include "hcn20.h"
#include "hcn31.h"
#include "hcn51.h"
#include "hcn53.h"
#include "hcn80.h"
#include "hcn90.h"

#include "DBM/Srv/KernelAccess/ServiceDB/DBMSrvKnlSrv_ConnectInfo.hpp"

/* ------------------------------------------------------------------
 * SPECIFICATION PRIVATE TYPES/MACROS
 * ------------------------------------------------------------------
 */
#define SESSION_SQLUSER       1
#define SESSION_UTIL          2
#define SESSION_SERVICE       3

#define SQL_SELECT            "SELECT"
#define SQL_CHAR_FIELDSEP     ';'
#define SQL_CHAR_RECSEP       '\n'
#define SQL_CHAR_STRINGDEL    '\''

#define PARAM_RECOVER         "RECOVER"

/* ------------------------------------------------------------------
 * SPECIFICATION PRIVATE FUNCTIONS
 * ------------------------------------------------------------------
 */
static tcn00_Error cn80_SQLExecSQL (
      char              * replyData,
      int               * replyLen,
      int                 replyLenMax,
      tin01_sql_session * pSession,
      const char        * szStatement);

/* PRIVATE FUNCTION cn80_SetSession
 * ------------------------------------------------------------------
 * purpose: set the session to global struct
 *
 */
static void cn80_SetSession (
      VControlDataT    * vcontrol,
      tin01_sql_session * pSession,
      int                nMode )
{
  switch (nMode) {
    case SESSION_SQLUSER:
      vcontrol->pSQLUserSession = (void *) pSession;
      break;
    case SESSION_UTIL:
      vcontrol->pUtilSession = (void *) pSession;
      break;
    case SESSION_SERVICE:
      vcontrol->pServiceSession = (void *) pSession;
      break;
  } /* end switch */

} /* end cn80_SetSession */

/* PRIVATE FUNCTION cn80_Session
 * ------------------------------------------------------------------
 * purpose: get the session from global struct and check
 *
 */
static tcn00_Error cn80_Session (
      VControlDataT    *  vcontrol,
      char             *  replyData,
      int              *  replyLen,
      tin01_sql_session ** pSession,
      int                 nMode )
{
  tcn00_Error nFuncReturn    = OK_CN00;
  tcn00_Error nPossibleError = OK_CN00;

  /**/

  switch (nMode) {
    case SESSION_SQLUSER:
      *pSession =  (tin01_sql_session *) vcontrol->pSQLUserSession;
      nPossibleError = ERR_NOSQLUSERSESSION_CN00;
      break;
    case SESSION_UTIL:
      *pSession =  (tin01_sql_session *) vcontrol->pUtilSession;
      nPossibleError = ERR_NOUTILSESSION_CN00;
      break;
    case SESSION_SERVICE:
      *pSession =  (tin01_sql_session *) vcontrol->pServiceSession;
      nPossibleError = ERR_NOSERVICESESSION_CN00;
      break;
  } /* end switch */

  /* is there an active  session */
  if (nFuncReturn == OK_CN00) {
    if ( (*pSession == NULL)          ||
         (!(*pSession)->is_connected)    ) {
      nFuncReturn = nPossibleError;
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } /* end if */
  } /* end if */
 
  /**/

  return nFuncReturn;
} /* end cn80_Session */

/* PRIVATE FUNCTION cn80_FreeSession
 * ------------------------------------------------------------------
 * purpose: frees the session from the VControlDataT structure
 *
 */
static void cn80_FreeSession(
      VControlDataT     * vcontrol,
      int                 nMode)
{
  tin01_sql_session  * pSession;

  /**/

  if (vcontrol != NULL) {
    switch (nMode) {
      case SESSION_SQLUSER:
        pSession =  (tin01_sql_session *) vcontrol->pSQLUserSession;
        vcontrol->pSQLUserSession = NULL;
        break;
      case SESSION_UTIL:
        cn31FreeBackupSession(vcontrol);
        pSession =  (tin01_sql_session *) vcontrol->pUtilSession;
        vcontrol->pUtilSession = NULL;
        break;
      case SESSION_SERVICE:
        pSession =  (tin01_sql_session *) vcontrol->pServiceSession;
        vcontrol->pServiceSession = NULL;

        if(0!=vcontrol->pServiceSessionInfo)
        {
            delete vcontrol->pServiceSessionInfo;
            vcontrol->pServiceSessionInfo=0;
        }
        break;
    } /* end switch */
  } /* end if */

  if (pSession != NULL) {
    if (pSession->is_connected ) {
      i29release(pSession, true);
    } /* end if */
    cn00MyFree(pSession);
  } /* end if */

} /* end cn80_FreeSession */

/* PRIVATE FUNCTION cn80_Connect
 * ------------------------------------------------------------------
 * purpose: open a session
 *
 */
static tcn00_Error cn80_Connect (
      char              * replyData,
      int               * replyLen,
      tin01_sql_session * pSession,
      const char        * szDatabase,
      const char        * szUsername,
      const char        * szPassword,
      int                 nMode)
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  tsp4_xuser_record * pXUser      = NULL;
  int                 rc;
  tsp00_ErrTextc        errtext;
  tsp00_KnlIdentifierc errname;
  tsp00_Int2            errcode;
  tsp00_Int2            errpos;

  /**/

  tcn002_XpValueString szUnicode;
  tcn002_XpValueName   szParameter;
  tsp00_DbNamec       szDbName;
  bool                bUnicode = false;

  szParameter.rawAssign(PAN_UNICODE_CATALOG);
  szDbName.rawAssign(szDatabase);
  if (cn20XParamGetValue(szDbName, szParameter, szUnicode) == OK_CN00) {
    bUnicode = (stricmp(szUnicode, XP_VAL_YES_CN00) == 0);
  } // end if

  /* create session */
  if (nFuncReturn == OK_CN00) {

    pSession->is_readonly = false;

    i29initsession(pSession, NULL);

    i29lasterr_on(pSession);

    rc = i29usrconnect(pSession, 
                        szDatabase, 
                        "",
                        szUsername, 
                        szPassword, 
                        bUnicode && (nMode != SESSION_SERVICE), 
                        (nMode == SESSION_UTIL || nMode == SESSION_SERVICE));

    if ((rc == DB_ERR_LOGFULL_CN00) && (nMode == SESSION_SQLUSER)) {
      pSession->is_readonly = true;
      i29lasterr_on(pSession);
      rc = i29usrconnect(pSession, 
                          szDatabase, 
                          "",
                          szUsername, 
                          szPassword, 
                          bUnicode, 
                          true);
    } // end if

    /* something wrong? */
    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29sqllasterr(pSession, errtext, errname, &errcode, &errpos);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, errtext, rc);
    }
  }

  /**/

  return nFuncReturn;
} /* end cn80_Connect */

/* PUBLIC FUNCTION cn80_InternConnect
 * ------------------------------------------------------------------
 * purpose: open a session
 *
 */
static tcn00_Error cn80_InternConnect (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax,
      int             nMode )
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  _TCHAR              szUsername[PARAMETER_MAXLEN_CN90];
  _TCHAR              szPassword[PARAMETER_MAXLEN_CN90];
  _TCHAR            * pPassword   = &szPassword[0];
  tin01_sql_session * pSession    = NULL;
  bool                bMallocOK   = true;

  /**/

  /* read the parameters */
  if (cn90GetToken(command->args, szUsername, 1, PARAMETER_MAXLEN_CN90)) {
    pPassword = _tcschr(szUsername, PWD_SEPARATOR_CN00);
    if (pPassword != NULL) {
      *pPassword = CHAR_STRINGTERM_CN90;
      pPassword++;
      cn90Uncrypt(pPassword, false);
    } else {
#ifdef CN71
      pPassword   = &szPassword[0];
      if (!cn90GetToken(command->args, szPassword, 2, PARAMETER_MAXLEN_CN90)) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } else {
        cn90Uncrypt(pPassword, false);
      } // end if
#else  /* CN71 */
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
#endif /* CN71 */
    } // end if
  } else {
    // look for cold user
    cn50DBMUser         usrCold    (vcontrol->dbname, cn50DBMUser::getUser(vcontrol->dbname, FIRSTDBM_CN50));

    _tcscpy(szUsername, usrCold.getUserName());
    cn90CalculateUncrypt(usrCold.getMasterPwd(), pPassword, false);
  } // end if

  /* Get session structure */
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80_Session(vcontrol, replyData, replyLen, &pSession, nMode);
    /* disconnect existing session */
    if (nFuncReturn == OK_CN00) {
      if (pSession->is_connected ) {
        i29release(pSession, true);
      } 
    } else {
      nFuncReturn = OK_CN00;
    } /* end if */
  } /* end if */

  /* allocate new memory for sql session */
  if (nFuncReturn == OK_CN00) {
    if (pSession == NULL) {
      cn00MyMalloc (sizeof (tin01_sql_session), &pSession, &bMallocOK);
    } /* end if */

    if ((pSession == NULL) || (!bMallocOK)) {
      nFuncReturn = ERR_MEM_CN00;
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } else {
      cn80_SetSession(vcontrol, pSession, nMode);
    } /* end if */
  } /* end if */

  /* execute connect */
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80_Connect(replyData, 
                               replyLen, 
                               pSession,
                               vcontrol->dbname,
                               szUsername, 
                               pPassword, 
                               nMode);
  } /* end if */

  /**/

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK(replyData, replyLen, NULL);
  } /* end if */

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn80_InternConnect */

/* PUBLIC FUNCTION cn80_Release
 * ------------------------------------------------------------------
 * purpose: release the session
 *
 */
tcn00_Error cn80_Release (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax,
      int             nMode )
{
  /* free memory from sql session */
  cn80_FreeSession(vcontrol, nMode);
  
  return cn90AnswerOK(replyData, replyLen, NULL);
} /* end cn80_Release */

/* SPECIFICATION PUBLIC FUNCTIONS
 * ------------------------------------------------------------------
 */

/* PUBLIC FUNCTION cn80UtilConnect
 * ------------------------------------------------------------------
 * purpose: open a utility session
 *
 */
tcn00_Error cn80UtilConnect (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  return cn80_InternConnect(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_UTIL);
} /* end cn80UtilConnect */

/* PUBLIC FUNCTION cn80UtilRelease
 * ------------------------------------------------------------------
 * purpose: release the utility session
 *
 */
tcn00_Error cn80UtilRelease (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  return cn80_Release(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_UTIL);
} /* end cn80UtilRelease */

/* PRIVATE FUNCTION cn80_CheckCreateInstance
 * ------------------------------------------------------------------
 * purpose: check for CREATE INSTANCE
 *
 */
static bool cn80_CheckCreateInstance (
      const char    * szStatement) 
{
  bool      bFound = false;
  char      szToken    [PARAMETER_MAXLEN_CN90];

  cn90GetToken(szStatement, szToken, 1, PARAMETER_MAXLEN_CN90);
  if (stricmp(szToken, "CREATE") == 0) {
    cn90GetToken(szStatement, szToken, 2, PARAMETER_MAXLEN_CN90);
    if (stricmp(szToken, "INSTANCE") == 0) {
      bFound = true;
    } // end if
  } // end if

  return bFound;
} // end cn80_CheckCreateInstance

/* PUBLIC FUNCTION cn80CheckVerify
 * ------------------------------------------------------------------
 * purpose: check for VERIFY
 *
 */
bool cn80CheckVerify (
      const char * szStatement, const char * & pAction) 
{
  bool      bVerify = false;
  char      szToken    [PARAMETER_MAXLEN_CN90];

  if (cn90GetToken(szStatement, szToken, 1, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szToken, "VERIFY") == 0) {
      pAction = DBAOP_CHECKDB_CN53;
      bVerify = true;
    } else if (stricmp(szToken, "CHECK") == 0) {
      if (cn90GetToken(szStatement, szToken, 2, PARAMETER_MAXLEN_CN90)) {
        if (stricmp(szToken, "DATA") == 0) {
          pAction = DBAOP_CHECKDB_CN53;
          bVerify = true;
        } else if (stricmp(szToken, "TABLE") == 0) {
          pAction = DBAOP_TABLECHECK_CN53;
          bVerify = true;
        } // end if
      } // end if
    } // end if
  } // end if

  return bVerify;
} // end cn80CheckVerify

/* PUBLIC FUNCTION cn80DBActivate
 * ------------------------------------------------------------------
 * purpose: execute actvtivate serverdb
 *
 */
tcn00_Error cn80DBActivate (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  char                szToken    [PARAMETER_MAXLEN_CN90];
  bool                bRecover  = false;
  bool                bConnect  = false;

  tin01_sql_session * pSQLSession;
  tin01_sql_session   aSQLSession;
  tcn00_UserNamec     szUser;
  tsp00_Namec         szPassword;

  /**/

  if (!cn90GetToken(command->args, szToken, 1, PARAMETER_MAXLEN_CN90)) {
    cn50DBMUser  usrDBA(vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname));
    if (usrDBA.existsOnDisk() ) {
      szUser     = usrDBA.getUserName();
      szPassword = usrDBA.getClearMasterPwd();
    } else {
      nFuncReturn = ERR_DBAUNKNOWN_CN00;
    } // end if
  } else {
    if (stricmp(szToken, PARAM_RECOVER) == 0) {
      bRecover = true;
    } else {
      char * pPassword = strchr(szToken, PWD_SEPARATOR_CN00);
      if (pPassword != NULL) {
        *pPassword = CHAR_STRINGTERM_CN90;
        pPassword++;
        cn90Uncrypt(pPassword, false);
        szUser.rawAssign(szToken);
        szPassword.rawAssign(pPassword);

        if (cn90GetToken(command->args, szToken, 2, PARAMETER_MAXLEN_CN90)) {
          nFuncReturn = ERR_TOOMANYPARAM_CN00;
        } // end if
      } else {
        nFuncReturn = ERR_PARAM_CN00;
      } // end if
    } // end if
  } // end if
  
  if (nFuncReturn == OK_CN00) {
    if (bRecover) {
      // delete possible existing sysdev parameters
      tsp00_XpKeyTypec szName;
      szName.rawAssign("SYSDEV_001");
      cn20XParamDelete(vcontrol->dbname, szName);
      szName.rawAssign(PAN_MAXSYSDEVSPACES);
      cn20XParamDelete(vcontrol->dbname, szName);

      // disable autosave
      cn51DBMConfigValue cfgAuto (vcontrol->dbname, CFG_AUTOSSAVE_CN51);
      cfgAuto = 0;

      command->args = command->args + strlen(PARAM_RECOVER) + 1;
      nFuncReturn =  cn31BackupRestoreCreate (vcontrol, command, replyData, replyLen, replyLenMax );
    } else {

      // check db state
      if (cn90DBState(vcontrol->dbname) != STATE_ADMIN_CN00) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_NOTADMIN_CN00);
      } // end if

      // utility session
      if (nFuncReturn == OK_CN00) {
        nFuncReturn = cn80UtilSession(vcontrol, replyData, replyLen, &pSQLSession);
        if (nFuncReturn == ERR_NOUTILSESSION_CN00) {
          pSQLSession = &aSQLSession;
          nFuncReturn = cn80ConnectUtil ( vcontrol->dbname, pSQLSession, replyData, replyLen);
          bConnect = (nFuncReturn == OK_CN00);
        } // end if
      } // end if

      if (nFuncReturn == OK_CN00) {
        // delete possible existing sysdev parameters
        tsp00_XpKeyTypec szName;
        szName.rawAssign("SYSDEV_001");
        cn20XParamDelete(vcontrol->dbname, szName);
        szName.rawAssign(PAN_MAXSYSDEVSPACES);
        cn20XParamDelete(vcontrol->dbname, szName);

        // disable autosave
        cn51DBMConfigValue cfgAuto (vcontrol->dbname, CFG_AUTOSSAVE_CN51);
        cfgAuto = 0;
      } // end if

      // place here the utility command
      if (nFuncReturn == OK_CN00) {
        char  szCommand[PARAMETER_MAXLEN_CN90];
        sprintf(szCommand, DB_CREATE_CN80, szUser.asCharp(), szPassword.asCharp());
        nFuncReturn = cn80ExecuteUtil(pSQLSession, szCommand, replyData, replyLen); 
      } // end if 

      if (nFuncReturn == OK_CN00) {
        // delete old sysdba-user
        cn50DBMUser         usrOldDBA(vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname));
        usrOldDBA.setSDBAUser(false);
        usrOldDBA.deleteUsr();
        
        // create new sysdba-user
        cn50DBMUser         usrDBA;

        // save data of new sysdba-user
        usrDBA.setDBName(vcontrol->dbname)
              .setUserName ( szUser)
              .setSDBAUser ( )
              .setMasterPwd( szPassword)
              .setServerRights ( DBMMaskAll_CN50, DBMUserDefault_CN50 )
              .setGUIRights    ( DBMMaskAll_CN50, DBMUserDefault_CN50 );

        nFuncReturn = usrDBA.save();
      } // end if

      if (nFuncReturn != OK_CN00) {
        cn90AnswerIError(replyData, replyLen, nFuncReturn);
      } else {
        cn90AnswerOK(replyData, replyLen, NULL);
      } // end if 

    } // end if

    if (bConnect) {
      cn80ReleaseUtil ( pSQLSession );
    } // end if

  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if

  return nFuncReturn;
} /* end cn80DBActivate */


/* PUBLIC FUNCTION cn80DBActivateRequest
 * ------------------------------------------------------------------
 * purpose: execute actvtivate serverdb
 *
 */
tcn00_Error cn80DBActivateRequest (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  FUNCTION_DBG_MCN00_1("cn80DBActivateRequest");

  tcn00_Error	        nFuncReturn = OK_CN00;
  char                szToken    [PARAMETER_MAXLEN_CN90];

  /**/

  cn90GetToken(command->args, szToken, 1, PARAMETER_MAXLEN_CN90);
  if (stricmp(szToken, PARAM_RECOVER) != 0) {
    teo200_EventList aPARAM(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", "Missing keyword RECOVER.");
    teo200_EventList aDBM(aPARAM, FUNCTION_NAME_MCN00_1, ERR_PARAM_CN00_1);
    nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
  } // end if

  if (nFuncReturn == OK_CN00) {
      // delete possible existing sysdev parameters
      tsp00_XpKeyTypec szName;
      szName.rawAssign("SYSDEV_001");
      cn20XParamDelete(vcontrol->dbname, szName);
      szName.rawAssign(PAN_MAXSYSDEVSPACES);
      cn20XParamDelete(vcontrol->dbname, szName);

      // disable autosave
      cn51DBMConfigValue cfgAuto (vcontrol->dbname, CFG_AUTOSSAVE_CN51);
      cfgAuto = 0;

      command->args = command->args + strlen(PARAM_RECOVER) + 1;
      nFuncReturn =  cn31BackupRestoreCreateRequest (vcontrol, command, replyData, replyLen, replyLenMax );
  } // end if

  return nFuncReturn;
} /* end cn80DBActivateRequest */

/* PUBLIC FUNCTION cn80UtilExecute
 * ------------------------------------------------------------------
 * purpose: execute a utility statement
 *
 */
tcn00_Error cn80UtilExecute (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	         nFuncReturn = OK_CN00;
  tin01_sql_session  * pSession;
  tin01_sql_session    aSQLSession;
  bool                 bConnect    = false;
  
  /**/

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80UtilSession(vcontrol, replyData, replyLen, &pSession);
    if (nFuncReturn == ERR_NOUTILSESSION_CN00) {
      cn90AnswerOK(replyData, replyLen, NULL);
      pSession = &aSQLSession;
      nFuncReturn = cn80ConnectUtil ( vcontrol->dbname, pSession, replyData,replyLen);
      bConnect = (nFuncReturn == OK_CN00);
    } // end if
  } // end if
  // nFuncReturn = cn80UtilSession(vcontrol, replyData, replyLen, &pSession);

  if (nFuncReturn == OK_CN00) {
    if (cn80_CheckCreateInstance(command->args)) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "please use db_activate");
    } else { 
      const char *     pAction = "";
      bool             bVerify     = false;
      tsp00_Timestampc szTimeStamp;
      if (cn80CheckVerify(command->args, pAction)) {
        bVerify = true;
        cn90Timestamp(szTimeStamp);
        tcn53_DBAAction::start(vcontrol->dbname, szTimeStamp, pAction, DBA_OBJ_DB_CN53);
        tcn53_DBAAction::writeDetail(DBADTL_CDBCMD_CN53, command->args);
      } // end if
      nFuncReturn = cn80ExecuteUtil(pSession, command->args, replyData, replyLen); 
      if (bVerify) {
        tcn53_DBAAction::writeDetail(DBADTL_CDBRESULT_CN53, replyData);
        tcn53_DBAAction::finish(cn90Timestamp(szTimeStamp), (nFuncReturn == OK_CN00));
      } // end if
    } /* end if */
  } /* end if */

  if (bConnect) {
    cn80ReleaseUtil ( pSession );
  } // end if

  /**/

//  if (nFuncReturn == OK_CN00) {
//    cn90AnswerOK(replyData, replyLen, NULL);
//  } /* end if */

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn80UtilExecute */

/* PUBLIC FUNCTION cn80ServiceConnect
 * ------------------------------------------------------------------
 * purpose: open a utility session with the service kernel
 *
 */
tcn00_Error cn80ServiceConnect (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_DbNamec       szDBName;
  tcn00_UserNamec     szUserName;
  tsp00_Namec         szPassword;
  tsp9_rte_xerror     xError;
  bool                bStarted = false; 
  tin01_sql_session * pSession    = NULL;
  bool                bMallocOK   = true;


  nFuncReturn = cn80ServiceSession(vcontrol, replyData, replyLen, &pSession);

  if (ERR_NOSERVICESESSION_CN00 == nFuncReturn) {
    //  get parameter of service kernel
    nFuncReturn =  cn20XParamGetServiceValues ( szDBName,
                                                vcontrol->dbroot,
                                                szUserName,
                                                szPassword );

    //  start service kernel
    if (nFuncReturn == OK_CN00) {
      cn20CreateSrvParam(szDBName, vcontrol->dbname);

      sqlxstart (szDBName, csp9_fast_pgm, vcontrol->dbroot, false, 0, NULL, &xError);

      if (xError.xe_result != csp9_xrte_ok) {
        nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
      } else {
        bStarted = true;
      } // end if
    } else {
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } // end if

    // connect
    if (nFuncReturn == OK_CN00) {
      /* allocate new memory for sql session */
      cn00MyMalloc (sizeof (tin01_sql_session), &pSession, &bMallocOK);

      vcontrol->pServiceSessionInfo=new DBMSrvKnlSrv_ConnectInfo(szDBName, szUserName, szPassword);

      if ((pSession == NULL) || (!bMallocOK) || 0==vcontrol->pServiceSessionInfo) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
      } else {
        cn80_SetSession(vcontrol, pSession, SESSION_SERVICE);
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    if (!pSession->is_connected) {
      nFuncReturn = cn80_Connect(replyData, 
                                 replyLen, 
                                 pSession,
                                 szDBName,
                                 szUserName, 
                                 szPassword, 
                                 SESSION_SERVICE);
    } // end if
  } // end if

  // stop kernel in case of errors
  if (nFuncReturn != OK_CN00 && bStarted) {
    sqlxstop (szDBName, vcontrol->dbroot, false, &xError);
    if (vcontrol->pServiceSession != NULL) {
      cn80_FreeSession(vcontrol, SESSION_SERVICE);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK(replyData, replyLen, NULL);
  } /* end if */

  return nFuncReturn;

} /* end cn80ServiceConnect */

/* PUBLIC FUNCTION cn80ServiceRelease
 * ------------------------------------------------------------------
 * purpose: release the utility session with the service kernel
 *
 */
tcn00_Error cn80ServiceRelease (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_DbNamec       szDBName;
  tsp9_rte_xerror     xError;
  tin01_sql_session * pSession = NULL;

  if (cn80_Session (vcontrol, replyData, replyLen, &pSession, SESSION_SERVICE ) == OK_CN00) {
    nFuncReturn = cn80_Release(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_SERVICE);

    //  get parameter of service kernel
    nFuncReturn =  cn20XParamGetServiceValues ( szDBName, vcontrol->dbroot);
    if (nFuncReturn == OK_CN00) {
      sqlxstop (szDBName, vcontrol->dbroot, false, &xError);
      if (xError.xe_result != csp9_xrte_ok) {
        nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
      } else {
        cn90AnswerOK(replyData, replyLen, NULL);
      } // end if
    } else {
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } // end if
  } else {
    nFuncReturn = cn80_Release(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_SERVICE);
  } // end if

  return nFuncReturn;

} /* end cn80ServiceRelease */

/* PUBLIC FUNCTION cn80SQLUserConnect
 * ------------------------------------------------------------------
 * purpose: open a SQLUser session
 *
 */
tcn00_Error cn80SQLUserConnect (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  return cn80_InternConnect(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_SQLUSER);
} /* end cn80SQLUserConnect */

/* PUBLIC FUNCTION cn80SQLUserRelease
 * ------------------------------------------------------------------
 * purpose: release the SQLUser session
 *
 */
tcn00_Error cn80SQLUserRelease (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  return cn80_Release(vcontrol, command, replyData, replyLen, replyLenMax, SESSION_SQLUSER);
} /* end cn80SQLUserRelease */

/* PUBLIC FUNCTION cn80SQLUserExecute
 * ------------------------------------------------------------------
 * purpose: execute a statement with the SQLUser session
 *
 */
tcn00_Error cn80SQLUserExecute (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  tin01_sql_session  * pSession;
  tin01_sql_session    aSQLSession;
  bool                 bConnect   = false;
  const char         * pCommand   = command->args;
  const char         * pValue;
  char                 szParameter[PARAMETER_MAXLEN_CN90];
  int                  nUser      = 0;
  /**/

  // read parameters 
  if (nFuncReturn == OK_CN00) {
    cn90GetToken(command->args, szParameter, 1, PARAMETER_MAXLEN_CN90);
    if (strncmp(szParameter, USER_TYPE_CN50, strlen(USER_TYPE_CN50)) == 0) {
      pValue = strchr(szParameter, ASSIGN_CHAR_CN50);
      if (pValue != NULL) {
        pValue++;
        pCommand = pCommand + strlen(szParameter);
        if (strcmp(pValue, USERTYPE_DBM_CN50) == 0) {
          nUser = FIRSTDBM_CN50;
        } else if (strcmp(pValue, USERTYPE_DBA_CN50) == 0) {
          nUser = SYSDBA_CN50;
        } else if (strcmp(pValue, USERTYPE_SAP_CN50) == 0) {
          nUser = SAPUSR_CN50;
        } else if (strcmp(pValue, USERTYPE_DOM_CN50) == 0) {
          nUser = DOMAIN_CN50;
        } else {
          nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "unknown usertype");
        } // end if
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "missing usertype");
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80SQLUserSession(vcontrol, replyData, replyLen, &pSession);
    if (nFuncReturn == ERR_NOSQLUSERSESSION_CN00) {
      pSession = &aSQLSession;
      nUser = (nUser == 0) ? FIRSTDBM_CN50 : nUser;
      nFuncReturn = cn80ConnectSQL ( vcontrol->dbname, pSession, replyData, replyLen, nUser);
      bConnect = (nFuncReturn == OK_CN00);
    } else {
      if (nUser != 0) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "SQL session exists");
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80_SQLExecSQL(replyData, replyLen,  replyLenMax, pSession, pCommand); 
  } /* end if */

  if (bConnect) {
    cn80ReleaseSQL ( pSession );
    // remove next command
    vcontrol->szNextCommand.rawAssign("");
    vcontrol->nNextCommandSkip = 0;
  } // end if

  /**/

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn80SQLUserExecute */

/* PUBLIC FUNCTION cn80SQLUserInfo
 * ------------------------------------------------------------------
 * purpose: provide info about sql result
 *
 */
tcn00_Error cn80SQLUserInfo (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  tin01_sql_session  * pSession;
  int                 rc;
  tsp00_C256c         errtext;
  
  /**/

  nFuncReturn = cn80SQLUserSession(vcontrol, replyData, replyLen, &pSession);

  if (nFuncReturn == OK_CN00) {

    cn90AnswerOK(replyData, replyLen, NULL);

    /* execute select */
    rc = i29selectinfo(pSession, 
                       command->args, 
                       replyData + strlen(replyData), 
                       SQL_CHAR_FIELDSEP);

    SAPDB_strcpy(&replyData[strlen(replyData)], LINE_SEPSTRING_CN00);

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    } /* end if */
  } /* end if */

  *replyLen = (int)strlen(replyData);

  return OK_CN00;
} /* end cn80SQLUserInfo */

/* PUBLIC FUNCTION cn80SQLUserFetch
 * ------------------------------------------------------------------
 * purpose: fetch next rows
 *
 */
tcn00_Error cn80SQLUserFetch (
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  tin01_sql_session  * pSession;
  int                 rc;
  tsp00_C256c         errtext;
  bool                bContinue;
  /**/

  nFuncReturn = cn80SQLUserSession(vcontrol, replyData, replyLen, &pSession);

  if (nFuncReturn == OK_CN00) {

    cn90AnswerOK(replyData, replyLen, NULL);

    /* execute select */
    rc = i29fetch(pSession, 
                  replyData + strlen(replyData), 
                  replyLenMax - (long)strlen(replyData),
                  SQL_CHAR_FIELDSEP,SQL_CHAR_STRINGDEL,SQL_CHAR_RECSEP,bContinue);

    SAPDB_strcpy(&replyData[strlen(replyData)], LINE_SEPSTRING_CN00);

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    } else {
      if (bContinue) {
        // prepare next command 
        vcontrol->szNextCommand.rawAssign("sql_fetch");
        vcontrol->nNextCommandSkip = 1;
      } // end if
    } /* end if */
  } /* end if */

  *replyLen = (int)strlen(replyData);

  return OK_CN00;
} /* end cn80SQLUserFetch */

/*
 * ------------------------------------------------------------------
 * FOR INTERNAL USE ONLY
 * ------------------------------------------------------------------
 */

/* INTERN FUNCTION cn80_SQLExecSQL
 * ------------------------------------------------------------------
 * purpose: execute a statement
 *
 */
static tcn00_Error cn80_SQLExecSQL (
      char               * replyData,
      int                * replyLen,
      int                  replyLenMax,
      tin01_sql_session  * pSession,
      const char         * szStatement)
{
  FUNCTION_DBG_MCN00_1("cn80_SQLExecSQL");

  tcn00_Error	        nFuncReturn = OK_CN00;
  int                 rc;
  tsp00_C256c         errtext;
  char                szCommand[PARAMETER_MAXLEN_CN90];
  bool                bSelect   = false;
  bool                bContinue = false;
  /**/

  const char *     pAction = "";
  bool             bVerify     = false;
  tsp00_Timestampc szTimeStamp;
  if (cn80CheckVerify(szStatement, pAction)) {
    bVerify = true;
    cn90Timestamp(szTimeStamp);
    tcn53_DBAAction::start(cn00DBMServerData::vcontrol()->dbname, szTimeStamp, pAction, DBA_OBJ_DB_CN53);
    tcn53_DBAAction::writeDetail(DBADTL_CDBCMD_CN53, szStatement);
  } // end if

  /* check the command */
  if (cn90GetToken(szStatement, szCommand, 1, PARAMETER_MAXLEN_CN90)) {
    bSelect = (cn90Stricmp(szCommand, SQL_SELECT) == 0);
  } /* end if */

  /* execute statement */
  if (!bSelect) {

    if (pSession->is_readonly) {
    
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_SQLREADONLY_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    
    } else {

      /* execute non select */
      rc = i29adbs(pSession, szStatement);

      if (rc != 0) {
        nFuncReturn = ERR_SQL_CN00;
        i29errmsg(pSession, errtext);
        cn90AnswerSQLError(replyData, replyLen, nFuncReturn, errtext, rc);
      } else {
        cn90AnswerOK(replyData, replyLen, NULL);
      } /* end if */

    } // end if

  } else {
    cn90AnswerOK(replyData, replyLen, NULL);

    /* execute select */
    rc = i29select(pSession, 
                   szStatement, 
                   replyData + strlen(replyData), 
                   replyLenMax - (long)strlen(replyData),
                   SQL_CHAR_FIELDSEP,SQL_CHAR_STRINGDEL,SQL_CHAR_RECSEP,bContinue);

    SAPDB_strcpy(&replyData[strlen(replyData)], LINE_SEPSTRING_CN00);

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    } else {
      *replyLen = (int)strlen(replyData);
      if (bContinue) {
        // prepare next command 
        cn00DBMServerData::vcontrol()->szNextCommand.rawAssign("sql_fetch");
        cn00DBMServerData::vcontrol()->nNextCommandSkip = 1;
      } // end if
    } /* end if */
  } /* end if */
 
  /**/

  if (bVerify) {
    tcn53_DBAAction::writeDetail(DBADTL_CDBRESULT_CN53, replyData);
    tcn53_DBAAction::finish(cn90Timestamp(szTimeStamp), (nFuncReturn == OK_CN00));
  } // end if

  return nFuncReturn;
} /* end cn80_SQLExecSQL */

/* INTERN FUNCTION cn80UtilSession
 * ------------------------------------------------------------------
 * purpose: get the utility session from global struct and check
 *
 */
tcn00_Error cn80UtilSession (
      VControlDataT    *  vcontrol,
      char             *  replyData,
      int              *  replyLen,
      tin01_sql_session ** pUtilSession )
{
  return cn80_Session(vcontrol, replyData, replyLen, pUtilSession, SESSION_UTIL);
} /* end cn80UtilSession */

/* INTERN FUNCTION cn80ServiceSession
 * ------------------------------------------------------------------
 * purpose: get the service kernel utility session from global struct and check
 *
 */
tcn00_Error cn80ServiceSession (
      VControlDataT    *  vcontrol,
      char             *  replyData,
      int              *  replyLen,
      tin01_sql_session ** pUtilSession )
{
  return cn80_Session(vcontrol, replyData, replyLen, pUtilSession, SESSION_SERVICE);
} /* end cn80ServiceSession */

/* INTERN FUNCTION cn80SQLUserSession
 * ------------------------------------------------------------------
 * purpose: get the sql user session from global struct and check
 *
 */
tcn00_Error cn80SQLUserSession (
      VControlDataT    *  vcontrol,
      char             *  replyData,
      int              *  replyLen,
      tin01_sql_session ** pSQLUserSession )
{
  return cn80_Session(vcontrol, replyData, replyLen, pSQLUserSession, SESSION_SQLUSER);
} /* end cn80SQLUserSession */

/* INTERN FUNCTION cn80FreeUtilSession
 * ------------------------------------------------------------------
 */
void cn80FreeUtilSession(
      VControlDataT     * vcontrol)
{
  cn80_FreeSession(vcontrol, SESSION_UTIL);
} /* end cn80FreeUtilSession */
 
/* INTERN FUNCTION cn80FreeSQLUserSession
 * ------------------------------------------------------------------
 */
void cn80FreeSQLUserSession(
      VControlDataT     * vcontrol)
{
  cn80_FreeSession(vcontrol, SESSION_SQLUSER);
} /* end cn80FreeSQLUserSession */

/* INTERN FUNCTION cn80FreeServiceSession
 * ------------------------------------------------------------------
 */
void cn80FreeServiceSession(
      VControlDataT     * vcontrol)
{
  FUNCTION_DBG_MCN00_1(_T("cn80FreeServiceSession"));

  tcn00_Error      nFuncReturn = OK_CN00;
  tsp00_DbNamec    szDBName;
  tsp9_rte_xerror  xError;

  if (vcontrol->pServiceSession != NULL) {
    teo200_EventList aEventS(FUNCTION_NAME_MCN00_1, nFuncReturn, TINF_CN00_1, "DBM", "implicit service_release started");
    tin100_GlobalLog::writeEntry (aEventS);

    cn80_FreeSession(vcontrol, SESSION_SERVICE);

    //  get parameter of service kernel
    nFuncReturn =  cn20XParamGetServiceValues ( szDBName ,vcontrol->dbroot);
    // stop service kernel
    if (nFuncReturn == OK_CN00) {
      sqlxstop (szDBName, vcontrol->dbroot, false, &xError);
      if (xError.xe_result != csp9_xrte_ok) {
        teo200_EventList aEvent1(FUNCTION_NAME_MCN00_1, xError.xe_result,  TERR_CN00_1, "DBM", "%.*s", sizeof(xError.xe_text), xError.xe_text);
        teo200_EventList aEvent2(aEvent1, FUNCTION_NAME_MCN00_1, ERR_CN00,          TERR_CN00_1, "DBM", "Could not stop running service kernel");
        tin100_GlobalLog::writeEntry (aEvent2);
      } // end if
    } else {
      teo200_EventList aEvent2(FUNCTION_NAME_MCN00_1, nFuncReturn, TERR_CN00_1, "DBM", "Could not parameter of running service kernel");
      tin100_GlobalLog::writeEntry (aEvent2);
    } // end if

    teo200_EventList aEventF(FUNCTION_NAME_MCN00_1, nFuncReturn, TINF_CN00_1, "DBM", "implicit service_release finished");
    tin100_GlobalLog::writeEntry (aEventF);
  } // end if

} /* end cn80FreeServiceSession */

/*
  -----------------------------------------------------------------------------
  public function cn80ExecuteSQL
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteSQL 
      ( const tsp00_DbNamec   szDBName,
        const _TCHAR      * szStatement)
{
  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 replyLen;

  return cn80ExecuteSQL (szDBName,
                         szStatement,
                         &szReply[0],
                         PARAMETER_MAXLEN_CN90,
                         replyLen);
} // end cn80ExecuteSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteSQL 
      ( const tsp00_DbNamec   szDBName,
        const _TCHAR        * szStatement,
        _TCHAR              * replyData,
        int                   replyLenMax,
        int                 & replyLen )

{
  cn50DBMUser         usrCold    (szDBName, cn50DBMUser::getUser(szDBName, FIRSTDBM_CN50));

  return cn80ExecuteSQL ( usrCold,
                          szStatement,
                          replyData,
                          replyLenMax,
                          replyLen );
} // end cn80ExecuteSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteSQL  
      ( const cn50DBMUser & aUser,
        const _TCHAR      * szStatement)
{
  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 replyLen;

  return cn80ExecuteSQL (aUser,
                         szStatement,
                         &szReply[0],
                         PARAMETER_MAXLEN_CN90,
                         replyLen);
} // end cn80ExecuteSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteSQL 
      ( const cn50DBMUser   & aUser,
        const _TCHAR        * szStatement,
        _TCHAR              * replyData,
        int                   replyLenMax,
        int                 & replyLen )

{
  tcn00_Error         nFuncReturn  = OK_CN00;
  tin01_sql_session   aSession;

  nFuncReturn = cn80ConnectSQL(aUser,
                               &aSession,
                               replyData,
                               &replyLen);

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80ExecuteSQL(&aSession, 
                                 szStatement,
                                 replyData,  
                                 replyLenMax, 
                                 replyLen);

    cn80ReleaseSQL(&aSession);
  } // end if

  return nFuncReturn;
} // end cn80ExecuteSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteSQL  
      ( tin01_sql_session   * pSQLSession,
        const _TCHAR        * szStatement,
        _TCHAR              * replyData,
        int                   replyLenMax,
        int                 & replyLen )
{
    return cn80_SQLExecSQL(replyData,  
                           &replyLen,  
                           replyLenMax, 
                           pSQLSession, 
                           szStatement);
} // end cn80ExecuteSQL


/*
  -----------------------------------------------------------------------------
  public function cn80ConnectSQL
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ConnectSQL
      ( const tsp00_DbNamec   szDBName,
        tin01_sql_session   * pSQLSession,
        char                * replyData,
        int                 * replyLen,
        int                   nUserType)
{
  cn50DBMUser aUser (szDBName, cn50DBMUser::getUser(szDBName, nUserType));
  return cn80ConnectSQL(szDBName, aUser, pSQLSession, replyData, replyLen);
} // end cn80ConnectSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ConnectSQL 
      ( const cn50DBMUser   & aUser,
        tin01_sql_session   * pSQLSession,
        char                * replyData,
        int                 * replyLen )
{
  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 nReplyLen;

  replyData = (replyData == NULL) ? &szReply[0] : replyData;
  replyLen  = (replyLen  == NULL) ? &nReplyLen  : replyLen;

  return cn80ConnectSQL(cn00DBMServerData::vcontrol()->dbname, aUser, pSQLSession, replyData, replyLen);
} // end cn80ConnectSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ConnectSQL 
      ( const tsp00_DbNamec   szDBName,
        const cn50DBMUser   & aUser,
        tin01_sql_session   * pSQLSession,
        char                * replyData,
        int                 * replyLen )
{
  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 nReplyLen;

  replyData = (replyData == NULL) ? &szReply[0] : replyData;
  replyLen  = (replyLen  == NULL) ? &nReplyLen  : replyLen;

  return  cn80_Connect(replyData, 
                       replyLen, 
                       pSQLSession,
                       szDBName,
                       aUser.getUserName(), 
                       aUser.getMasterPwd(true), 
                       SESSION_SQLUSER);

} // end cn80ConnectSQL
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ConnectSQL(
                const char        * dbName,
                const char        * userName,
                const char        * userPassword,
                tin01_sql_session * sqlSession)
{
    char reply[PARAMETER_MAXLEN_CN90]="";
    int  replyLen;

    return cn80_Connect(
                reply, 
                &replyLen, 
                sqlSession,
                dbName,
                userName, 
                userPassword, 
                SESSION_SQLUSER);
}

/*
  -----------------------------------------------------------------------------
  public function cn80ReleaseSQL
  -----------------------------------------------------------------------------
 */
void cn80ReleaseSQL 
     ( tin01_sql_session * pSQLSession,
       bool                bWithCommit )
{
  if (pSQLSession->is_connected ) {
    i29release(pSQLSession, bWithCommit);
  } // end if

} // end cn80ReleaseSQL

/*
  -----------------------------------------------------------------------------
  public function cn80ExecuteUtil
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteUtil (const tsp00_DbNamec   szDBName,
                             const _TCHAR        * szStatement,
                             char                * replyData,
                             int                 * replyLen)
{
  tcn00_Error          nFuncReturn  = OK_CN00;
  tin01_sql_session    aSession;
  tin01_sql_session  * pSession = NULL;

  pSession =  (tin01_sql_session *) cn00DBMServerData::vcontrol()->pUtilSession;

  if ( (pSession == NULL) || !(pSession->is_connected) ) {
    pSession = &aSession;

    nFuncReturn = cn80ConnectUtil(szDBName,
                                  pSession,
                                  replyData, 
                                  replyLen);
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80ExecuteUtil(pSession, 
                                  szStatement,
                                  replyData,  
                                  replyLen);

    if (pSession == &aSession) {
      cn80ReleaseUtil(pSession);
    } // end if
  } // end if

  return nFuncReturn;
} // end cn80ExecuteUtil
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ExecuteUtil (
      tin01_sql_session * pSession,
      const char        * szStatement,
      char              * replyData,
      int               * replyLen)
{
  FUNCTION_DBG_MCN00_1("cn80ExecuteUtil");

  tcn00_Error	        nFuncReturn = OK_CN00;
  int                 rc;
  tsp00_C256c         errtext;

  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 nReplyLen;
  replyData = (replyData == NULL) ? &szReply[0] : replyData;
  replyLen  = (replyLen  == NULL) ? &nReplyLen  : replyLen;

  /**/

  cn90AnswerOK(replyData, replyLen, NULL);

  rc = i29utilitynice(pSession, 
                      szStatement, 
                      replyData + strlen(replyData), false);

  if (rc != 0) {
    i29errmsg(pSession, errtext);
    teo200_EventList aSQLEvent(FUNCTION_NAME_MCN00_1, rc, TERR_CN00_1, "DBM", errtext.asCharp());
    if (rc == cin01_db_shutdown) {
      teo200_EventList aDBMEvent(aSQLEvent, FUNCTION_NAME_MCN00_1, ERR_SHUTDOWN_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBMEvent);
    } else {
      teo200_EventList aDBMEvent(aSQLEvent, FUNCTION_NAME_MCN00_1, ERR_SQL_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBMEvent);
    } // end if
  } // end if
 
  /**/

  *replyLen = (int) strlen(replyData);

  return nFuncReturn;
} /* end cn80ExecuteUtil */

/*
  -----------------------------------------------------------------------------
  public function cn80ConnectUtil
  -----------------------------------------------------------------------------
 */
tcn00_Error cn80ConnectUtil 
      ( const tsp00_DbNamec   szDBName,
        tin01_sql_session   * pUtilSession,
        char                * replyData,
        int                 * replyLen )
{
  _TCHAR              szReply[PARAMETER_MAXLEN_CN90];
  int                 nReplyLen;
  tcn002_XpValueString  szUsr;
  tcn002_XpValueString  szPwd;
  tcn002_XpValueName    szKeyUsr;
  tcn002_XpValueName    szKeyPwd;

  replyData = (replyData == NULL) ? &szReply[0] : replyData;
  replyLen  = (replyLen  == NULL) ? &nReplyLen  : replyLen;

  szKeyUsr.rawAssign(PAN_CONTROLID);
  szKeyPwd.rawAssign(PAN_CONTROLPW);

  if ((cn20XParamGetValue(szDBName, szKeyUsr, szUsr) == OK_CN00) &&
      (cn20XParamGetValue(szDBName, szKeyPwd, szPwd) == OK_CN00)     ) {
    return  cn80_Connect(replyData, replyLen, pUtilSession, szDBName, szUsr, szPwd, SESSION_UTIL);
  } else {
    return cn90AnswerIError(replyData, replyLen, ERR_USRREAD_CN00);
  } // end if

} // end cn80ConnectUtil

/*
  -----------------------------------------------------------------------------
  public function cn80ReleaseUtil
  -----------------------------------------------------------------------------
 */
void cn80ReleaseUtil 
     ( tin01_sql_session * pUtilSession,
       bool                bWithCommit )
{
  if (pUtilSession->is_connected ) {
    i29release(pUtilSession, bWithCommit);
  } // end if

} // end cn80ReleaseUtil
