📄 dbcommand.cpp_1
字号:
// File: dbcommand.cpp_1
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Classes Reference and related electronic
// documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft C++ Libraries products.
#include "StdAfx.h"
#include "dbcommand.h"
DBCommand::DBCommand(IResultsBuilder *builder)
{
m_pResultBuilder = builder;
m_arrParams = NULL;
}
DBCommand::~DBCommand(void)
{
Clean();
m_pResultBuilder = NULL;
}
void DBCommand::Clean()
{
if (m_arrParams)
delete[] m_arrParams;
m_arrParams = NULL;
}
HRESULT DBCommand::GetCmdInfo( CStringA& cmdName,
CStringA& connectionString,
IMemoryCache *spBinaryCache,
const CSession &session,
CmdInfo **cmdInfo,
bool& infoFromCache)
{
HRESULT hr = S_OK;
CProcedureParameters procInfo;
if (spBinaryCache == NULL)
{
hr = CreateAndStoreCmdInfo( procInfo,
session,
spBinaryCache,
cmdName,
connectionString,
cmdInfo,
infoFromCache);
ASSERT(!FAILED(hr));
if (FAILED(hr))
{
// if we can't get cmd information, nothing to do but return
return hr;
}
}
else
{
// we do have a cache, see if our cmd info is in it
HANDLE hEntry;
if (SUCCEEDED(spBinaryCache->LookupEntry(cmdName + connectionString, &hEntry)))
{
DWORD dwSize = 0;
hr = spBinaryCache->GetData(hEntry, (void**)*cmdInfo, &dwSize);
if (FAILED(hr))
{
// if we couldn't get the command info from the cache, create it
// ourselves
hr = CreateAndStoreCmdInfo( procInfo,
session,
spBinaryCache,
cmdName,
connectionString,
cmdInfo,
infoFromCache);
ASSERT(!FAILED(hr));
if (FAILED(hr))
{
// if we can't get cmd information, nothing to do but return
return hr;
}
}
else
{
// getting here means we got our cmd information from the
// cache successfully, all we have to do is set the flag
// so nobody deletes this value
infoFromCache = true;
// close our handle
CloseHandle(hEntry);
}
}
else
{
// if there was nothing in the cache, we'll have to create things on our own
hr = CreateAndStoreCmdInfo( procInfo,
session,
spBinaryCache,
cmdName,
connectionString,
cmdInfo,
infoFromCache);
ASSERT(!FAILED(hr));
if (FAILED(hr))
{
// if we can't get cmd information, nothing to do but return
return hr;
}
}
}
return hr;
}
void DBCommand::IterateRowset(CommandType& command,
ULONG ulColumns,
struct MYBIND* pBind)
{
long rowsAffected = 0;
// get the rowset items
while (command.MoveNext() == S_OK)
{
for (ULONG j = 1; j <= ulColumns; j++)
{
if (pBind[j-1].dwStatus == DBSTATUS_S_ISNULL)
_tcscpy(pBind[j-1].szValue, _T(""));
m_pResultBuilder->AddColumnValue(CStringA(pBind[j-1].szValue));
}
m_pResultBuilder->DoneRow();
}
}
HRESULT DBCommand::GetResults(CommandType& command, int numParams)
{
HRESULT hr = S_OK;
LONG lRows = 0;
// Get the column information and bind the output columns.
ULONG ulColumns = NULL;
DBCOLUMNINFO* pColumnInfo = NULL;
OLECHAR* pColumnNames = NULL;
OLECHAR** ppNames;
struct MYBIND* pColumns = NULL;
// this loop will handle stored procs that handle multiple result sets
do
{
if (command.m_spRowset != NULL)
{
ulColumns = NULL;
pColumnInfo = NULL;
pColumnNames = NULL;
pColumns = NULL;
hr = command.GetColumnInfo(&ulColumns, &pColumnInfo, &pColumnNames);
if (FAILED(hr))
return hr;
if (ulColumns > 0)
{
ppNames = new OLECHAR*[ulColumns];
pColumns = new MYBIND[ulColumns];
command.CreateAccessor(ulColumns, &pColumns[0], sizeof(MYBIND)*ulColumns);
for (ULONG l = 0; l < ulColumns; l++)
{
ppNames[l] = pColumnNames;
if (*pColumnNames)
{
while(*pColumnNames++);
}
command.AddBindEntry(l+1,
DBTYPE_STR,
sizeof(TCHAR)*MAX_SIZE,
&pColumns[l].szValue,
NULL,
&pColumns[l].dwStatus);
}
}
// bind our command to get column, output parameter and return values
command.Bind();
// iterate over our results
IterateRowset(command, ulColumns, pColumns);
// we are finished with 1 result set, move on to the others
Trace::TraceMsg("DBCommand done result set");
m_pResultBuilder->DoneResultSet();
// clean up
CoTaskMemFree(pColumnInfo);
CoTaskMemFree(pColumnNames);
CoTaskMemFree(*ppNames);
if (ppNames)
{
delete[] ppNames;
ppNames = NULL;
}
if (pColumns)
{
delete[] pColumns;
pColumns = NULL;
}
}
lRows = 0;
}while (command.GetNextResult(&lRows, false) == S_OK);
// TODO HACK, m_arrParams[i].dwStatus is not being set properly, workaround it
// for now
for (int i = 0; i < numParams; i++)
{
if (i == 0)
{
m_pResultBuilder->SetReturnValue(CStringA(m_arrParams[i].szValue));
}
else if (m_arrParams[i].dwStatus == DBPARAMTYPE_RETURNVALUE)
{
m_pResultBuilder->AddOutputParamValue(CStringA(m_arrParams[i].szValue));
}
}
return hr;
}
HRESULT DBCommand::ExecuteCommand( const CSession& session,
CmdInfo *cmdInfo,
StringList& inputParams)
{
ASSERT(cmdInfo != NULL);
if (cmdInfo == NULL)
{
return E_FAIL;
}
USES_CONVERSION;
HRESULT hr = S_OK;
CommandType command;
// create the command using our call string
hr = command.Create(session, cmdInfo->cmdCallString);
// only going to call this once
hr = command.Prepare(1);
// if this stored proc takes parameters pass them in
int numParams = cmdInfo->paramTypes.GetCount();
if (numParams > 0)
{
DBPARAMBINDINFO* bindInfo = new DBPARAMBINDINFO[numParams];
ULONG* ordinals = new ULONG[numParams];
m_arrParams = new MYBIND[numParams];
// make the bindings for the accessor based on the DBTYPE_STR data type
command.CreateParameterAccessor(numParams, &m_arrParams[0], sizeof(MYBIND)*numParams);
for (int l = 0; l < numParams; l++)
{
// Set up information for the SetParameterInfo call
ordinals[l] = l+1;
bindInfo[l].pwszDataSourceType = T2OLE(_T("DBTYPE_CHAR"));
bindInfo[l].pwszName = NULL;
bindInfo[l].ulParamSize = MAX_SIZE;
bindInfo[l].bPrecision = 0;
bindInfo[l].bScale = 0;
DWORD dwFlags = 0;
if (cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUT ||
cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUTOUTPUT)
dwFlags |= DBPARAMFLAGS_ISINPUT;
if (cmdInfo->paramTypes[l] == DBPARAMTYPE_OUTPUT ||
cmdInfo->paramTypes[l] == DBPARAMTYPE_INPUTOUTPUT ||
cmdInfo->paramTypes[l] == DBPARAMTYPE_RETURNVALUE)
dwFlags |= DBPARAMFLAGS_ISOUTPUT;
bindInfo[l].dwFlags = dwFlags;
// Set up information for bindings
if (cmdInfo->paramTypes[l] == DBPARAMTYPE_RETURNVALUE)
{
command.AddParameterEntry( 1,
DBTYPE_STR,
sizeof(TCHAR)*MAX_SIZE,
&m_arrParams[l].szValue,
NULL,
&m_arrParams[l].dwStatus,
DBPARAMIO_OUTPUT);
}
else
{
command.AddParameterEntry( l+1,
DBTYPE_STR,
sizeof(TCHAR)*MAX_SIZE,
&m_arrParams[l].szValue,
NULL,
&m_arrParams[l].dwStatus,
cmdInfo->paramTypes[l]);
}
}
// call ICommandWithParameters::SetParameterInfo so that we can
// tell the provider to convert the parameter types to DBTYPE_STR
command.SetParameterInfo(numParams, ordinals, bindInfo);
// cleanup
delete[] ordinals;
delete[] bindInfo;
}
// put in our input parameters
if (inputParams.GetCount() > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -