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.

443 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995-2000.
  5. //
  6. // File: DisQuery.cxx
  7. //
  8. // Contents: PIInternalQuery for distributed implementation.
  9. //
  10. // Classes: CDistributedQuery
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV, related changes
  14. //
  15. // Notes:
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.cxx>
  19. #pragma hdrstop
  20. #include <coldesc.hxx>
  21. #include <rstprop.hxx>
  22. #include <pidmap.hxx>
  23. #include <cmdprutl.hxx>
  24. #include <proputl.hxx>
  25. #include "disquery.hxx"
  26. #include "seqser.hxx"
  27. #include "seqsort.hxx"
  28. #include "scrlsort.hxx"
  29. //+-------------------------------------------------------------------------
  30. //
  31. // Function: EvalDistributedQuery, public
  32. //
  33. // Synopsis: Simulates bind to IInternalQuery for a ci object store
  34. //
  35. // Arguments: [ppQuery] -- Returns a PIInternalQuery
  36. // [cScope] -- Count of [awcsScope]
  37. // [pdwDepths] -- Array of scope depths
  38. // [awcsScope] -- Array of scopes to query
  39. // [awcsCat] -- Array of overrides for catalog location
  40. // [fVirtualPaths] -- TRUE if [wcsScope] is a virtual scope
  41. // instead of a physical scope.
  42. //
  43. // Returns: SCODE result
  44. //
  45. // History: 08-Feb-96 KyleP Added header
  46. // 08-Feb-96 KyleP Add virtual path support
  47. // 14-May-97 MohamedN hidden core and fs properties
  48. //
  49. // Notes: Scaffolding
  50. //
  51. //--------------------------------------------------------------------------
  52. SCODE EvalDistributedQuery(
  53. PIInternalQuery ** ppQuery,
  54. CGetCmdProps & getCmdProps )
  55. {
  56. *ppQuery = 0;
  57. CDistributedQuery * pQuery = 0;
  58. SCODE sc = S_OK;
  59. TRY
  60. {
  61. ULONG cChildren = getCmdProps.GetCardinality();
  62. pQuery = new CDistributedQuery( cChildren );
  63. for ( unsigned i = 0; i < cChildren ; i++ )
  64. {
  65. PIInternalQuery * pChild = 0;
  66. CDbProperties idbProps;
  67. getCmdProps.PopulateDbProps( &idbProps, i );
  68. SCODE s = EvalQuery(&pChild, idbProps );
  69. if ( FAILED( s ) )
  70. {
  71. vqDebugOut(( DEB_ERROR,
  72. "Error 0x%x getting PIInternalQuery for %ws\n",
  73. s, getCmdProps.GetCatalog(i) ));
  74. THROW( CException( s ) );
  75. }
  76. pQuery->Add( pChild, i );
  77. }
  78. }
  79. CATCH( CException, e )
  80. {
  81. if ( 0 != pQuery )
  82. {
  83. pQuery->Release();
  84. pQuery = 0;
  85. }
  86. sc = GetOleError( e );
  87. }
  88. END_CATCH
  89. *ppQuery = pQuery;
  90. return sc;
  91. }
  92. //+-------------------------------------------------------------------------
  93. //
  94. // Member: CDistributedQuery::CDistributedQuery, public
  95. //
  96. // Synopsis: Constructor.
  97. //
  98. // Arguments: [cChild] -- Number of child scopes.
  99. //
  100. // History: 07-Jun-95 KyleP Created
  101. //
  102. //--------------------------------------------------------------------------
  103. CDistributedQuery::CDistributedQuery( unsigned cChild )
  104. : _aChild( cChild ),
  105. PIInternalQuery( 1 )
  106. {
  107. RtlZeroMemory( _aChild.GetPointer(), cChild * sizeof(PIInternalQuery *) );
  108. }
  109. //+-------------------------------------------------------------------------
  110. //
  111. // Member: CDistributedQuery::~CDistributedQuery, public
  112. //
  113. // Synopsis: Destructor.
  114. //
  115. // History: 07-Jun-95 KyleP Created
  116. //
  117. //--------------------------------------------------------------------------
  118. CDistributedQuery::~CDistributedQuery()
  119. {
  120. for ( unsigned i = 0; i < _aChild.Count(); i++ )
  121. {
  122. if ( _aChild[i] )
  123. {
  124. _aChild[i]->Release();
  125. }
  126. }
  127. }
  128. //+-------------------------------------------------------------------------
  129. //
  130. // Member: CDistributedQuery::QueryInterface, public
  131. //
  132. // Arguments: [ifid] -- Interface id
  133. // [ppiuk] -- Interface return pointer
  134. //
  135. // Returns: Error. No rebind from this class is supported.
  136. //
  137. // History: 01-Oct-92 KyleP Created
  138. //
  139. //--------------------------------------------------------------------------
  140. STDMETHODIMP CDistributedQuery::QueryInterface( REFIID ifid, void ** ppiuk )
  141. {
  142. if ( ifid == IID_IUnknown )
  143. {
  144. AddRef();
  145. *ppiuk = (void *)((IUnknown *)this);
  146. return S_OK;
  147. }
  148. else
  149. {
  150. *ppiuk = 0;
  151. return E_NOINTERFACE;
  152. }
  153. }
  154. //+-------------------------------------------------------------------------
  155. //
  156. // Member: CDistributedQuery::AddRef, public
  157. //
  158. // Synopsis: Reference the virtual table.
  159. //
  160. // History: 01-Oct-92 KyleP Created
  161. //
  162. //--------------------------------------------------------------------------
  163. STDMETHODIMP_(ULONG) CDistributedQuery::AddRef(void)
  164. {
  165. return InterlockedIncrement( (long *)&_ref );
  166. }
  167. //+-------------------------------------------------------------------------
  168. //
  169. // Member: CDistributedQuery::Release, public
  170. //
  171. // Synopsis: De-Reference the virtual table.
  172. //
  173. // Effects: If the ref count goes to 0 then the table is deleted.
  174. //
  175. // History: 01-Oct-92 KyleP Created
  176. //
  177. //--------------------------------------------------------------------------
  178. STDMETHODIMP_(ULONG) CDistributedQuery::Release(void)
  179. {
  180. long l = InterlockedDecrement( (long *)&_ref );
  181. if ( l <= 0 )
  182. {
  183. delete this;
  184. return 0;
  185. }
  186. return l;
  187. }
  188. //+-------------------------------------------------------------------------
  189. //
  190. // Member: CDistributedQuery::Execute, public
  191. //
  192. // Synopsis: Executes a query. Helper method for ICommand::Execute.
  193. //
  194. // Arguments: [pUnkOuter] -- Outer unknown
  195. // [pRestriction] -- Query restriction
  196. // [pidmap] -- pid mapper for output, sort, category columns
  197. // [rColumns] -- Output columns in IRowset
  198. // [rSort] -- Initial sort
  199. // [Props] -- Rowset properties
  200. // [rCateg] -- Categorization specification
  201. // [cRowsets] -- # of rowsets
  202. // [ppUnknowns] -- IUnknown pointers returned here
  203. // [aAccessors] -- Bag of accessors which rowsets need to inherit
  204. //
  205. // Returns: Error code
  206. //
  207. // History: 07-Jun-95 KyleP Created
  208. //
  209. // Notes:
  210. //
  211. //--------------------------------------------------------------------------
  212. void CDistributedQuery::Execute( IUnknown * pUnkOuter,
  213. RESTRICTION * pRestriction,
  214. CPidMapperWithNames & pidmap,
  215. CColumnSet & rColumns,
  216. CSortSet & rSort,
  217. XPtr<CMRowsetProps> & xProps,
  218. CCategorizationSet & rCateg,
  219. ULONG cRowsets,
  220. IUnknown ** ppUnknowns,
  221. CAccessorBag & aAccessors,
  222. IUnknown * pCreatorUnk )
  223. {
  224. SCODE sc = S_OK;
  225. unsigned iChild = 0;
  226. IRowset ** aRowset = 0;
  227. TRY
  228. {
  229. if ( (xProps->GetPropertyFlags() & eLocatable) != 0 )
  230. {
  231. //
  232. // If no sort was specified for scrollable query, then add one
  233. // based on workid.
  234. //
  235. if ( 0 == rSort.Count() )
  236. {
  237. // This whole process could be streamlined if it was
  238. // possible to query bindings *before* ExecQuery was
  239. // called. Then we could potentially find an existing
  240. // column suitable for sorting.
  241. //
  242. // Setup sort.
  243. //
  244. GUID guidQuery = DBQUERYGUID;
  245. CFullPropSpec propWorkId( guidQuery, DISPID_QUERY_WORKID );
  246. SSortKey SortKey( pidmap.NameToPid(propWorkId), QUERY_SORTASCEND );
  247. rSort.Add( SortKey, 0 );
  248. }
  249. }
  250. //
  251. // Since we need to bind to sort columns in order to compare rows, all
  252. // sort columns must be in the binding set.
  253. // At the same time, create a CSort from the CSortSet for use by the
  254. // rowset implementation class.
  255. //
  256. unsigned cOriginalColumns = rColumns.Count();
  257. CSort SortDup;
  258. if ( 0 != rSort.Count() )
  259. {
  260. for ( unsigned i = 0; i < rSort.Count(); i++ )
  261. {
  262. PROPID prop = rSort.Get( i ).pidColumn;
  263. CSortKey sk( *pidmap.PidToName(prop),
  264. rSort.Get(i).dwOrder,
  265. rSort.Get(i).locale );
  266. SortDup.Add(sk, i);
  267. for ( unsigned j = 0; j < rColumns.Count(); j++ )
  268. {
  269. if ( rColumns.Get(j) == prop )
  270. break;
  271. }
  272. if ( j == rColumns.Count() )
  273. {
  274. rColumns.Add( prop, j );
  275. }
  276. }
  277. }
  278. //
  279. // This array is passed to distributed rowset.
  280. //
  281. Win4Assert(1 == cRowsets ); // allocs below only account for 1 cRowset
  282. XArray<IUnknown *> xUnknowns( _aChild.Count() );
  283. aRowset = new IRowset * [_aChild.Count()];
  284. //
  285. // Create the children.
  286. //
  287. CAccessorBag aEmpty(this);
  288. for ( iChild = 0; iChild < _aChild.Count(); iChild++ )
  289. {
  290. //
  291. // If we're going non-sequential, go all the way.
  292. //
  293. XPtr<CMRowsetProps> xPropsTemp( new CMRowsetProps( xProps.GetReference() ) );
  294. if ( (xPropsTemp->GetPropertyFlags() & eLocatable) != 0 )
  295. xPropsTemp->SetImpliedProperties( IID_IRowsetScroll, cRowsets );
  296. // For distributed rowsets, always set holdrows to true
  297. xPropsTemp->SetPropertyFlags( eHoldRows );
  298. _aChild[iChild]->Execute( 0, // children are private and aren't aggregated
  299. pRestriction,
  300. pidmap,
  301. rColumns,
  302. rSort,
  303. xPropsTemp,
  304. rCateg,
  305. cRowsets,
  306. &xUnknowns[iChild],
  307. aEmpty, // these guys don't really need aAccessors
  308. pCreatorUnk );
  309. if ( FAILED(sc) )
  310. {
  311. vqDebugOut(( DEB_ERROR, "CDistributedQuery: Error 0x%x calling Execute for child %u\n",
  312. sc, iChild ));
  313. THROW( CException(sc) );
  314. }
  315. // get IRowset pointer
  316. xUnknowns[iChild]->QueryInterface(IID_IRowset, (void **) &aRowset[iChild]);
  317. xUnknowns[iChild]->Release(); // release extra ref
  318. }
  319. //
  320. // First case: sequential cursors
  321. //
  322. IUnknown * pIUnkInner = 0;
  323. XInterface<IUnknown> xIUnkInner(pIUnkInner);
  324. IRowset * pTemp;
  325. if ( 0 == (xProps->GetPropertyFlags() & eLocatable) )
  326. {
  327. if ( 0 != rSort.Count() )
  328. {
  329. pTemp = (IRowset *)
  330. new CSequentialSorted( pUnkOuter,
  331. (IUnknown **)xIUnkInner.GetQIPointer(),
  332. aRowset,
  333. _aChild.Count(),
  334. xProps.GetReference(),
  335. cOriginalColumns,
  336. SortDup,
  337. aAccessors );
  338. }
  339. else
  340. {
  341. pTemp = (IRowset *)
  342. new CSequentialSerial( pUnkOuter,
  343. (IUnknown **)xIUnkInner.GetQIPointer(),
  344. aRowset,
  345. _aChild.Count(),
  346. xProps.GetReference(),
  347. cOriginalColumns,
  348. aAccessors );
  349. }
  350. }
  351. //
  352. // Other case: Scrollable
  353. //
  354. else
  355. {
  356. Win4Assert( 0 != rSort.Count() );
  357. pTemp = (IRowset *)
  358. new CScrollableSorted( pUnkOuter,
  359. (IUnknown **)xIUnkInner.GetQIPointer(),
  360. (IRowsetScroll **)aRowset,
  361. _aChild.Count(),
  362. xProps.GetReference(),
  363. cOriginalColumns,
  364. SortDup,
  365. aAccessors );
  366. }
  367. *ppUnknowns = xIUnkInner.Acquire();
  368. Win4Assert(*ppUnknowns);
  369. }
  370. CATCH( CException, e )
  371. {
  372. sc = e.GetErrorCode();
  373. for ( ; iChild > 0; iChild-- )
  374. aRowset[iChild-1]->Release();
  375. delete [] aRowset;
  376. RETHROW( );
  377. }
  378. END_CATCH
  379. }