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

📄 atldbcli.h

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 H
📖 第 1 页 / 共 5 页
字号:
		ULONG   nRowsFetched;

		CComPtr<IRowsetScroll> spRowsetScroll;
		HRESULT hr = m_spRowset->QueryInterface(&spRowsetScroll);
		if (FAILED(hr))
			return hr;

		ReleaseRows();
		HROW* phRow = &m_hRow;
		hr = spRowsetScroll->GetRowsAtRatio(NULL, NULL, nNumerator, nDenominator, (bForward) ? 1 : -1,
			&nRowsFetched, &phRow);
		// Note we're not using SUCCEEDED here, because we could get DB_S_ENDOFROWSET
		if (hr == S_OK)
			hr = GetData();

		return hr;
	}

// Implementation
	static const IID& GetIID()
	{
		return IID_IRowset;
	}
	IRowset* GetInterface() const
	{
		return m_spRowset;
	}
	IRowset** GetInterfacePtr()
	{
		return &m_spRowset;
	}
	void SetupOptionalRowsetInterfaces()
	{
		// Cache IRowsetChange if available
		if (m_spRowset != NULL)
			m_spRowset->QueryInterface(&m_spRowsetChange);
	}
	HRESULT BindFinished() const { return S_OK; }
	void    SetAccessor(CAccessorBase* pAccessor)
	{
		m_pAccessor = pAccessor;
	}

	CComPtr<IRowset>        m_spRowset;
	CComPtr<IRowsetChange>  m_spRowsetChange;
	CAccessorBase*          m_pAccessor;
	HROW                    m_hRow;
};


///////////////////////////////////////////////////////////////////////////
// class CBulkRowset

class CBulkRowset : public CRowset
{
public:
	CBulkRowset()
	{
		// Default the number of rows to bulk fetch to 10
		m_nRows = 10;
		m_hr    = S_OK;
		m_phRow = NULL;
	}
	CBulkRowset::~CBulkRowset()
	{
		Close();

		delete [] m_phRow;
	}
	// Set the number of row handles that will be retrieved in each
	// bulk row fetch. The default is 10 and this function must be called
	// before Open if you wish to change it.
	void SetRows(ULONG nRows)
	{
		// This function must be called before the memory is allocated
		// during binding
		ATLASSERT(m_phRow == NULL);
		m_nRows = nRows;
	}
	// AddRef all the currently retrieved row handles
	HRESULT AddRefRows()
	{
		ATLASSERT(m_spRowset != NULL);
		return m_spRowset->AddRefRows(m_nCurrentRows, m_phRow, NULL, NULL);
	}
	// Release all the currently retrieved row handles
	HRESULT ReleaseRows()
	{
		ATLASSERT(m_spRowset != NULL);
		// We're going to Release the rows so reset the current row position
		m_nCurrentRow = 0;
		m_hRow        = NULL;
		return m_spRowset->ReleaseRows(m_nCurrentRows, m_phRow, NULL, NULL, NULL);
	}
	// Move to the first record
	HRESULT MoveFirst()
	{
		ATLASSERT(m_spRowset != NULL);
		ReleaseRows();

		// Cause MoveNext to perform a new bulk fetch
		m_nCurrentRow  = m_nRows;

		HRESULT hr = m_spRowset->RestartPosition(NULL);
		if (FAILED(hr))
			return hr;

		// Get the data
		return MoveNext();
	}
	// Move to the next record
	HRESULT MoveNext()
	{
		ATLASSERT(m_spRowset != NULL);
		ATLASSERT(m_phRow    != NULL);

		// Move to the next record in the buffer
		m_nCurrentRow++;

		// Have we reached the end of the buffer?
		if (m_nCurrentRow >= m_nCurrentRows)
		{
			// If we've reached the end of the buffer and we had a non S_OK HRESULT from
			// the last call to GetNextRows then return that HRESULT now.
			if (m_hr != S_OK)
				return m_hr;

			// We've finished with these rows so we need some more
			// First release any HROWs that we have
			ReleaseRows();

			m_hr = m_spRowset->GetNextRows(NULL, 0, m_nRows, &m_nCurrentRows, &m_phRow);
			// If we have an error HRESULT or we haven't retrieved any rows then return
			// the HRESULT now.
			if (FAILED(m_hr) || m_nCurrentRows == 0)
				return m_hr;
		}

		// Get the data for the current row
		m_hRow = m_phRow[m_nCurrentRow];
		return GetData();
	}
	// Move to the previous record
	HRESULT MovePrev()
	{
		ATLASSERT(m_spRowset != NULL);
		ATLASSERT(m_phRow    != NULL);

		// Check if we're at the start of the block
		if (m_nCurrentRow == 0)
		{
			ReleaseRows();

			// Go back the amount of rows in the block - 1 and fetch forward
			m_hr = m_spRowset->GetNextRows(NULL, -(LONG)m_nRows-1, m_nRows, &m_nCurrentRows, &m_phRow);

			// Set the current record to the end of the new block
			m_nCurrentRow = m_nCurrentRows - 1;

			// If we have an error HRESULT or we haven't retrieved any rows then return
			// the HRESULT now.
			if (FAILED(m_hr) || m_nCurrentRows == 0)
				return m_hr;
		}
		else
		{
			// Move back a row in the block
			m_nCurrentRow--;
		}

		// Get the data for the current row
		m_hRow = m_phRow[m_nCurrentRow];
		return GetData();
	}
	// Move to the last record
	HRESULT MoveLast()
	{
		ReleaseRows();
		return CRowset::MoveLast();
	}
	// Move to the passed bookmark
	HRESULT MoveToBookmark(const CBookmarkBase& bookmark, LONG lSkip = 0)
	{
		ATLASSERT(m_spRowset != NULL);
		CComPtr<IRowsetLocate> spLocate;
		HRESULT hr = m_spRowset->QueryInterface(&spLocate);
		if (FAILED(hr))
			return hr;

		ReleaseRows();
		m_hr = spLocate->GetRowsAt(NULL, NULL, bookmark.GetSize(), bookmark.GetBuffer(),
			lSkip, m_nRows, &m_nCurrentRows, &m_phRow);
		if (m_hr != S_OK || m_nCurrentRows == 0)
			return m_hr;

		// Get the data
		m_hRow = m_phRow[m_nCurrentRow];
		return GetData();
	}
	// Move to a fractional position in the rowset
	HRESULT MoveToRatio(ULONG nNumerator, ULONG nDenominator)
	{
		ATLASSERT(m_spRowset != NULL);

		CComPtr<IRowsetScroll> spRowsetScroll;
		HRESULT hr = m_spRowset->QueryInterface(&spRowsetScroll);
		if (FAILED(hr))
			return hr;

		ReleaseRows();
		m_hr = spRowsetScroll->GetRowsAtRatio(NULL, NULL, nNumerator, nDenominator, m_nRows, &m_nCurrentRows, &m_phRow);
		if (m_hr != S_OK || m_nCurrentRows == 0)
			return m_hr;

		// Get the data
		m_hRow = m_phRow[m_nCurrentRow];
		return GetData();
	}
	// Insert the current record
	HRESULT Insert(int nAccessor = 0, bool bGetHRow = false)
	{
		ReleaseRows();
		return CRowset::Insert(nAccessor, bGetHRow);
	}

// Implementation
	HRESULT BindFinished()
	{
		// No rows in the buffer yet
		m_nCurrentRows = 0;
		// Cause MoveNext to automatically perform a new bulk fetch the first time
		m_nCurrentRow  = m_nRows;

		m_phRow = NULL;
		ATLTRY(m_phRow = new HROW[m_nRows]);
		if (m_phRow == NULL)
			return E_OUTOFMEMORY;

		return S_OK;
	}

