📄 datalink.cpp
字号:
#include "stdafx.h"
#include "DataLink.h"
#include <atlbase.h>
// ado supproted
#pragma warning(disable:4146)
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace \
rename("EOF","IsEOF")
#pragma warning(default:4146)
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#ifndef _WIN64
#define DWORD_PTR DWORD
#endif
/////////////////////////////////////////////////////////////////////////////
// datalink state
void _SetErrorInfo(ErrorsPtr pErrors)
{
if (pErrors->Count <= 0)
return;
CComPtr<ICreateErrorInfo> spErrorInfo;
if (FAILED(CreateErrorInfo(&spErrorInfo)))
return;
ErrorPtr pError = pErrors->Item[COleVariant(0L)];
spErrorInfo->SetDescription(pError->Description);
spErrorInfo->SetSource(pError->Source);
spErrorInfo->SetHelpContext(pError->HelpContext);
spErrorInfo->SetHelpFile(pError->HelpFile);
_AFX_DATALINK_STATE* pState = _afxDataLinkState.GetData();
if (pState->m_pErrorInfo != NULL)
pState->m_pErrorInfo->Release();
spErrorInfo->QueryInterface(__uuidof(IErrorInfo), (void**)&pState->m_pErrorInfo);
::SetErrorInfo(0, pState->m_pErrorInfo);
}
BOOL AFXAPI AfxGetErrorMessage(CString& rString)
{
DWORD dwError = ::GetLastError();
if (dwError != 0)
{
return TRUE;
}
CComPtr<IErrorInfo> pErrorInfo;
::GetErrorInfo(0, &pErrorInfo);
if (pErrorInfo == NULL)
{
// 使用 Common 错误信息
_AFX_DATALINK_STATE* pState = _afxDataLinkState.GetData();
pErrorInfo = pState->m_pErrorInfo;
}
if (pErrorInfo != NULL)
{
CComBSTR description;
pErrorInfo->GetDescription(&description);
//rString.SetString(CString(description));
memcpy(rString.GetBufferSetLength(description.Length()), CString(description), description.Length() * sizeof(TCHAR));
rString.ReleaseBuffer();
return TRUE;
}
return FALSE;
}
void AFXAPI AfxSetErrorMessage(LPCTSTR lpString)
{
CComPtr<ICreateErrorInfo> spErrorInfo;
if (FAILED(CreateErrorInfo(&spErrorInfo)))
return;
CComBSTR description(lpString);
spErrorInfo->SetDescription(description);
spErrorInfo->SetSource(description);
spErrorInfo->SetHelpContext(0L);
spErrorInfo->SetHelpFile(NULL);
_AFX_DATALINK_STATE* pState = _afxDataLinkState.GetData();
if (pState->m_pErrorInfo != NULL)
pState->m_pErrorInfo->Release();
spErrorInfo->QueryInterface(__uuidof(IErrorInfo), (void**)&pState->m_pErrorInfo);
::SetErrorInfo(0, pState->m_pErrorInfo);
}
/////////////////////////////////////////////////////////////////////////////
// datalink state
_AFX_DATALINK_STATE::_AFX_DATALINK_STATE()
{
m_pszConnectionString = NULL;
m_pErrorInfo = NULL;
}
_AFX_DATALINK_STATE::~_AFX_DATALINK_STATE()
{
free((void*)m_pszConnectionString);
if (m_pErrorInfo != NULL)
m_pErrorInfo->Release();
}
PROCESS_LOCAL(_AFX_DATALINK_STATE, _afxDataLinkState)
/////////////////////////////////////////////////////////////////////////////
// datalink globals and implementation helpers
void AFXAPI AfxDataLinkTerm()
{
}
void AFXAPI AfxSetDataLink(LPCTSTR lpszConnectionString)
{
ASSERT(lpszConnectionString != NULL);
_AFX_DATALINK_STATE* pState = _afxDataLinkState.GetData();
BOOL bEnable = AfxEnableMemoryTracking(FALSE);
free((void*)pState->m_pszConnectionString);
pState->m_pszConnectionString = _tcsdup(lpszConnectionString);
AfxEnableMemoryTracking(bEnable);
}
void AFXAPI AfxGetDataLink(CString& strConnectionString)
{
_AFX_DATALINK_STATE* pState = _afxDataLinkState.GetData();
//strConnectionString.SetString(pState->m_pszConnectionString);
int nLen = lstrlen(pState->m_pszConnectionString);
memcpy(strConnectionString.GetBufferSetLength(nLen), pState->m_pszConnectionString, nLen * sizeof(TCHAR));
strConnectionString.ReleaseBuffer();
}
//////////////////////////////////////////////////////////////////////////////
// Helpers
void AFXAPI _AfxSetCurrentRecord(long* plCurrentRecord, long nRows, RETCODE nRetCode)
{
if (*plCurrentRecord != AFX_CURRENT_RECORD_UNDEFINED &&
nRetCode != SQL_NO_DATA_FOUND)
*plCurrentRecord += nRows;
}
void AFXAPI _AfxSetRecordCount(long* plRecordCount, long lCurrentRecord,
BOOL bEOFSeen, RETCODE nRetCode)
{
// If not at the end and haven't yet been to the end, incr count
if (nRetCode != SQL_NO_DATA_FOUND && !bEOFSeen &&
lCurrentRecord != AFX_CURRENT_RECORD_UNDEFINED)
{
// lCurrentRecord 0-based and it's already been set
*plRecordCount =
__max(*plRecordCount, lCurrentRecord + 1);
}
}
/////////////////////////////////////////////////////////////////////////////
// tchar globals helpers
// 去除前置空格
LPCTSTR _tltrim(LPCTSTR string)
{
while (_istspace(*string))
string++;
return string;
}
// 去除右置空格
void _trtrim(LPTSTR string)
{
string += lstrlen(string);
while (_istspace(*(--string)))
*string = '\0';
}
// 返回指向第一个出现分割符的字符串,忽略成对出现的分隔符
LPCTSTR _tcschr2(LPCTSTR string, LPTSTR item, TCHAR chSep)
{
LPCTSTR lpchEnd = _tcschr(string, chSep);
if (item != NULL) *item = '\0';
while (lpchEnd != NULL && *(lpchEnd+1) == chSep)
{
// 如果分割符成对出现,忽略第二个分割符
if (item != NULL)
_tcsncat(item, string, (int)(lpchEnd - string) + 1);
string = lpchEnd + 2;
lpchEnd = _tcschr(string, chSep);
}
if (item != NULL)
_tcsncat(item, string, (lpchEnd == NULL) ? lstrlen(string) : (int)(lpchEnd - string));
return lpchEnd;
}
LPCTSTR _tsplitattr(LPCTSTR string, LPTSTR keyName, LPTSTR value, TCHAR chSep = _T(';'))
{
TCHAR chOldSep = chSep;
chSep = _T('=');
string = _tcschr2(_tltrim(string), keyName, chSep);
if (keyName != NULL) _trtrim(keyName);
if (string == NULL)
return NULL;
string = _tltrim(++string);
chSep = _tcschr(_T("\'\""), *string) ? *(string++) : chOldSep;
string = _tcschr2(string, value, chSep);
if (string != NULL && chSep != chOldSep)
string = _tcschr2(++string, NULL, chOldSep);
if (value != NULL) _trtrim(value);
return (string == NULL) ? NULL : ++string;
}
// 拷贝字符串,如果字符串包含分隔符,分隔符成对出现
LPTSTR _tcscpy2(LPTSTR string, LPCTSTR source, TCHAR chSep)
{
*string = '\0';
if (source == NULL)
return string;
LPCTSTR lpchEnd = _tcschr(source, chSep);
while (lpchEnd != NULL && *lpchEnd == chSep)
{
// 如果字符串包含分隔符,分隔符成对出现
_tcsncat(string, source, (int)(lpchEnd - source) + 1);
_tcsncat(string, lpchEnd, 1);
source = lpchEnd + 1;
lpchEnd = _tcschr(source, chSep);
}
int nLen = (lpchEnd == NULL) ? lstrlen(source) : (int)(lpchEnd - source);
return _tcsncat(string, source, nLen);
}
// 返回指向下一个字符串的指针,跳过由分隔符 ''()[]限定的字符串
const TCHAR* _strinc2(const TCHAR* string)
{
ASSERT(string != NULL);
DWORD dwReserve = 0; // 保留右分隔符的列表,最多4个嵌套
for (BOOL bSeek = FALSE; *string != 0; string++, bSeek = TRUE)
{
if (*string == LOBYTE(dwReserve))
dwReserve = dwReserve >> 8;
else if (*string == _T('\''))
dwReserve = (DWORD_PTR)(_T('\'')) & 0xff | dwReserve << 8;
else if (*string == _T('('))
dwReserve = (DWORD_PTR)(_T(')')) & 0xff | dwReserve << 8;
else if (*string == _T('['))
dwReserve = (DWORD_PTR)(_T(']')) & 0xff | dwReserve << 8;
else if (dwReserve == 0 && bSeek)
break;
}
return string;
}
// 返回指向第一个出现分割符的字符串的索引,跳过由分隔符 ''()[]限定的字符串
const TCHAR* _tcschr2(const TCHAR* string, const TCHAR chSep)
{
while (*string != 0)
{
if (chSep == *string)
return string;
string = _strinc2(string);
}
return NULL;
}
// 返回指向第一个出现分割符的字符串的索引,跳过由分隔符 ''()[]限定的字符串
size_t _tcscspn2(const TCHAR* string, const TCHAR* strCharSet)
{
LPCTSTR lpchEnd = string;
while (*lpchEnd != 0)
{
if (_tcschr(strCharSet, *lpchEnd) != NULL)
break;
lpchEnd = _strinc2(lpchEnd);
}
return size_t(lpchEnd - string);
}
int _istspace2(TCHAR c)
{
return (_istspace(c) || c == _T('\n') || c == _T('\t')) ? 1 : 0;
}
int _tcsnicmp2(const TCHAR *string1, const TCHAR *string2, size_t count)
{
size_t count2 = lstrlen(string2);
if (count2 != count)
return (int)(count - count2);
return _tcsnicmp(string1, string2, count);
}
// 返回指向第一个出现关键字的字符串之后的索引,跳过由分隔符 ''()[]限定的字符串
// 如果没有找到关键字,返回字符串的长度
size_t _tcskey1(const TCHAR* string, const TCHAR* strSearch)
{
ASSERT(strSearch != NULL);
int nLen;
BOOL bResult;
LPCTSTR lpchEnd = string;
while (*lpchEnd != 0)
{
nLen = (int)_tcscspn2(lpchEnd, _T(" \t\n"));
bResult = (_tcsnicmp2(lpchEnd, strSearch, nLen) == 0);
lpchEnd += nLen;
if (*lpchEnd != 0)
lpchEnd++; // point past the space
if (bResult)
break;
}
return (lpchEnd - string);
}
// 返回指向第一个出现关键字的字符串之前的索引,跳过由分隔符 ''()[]限定的字符串
// 如果没有找到关键字,返回字符串的长度
size_t _tcskey2(const TCHAR* string, const TCHAR* strSearch)
{
ASSERT(strSearch != NULL);
int nLen;
LPCTSTR lpchEnd = string;
while (*lpchEnd != 0)
{
nLen = (int)_tcscspn2(lpchEnd, _T(" \t\n"));
if (_tcsnicmp2(lpchEnd, strSearch, nLen) == 0)
break;
lpchEnd += nLen;
if (*lpchEnd != 0)
lpchEnd++; // point past the space
}
if (*lpchEnd != 0 && (lpchEnd - string) > 0)
lpchEnd--; // point to the space
return (lpchEnd - string);
}
// 返回指向第一个出现"join"的字符串之前的索引,跳过由分隔符 ''()[]限定的字符串
// 如果没有找到关键字,返回字符串的长度
size_t _tcskey3(const TCHAR* string, const TCHAR* strSearch)
{
int nLen;
LPCTSTR lpchEnd = string;
while (*lpchEnd != 0)
{
nLen = (int)_tcscspn2(lpchEnd, _T(" \t\n"));
if (_tcsnicmp2(lpchEnd, _T("inner"), nLen) == 0 ||
_tcsnicmp2(lpchEnd, _T("left"), nLen) == 0 ||
_tcsnicmp2(lpchEnd, _T("right"), nLen) == 0 ||
_tcsnicmp2(lpchEnd, _T("full"), nLen) == 0 ||
_tcsnicmp2(lpchEnd, strSearch, nLen) == 0)
break;
lpchEnd += nLen;
if (*lpchEnd != 0)
lpchEnd++; // point past the space
}
if (*lpchEnd != 0 && (lpchEnd - string) > 0)
lpchEnd--; // point to the space
return (lpchEnd - string);
}
/////////////////////////////////////////////////////////////////////////////
// sql string globals helpers
// 将SQL语句格式化为标准格式
// 列别名使用AS;表别名使用空格
void SqlString_Normalize(CString& rString)
{
int nNewLength = rString.GetLength();
LPCTSTR pszBuffer = rString.GetBuffer(nNewLength);
while (*pszBuffer != 0)
{
// 如果当前是空格,下一个字符是分隔符,删除当前字符
if (_istspace2(*pszBuffer) && *(pszBuffer+1) != _T('[') &&
(_istpunct(*(pszBuffer+1)) || _istspace2(*(pszBuffer+1))))
{
memmove((void*)pszBuffer, pszBuffer+1,
(lstrlen(pszBuffer))*sizeof(TCHAR));
nNewLength--;
continue;
}
// 如果当前是分隔符,下一个是空格,删除下一个字符
if (_istpunct(*pszBuffer) && _istspace2(*(pszBuffer+1)))
{
memmove((void*)(pszBuffer+1), pszBuffer+2,
(lstrlen(pszBuffer)-1)*sizeof(TCHAR));
nNewLength--;
continue;
}
pszBuffer = _strinc2(pszBuffer);
}
rString.ReleaseBuffer();
}
void SqlString_Insert(CString& rString, int &nIndex, LPCTSTR lpszKey)
{
if (nIndex > 0 && !_istspace2(rString[nIndex-1]))
rString.Insert(nIndex++, _T(' '));
rString.Insert(nIndex, lpszKey);
nIndex += lstrlen(lpszKey);
if (rString[nIndex] != 0 && !_istspace2(rString[nIndex]))
rString.Insert(nIndex++, _T(' '));
}
// 删除指定长度的字符并在指定的起始点插入另一组字符。
int SqlString_Stuff(CString& rString, int nIndex, int nCount, LPCTSTR psz)
{
if(nIndex < 0)
nIndex = 0;
int nLength = rString.GetLength();
if (nIndex > nLength)
nIndex = nLength;
if ((nIndex + nCount) > nLength)
nCount = nLength - nIndex;
if(nCount < 0)
nCount = 0;
int nNewLength = nLength;
int nInsertLength = (psz != NULL) ? int(strlen(psz)) : 0;
if (nCount > 0 || nInsertLength > 0)
{
nNewLength += nInsertLength - nCount;
LPTSTR pszBuffer = rString.GetBuffer(nNewLength);
// move existing bytes down
memmove(pszBuffer+nIndex+nInsertLength, pszBuffer+nIndex+nCount,
(nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
memcpy(pszBuffer+nIndex, psz, nInsertLength*sizeof(TCHAR));
rString.ReleaseBuffer();
}
return(nNewLength);
}
BOOL SqlString_Alias(CString& rAlias)
{
int nIndex = (int)_tcscspn2(rAlias, _T(" ,()"));
if (nIndex < rAlias.GetLength())
{
rAlias.Insert(0, _T('['));
rAlias.Insert(rAlias.GetLength(), _T(']'));
return TRUE;
}
return FALSE;
}
BOOL SqlString_SelectList(LPCTSTR lpszFullString, int& nIndex, int& nCount)
{
nIndex = (int)_tcskey1(lpszFullString, _T("select"));
lpszFullString += nIndex;
if (*lpszFullString == 0)
{
nCount = 0;
return FALSE;
}
nCount = (int)_tcskey2(lpszFullString, _T("from"));
return TRUE;
}
int SqlString_ColumnCount(LPCTSTR lpszSelectList)
{
for (int nCount=0; lpszSelectList != NULL; nCount++)
{
lpszSelectList = _tcschr2(lpszSelectList, _T(','));
if (lpszSelectList != NULL)
lpszSelectList++;
}
return nCount;
}
BOOL SqlString_ColumnItem(LPCTSTR lpszSelectList, int nIndex, int& nStart,
int& nCount)
{
LPCTSTR lpchStart = lpszSelectList;
while (nIndex--)
{
lpchStart = _tcschr2(lpchStart, _T(','));
if (lpchStart == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -