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

📄 odbcrecordset.cpp

📁 几个老外写的源代码大家快快下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:

/*************************************************************************
 FILE       : ODBCRecordset.cpp

 Author :	  Stefan Tchekanov  (stefant@iname.com)

 Description: CODBCRecordset and CDBField classes implementation

 Created By : Stefan Tchekanov


Copyright(c) 1998,1999,2000
Stefan Tchekanov (stefant@iname.com)

This code may be used in compiled form in any way you desire. This
file may be redistributed unmodified by any means PROVIDING it is 
not sold for profit without the authors written consent, and 
providing that this notice and the authors name is included. If 
the source code in this file is used in any commercial application 
then a simple email to the author would be nice.

This file is provided "as is" with no expressed or implied warranty.
The author accepts no liability if it causes any damage.

*************************************************************************/
/* #    Revisions    # */

/*************************************************************************
  REVISION ON 12.09.2000 15:27:22  By Stefan Tchekanov
 
  Comments  : The field names in DoFieldExchange() are made to be quoted
			  in square brackets - [FieldName]. This is the way the class 
			  wizard passes field names in DoFieldExchange() implementations.
 
 *************************************************************************/


/*************************************************************************
  REVISION ON 09.06.2000 21:46:00  By Stefan Tchekanov
 
  Comments  : 1. Added CDBField::operator =( const char );
			  2. Removed (!IsEOF()) && (!IsBOF()) from the ASSERT in
				 CODBCRecordset::Field( int nField ) to be able to
				 add records on empty recordsets
 
 *************************************************************************/



////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ODBCRecordset.h"

////////////////////////////////////////////////////////////////
//
//	CODBCRecordset class
//
////////////////////////////////////////////////////////////////

CODBCRecordset::CODBCRecordset( CDatabase* pDatabase /*= NULL*/ ) : 
				CRecordset( pDatabase )
{
	m_fields = NULL;
	m_AllocatedFields = 0;
}
////////////////////////////////////////////////////////////////

CODBCRecordset::~CODBCRecordset() {
	Clear();
}
////////////////////////////////////////////////////////////////

//	Frees all the allocated memory
void	CODBCRecordset::Clear() {
	if( m_fields != NULL )
		delete[]	m_fields;
	m_fields = NULL;
	m_AllocatedFields = 0;
}
////////////////////////////////////////////////////////////////

//	Open the recordset
//	lpszSQL is a SQL statement that returns recordset
//	e.g. SELECT * FROM tablename
//	nOpentype is CRecordset open type, see CRecordset::Open()
//	dwOptions is CRecordset options, see CRecordset::Open()
BOOL	CODBCRecordset::Open( LPCTSTR lpszSQL, 
							  UINT nOpenType, /*=AFX_DB_USE_DEFAULT_TYPE*/
							  DWORD dwOptions /*= 0*/ )
{
	//	Allocate the maximum possible field info storage
	//	This is managed by CRecordset class
	m_nFields = 255;
	m_bNotLoadedFieldsMap = true;
	BOOL	nRes = CRecordset::Open( 
				nOpenType, 
				lpszSQL, 
				dwOptions );
	
	return	nRes;
}
////////////////////////////////////////////////////////////////

//	Called by Move() to load info about all the fields
void	CODBCRecordset::LoadFieldNamesMap()
{
	m_mapNameIdx.RemoveAll();

	int	nFields = m_nFields = GetODBCFieldCount();

	//	Smart storage reallocation for the fields buffer
	if( m_AllocatedFields < nFields ) {
		Clear();
		m_fields = new CDBField[ m_nFields ];
		m_AllocatedFields = m_nFields;
	}

	//	Load field names map
	CODBCFieldInfo	fi;
	CString			cName;
	for( int i = 0; i < nFields; i++ ) {
		//	Clear the previously allocated storage object
		m_fields[i].Clear();

		// Determine the field type and initialize the data buffer
		GetODBCFieldInfo( i, fi );
		AllocDataBuffer( m_fields[i], fi );
		
		//	Set the field name
		fi.m_strName.MakeUpper();
		cName = fi.m_strName;

		//	Make different field names for the fields with
		//	equal names.
		int	fldCount = 1;
		while( GetFieldID( cName ) != -1 ) {
			fldCount++;
			cName.Format( "%s%d", fi.m_strName, fldCount );
		}
		m_fields[i].m_cName = cName;
		m_mapNameIdx.SetAt( cName, (void*)i );
	}
}
////////////////////////////////////////////////////////////////

