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

📄 myrecord.cpp

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

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

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

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

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

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


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

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

// 构建 UpdateSQLs

MYHEAP_IMPLEMENTATION(CMyRecord,s_heap)
///////////////////////////////////////////////////////////////////////
bool CMyRecord::FormatField(char* szFormat, const CMyField& objField)
{
	switch (objField.m_ulType)
	{
	case FIELD_TYPE_STRING:
	case FIELD_TYPE_VAR_STRING:
		if (strlen(objField.m_szVal) == NULL)			//paled 不能向数据库写入空串!!!
			return false;
		else 
			sprintf(szFormat, "'%s'",objField.m_szVal);
		break;

	case FIELD_TYPE_TINY:
	case FIELD_TYPE_SHORT:
		sprintf(szFormat, "%d",objField.m_iVal);
		break;

	case FIELD_TYPE_FLOAT:
		sprintf(szFormat, "%.2f",objField.m_fVal);
		break;

	case FIELD_TYPE_DOUBLE:
		sprintf(szFormat, "%.2f",objField.m_dVal);
		break;

	case FIELD_TYPE_LONG:
		if ((objField.m_Field.flags & UNSIGNED_FLAG) != 0)
			sprintf(szFormat, "%u", objField.m_ulVal);
		else
			sprintf(szFormat, "%ld", objField.m_lVal);
		break;

	default:
		::LogSave("Error: unknow type in CMyRecord::FieldToStr()");
		return false;
	}

	return true;
}

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

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

	m_szUpdateOpration[0]='\0';

	BOOL bFirst = true;
	
	switch ( m_nEditMode )
	{	
	case modeEdit:
	case modeAddNew:
		for (UINT i=0; i<m_uiFieldsCount; i++ )
		{	
			if ( m_pbDirty[i] )
			{
				if (FormatField(szFormat, m_objFields[i]))
				{	
					if (!bFirst)
						strcat(m_szUpdateOpration,",");
					else 
						bFirst = false;

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

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


///////////////////////////////////////////////////////////////////////
void CMyRecord::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 CMyRecord::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 * CMyRecord::GetFieldRef(UINT uiIndex)
{
	return m_objFields+uiIndex;
}

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

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

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

	return (new CMyRecord(pMyDatabase));
}

///////////////////////////////////////////////////////////////////////
bool CMyRecord::Open(CMyRecordset  *pMyRecordset, DWORD idNewKey /*= NEWKEY_NONE*/)
{
	if (pMyRecordset == NULL ||	!pMyRecordset->IsOpen())
		return NULL;

	if (!m_pMyDatabase->IsOpen())
		return false;
	if (!( pMyRecordset->IsOpen() && (pMyRecordset->RecordCount() > 0 || pMyRecordset->m_bDefaultValue) ))	// m_bDefaultValue : add by paled
		return false;

	m_uiFieldsCount	= pMyRecordset->m_uiFieldsCount;
	strcpy(m_szKey, pMyRecordset->m_szKey);
	m_uiKeyIndex	= pMyRecordset->m_uiKeyIndex;
	m_bEdit			= pMyRecordset->m_bEdit;
	m_bIsOpen			= pMyRecordset->m_bIsOpen;
	m_nEditMode		= pMyRecordset->m_nEditMode;
	strcpy(m_szTableName, pMyRecordset->m_szTableName);
	m_bCanUpdate		= pMyRecordset->m_bCanUpdate;

#ifdef	USE_NEW
	m_pbDirty	= (bool*)s_heapString.Alloc(sizeof(bool) * pMyRecordset->m_uiFieldsCount);
#else
	m_pbDirty	= (bool *)g_heapSystem.New(sizeof(bool) * pMyRecordset->m_uiFieldsCount);		//★ 全局堆分配,可能产生内存碎片。
#endif
	memset(m_pbDirty, 0, (sizeof(bool) * pMyRecordset->m_uiFieldsCount));

#ifdef	USE_NEW
	m_Fields		= (MYSQL_FIELD*)s_heapString.Alloc(sizeof(MYSQL_FIELD) * m_uiFieldsCount);
#else
	m_Fields		= (MYSQL_FIELD*)g_heapSystem.New(sizeof(MYSQL_FIELD) * m_uiFieldsCount);
#endif
	for(int i = 0; i < (int)m_uiFieldsCount; i++)
	{
		m_Fields[i]	= pMyRecordset->m_Fields[i];
#ifdef	USE_NEW
		m_Fields[i].name = (char*)s_heapString.Alloc(sizeof(char) * (strlen(pMyRecordset->m_Fields[i].name)+1));
#else
		m_Fields[i].name = (char*)g_heapSystem.New(sizeof(char) * (strlen(pMyRecordset->m_Fields[i].name)+1));
#endif
		strcpy(m_Fields[i].name, pMyRecordset->m_Fields[i].name);		//VVVVV 注意删除。table、def不复制,从未用到过
	}

	m_objFields		= new CMyField [m_uiFieldsCount];
	for( i = 0; i < (int)m_uiFieldsCount; i++)
	{
		pMyRecordset->GetFieldValue(i);
		m_objFields[i]		= pMyRecordset->m_objFields[i];
		m_objFields[i].m_Field = m_Fields[i];					// 指向本地name串
		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
															//★ 全局堆分配,会有内存碎片
			strcpy(m_objFields[i].m_szVal, pMyRecordset->m_objFields[i].m_szVal);
		}
	}

	if(idNewKey != NEWKEY_NONE)
	{
		sprintf(m_szKeyData, "%u", idNewKey);
		m_objFields[m_uiKeyIndex].m_ulVal	= idNewKey;
	}
	else
		FormatField(m_szKeyData, pMyRecordset->m_objFields[pMyRecordset->m_uiKeyIndex]);

	return true;
}

///////////////////////////////////////////////////////////////////////
bool CMyRecord::Spawn(CMyRecord *pMyRecord, DWORD idNewKey /*= NEWKEY_NONE*/)
{
	*this	= *pMyRecord;

#ifdef	USE_NEW
	m_pbDirty	= (bool *)s_heapString.Alloc(sizeof(bool) * pMyRecord->m_uiFieldsCount);
#else
	m_pbDirty	= (bool *)g_heapSystem.New(sizeof(bool) * pMyRecord->m_uiFieldsCount);		//★ 全局堆分配,可能产生内存碎片。
#endif
	memset(m_pbDirty, 0, (sizeof(bool) * pMyRecord->m_uiFieldsCount));

#ifdef	USE_NEW
	m_Fields		= (MYSQL_FIELD*)s_heapString.Alloc(sizeof(MYSQL_FIELD) * m_uiFieldsCount);
#else
	m_Fields		= (MYSQL_FIELD*)g_heapSystem.New(sizeof(MYSQL_FIELD) * m_uiFieldsCount);
#endif
	for(int i = 0; i < (int)m_uiFieldsCount; i++)
	{
		m_Fields[i]	= pMyRecord->m_Fields[i];
#ifdef	USE_NEW
		m_Fields[i].name = (char*)s_heapString.Alloc(sizeof(char) * (strlen(pMyRecord->m_Fields[i].name)+1));
#else
		m_Fields[i].name	= (char*)g_heapSystem.New(sizeof(char) * (strlen(pMyRecord->m_Fields[i].name)+1));
#endif
		strcpy(m_Fields[i].name, pMyRecord->m_Fields[i].name);		//VVVVV 注意删除。table、def不复制,从未用到过
	}

	m_objFields		= new CMyField [m_uiFieldsCount];
	for( i = 0; i < (int)m_uiFieldsCount; i++)
	{
		m_objFields[i]		= pMyRecord->m_objFields[i];
		m_objFields[i].m_Field	= m_Fields[i];					// 指向本地name串
		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
															//★ 全局堆分配,会有内存碎片
			strcpy(m_objFields[i].m_szVal, pMyRecord->m_objFields[i].m_szVal);
		}
	}

	if(idNewKey != NEWKEY_NONE)
	{
		sprintf(m_szKeyData, "%u", idNewKey);
		m_objFields[m_uiKeyIndex].m_ulVal	= idNewKey;
	}

	return true;
}

///////////////////////////////////////////////////////////////////////
void CMyRecord::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

#ifdef	USE_NEW
				s_heapString.Free(m_Fields[i].name);			// AAAAAAAAAAAAAAAAAA
#else
				g_heapSystem.Delete(m_Fields[i].name);
#endif
			}
			delete [] m_objFields;
#ifdef	USE_NEW
			s_heapString.Free(m_Fields);
#else
			g_heapSystem.Delete(m_Fields);
#endif
			m_pMyDatabase->m_nRefCount --;
		}
		m_bIsOpen = false;
	}
	catch(...)
	{
		char szMsg[]	="Mysql RecordSet close error.";
		::OutputDebugString(szMsg);
	}
}

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


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

///////////////////////////////////////////////////////////////////////
void CMyRecord::AddNew()
{	m_bEdit = true;
	if (! m_bIsOpen ) return;
	m_nEditMode = modeAddNew;
}

///////////////////////////////////////////////////////////////////////
void CMyRecord::Delete()
{	m_bEdit = true;
	if (! m_bIsOpen ) return;
	m_nEditMode = modeDelete;
}

///////////////////////////////////////////////////////////////////////
// SQL
bool CMyRecord::Query(char * strSQL, MYSQL_RES * * res)
{
	if (!CMyDatabase::CheckSQL(strSQL))
		return false;

	try {
		if (!m_bIsOpen) return false;

		time_t	tStart = clock();
#ifdef	NO_MUTEX

⌨️ 快捷键说明

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