📄 vmodbc.cpp
字号:
/*****************************************************************************/
/* SOURCE FILE */
/*****************************************************************************/
/*
$Archive: $
$Revision: $
$Date: $
$Author: $
Description: Implementation of an ODBC wrapper class that can bind to
and read data from any sql result set
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: 2 $ : $Date: 3/14/00 3:33p $";
/*****************************************************************************/
#include "../../../stdafx.h"
#include <string.h>
#include <memory.h>
#include <assert.h>
#pragma warning( disable : 4786 )
#include "VMODBCConnection.h"
#include "../TraceTools/VMWatcherOutput.h"
#include "../VMException.h"
#include "VMByteArray.h"
#include "VMODBC.h"
/////////////////////////////////////////////////////////////////////////////
//
// simple macros for checking SQLfuncx return values for success and warnings
//
#define RC_SUCCESSFUL( rc ) ( !( ( rc ) >> 1 ) )
#define RC_NOTSUCCESSFUL( rc ) ( ( rc ) >> 1 )
const int ciMaxMsgSize = 500;
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::VMODBC
DESCRIPTION: ctor
INPUT: none
OUTPUT: none
RETURNS: none
*/
VMODBC::VMODBC( void ) : VMODBCConnection()
{
m_bIsEOF = true;
m_bIsBOF = true;
m_bIsBound = true;
m_bShouldBind = false;
m_bIsEmpty = true;
m_hstmt = INVALID_HANDLE_VALUE;
m_iColumnCount = 0;
}
/* End of function "VMODBC::VMODBC"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::~VMODBC
DESCRIPTION: dtor
INPUT: none
OUTPUT: none
RETURNS: none
*/
VMODBC::~VMODBC( void )
{
ReleaseColumns();
}
/* End of function "VMODBC::~VMODBC"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::ReleaseColumns
DESCRIPTION: releases all local buffers and column objects
INPUT: void
OUTPUT: none
RETURNS: void
*/
void VMODBC::ReleaseColumns( void )
{
COLUMN_INFO_BY_INDEX_ITER oIndexIter;
for ( oIndexIter = m_oColumnsByIndex.begin();
oIndexIter != m_oColumnsByIndex.end();
oIndexIter++ )
{
VMColumnInfo* poColumnInfo = *oIndexIter;
switch ( poColumnInfo->m_iSqlDataType )
{
// character family
//
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
//
// mjs: is this right for unicode as well?
//
case SQL_WCHAR:
case SQL_WVARCHAR:
case SQL_WLONGVARCHAR:
delete (VMString*)poColumnInfo->m_pvData;
break;
// Integer family
//
case SQL_BIT:
delete (BOOL*)poColumnInfo->m_pvData;
break;
case SQL_TINYINT:
delete (unsigned char *)poColumnInfo->m_pvData;
break;
case SQL_SMALLINT:
delete (int*)poColumnInfo->m_pvData;
break;
case SQL_INTEGER:
delete (long*)poColumnInfo->m_pvData;
break;
case SQL_BIGINT:
delete (_int64*)poColumnInfo->m_pvData;
break;
// Floating-point type family and Fixed-point exact numerics.
//
case SQL_NUMERIC:
delete (double*)poColumnInfo->m_pvData;
// delete (SQL_NUMERIC_STRUCT*)poColumnInfo->m_pvData;
break;
// case SQL_DECIMAL:
case SQL_REAL:
case SQL_FLOAT:
delete (float*)poColumnInfo->m_pvData;
break;
case SQL_DECIMAL:
case SQL_DOUBLE:
delete (double*)poColumnInfo->m_pvData;
break;
case SQL_BINARY:
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
delete (VMByteArray*)poColumnInfo->m_pvData;
break;
// Date/Time family
//
case SQL_DATE:
delete (SQL_TIMESTAMP_STRUCT*)poColumnInfo->m_pvData;
break;
case SQL_TIME:
delete (SQL_TIME_STRUCT*)poColumnInfo->m_pvData;
break;
case SQL_TIMESTAMP:
delete (SQL_TIMESTAMP_STRUCT*)poColumnInfo->m_pvData;
break;
case SQL_GUID:
delete (SQLGUID*)poColumnInfo->m_pvData;
break;
case SQL_INTERVAL_DAY:
case SQL_INTERVAL_DAY_TO_MINUTE:
case SQL_INTERVAL_HOUR:
case SQL_INTERVAL_DAY_TO_SECOND:
case SQL_INTERVAL_MINUTE:
case SQL_INTERVAL_HOUR_TO_MINUTE:
case SQL_INTERVAL_SECOND:
case SQL_INTERVAL_HOUR_TO_SECOND:
case SQL_INTERVAL_DAY_TO_HOUR:
case SQL_INTERVAL_MINUTE_TO_SECOND:
delete (VMString*)poColumnInfo->m_pvData;
break;
default:
delete poColumnInfo->m_pvData;
break;
}
delete poColumnInfo;
}
m_oColumnsByIndex.clear();
m_oColumnsByName.clear();
}
/* End of function "VMODBC::ReleaseColumns"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::Close
DESCRIPTION: essentially shuts this down.
INPUT: none
OUTPUT: none
RETURNS: true
*/
void VMODBC::Close( void )
{
if ( m_hstmt != INVALID_HANDLE_VALUE )
{
::SQLCloseCursor( m_hstmt );
::SQLFreeStmt( m_hstmt, SQL_UNBIND );
m_hstmt = INVALID_HANDLE_VALUE;
ReleaseColumns();
}
m_bIsEmpty = true;
m_bIsBOF = true;
m_bIsEOF = true;
}
/* End of function "VMODBC::Close"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::ExecuteQuery
DESCRIPTION: top level public function. Allows a query to be specified
and then will issue the query. After the query returns will
then build this record set object to bind to whatever the
query came back with
INPUT: pchToExecute : pointer to the query to run ( a string )
OUTPUT: none
RETURNS: true if worked, false if not
*/
bool VMODBC::ExecuteQuery( const char* pchToExecute )
{
RETCODE nRetCode;
m_bIsEmpty = false;
m_bIsEOF = false;
m_bIsBOF = false;
// in case some is getting sloppy, free up resources and
// get ready to bind again
//
if ( m_hstmt != INVALID_HANDLE_VALUE )
{
::SQLCloseCursor( m_hstmt );
::SQLFreeStmt( m_hstmt, SQL_UNBIND );;
m_hstmt = INVALID_HANDLE_VALUE;
ReleaseColumns();
}
::SQLAllocStmt( m_hdbc, &m_hstmt );
nRetCode = SQLSetStmtAttr( m_hstmt,
SQL_ATTR_CURSOR_SCROLLABLE,
(SQLPOINTER)SQL_SCROLLABLE,
SQL_IS_INTEGER );
nRetCode = SQLSetStmtAttr( m_hstmt,
SQL_ATTR_CURSOR_SENSITIVITY,
(SQLPOINTER)SQL_INSENSITIVE,
SQL_IS_INTEGER );
nRetCode = ::SQLExecDirect( m_hstmt,
(SQLCHAR*)pchToExecute,
strlen( pchToExecute ) );
if ( RC_SUCCESSFUL( nRetCode ) )
{
if ( nRetCode != SQL_NO_DATA )
{
if ( MakeColumnListFromQuery() )
{
if ( m_bShouldBind )
{
bool bBoundWithSuccess = true;
COLUMN_INFO_BY_INDEX_ITER oIndexIter;
for ( oIndexIter = m_oColumnsByIndex.begin();
oIndexIter != m_oColumnsByIndex.end();
oIndexIter++ )
{
VMColumnInfo* poColumnInfo = *oIndexIter;
bBoundWithSuccess &= BindColumn( poColumnInfo );
}
m_bIsBound = bBoundWithSuccess;
}
else
{
// make sure this is set right
//
m_bIsBound = false;
}
}
else
{
return( false );
}
}
else
{
m_bIsEmpty = true;
m_bIsBOF = true;
m_bIsEOF = true;
return( true );
}
}
else
{
return( false );
}
MoveToStart();
return( true );
}
/* End of function "VMODBC::ExecuteQuery"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveToIndexFromStart
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveToIndexFromStart( int iIndex )
{
SQLRETURN ret;
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_ABSOLUTE, iIndex );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsBOF = ret == SQL_NO_DATA;
m_bIsEOF = false;
return( ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO );
}
/* End of function "VMODBC::MoveToIndexFromStart"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveToIndexFromEnd
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveToIndexFromEnd( int iIndex )
{
SQLRETURN ret;
iIndex = -1 * abs( iIndex );
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_ABSOLUTE, iIndex );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsEOF = ret == SQL_NO_DATA;
m_bIsBOF = false;
return( ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO );
}
/* End of function "VMODBC::MoveToIndexFromEnd"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveNext
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveNext( void )
{
SQLRETURN ret;
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_NEXT, 0 );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsEOF = ret == SQL_NO_DATA;
m_bIsBOF = false;
return( ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO );
}
/* End of function "VMODBC::MoveNext"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MovePrev
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MovePrev( void )
{
SQLRETURN ret;
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_PRIOR, 0 );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsBOF = ret == SQL_NO_DATA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -