⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmodbcconnection.cpp

📁 TOOL (Tiny Object Oriented Language) is an easily-embedded, object-oriented, C++-like-language inter
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************/
/*                              SOURCE FILE                                  */
/*****************************************************************************/
/*
       $Archive:   $

      $Revision:   $
          $Date:   $
        $Author:   $

    Description:   Implementation of a 'clone of' the MFC CDatabase class that
                   is implemented without all of the AFX goo....

                      TOOL And XML FORMS License
                      ==========================

                      Except where otherwise noted, all of the documentation 
                      and software included in the TOOL package is 
                      copyrighted by Michael Swartzendruber.

                      Copyright (C) 2005 Michael John Swartzendruber. 
                      All rights reserved.

                      Access to this code, whether intentional or accidental,
                      does NOT IMPLY any transfer of rights.

                      This software is provided "as-is," without any express 
                      or implied warranty. In no event shall the author be held
                      liable for any damages arising from the use of this software.

                      Permission is granted to anyone to use this software for 
                      any purpose, including commercial applications, and to 
                      alter and redistribute it, provided that the following 
                      conditions are met:

                      1. All redistributions of source code files must retain 
                         all copyright notices that are currently in place, 
                         and this list of conditions without modification.

                      2. The origin of this software must not be misrepresented;
                         you must not claim that you wrote the original software.

                      3. If you use this software in another product, an acknowledgment
                         in the product documentation would be appreciated but is
                         not required.

                      4. Modified versions in source or binary form must be plainly 
                         marked as such, and must not be misrepresented as being 
                         the original software.
*/
static char OBJECT_ID[] = "$Revision:   $ : $Date:   $";
/*****************************************************************************/


#include <assert.h>


#include "../../../StdAfx.h"
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>
#include "../TraceTools/VMWatcherOutput.h"
#include "../TraceTools/VMPerfTracking.h"
#include "../VMException.h"
#include "VMString.h"
#include "VMODBCConnection.h"
#include "VMVersionInfo.h"

// mjs, should protect with critical section
//
HENV VMODBCConnection::m_henvAllConnections    = SQL_NULL_HENV;
int  VMODBCConnection::m_nAllocatedConnections = 0;


const DWORD DEFAULT_LOGIN_TIMEOUT = 5;
const DWORD DEFAULT_QUERY_TIMEOUT = 5;
const int   MAX_TNAME_LEN         = 64;
const int   MAX_CONNECT_LEN       = 255;


const char cachODBCTrail[]        = "ODBC;";
const char cachComma[]            = ",";
const char cachLiteralSeparator   = '\'';
const char cachCall[]             = "{CALL ";
const char cachParamCall[]        = "{?";
const char cachSelect[]           = "SELECT ";
const char cachFrom[]             = " FROM ";
const char cachWhere[]            = " WHERE ";
const char cachOrderBy[]          = " ORDER BY ";
const char cachForUpdate[]        = " FOR UPDATE ";
const char cachRowFetch[]         = "State:01S01";
const char cachDataTruncated[]    = "State:01004";
const char cachInfoRange[]        = "State:S1096";
const char cachOutOfSequence[]    = "State:S1010";
const char cachDriverNotCapable[] = "State:S1C00";
const char cachODBCDLL[]          = "ODBC32.DLL";

// communications failure codes
//
// NOTE: These are VERY LIKELY TO BE MS-SQL Server dependant
//       If change to another dbms, then these values may be
//       all wrong and will have to be adjusted
//
const char UNABLE_TO_CONNECT[]   = "08001";
const char ALREADY_IN_USE[]      = "08002";
const char COMM_LINK_FAILED[]    = "08S01";
const char COMM_LINK_FAILURE[]   = "37000";


const int ciLogonWait             = 15;



/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::VMODBCConnection

       DESCRIPTION:  ctor. inits this

             INPUT:  void
            OUTPUT:  none

           RETURNS:  none
