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.

445 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: seqquery.cxx
  7. //
  8. // Contents: Declarations of classes which implement sequential ICursor
  9. // and related OLE DB interfaces over file stores.
  10. //
  11. // Classes: CSeqQuery - container of table/query for a set of seq cursors
  12. //
  13. // History: 09-Jan-95 DwightKr Created
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include <tblalloc.hxx>
  19. #include <rowseek.hxx>
  20. #include <tblvarnt.hxx>
  21. #include "tabledbg.hxx"
  22. #include "seqquery.hxx"
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Class: CSeqQuery
  26. //
  27. // Purpose: Encapsulates a sequential query execution context, and PID
  28. // mapper for use by a row cursor.
  29. //
  30. // Arguments: [qopt] - Query optimizer
  31. // [col] - Initial set of columns to return
  32. // [pulCursors] - cursor returned
  33. // [pidremap] - prop ID mapping
  34. // [pDocStore] - client doc store
  35. //
  36. // History: 09 Jan 95 DwightKr Created
  37. //
  38. //----------------------------------------------------------------------------
  39. CSeqQuery::CSeqQuery( XQueryOptimizer & qopt,
  40. XColumnSet & col,
  41. ULONG *pulCursor,
  42. XInterface<CPidRemapper> & pidremap,
  43. ICiCDocStore *pDocStore
  44. )
  45. : PQuery( ),
  46. _ref( 1 ),
  47. _pidremap( pidremap.Acquire() ),
  48. _QExec( 0 )
  49. {
  50. //
  51. // Get ci manager and translator interfaces
  52. //
  53. ICiManager *pCiManager = 0;
  54. SCODE sc = pDocStore->GetContentIndex( &pCiManager );
  55. if ( FAILED( sc ) )
  56. {
  57. Win4Assert( !"Need to support GetContentIndex interface" );
  58. THROW( CException( sc ) );
  59. }
  60. _xCiManager.Set( pCiManager );
  61. ICiCDocNameToWorkidTranslator *pNameToWidTranslator;
  62. sc = pDocStore->QueryInterface( IID_ICiCDocNameToWorkidTranslator,
  63. (void **) &pNameToWidTranslator );
  64. if ( FAILED( sc ) )
  65. {
  66. Win4Assert( !"Need to support translator QI" );
  67. THROW( CException( sc ) );
  68. }
  69. _xNameToWidTranslator.Set( pNameToWidTranslator );
  70. _QExec.Set( new CQSeqExecute( qopt ) );
  71. *pulCursor = _CreateRowCursor();
  72. ciDebugOut(( DEB_USER1, "Using a sequential cursor.\n" ));
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Member: CSeqQuery::AddRef, public
  77. //
  78. // Synopsis: Reference the query.
  79. //
  80. // History: 19-Jan-95 DwightKr Created
  81. //
  82. //----------------------------------------------------------------------------
  83. ULONG CSeqQuery::AddRef(void)
  84. {
  85. return InterlockedIncrement( &_ref );
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: CSeqQuery::Release, public
  90. //
  91. // Synopsis: De-Reference the query.
  92. //
  93. // Effects: If the ref count goes to 0 then the query is deleted.
  94. //
  95. // History: 19-Jan-95 DwightKr Created
  96. //
  97. //----------------------------------------------------------------------------
  98. ULONG CSeqQuery::Release(void)
  99. {
  100. long l = InterlockedDecrement( &_ref );
  101. if ( l <= 0 )
  102. {
  103. tbDebugOut(( DEB_ITRACE, "CSeqQuery unreferenced. Deleting.\n" ));
  104. delete this;
  105. return 0;
  106. }
  107. return l;
  108. }
  109. //+-------------------------------------------------------------------------
  110. //
  111. // Member: CSeqQuery::FetchDeferredValue
  112. //
  113. // Synopsis: Fetch value from property cache
  114. //
  115. // Arguments: [wid] -- Workid.
  116. // [ps] -- Property to be fetched.
  117. // [var] -- Property returned here.
  118. //
  119. // History: Jun-1-95 KyleP Created
  120. //
  121. //--------------------------------------------------------------------------
  122. BOOL CSeqQuery::FetchDeferredValue( WORKID wid,
  123. CFullPropSpec const & ps,
  124. PROPVARIANT & var )
  125. {
  126. return _QExec->FetchDeferredValue( wid, ps, var );
  127. }
  128. //
  129. // Methods supporting IRowset
  130. //
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Member: CSeqQuery::SetBindings, public
  134. //
  135. // Synopsis: Set column bindings into a cursor
  136. //
  137. // Arguments: [hCursor] - the handle of the cursor to set bindings on
  138. // [cbRowLength] - the width of an output row
  139. // [cols] - a description of column bindings to be set
  140. // [pids] - a PID mapper which maps fake pids in cols to
  141. // column IDs.
  142. //
  143. // Returns: nothing - failures are thrown. E_FAIL
  144. // is thrown if hCursor cannot be looked up,
  145. // presumably an internal error.
  146. //
  147. // History: 19-Jan-95 DwightKr Created
  148. //
  149. //----------------------------------------------------------------------------
  150. void CSeqQuery::SetBindings(
  151. ULONG hCursor,
  152. ULONG cbRowLength,
  153. CTableColumnSet & cols,
  154. CPidMapper & pids )
  155. {
  156. _VerifyHandle(hCursor);
  157. if (0 == cols.Count() ||
  158. 0 == cbRowLength || cbRowLength >= USHRT_MAX)
  159. THROW( CException( E_INVALIDARG ));
  160. XPtr<CTableColumnSet> outset(new CTableColumnSet( cols.Count() ));
  161. for (unsigned iCol = 0; iCol < cols.Count(); iCol++)
  162. {
  163. CTableColumn * pCol = cols.Get( iCol );
  164. CFullPropSpec * propspec = pids.Get( pCol->PropId );
  165. //
  166. // Convert the DBID to a PROPID
  167. //
  168. // Win4Assert( iCol+1 == pCol->PropId ); // Therefore pids is useless
  169. PROPID prop = _pidremap->NameToReal(propspec);
  170. if ( prop == pidInvalid )
  171. THROW( CException( DB_E_BADCOLUMNID ));
  172. if (pCol->IsCompressedCol())
  173. THROW( CException( E_INVALIDARG ));
  174. XPtr<CTableColumn> xpOutcol ( new CTableColumn( prop, pCol->GetStoredType() ) );
  175. if (pCol->IsValueStored())
  176. xpOutcol->SetValueField(pCol->GetStoredType(),
  177. pCol->GetValueOffset(),
  178. pCol->GetValueSize());
  179. Win4Assert( pCol->IsStatusStored() );
  180. xpOutcol->SetStatusField(pCol->GetStatusOffset(),
  181. (USHORT)pCol->GetStatusSize());
  182. if (pCol->IsLengthStored())
  183. xpOutcol->SetLengthField(pCol->GetLengthOffset(),
  184. (USHORT)pCol->GetLengthSize());
  185. outset->Add(xpOutcol, iCol);
  186. }
  187. SCODE sc = _cursor.SetBindings( cbRowLength, outset );
  188. if ( FAILED( sc ) )
  189. THROW( CException( sc ) );
  190. } //SetBindings
  191. //+-------------------------------------------------------------------------
  192. //
  193. // Member: CSeqQuery::RatioFinished, public
  194. //
  195. // Synopsis: Return the completion status as a fraction
  196. //
  197. // Arguments: [hCursor] - the handle of the cursor to check completion for
  198. // [rulDenominator] - on return, denominator of fraction
  199. // [rulNumerator] - on return, numerator of fraction
  200. // [rcRows] - on return, number of rows in cursor
  201. // [rfNewRows] - on return, TRUE if new rows available
  202. //
  203. // Returns: nothing
  204. //
  205. // Notes: A value of 0 for hCursor is allowed so that completion
  206. // can be checked before a handle exists.
  207. //
  208. //--------------------------------------------------------------------------
  209. void CSeqQuery::RatioFinished(
  210. ULONG hCursor,
  211. DBCOUNTITEM & rulDenominator,
  212. DBCOUNTITEM & rulNumerator,
  213. DBCOUNTITEM & rcRows,
  214. BOOL & rfNewRows
  215. )
  216. {
  217. if ( 0 != hCursor )
  218. _VerifyHandle(hCursor);
  219. rulDenominator = 1;
  220. rulNumerator = 1;
  221. rcRows = 0; // we don't know how many there are...
  222. rfNewRows = FALSE;
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // Member: CSeqQuery::GetRows, public
  227. //
  228. // Synopsis: Retrieve row data for a table cursor
  229. //
  230. // Arguments: [hCursor] - the handle of the cursor to fetch data for
  231. // [rSeekDesc] - row seek operation to be done before fetch
  232. // [rFetchParams] - row fetch parameters and buffer pointers
  233. //
  234. // Returns: SCODE - the status of the operation. E_FAIL
  235. // is thrown if hCursor cannot be looked up,
  236. // presumably an internal error.
  237. //
  238. // History: 19-Jan-95 DwightKr Created
  239. //
  240. //----------------------------------------------------------------------------
  241. SCODE CSeqQuery::GetRows(
  242. ULONG hCursor,
  243. const CRowSeekDescription& rSeekDesc,
  244. CGetRowsParams& rFetchParams,
  245. XPtr<CRowSeekDescription>& pSeekDescOut
  246. )
  247. {
  248. _VerifyHandle( hCursor );
  249. if ( ! rSeekDesc.IsCurrentRowSeek() )
  250. THROW( CException( E_FAIL ) );
  251. CRowSeekNext* pRowSeek = (CRowSeekNext*) &rSeekDesc;
  252. unsigned cRowsToSkip = pRowSeek->GetSkip();
  253. _cursor.ValidateBindings();
  254. SCODE scRet = _QExec->GetRows( _cursor.GetBindings(),
  255. cRowsToSkip,
  256. rFetchParams );
  257. if (FAILED(scRet))
  258. {
  259. tbDebugOut(( DEB_WARN, "CSeqQuery::GetRows got sc=%x\n",
  260. scRet ));
  261. }
  262. if (DB_S_BLOCKLIMITEDROWS == scRet)
  263. pSeekDescOut.Set( new CRowSeekNext(pRowSeek->GetChapter(), 0) );
  264. return scRet;
  265. } //GetRows
  266. //+-------------------------------------------------------------------------
  267. //
  268. // Member: CSeqQuery::GetQueryStatus, public
  269. //
  270. // Synopsis: Return the query status
  271. //
  272. // Arguments: [hCursor] - the handle of the cursor to check completion for
  273. // [rdwStatus] - on return, the query status
  274. //
  275. // Returns: nothing
  276. //
  277. //--------------------------------------------------------------------------
  278. void CSeqQuery::GetQueryStatus(
  279. ULONG hCursor,
  280. DWORD & rdwStatus)
  281. {
  282. _VerifyHandle( hCursor );
  283. rdwStatus = _QExec->Status();
  284. }
  285. //+-------------------------------------------------------------------------
  286. //
  287. // Member: CSeqQuery::GetQueryStatusEx, public
  288. //
  289. // Synopsis: Return the query status plus bonus information. It's kind
  290. // of an odd assortment of info, but it saves net trips.
  291. //
  292. // Arguments: [hCursor] - handle of the cursor to check completion for
  293. // [rdwStatus] - returns the query status
  294. // [rcFilteredDocuments] - returns # of filtered docs
  295. // [rcDocumentsToFilter] - returns # of docs to filter
  296. // [rdwRatioFinishedDenominator] - ratio finished denom
  297. // [rdwRatioFinishedNumerator] - ratio finished num
  298. // [bmk] - bmk to find
  299. // [riRowBmk] - index of bmk row
  300. // [rcRowsTotal] - # of rows in table
  301. //
  302. // History: Nov-9-96 dlee Created
  303. //
  304. //--------------------------------------------------------------------------
  305. void CSeqQuery::GetQueryStatusEx(
  306. ULONG hCursor,
  307. DWORD & rdwStatus,
  308. DWORD & rcFilteredDocuments,
  309. DWORD & rcDocumentsToFilter,
  310. DBCOUNTITEM & rdwRatioFinishedDenominator,
  311. DBCOUNTITEM & rdwRatioFinishedNumerator,
  312. CI_TBL_BMK bmk,
  313. DBCOUNTITEM & riRowBmk,
  314. DBCOUNTITEM & rcRowsTotal )
  315. {
  316. GetQueryStatus( hCursor, rdwStatus );
  317. CIF_STATE state;
  318. state.cbStruct = sizeof state;
  319. SCODE sc = _xCiManager->GetStatus( &state );
  320. if ( SUCCEEDED( sc ) )
  321. {
  322. rcFilteredDocuments = state.cFilteredDocuments;
  323. rcDocumentsToFilter = state.cDocuments;
  324. }
  325. else
  326. {
  327. ciDebugOut(( DEB_ERROR,
  328. "CSeqQuery::GetQueryStatusEx, get status failed, 0x%x\n", sc ));
  329. rcFilteredDocuments = 0;
  330. rcDocumentsToFilter = 0;
  331. }
  332. // sequential query -- it's done
  333. rdwRatioFinishedDenominator = 1;
  334. rdwRatioFinishedNumerator = 1;
  335. // sequential query -- this info isn't available
  336. riRowBmk = 0;
  337. rcRowsTotal = 0;
  338. } //GetQueryStatusEx
  339. //+-------------------------------------------------------------------------
  340. //
  341. // Member: CAsyncQuery::WorkIdToPath
  342. //
  343. // Synopsis: Converts a wid to a path
  344. //
  345. // Arguments: [wid] -- of the file to be translated
  346. // [funnyPath] -- resulting path
  347. //
  348. // History: Oct-5-96 dlee Created
  349. //
  350. //--------------------------------------------------------------------------
  351. void CSeqQuery::WorkIdToPath(
  352. WORKID wid,
  353. CFunnyPath & funnyPath )
  354. {
  355. ICiCDocName *pDocName;
  356. SCODE sc = _xNameToWidTranslator->QueryDocName( &pDocName );
  357. if ( SUCCEEDED( sc ) )
  358. {
  359. XInterface<ICiCDocName> xDocName( pDocName );
  360. sc = _xNameToWidTranslator->WorkIdToDocName( wid,
  361. xDocName.GetPointer() );
  362. if ( SUCCEEDED( sc ) && sc != CI_S_WORKID_DELETED )
  363. {
  364. // PERFFIX: Here we are using two buffers XGrowable and
  365. // CFunnyPath. This can be avoided if xDocName->Get can take
  366. // in CFunnyPath instead of WCHAR*
  367. XGrowable<WCHAR> xBuf(MAX_PATH);
  368. ULONG cb = xBuf.SizeOf();
  369. sc = xDocName->Get( (BYTE *) xBuf.Get(), &cb );
  370. if ( CI_E_BUFFERTOOSMALL == sc )
  371. {
  372. xBuf.SetSizeInBytes( cb );
  373. sc = xDocName->Get( (BYTE *) xBuf.Get(), &cb );
  374. }
  375. if ( SUCCEEDED( sc ) )
  376. funnyPath.SetPath( xBuf.Get() );
  377. }
  378. }
  379. } //WorkIdToPath