//	Overloaded so all the fields be loaded when needed
void	CODBCRecordset::Move( long nRows, WORD wFetchType /*= SQL_FETCH_RELATIVE*/ )
{
	if( m_bNotLoadedFieldsMap )
	{
		LoadFieldNamesMap();
		m_bNotLoadedFieldsMap = false;
	}
	CRecordset::Move( nRows, wFetchType );
}
////////////////////////////////////////////////////////////////

//	Get the field ID by name
//	GetFieldIndexByName() works, but is case sensitive
int	CODBCRecordset::GetFieldID( LPCTSTR szName )
{
	void*	idx = (void*)-1;
	CString	cName( szName );
	cName.MakeUpper();
	if( ! m_mapNameIdx.Lookup( cName, idx ) )
		return	-1;
	return	(int)idx;
}

CString	CODBCRecordset::GetFieldName( int nField )
{
	//	The field ID is invalid
	ASSERT( nField >= 0 );
	ASSERT( nField < GetODBCFieldCount() );

	CString		cName;
	void*		idx;
	POSITION	pos = m_mapNameIdx.GetStartPosition();
	while( pos != NULL ) {
		m_mapNameIdx.GetNextAssoc( pos, cName, idx );
		if( (int)idx == nField )
			return	cName;
	}
	cName.Empty();
	return	cName;
}
////////////////////////////////////////////////////////////////

void CODBCRecordset::DoFieldExchange( CFieldExchange* pFX )
{
	pFX->SetFieldType( CFieldExchange::outputColumn );

	
	CString		cFieldName;
	for( UINT i = 0; i < m_nFields; i++ )
	{
		cFieldName.Format( "[%s]", GetFieldName(i) );
		switch( m_fields[i].m_dwType )
		{
		case	DBVT_NULL:
					break;
		case	DBVT_BOOL:
					RFX_Bool( pFX, cFieldName, m_fields[i].m_boolVal );
					break;
		case	DBVT_UCHAR:
					RFX_Byte( pFX, cFieldName, m_fields[i].m_chVal );
					break;
		case	DBVT_SHORT:
					//	CDBVariant::m_iVal is of type short
					//	RFX_Int() requires parameter of type int.
					//	Class wizard maps int variable in this case
					//	but CDBVariand does not have int member.
					m_fields[i].m_dwType = DBVT_LONG;
					RFX_Long( pFX, cFieldName, m_fields[i].m_lVal );
					break;
		case	DBVT_LONG:
					RFX_Long( pFX, cFieldName, m_fields[i].m_lVal );
					break;
		case	DBVT_SINGLE:
					RFX_Single( pFX, cFieldName, m_fields[i].m_fltVal );
					break;
		case	DBVT_DOUBLE:
					RFX_Double( pFX, cFieldName, m_fields[i].m_dblVal );
					break;
		case	DBVT_DATE:
					RFX_Date( pFX, cFieldName, *m_fields[i].m_pdate );
					break;
		case	DBVT_STRING:
				{
					CODBCFieldInfo	fi;
					GetODBCFieldInfo( i, fi );
					RFX_Text( pFX, cFieldName, *m_fields[i].m_pstring, fi.m_nPrecision );
					break;
				}
		case	DBVT_BINARY:
					RFX_LongBinary( pFX, cFieldName, *(m_fields[i].m_pbinary) );
					break;
		default:
			//	Unknown datatype
			ASSERT( FALSE );
		}
		m_fields[i].SetNull( FALSE != IsFieldStatusNull( i ) );
	}
}
////////////////////////////////////////////////////////////////

short CODBCRecordset::GetCFieldType( short nSQLType )
{
	short nFieldType = 0;

	switch( nSQLType )
	{
	case SQL_BIT:
		nFieldType = SQL_C_BIT;
		break;

	case SQL_TINYINT:
		nFieldType = SQL_C_UTINYINT;
		break;

	case SQL_SMALLINT:
		nFieldType = SQL_C_SSHORT;
		break;

	case SQL_INTEGER:
		nFieldType = SQL_C_SLONG;
		break;

	case SQL_REAL:
		nFieldType = SQL_C_FLOAT;
		break;

	case SQL_FLOAT:
	case SQL_DOUBLE:
		nFieldType = SQL_C_DOUBLE;
		break;

	case SQL_DATE:
	case SQL_TIME:
	case SQL_TIMESTAMP:
		nFieldType = SQL_C_TIMESTAMP;
		break;

	case SQL_NUMERIC:
	case SQL_DECIMAL:
	case SQL_BIGINT:
	case SQL_CHAR:
	case SQL_VARCHAR:
		nFieldType = SQL_C_CHAR;
		break;

	//	SQL_LONGVARCHAR moved here. 
	//	Its default value is SQL_C_CHAR
	case SQL_LONGVARCHAR:
	case SQL_BINARY:
	case SQL_VARBINARY:
	case SQL_LONGVARBINARY:
		nFieldType = SQL_C_BINARY;
		break;

	default:
		//	Unknown data type
		ASSERT( FALSE );
	}

	return	nFieldType;
}
////////////////////////////////////////////////////////////////

