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

📄 myrecordset.cpp

📁 魔域的服务端源代码。Visual C++编译的版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// MyRecordset.cpp: implementation of the CMyRecordset class.
//
//////////////////////////////////////////////////////////////////////

//#ifdef	MULTITHREAD_SAFE
//#define	LOCKADD_TIMESUM
//#else
extern	long	s_nDatabaseTimeSum;			//?? 用于统计数据库操作所消耗的时间
#define	LOCKADD_TIMESUM		::InterlockedExchangeAdd(&s_nDatabaseTimeSum, clock() - tStart)
//#endif

#ifdef	MULTITHREAD_SAFE
	#include <afxmt.h>
	#define	LOCKOBJ		CSingleLock xLock(&m_xCtrl, true)
	#include <winsock2.h>
#else
	#define	LOCKOBJ		
#endif

#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>

#include "mydb.h"
#include "basefunc.h"
#include "common.h"

#ifdef	NO_MUTEX
	#define		RELEASE_MUTEX(x)
#else
	#define		RELEASE_MUTEX(x)		::ReleaseMutex(x)
#endif


// static init
CMyHeap	CMyRecordset::s_heapString("CMyRecordset::s_heapString");
#ifdef	MULTITHREAD_SAFE
	CCriticalSection	CMyRecordset::m_xCtrl;
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// 构建 UpdateSQLs

MYHEAP_IMPLEMENTATION(CMyRecordset,s_heap)
///////////////////////////////////////////////////////////////////////
void CMyRecordset::BuildUpdateCondition()
{
	switch ( m_nEditMode )
	{	
	case modeEdit:
		sprintf(m_szUpdateCondition, "%s=%s", m_szKey, m_Row[m_uiKeyIndex]);
		break;
	case modeAddNew:
	case modeDelete:
		sprintf(m_szUpdateCondition, "%s=%u", m_szKey, m_objFields[m_uiKeyIndex].m_ulVal);
		break;
	}
}

///////////////////////////////////////////////////////////////////////
void CMyRecordset::BuildUpdateOpration()
{
	char szFormat[1024];

	m_szUpdateOpration[0]='\0';

	BOOL bFirst = true;
	BOOL bFlag = true;
	
	switch ( m_nEditMode )
	{	
	case modeEdit:
	case modeAddNew:
		for (UINT i=0; i<m_uiFieldsCount; i++ )
		{	
			if ( m_pbDirty[i] )
			{
				switch (m_objFields[i].m_ulType)
				{
				case FIELD_TYPE_STRING:
				case FIELD_TYPE_VAR_STRING:
					if (strlen(m_objFields[i].m_szVal) == NULL) 
						bFlag = false;
					else 
						sprintf(szFormat, "='%s'",m_objFields[i].m_szVal);
					break;

				case FIELD_TYPE_TINY:
				case FIELD_TYPE_SHORT:
					sprintf(szFormat, "=%d",m_objFields[i].m_iVal);
					break;

				case FIELD_TYPE_FLOAT:
					sprintf(szFormat, "=%.2f",m_objFields[i].m_fVal);
					break;

				case FIELD_TYPE_DOUBLE:
					sprintf(szFormat, "=%.2f",m_objFields[i].m_dVal);
					break;

				case FIELD_TYPE_LONG:
					if ((m_Fields[i].flags&UNSIGNED_FLAG) != 0)
						sprintf(szFormat, "=%u", m_objFields[i].m_ulVal);
					else
						sprintf(szFormat, "=%ld", m_objFields[i].m_lVal);
					break;

				default:
					::LogSave("Error: unknow type in CMyRecordset::BuildUpdateOpration()");
					break;
				}

				if (bFlag)
				{	
					if (!bFirst)
						strcat(m_szUpdateOpration,",");
					else 
						bFirst = false;

					strcat(m_szUpdateOpration, m_Fields[i].name);
					strcat(m_szUpdateOpration, szFormat);
					if(strlen(m_szUpdateOpration) >= 1024)
						::LogSave("ERROR: BuildUpdateOpration() 溢出!!!");
				}
				else
					bFlag	=true;

			} // if ( m_pbDirty[i] )
		} // for ( i=0; i<m_uiFieldsCount; i++ )
		break;
	}
}


///////////////////////////////////////////////////////////////////////
void CMyRecordset::BuildUpdateSQL()
{
	if (!m_bCanUpdate) return;

	BuildUpdateOpration();
	BuildUpdateCondition();

	char * psz;

	switch (m_nEditMode)
	{
	case modeDelete:
		psz = (char * )SQL_STMT_DELETE;
		break;

	case modeEdit:
		psz = (char * )SQL_STMT_UPDATE;
		break;

	case modeAddNew:
		psz = (char * )SQL_STMT_INSERT;
		break;
	}

	sprintf(m_szUpdateSQL,psz,m_szTableName,			//paled - SQL_STMT_DELETE的第2个参数为空串
		m_szUpdateOpration,m_szUpdateCondition);		//paled - SQL_STMT_INSERT只有两个参数,将丢弃第3个参数
	if(strlen(m_szUpdateSQL) >= 1024)
		::LogSave("ERROR: BuildUpdateSQL() 溢出!!!");
}





///////////////////////////////////////////////////////////////////////
bool CMyRecordset::Update()
{
	if (!m_bIsOpen) 
		return false;

	m_bEdit = false;

	bool ret	=true;
	if (this->UpdateFieldsCount() > 0)
	{
		// build sql
		this->BuildUpdateSQL();

		// need change the local row;
		MYSQL_RES * res;
		ret = Query(m_szUpdateSQL, &res);
		if(ret && res)
			mysql_free_result(res);
	}

	// clear edit flag
	this->ClsEditFlag();

	return	ret;
}








///////////////////////////////////////////////////////////////////////
CMyField * CMyRecordset::GetFieldRef(UINT uiIndex)
{
	return m_objFields+uiIndex;
}


///////////////////////////////////////////////////////////////////////
void CMyRecordset::GetFieldValue(UINT uiIndex)		//paled - 将ROW中的串转换为数,并填入objField的VAL联合中。
{
/*
	if ( m_ulRowsCount ==0) return;
	if (m_Row[uiIndex] == 0)
	{	m_objFields[uiIndex].m_lVal = 0;
		return;
	}
	switch (m_objFields[uiIndex].m_ulType)
	{	
	case	FIELD_TYPE_TINY:
	case	FIELD_TYPE_SHORT:
		m_objFields[uiIndex].m_iVal = atoi(m_Row[uiIndex]);
		break;
	case	FIELD_TYPE_LONG:
		m_objFields[uiIndex].m_lVal = atol(m_Row[uiIndex]);
		break;
	case	FIELD_TYPE_DECIMAL:
	case	FIELD_TYPE_FLOAT:
	case	FIELD_TYPE_DOUBLE:
		m_objFields[uiIndex].m_dVal = atof(m_Row[uiIndex]);
		break;
	case	FIELD_TYPE_STRING:
	case	FIELD_TYPE_VAR_STRING:
		strcpy(m_objFields[uiIndex].m_szVal,m_Row[uiIndex]);
		break;
	}
*/
}	

///////////////////////////////////////////////////////////////////////
void CMyRecordset::GetAllField()		//paled - 将ROW中的串转换为数,并填入objField的VAL联合中。
{
	if(m_Row)
	{
		for(int i = 0; i < FieldsCount(); i++)
		{
			if ( m_ulRowsCount ==0) return;
			if (m_Row[i] == 0)
			{	m_objFields[i].m_lVal = 0;
				return;
			}
			switch (m_objFields[i].m_ulType)
			{	
			case	FIELD_TYPE_TINY:
			case	FIELD_TYPE_SHORT:
				m_objFields[i].m_iVal = atoi(m_Row[i]);
				break;
			case	FIELD_TYPE_LONG:
				m_objFields[i].m_lVal = atol(m_Row[i]);
				break;
			case	FIELD_TYPE_DECIMAL:
			case	FIELD_TYPE_FLOAT:
			case	FIELD_TYPE_DOUBLE:
				m_objFields[i].m_dVal = atof(m_Row[i]);
				break;
			case	FIELD_TYPE_STRING:
			case	FIELD_TYPE_VAR_STRING:
				strcpy(m_objFields[i].m_szVal,m_Row[i]);
				break;
			}
		}
	}

	ClsEditFlag();
}

