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

📄 rowset.cpp

📁 oledb的例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

/////////////////////////////////////////////////////////////////
// myDisplayColumnNames
//
// This function takes an IUnknown pointer to a rowset object
// and displays the names of the columns of that rowset
//
/////////////////////////////////////////////////////////////////

HRESULT myDisplayColumnNames(	IUnknown *       pUnkRowset,
															ULONG *          rgDispSize
															)
{
	HRESULT          hr;
	IColumnsInfo *   pIColumnsInfo    = NULL;
	ULONG            cColumns;
	DBCOLUMNINFO *   rgColumnInfo     = NULL;
	LPOLESTR         pStringsBuffer   = NULL;
	WCHAR            wszColumn[MAX_DISPLAY_SIZE + 1];
	LPWSTR           pwszColName;
	ULONG            iCol;
	ULONG            cSpaces;
	ULONG            iSpace;

	// Get the IColumnsInfo interface for the rowset
	XCHECK_HR(hr = pUnkRowset->QueryInterface(IID_IColumnsInfo, (void**)&pIColumnsInfo));
	// Get the columns information
	XCHECK_HR(hr = pIColumnsInfo->GetColumnInfo(
									&cColumns,                            // pcColumns
									&rgColumnInfo,                        // prgColumnInfo
									&pStringsBuffer                       // ppStringBuffer
									));

	// Display the title of the row index column
	wprintf(L" Row | ");
	// Display all column names
	for( iCol = 0; iCol < cColumns; iCol++ )
	{
		pwszColName = rgColumnInfo[iCol].pwszName;
		// If the column name is NULL, we'll use a default string
		if( !pwszColName )
		{
			// Is this the bookmark column?
			if( !rgColumnInfo[iCol].iOrdinal )
				pwszColName = L"Bmk";
			else
				pwszColName = L"(null)";
		}

		// Ensure that the name is no longer than MAX_DISPLAY_SIZE
		wcsncpy(wszColumn, pwszColName, MAX_DISPLAY_SIZE);
		wszColumn[min(rgDispSize[iCol], MAX_DISPLAY_SIZE)] = L'\0';
		// Figure out how many spaces we need to print after
		// this column name
		cSpaces = min(rgDispSize[iCol], MAX_DISPLAY_SIZE) - wcslen(wszColumn);
		// Print the column name
		wprintf(L"%s", wszColumn);
		// Now print any spaces necessary to align this column
		for(iSpace = 0; iSpace < cSpaces; iSpace++ )
			putch(' ');
		// Now end the column with a separator marker if necessary
		if( iCol < cColumns - 1 )
			wprintf(L" | ");
	}

	// Done with the header, so print a newline
	wprintf(L"\n");
CLEANUP:
	CoTaskMemFree(rgColumnInfo);
	CoTaskMemFree(pStringsBuffer);
	if( pIColumnsInfo )
		pIColumnsInfo->Release();
	return hr;
}

/////////////////////////////////////////////////////////////////
// myDisplayRow
//
// This function displays the data for a row
//
/////////////////////////////////////////////////////////////////

HRESULT myDisplayRow(
											ULONG                 iRow, 
											ULONG                 cBindings, 
											DBBINDING *           rgBindings, 
											void *                pData, 
											ULONG *               rgDispSize
											)

{
	HRESULT               hr = S_OK;
	WCHAR                 wszColumn[MAX_DISPLAY_SIZE + 1];
	DBSTATUS              dwStatus;
	ULONG                 ulLength;
	void *                pvValue;
	ULONG                 iCol;
	ULONG                 cbRead;
	ISequentialStream *   pISeqStream = NULL;
	ULONG                 cSpaces;
	ULONG                 iSpace;

	// Display the row number
	wprintf(L" [%d] | ", iRow);
	// For each column that we have bound, display the data
	for( iCol = 0; iCol < cBindings; iCol++ )
	{
		// We have bound status, length, and the data value for all
		// columns, so we know that these can all be used
		dwStatus   = *(DBSTATUS *)((BYTE *)pData + rgBindings[iCol].obStatus);
		ulLength   = *(ULONG *)((BYTE *)pData + rgBindings[iCol].obLength);
		pvValue    = (BYTE *)pData + rgBindings[iCol].obValue;

		// Check the status of this column. This decides
		// exactly what will be displayed for the column.
		switch( dwStatus )
		{
			// The data is NULL, so don't try to display it
			case DBSTATUS_S_ISNULL:
			wcscpy(wszColumn, L"(null)");
			break;
			// The data was fetched, but may have been truncated.
			// Display string data for this column to the user.
			case DBSTATUS_S_TRUNCATED:
			case DBSTATUS_S_OK:
			case DBSTATUS_S_DEFAULT:
			{
				// We have bound the column either as a Unicode string
				// (DBTYPE_WSTR) or as an ISequentialStream object
				// (DBTYPE_IUNKNOWN), and we have to do different processing
				// for each one of these possibilities
				switch( rgBindings[iCol].wType )
				{
					case DBTYPE_WSTR:
					{
						// Copy the string data
						wcsncpy(wszColumn, (WCHAR *)pvValue, MAX_DISPLAY_SIZE);
						wszColumn[MAX_DISPLAY_SIZE - 1] = L'\0';
						break;
					}
					case DBTYPE_IUNKNOWN:
					{
						// We've bound this as an ISequentialStream object,
						// therefore the data in our buffer is a pointer
						// to the object's ISequentialStream interface
						pISeqStream = *(ISequentialStream**)pvValue;
						// We call ISequentialStream::Read to read bytes from
						// the stream blindly into our buffer, simply as a
						// demonstration of ISequentialStream. To display the
						// data properly, the native provider type of this
						// column should be accounted for; it could be
						// DBTYPE_WSTR, in which case this works, or it could
						// be DBTYPE_STR or DBTYPE_BYTES, in which case this
						// won't display the data correctly.
						CHECK_HR(hr = pISeqStream->Read(
														wszColumn,                     // pBuffer
														MAX_DISPLAY_SIZE,              // cBytes
														&cbRead                        // pcBytesRead
														));

						// Since streams don't provide NULL-termination,
						// we'll NULL-terminate the resulting string ourselves
						wszColumn[cbRead / sizeof(WCHAR)] = L'\0';
						// Release the stream object, now that we're done
						pISeqStream->Release();
						pISeqStream = NULL;
						break;
					}
				}
				break;
			}

			// This is an error status, so don't try to display the data
			default:
				wcscpy(wszColumn, L"(error status)");
				break;
		}

		// Determine how many spaces we need to add after displaying this
		// data to align it with this column in other rows
		cSpaces = min(rgDispSize[iCol], MAX_DISPLAY_SIZE) - wcslen(wszColumn);
		// Print the column data
		wprintf(L"%s", wszColumn);
		// Now print any spaces necessary
		for(iSpace = 0; iSpace < cSpaces; iSpace++ )
			putch(' ');
		// Now end the column with a separator marker if necessary
		if( iCol < cBindings - 1 )
			wprintf(L" | ");
	}

CLEANUP:
	if( pISeqStream )
		pISeqStream->Release();
	// Print the row separator
	wprintf(L"\n");
	return hr;
}

/////////////////////////////////////////////////////////////////
// myFreeBindings
//
//This function frees a bindings array and any allocated
// structures contained in that array
//
/////////////////////////////////////////////////////////////////
void myFreeBindings(
										ULONG         cBindings, 
										DBBINDING *   rgBindings
										)

{
	ULONG         iBind;
	// Free any memory used by DBOBJECT structures in the array
	for( iBind = 0; iBind < cBindings; iBind++ )
		CoTaskMemFree(rgBindings[iBind].pObject);
	// Now free the bindings array itself
	CoTaskMemFree(rgBindings);
}

/////////////////////////////////////////////////////////////////
// myAddRowsetProperties
//
// This function sets up the given DBPROPSET and DBPROP
// structures, adding two optional properties that describe
// features that we would like to use on the rowset created
// with these properties applied:
// - DBPROP_CANFETCHBACKWARDS -- the rowset should support
//   fetching rows backwards from our current cursor position.
// - DBPROP_IRowsetLocate -- the rowset should support
//   the IRowsetLocate interface and its semantics.
//
/////////////////////////////////////////////////////////////////

void myAddRowsetProperties(DBPROPSET* pPropSet, ULONG cProperties, DBPROP* rgProperties)
{
	// Initialize the property set array
	pPropSet->rgProperties      = rgProperties;
	pPropSet->cProperties       = cProperties;
	pPropSet->guidPropertySet   = DBPROPSET_ROWSET;
	// Add the following two properties (as OPTIONAL) to the property
	// array contained in the property set array in order to request
	// that they be supported by the rowset we will create. Because
	// these are optional, the rowset we obtain may or may not support
	// this functionality. We will check for the functionality that
	// we need once the rowset is created and will modify our behavior
	// appropriately.
	myAddProperty(&rgProperties[0], DBPROP_CANFETCHBACKWARDS);
	myAddProperty(&rgProperties[1], DBPROP_IRowsetLocate);
}

/////////////////////////////////////////////////////////////////
// myUpdateDisplaySize
//
// This function updates the rgDispSize array, keeping the
// maximum of the display size needed for the given data and
// the previous maximum size already in the array
//
/////////////////////////////////////////////////////////////////
HRESULT myUpdateDisplaySize(
														ULONG         cBindings, 
														DBBINDING *   rgBindings, 
														void *        pData, 
														ULONG *       rgDispSize
														)

{
	DBSTATUS      dwStatus;
	ULONG         cchLength;
	ULONG         iCol;
	// Loop through the bindings, comparing the size of each column
	// against the previously found maximum size for that column
	for( iCol = 0; iCol < cBindings; iCol++ )
	{
		dwStatus = *(DBSTATUS *)((BYTE *)pData + rgBindings[iCol].obStatus);
		cchLength = ((*(ULONG *)((BYTE *)pData + rgBindings[iCol].obLength)) / sizeof(WCHAR));

		// The length that we need to display depends on the status
		// of this column and generally on the data in the column
		switch( dwStatus )
		{
			case DBSTATUS_S_ISNULL:
				cchLength = 6;                              // "(null)"
				break;
			case DBSTATUS_S_TRUNCATED:
			case DBSTATUS_S_OK:
			case DBSTATUS_S_DEFAULT:
				if( rgBindings[iCol].wType == DBTYPE_IUNKNOWN )
					cchLength = 2 + 8;                      // "0x%08lx"
				// Ensure that the length is at least the minimum
				// display size
				cchLength = max(cchLength, MIN_DISPLAY_SIZE);
				break;
			default:
				cchLength = 14;                        // "(error status)"
				break;
		}

		if( rgDispSize[iCol] < cchLength )
			rgDispSize[iCol] = cchLength;
	}

	return S_OK;
}

/////////////////////////////////////////////////////////////////
// myFindColumn
//
// Find the index of the column described in pwszName, and return
// S_OK or, if not found, S_FALSE
//
/////////////////////////////////////////////////////////////////

HRESULT myFindColumn(
											IUnknown *       pUnkRowset,
											LPCWSTR          pwszName,
											LONG *           plIndex
											)
{
	HRESULT          hr;
	IColumnsInfo *   pIColumnsInfo    = NULL;
	ULONG            cColumns;
	DBCOLUMNINFO *   rgColumnInfo     = NULL;
	OLECHAR *        pStringsBuffer   = NULL;
	ULONG            iCol;
	// Get the IColumnsInfo interface
	XCHECK_HR(hr = pUnkRowset->QueryInterface(
	IID_IColumnsInfo, (void**)&pIColumnsInfo));
	// Get the columns information
	XCHECK_HR(hr = pIColumnsInfo->GetColumnInfo(
									&cColumns,                            // pcColumns
									&rgColumnInfo,                        // prgColumnInfo
									&pStringsBuffer                       // ppStringBuffer
									));

	// Assume that we'll find the column
	hr = S_OK;
	// Search for the column we need
	for( iCol = 0; iCol < cColumns; iCol++ )
	{
		// If the column name matches, we've found the column...
		if( rgColumnInfo[iCol].pwszName && !wcscmp(pwszName, rgColumnInfo[iCol].pwszName) )
		{
			*plIndex = iCol;
			goto CLEANUP;
		}
	}

	// If we didn't find the column, we'll return S_FALSE
	hr = S_FALSE;
CLEANUP:
	CoTaskMemFree(rgColumnInfo);
	CoTaskMemFree(pStringsBuffer);
	if( pIColumnsInfo )
		pIColumnsInfo->Release();
	return hr;
}

⌨️ 快捷键说明

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