#include "StdAfx.h" #include "CatalogObj.h" #include "SQLStatementImpl.h" ////////////////////////////////////////////////////////////////////////// BOOL CCatalogObj::m_bEndofThread = FALSE; CCatalogObj::CCatalogObj(void) { m_bOpen = FALSE; m_bSolve = FALSE; m_pdbInstance = NULL; m_hReConnectEvent = NULL; m_hReConnectThread = NULL; m_hWaitableTimer = NULL; memset(m_szConnectString,0,sizeof(TCHAR)*MAX_PATH); InitializeCriticalSection(&m_CriticalSection); } CCatalogObj::~CCatalogObj(void) { CloseCatalog(); EndofThread(); DeleteCriticalSection(&m_CriticalSection); } /************************************************************************/ /* 函数:SolveDBError 描述:处理数据库实例操作过程中出现的错误,当前只处理:命名管道连接错误,网络连接错误,网络中断错误; 参数: IN: dwError 操作SQL数据库实例中产生的错误码; IN: lpErrorString 错误码对应的描述; 返回:已处理中返回TRUE,否则返回FALSE; 要求: 注意: */ /************************************************************************/ BOOL CCatalogObj::SolveDBError(IN CONST DWORD &dwError, IN LPCTSTR lpErrorString) { EnterCriticalSection(&m_CriticalSection); if(m_bSolve) { LeaveCriticalSection(&m_CriticalSection); return TRUE; } LeaveCriticalSection(&m_CriticalSection); switch(dwError) { case ERROR_PIPE_NOT_CONNECTED: case WSAECONNRESET: case WSAECONNABORTED: { EnterCriticalSection(&m_CriticalSection); m_bSolve = TRUE; LeaveCriticalSection(&m_CriticalSection); m_strConnectErrorDescriptor = lpErrorString; // 启用重连线程; CloseCatalog(); StartThread(); // LOG4C((LOG_NOTICE,"数据库连接失败,请检查配置信息或数据库服务是否启动!")); } break; default: // 其他错误,输出日志; // LOG4C((LOG_NOTICE,"数据库错误信息:%s",CW2A(lpErrorString))); break; } return FALSE; } /************************************************************************/ /* 函数:StartThread 描述:启动重连线程; 参数: 返回: 要求: 注意: */ /************************************************************************/ int CCatalogObj::StartThread() { #if JEFF_TEST_OFF // 计时器; SYSTEMTIME st; FILETIME ftLocal, ftUTC; LARGE_INTEGER liUTC; st.wYear = 2014; // Year st.wMonth = 12; // January st.wDayOfWeek = 0; // Ignored st.wDay = 1; // The first of the month st.wHour = 13; // 1PM st.wMinute = 0; // 0 minutes into the hour st.wSecond = 0; // 0 seconds into the minute st.wMilliseconds = 0; // 0 milliseconds into the second SystemTimeToFileTime(&st, &ftLocal); // Convert local time to UTC time. LocalFileTimeToFileTime(&ftLocal, &ftUTC); // Convert FILETIME to LARGE_INTEGER because of different alignment. liUTC.LowPart = ftUTC.dwLowDateTime; liUTC.HighPart = ftUTC.dwHighDateTime; //liUTC.QuadPart = -(2*10000000); m_bEndofThread = FALSE; m_hWaitableTimer = CreateWaitableTimer(NULL,FALSE,NULL); const int nTimerUnitsPerSecond = 10000000; SetWaitableTimer(m_hWaitableTimer,&liUTC,3*60*60*1000,NULL,NULL,FALSE); // 3小时执行一次; #else if(m_hReConnectEvent == NULL) m_hReConnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 无信号事件; if (m_hReConnectEvent == NULL) { m_bSolve = FALSE; return -1; } if(m_hReConnectThread == NULL) m_hReConnectThread = CreateThread(NULL, 0, ReConnectDatabaseThread, this, 0, NULL); if (m_hReConnectThread == NULL) { m_bSolve = FALSE; return -1; } else { CloseHandle(m_hReConnectThread); m_hReConnectThread = NULL; } #endif return 0; } /************************************************************************/ /* 函数:EndofThread 描述:结束重连线程; 参数: 返回: 要求: 注意: */ /************************************************************************/ int CCatalogObj::EndofThread() { #if JEFF_TEST_OFF // 重置等待时间,立即返回; LARGE_INTEGER li; const int nTimerUnitsPerSecond = 10000000; li.QuadPart = 1*nTimerUnitsPerSecond; SetWaitableTimer(m_hWaitableTimer,&li,NULL,NULL,NULL,FALSE); m_bEndofThread = TRUE; #else if (m_hReConnectEvent) SetEvent(m_hReConnectEvent); if (m_hReConnectThread) { if (WaitForSingleObject(m_hReConnectThread, INFINITE) != WAIT_TIMEOUT) CloseHandle(m_hReConnectThread); m_hReConnectThread = NULL; } if (m_hReConnectEvent) CloseHandle(m_hReConnectEvent); m_hReConnectEvent = NULL; #endif return 0L; } /************************************************************************/ /* 函数:ReConnectDatabaseThread 描述:重连数据库实例连接的线程; 参数: IN: lpPara CCatalogObj自身; 返回: 要求: 注意: */ /************************************************************************/ DWORD CCatalogObj::ReConnectDatabaseThread(IN LPVOID lpPara) { CCatalogObj *pInstance = (CCatalogObj*)lpPara; #if JEFF_TEST_OFF while ( !m_bEndofThread ) { WaitForSingleObject(pInstance->m_hWaitableTimer,INFINITE); if ( !m_bEndofThread) { if( pInstance->OpenDatabase()) { pInstance->m_bSolve = FALSE; break; } } } if (pInstance->m_hReConnectEvent) CloseHandle(pInstance->m_hReConnectEvent); pInstance->m_hReConnectEvent = NULL; #else do { if( pInstance->OpenCatalog()) { pInstance->m_bSolve = FALSE; break; } } while (WaitForSingleObject(pInstance->m_hReConnectEvent,5000L) == WAIT_TIMEOUT); if (pInstance->m_hReConnectEvent) CloseHandle(pInstance->m_hReConnectEvent); pInstance->m_hReConnectEvent = NULL; #endif return 0L; } /************************************************************************/ /* 函数:OpenCatalog 描述:创建并打开数据库连接对象实例; 参数: IN: lpSQLConnectString 连接数据库实例的连接串; 返回:连接数据库实例成功返回TRUE,否则返回FALSE; 要求: 注意: */ /************************************************************************/ BOOL CCatalogObj::OpenCatalog(LPCTSTR lpSQLConnectString) { EnterCriticalSection(&m_CriticalSection); if(m_bOpen) { LeaveCriticalSection(&m_CriticalSection); return TRUE; } if (lpSQLConnectString == NULL || _tcscmp(lpSQLConnectString,_T("")) == 0) { if (_tcscmp(m_szConnectString, _T("")) == 0) { LeaveCriticalSection(&m_CriticalSection); //OutputDebugString(_T("数据库连接串为空!\n")); //LOG4C_NO_FILENUM((LOG_NOTICE,"数据库连接串为空")); return FALSE; } } else { _stprintf_s(m_szConnectString,MAX_PATH,_T("%s"),lpSQLConnectString); } if (m_pdbInstance == NULL) { try { m_pdbInstance = new CDatabase; m_pdbInstance->OpenEx(m_szConnectString, CDatabase::noOdbcDialog); } catch (CDBException* e) { //m_strConnectErrorDescriptor = e->m_strError; LeaveCriticalSection(&m_CriticalSection); delete m_pdbInstance; m_pdbInstance = NULL; //OutputDebugString(e->m_strError); //LOG4C_NO_FILENUM((LOG_NOTICE,"打开数据库失败:%s",CW2A(e->m_strError))); #ifdef _DEBUG e->ReportError(); #endif e->Delete(); return FALSE; } m_bOpen = TRUE; } LeaveCriticalSection(&m_CriticalSection); return m_bOpen; } /************************************************************************/ /* 函数:CloseCatalog 描述:关闭数据库连接对象实例; 参数: 返回: 要求: 注意: */ /************************************************************************/ void CCatalogObj::CloseCatalog() { EnterCriticalSection(&m_CriticalSection); //if (!m_bOpen) return; m_bOpen = FALSE; if (m_pdbInstance) delete m_pdbInstance; m_pdbInstance = NULL; LeaveCriticalSection(&m_CriticalSection); } /************************************************************************/ /* 函数:Execute 描述:执行指定的SQL语句; 参数: IN: lpSQL 要执行SQL语句; 返回:成功查询返回TRUE,否则返回FALSE; 要求: 注意: */ /************************************************************************/ BOOL CCatalogObj::Execute(IN LPCTSTR lpSQL) { try { EnterCriticalSection(&m_CriticalSection); if (!m_bOpen) { LeaveCriticalSection(&m_CriticalSection); return FALSE; } //m_pdbInstance->BeginTrans(); m_pdbInstance->ExecuteSQL(lpSQL); //m_pdbInstance->CommitTrans(); LeaveCriticalSection(&m_CriticalSection); } catch (CDBException* e) { //m_pdbInstance->Rollback(); LeaveCriticalSection(&m_CriticalSection); SolveDBError(GetLastError(),e->m_strError); WriteTextLog(_T("%s,%s"),e->m_strError,lpSQL); #ifdef _DEBUG e->ReportError(); #endif e->Delete(); return FALSE; } return TRUE; } /************************************************************************/ /* 函数:GetSelectCount 描述:获取指定表的查询记录数; 参数: IN: lpTableName 要查询的表; IN: lpFilter 查询条件; 返回:成功查询返回记录条数,否则返回-1; 要求: 注意: */ /************************************************************************/ int CCatalogObj::GetSelectCount(IN LPCTSTR lpTableName, IN LPCTSTR lpFilter) { try { EnterCriticalSection(&m_CriticalSection); if (!m_bOpen) { LeaveCriticalSection(&m_CriticalSection); return -1; } CString strSQL; if (lpFilter && _tcsicmp(lpFilter, _T("")) != 0) strSQL.Format(_T("select count(*) as cot from %s where %s"), lpTableName, lpFilter); else strSQL.Format(_T("select count(*) as cot from %s"), lpTableName); CRecordset tagRecordset(m_pdbInstance); tagRecordset.Open(CRecordset::forwardOnly, strSQL); tagRecordset.GetFieldValue(_T("cot"), strSQL); tagRecordset.Close(); LeaveCriticalSection(&m_CriticalSection); return _ttoi(strSQL); } catch (CDBException* e) { LeaveCriticalSection(&m_CriticalSection); SolveDBError(GetLastError(),e->m_strError); //OutputDebugString(e->m_strError); WriteTextLog(e->m_strError); #ifdef _DEBUG e->ReportError(); #endif e->Delete(); return -1; } } /************************************************************************/ /* 函数:GetTableValues 描述:获取查询结果; 参数: IN: lpTableName 要查询的表; IN: lpFilter 查询条件; IN: AryOfFields 要查询的字段; OUT: AryOfValues 记录集结果返回; 返回:查询成功且记录数大于0返回TRUE; 要求: 注意: */ /************************************************************************/ BOOL CCatalogObj::GetTableValues(IN LPCTSTR lpTableName, IN LPCTSTR lpFilter, IN CStringArray &AryOfFields, OUT CArray &AryOfValues) { try { EnterCriticalSection(&m_CriticalSection); if ( !m_bOpen ) { //OutputDebugString(_T("数据库未打开\n")); //LOG4C_NO_FILENUM((LOG_NOTICE,"数据库未打开")); LeaveCriticalSection(&m_CriticalSection); return FALSE; } // 获取记录数; DWORD dwCount = 0; CString strSQL = _T(""); if (lpFilter && _tcsicmp(lpFilter, _T("")) != 0) strSQL.Format(_T("select count(*) as cot from %s where %s"), lpTableName, lpFilter); else strSQL.Format(_T("select count(*) as cot from %s"), lpTableName); CRecordset tagRet(m_pdbInstance); tagRet.Open(CRecordset::forwardOnly, strSQL); tagRet.GetFieldValue(_T("cot"), strSQL); tagRet.Close(); if( (dwCount = _ttol(strSQL)) == 0 ) { //OutputDebugString(_T("查询无记录\n")); //LOG4C_NO_FILENUM((LOG_NOTICE,"查询无记录")); LeaveCriticalSection(&m_CriticalSection); return TRUE; } // 查询; strSQL = _T("select "); for ( int i = 0; i < AryOfFields.GetSize(); i++) { strSQL += AryOfFields.ElementAt(i); strSQL += _T(","); } strSQL.TrimRight(_T(",")); strSQL += _T(" from "); strSQL += lpTableName; if (lpFilter && _tcsicmp(lpFilter, _T("")) != 0) { strSQL += _T(" where "); strSQL += lpFilter; } #if 1 // 关键字要去除[]后才能取值; for ( int i = 0; i < AryOfFields.GetSize(); i++) { AryOfFields.ElementAt(i).TrimLeft(_T('[')); AryOfFields.ElementAt(i).TrimRight(_T(']')); } #endif DWORD dwIndex = 0; AryOfValues.SetSize(dwCount); tagRet.Open(CRecordset::forwardOnly,strSQL); while(!tagRet.IsEOF()) { for ( int i = 0; i < AryOfFields.GetSize(); i++) { #if 0 CString str; CDBVariant dbv; tagRet.GetFieldValue(AryOfFields.ElementAt(i),dbv); switch(dbv.m_dwType) { case DBVT_NULL: AryOfValues.ElementAt(dwIndex).Add(""); break; case DBVT_BOOL: str.Format(_T("%d"),dbv.m_boolVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_UCHAR: str.Format(_T("%d"),dbv.m_chVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_SHORT: str.Format(_T("%d"),dbv.m_iVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_LONG: str.Format(_T("%ld"),dbv.m_lVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_SINGLE: str.Format(_T("%lf"),dbv.m_fltVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_DOUBLE: str.Format(_T("%lf"),dbv.m_dblVal); AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_DATE: break; case DBVT_STRING: break; case DBVT_BINARY: break; case DBVT_ASTRING: str = *dbv.m_pstringA; AryOfValues.ElementAt(dwIndex).Add(str); break; case DBVT_WSTRING: if ( AryOfFields.ElementAt(i) == _T("content")) { str = *dbv.m_pstringA; AryOfValues.ElementAt(dwIndex).Add(str); } else { str = CW2A(*dbv.m_pstringW); AryOfValues.ElementAt(dwIndex).Add(str); } break; default: break; } #else CString str = _T(""); CString strKey = AryOfFields.ElementAt(i); tagRet.GetFieldValue(strKey,str); OutputDebugString(str); OutputDebugString("\n"); AryOfValues.ElementAt(dwIndex).Add(str); #endif } dwIndex++; #if 1 // 防止查询过程中有新记录添加导致错误; if ( dwIndex >= dwCount ) break; #endif tagRet.MoveNext(); } tagRet.Close(); //AryOfValues.FreeExtra(); LeaveCriticalSection(&m_CriticalSection); } catch (CDBException *e) { LeaveCriticalSection(&m_CriticalSection); SolveDBError(GetLastError(),e->m_strError); //OutputDebugString(e->m_strError); //AfxMessageBox(e->m_strError); WriteTextLog(e->m_strError); #ifdef _DEBUG e->ReportError(); #endif e->Delete(); return FALSE; } return TRUE; }