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.

306 lines
7.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: Strategy.hxx
  7. //
  8. // Contents: Encapsulates strategy for choosing indexes
  9. //
  10. // History: 03-Nov-94 KyleP Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #pragma once
  14. class CRange
  15. {
  16. public:
  17. inline CRange( PROPID pid );
  18. void SetPid( PROPID pid ) { _pid = pid; }
  19. void SetLowerBound( CStorageVariant const & var )
  20. {
  21. _varLower = var;
  22. if ( !_varLower.IsValid() )
  23. THROW( CException( E_OUTOFMEMORY ) );
  24. }
  25. void SetUpperBound( CStorageVariant const & var )
  26. {
  27. _varUpper = var;
  28. if ( !_varUpper.IsValid() )
  29. THROW( CException( E_OUTOFMEMORY ) );
  30. }
  31. PROPID Pid() const { return _pid; }
  32. CStorageVariant const & LowerBound() const { return _varLower; }
  33. CStorageVariant const & UpperBound() const { return _varUpper; }
  34. BOOL IsValid() { return _fValid; }
  35. void MarkInvalid() { _fValid = FALSE; }
  36. private:
  37. BOOL _fValid;
  38. PROPID _pid;
  39. CStorageVariant _varLower;
  40. CStorageVariant _varUpper;
  41. };
  42. inline CRange::CRange( PROPID pid )
  43. : _fValid( TRUE ),
  44. _pid( pid )
  45. {
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. // Class: CIndexStrategy
  50. //
  51. // Purpose: Helper class for choosing index strategy. Tracks bounds of
  52. // properties used in restrictions.
  53. //
  54. // History: 18-Sep-95 KyleP Added header.
  55. //
  56. //----------------------------------------------------------------------------
  57. class CIndexStrategy
  58. {
  59. public:
  60. CIndexStrategy();
  61. ~CIndexStrategy();
  62. //
  63. // Information input
  64. //
  65. void SetBounds( PROPID pid,
  66. CStorageVariant const & varLower,
  67. CStorageVariant const & varUpper );
  68. void SetLowerBound( PROPID pid, CStorageVariant const & varLower );
  69. void SetUpperBound( PROPID pid, CStorageVariant const & varUpper );
  70. inline void SetLowerBound( PROPID pid, CStorageVariant const & varLower, BOOL fSecondBound );
  71. inline void SetUpperBound( PROPID pid, CStorageVariant const & varUpper, BOOL fSecondBound );
  72. void SetUnknownBounds( PROPID pid = pidInvalid );
  73. void SetContentHelper( CRestriction * pcrst );
  74. inline BOOL SetOrMode();
  75. inline BOOL SetAndMode();
  76. inline void DoneWithBoolean();
  77. //
  78. // Information output
  79. //
  80. CStorageVariant const & LowerBound( PROPID pid ) const;
  81. CStorageVariant const & UpperBound( PROPID pid ) const;
  82. CRestriction * QueryContentRestriction( BOOL fPropertyOnly = FALSE );
  83. BOOL CanUse( PROPID pid, BOOL fAscending ) const;
  84. BOOL GetUsnRange( USN & usnMin, USN & usnMax ) const;
  85. private:
  86. unsigned FindPid( PROPID pid );
  87. enum
  88. {
  89. NoMode,
  90. AndMode,
  91. OrMode,
  92. InvalidMode
  93. } _BooleanMode;
  94. unsigned _cNodes;
  95. unsigned _depth; // Depth below OR (started with AND) or below AND (started with OR)
  96. unsigned _cBounds;
  97. CDynArray<CRange> _aBounds;
  98. CDynStack<CRestriction> _stkContentHelpers;
  99. unsigned _iRangeUsn; // Index of USN range. 0xFFFFFFFF if invalid
  100. };
  101. unsigned const InvalidUsnRange = 0xFFFFFFFF;
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Member: CIndexStrategy::SetOrMode
  105. //
  106. // Synopsis: Indicates an OR node is being processed.
  107. //
  108. // History: 10-Oct-95 KyleP Created.
  109. //
  110. // Notes: The depth is incremented only if a mode switch (AND --> OR)
  111. // occurred. We can handle OR with OR below, and AND with AND
  112. // below.
  113. //
  114. //----------------------------------------------------------------------------
  115. inline BOOL CIndexStrategy::SetOrMode()
  116. {
  117. switch( _BooleanMode )
  118. {
  119. case NoMode:
  120. Win4Assert( 0 == _depth );
  121. break;
  122. case AndMode:
  123. break;
  124. case OrMode:
  125. return FALSE;
  126. default:
  127. Win4Assert( !"Invalid mode" );
  128. }
  129. _BooleanMode = OrMode;
  130. _depth++;
  131. return TRUE;
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // Member: CIndexStrategy::SetAndMode
  136. //
  137. // Synopsis: Indicates an AND node is being processed.
  138. //
  139. // History: 10-Oct-95 KyleP Created.
  140. //
  141. // Notes: The depth is incremented only if a mode switch (OR --> AND)
  142. // occurred. We can handle OR with OR below, and AND with AND
  143. // below.
  144. //
  145. //----------------------------------------------------------------------------
  146. inline BOOL CIndexStrategy::SetAndMode()
  147. {
  148. switch( _BooleanMode )
  149. {
  150. case NoMode:
  151. Win4Assert( 0 == _depth );
  152. break;
  153. case OrMode:
  154. break;
  155. case AndMode:
  156. return FALSE;
  157. default:
  158. Win4Assert( !"Invalid mode" );
  159. }
  160. _BooleanMode = AndMode;
  161. _depth++;
  162. return TRUE;
  163. }
  164. //+---------------------------------------------------------------------------
  165. //
  166. // Member: CIndexStrategy::DoneWithBoolean
  167. //
  168. // Synopsis: Indicates end of processing for a boolean node.
  169. //
  170. // History: 10-Oct-95 KyleP Created.
  171. //
  172. // Notes: The depth is only decremented if we're tracking depth, which
  173. // happens when we've switched boolean modes.
  174. //
  175. //----------------------------------------------------------------------------
  176. inline void CIndexStrategy::DoneWithBoolean()
  177. {
  178. switch( _depth )
  179. {
  180. case 0:
  181. Win4Assert( !"See CNodeXpr::SelectIndexing. This is not possible" );
  182. return;
  183. case 1:
  184. break;
  185. default:
  186. switch( _BooleanMode )
  187. {
  188. case AndMode:
  189. _BooleanMode = OrMode;
  190. break;
  191. case OrMode:
  192. _BooleanMode = AndMode;
  193. break;
  194. default:
  195. Win4Assert( !"Unrecognized mode");
  196. break;
  197. }
  198. break;
  199. }
  200. _depth --;
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Member: CIndexStrategy::SetLowerBound
  205. //
  206. // Synopsis: Set lower bound.
  207. //
  208. // Effects: Same as the other form of SetLowerBound, except this doesn't
  209. // count as the one allowed Set* for a single node. Used for
  210. // bookkeeping.
  211. //
  212. // Arguments: [pid] -- Property Id
  213. // [varLower] -- Lower bound
  214. // [fSecondBound] -- TRUE if this is the second of a pair.
  215. //
  216. // History: 10-Oct-95 KyleP Created.
  217. //
  218. //----------------------------------------------------------------------------
  219. inline void CIndexStrategy::SetLowerBound( PROPID pid,
  220. CStorageVariant const & varLower,
  221. BOOL fSecondBound )
  222. {
  223. SetLowerBound( pid, varLower );
  224. if ( fSecondBound )
  225. _cNodes--;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Member: CIndexStrategy::SetUpperBound
  230. //
  231. // Synopsis: Set upper bound.
  232. //
  233. // Effects: Same as the other form of SetUpperBound, except this doesn't
  234. // count as the one allowed Set* for a single node. Used for
  235. // bookkeeping.
  236. //
  237. // Arguments: [pid] -- Property Id
  238. // [varUpper] -- Upper bound
  239. // [fSecondBound] -- TRUE if this is the second of a pair.
  240. //
  241. // History: 10-Oct-95 KyleP Created.
  242. //
  243. //----------------------------------------------------------------------------
  244. inline void CIndexStrategy::SetUpperBound( PROPID pid,
  245. CStorageVariant const & varUpper,
  246. BOOL fSecondBound )
  247. {
  248. SetUpperBound( pid, varUpper );
  249. if ( fSecondBound )
  250. _cNodes--;
  251. }