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.

424 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 2000.
  5. //
  6. // File: Parsexpr.cxx
  7. //
  8. // Contents: Converts OLE-DB boolean expression into a restriction
  9. //
  10. // Functions: CParseCommandTree::ParseExpression
  11. //
  12. // History: 31 May 95 AlanW Created from parse.cxx
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <coldesc.hxx>
  18. #include <pidmap.hxx>
  19. #include <parstree.hxx>
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Method: CParseCommandTree::ParseExpression, private
  23. //
  24. // Synopsis: Convert an OLE-DB boolean expression into a CRestriction
  25. //
  26. // Arguments: [pdbt] -- CDbCmdTreeNode to convert
  27. //
  28. // Returns: A pointer to the CRestriction which will resolve [pdbt]
  29. //
  30. // History: 31 May 95 AlanW Created
  31. //
  32. // Notes:
  33. //
  34. //----------------------------------------------------------------------------
  35. CRestriction * CParseCommandTree::ParseExpression( CDbCmdTreeNode * pdbt )
  36. {
  37. CheckRecursionLimit();
  38. XRestriction prst;
  39. CNodeRestriction * pnrst;
  40. unsigned cres;
  41. //
  42. // The weight is retrieved from pdbt and set into prst at the end
  43. // of the switch statement.
  44. //
  45. switch ( pdbt->GetCommandType() )
  46. {
  47. case DBOP_not:
  48. {
  49. VerifyValueType(pdbt, DBVALUEKIND_I4);
  50. CheckOperatorArity(pdbt, 1);
  51. XRestriction pTemp( ParseExpression( pdbt->GetFirstChild() ) );
  52. prst.Set( new CNotRestriction( pTemp.GetPointer() ) );
  53. vqDebugOut((DEB_PARSE, "NOT node with weight of %d\n", ((CDbNotRestriction *)pdbt)->GetWeight()));
  54. pTemp.Acquire();
  55. break;
  56. }
  57. case DBOP_and:
  58. case DBOP_or:
  59. {
  60. VerifyValueType(pdbt, DBVALUEKIND_I4);
  61. cres = CheckOperatorArity(pdbt, -2);
  62. DWORD nt = (pdbt->GetCommandType() == DBOP_and) ?
  63. RTAnd : RTOr;
  64. pnrst = new CNodeRestriction( nt, cres );
  65. prst.Set( pnrst );
  66. vqDebugOut(( DEB_PARSE,
  67. "ParseExpression: %s node, %d restrictions, %d weight\n",
  68. (nt == RTAnd) ? "AND" : "OR", cres, ((CDbBooleanNodeRestriction *)pdbt)->GetWeight() ));
  69. for ( CDbCmdTreeNode *pChild = pdbt->GetFirstChild();
  70. cres;
  71. cres--, pChild = pChild->GetNextSibling() )
  72. {
  73. XRestriction pTemp( ParseExpression( pChild ) );
  74. pnrst->AddChild( pTemp.GetPointer() );
  75. pTemp.Acquire();
  76. }
  77. break;
  78. }
  79. case DBOP_content_vector_or:
  80. {
  81. // NOTE: We permit vector-or nodes with only one operand simply
  82. // for client convenience.
  83. //
  84. cres = CheckOperatorArity(pdbt, -1);
  85. VerifyValueType(pdbt, DBVALUEKIND_CONTENTVECTOR);
  86. CDbVectorRestriction * pdbVector = (CDbVectorRestriction *) pdbt;
  87. ULONG RankMethod = pdbVector->RankMethod();
  88. if ( RankMethod > VECTOR_RANK_JACCARD )
  89. SetError( pdbt, E_INVALIDARG );
  90. pnrst = new CVectorRestriction( RankMethod, cres );
  91. prst.Set( pnrst );
  92. vqDebugOut(( DEB_PARSE,
  93. "ParseExpression: VECTOR node, %d restrictions, "
  94. "RankMethod %lu, Weight %d\n", cres, RankMethod, ((CDbVectorRestriction *)pdbt)->GetWeight() ));
  95. //
  96. // Ordering is important in the vector and must be preserved.
  97. //
  98. unsigned iWeight = 0;
  99. for ( CDbCmdTreeNode *pChild = pdbt->GetFirstChild();
  100. cres;
  101. cres--, pChild = pChild->GetNextSibling(), iWeight++ )
  102. {
  103. XRestriction pTemp( ParseExpression( pChild ) );
  104. //
  105. // We should be able to get weights for all the nodes.
  106. //
  107. pTemp->SetWeight( pChild->GetWeight() );
  108. pnrst->AddChild( pTemp.GetPointer() );
  109. pTemp.Acquire();
  110. }
  111. break;
  112. }
  113. case DBOP_equal:
  114. case DBOP_not_equal:
  115. case DBOP_less:
  116. case DBOP_less_equal:
  117. case DBOP_greater:
  118. case DBOP_greater_equal:
  119. case DBOP_equal_any:
  120. case DBOP_not_equal_any:
  121. case DBOP_less_any:
  122. case DBOP_less_equal_any:
  123. case DBOP_greater_any:
  124. case DBOP_greater_equal_any:
  125. case DBOP_equal_all:
  126. case DBOP_not_equal_all:
  127. case DBOP_less_all:
  128. case DBOP_less_equal_all:
  129. case DBOP_greater_all:
  130. case DBOP_greater_equal_all:
  131. case DBOP_anybits:
  132. case DBOP_allbits:
  133. case DBOP_anybits_any:
  134. case DBOP_allbits_any:
  135. case DBOP_anybits_all:
  136. case DBOP_allbits_all:
  137. {
  138. CheckOperatorArity(pdbt, 2); // exactly two operands
  139. VerifyValueType( pdbt, DBVALUEKIND_I4 );
  140. CDbCmdTreeNode * pProp = pdbt->GetFirstChild();
  141. CDbCmdTreeNode * pValue = pProp->GetNextSibling();
  142. if ( ! pProp->IsColumnName() )
  143. SetError( pProp );
  144. CFullPropSpec Prop;
  145. GetColumnPropSpec( pProp, Prop );
  146. XPtr<CStorageVariant> xValue( new CStorageVariant );
  147. if ( 0 == xValue.GetPointer() )
  148. {
  149. THROW( CException(E_OUTOFMEMORY) );
  150. }
  151. GetValue( pValue, xValue.GetReference() );
  152. //
  153. // compute relation from query tree operator
  154. //
  155. int Relation = 0;
  156. int fAnyOrAll = 0;
  157. switch (pdbt->GetCommandType())
  158. {
  159. case DBOP_equal_any:
  160. fAnyOrAll |= PRAny;
  161. case DBOP_equal_all:
  162. fAnyOrAll |= PRAll;
  163. case DBOP_equal:
  164. Relation = PREQ; break;
  165. case DBOP_not_equal_any:
  166. fAnyOrAll |= PRAny;
  167. case DBOP_not_equal_all:
  168. fAnyOrAll |= PRAll;
  169. case DBOP_not_equal:
  170. Relation = PRNE; break;
  171. case DBOP_less_any:
  172. fAnyOrAll |= PRAny;
  173. case DBOP_less_all:
  174. fAnyOrAll |= PRAll;
  175. case DBOP_less:
  176. Relation = PRLT; break;
  177. case DBOP_less_equal_any:
  178. fAnyOrAll |= PRAny;
  179. case DBOP_less_equal_all:
  180. fAnyOrAll |= PRAll;
  181. case DBOP_less_equal:
  182. Relation = PRLE; break;
  183. case DBOP_greater_any:
  184. fAnyOrAll |= PRAny;
  185. case DBOP_greater_all:
  186. fAnyOrAll |= PRAll;
  187. case DBOP_greater:
  188. Relation = PRGT; break;
  189. case DBOP_greater_equal_any:
  190. fAnyOrAll |= PRAny;
  191. case DBOP_greater_equal_all:
  192. fAnyOrAll |= PRAll;
  193. case DBOP_greater_equal:
  194. Relation = PRGE; break;
  195. case DBOP_anybits_any:
  196. fAnyOrAll |= PRAny;
  197. case DBOP_anybits_all:
  198. fAnyOrAll |= PRAll;
  199. case DBOP_anybits:
  200. Relation = PRSomeBits; break;
  201. case DBOP_allbits_any:
  202. fAnyOrAll |= PRAny;
  203. case DBOP_allbits_all:
  204. fAnyOrAll |= PRAll;
  205. case DBOP_allbits:
  206. Relation = PRAllBits; break;
  207. }
  208. if (fAnyOrAll & PRAny)
  209. Relation |= PRAny;
  210. else if (fAnyOrAll & PRAll)
  211. Relation |= PRAll;
  212. prst.Set( new CPropertyRestriction( Relation, Prop, xValue.GetReference() ) );
  213. vqDebugOut((DEB_PARSE, "Relational Property node with weight %d\n", ((CDbPropertyRestriction *)pdbt)->GetWeight() ));
  214. break;
  215. }
  216. case DBOP_like:
  217. {
  218. CheckOperatorArity(pdbt, 2); // exactly two operands
  219. VerifyValueType(pdbt, DBVALUEKIND_LIKE);
  220. CDbPropertyRestriction * pInputRst = (CDbPropertyRestriction *)pdbt;
  221. if ( ! pInputRst->IsCIDialect() )
  222. SetError( pdbt );
  223. CDbCmdTreeNode * pProp = pdbt->GetFirstChild();
  224. CDbCmdTreeNode * pValue = pProp->GetNextSibling();
  225. if ( ! pProp->IsColumnName() )
  226. SetError( pProp );
  227. CFullPropSpec Prop;
  228. GetColumnPropSpec( pProp, Prop );
  229. XPtr<CStorageVariant> xValue(new CStorageVariant);
  230. if ( 0 == xValue.GetPointer() )
  231. {
  232. THROW( CException(E_OUTOFMEMORY) );
  233. }
  234. GetValue( pValue, xValue.GetReference() );
  235. prst.Set( new CPropertyRestriction( PRRE, Prop, xValue.GetReference() ) );
  236. vqDebugOut((DEB_PARSE, "Reg Expr node with weight of %d\n", ((CDbPropertyRestriction *)pdbt)->GetWeight() ));
  237. break;
  238. }
  239. case DBOP_content:
  240. case DBOP_content_freetext:
  241. case DBOP_content_proximity:
  242. prst.Set( ParseContentExpression( pdbt ) );
  243. break;
  244. default:
  245. vqDebugOut(( DEB_ERROR, "Unhandled expression type %d\n",
  246. pdbt->GetCommandType() ));
  247. Win4Assert( !"Unhandled expression type" );
  248. SetError( pdbt, E_INVALIDARG );
  249. break;
  250. }
  251. prst->SetWeight(pdbt->GetWeight());
  252. return( prst.Acquire() );
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // Method: CParseCommandTree::ParseContentExpression, private
  257. //
  258. // Synopsis: Convert an OLE-DB boolean expression with content restrictions
  259. // into a CRestriction. Like ParseExpression, but each node
  260. // must be content.
  261. //
  262. //
  263. // Arguments: [pdbt] -- CDbCmdTreeNode to convert
  264. //
  265. // Returns: A pointer to the CRestriction which will resolve [pdbt]
  266. //
  267. // History: 31 May 95 AlanW Created
  268. //
  269. //----------------------------------------------------------------------------
  270. CRestriction * CParseCommandTree::ParseContentExpression(
  271. CDbCmdTreeNode * pdbt )
  272. {
  273. CheckRecursionLimit();
  274. XRestriction prst;
  275. CNodeRestriction * pnrst;
  276. unsigned cres;
  277. switch ( pdbt->GetCommandType() )
  278. {
  279. case DBOP_content_proximity:
  280. {
  281. VerifyValueType(pdbt, DBVALUEKIND_CONTENTPROXIMITY);
  282. cres = CheckOperatorArity(pdbt, -2);
  283. pnrst = new CNodeRestriction( RTProximity, cres );
  284. prst.Set( pnrst );
  285. vqDebugOut(( DEB_PARSE,
  286. "ParseContentExpression: Proximity node, %d restrictions, weight %d\n",
  287. cres, ((CDbProximityNodeRestriction *)pdbt)->GetWeight() ));
  288. for ( CDbCmdTreeNode *pChild = pdbt->GetFirstChild();
  289. cres;
  290. cres--, pChild = pChild->GetNextSibling() )
  291. {
  292. XRestriction pTemp( ParseExpression( pChild ) );
  293. pnrst->AddChild( pTemp.GetPointer() );
  294. pTemp.Acquire();
  295. }
  296. break;
  297. }
  298. case DBOP_content:
  299. {
  300. VerifyValueType(pdbt, DBVALUEKIND_CONTENT);
  301. cres = CheckOperatorArity(pdbt, 1);
  302. CDbContentRestriction *pInputRst = (CDbContentRestriction *)pdbt;
  303. CFullPropSpec Prop;
  304. GetColumnPropSpec( pdbt->GetFirstChild(), Prop );
  305. XRestriction pCRst ( new CContentRestriction (
  306. pInputRst->GetPhrase(),
  307. Prop,
  308. pInputRst->GenerateMethod(),
  309. pInputRst->GetLocale()
  310. ) );
  311. prst.Set( pCRst.Acquire() );
  312. vqDebugOut((DEB_PARSE, "Content node with weight %d\n", pInputRst->GetWeight() ));
  313. break;
  314. }
  315. case DBOP_content_freetext:
  316. {
  317. VerifyValueType(pdbt, DBVALUEKIND_CONTENT);
  318. cres = CheckOperatorArity(pdbt, 1);
  319. CDbNatLangRestriction *pInputRst = (CDbNatLangRestriction *)pdbt;
  320. CFullPropSpec Prop;
  321. GetColumnPropSpec( pdbt->GetFirstChild(), Prop );
  322. XRestriction pCRst ( new CNatLanguageRestriction (
  323. pInputRst->GetPhrase(),
  324. Prop,
  325. pInputRst->GetLocale()
  326. ) );
  327. prst.Set( pCRst.Acquire() );
  328. vqDebugOut((DEB_PARSE, "Freetext node with weight %d\n", pInputRst->GetWeight() ));
  329. break;
  330. }
  331. default:
  332. vqDebugOut(( DEB_ERROR, "Unhandled expression type %d\n", pdbt->GetCommandType() ));
  333. Win4Assert( !"Unhandled expression type" );
  334. SetError( pdbt, E_INVALIDARG );
  335. break;
  336. }
  337. prst->SetWeight(pdbt->GetWeight());
  338. return( prst.Acquire() );
  339. }