void	CODBCRecordset::AllocDataBuffer( CDBVariant& varValue, CODBCFieldInfo& fi )
{
	int	nFieldType = GetCFieldType( fi.m_nSQLType );
	switch( nFieldType )
	{
	case SQL_C_BIT:
		varValue.m_dwType = DBVT_BOOL;
		break;

	case SQL_C_UTINYINT:
		varValue.m_dwType = DBVT_UCHAR;
		break;

	case SQL_C_SSHORT:
		varValue.m_dwType = DBVT_SHORT;
		break;

	case SQL_C_SLONG:
		varValue.m_dwType = DBVT_LONG;
		break;

	case SQL_C_FLOAT:
		varValue.m_dwType = DBVT_SINGLE;
		break;

	case SQL_C_DOUBLE:
		varValue.m_dwType = DBVT_DOUBLE;
		break;

	case SQL_C_TIMESTAMP:
		varValue.m_pdate = new TIMESTAMP_STRUCT;
		varValue.m_dwType = DBVT_DATE;
		break;

	case SQL_C_CHAR:
		varValue.m_pstring = new CString;
		varValue.m_dwType = DBVT_STRING;
		break;

	case SQL_C_BINARY:
		varValue.m_pbinary = new CLongBinary;
		varValue.m_dwType = DBVT_BINARY;
		break;

	default:
		//	Unknown data type
		ASSERT( FALSE );
	}
}
////////////////////////////////////////////////////////////////





////////////////////////////////////////////////////////////////
//
//	CDBField implementation
//
////////////////////////////////////////////////////////////////

void	BinaryToString( CString& cStr, const CLongBinary& bin, bool bExpand )
{
	int	nSize = min( (int)bin.m_dwDataLength, cStr.GetLength() );
	if( bExpand )
		nSize = bin.m_dwDataLength;

	if( nSize < 1 ) {
		cStr.Empty();
		return;
	}

	void*	p = ::GlobalLock( bin.m_hData );
	if( p == NULL )
		::AfxThrowMemoryException();
	
	char* pStr = cStr.GetBuffer( nSize );
	memcpy( pStr, p, nSize );
	cStr.ReleaseBuffer( nSize );
	::GlobalUnlock( bin.m_hData );
}
////////////////////////////////////////////////////////////////

CDBField::CDBField() {
	m_bIsNull = true;
}
////////////////////////////////////////////////////////////////

CDBField::CDBField( const CDBField& dbv ) {
	m_bIsNull = true;
}
////////////////////////////////////////////////////////////////

CDBField::~CDBField() {
}
////////////////////////////////////////////////////////////////

bool	CDBField::AsBool()	const
{
	if( IsNull() )
		return	false;

	CString	cValue;
	switch( m_dwType ) {
	case	DBVT_NULL:
				return	false;

	case	DBVT_BOOL:
				return	(m_boolVal == TRUE);

	case	DBVT_UCHAR:
				return	(m_chVal == 'T' || m_chVal == '1');

	case	DBVT_SHORT:
				return	(m_iVal != 0);

	case	DBVT_LONG:
				return	(m_lVal != 0);

	case	DBVT_SINGLE:
				return	(m_fltVal != 0.0);

	case	DBVT_DOUBLE:
				return	(m_dblVal != 0.0);

	case	DBVT_DATE:
				//	Cannot convert date to bool
				ASSERT( FALSE );
				break;

	case	DBVT_STRING:
				ASSERT( m_pstring != NULL );
				if( m_pstring->GetLength() < 1 )
					return	false;
				return	((*m_pstring)[0] == 'T' || (*m_pstring)[0] == '1');

	case	DBVT_BINARY:
				//	Cannot convert long binary to bool
				ASSERT( FALSE );
				break;
	}
	//	Undefined data type
	ASSERT( FALSE );
	return	false;
}