*/
VMODBCConnection::VMODBCConnection( void )
{
  m_hdbc                 = SQL_NULL_HDBC;
  m_hstmt                = SQL_NULL_HSTMT;
  m_bUpdatable           = false;
  m_bTransactions        = false;
  m_dwLoginTimeout       = DEFAULT_LOGIN_TIMEOUT;
  m_dwQueryTimeout       = DEFAULT_QUERY_TIMEOUT;
  m_bStripTrailingSpaces = false;
  m_bIncRecordCountOnAdd = false;
  m_bAddForUpdate        = false;
  m_uiReconnectWait      = 1000 * ciLogonWait;
  m_bReconnectTimer      = false;
  m_bIsOpen              = false;

 strcpy( (char*)m_auchErrorMsg, "" );
}
/* End of function "VMODBCConnection::VMODBCConnection"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::~VMODBCConnection

       DESCRIPTION:  dtor. frees all resources

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  none
*/
VMODBCConnection::~VMODBCConnection( void )
{
  Free();
}
/* End of function "VMODBCConnection::~VMODBCConnection"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  VMODBCConnection::GetDbmsHostName

       DESCRIPTION:  retrieves the name of the host where the database is 
                     actually running

             INPUT:  pchOutput - pointer to output buffer
                     iBufferLength - size of the output buffer
            OUTPUT:  

           RETURNS:  true if worked, false if not
*/
bool VMODBCConnection::GetDbmsHostName( char* pchOutput, int iBufferLength )
{
  short     iLength;

  // get the driver dll hmodule and use that for version info
  //
  SQLGetInfo( m_hdbc,
              SQL_SERVER_NAME,
              pchOutput,
              iBufferLength,
              &iLength );

  if ( iLength == 0 )
  {
    return( false );
  }
  else
  {
    return( true );
  }
}
/* End of function "VMODBCConnection::GetDbmsHostName"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  VMODBCConnection::GetVendorInfo

       DESCRIPTION:  Define what kind of dbms this is connected to

             INPUT:  pchOutput - output buffer
                     iBufferLength - length of the output buffer
            OUTPUT:  

           RETURNS:  true if data returned, false if not
*/
bool VMODBCConnection::GetVendorInfo( char* pchOutput, int iBufferLength )
{
  short     iLength;
  HINSTANCE hInstance;

  // get the driver dll hmodule and use that for version info
  //
  SQLGetInfo( m_hdbc,
              SQL_DRIVER_HLIB,
              &hInstance,
              sizeof( HINSTANCE ),
              &iLength );

  if ( hInstance == NULL )
  {
    return( false );
  }

  VMVersionInfo oVerInfo( hInstance );

  const char* pchTemp;

  pchTemp = oVerInfo.GetCompanyName();
  strcpy( pchOutput, pchTemp );
  strcat( pchOutput, " " );

  pchTemp = oVerInfo.GetProductName();
  strcat( pchOutput, pchTemp );
  strcat( pchOutput, " " );

  pchTemp = oVerInfo.GetProductVersion();
  strcat( pchOutput, pchTemp );
  strcat( pchOutput, " " );

  pchTemp = oVerInfo.GetFileVersion();
  strcat( pchOutput, pchTemp );
  strcat( pchOutput, " " );
    
  pchTemp = oVerInfo.GetFileDescription();
  strcat( pchOutput, pchTemp );
  strcat( pchOutput, " " );

  pchTemp = oVerInfo.GetOriginalFileName();
  strcat( pchOutput, pchTemp );
  strcat( pchOutput, " " );

  pchTemp = oVerInfo.GetInternalName();
  strcat( pchOutput, pchTemp );

  return( true );
}
/* End of function "VMODBCConnection::GetVendorInfo"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::Open

       DESCRIPTION:  opens the connection to the database

             INPUT:  lpszDSN - pointer to string containing dsn to use for the
                               connection
                     bExclusive - true if this is an exclusive connection to the
                               dbms
                     bReadonly - true if this is a read only connection
                     lpszConnect - the string argument to the connection
                     bUseCursorLib - true if cursors are to be used
            OUTPUT:  

           RETURNS:  true if worked, false if not
*/
bool VMODBCConnection::Open( LPCTSTR lpszDSN, 
                             bool    bExclusive,
                             bool    bReadonly, 
                             LPCTSTR lpszConnect, 
                             bool    bUseCursorLib )
{
  VMString oConnect;

  if ( lpszConnect != NULL )
  {
    oConnect = lpszConnect;
  }

  // For VB/Access compatibility, require "ODBC;" (or "odbc;")
  // prefix to the connect string
  //
  if ( _tcsnicmp( oConnect, "ODBC;", lstrlen( "ODBC;" ) ) != 0 )
  {
    return( false );
  }

  // Strip "ODBC;"
  //
  oConnect.Right( oConnect.GetLength() - lstrlen( "ODBC;" ), oConnect );

  if ( lpszDSN != NULL && lstrlen( lpszDSN ) != 0 )
  {
    // Append "DSN=" lpszDSN
    // 
    oConnect += _T( ";DSN=" );
    oConnect += lpszDSN;
  }

  DWORD dwOptions = 0;

  if ( bExclusive )
  {
    dwOptions |= openExclusive;
  }

  if ( bReadonly )
  {
    dwOptions |= openReadOnly;
  }

  if ( bUseCursorLib )
  {
    dwOptions |= useCursorLib;
  }

  return( OpenEx( (const char*)oConnect, dwOptions ) );
}
/* End of function "VMODBCConnection::Open"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::OpenEx

       DESCRIPTION:  opens a connections to the dbms

             INPUT:  lpszConnectString - pointer to string containing connection
                     info
                     dwOptions - connection options
            OUTPUT:  

           RETURNS:  true if worked, false if not
*/
bool VMODBCConnection::OpenEx( LPCTSTR lpszConnectString, DWORD dwOptions )
{
  assert( !( dwOptions & noOdbcDialog && dwOptions & forceOdbcDialog ) );

  // Exclusive access not supported.
  //
  assert( !( dwOptions & openExclusive ) );

  m_bUpdatable = !( dwOptions & openReadOnly );

  m_oConnect = lpszConnectString;

  try
  {
    // Allocate the HDBC and make connection
    //
    AllocConnect( dwOptions );

    if ( !Connect( dwOptions ) )
    {
      return( false );
    }

    // Verify support for required functionality and cache info
    //
    VerifyConnect();
    GetConnectInfo();
    m_bIsOpen = true;
  }
  catch( VMException* poError )
  {
    Free();
    throw poError;
  }
  return( true );
}
/* End of function "VMODBCConnection::OpenEx"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::CanTransact

       DESCRIPTION:  determines if transactions are supported in the driver / dbms

             INPUT:  void
            OUTPUT:  none

           RETURNS:  true if can, false if can not
*/
bool VMODBCConnection::CanTransact( void ) const 
{
	return( m_bTransactions );  
}
/* End of function "VMODBCConnection::CanTransact"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMODBCConnection::ExecuteSQLGetRowCount

       DESCRIPTION:  used to execute a specific sql command againts the dbms

             INPUT:  lpszSQL - pointer to string containing the command to exec
            OUTPUT:  none

           RETURNS:  affected row count from dbms drivers
*/
int VMODBCConnection::ExecuteSQLGetRowCount( LPCTSTR lpszSQL )
{
  VMPerfTimer oTimer( "ExecuteSQLGetRowCount" );

  SQLINTEGER  iResult = 0;
  RETCODE     nRetCode;
  HSTMT       hstmt;

  nRetCode = ::SQLAllocStmt( m_hdbc, &hstmt );

  if ( !CheckHstmt( nRetCode, hstmt ) )
  {
    GetErrorMessages( SQL_HANDLE_STMT, hstmt );
    throw new VMException( __FILE__, __LINE__, "SQLAllocStatement Failed.", VMException::fatal );
  }

  try
  {
    OnSetOptions( hstmt );

    // Give derived VMODBCConnection classes option to use parameters
    //
    BindParameters( hstmt );

    if ( CanTransact() )
    {
       BeginTrans();
    }

    VMPerfTimer oExecTime( "SQLExecDirect", false );
    oExecTime.StartTimer();
    ODBC_CALL_WAIT( ::SQLExecDirect( hstmt,
                                     (unsigned char*) lpszSQL, 
                                     SQL_NTS ) );
    oExecTime.StopTimer();

    if ( CanTransact() )
    {
      CommitTrans();
    }
 
    if ( !CheckHstmt( nRetCode, hstmt ) )
    {
      GetErrorMessages( SQL_HANDLE_STMT, hstmt );

      // test for a lost database connection
      //
      char* pcTest = strstr( (const char*)m_auchErrorMsg, COMM_LINK_FAILED );
      if( pcTest != NULL )
      {
        // connection has been broken

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -