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

📄 s15_03.cpp

📁 本书分为五个部分
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// Get the IColumnsInfo interface.
	// See IColumnsInfo
	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;
}

/////////////////////////////////////////////////////////////////
// 函数: DisplayColumnNames
//
// 显示行集的列名.
//
/////////////////////////////////////////////////////////////////
HRESULT DisplayColumnNames(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.
	// See IColumnsInfo
	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 new line.
	wprintf(L"\n");

CLEANUP:
	CoTaskMemFree(rgColumnInfo);
	CoTaskMemFree(pStringsBuffer);
	if( pIColumnsInfo )
		pIColumnsInfo->Release();
	return hr;
}

/////////////////////////////////////////////////////////////////
// 函数: DisplayRow
//
// 显示行集行数据.
//
/////////////////////////////////////////////////////////////////
HRESULT DisplayRow(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;
}

/////////////////////////////////////////////////////////////////
// 函数: FreeBindings
//
// 释放绑定数组和这个结构中分配的任何内存.
//
/////////////////////////////////////////////////////////////////
void FreeBindings(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);
}



/////////////////////////////////////////////////////////////////
// 函数: CreateCommand
//
// 这个函数试图用指定的会话对象(IUnknown接口指针)的IDBCreateCommand接口
// 创建一个命令对象. 因为这个接口是可选的, 所以有可能失败.
//
/////////////////////////////////////////////////////////////////
HRESULT   CreateCommand(IUnknown *pUnkSession,
						  IUnknown **ppUnkCommand)
{
	HRESULT              hr;
	IDBCreateCommand *   pIDBCreateCommand = NULL;

	// Attempt to create a command object from the session object.
	XCHECK_HR(hr = pUnkSession->QueryInterface(
		IID_IDBCreateCommand, (void**)&pIDBCreateCommand));
	XCHECK_HR(hr = pIDBCreateCommand->CreateCommand(
		NULL,             // pUnkOuter
		IID_ICommand,     // riid
		ppUnkCommand));   // ppCommand

CLEANUP:
	if( pIDBCreateCommand )
		pIDBCreateCommand->Release();
	return hr;
}

/////////////////////////////////////////////////////////////////
// 函数: ExecuteCommand
//
// 这个函数接受一个命令对象的IUnknown接口指针, 并通过下面这些
// 步骤来创建行集对象:
//  - 设置命令对象的属性; 这些属性将由提供程序用于由这个命令对象创建的行集.
//  - 设置命令对象的命令文本.
//  - 执行命令来创建一个新的行集对象.
//
/////////////////////////////////////////////////////////////////
HRESULT   ExecuteCommand(IUnknown*    pUnkCommand,
						 WCHAR*       pwszCommandText,
						 ULONG        cPropSets,
						 DBPROPSET*   rgPropSets,
						 IUnknown**   ppUnkRowset)
{
	HRESULT                hr;
	ICommandText *         pICommandText          = NULL;
	ICommandProperties *   pICommandProperties   = NULL;

	// Set the properties on the command object.
	XCHECK_HR(hr = pUnkCommand->QueryInterface(
		IID_ICommandProperties, (void**)&pICommandProperties));
	XCHECK_HR(hr = pICommandProperties->SetProperties(cPropSets,
		rgPropSets));

	// Set the text for this command, using the default command text
	// dialect. All providers that support commands must support this
	// dialect, and providers that support SQL must be able to recognize
	// an SQL command as SQL when this dialect is specified.
	XCHECK_HR(hr = pUnkCommand->QueryInterface(
		IID_ICommandText, (void**)&pICommandText));
	XCHECK_HR(hr = pICommandText->SetCommandText(
		DBGUID_DEFAULT,      // guidDialect
		pwszCommandText));   // pwszCommandText

	// And execute the command. Note that the user could have
	// entered a non-row returning command, so we will check for
	// that and return failure to prevent the display of the
	// nonexistent rowset by the caller.
	XCHECK_HR(hr = pICommandText->Execute(   
		NULL,            // pUnkOuter
		IID_IRowset,     // riid
		NULL,            // pParams
		NULL,            // pcRowsAffected
		ppUnkRowset));   // ppRowset

	if( !*ppUnkRowset )
	{
		printf("\nThe command executed successfully, but did not " \
			"return a rowset.\nNo rowset will be displayed.\n");
		hr = E_FAIL;
	}


CLEANUP:
	if( pICommandText )
		pICommandText->Release();
	if( pICommandProperties )
		pICommandProperties->Release();
	return hr;
}

⌨️ 快捷键说明

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