///////////////////////////////////////////////////////////////////////
bool CMyRecordset::GetDefauldField()		//paled - 取缺省域值,并填入objField的VAL联合中。
{
	MYSQL_RES *pRes = mysql_list_fields(m_pMyDatabase->m_hdbc, m_szTableName, NULL);
	if(!pRes)
		return false;

	for(int i = 0; i < FieldsCount(); i++)
	{
		MYSQL_FIELD * pField = mysql_fetch_field(pRes);
		if(!pField)
		{
			ASSERT(!"GetDefauldField()");
			mysql_free_result(pRes);
			return false;
		}

		switch (m_objFields[i].m_ulType)
		{
		case	FIELD_TYPE_TINY:
		case	FIELD_TYPE_SHORT:
			if(pField->def)
				m_objFields[i].m_iVal = atol(pField->def);
			else
				m_objFields[i].m_iVal = 0;
			break;
		case	FIELD_TYPE_LONG:
			if(pField->def)
				m_objFields[i].m_lVal = atol(pField->def);
			else
				m_objFields[i].m_lVal = 0;
			break;
		case	FIELD_TYPE_DECIMAL:
		case	FIELD_TYPE_FLOAT:
		case	FIELD_TYPE_DOUBLE:
			if(pField->def)
				m_objFields[i].m_dVal = atof(pField->def);
			else
				m_objFields[i].m_dVal = 0;
			break;
		case	FIELD_TYPE_STRING:
		case	FIELD_TYPE_VAR_STRING:
			if(pField->def)
				strcpy(m_objFields[i].m_szVal, pField->def);
			else
				strcpy(m_objFields[i].m_szVal, "");
			break;
		}
	}

	mysql_free_result(pRes);

	ClsEditFlag();
	m_bDefaultValue	= true;
	return true;
}	

// 基本操作

///////////////////////////////////////////////////////////////////////
CMyRecordset::CMyRecordset(CMyDatabase  * pMyDatabase )
{	
	m_bIsOpen = false;
	m_bEdit	  = false;

	m_pMyDatabase = pMyDatabase;
	if (pMyDatabase == NULL ) return;
	m_Recordset = NULL;
	
	if (m_pMyDatabase != NULL && m_pMyDatabase->IsOpen())
	{	m_pMyDatabase->m_nRefCount++;
	}
}			//★ 未初始化其它成员变量(其它成员变量由open()初始化)

///////////////////////////////////////////////////////////////////////
CMyRecordset* CMyRecordset::CreateNew(CMyDatabase  * pMyDatabase)
{
	if (pMyDatabase == NULL ||
			!pMyDatabase->IsOpen())
		return NULL;

	return (new CMyRecordset(pMyDatabase));
}