unsigned char	CDBField::AsChar()	const
{
	if( IsNull() )
		return	' ';

	switch( m_dwType ) {
	case	DBVT_NULL:
				return	' ';

	case	DBVT_BOOL:
				return	(m_boolVal) ? 'T' : 'F';

	case	DBVT_UCHAR:
				return	m_chVal;

	case	DBVT_SHORT:
				return	(unsigned char)m_iVal;

	case	DBVT_LONG:
				return	(unsigned char)m_lVal;

	case	DBVT_SINGLE:
				return	(unsigned char)m_fltVal;

	case	DBVT_DOUBLE:
				return	(unsigned char)m_dblVal;

	case	DBVT_DATE:
				//	Cannot convert date to unsigned char
				ASSERT( FALSE );
				break;

	case	DBVT_STRING:
				ASSERT( m_pstring != NULL );
				if( m_pstring->GetLength() < 1 )
					return	' ';
				return	(unsigned char)((*m_pstring)[0]);

	case	DBVT_BINARY:
				//	Cannot convert long binary to unsigned char
				ASSERT( FALSE );
				break;
	}
	//	Undefined data type
	ASSERT( FALSE );
	return	' ';
}

short	CDBField::AsShort()	const
{
	if( IsNull() )
		return	0;

	switch( m_dwType ) {
	case	DBVT_NULL:
				return	0;

	case	DBVT_BOOL:
				return	m_boolVal ? 1 : 0;

	case	DBVT_UCHAR:
				return	(short)m_chVal;

	case	DBVT_SHORT:
				return	m_iVal;

	case	DBVT_LONG:
				return	(short)m_lVal;

	case	DBVT_SINGLE:
				return	(short)m_fltVal;

	case	DBVT_DOUBLE:
				return	(short)m_dblVal;

	case	DBVT_DATE:
				//	Cannot convert date to short
				ASSERT( FALSE );
				break;

	case	DBVT_STRING:
				ASSERT( m_pstring != NULL );
				return	(short)atoi( *m_pstring );

	case	DBVT_BINARY:
				//	Cannot conver long binary to short
				ASSERT( FALSE );
				break;
	}
	//	Undefined data type
	ASSERT( FALSE );
	return	0;
}

int		CDBField::AsInt()	const
{
	return	AsLong();
}

long	CDBField::AsLong()	const
{
	if( IsNull() )
		return	0;

	switch( m_dwType ) {
	case	DBVT_NULL:
				return	0;

	case	DBVT_BOOL:
				return	m_boolVal ? 1 : 0;

	case	DBVT_UCHAR:
				return	(long)m_chVal;

	case	DBVT_SHORT:
				return	(long)m_iVal;

	case	DBVT_LONG:
				return	m_lVal;

	case	DBVT_SINGLE:
				return	(long)m_fltVal;

	case	DBVT_DOUBLE:
				return	(long)m_dblVal;

	case	DBVT_DATE:
				//	Cannot convert date to long
				ASSERT( FALSE );
				break;

	case	DBVT_STRING:
				ASSERT( m_pstring != NULL );
				return	atol( *m_pstring );

	case	DBVT_BINARY:
				//	Cannot conver long binary to long
				ASSERT( FALSE );
				break;
	}
	//	Undefined data type
	ASSERT( FALSE );
	return	0;
}

float	CDBField::AsFloat()	const
{
	if( IsNull() )
		return	0.0;

	switch( m_dwType ) {
	case	DBVT_NULL:
				return	0.0;

	case	DBVT_BOOL:
				return	(float)(m_boolVal ? 1.0 : 0.0);

	case	DBVT_UCHAR:
				return	(float)m_chVal;

	case	DBVT_SHORT:
				return	(float)m_iVal;

	case	DBVT_LONG:
				return	(float)m_lVal;

	case	DBVT_SINGLE:
				return	m_fltVal;

	case	DBVT_DOUBLE:
				return	(float)m_dblVal;

	case	DBVT_DATE:
				//	Cannot convert date to float
				ASSERT( FALSE );
				break;

	case	DBVT_STRING:
				ASSERT( m_pstring != NULL );
				return	(float)atof( *m_pstring );

	case	DBVT_BINARY:
				//	Cannot conver long binary to float
				ASSERT( FALSE );
				break;
	}
	//	Undefined data type
	ASSERT( FALSE );
	return	0.0;
}

⌨️ 快捷键说明

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