	HRESULT m_hr;           // HRESULT to return from MoveNext at end of buffer
	HROW*   m_phRow;        // Pointer to array of HROWs for each row in buffer
	ULONG   m_nRows;        // Number of rows that will fit in the buffer
	ULONG   m_nCurrentRows; // Number of rows currently in the buffer
	ULONG   m_nCurrentRow;
};

///////////////////////////////////////////////////////////////////////////
// class CArrayRowset
//
// Allows you to access a rowset with an array syntax

template <class T, class TRowset = CRowset>
class CArrayRowset :
	public CVirtualBuffer<T>,
	public TRowset
{
public:
	CArrayRowset(int nMax = 100000) : CVirtualBuffer<T>(nMax)
	{
		m_nRowsRead = 0;
	}
	T& operator[](int nRow)
	{
		ATLASSERT(nRow >= 0);
		HRESULT hr = S_OK;
		T* m_pCurrent = m_pBase + m_nRowsRead;

		// Retrieve the row if we haven't retrieved it already
		while ((ULONG)nRow >= m_nRowsRead)
		{
			m_pAccessor->SetBuffer((BYTE*)m_pCurrent);
			__try
			{
				// Get the row
				hr = MoveNext();
				if (hr != S_OK)
					break;
			}
			__except(Except(GetExceptionInformation()))
			{
			}
			m_nRowsRead++;
			m_pCurrent++;
		}
		if (hr != S_OK)
			*((char*)0) = 0; // Force exception

		return *(m_pBase + nRow);
	}

	HRESULT Snapshot()
	{
		ATLASSERT(m_nRowsRead == 0);
		ATLASSERT(m_spRowset != NULL);
		HRESULT hr = MoveFirst();
		if (FAILED(hr))
			return hr;
		do
		{
			Write(*(T*)m_pAccessor->GetBuffer());
			m_nRowsRead++;
			hr = MoveNext();
		} while (SUCCEEDED(hr) &&  hr != DB_S_ENDOFROWSET);

		return (hr == DB_S_ENDOFROWSET) ? S_OK : hr;
	}


// Implementation
	ULONG   m_nRowsRead;
};

// Used when you don't need any parameters or output columns
class CNoAccessor
{
public:
	// We don't need any typedef's here as the default
	// global typedef is not to have any parameters and
	// output columns.
	HRESULT BindColumns(IUnknown*) { return S_OK; }
	HRESULT BindParameters(HACCESSOR*, ICommand*, void**) { return S_OK; }
	void    Close() { }
	HRESULT ReleaseAccessors(IUnknown*) { return S_OK; }
};

// Used when a rowset will not be returned from the command
class CNoRowset
{
public:
	HRESULT             BindFinished() { return S_OK; }
	void                Close() { }
	static const IID&   GetIID() { return IID_NULL; }
	IRowset*            GetInterface() const { return NULL; }
	IRowset**           GetInterfacePtr() { return NULL; }
	void                SetAccessor(void*) { }
	void                SetupOptionalRowsetInterfaces() { }
};

///////////////////////////////////////////////////////////////////////////
// class CAccessor

// T is the class that contains the data that will be accessed.
template <class T>
class CAccessor :
	public T,
	public CAccessorBase
{
public:
// Implementation
	// Free's any columns in the current record that need to be freed.
	// E.g. Calls SysFreeString on any BSTR's and Release on any interfaces.
	void FreeRecordMemory(IRowset* /* pRowset */)
	{
		ULONG nColumns;
		ULONG i;

		for (i = 0; i < GetNumAccessors(); i++)
		{
			// Passing in m_pBuffer tells the column entry maps to free the
			// memory for the types if appropriate
			_GetBindEntries(&nColumns, NULL, i, NULL, m_pBuffer);
		}
	}
	HRESULT BindColumns(IUnknown* pUnk)
	{
		HRESULT hr;
		ULONG   nAccessors;
		ULONG   nSize;
		nAccessors = _OutputColumnsClass::_GetNumAccessors();

		SetBuffer((BYTE*)this);

		nSize = sizeof(T);
		hr = BindAccessors(nAccessors, nSize, pUnk);
		return hr;
	}
	HRESULT BindAccessors(ULONG nAccessors, ULONG nSize, IUnknown* pUnk)
	{
		ATLASSERT(pUnk != NULL);
		HRESULT hr;

		CComPtr<IAccessor> spAccessor;
		hr = pUnk->QueryInterface(&spAccessor);
		if (SUCCEEDED(hr))
		{
			// Allocate the accessor memory if we haven't done so yet
			if (m_pAccessorInfo == NULL)
			{
				hr = AllocateAccessorMemory(nAccessors);
				if (FAILED(hr))
					return hr;
			}

			for (ULONG i=0; i<nAccessors && SUCCEEDED(hr); i++)
				hr = BindAccessor(spAccessor, i, nSize);
		}

		return hr;
	}

	HRESULT BindAccessor(IAccessor* pAccessor, ULONG nAccessor, ULONG nSize)
	{
		DBBINDING*  pBindings = NULL;
		ULONG       nColumns;
		bool        bAuto;
		HRESULT     hr;

		// First time just get the number of entries by passing in &nColumns
		_OutputColumnsClass::_GetBindEntries(&nColumns, NULL, nAccessor, NULL);

		// Now allocate the binding structures
		ATLTRY(pBindings = new DBBINDING[nColumns]);
		if (pBindings == NULL)
			return E_OUTOFMEMORY;

		// Now get the bind entries
		hr = _OutputColumnsClass::_GetBindEntries(&nColumns, pBindings, nAccessor, &bAuto);
		if (FAILED(hr))
			return hr;

		m_pAccessorInfo[nAccessor].bAutoAccessor = bAuto;
		hr = BindEntries(pBindings, nColumns, &m_pAccessorInfo[nAccessor].hAccessor, nSize, pAccessor);
		delete [] pBindings;
		return hr;
	}

	HRESULT BindParameters(HACCESSOR* pHAccessor, ICommand* pCommand, void** ppParameterBuffer)
	{
		HRESULT hr = S_OK;
		// In the static accessor case, the parameter buffer will be T
		*ppParameterBuffer = this;

		// Only bind the parameters if we haven't already done it
		if (*pHAccessor == NULL)
		{
			ULONG   nColumns;
			_ParamClass::_GetParamEntries(&nColumns, NULL);

			DBBINDING* pBinding = NULL;
			ATLTRY(pBinding = new DBBINDING[nColumns]);
			if (pBinding == NULL)
				return E_OUTOFMEMORY;

			hr = _ParamClass::_GetParamEntries(&nColumns, pBinding);
			if (SUCCEEDED(hr))
			{
				// Get the IAccessor from the passed IUnknown
				CComPtr<IAccessor> spAccessor;
				hr = pCommand->QueryInterface(&spAccessor);
				if (SUCCEEDED(hr))
				{
					hr = BindEntries(pBinding, nColumns, pHAccessor, sizeof(T),
						spAccessor);
				}
			}
			delete [] pBinding;
		}
		return hr;
	}
};


///////////////////////////////////////////////////////////////////////////
// CDynamicAccessor

class CDynamicAccessor :
	public CAccessorBase
{
public:
	CDynamicAccessor()
	{
		m_nColumns        = 0;
		m_pColumnInfo     = NULL;
		m_pStringsBuffer  = NULL;
	};
	~CDynamicAccessor()
	{
		Close();

⌨️ 快捷键说明

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