///////////////////////////////////////////////////////////////////////
bool CMyRecordset::Open(const char * szSQL)
{	
	try {
		time_t	tStart = clock();
		if(!m_pMyDatabase)
			return false;

		int nLen = strlen(szSQL);
		char * p,* sz= strstr((char*)szSQL, "FROM");
		int nSize = 0;
		if(sz == NULL)
			sz= strstr((char*)szSQL, "from");

		if (!m_pMyDatabase->IsOpen())  return false;

		MYSQL * hdbc = m_pMyDatabase->m_hdbc;

		strcpy(m_szSQL,szSQL);

		if (m_bIsOpen) 
		{	Close();
			g_nMyDBError = 2000;
			return false;
		}

#ifdef	NO_MUTEX
		if(false)
#else
		if (WAIT_TIMEOUT ==::WaitForSingleObject(m_pMyDatabase->m_hDbMutex, _MAX_DBACCESSTIME))
#endif
		{
			::LogSave("*DATABASE* WARNING: Open() overtime");
			return false;
		}
//@@@int sec = (rand()%5)*100 + 0;printf("*[%d] --> ", sec/100); Sleep(sec); printf("|||\n");
		CTimeCostChk chk("CMyRecordset::Open", 1000);

		if (mysql_query(hdbc, m_szSQL)!=NULL)
		{	
			RELEASE_MUTEX(m_pMyDatabase->m_hDbMutex);
			g_nMyDBError = 2001;

			// log error sql
			::MsgLogSave("gmlog/DbError", "%s", szSQL);
			return false;
		}
		else 
		{	
			m_Recordset=mysql_store_result(hdbc);

			RELEASE_MUTEX(m_pMyDatabase->m_hDbMutex);
			if (m_Recordset == NULL)
			{	g_nMyDBError = 2002;
				return false;
			}
			else 
			{	
				m_bBOF = false;
				m_bEOF = false;
				m_bIsOpen = true;
				m_bDefaultValue	= false;		// paled

				m_uiFieldsCount = mysql_num_fields(m_Recordset);
				m_ulRowsCount = mysql_num_rows(m_Recordset);
				m_Fields = mysql_fetch_field(m_Recordset);
				
				m_objFields = new CMyField [m_uiFieldsCount];
				//m_pbDirty	= new bool [m_uiFieldsCount];
#ifdef	USE_NEW
				m_pbDirty	= (bool *)s_heapString.Alloc(sizeof(bool) * m_uiFieldsCount);
#else
				m_pbDirty	= (bool *)g_heapSystem.New(sizeof(bool) * m_uiFieldsCount);		//★ 全局堆分配,可能产生内存碎片。
#endif
				ZeroMemory(m_pbDirty, sizeof(bool) * m_uiFieldsCount);
				

				m_bCanUpdate = false;
				for (UINT i =0; i< m_uiFieldsCount; i++)
				{	m_objFields[i].m_Field = m_Fields[i];
					m_objFields[i].m_ulType = m_Fields[i].type;

					if (m_objFields[i].m_ulType == FIELD_TYPE_VAR_STRING 
							|| m_objFields[i].m_ulType == FIELD_TYPE_STRING)
#ifdef	USE_NEW
						m_objFields[i].m_szVal	= (char *) s_heapString.Alloc(sizeof(char)*(m_Fields[i].length+1));
#else
						m_objFields[i].m_szVal = (char *) g_heapSystem.New(sizeof(char)*(m_Fields[i].length+1));
																		//★ 全局堆分配,会有内存碎片
#endif
					
					m_objFields[i].m_pMyField = &m_objFields[i];	//paled
					m_objFields[i].m_nIndex = i;
					if (
						!m_bCanUpdate && (
						m_Fields[i].flags & PRI_KEY_FLAG ||
						//paled 不安全		m_Fields[i].flags & UNIQUE_KEY_FLAG ||
						m_Fields[i].flags & AUTO_INCREMENT_FLAG ) )
					{	m_bCanUpdate = true;
						strcpy(m_szKey,m_Fields[i].name);
						m_uiKeyIndex = i;
					}
				}
				MoveFirst();
				if (sz !=NULL) 
				{	sz = strstr(sz+1," ");
					if ( sz !=NULL )  
					{	p=sz+1;
						sz = strstr(sz+1," ");
						if ( sz == NULL) nSize = nLen -(p-szSQL);
						else nSize = sz - p;
					}
				}
				strncpy(m_szTableName,p,nSize);
				m_szTableName[nSize]='\0';
			}
		}
		LOCKADD_TIMESUM;
		return true;
	}
	catch(...)
	{
		char szMsg[]	="Mysql RecordSet open error.";
		::OutputDebugString(szMsg);
		return false;
	}
}

///////////////////////////////////////////////////////////////////////
void CMyRecordset::Close()
{	
	try {
		if (m_bIsOpen)
		{	
#ifdef	USE_NEW
			s_heapString.Free(m_pbDirty);
#else
			g_heapSystem.Delete(m_pbDirty);
#endif
			for (unsigned int i=0;i<m_uiFieldsCount;i++)
			if (m_objFields[i].m_ulType == FIELD_TYPE_STRING 
				|| m_objFields[i].m_ulType == FIELD_TYPE_VAR_STRING)
#ifdef	USE_NEW
				s_heapString.Free(m_objFields[i].m_szVal);
#else
				g_heapSystem.Delete(m_objFields[i].m_szVal);
#endif

			delete [] m_objFields;
			m_pMyDatabase->m_nRefCount --;
		}
		m_bIsOpen = false;
		m_ulRowsCount = 0;
		if (m_Recordset !=NULL)
			mysql_free_result(m_Recordset);
		m_Recordset = NULL;
	}
	catch(...)
	{
		char szMsg[]	="Mysql RecordSet close error.";
		::OutputDebugString(szMsg);
	}
}

///////////////////////////////////////////////////////////////////////
CMyRecordset::~CMyRecordset()
{
	if (m_bIsOpen) Close();
}


///////////////////////////////////////////////////////////////////////
// 数据集操作
void CMyRecordset::Edit()
{	m_bEdit = true;
	if (! m_bIsOpen ) return;
	m_nEditMode = modeEdit;

}

///////////////////////////////////////////////////////////////////////
void CMyRecordset::AddNew()

⌨️ 快捷键说明

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