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

📄 proxyrowsetimpl.h

📁 The ATL OLE DB Provider templates only seem to support read-only rowsets and making them support upd
💻 H
📖 第 1 页 / 共 2 页
字号:

   const LONG numCols = GetNumColumns();

   if (numCols == 0)
   {
		return DB_E_NOTABLE;
   }

   if (pcRowsAffected != NULL)
   {
		*pcRowsAffected = numCols;
   }

   return S_OK;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
STDMETHODIMP CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::GetData(
   HROW hRow,
   HACCESSOR hAccessor,
   void *pDstData)
{
	ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - hRow = %d\n", hRow);

	if (pDstData == NULL)
   {
		return E_INVALIDARG;
   }

	RowClass* pRow = 0;
	
   if (hRow == NULL || (pRow = m_rgRowHandles.Lookup((RowClass::KeyType)hRow)) == NULL)
   {
      ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Bad row handle\n");
      return DB_E_BADROWHANDLE;
   }

   _BindType *pBinding = m_rgBindings.Lookup((int)hAccessor);

   if (pBinding == NULL)
   {
	   return DB_E_BADACCESSORHANDLE;
   }

   // At this point we know the bindings for the data we're accesssing...
   
   HRESULT hr = S_OK;

   ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Bindings for %d columns\n", pBinding->cBindings);

	for (ULONG iBind =0; SUCCEEDED(hr) && iBind < pBinding->cBindings; iBind++)
	{
		DBBINDING* pBindCur = &(pBinding->pBindings[iBind]);

      
      ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Binding for column ordinal %d\n", pBindCur->iOrdinal);
      
      if (pBindCur->iOrdinal > GetNumColumns())
      {
      	ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Error - bad ordinal\n");

         return DB_E_BADORDINAL;
      }

		BOOL bProvOwn = (pBindCur->dwMemOwner == DBMEMOWNER_PROVIDEROWNED);

      if (bProvOwn)
      {
      	ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Error - we dont support provider owned memory\n");

         return E_FAIL;
      }

      DBSTATUS dbStat = DBSTATUS_S_OK; 

      ULONG cbDst = pBindCur->cbMaxLen;
   	BYTE *pDstTemp = (BYTE*)pDstData + pBindCur->obValue;


      ULONG cbCol = 0; 
      void *pSrcTemp = 0; 
      DBTYPE colType; 
      bool bUpdatable;

      InternalGetColumnData(pRow->m_iRowset, pBindCur->iOrdinal, colType, cbCol, pSrcTemp, bUpdatable);

		if (pBindCur->dwPart & DBPART_VALUE)
		{
			hr = m_spConvert->DataConvert(
            colType,                         // the column type
            pBindCur->wType,                 // the required type
				cbCol,                           // length of column data
            &cbDst,                          // length of data after conversion
            (BYTE*)pSrcTemp,                 // pointer to the column data
			   pDstTemp,                        // pointer to where to put it...
            pBindCur->cbMaxLen,              // max length of destination buffer
            dbStat,                          // source status
            &dbStat,                         // dest status
				pBindCur->bPrecision,            // precision
            pBindCur->bScale,                // scale
            0);                              // flags - none supplied
      }

		if (pBindCur->dwPart & DBPART_LENGTH)
      {
			*((ULONG*)((BYTE*)(pDstData) + pBindCur->obLength)) = cbDst;
      }

		if (pBindCur->dwPart & DBPART_STATUS)
      {
			*((DBSTATUS*)((BYTE*)(pDstData) + pBindCur->obStatus)) = dbStat;
      }
	}

   ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - %s\n", (hr == S_OK ? "OK" : "FAILED"));

	return hr;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::InternalGetColumnData(
   size_t row,
   size_t column,
   DBTYPE &dbType, 
   ULONG &size, 
   void *&pData,
   bool &bUpdatable)
{
   if (column == 0)
   {
      // We handle the bookmark column. 
      
      dbType = DBTYPE_BYTES;

      size = sizeof(DWORD);

      static DWORD bookmark;
   
      bookmark = row + 1;        // The bookmark can't be 0, so we use the row index + 1

      pData = &bookmark;

      bUpdatable = false;
   }
   else
   {
      GetColumnData(row, column - 1, dbType, size, pData, bUpdatable);
   }
}

///////////////////////////////////////////////////////////////////////////////
// Stuff needed because our storage object passes on the call it gets for
// column information, we own the column map.
///////////////////////////////////////////////////////////////////////////////

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
ATLCOLUMNINFO* CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::StorageProxy_GetColumnInfo(
   ULONG *pcCols)
{
   if (!m_pColumnInfo)
   {
      // If we've never been called before, build the column map...

      BuildColumnInfo();
   }

   ULONG cCols = m_NumCols;

   ATLCOLUMNINFO *pRetCols = m_pColumnInfo;

   if (!BookmarksRequired())
   {
      // The column info map always contains the bookmark column as the first col,

      // If bookmarks aren't required, pass out all but the first column info struct, 
      // and adjust the count to suit.
      pRetCols++;
      cCols--;
   }

   if (pcCols != NULL)
   {
		*pcCols = cCols;
   }

   return pRetCols;
}


///////////////////////////////////////////////////////////////////////////////
// 
///////////////////////////////////////////////////////////////////////////////

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::BuildColumnInfo()
{
   // columns start at 1, 0 is reserved for the bookmark column which may or may
   // not be required, the actual ATLCOLUMNINFO entry for 0 is always present though

   const size_t numCols = GetNumColumns();
   
   m_NumCols = numCols + 1;      // Add one for the bookmark column

   m_pColumnInfo = new ATLCOLUMNINFO[m_NumCols];

   ULONG ulCols = 0;

   // Always add the bookmark column

   // TODO: This should be called something other than "Bookmark"...

   m_pColumnInfo[ulCols].pwszName = ustrdup("Bookmark");
	m_pColumnInfo[ulCols].pTypeInfo = (ITypeInfo*)NULL; 
	m_pColumnInfo[ulCols].iOrdinal = ulCols;
	m_pColumnInfo[ulCols].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK; 
	m_pColumnInfo[ulCols].ulColumnSize = sizeof(DWORD);
	m_pColumnInfo[ulCols].wType = DBTYPE_BYTES; 
	m_pColumnInfo[ulCols].bPrecision = 0; 
	m_pColumnInfo[ulCols].bScale = 0;
	m_pColumnInfo[ulCols].cbOffset = 0; 
	memset(&(m_pColumnInfo[ulCols].columnid), 0, sizeof(DBID));
	m_pColumnInfo[ulCols].columnid.uName.pwszName = m_pColumnInfo[ulCols].pwszName;

   ulCols++;

   ULONG offset = sizeof(DWORD);

   for (size_t i = 0; i < numCols; i++)
   {
	   // Next set the other columns up.
      
      DBTYPE dbType; 
      ULONG size; 
      std::string columnName;
      DWORD flags = DBCOLUMNFLAGS_ISFIXEDLENGTH | DBCOLUMNFLAGS_WRITE;

      GetColumnInformation(i, dbType, size, columnName, flags);

	   m_pColumnInfo[ulCols].pwszName = ustrdup(columnName.c_str());
	   m_pColumnInfo[ulCols].pTypeInfo = (ITypeInfo*)NULL; 
	   m_pColumnInfo[ulCols].iOrdinal = ulCols; 
	   m_pColumnInfo[ulCols].dwFlags = flags;
	   m_pColumnInfo[ulCols].ulColumnSize = size;
	   m_pColumnInfo[ulCols].wType = dbType;
	   m_pColumnInfo[ulCols].bPrecision = 0xFF; 
	   m_pColumnInfo[ulCols].bScale = 0xFF;
	   m_pColumnInfo[ulCols].cbOffset = offset;
	   memset(&(m_pColumnInfo[ulCols].columnid), 0, sizeof(DBID)); 
	   m_pColumnInfo[ulCols].columnid.uName.pwszName = m_pColumnInfo[ulCols].pwszName;

      offset += size;         // offset isn't used by us.
	   ulCols++;
   }
}

///////////////////////////////////////////////////////////////////////////////
// Stuff needed because our ArrayType is just a proxy that forwards all 
// significant requests on to us. We own the data that our recordset represents!
///////////////////////////////////////////////////////////////////////////////

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
int CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_GetSize() const
{
   return GetNumRows();
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
unsigned char &CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_IndexOperator(
   int nIndex) const
{
   ATLASSERT(true);

   // This should never be called. We dont access the ArrayType using [], but the standard
   // templates do and even though we're not using the code that does use [] we have to 
   // have one because VC doesnt quite conform to how templates are supposed to work (It
   // should only require a function if we actually use it, we dont use it, so it shouldnt
   // require it...)
   // As such we assert, but we also have to return something or the compiler gets upset...
   
   static unsigned char bugger = 'c';
   return bugger;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
BOOL CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_Add(
   Storage &/*storage*/)
{
   // The standard ATL OLE DB Provider templates add a new row by creating an instance of
   // the rowset class's Storage object and calling Add() on the ArrayType object...
   // Our Storage and ArrayType objects are just thin proxies that pass all calls on to
   // the Rowset, so we ignore the Storage that's passed in (it's meaningless to us) and
   // assume that the Rowset knows how to add a row when we call AddRow()

   return AddRow();
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
BOOL CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_RemoveAt(
   int nIndex)
{
   // The standard ATL OLE DB Provider templates use an array class as their ArrayType,
   // removing a row (which isn't actually done in the standard provider...) can be achieved
   // simply by calling RemoveAt(). Our ArrayType is a proxy that passes the call on to us, 
   // we call RemoveRow() on the derived Rowset and leave it up to it how or if it does the 
   // job.

   return RemoveRow(nIndex);
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_RemoveAll()
{
   // The standard ATL OLE DB Provider templates use an array class as their ArrayType,
   // RemoveAllRows() is called when the ArrayType object is destroyed, Our ArrayType is 
   // a proxy that passes the call on to us, we call RemoveAllRows() on the derived Rowset 
   // and leave it up to it how or if it does the job.

   RemoveAllRows();
}

///////////////////////////////////////////////////////////////////////////////
// Default implementations of AddRow(), RemoveRow() and RemoveAllRows() so that
// if the derived Rowset doesnt need them it doesnt have to provide these empty
// implementations....
///////////////////////////////////////////////////////////////////////////////

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::AddRow() 
{
   // By default do nothing
   return E_NOTIMPL;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::RemoveRow(
   int nIndex)
{
   // By default do nothing
   return E_NOTIMPL;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::RemoveAllRows()
{
   // By default do nothing
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
wchar_t *CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ustrdup(const char *pIn)
{
   size_t length = strlen(pIn) + 1;
    
   wchar_t *pOut = new wchar_t[length];
    
   if (pOut)
   {
      mbstowcs(pOut, pIn, length);
   }

   return pOut;
}

template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::Execute(DBPARAMS * pParams, LONG* pcRowsAffected)
{
   // This should never be used
      
   return E_NOTIMPL;
}

#endif // __PROXY_ROWSET_IMPL__INCLUDED__

///////////////////////////////////////////////////////////////////////////////
// End of file...
///////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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