BOOL COledbCommand::Execute(IDbRecordset* pRecordset /*= NULL*/) { _ASSERTE(m_spText); HRESULT Hr; //CComQIPtr<ICommandWithParameters> spParams = m_spRowset; //_ASSERTE(spParams); //if( spParams==NULL ) return FALSE; //spParams->SetParameterInfo(m_nParams, ...); m_nRowsAffected = 0; // Create accessor CComQIPtr<IAccessor> spAccessor = m_spText; if( spAccessor == NULL ) return FALSE; if( m_nParams > 0 ) { #ifdef _DEBUG DBBINDSTATUS stat[MAX_PARAMS] = { 0 }; Hr = spAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, m_nParams, m_rgBindings, m_dwBindOffset, &m_hAccessor, stat); #else Hr = spAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, m_nParams, m_rgBindings, m_dwBindOffset, &m_hAccessor, NULL); #endif if( FAILED(Hr) ) return _Error(Hr); } DBPARAMS Params; Params.pData = m_pData; Params.cParamSets = m_nParams > 0 ? 1 : 0; Params.hAccessor = m_hAccessor; Hr = m_spText->Execute(NULL, IID_IRowset, &Params, &m_nRowsAffected, (LPUNKNOWN*) &m_spRowset); if( FAILED(Hr) ) return _Error(Hr); // Did we want to see the result set? if( m_spRowset != NULL && pRecordset != NULL ) { COledbRecordset* pRec = static_cast<COledbRecordset*>(pRecordset); return pRec->Attach(m_spRowset); } return TRUE; }
BOOL COledbRecordset::_BindColumns() { _ASSERTE(m_rgBindings==NULL); if( !IsOpen() ) return FALSE; HRESULT Hr; m_nCols = 0; m_pwstrNameBuffer = NULL; CComQIPtr<IColumnsInfo> spColInfo = m_spRowset; if( spColInfo == NULL ) return FALSE; DBCOLUMNINFO* rgColumnInfo = NULL; ULONG nCols = 0; Hr = spColInfo->GetColumnInfo(&nCols, &rgColumnInfo, &m_pwstrNameBuffer); if( FAILED(Hr) ) return _Error(Hr); // Allocate memory for the bindings array; there is a one-to-one // mapping between the columns returned from GetColumnInfo() and our // bindings. long cbAlloc = nCols * sizeof(DBBINDING); m_rgBindings = (DBBINDING*) ::CoTaskMemAlloc(cbAlloc); if( m_rgBindings == NULL ) return FALSE; ::ZeroMemory(m_rgBindings, cbAlloc); m_iAdjustIndex = 0; // Construct the binding array element for each column. ULONG dwOffset = 0; for( ULONG iCol = 0; iCol < nCols; iCol++ ) { DBBINDING& b = m_rgBindings[iCol]; b.iOrdinal = rgColumnInfo[iCol].iOrdinal; b.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS; b.obStatus = dwOffset; b.obLength = dwOffset + sizeof(DBSTATUS); b.obValue = dwOffset + sizeof(DBSTATUS) + sizeof(ULONG); b.dwMemOwner = DBMEMOWNER_CLIENTOWNED; b.eParamIO = DBPARAMIO_NOTPARAM; b.bPrecision = rgColumnInfo[iCol].bPrecision; b.bScale = rgColumnInfo[iCol].bScale; // Ignore bookmark column if( (rgColumnInfo[iCol].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK) != 0 ) m_iAdjustIndex++; WORD wType = rgColumnInfo[iCol].wType; switch( wType ) { case DBTYPE_CY: case DBTYPE_DECIMAL: case DBTYPE_NUMERIC: b.wType = DBTYPE_STR; b.cbMaxLen = 50; // Allow 50 characters for conversion break; case DBTYPE_STR: case DBTYPE_WSTR: #ifdef _UNICODE b.wType = DBTYPE_WSTR; #else b.wType = DBTYPE_STR; #endif b.cbMaxLen = max(min((rgColumnInfo[iCol].ulColumnSize + 1UL) * sizeof(TCHAR), 1024UL), 0UL); break; default: b.wType = wType; b.cbMaxLen = max(min(rgColumnInfo[iCol].ulColumnSize, 1024UL), 0UL); } // ROUNDUP on all platforms pointers must be aligned properly #define ROUNDUP_AMOUNT 8 #define ROUNDUP_(size,amount) (((ULONG)(size)+((amount)-1))&~((amount)-1)) #define ROUNDUP(size) ROUNDUP_(size, ROUNDUP_AMOUNT) // Update the offset past the end of this column's data dwOffset = b.cbMaxLen + b.obValue; dwOffset = ROUNDUP(dwOffset); } m_nCols = (short) nCols; m_dwBufferSize = dwOffset; ::CoTaskMemFree(rgColumnInfo); // Create accessor CComQIPtr<IAccessor> spAccessor = m_spRowset; if( spAccessor == NULL ) return FALSE; Hr = spAccessor->CreateAccessor(DBACCESSOR_ROWDATA, m_nCols, m_rgBindings, 0, &m_hAccessor, NULL); if( FAILED(Hr) ) return _Error(Hr); m_pData = ::CoTaskMemAlloc(m_dwBufferSize); if( m_pData == NULL ) return FALSE; return TRUE; }