Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
8.2 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995-2000.
  5. //
  6. // File: SeqSer.cxx
  7. //
  8. // Contents: Sequential cursor for serial (unsorted) results.
  9. //
  10. // Classes: CSequentialSerial
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include "seqser.hxx"
  19. #include "rowman.hxx"
  20. // Rowset object Interfaces that support Ole DB error objects
  21. static const IID * apRowsetErrorIFs[] =
  22. {
  23. &IID_IAccessor,
  24. &IID_IColumnsInfo,
  25. &IID_IConvertType,
  26. &IID_IRowset,
  27. &IID_IRowsetInfo,
  28. //&IID_IRowsetWatchRegion,
  29. //&IID_IRowsetAsynch,
  30. &IID_IRowsetQueryStatus,
  31. //&IID_IColumnsRowset,
  32. &IID_IConnectionPointContainer,
  33. &IID_IRowsetIdentity,
  34. //&IID_IRowsetLocate,
  35. //&IID_IRowsetResynch,
  36. //&IID_IRowsetScroll,
  37. //&IID_IRowsetUpdate,
  38. //&IID_ISupportErrorInfo
  39. };
  40. static const ULONG cRowsetErrorIFs = sizeof(apRowsetErrorIFs)/sizeof(apRowsetErrorIFs[0]);
  41. //+---------------------------------------------------------------------------
  42. //
  43. // Member: CSequentialSerial::CSequentialSerial, public
  44. //
  45. // Synopsis: Constructor.
  46. //
  47. // Arguments: [pUnkOuter] -- outer unknown
  48. // [ppMyUnk] -- OUT: on return, filled with pointer to my
  49. // non-delegating IUnknown
  50. // [aChild] -- Child rowset(s)
  51. // [cChild] -- Count of rowsets in [aChild]
  52. // [Props] -- Rowset properties.
  53. // [cCol] -- Number of original columns.
  54. //
  55. // History: 05-Jun-95 KyleP Created.
  56. //
  57. //----------------------------------------------------------------------------
  58. CSequentialSerial::CSequentialSerial( IUnknown * pUnkOuter,
  59. IUnknown ** ppMyUnk,
  60. IRowset ** aChild,
  61. unsigned cChild,
  62. CMRowsetProps const & Props,
  63. unsigned cCol,
  64. CAccessorBag & aAccessors) :
  65. CDistributedRowset( pUnkOuter, ppMyUnk,
  66. aChild, cChild, Props, cCol,
  67. aAccessors, _DBErrorObj ),
  68. #pragma warning(disable : 4355) // 'this' in a constructor
  69. _DBErrorObj(* (IUnknown *) (IRowset *)this, _mutex ),
  70. #pragma warning(default : 4355) // 'this' in a constructor
  71. _iChild( 0 )
  72. {
  73. _DBErrorObj.SetInterfaceArray(cRowsetErrorIFs, apRowsetErrorIFs);
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Member: CSequentialSerial::~CSequentialSerial, public
  78. //
  79. // Synopsis: Virtual destructor.
  80. //
  81. // History: 05-Jun-95 KyleP Created.
  82. //
  83. //----------------------------------------------------------------------------
  84. CSequentialSerial::~CSequentialSerial()
  85. {
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: CSequentialSerial::_GetNextRows, protected
  90. //
  91. // Synopsis: Sequentially fetch rows
  92. //
  93. // Arguments: [hChapter] -- Chapter
  94. // [cRowsToSkip] -- Skip this many rows before beginning.
  95. // [cRows] -- Try to fetch this many rows.
  96. // [pcRowsObtained] -- Actually fetched this many.
  97. // [pphRows] -- Store HROWs here. Allocate memory if
  98. // [pphRows] is zero.
  99. //
  100. // History: 07-Apr-95 KyleP Created.
  101. //
  102. // Notes: Since every child cursor was given the same bindings, this
  103. // method can be resolved by any of the child cursors.
  104. //
  105. // Notes: Need to have Ole DB error handling here because we are translating
  106. // errors.
  107. //
  108. //----------------------------------------------------------------------------
  109. SCODE CSequentialSerial::_GetNextRows( HCHAPTER hChapter,
  110. DBROWOFFSET cRowsToSkip,
  111. DBROWCOUNT cRows,
  112. DBCOUNTITEM * pcRowsObtained,
  113. HROW * * pphRows )
  114. {
  115. _DBErrorObj.ClearErrorInfo();
  116. SCODE sc = S_OK;
  117. Win4Assert( 0 == hChapter && "Chapter support not yet implemented" );
  118. if (!pcRowsObtained || !pphRows)
  119. {
  120. vqDebugOut(( DEB_IERROR, "CSequentialSerial::GetNextRows: Invalid parameter(s).\n" ));
  121. return _DBErrorObj.PostHResult(E_INVALIDARG, IID_IRowset);
  122. }
  123. *pcRowsObtained = 0;
  124. if (0 == cRows) // nothing to fetch
  125. return S_OK;
  126. TRY
  127. {
  128. //
  129. // Don't support backwards fetch.
  130. //
  131. if ( cRows < 0 || cRowsToSkip < 0 )
  132. {
  133. return _DBErrorObj.PostHResult(DB_E_CANTFETCHBACKWARDS, IID_IRowset);
  134. }
  135. //
  136. // We may have to allocate memory, if the caller didn't.
  137. //
  138. XCoMem<HROW> xmem;
  139. if ( 0 == *pphRows )
  140. {
  141. xmem.Set( (HROW *)CoTaskMemAlloc( (ULONG) ( cRows * sizeof(HROW) ) ) );
  142. *pphRows = xmem.GetPointer();
  143. }
  144. if ( 0 == *pphRows )
  145. {
  146. vqDebugOut(( DEB_ERROR, "CSequentialSerial::GetNextRows: Out of memory.\n" ));
  147. THROW( CException( E_OUTOFMEMORY ) );
  148. }
  149. //
  150. // Fetch from current child.
  151. //
  152. ULONG cTotalRowsObtained = 0;
  153. while ( cTotalRowsObtained < (ULONG)cRows )
  154. {
  155. if ( _iChild >= _cChild )
  156. {
  157. sc = DB_S_ENDOFROWSET;
  158. break;
  159. }
  160. DBCOUNTITEM cRowsObtained;
  161. HROW * pStart = *pphRows + cTotalRowsObtained;
  162. sc = _aChild[_iChild]->GetNextRows( hChapter,
  163. cRowsToSkip,
  164. cRows - cTotalRowsObtained,
  165. &cRowsObtained,
  166. &pStart );
  167. Win4Assert( pStart == *pphRows + cTotalRowsObtained );
  168. cRowsToSkip = 0;
  169. if ( FAILED(sc) )
  170. {
  171. vqDebugOut(( DEB_ERROR, "Error 0x%x calling IRowset::GetNextRows\n", sc ));
  172. //
  173. // If we already have some rows, then we can't 'unfetch' them, so we have
  174. // to mask this error. Presumably it won't be transient and we'll get it
  175. // again later.
  176. //
  177. if ( cTotalRowsObtained > 0 )
  178. {
  179. sc = DB_S_ROWLIMITEXCEEDED;
  180. }
  181. break;
  182. }
  183. //
  184. // Convert HROWs into distributed HROWs.
  185. //
  186. for ( unsigned i = 0; i < cRowsObtained; i++ )
  187. {
  188. (*pphRows)[cTotalRowsObtained] = _RowManager.Add( _iChild, pStart[i] );
  189. cTotalRowsObtained++;
  190. }
  191. //
  192. // May have to move to next child cursor.
  193. //
  194. if ( sc == DB_S_ENDOFROWSET )
  195. {
  196. _iChild++;
  197. }
  198. else if ( 0 == cRowsObtained )
  199. {
  200. Win4Assert( ( DB_S_ROWLIMITEXCEEDED == sc ) ||
  201. ( DB_S_STOPLIMITREACHED == sc ) );
  202. break;
  203. }
  204. }
  205. *pcRowsObtained = cTotalRowsObtained;
  206. xmem.Acquire();
  207. }
  208. CATCH( CException, e )
  209. {
  210. sc = e.GetErrorCode();
  211. }
  212. END_CATCH
  213. if (FAILED(sc))
  214. _DBErrorObj.PostHResult(sc, IID_IRowset);
  215. return sc;
  216. } //_GetNextRows
  217. //+---------------------------------------------------------------------------
  218. //
  219. // Member: CSequentialSerial::RestartPosition, public
  220. //
  221. // Synopsis: Reset cursor for GetNextRows
  222. //
  223. // Arguments: [hChapter] -- Chapter
  224. //
  225. // History: 22 Sep 98 VikasMan Created.
  226. //
  227. //----------------------------------------------------------------------------
  228. STDMETHODIMP CSequentialSerial::RestartPosition( HCHAPTER hChapter )
  229. {
  230. _iChild = 0;
  231. return CDistributedRowset::RestartPosition( hChapter );
  232. }