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.

939 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: query.cxx
  7. //
  8. // Contents: Class encapsulating all the context for a running
  9. // query, including the query execution context, the
  10. // cached query results, and all cursors over the
  11. // results.
  12. // Dispatches requests to the appropriate subobject.
  13. //
  14. // Classes: CAsyncQuery
  15. // CGetRowsParams
  16. //
  17. // History: 31 May 94 AlanW Created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include <pch.cxx>
  21. #pragma hdrstop
  22. #include <query.hxx>
  23. #include <srequest.hxx>
  24. #include <rowseek.hxx>
  25. #include <tbrowkey.hxx>
  26. #include <oleprop.hxx>
  27. #include "tabledbg.hxx"
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Member: CGetRowsParams::GetRowBuffer, public inline
  31. //
  32. // Synopsis: Return a pointer to the row buffer. If this is the first
  33. // reference, get it from the fixed allocator.
  34. //
  35. // Arguments: - none -
  36. //
  37. // Returns: PBYTE - a pointer to the row buffer.
  38. //
  39. // Notes: We don't put this in query.hxx since we don't want to
  40. // have to refer to PFixedVarAllocator there.
  41. //
  42. //--------------------------------------------------------------------------
  43. PBYTE CGetRowsParams::GetRowBuffer( void )
  44. {
  45. if (0 == _pData)
  46. _pData = _rAllocator.AllocFixed();
  47. return (PBYTE) _pData;
  48. }
  49. PBYTE CGetRowsParams::GetBuffer( ) const
  50. { return _rAllocator.BufferAddr(); }
  51. //+---------------------------------------------------------------------------
  52. //
  53. // Member: CAsyncQuery::CAsyncQuery, public
  54. //
  55. // Synopsis: Creates a locally accessible Query
  56. //
  57. // Arguments: [qopt] - Query optimizer
  58. // [col] - Initial set of columns to return
  59. // [sort] - Initial sort
  60. // [categ] - Categorization specification
  61. // [cCursors] - # of cursors to create
  62. // [aCursors] - array of cursors returned
  63. // [pidremap] - prop ID mapping
  64. // [fEnableNotification] - if TRUE, allow watches
  65. // [pDocStore] - client doc store
  66. // [pEvtComplete] - completion event
  67. //
  68. //----------------------------------------------------------------------------
  69. CAsyncQuery::CAsyncQuery( XQueryOptimizer & qopt,
  70. XColumnSet & col,
  71. XSortSet & sort,
  72. XCategorizationSet &categ,
  73. unsigned cCursors,
  74. ULONG * aCursors,
  75. XInterface<CPidRemapper> & pidremap,
  76. BOOL fEnableNotification,
  77. ICiCDocStore *pDocStore,
  78. CRequestServer * pQuiesce
  79. )
  80. : _fCanDoWorkidToPath( !qopt->IsWorkidUnique() ),
  81. PQuery( ),
  82. _ref( 1 ),
  83. _pidremap( pidremap.Acquire() ),
  84. _Table( col,
  85. sort,
  86. cCursors - 1,
  87. _mutex,
  88. !_fCanDoWorkidToPath,
  89. pQuiesce ),
  90. _cRowsLastAsked (0),
  91. _aCursors( ),
  92. _aCategorize( cCursors - 1 )
  93. {
  94. //
  95. // Get ci manager and translator interfaces
  96. //
  97. ICiManager *pCiManager = 0;
  98. SCODE sc = pDocStore->GetContentIndex( &pCiManager );
  99. if ( FAILED( sc ) )
  100. {
  101. Win4Assert( !"Need to support GetContentIndex interface" );
  102. THROW( CException( sc ) );
  103. }
  104. _xCiManager.Set( pCiManager );
  105. ICiCDocNameToWorkidTranslator *pNameToWidTranslator;
  106. sc = pDocStore->QueryInterface( IID_ICiCDocNameToWorkidTranslator,
  107. (void **) &pNameToWidTranslator );
  108. if ( FAILED( sc ) )
  109. {
  110. Win4Assert( !"Need to support translator QI" );
  111. THROW( CException( sc ) );
  112. }
  113. _xNameToWidTranslator.Set( pNameToWidTranslator );
  114. Win4Assert( 0 != cCursors );
  115. // make a cursor for the main table and each categorization level
  116. for (unsigned cursor = 0; cursor < cCursors; cursor++)
  117. aCursors[cursor] = _CreateRowCursor();
  118. // the last cursor is associated with the main table
  119. _aCursors.Lookup(aCursors[cCursors - 1]).SetSource( &_Table );
  120. if (cCursors > 1)
  121. {
  122. //
  123. // NOTE: pidWorkid is always added to the sort set in the table,
  124. // so it should always be sorted. That's why it's sort count-1
  125. // SPECDEVIATION - if workid was already in the sort, this test
  126. // is incorrect. Who would want to categorize on workid though?
  127. //
  128. if ( ! _Table.IsSorted() ||
  129. cCursors-1 > _Table.GetSortSet()->Count()-1 )
  130. {
  131. // CLEANCODE: Should this check be handled in the categorizers?
  132. // Is it specific to the unique categorization?
  133. tbDebugOut(( DEB_WARN, "Query contains too few sort specs "
  134. "for categorization spec\n" ));
  135. THROW( CException( E_INVALIDARG ) );
  136. }
  137. // this is a categorized table, so set up the categorizers
  138. for ( unsigned cat = 0; cat < (cCursors - 1); cat++ )
  139. {
  140. _aCategorize[cat] = new CCategorize( * (categ->Get(cat)),
  141. cat + 1,
  142. cat ? _aCategorize[cat-1] : 0,
  143. _mutex );
  144. _aCursors.Lookup(aCursors[cat]).SetSource( _aCategorize[cat] );
  145. }
  146. _Table.SetCategorizer(_aCategorize[cCursors - 2]);
  147. // now tell each categorizer what it is categorizing over
  148. for ( cat = 0; cat < (cCursors - 2); cat++ )
  149. _aCategorize[cat]->SetChild( _aCategorize[ cat + 1 ] );
  150. _aCategorize[ cCursors - 2 ]->SetChild( & _Table );
  151. }
  152. // Without the lock, the query can be complete and destructed
  153. // BEFORE the constructor finishes
  154. CLock lock( _mutex );
  155. //
  156. // Since we can be swapping rows, we may need singleton cursor(s)
  157. //
  158. qopt->EnableSingletonCursors();
  159. if ( 0 != pQuiesce )
  160. pQuiesce->SetPQuery( (PQuery *) this );
  161. _QExec.Set( new CQAsyncExecute( qopt, fEnableNotification, _Table, pDocStore ) );
  162. _Table.SetQueryExecute( _QExec.GetPointer() );
  163. ciDebugOut(( DEB_USER1, "Using an asynchronous cursor.\n" ));
  164. END_CONSTRUCTION( CAsyncQuery );
  165. }
  166. //+---------------------------------------------------------------------------
  167. //
  168. // Member: CAsyncQuery::~CAsyncQuery, public
  169. //
  170. // Synopsis: Destroy the query
  171. //
  172. //----------------------------------------------------------------------------
  173. CAsyncQuery::~CAsyncQuery()
  174. {
  175. CLock lock( _mutex );
  176. //Win4Assert( _ref == 0 ); This isn't true when queries are aborted
  177. _Table.ReleaseQueryExecute();
  178. }
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Member: CAsyncQuery::AddRef, public
  182. //
  183. // Synopsis: Reference the query.
  184. //
  185. //--------------------------------------------------------------------------
  186. ULONG CAsyncQuery::AddRef(void)
  187. {
  188. return InterlockedIncrement( &_ref );
  189. }
  190. //+-------------------------------------------------------------------------
  191. //
  192. // Member: CAsyncQuery::Release, public
  193. //
  194. // Synopsis: De-Reference the query.
  195. //
  196. // Effects: If the ref count goes to 0 then the query is deleted.
  197. //
  198. //--------------------------------------------------------------------------
  199. ULONG CAsyncQuery::Release(void)
  200. {
  201. long l = InterlockedDecrement( &_ref );
  202. if ( l <= 0 )
  203. {
  204. tbDebugOut(( DEB_ITRACE, "CAsyncQuery unreferenced. Deleting.\n" ));
  205. delete this;
  206. return 0;
  207. }
  208. return l;
  209. }
  210. //+-------------------------------------------------------------------------
  211. //
  212. // Member: CAsyncQuery::_CreateRowCursor, private
  213. //
  214. // Synopsis: Create a new CTableCursor, return a handle to it.
  215. //
  216. // Arguments: - none -
  217. //
  218. // Returns: ULONG - handle associated with the new cursor. Will
  219. // be zero if the cursor could not be created.
  220. //
  221. // Notes: There needs to be a subsequent call to SetBindings prior
  222. // to any call to GetRows.
  223. //
  224. //--------------------------------------------------------------------------
  225. ULONG CAsyncQuery::_CreateRowCursor( )
  226. {
  227. CTableCursor * pCursor = new CTableCursor;
  228. ULONG hCursor = 0;
  229. _aCursors.Add(pCursor, hCursor);
  230. // By default, make the cursor refer to the real table,
  231. // not categorization
  232. pCursor->SetSource(&_Table);
  233. Win4Assert(hCursor != 0);
  234. return hCursor;
  235. }
  236. //+-------------------------------------------------------------------------
  237. //
  238. // Member: CAsyncQuery::FreeCursor, public
  239. //
  240. // Synopsis: Free a handle to a CTableCursor
  241. //
  242. // Arguments: [hCursor] - handle to the cursor to be freed
  243. //
  244. // Returns: # of cursors left
  245. //
  246. //--------------------------------------------------------------------------
  247. unsigned CAsyncQuery::FreeCursor(
  248. ULONG hCursor )
  249. {
  250. Win4Assert( hCursor != 0 );
  251. _aCursors.Release(hCursor);
  252. return _aCursors.Count();
  253. }
  254. //+-------------------------------------------------------------------------
  255. //
  256. // Member: CAsyncQuery::SetBindings, public
  257. //
  258. // Synopsis: Set column bindings into a cursor
  259. //
  260. // Arguments: [hCursor] - the handle of the cursor to set bindings on
  261. // [cbRowLength] - the width of an output row
  262. // [cols] - a description of column bindings to be set
  263. // [pids] - a PID mapper which maps fake pids in cols to
  264. // column IDs.
  265. //
  266. // Returns: nothing
  267. //
  268. //--------------------------------------------------------------------------
  269. void
  270. CAsyncQuery::SetBindings(
  271. ULONG hCursor,
  272. ULONG cbRowLength,
  273. CTableColumnSet & cols,
  274. CPidMapper & pids )
  275. {
  276. CTableCursor& rCursor = _aCursors.Lookup(hCursor);
  277. if (0 == cols.Count() ||
  278. 0 == cbRowLength || cbRowLength >= USHRT_MAX)
  279. THROW( CException( E_INVALIDARG ));
  280. XPtr<CTableColumnSet> outset(new CTableColumnSet( cols.Count() ));
  281. for (unsigned iCol = 0; iCol < cols.Count(); iCol++)
  282. {
  283. CTableColumn * pCol = cols.Get( iCol );
  284. CFullPropSpec * propspec = pids.Get( pCol->PropId );
  285. //
  286. // Convert the DBID to a PROPID
  287. //
  288. // Win4Assert( iCol+1 == pCol->PropId ); // therefore pids is useless
  289. PROPID prop = _pidremap->NameToReal(propspec);
  290. if ( prop == pidInvalid || _Table.IsColumnInTable(prop) == FALSE )
  291. {
  292. tbDebugOut(( DEB_ERROR, "Column unavailable: prop = 0x%x\n", prop ));
  293. THROW( CException( DB_E_BADCOLUMNID ));
  294. }
  295. if (pCol->IsCompressedCol())
  296. THROW( CException( E_INVALIDARG ));
  297. XPtr<CTableColumn> xpOutcol ( new CTableColumn( prop, pCol->GetStoredType() ) );
  298. if (pCol->IsValueStored())
  299. xpOutcol->SetValueField(pCol->GetStoredType(),
  300. pCol->GetValueOffset(),
  301. pCol->GetValueSize());
  302. Win4Assert( pCol->IsStatusStored() );
  303. xpOutcol->SetStatusField(pCol->GetStatusOffset(),
  304. (USHORT)pCol->GetStatusSize());
  305. if (pCol->IsLengthStored())
  306. xpOutcol->SetLengthField(pCol->GetLengthOffset(),
  307. (USHORT)pCol->GetLengthSize());
  308. outset->Add(xpOutcol, iCol);
  309. }
  310. SCODE sc = rCursor.SetBindings( cbRowLength, outset );
  311. if ( FAILED( sc ) )
  312. THROW( CException( sc ) );
  313. } //SetBindings
  314. //+-------------------------------------------------------------------------
  315. //
  316. // Member: CAsyncQuery::GetRows, public
  317. //
  318. // Synopsis: Retrieve row data for a table cursor
  319. //
  320. // Arguments: [hCursor] - the handle of the cursor to fetch data for
  321. // [rSeekDesc] - row seek operation to be done before fetch
  322. // [rFetchParams] - row fetch parameters and buffer pointers
  323. // [pSeekDescOut] - row seek description for restart
  324. //
  325. // Returns: SCODE - the status of the operation. E_HANDLE
  326. // is returned if hCursor cannot be looked up,
  327. // presumably an internal error.
  328. //
  329. // History: 24 Jan 1995 Alanw Created
  330. //
  331. //--------------------------------------------------------------------------
  332. SCODE
  333. CAsyncQuery::GetRows(
  334. ULONG hCursor,
  335. const CRowSeekDescription & rSeekDesc,
  336. CGetRowsParams& rFetchParams,
  337. XPtr<CRowSeekDescription> & pSeekDescOut)
  338. {
  339. CTableCursor & rCursor = _aCursors.Lookup(hCursor);
  340. rCursor.ValidateBindings();
  341. CTableSource & rSource = rCursor.GetSource();
  342. Win4Assert(rCursor.GetRowWidth() == rFetchParams.GetRowWidth());
  343. return rSeekDesc.GetRows( rCursor,
  344. rSource,
  345. rFetchParams,
  346. pSeekDescOut );
  347. } //GetRows
  348. //+-------------------------------------------------------------------------
  349. //
  350. // Member: CAsyncQuery::RestartPosition, public
  351. //
  352. // Synopsis: Reset fetch position for chapter to the start
  353. //
  354. // Arguments: [hCursor] - the handle of the cursor to restart
  355. // [chapter] - the chapter to restart
  356. //
  357. // Returns: SCODE - the status of the operation.
  358. //
  359. // Notes:
  360. //
  361. // History: 17 Apr 1997 EmilyB Created
  362. //
  363. //--------------------------------------------------------------------------
  364. void
  365. CAsyncQuery::RestartPosition(
  366. ULONG hCursor,
  367. CI_TBL_CHAPT chapter)
  368. {
  369. CTableCursor & rCursor = _aCursors.Lookup(hCursor);
  370. CTableSource & rSource = rCursor.GetSource();
  371. rSource.RestartPosition ( chapter );
  372. }
  373. //+-------------------------------------------------------------------------
  374. //
  375. // Member: CAsyncQuery::RatioFinished, public
  376. //
  377. // Synopsis: Return the completion status as a fraction
  378. //
  379. // Arguments: [hCursor] - the handle of the cursor to check completion for
  380. // [rulDenominator] - on return, denominator of fraction
  381. // [rulNumerator] - on return, numerator of fraction
  382. // [rcRows] - on return, number of rows in cursor
  383. // [rfNewRows] - on return, TRUE if new rows available
  384. //
  385. // Returns: nothing
  386. //
  387. // Notes: A handle of zero can be passed for use with sequential
  388. // cursors to check completion before a handle exists.
  389. //
  390. //--------------------------------------------------------------------------
  391. void CAsyncQuery::RatioFinished(
  392. ULONG hCursor,
  393. DBCOUNTITEM & rulDenominator,
  394. DBCOUNTITEM & rulNumerator,
  395. DBCOUNTITEM & rcRows,
  396. BOOL & rfNewRows
  397. ) {
  398. if (hCursor != 0)
  399. CTableCursor& rCursor = _aCursors.Lookup(hCursor); // For error check
  400. rulDenominator = 1;
  401. rulNumerator = 0;
  402. rfNewRows = FALSE;
  403. unsigned status = QUERY_FILL_STATUS(_Table.Status());
  404. //
  405. // SPECDEVIATION: should do something more meaningful with STAT_ERROR
  406. // RatioFinished should probably fail in this case.
  407. //
  408. if (STAT_DONE == status ||
  409. STAT_ERROR == status ||
  410. STAT_REFRESH == status)
  411. {
  412. rulNumerator = 1;
  413. rcRows = _Table.RowCount();
  414. if (rcRows != _cRowsLastAsked)
  415. {
  416. _cRowsLastAsked = rcRows;
  417. rfNewRows = TRUE;
  418. }
  419. return;
  420. }
  421. _Table.RatioFinished (rulDenominator, rulNumerator, rcRows);
  422. if (rcRows != _cRowsLastAsked)
  423. {
  424. _cRowsLastAsked = rcRows;
  425. rfNewRows = TRUE;
  426. }
  427. Win4Assert( rulDenominator >= rulNumerator );
  428. }
  429. //+-------------------------------------------------------------------------
  430. //
  431. // Member: CAsyncQuery::Compare, public
  432. //
  433. // Synopsis: Return the approximate current position as a fraction
  434. //
  435. // Arguments: [hCursor] - the handle of the cursor to compare bmks from
  436. // [bmkFirst] - First bookmark to compare
  437. // [bmkSecond] - Second bookmark to compare
  438. // [rdwComparison] - on return, comparison value
  439. //
  440. // Returns: nothing
  441. //
  442. //--------------------------------------------------------------------------
  443. void CAsyncQuery::Compare(
  444. ULONG hCursor,
  445. CI_TBL_CHAPT chapt,
  446. CI_TBL_BMK bmkFirst,
  447. CI_TBL_BMK bmkSecond,
  448. DWORD & rdwComparison
  449. ) {
  450. rdwComparison = DBCOMPARE_NOTCOMPARABLE;
  451. CTableCursor& rCursor = _aCursors.Lookup(hCursor);
  452. CTableSource & rSource = rCursor.GetSource();
  453. DBCOUNTITEM ulNum1, ulDen1;
  454. SCODE scRet = rSource.GetApproximatePosition( chapt,
  455. bmkFirst,
  456. &ulNum1,
  457. &ulDen1);
  458. DBCOUNTITEM ulNum2, ulDen2;
  459. if (SUCCEEDED(scRet))
  460. {
  461. scRet = rSource.GetApproximatePosition( chapt,
  462. bmkSecond,
  463. &ulNum2,
  464. &ulDen2);
  465. }
  466. if (SUCCEEDED(scRet))
  467. {
  468. Win4Assert(ulDen1 == ulDen2);
  469. if (ulNum1 < ulNum2)
  470. rdwComparison = DBCOMPARE_LT;
  471. else if (ulNum1 > ulNum2)
  472. rdwComparison = DBCOMPARE_GT;
  473. else // ulNum1 == ulNum2
  474. rdwComparison = DBCOMPARE_EQ;
  475. }
  476. // CLEANCODE - have the source table THROW if errors in GetApproximatePosition
  477. if (scRet != S_OK)
  478. THROW(CException(scRet));
  479. }
  480. //+-------------------------------------------------------------------------
  481. //
  482. // Member: CAsyncQuery::GetApproximatePosition, public
  483. //
  484. // Synopsis: Return the approximate current position as a fraction
  485. //
  486. // Arguments: [hCursor] - the handle of the cursor to retrieve info. from
  487. // [bmk] - bookmark of row to get position of
  488. // [pulNumerator] - on return, numerator of fraction
  489. // [pulDenominator] - on return, denominator of fraction
  490. //
  491. // Returns: nothing
  492. //
  493. //--------------------------------------------------------------------------
  494. void
  495. CAsyncQuery::GetApproximatePosition(
  496. ULONG hCursor,
  497. CI_TBL_CHAPT chapt,
  498. CI_TBL_BMK bmk,
  499. DBCOUNTITEM * pulNumerator,
  500. DBCOUNTITEM * pulDenominator
  501. ) {
  502. CTableCursor& rCursor = _aCursors.Lookup(hCursor);
  503. CTableSource & rSource = rCursor.GetSource();
  504. SCODE scRet = rSource.GetApproximatePosition( chapt,
  505. bmk,
  506. pulNumerator,
  507. pulDenominator);
  508. // CLEANCODE - have the source table THROW if errors in GetApproximatePosition
  509. if (scRet != S_OK)
  510. THROW(CException(scRet));
  511. }
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Member: CAsyncQuery::GetNotifications, private
  515. //
  516. // Synopsis: Retrieves the notification info from the query object
  517. // row data.
  518. //
  519. // Arguments: [rSync] -- notification synchronization info
  520. // [rParams] -- notification data info
  521. //
  522. // Returns: SCODE
  523. //
  524. // History: 10-24-94 dlee created
  525. //
  526. //----------------------------------------------------------------------------
  527. SCODE
  528. CAsyncQuery::GetNotifications(
  529. CNotificationSync & rSync,
  530. DBWATCHNOTIFY & changeType )
  531. {
  532. return _Table.GetNotifications(rSync,changeType);
  533. }
  534. //+-------------------------------------------------------------------------
  535. //
  536. // Member: CAsyncQuery::SetWatchMode
  537. //
  538. // Synopsis: Stub implementation
  539. //
  540. // Arguments: [phRegion] -- handle to watch region
  541. // [mode] -- watch mode
  542. //
  543. // History: May-2-95 BartoszM Created
  544. //
  545. //--------------------------------------------------------------------------
  546. void CAsyncQuery::SetWatchMode (
  547. HWATCHREGION* phRegion,
  548. ULONG mode)
  549. {
  550. if (*phRegion == watchRegionInvalid)
  551. _Table.CreateWatchRegion (mode, phRegion);
  552. else
  553. _Table.ChangeWatchMode (*phRegion, mode);
  554. }
  555. //+-------------------------------------------------------------------------
  556. //
  557. // Member: CAsyncQuery::GetWatchInfo
  558. //
  559. // Synopsis: Stub implementation
  560. //
  561. // Arguments: [hRegion] -- handle to watch region
  562. // [pMode] -- watch mode
  563. // [pChapter] -- chapter
  564. // [pBookmark] -- bookmark
  565. // [pcRows] -- number of rows
  566. //
  567. // History: May-2-95 BartoszM Created
  568. //
  569. //--------------------------------------------------------------------------
  570. void CAsyncQuery::GetWatchInfo (
  571. HWATCHREGION hRegion,
  572. ULONG* pMode,
  573. CI_TBL_CHAPT* pChapter,
  574. CI_TBL_BMK* pBookmark,
  575. DBCOUNTITEM* pcRows)
  576. {
  577. _Table.GetWatchRegionInfo (hRegion, pChapter, pBookmark, (DBROWCOUNT *)pcRows);
  578. }
  579. //+-------------------------------------------------------------------------
  580. //
  581. // Member: CAsyncQuery::ShrinkWatchRegion
  582. //
  583. // Synopsis: Stub implementation
  584. //
  585. // Arguments: [hRegion] -- handle to watch region
  586. // [pChapter] -- chapter
  587. // [pBookmark] -- bookmark
  588. // [cRows] -- number of rows
  589. //
  590. // History: May-2-95 BartoszM Created
  591. //
  592. //--------------------------------------------------------------------------
  593. void CAsyncQuery::ShrinkWatchRegion (
  594. HWATCHREGION hRegion,
  595. CI_TBL_CHAPT chapter,
  596. CI_TBL_BMK bookmark,
  597. LONG cRows )
  598. {
  599. if (cRows == 0)
  600. _Table.DeleteWatchRegion (hRegion);
  601. else
  602. _Table.ShrinkWatchRegion (hRegion, chapter, bookmark, cRows);
  603. }
  604. //+-------------------------------------------------------------------------
  605. //
  606. // Member: CAsyncQuery::Refresh
  607. //
  608. // Synopsis: Stub implementation
  609. //
  610. // Arguments: [] --
  611. //
  612. // History: Arp-4-95 BartoszM Created
  613. //
  614. //--------------------------------------------------------------------------
  615. void CAsyncQuery::Refresh()
  616. {
  617. _Table.Refresh();
  618. }
  619. //+-------------------------------------------------------------------------
  620. //
  621. // Member: CAsyncQuery::GetQueryStatus, public
  622. //
  623. // Synopsis: Return the query status
  624. //
  625. // Arguments: [hCursor] - the handle of the cursor to check completion for
  626. // [rdwStatus] - on return, the query status
  627. //
  628. // Returns: nothing
  629. //
  630. //--------------------------------------------------------------------------
  631. void CAsyncQuery::GetQueryStatus(
  632. ULONG hCursor,
  633. DWORD & rdwStatus)
  634. {
  635. rdwStatus = _Table.Status();
  636. }
  637. //+-------------------------------------------------------------------------
  638. //
  639. // Member: CAsyncQuery::GetQueryStatusEx, public
  640. //
  641. // Synopsis: Return the query status plus bonus information. It's kind
  642. // of an odd assortment of info, but it saves net trips.
  643. //
  644. // Arguments: [hCursor] - handle of the cursor to check completion for
  645. // [rdwStatus] - returns the query status
  646. // [rcFilteredDocuments] - returns # of filtered docs
  647. // [rcDocumentsToFilter] - returns # of docs to filter
  648. // [rdwRatioFinishedDenominator] - ratio finished denom
  649. // [rdwRatioFinishedNumerator] - ratio finished num
  650. // [bmk] - bmk to find
  651. // [riRowBmk] - index of bmk row
  652. // [rcRowsTotal] - # of rows in table
  653. //
  654. // History: Nov-9-96 dlee Created
  655. //
  656. //--------------------------------------------------------------------------
  657. void CAsyncQuery::GetQueryStatusEx(
  658. ULONG hCursor,
  659. DWORD & rdwStatus,
  660. DWORD & rcFilteredDocuments,
  661. DWORD & rcDocumentsToFilter,
  662. DBCOUNTITEM & rdwRatioFinishedDenominator,
  663. DBCOUNTITEM & rdwRatioFinishedNumerator,
  664. CI_TBL_BMK bmk,
  665. DBCOUNTITEM & riRowBmk,
  666. DBCOUNTITEM & rcRowsTotal )
  667. {
  668. rdwStatus = _Table.Status();
  669. CIF_STATE state;
  670. state.cbStruct = sizeof state;
  671. SCODE sc = _xCiManager->GetStatus( &state );
  672. if ( SUCCEEDED( sc ) )
  673. {
  674. rcFilteredDocuments = state.cFilteredDocuments;
  675. rcDocumentsToFilter = state.cDocuments;
  676. }
  677. else
  678. {
  679. ciDebugOut(( DEB_ERROR, "CAsyncQuery::GetQueryStatusEx, get status failed, 0x%x\n", sc ));
  680. rcFilteredDocuments = 0;
  681. rcDocumentsToFilter = 0;
  682. }
  683. DBCOUNTITEM cRows;
  684. BOOL fNewRows;
  685. RatioFinished( hCursor,
  686. rdwRatioFinishedDenominator,
  687. rdwRatioFinishedNumerator,
  688. cRows,
  689. fNewRows );
  690. GetApproximatePosition( hCursor,
  691. 0,
  692. bmk,
  693. & riRowBmk,
  694. & rcRowsTotal );
  695. } //GetQueryStatusEx
  696. //+-------------------------------------------------------------------------
  697. //
  698. // Member: CAsyncQuery::WorkIdToPath
  699. //
  700. // Synopsis: Converts a wid to a path
  701. //
  702. // Arguments: [wid] -- of the file to be translated
  703. // [funnyPath] -- resulting path
  704. //
  705. // History: Jun-1-95 dlee Created
  706. //
  707. //--------------------------------------------------------------------------
  708. void CAsyncQuery::WorkIdToPath( WORKID wid, CFunnyPath & funnyPath )
  709. {
  710. if ( _fCanDoWorkidToPath )
  711. {
  712. ULONG cbBuf = MAX_PATH * sizeof WCHAR; // first guess -- it may be more
  713. XArray<BYTE> xBuf( cbBuf );
  714. CInlineVariant * pVariant = (CInlineVariant *) xBuf.GetPointer();
  715. if (! _Table.WorkIdToPath( wid, *pVariant, cbBuf ) )
  716. {
  717. if ( 0 != cbBuf )
  718. {
  719. BYTE *pb = xBuf.Acquire();
  720. delete [] pb;
  721. cbBuf += sizeof CInlineVariant;
  722. xBuf.Init( cbBuf );
  723. _Table.WorkIdToPath( wid, *pVariant, cbBuf );
  724. }
  725. }
  726. if ( 0 != cbBuf )
  727. {
  728. WCHAR *pwc = (WCHAR *) pVariant->GetVarBuffer();
  729. funnyPath.SetPath( pwc );
  730. }
  731. }
  732. else
  733. {
  734. ICiCDocName *pDocName;
  735. SCODE sc = _xNameToWidTranslator->QueryDocName( &pDocName );
  736. if ( SUCCEEDED( sc ) )
  737. {
  738. XInterface<ICiCDocName> xDocName( pDocName );
  739. sc = _xNameToWidTranslator->WorkIdToDocName( wid,
  740. xDocName.GetPointer() );
  741. if ( SUCCEEDED( sc ) && sc != CI_S_WORKID_DELETED )
  742. {
  743. // PERFFIX: Here we are using two buffers XGrowable and CFunnyPath.
  744. // This can be avoided if xDocName->Get can take in CFunnyPath instead of WCHAR*
  745. XGrowable<WCHAR> xBuf(MAX_PATH);
  746. ULONG cb = xBuf.SizeOf();
  747. sc = xDocName->Get( (BYTE *) xBuf.Get(), &cb );
  748. if ( CI_E_BUFFERTOOSMALL == sc )
  749. {
  750. xBuf.SetSizeInBytes( cb );
  751. sc = xDocName->Get( (BYTE *) xBuf.Get(), &cb );
  752. }
  753. if ( SUCCEEDED( sc ) )
  754. {
  755. funnyPath.SetPath( xBuf.Get() );
  756. }
  757. }
  758. }
  759. }
  760. } //WorkIdToPath
  761. BOOL CAsyncQuery::CanDoWorkIdToPath()
  762. {
  763. return _fCanDoWorkidToPath;
  764. } //CanDoWorkIdToPath
  765. //+-------------------------------------------------------------------------
  766. //
  767. // Member: CAsyncQuery::FetchDeferredValue
  768. //
  769. // Synopsis: Fetch deferred value from property cache
  770. //
  771. // Arguments: [wid] -- Workid.
  772. // [ps] -- Property to be fetched.
  773. // [var] -- Property returned here.
  774. //
  775. // History: Jun-1-95 KyleP Created
  776. //
  777. //--------------------------------------------------------------------------
  778. BOOL CAsyncQuery::FetchDeferredValue(
  779. WORKID wid,
  780. CFullPropSpec const & ps,
  781. PROPVARIANT & var )
  782. {
  783. //
  784. // If using a NULL catalog, assume a file system and go get the value.
  785. // The NULL catalog case is only supported by fsci, anyway, so it's
  786. // ok to do this hack.
  787. //
  788. if ( _fCanDoWorkidToPath )
  789. {
  790. CFunnyPath funnyPath;
  791. WorkIdToPath( wid, funnyPath );
  792. COLEPropManager propMgr;
  793. propMgr.Open( funnyPath );
  794. return propMgr.ReadProperty( ps, var );
  795. }
  796. return _QExec->FetchDeferredValue( wid, ps, var );
  797. } //FetchDeferredValue