📄 vmodbc.cpp
字号:
m_bIsEOF = false;
return( ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO );
}
/* End of function "VMODBC::MovePrev"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveToStart
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveToStart( void )
{
SQLRETURN ret;
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_FIRST, 0 );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsBOF = ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO;
if ( m_bIsBOF )
{
m_bIsEOF = false;
}
return m_bIsBOF;
}
/* End of function "VMODBC::MoveToStart"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveToEnd
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveToEnd( void )
{
SQLRETURN ret;
ret = ::SQLFetchScroll( m_hstmt, SQL_FETCH_LAST, 0 );
if ( SQL_SUCCESS != ret )
{
DecodeSQLError( ret,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
m_bIsEOF = ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO;
if( m_bIsEOF )
{
m_bIsBOF = false;
}
return( m_bIsEOF );
}
/* End of function "VMODBC::MoveToEnd"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveForward
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveForward( int iMoveAmount )
{
do
{
;
} while( MoveNext() && --iMoveAmount >= 0 );
if ( iMoveAmount == 0 )
{
return( true );
}
else
{
return( false );
}
}
/* End of function "VMODBC::MoveForward"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MoveBackward
DESCRIPTION: cursor mover
INPUT: none
OUTPUT: none
RETURNS: instance count if the switch was found, -1 otherwise
*/
bool VMODBC::MoveBackward( int iMoveAmount )
{
do
{
;
} while( MovePrev() && -- iMoveAmount >= 0 );
if ( iMoveAmount == 0 )
{
return( true );
}
else
{
return( false );
}
}
/* End of function "VMODBC::MoveBackward"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::ExchangeData
DESCRIPTION: does any work required to move data from the sql buffers
into local buffers, then invokes the poDataExchange object
to move that data into the application space ( the exchanger
is expected to provide mediation services between this and
the application )
INPUT: poDataExchange : pointer to the data exchanger object
OUTPUT: none
RETURNS: void
*/
void VMODBC::ExchangeData( VMDataExchanger* poDataExchange )
{
bool bCanExchange = true;
if ( m_bIsBound )
{
// simple, all columns are bound, so cursor lib already did the work
}
else
{
// harder have to fetch data ourselves since no buffers are bound
//
COLUMN_INFO_BY_INDEX_ITER oIndexIter;
for ( oIndexIter = m_oColumnsByIndex.begin();
oIndexIter != m_oColumnsByIndex.end();
oIndexIter++ )
{
VMColumnInfo* poColumnInfo = *oIndexIter;
RETCODE nRetCode;
switch( poColumnInfo->m_iSqlDataType )
{
// directly transfer simple types,
// no additional buffer allocations needed
//
case SQL_DECIMAL:
case SQL_NUMERIC:
case SQL_BIT:
case SQL_TINYINT:
case SQL_SMALLINT:
case SQL_INTEGER:
case SQL_REAL:
case SQL_FLOAT:
case SQL_DOUBLE:
case SQL_GUID:
{
nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
poColumnInfo->m_pvData,
sizeof( poColumnInfo->m_pvData ),
NULL );
}
break;
case SQL_BIGINT:
{
// since SQL_C_BIGINT is not defined for
// our version of library, must fall back
// to this approach:
//
// get as a string, then convert to _int64
//
char achValue[ 50 ];
nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
achValue,
sizeof( achValue ),
NULL );
#ifdef _UNICODE
*( (_int64*)poColumnInfo->m_pvData ) = _wtoi64( achValue );
#else
*( (_int64*)poColumnInfo->m_pvData ) = _atoi64( achValue );
#endif
}
break;
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_WCHAR:
case SQL_WVARCHAR:
//
// mjs: are these correctly interpreted as strings?
//
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:
{
VMString* poText = ((VMString*)poColumnInfo->m_pvData);
char* pchBuffer = poText->GetBufferSetLength( 1000 );
long iLength;
nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
pchBuffer,
1000,
&iLength );
int iTestFlags = IS_TEXT_UNICODE_ASCII16;
if ( IsTextUnicode( pchBuffer, iLength, &iTestFlags ) )
{
// stupid db did some unicode crap, undo it....
//
if ( iLength > 0 )
{
char* pchTemp = new char[ iLength ];
if ( WideCharToMultiByte( CP_ACP,
0,
(const unsigned short*)pchBuffer,
-1,
pchTemp,
iLength,
NULL,
NULL ) )
{
poText->ReleaseBuffer();
*poText = pchTemp;
}
delete [] pchTemp;
}
}
else
{
poText->ReleaseBuffer();
}
}
break;
case SQL_LONGVARCHAR:
case SQL_WLONGVARCHAR:
{
VMString* poText = ((VMString*)poColumnInfo->m_pvData);
poText->Empty();
SQLCHAR achLocalBuffer[ 5000 ];
SQLINTEGER iLengthIndicator;
memset( achLocalBuffer, 0, 5000 );
while ( SQL_NO_DATA != ( nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
achLocalBuffer,
sizeof( achLocalBuffer ),
&iLengthIndicator ) ) )
{
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
break;
}
*poText += (const char*)achLocalBuffer;
memset( achLocalBuffer, 0, 5000 );
}
}
break;
case SQL_DATE:
case SQL_TIME:
case SQL_TIMESTAMP:
{
nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
poColumnInfo->m_pvData,
sizeof( poColumnInfo->m_pvData ),
NULL );
}
break;
case SQL_BINARY:
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
{
VMByteArray* poData = ((VMByteArray*)poColumnInfo->m_pvData);
poData->FreeAll();
SQLCHAR* pchLocalBuffer;
SQLINTEGER iLengthIndicator;
int iBufferLength;
if ( poColumnInfo->m_iSqlDataType == SQL_LONGVARBINARY )
{
iBufferLength = 32576;
}
else
{
iBufferLength = 256;
}
poData->SetSize( iBufferLength );
pchLocalBuffer = new SQLCHAR[ iBufferLength ];
memset( pchLocalBuffer, 0, 5000 );
while ( SQL_NO_DATA != ( nRetCode = ::SQLGetData( m_hstmt,
poColumnInfo->m_iColumnIndex,
poColumnInfo->m_iCDataType,
pchLocalBuffer,
iBufferLength,
&iLengthIndicator ) ) )
{
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
break;
}
for ( int iLoop = 0;
( iLoop < 5000 ) && ( iLoop < iLengthIndicator );
iLoop++ )
{
poData->Add( (BYTE)pchLocalBuffer[ iLoop ] );
}
memset( pchLocalBuffer, 0, iBufferLength * sizeof( SQLCHAR ) );
}
delete [] pchLocalBuffer;
}
break;
}
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
bCanExchange = false;
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
}
}
}
if ( bCanExchange && poDataExchange )
{
poDataExchange->ExchangeData( this );
}
}
/* End of function "VMODBC::ExchangeData"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBC::MakeColumnListFromQuery
DESCRIPTION: does all the work required to operate against the meta
data for an sql result set, and then calls on subordinates
to use that meta data for the creation of local buffers for
data exchange
INPUT: void
OUTPUT: essentially inits this....
RETURNS: true if worked, false if not
*/
bool VMODBC::MakeColumnListFromQuery( void )
{
bool bResult = false; // Assume we'll fail; allow reselect
RETCODE nRetCode; // Return code from ODBC functions
VMColumnInfo* poColumnInfo; // Data type output for each column
int iIndex; // Index for columns
short iColumns; // the number of columns in this query
// check to see if this object was constructed sans open CDatabase
//
if ( m_hstmt == SQL_NULL_HSTMT )
{
DEBUGOUT( "ERROR!!!!! >>>NO STATEMENT HANDLE<<<" );
throw new VMException( __FILE__, __LINE__, "Invalid Connection or SQL State" );
}
if ( !IsOpen() )
{
DEBUGOUT( "ERROR!!!!! >>>DB CONNECTION CLOSED<<<" );
throw new VMException( __FILE__, __LINE__, "Invalid Connection or SQL State" );
}
// how many columns are there in the result
//
nRetCode = ::SQLNumResultCols( m_hstmt, &iColumns );
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
goto cleanup;
}
// now loop through the column set gathering facts about each one
// to store in a CColumn class for each column. All the CColumn
// classes will be added to the m_CPA_ColumnInfoList
//
for( iIndex = 0; iIndex < iColumns; iIndex++ )
{
poColumnInfo = new VMColumnInfo;
if ( poColumnInfo == NULL )
{
goto cleanup;
}
poColumnInfo->m_iColumnIndex = iIndex + 1;
// get the SQL_xxx type (and related info) for the column
//
nRetCode = ::SQLDescribeCol( m_hstmt,
(UWORD)( iIndex + 1 ),
NULL,
0,
NULL,
&poColumnInfo->m_iSqlDataType,
&poColumnInfo->m_dwPrecision,
&poColumnInfo->m_iScale,
&poColumnInfo->m_iIsNullable );
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
goto cleanup;
}
// Get the named type of the column for mapping
//
nRetCode = ::SQLColAttributes( m_hstmt,
(UWORD)( iIndex + 1 ),
SQL_COLUMN_TYPE_NAME,
&poColumnInfo->m_achNamedType,
sizeof( poColumnInfo->m_achNamedType ),
NULL,
NULL );
if ( RC_NOTSUCCESSFUL( nRetCode ) )
{
DecodeSQLError( nRetCode,
m_hdbc,
m_hstmt,
__FILE__,
__LINE__ );
goto cleanup;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -