Leaked source code of windows server 2003
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.

347 lines
10 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1998.
  5. //
  6. // File: SeqSort.cxx
  7. //
  8. // Contents: Sequential cursor for sorted results.
  9. //
  10. // Classes: CSequentialSerial
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-Jan-97 KrishnaN Undefined CI_INETSRV and
  14. // related changes
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include "seqsort.hxx"
  20. #include "rowman.hxx"
  21. #include "rowcache.hxx"
  22. // Rowset object Interfaces that support Ole DB error objects
  23. static const IID * apRowsetErrorIFs[] =
  24. {
  25. &IID_IAccessor,
  26. &IID_IColumnsInfo,
  27. &IID_IConvertType,
  28. &IID_IRowset,
  29. &IID_IRowsetInfo,
  30. //&IID_IRowsetWatchRegion,
  31. //&IID_IRowsetAsynch,
  32. &IID_IRowsetQueryStatus,
  33. //&IID_IColumnsRowset,
  34. &IID_IConnectionPointContainer,
  35. &IID_IRowsetIdentity,
  36. //&IID_IRowsetLocate,
  37. //&IID_IRowsetResynch,
  38. //&IID_IRowsetScroll,
  39. //&IID_IRowsetUpdate,
  40. //&IID_ISupportErrorInfo
  41. };
  42. static const ULONG cRowsetErrorIFs = sizeof(apRowsetErrorIFs)/sizeof(apRowsetErrorIFs[0]);
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Member: CSequentialSorted::CSequentialSorted, public
  46. //
  47. // Synopsis: Constructor.
  48. //
  49. // Arguments: [pUnkOuter] -- outer unknown
  50. // [ppMyUnk] -- OUT: on return, filled with pointer to my
  51. // non-delegating IUnknown
  52. // [aChild] -- Child rowset(s).
  53. // [cChild] -- Count of rowsets in [aChild].
  54. // [Props] -- Rowset properties.
  55. // [cCol] -- Number of original columns.
  56. // [Sort] -- Sort specification.
  57. //
  58. // History: 05-Jun-95 KyleP Created.
  59. //
  60. //----------------------------------------------------------------------------
  61. CSequentialSorted::CSequentialSorted( IUnknown * pUnkOuter,
  62. IUnknown ** ppMyUnk,
  63. IRowset ** aChild,
  64. unsigned cChild,
  65. CMRowsetProps const & Props,
  66. unsigned cCol,
  67. CSort const & Sort,
  68. CAccessorBag & aAccessors) :
  69. CDistributedRowset( pUnkOuter, ppMyUnk,
  70. aChild, cChild, Props, cCol,
  71. aAccessors, _DBErrorObj ),
  72. _apCursor( cChild ),
  73. _bindSort( Sort.Count() ),
  74. #pragma warning(disable : 4355) // 'this' in a constructor
  75. _DBErrorObj(* (IUnknown *) (IRowset *)this, _mutex),
  76. #pragma warning(default : 4355) // 'this' in a constructor
  77. _heap( cChild )
  78. {
  79. _DBErrorObj.SetInterfaceArray(cRowsetErrorIFs, apRowsetErrorIFs);
  80. //
  81. // Build binding for sort set.
  82. //
  83. DBORDINAL cColumnInfo;
  84. DBCOLUMNINFO * aColumnInfo;
  85. WCHAR * awchColInfo;
  86. SCODE sc = _GetFullColumnInfo( &cColumnInfo, &aColumnInfo, &awchColInfo );
  87. XCoMem<DBCOLUMNINFO> mem( aColumnInfo );
  88. XCoMem<WCHAR> strings( awchColInfo );
  89. if ( FAILED(sc) )
  90. {
  91. vqDebugOut(( DEB_ERROR, "CSequentialSort: GetColumnInfo returned 0x%x\n", sc ));
  92. THROW( CException( sc ) );
  93. }
  94. _cbSort = _Comparator.Init( Sort,
  95. _bindSort.GetPointer(),
  96. aColumnInfo,
  97. cColumnInfo );
  98. //
  99. // Create accessors
  100. //
  101. for ( unsigned i = 0; i < _cChild; i++ )
  102. {
  103. _apCursor[i] = new CMiniRowCache( i,
  104. _aChild[i],
  105. Sort.Count(),
  106. _bindSort.GetPointer(),
  107. _cbSort );
  108. }
  109. //
  110. // Initialize heap
  111. //
  112. _heap.Init( &_Comparator, _apCursor.GetPointer() );
  113. END_CONSTRUCTION( CSequentialSorted );
  114. }
  115. //+---------------------------------------------------------------------------
  116. //
  117. // Member: CSequentialSorted::~CSequentialSorted, public
  118. //
  119. // Synopsis: Destructor
  120. //
  121. // History: 05-Jun-95 KyleP Created.
  122. //
  123. //----------------------------------------------------------------------------
  124. CSequentialSorted::~CSequentialSorted()
  125. {
  126. //
  127. // Release any remaining cursors.
  128. //
  129. for ( int i = _cChild - 1; i >= 0; i-- )
  130. {
  131. delete _apCursor[i];
  132. }
  133. }
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Member: CSequentialSort::_GetNextRows, protected
  137. //
  138. // Synopsis: Sequentially fetch rows
  139. //
  140. // Arguments: [hChapter] -- Chapter
  141. // [cRowsToSkip] -- Skip this many rows before beginning.
  142. // [cRows] -- Try to fetch this many rows.
  143. // [pcRowsObtained] -- Actually fetched this many.
  144. // [pphRows] -- Store HROWs here. Allocate memory if
  145. // [pphRows] is zero.
  146. //
  147. // History: 07-Apr-95 KyleP Created.
  148. //
  149. // Notes: Need to have Ole DB error handling here because we are translating
  150. // errors.
  151. //
  152. //----------------------------------------------------------------------------
  153. SCODE CSequentialSorted::_GetNextRows( HCHAPTER hChapter,
  154. DBROWOFFSET cRowsToSkip,
  155. DBROWCOUNT cRows,
  156. DBCOUNTITEM * pcRowsObtained,
  157. HROW * * pphRows )
  158. {
  159. _DBErrorObj.ClearErrorInfo();
  160. SCODE sc = S_OK;
  161. BOOL fAllocated = FALSE;
  162. ULONG cTotalRowsObtained = 0;
  163. Win4Assert( 0 == hChapter && "Chapter support not yet implemented" );
  164. if (!pcRowsObtained || !pphRows)
  165. {
  166. vqDebugOut(( DEB_IERROR, "CSequentialSorted::GetNextRows: Invalid parameter(s).\n" ));
  167. return _DBErrorObj.PostHResult(E_INVALIDARG, IID_IRowset);
  168. }
  169. *pcRowsObtained = 0;
  170. if (0 == cRows) // nothing to fetch
  171. return S_OK;
  172. //
  173. // Don't support backwards fetch.
  174. //
  175. if ( cRows < 0 || cRowsToSkip < 0 )
  176. {
  177. return _DBErrorObj.PostHResult(DB_E_CANTSCROLLBACKWARDS, IID_IRowset);
  178. }
  179. TRY
  180. {
  181. //
  182. // We may have to allocate memory, if the caller didn't.
  183. //
  184. if ( 0 == *pphRows )
  185. {
  186. *pphRows = (HROW *)CoTaskMemAlloc( (ULONG) ( cRows * sizeof(HROW) ) );
  187. fAllocated = TRUE;
  188. }
  189. if ( 0 == *pphRows )
  190. {
  191. vqDebugOut(( DEB_ERROR, "CSequentialSerial::GetNextRows: Out of memory.\n" ));
  192. THROW( CException( E_OUTOFMEMORY ) );
  193. }
  194. //
  195. // We may have reached some temporary condition such as
  196. // DB_S_ROWLIMITEXCEEDED on the last pass. Iterate until we
  197. // have a valid heap.
  198. //
  199. _heap.Validate();
  200. //
  201. // Adjust cache size if necessary.
  202. //
  203. if ( !_heap.IsHeapEmpty() )
  204. _heap.AdjustCacheSize( (ULONG) cRows );
  205. //
  206. // Fetch from top of heap.
  207. //
  208. while ( cTotalRowsObtained < (ULONG)cRows )
  209. {
  210. //
  211. // We may be entirely out of rows.
  212. //
  213. if ( _heap.IsHeapEmpty() )
  214. {
  215. sc = DB_S_ENDOFROWSET;
  216. break;
  217. }
  218. if ( cRowsToSkip )
  219. {
  220. cRowsToSkip--;
  221. }
  222. else
  223. {
  224. if ( _RowManager.IsTrackingSiblings() )
  225. (*pphRows)[cTotalRowsObtained] =
  226. _RowManager.Add( _heap.Top()->Index(), _heap.TopHROWs() );
  227. else
  228. (*pphRows)[cTotalRowsObtained] =
  229. _RowManager.Add( _heap.Top()->Index(), _heap.Top()->GetHROW() );
  230. cTotalRowsObtained++;
  231. }
  232. //
  233. // Fetch the next row.
  234. //
  235. PMiniRowCache::ENext next = _heap.Next();
  236. if ( CMiniRowCache::NotNow == next )
  237. {
  238. sc = DB_S_ROWLIMITEXCEEDED;
  239. break;
  240. }
  241. }
  242. *pcRowsObtained = cTotalRowsObtained;
  243. }
  244. CATCH( CException, e )
  245. {
  246. sc = e.GetErrorCode();
  247. vqDebugOut(( DEB_ERROR, "Exception 0x%x calling IRowset::GetNextRows\n", sc ));
  248. //
  249. // If we already have some rows, then we can't 'unfetch' them, so we have
  250. // to mask this error. Presumably it won't be transient and we'll get it
  251. // again later.
  252. //
  253. if ( cTotalRowsObtained > 0 )
  254. {
  255. sc = DB_S_ROWLIMITEXCEEDED;
  256. }
  257. else if ( fAllocated )
  258. {
  259. CoTaskMemFree( *pphRows );
  260. *pphRows = 0;
  261. }
  262. }
  263. END_CATCH
  264. if (FAILED(sc))
  265. _DBErrorObj.PostHResult(sc, IID_IRowset);
  266. return( sc );
  267. }
  268. //+---------------------------------------------------------------------------
  269. //
  270. // Member: CSequentialSorted::RestartPosition, public
  271. //
  272. // Synopsis: Reset cursor for GetNextRows
  273. //
  274. // Arguments: [hChapter] -- Chapter
  275. //
  276. // History: 22 Sep 98 VikasMan Created.
  277. //
  278. //----------------------------------------------------------------------------
  279. STDMETHODIMP CSequentialSorted::RestartPosition( HCHAPTER hChapter )
  280. {
  281. for ( unsigned i = 0; i < _cChild; i++ )
  282. {
  283. _apCursor[i]->FlushCache();
  284. }
  285. _heap.ReInit( 0 );
  286. SCODE sc = CDistributedRowset::RestartPosition( hChapter );
  287. for ( i = 0; i < _cChild; i++ )
  288. {
  289. _apCursor[i]->Next();
  290. }
  291. _heap.ReInit( _cChild );
  292. return sc;
  293. }