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.

1394 lines
35 KiB

  1. //***************************************************************************
  2. //
  3. // SQL_1.CPP
  4. //
  5. // Level 1 Syntax SQL Parser
  6. //
  7. // Implements the syntax described in SQL_1.BNF. This translates the input
  8. // into an RPN stream of tokens.
  9. //
  10. // 21-Jun-96 Created.
  11. //
  12. //***************************************************************************
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <genlex.h>
  16. #include <sqllex.h>
  17. #include <sql_1.h>
  18. //#define trace(x) printf x
  19. #define trace(x)
  20. static DWORD TranslateIntrinsic(LPWSTR pFuncName)
  21. {
  22. if (_wcsicmp(pFuncName, L"UPPER") == 0)
  23. return SQL_LEVEL_1_TOKEN::IFUNC_UPPER;
  24. if (_wcsicmp(pFuncName, L"LOWER") == 0)
  25. return SQL_LEVEL_1_TOKEN::IFUNC_LOWER;
  26. return SQL_LEVEL_1_TOKEN::IFUNC_NONE;
  27. }
  28. SQL1_Parser::SQL1_Parser(CGenLexSource *pSrc)
  29. {
  30. m_pLexer = new CGenLexer(Sql_1_LexTable, pSrc);
  31. m_nLine = 0;
  32. m_pTokenText = 0;
  33. m_nCurrentToken = 0;
  34. // Semantic transfer variables.
  35. // ============================
  36. m_nRelOp = 0;
  37. VariantInit(&m_vTypedConst);
  38. m_dwPropFunction = 0;
  39. m_dwConstFunction = 0;
  40. m_pIdent = 0;
  41. m_bConstIsStrNumeric = FALSE;
  42. m_pExpression = new SQL_LEVEL_1_RPN_EXPRESSION;
  43. }
  44. SQL1_Parser::~SQL1_Parser()
  45. {
  46. VariantClear(&m_vTypedConst);
  47. delete m_pIdent;
  48. delete m_pLexer;
  49. delete m_pExpression;
  50. }
  51. int SQL1_Parser::GetQueryClass(
  52. LPWSTR pDestBuf,
  53. int nBufLen
  54. )
  55. {
  56. // Scan until 'FROM' and then get the class name.
  57. // ==============================================
  58. for (;;)
  59. {
  60. m_nCurrentToken = m_pLexer->NextToken();
  61. if (m_nCurrentToken == SQL_1_TOK_EOF)
  62. {
  63. m_pLexer->Reset();
  64. return FAILED;
  65. }
  66. if (_wcsicmp(m_pLexer->GetTokenText(), L"from") == 0)
  67. {
  68. m_nCurrentToken = m_pLexer->NextToken();
  69. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  70. {
  71. m_pLexer->Reset();
  72. return FAILED;
  73. }
  74. // If here, we have the class name.
  75. // ================================
  76. if (wcslen(m_pLexer->GetTokenText()) >= (size_t)nBufLen)
  77. {
  78. m_pLexer->Reset();
  79. return BUFFER_TOO_SMALL;
  80. }
  81. wcscpy(pDestBuf, m_pLexer->GetTokenText());
  82. break;
  83. }
  84. }
  85. // Reset the scanner.
  86. // ==================
  87. m_pLexer->Reset();
  88. return SUCCESS;
  89. }
  90. //
  91. // NOTE: the caller must delete the output expression.
  92. //
  93. int SQL1_Parser::Parse(SQL_LEVEL_1_RPN_EXPRESSION **pOutput)
  94. {
  95. *pOutput = 0;
  96. int nRes = parse();
  97. if (nRes)
  98. return nRes;
  99. *pOutput = m_pExpression;
  100. m_pExpression = 0;
  101. return SUCCESS;
  102. }
  103. LPSTR ToAnsi(LPWSTR Src)
  104. {
  105. static char buf[256];
  106. WideCharToMultiByte(CP_ACP, NULL, Src, -1, buf, 256, NULL, NULL);
  107. return buf;
  108. }
  109. //***************************************************************************
  110. //
  111. // Next()
  112. //
  113. // Advances to the next token and recognizes keywords, etc.
  114. //
  115. //***************************************************************************
  116. BOOL SQL1_Parser::Next()
  117. {
  118. m_nCurrentToken = m_pLexer->NextToken();
  119. if (m_nCurrentToken == SQL_1_TOK_ERROR)
  120. return FALSE;
  121. m_nLine = m_pLexer->GetLineNum();
  122. m_pTokenText = m_pLexer->GetTokenText();
  123. if (m_nCurrentToken == SQL_1_TOK_EOF)
  124. m_pTokenText = L"<end of file>";
  125. // Keyword check.
  126. // ==============
  127. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  128. {
  129. if (_wcsicmp(m_pTokenText, L"select") == 0)
  130. m_nCurrentToken = SQL_1_TOK_SELECT;
  131. else if (_wcsicmp(m_pTokenText, L"from") == 0)
  132. m_nCurrentToken = SQL_1_TOK_FROM;
  133. else if (_wcsicmp(m_pTokenText, L"where") == 0)
  134. m_nCurrentToken = SQL_1_TOK_WHERE;
  135. else if (_wcsicmp(m_pTokenText, L"like") == 0)
  136. m_nCurrentToken = SQL_1_TOK_LIKE;
  137. else if (_wcsicmp(m_pTokenText, L"or") == 0)
  138. m_nCurrentToken = SQL_1_TOK_OR;
  139. else if (_wcsicmp(m_pTokenText, L"and") == 0)
  140. m_nCurrentToken = SQL_1_TOK_AND;
  141. else if (_wcsicmp(m_pTokenText, L"not") == 0)
  142. m_nCurrentToken = SQL_1_TOK_NOT;
  143. else if (_wcsicmp(m_pTokenText, L"IS") == 0)
  144. m_nCurrentToken = SQL_1_TOK_IS;
  145. else if (_wcsicmp(m_pTokenText, L"NULL") == 0)
  146. m_nCurrentToken = SQL_1_TOK_NULL;
  147. else if (_wcsicmp(m_pTokenText, L"TRUE") == 0)
  148. {
  149. m_nCurrentToken = SQL_1_TOK_INT;
  150. m_pTokenText = L"65535";
  151. }
  152. else if (_wcsicmp(m_pTokenText, L"FALSE") == 0)
  153. {
  154. m_nCurrentToken = SQL_1_TOK_INT;
  155. m_pTokenText = L"0";
  156. }
  157. }
  158. return TRUE;
  159. }
  160. //***************************************************************************
  161. //
  162. // <parse> ::= SELECT <prop_list> FROM <classname> WHERE <expr>;
  163. //
  164. //***************************************************************************
  165. // ok
  166. int SQL1_Parser::parse()
  167. {
  168. int nRes;
  169. // SELECT
  170. // ======
  171. if (!Next())
  172. return LEXICAL_ERROR;
  173. if (m_nCurrentToken != SQL_1_TOK_SELECT)
  174. return SYNTAX_ERROR;
  175. if (!Next())
  176. return LEXICAL_ERROR;
  177. // <prop_list>
  178. // ===========
  179. if (nRes = prop_list())
  180. return nRes;
  181. // FROM
  182. // ====
  183. if (m_nCurrentToken != SQL_1_TOK_FROM)
  184. return SYNTAX_ERROR;
  185. if (!Next())
  186. return LEXICAL_ERROR;
  187. // <classname>
  188. // ===========
  189. if (nRes = class_name())
  190. return nRes;
  191. // WHERE clause.
  192. // =============
  193. return opt_where();
  194. }
  195. //***************************************************************************
  196. //
  197. // <opt_where> ::= WHERE <expr>;
  198. // <opt_where> ::= <>;
  199. //
  200. //***************************************************************************
  201. int SQL1_Parser::opt_where()
  202. {
  203. int nRes;
  204. if (m_nCurrentToken == SQL_1_TOK_EOF)
  205. {
  206. trace(("No WHERE clause\n"));
  207. return SUCCESS;
  208. }
  209. if (m_nCurrentToken != SQL_1_TOK_WHERE)
  210. return SYNTAX_ERROR;
  211. if (!Next())
  212. return LEXICAL_ERROR;
  213. // <expr>
  214. // ======
  215. if (nRes = expr())
  216. return nRes;
  217. // Verify that the current token is SQL_1_TOK_EOF.
  218. // ===============================================
  219. if (m_nCurrentToken != SQL_1_TOK_EOF)
  220. return SYNTAX_ERROR;
  221. return SUCCESS;
  222. }
  223. //***************************************************************************
  224. //
  225. // <prop_list> ::= <property_name> <prop_list_2>;
  226. //
  227. //***************************************************************************
  228. int SQL1_Parser::prop_list()
  229. {
  230. int nRes;
  231. if (m_nCurrentToken != SQL_1_TOK_ASTERISK &&
  232. m_nCurrentToken != SQL_1_TOK_IDENT)
  233. return SYNTAX_ERROR;
  234. if (nRes = property_name())
  235. return nRes;
  236. if (!Next())
  237. return LEXICAL_ERROR;
  238. return prop_list_2();
  239. }
  240. //***************************************************************************
  241. //
  242. // <prop_list_2> ::= COMMA <prop_list>;
  243. // <prop_list_2> ::= <>;
  244. //
  245. //***************************************************************************
  246. int SQL1_Parser::prop_list_2()
  247. {
  248. if (m_nCurrentToken == SQL_1_TOK_COMMA)
  249. {
  250. if (!Next())
  251. return LEXICAL_ERROR;
  252. return prop_list();
  253. }
  254. return SUCCESS;
  255. }
  256. //***************************************************************************
  257. //
  258. // <property_name> ::= PROPERTY_NAME_STRING;
  259. // <property_name> ::= ASTERISK;
  260. //
  261. //***************************************************************************
  262. int SQL1_Parser::property_name()
  263. {
  264. if (m_nCurrentToken == SQL_1_TOK_ASTERISK)
  265. {
  266. trace(("Asterisk\n"));
  267. m_pExpression->nNumberOfProperties = 0;
  268. // This signals 'all properties' to the evaluator
  269. return SUCCESS;
  270. }
  271. // Else a property name.
  272. // =====================
  273. trace(("Property name %S\n", m_pTokenText));
  274. m_pExpression->AddProperty(m_pTokenText);
  275. return SUCCESS;
  276. }
  277. //***************************************************************************
  278. //
  279. // <classname> ::= CLASS_NAME_STRING;
  280. //
  281. //***************************************************************************
  282. int SQL1_Parser::class_name()
  283. {
  284. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  285. return SYNTAX_ERROR;
  286. trace(("Class name is %S\n", m_pTokenText));
  287. m_pExpression->bsClassName = SysAllocString(m_pTokenText);
  288. if (!Next())
  289. return LEXICAL_ERROR;
  290. return SUCCESS;
  291. }
  292. //***************************************************************************
  293. //
  294. // <expr> ::= <term> <expr2>;
  295. //
  296. //***************************************************************************
  297. int SQL1_Parser::expr()
  298. {
  299. int nRes;
  300. if (nRes = term())
  301. return nRes;
  302. if (nRes = expr2())
  303. return nRes;
  304. return SUCCESS;
  305. }
  306. //***************************************************************************
  307. //
  308. // <expr2> ::= OR <term> <expr2>;
  309. // <expr2> ::= <>;
  310. //
  311. // Entry: Assumes token OR already current.
  312. // Exit: Advances a token
  313. //
  314. //***************************************************************************
  315. int SQL1_Parser::expr2()
  316. {
  317. int nRes;
  318. while (1)
  319. {
  320. if (m_nCurrentToken == SQL_1_TOK_OR)
  321. {
  322. trace(("Token OR\n"));
  323. if (!Next())
  324. return LEXICAL_ERROR;
  325. if (nRes = term())
  326. return nRes;
  327. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  328. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  329. m_pExpression->AddToken(pNewTok);
  330. }
  331. else break;
  332. }
  333. return SUCCESS;
  334. }
  335. //***************************************************************************
  336. //
  337. // <term> ::= <simple_expr> <term2>;
  338. //
  339. //***************************************************************************
  340. int SQL1_Parser::term()
  341. {
  342. int nRes;
  343. if (nRes = simple_expr())
  344. return nRes;
  345. if (nRes = term2())
  346. return nRes;
  347. return SUCCESS;
  348. }
  349. //***************************************************************************
  350. //
  351. // <term2> ::= AND <simple_expr> <term2>;
  352. // <term2> ::= <>;
  353. //
  354. //***************************************************************************
  355. int SQL1_Parser::term2()
  356. {
  357. int nRes;
  358. while (1)
  359. {
  360. if (m_nCurrentToken == SQL_1_TOK_AND)
  361. {
  362. trace(("Token AND\n"));
  363. if (!Next())
  364. return LEXICAL_ERROR;
  365. if (nRes = simple_expr())
  366. return nRes;
  367. // Add the AND token.
  368. // ==================
  369. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  370. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  371. m_pExpression->AddToken(pNewTok);
  372. }
  373. else break;
  374. }
  375. return SUCCESS;
  376. }
  377. //***************************************************************************
  378. //
  379. // <simple_expr> ::= NOT <expr>;
  380. // <simple_expr> ::= OPEN_PAREN <expr> CLOSE_PAREN;
  381. // <simple_expr> ::= IDENTIFIER <leading_ident_expr> <finalize>;
  382. // <simple_expr> ::= VARIANT <rel_operator> <trailing_prop_expr> <finalize>;
  383. //
  384. //***************************************************************************
  385. // ok
  386. int SQL1_Parser::simple_expr()
  387. {
  388. int nRes;
  389. // NOT <expr>
  390. // ==========
  391. if (m_nCurrentToken == SQL_1_TOK_NOT)
  392. {
  393. trace(("Operator NOT\n"));
  394. if (!Next())
  395. return LEXICAL_ERROR;
  396. if (nRes = simple_expr())
  397. return nRes;
  398. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  399. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
  400. m_pExpression->AddToken(pNewTok);
  401. return SUCCESS;
  402. }
  403. // OPEN_PAREN <expr> CLOSE_PAREN
  404. // =============================
  405. else if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  406. {
  407. trace(("Open Paren: Entering subexpression\n"));
  408. if (!Next())
  409. return LEXICAL_ERROR;
  410. if (expr())
  411. return SYNTAX_ERROR;
  412. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  413. return SYNTAX_ERROR;
  414. trace(("Close paren: Exiting subexpression\n"));
  415. if (!Next())
  416. return LEXICAL_ERROR;
  417. return SUCCESS;
  418. }
  419. // IDENTIFIER <leading_ident_expr> <finalize>
  420. // ==========================================
  421. else if (m_nCurrentToken == SQL_1_TOK_IDENT)
  422. {
  423. trace((" Identifier <%S>\n", m_pTokenText));
  424. m_pIdent = new wchar_t[wcslen(m_pTokenText) + 1];
  425. if ( !m_pIdent )
  426. {
  427. return FAILED;
  428. }
  429. wcscpy(m_pIdent, m_pTokenText);
  430. if (!Next())
  431. return LEXICAL_ERROR;
  432. if (nRes = leading_ident_expr())
  433. return SYNTAX_ERROR;
  434. return finalize();
  435. }
  436. // <typed_constant> <rel_operator> <trailing_prop_expr> <finalize>
  437. // ======================================================
  438. else if (m_nCurrentToken == SQL_1_TOK_INT ||
  439. m_nCurrentToken == SQL_1_TOK_REAL ||
  440. m_nCurrentToken == SQL_1_TOK_QSTRING
  441. )
  442. {
  443. if (nRes = typed_constant())
  444. return nRes;
  445. if (nRes = rel_operator())
  446. return nRes;
  447. if (nRes = trailing_prop_expr())
  448. return nRes;
  449. return finalize();
  450. }
  451. return SYNTAX_ERROR;
  452. }
  453. //***************************************************************************
  454. //
  455. // <trailing_prop_expr> ::= IDENTIFIER <trailing_prop_expr2>;
  456. //
  457. //***************************************************************************
  458. // ok
  459. int SQL1_Parser::trailing_prop_expr()
  460. {
  461. if (m_nCurrentToken != SQL_1_TOK_IDENT)
  462. return SYNTAX_ERROR;
  463. m_pIdent = new wchar_t[wcslen(m_pTokenText) + 1];
  464. if ( !m_pIdent )
  465. {
  466. return FAILED;
  467. }
  468. wcscpy(m_pIdent, m_pTokenText);
  469. if (!Next())
  470. return LEXICAL_ERROR;
  471. return trailing_prop_expr2();
  472. }
  473. //***************************************************************************
  474. //
  475. // <trailing_prop_expr2> ::= OPEN_PAREN IDENTIFIER CLOSE_PAREN;
  476. // <trailing_prop_expr2> ::= <>;
  477. //
  478. //***************************************************************************
  479. // ok
  480. int SQL1_Parser::trailing_prop_expr2()
  481. {
  482. if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  483. {
  484. if (!Next())
  485. return LEXICAL_ERROR;
  486. // If we got to this point, the string pointed to by m_pIdent
  487. // was an intrinsic function and not a property name, and we
  488. // are about to get the property name, so we have to translate
  489. // the function name to its correct code before overwriting it.
  490. // ============================================================
  491. trace(("Translating intrinsic function %S\n", m_pIdent));
  492. m_dwPropFunction = TranslateIntrinsic(m_pIdent);
  493. delete m_pIdent;
  494. m_pIdent = new wchar_t[wcslen(m_pTokenText) + 1];
  495. if ( !m_pIdent )
  496. {
  497. return FAILED;
  498. }
  499. wcscpy(m_pIdent, m_pTokenText);
  500. if (!Next())
  501. return LEXICAL_ERROR;
  502. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  503. return SYNTAX_ERROR;
  504. if (!Next())
  505. return LEXICAL_ERROR;
  506. }
  507. trace(("Property name is %S\n", m_pIdent));
  508. return SUCCESS;
  509. }
  510. //***************************************************************************
  511. //
  512. // <leading_ident_expr> ::= OPEN_PAREN <unknown_func_expr>;
  513. // <leading_ident_expr> ::= <comp_operator> <trailing_const_expr>;
  514. // <leading_ident_expr> ::= <equiv_operator> <trailing_or_null>;
  515. // <leading_ident_expr> ::= <is_operator> NULL;
  516. //
  517. //***************************************************************************
  518. // ok
  519. int SQL1_Parser::leading_ident_expr()
  520. {
  521. int nRes;
  522. if (m_nCurrentToken == SQL_1_TOK_OPEN_PAREN)
  523. {
  524. if (!Next())
  525. return LEXICAL_ERROR;
  526. return unknown_func_expr();
  527. }
  528. if (SUCCESS == comp_operator())
  529. {
  530. return trailing_const_expr();
  531. }
  532. else if(SUCCESS == equiv_operator())
  533. return trailing_or_null();
  534. nRes = is_operator();
  535. if(nRes != SUCCESS)
  536. return nRes;
  537. if (m_nCurrentToken != SQL_1_TOK_NULL)
  538. return LEXICAL_ERROR;
  539. if (Next())
  540. return SUCCESS;
  541. else
  542. return LEXICAL_ERROR;
  543. }
  544. //***************************************************************************
  545. //
  546. // <unknown_func_expr> ::= IDENTIFIER CLOSE_PAREN
  547. // <rel_operator> <trailing_const_expr>;
  548. //
  549. // <unknown_func_expr> ::= <typed_constant> CLOSE_PAREN
  550. // <rel_operator> <trailing_prop_expr>;
  551. //
  552. //***************************************************************************
  553. // ok
  554. int SQL1_Parser::unknown_func_expr()
  555. {
  556. int nRes;
  557. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  558. {
  559. m_dwPropFunction = TranslateIntrinsic(m_pIdent);
  560. delete m_pIdent;
  561. m_pIdent = new wchar_t[wcslen(m_pTokenText) + 1];
  562. if ( !m_pIdent )
  563. {
  564. return FAILED;
  565. }
  566. wcscpy(m_pIdent, m_pTokenText);
  567. if (!Next())
  568. return LEXICAL_ERROR;
  569. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  570. return SYNTAX_ERROR;
  571. if (!Next())
  572. return LEXICAL_ERROR;
  573. if (nRes = rel_operator())
  574. return nRes;
  575. return trailing_const_expr();
  576. }
  577. // Else the other production.
  578. // ==========================
  579. if (nRes = typed_constant())
  580. return nRes;
  581. // If here, we know that the leading ident was
  582. // an intrinsic function.
  583. // ===========================================
  584. m_dwConstFunction = TranslateIntrinsic(m_pIdent);
  585. delete m_pIdent;
  586. m_pIdent = 0;
  587. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  588. return SYNTAX_ERROR;
  589. if (!Next())
  590. return LEXICAL_ERROR;
  591. if (nRes = rel_operator())
  592. return nRes;
  593. return trailing_prop_expr();
  594. }
  595. //***************************************************************************
  596. //
  597. // <trailing_or_null> ::= NULL;
  598. // <trailing_or_null> ::= <trailing_const_expr>;
  599. //
  600. //***************************************************************************
  601. int SQL1_Parser::trailing_or_null()
  602. {
  603. if (m_nCurrentToken == SQL_1_TOK_NULL)
  604. {
  605. if (!Next())
  606. return LEXICAL_ERROR;
  607. else
  608. {
  609. V_VT(&m_vTypedConst) = VT_NULL;
  610. return SUCCESS;
  611. }
  612. }
  613. return trailing_const_expr();
  614. }
  615. //***************************************************************************
  616. //
  617. // <trailing_const_expr> ::= IDENTIFIER OPEN_PAREN
  618. // <typed_constant> CLOSE_PAREN;
  619. // <trailing_const_expr> ::= <typed_constant>;
  620. //
  621. //***************************************************************************
  622. // ok
  623. int SQL1_Parser::trailing_const_expr()
  624. {
  625. int nRes;
  626. if (m_nCurrentToken == SQL_1_TOK_IDENT)
  627. {
  628. trace(("Function applied to typed const = %S\n", m_pTokenText));
  629. m_dwConstFunction = TranslateIntrinsic(m_pTokenText);
  630. if (!Next())
  631. return LEXICAL_ERROR;
  632. if (m_nCurrentToken != SQL_1_TOK_OPEN_PAREN)
  633. return SYNTAX_ERROR;
  634. if (!Next())
  635. return LEXICAL_ERROR;
  636. if (nRes = typed_constant())
  637. return nRes;
  638. if (m_nCurrentToken != SQL_1_TOK_CLOSE_PAREN)
  639. return SYNTAX_ERROR;
  640. if (!Next())
  641. return LEXICAL_ERROR;
  642. return SUCCESS;
  643. }
  644. return typed_constant();
  645. }
  646. //***************************************************************************
  647. //
  648. // <finalize> ::= <>;
  649. //
  650. // This composes the SQL_LEVEL_1_TOKEN for a simple relational expression,
  651. // complete with any associated intrinsic functions. All of the other
  652. // parse functions help isolate the terms of the expression, but only
  653. // this function builds the token.
  654. //
  655. // To build the token, the following member variables are used:
  656. // m_pPropName
  657. // m_vTypedConst
  658. // m_dwPropFunction
  659. // m_dwConstFunction
  660. // m_nRelOp;
  661. //
  662. // After the token is built, these are cleared/deallocated as appropriate.
  663. // No tokens are consumed and the input is not advanced.
  664. //
  665. //***************************************************************************
  666. int SQL1_Parser::finalize()
  667. {
  668. HRESULT hr;
  669. // At this point, we have all the info needed for a token.
  670. // =======================================================
  671. SQL_LEVEL_1_TOKEN *pNewTok = new SQL_LEVEL_1_TOKEN;
  672. if ( pNewTok == NULL )
  673. {
  674. return FAILED;
  675. }
  676. pNewTok->nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION;
  677. pNewTok->pPropertyName = SysAllocString(m_pIdent);
  678. pNewTok->nOperator = m_nRelOp;
  679. VariantInit(&pNewTok->vConstValue);
  680. hr = VariantCopy(&pNewTok->vConstValue, &m_vTypedConst);
  681. if ( FAILED( hr ) )
  682. {
  683. throw WBEM_E_OUT_OF_MEMORY;
  684. }
  685. pNewTok->dwPropertyFunction = m_dwPropFunction;
  686. pNewTok->dwConstFunction = m_dwConstFunction;
  687. pNewTok->bConstIsStrNumeric = m_bConstIsStrNumeric;
  688. m_pExpression->AddToken(pNewTok);
  689. // Cleanup.
  690. // ========
  691. VariantClear(&m_vTypedConst);
  692. delete m_pIdent;
  693. m_pIdent = 0;
  694. m_nRelOp = 0;
  695. m_dwPropFunction = 0;
  696. m_dwConstFunction = 0;
  697. m_bConstIsStrNumeric = FALSE;
  698. return SUCCESS;
  699. }
  700. //***************************************************************************
  701. //
  702. // <typed_constant> ::= VARIANT;
  703. //
  704. // Ouput: m_vTypedConst is set to the value of the constant. The only
  705. // supported types are VT_I4, VT_R8 and VT_BSTR.
  706. //
  707. //***************************************************************************
  708. int SQL1_Parser::typed_constant()
  709. {
  710. trace((" Typed constant <%S> ", m_pTokenText));
  711. VariantClear(&m_vTypedConst);
  712. m_bConstIsStrNumeric = FALSE;
  713. if (m_nCurrentToken == SQL_1_TOK_INT)
  714. {
  715. trace((" Integer\n"));
  716. DWORD x = wcslen(m_pTokenText);
  717. if (*m_pTokenText == L'-')
  718. {
  719. //negative
  720. if ((x < 11) ||
  721. ((x == 11) && (wcscmp(m_pTokenText, L"-2147483648") <= 0)))
  722. {
  723. V_VT(&m_vTypedConst) = VT_I4;
  724. V_I4(&m_vTypedConst) = _wtol(m_pTokenText);
  725. }
  726. else
  727. {
  728. trace((" Actually Integer String\n"));
  729. V_VT(&m_vTypedConst) = VT_BSTR;
  730. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  731. m_bConstIsStrNumeric = TRUE;
  732. }
  733. }
  734. else
  735. {
  736. //positive
  737. if ((x < 10) ||
  738. ((x == 10) && (wcscmp(m_pTokenText, L"2147483647") <= 0)))
  739. {
  740. V_VT(&m_vTypedConst) = VT_I4;
  741. V_I4(&m_vTypedConst) = _wtol(m_pTokenText);
  742. }
  743. else
  744. {
  745. trace((" Actually Integer String\n"));
  746. V_VT(&m_vTypedConst) = VT_BSTR;
  747. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  748. m_bConstIsStrNumeric = TRUE;
  749. }
  750. }
  751. }
  752. else if (m_nCurrentToken == SQL_1_TOK_QSTRING)
  753. {
  754. trace((" String\n"));
  755. V_VT(&m_vTypedConst) = VT_BSTR;
  756. V_BSTR(&m_vTypedConst) = SysAllocString(m_pTokenText);
  757. }
  758. else if (m_nCurrentToken == SQL_1_TOK_REAL)
  759. {
  760. trace((" Real\n"));
  761. V_VT(&m_vTypedConst) = VT_R8;
  762. V_R8(&m_vTypedConst) = 0.0;
  763. if (m_pTokenText)
  764. {
  765. VARIANT varFrom;
  766. varFrom.vt = VT_BSTR;
  767. varFrom.bstrVal = SysAllocString(m_pTokenText);
  768. if(varFrom.bstrVal != NULL)
  769. {
  770. VariantClear(&m_vTypedConst);
  771. VariantInit(&m_vTypedConst);
  772. SCODE sc = VariantChangeTypeEx(&m_vTypedConst, &varFrom, 0, 0x409, VT_R8);
  773. VariantClear(&varFrom);
  774. if(sc != S_OK)
  775. {
  776. VariantClear(&m_vTypedConst);
  777. VariantInit(&m_vTypedConst);
  778. return LEXICAL_ERROR;
  779. }
  780. }
  781. }
  782. }
  783. // Else, not a typed constant.
  784. else
  785. return SYNTAX_ERROR;
  786. if (!Next())
  787. return LEXICAL_ERROR;
  788. return SUCCESS;
  789. }
  790. //***************************************************************************
  791. //
  792. // <rel_operator> ::= <equiv_operator>;
  793. // <rel_operator> ::= <comp_operator>;
  794. //
  795. //***************************************************************************
  796. int SQL1_Parser::rel_operator()
  797. {
  798. if(SUCCESS == equiv_operator())
  799. return SUCCESS;
  800. else if (SUCCESS == comp_operator())
  801. return SUCCESS;
  802. else return LEXICAL_ERROR;
  803. }
  804. //***************************************************************************
  805. //
  806. // <equiv_operator> ::= EQUIV_OPERATOR; // =, !=
  807. //
  808. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  809. //
  810. //***************************************************************************
  811. int SQL1_Parser::equiv_operator()
  812. {
  813. m_nRelOp = 0;
  814. if (m_nCurrentToken == SQL_1_TOK_EQ)
  815. {
  816. trace((" REL OP =\n"));
  817. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  818. }
  819. else if (m_nCurrentToken == SQL_1_TOK_NE)
  820. {
  821. trace((" REL OP <> (!=) \n"));
  822. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  823. }
  824. else
  825. return SYNTAX_ERROR;
  826. if (!Next())
  827. return LEXICAL_ERROR;
  828. return SUCCESS;
  829. }
  830. //***************************************************************************
  831. //
  832. // <is_operator> ::= IS_OPERATOR; // is, isnot
  833. //
  834. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  835. //
  836. //***************************************************************************
  837. int SQL1_Parser::is_operator()
  838. {
  839. m_nRelOp = 0;
  840. if (m_nCurrentToken != SQL_1_TOK_IS)
  841. return SYNTAX_ERROR;
  842. if (!Next())
  843. return LEXICAL_ERROR;
  844. if (m_nCurrentToken == SQL_1_TOK_NOT)
  845. {
  846. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  847. if (!Next())
  848. return LEXICAL_ERROR;
  849. trace((" REL OP IS NOT \n"));
  850. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  851. return SUCCESS;
  852. }
  853. else
  854. {
  855. trace((" REL OP IS \n"));
  856. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  857. return SUCCESS;
  858. }
  859. return SUCCESS;
  860. }
  861. //***************************************************************************
  862. //
  863. // <comp_operator> ::= COMP_OPERATOR; // <=, >=, <, >, like
  864. //
  865. // Output: m_nRelOp is set to the correct operator for a SQL_LEVEL_1_TOKEN.
  866. //
  867. //***************************************************************************
  868. int SQL1_Parser::comp_operator()
  869. {
  870. m_nRelOp = 0;
  871. if (m_nCurrentToken == SQL_1_TOK_LE)
  872. {
  873. trace((" REL OP <=\n"));
  874. if (m_pIdent)
  875. {
  876. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN;
  877. }
  878. else
  879. {
  880. trace((" REL OP changed to >=\n"));
  881. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN;
  882. }
  883. }
  884. else if (m_nCurrentToken == SQL_1_TOK_LT)
  885. {
  886. trace((" REL OP <\n"));
  887. if (m_pIdent)
  888. {
  889. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LESSTHAN;
  890. }
  891. else
  892. {
  893. trace((" REL OP changed to >\n"));
  894. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_GREATERTHAN;
  895. }
  896. }
  897. else if (m_nCurrentToken == SQL_1_TOK_GE)
  898. {
  899. trace((" REL OP >=\n"));
  900. if (m_pIdent)
  901. {
  902. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN;
  903. }
  904. else
  905. {
  906. trace((" REL OP changed to <=\n"));
  907. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN;
  908. }
  909. }
  910. else if (m_nCurrentToken == SQL_1_TOK_GT)
  911. {
  912. trace((" REL OP >\n"));
  913. if (m_pIdent)
  914. {
  915. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_GREATERTHAN;
  916. }
  917. else
  918. {
  919. trace((" REL OP changed to <\n"));
  920. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LESSTHAN;
  921. }
  922. }
  923. else if (m_nCurrentToken == SQL_1_TOK_LIKE)
  924. {
  925. trace((" REL OP 'like' \n"));
  926. m_nRelOp = SQL_LEVEL_1_TOKEN::OP_LIKE;
  927. }
  928. else
  929. return SYNTAX_ERROR;
  930. if (!Next())
  931. return LEXICAL_ERROR;
  932. return SUCCESS;
  933. }
  934. //***************************************************************************
  935. //
  936. // Expression and token structure methods.
  937. //
  938. //***************************************************************************
  939. SQL_LEVEL_1_RPN_EXPRESSION::SQL_LEVEL_1_RPN_EXPRESSION()
  940. {
  941. nNumTokens = 0;
  942. pArrayOfTokens = 0;
  943. bsClassName = 0;
  944. nNumberOfProperties = 0;
  945. pbsRequestedPropertyNames = 0;
  946. nCurSize = 32;
  947. nCurPropSize = 32;
  948. pArrayOfTokens = new SQL_LEVEL_1_TOKEN[nCurSize];
  949. pbsRequestedPropertyNames = new BSTR[nCurPropSize];
  950. }
  951. SQL_LEVEL_1_RPN_EXPRESSION::~SQL_LEVEL_1_RPN_EXPRESSION()
  952. {
  953. delete [] pArrayOfTokens;
  954. if (bsClassName)
  955. SysFreeString(bsClassName);
  956. for (int i = 0; i < nNumberOfProperties; i++)
  957. SysFreeString(pbsRequestedPropertyNames[i]);
  958. delete pbsRequestedPropertyNames;
  959. }
  960. void SQL_LEVEL_1_RPN_EXPRESSION::AddToken(SQL_LEVEL_1_TOKEN *pTok)
  961. {
  962. AddToken(*pTok);
  963. delete pTok;
  964. pTok = NULL;
  965. }
  966. void SQL_LEVEL_1_RPN_EXPRESSION::AddToken(SQL_LEVEL_1_TOKEN &pTok)
  967. {
  968. if (nCurSize == nNumTokens)
  969. {
  970. nCurSize += 32;
  971. SQL_LEVEL_1_TOKEN *pTemp = new SQL_LEVEL_1_TOKEN[nCurSize];
  972. for (int i = 0; i < nNumTokens; i++)
  973. pTemp[i] = pArrayOfTokens[i];
  974. delete [] pArrayOfTokens;
  975. pArrayOfTokens = pTemp;
  976. }
  977. pArrayOfTokens[nNumTokens++] = pTok;
  978. }
  979. void SQL_LEVEL_1_RPN_EXPRESSION::AddProperty(LPWSTR pProp)
  980. {
  981. if (nCurPropSize == nNumberOfProperties)
  982. {
  983. nCurPropSize += 32;
  984. BSTR * pTemp = new BSTR[ nCurPropSize ];
  985. if ( !pTemp )
  986. {
  987. return;
  988. }
  989. memcpy(pTemp, pbsRequestedPropertyNames,
  990. sizeof(BSTR) * nNumberOfProperties);
  991. delete pbsRequestedPropertyNames;
  992. pbsRequestedPropertyNames = pTemp;
  993. }
  994. pbsRequestedPropertyNames[nNumberOfProperties++] = SysAllocString(pProp);
  995. }
  996. void SQL_LEVEL_1_RPN_EXPRESSION::Dump(const char *pszTextFile)
  997. {
  998. FILE *f = fopen(pszTextFile, "wt");
  999. if (!f)
  1000. return;
  1001. fprintf(f, "----RPN Expression----\n");
  1002. fprintf(f, "Class name = %S\n", bsClassName);
  1003. fprintf(f, "Properties selected: ");
  1004. if (!nNumberOfProperties)
  1005. {
  1006. fprintf(f, "* = all properties selected\n");
  1007. }
  1008. else for (int i = 0; i < nNumberOfProperties; i++)
  1009. {
  1010. fprintf(f, "%S ", pbsRequestedPropertyNames[i]);
  1011. }
  1012. fprintf(f, "\n------------------\n");
  1013. fprintf(f, "Tokens:\n");
  1014. for (int i = 0; i < nNumTokens; i++)
  1015. pArrayOfTokens[i].Dump(f);
  1016. fprintf(f, "---end of expression---\n");
  1017. fclose(f);
  1018. }
  1019. SQL_LEVEL_1_TOKEN::SQL_LEVEL_1_TOKEN()
  1020. {
  1021. nTokenType = 0;
  1022. pPropertyName = 0;
  1023. nOperator = 0;
  1024. VariantInit(&vConstValue);
  1025. dwPropertyFunction = 0;
  1026. dwConstFunction = 0;
  1027. bConstIsStrNumeric = FALSE;
  1028. }
  1029. SQL_LEVEL_1_TOKEN::SQL_LEVEL_1_TOKEN(SQL_LEVEL_1_TOKEN &Src)
  1030. {
  1031. nTokenType = 0;
  1032. pPropertyName = 0;
  1033. nOperator = 0;
  1034. VariantInit(&vConstValue);
  1035. dwPropertyFunction = 0;
  1036. dwConstFunction = 0;
  1037. bConstIsStrNumeric = FALSE;
  1038. *this = Src;
  1039. }
  1040. SQL_LEVEL_1_TOKEN& SQL_LEVEL_1_TOKEN::operator =(SQL_LEVEL_1_TOKEN &Src)
  1041. {
  1042. //first clear any old values...
  1043. if (pPropertyName)
  1044. SysFreeString(pPropertyName);
  1045. VariantClear(&vConstValue);
  1046. nTokenType = Src.nTokenType;
  1047. pPropertyName = SysAllocString(Src.pPropertyName);
  1048. nOperator = Src.nOperator;
  1049. HRESULT hr = VariantCopy(&vConstValue, &Src.vConstValue);
  1050. if ( FAILED( hr ) )
  1051. {
  1052. throw WBEM_E_OUT_OF_MEMORY;
  1053. }
  1054. dwPropertyFunction = Src.dwPropertyFunction;
  1055. dwConstFunction = Src.dwConstFunction;
  1056. bConstIsStrNumeric = Src.bConstIsStrNumeric;
  1057. return *this;
  1058. }
  1059. SQL_LEVEL_1_TOKEN::~SQL_LEVEL_1_TOKEN()
  1060. {
  1061. nTokenType = 0;
  1062. if (pPropertyName)
  1063. SysFreeString(pPropertyName);
  1064. nOperator = 0;
  1065. VariantClear(&vConstValue);
  1066. }
  1067. void SQL_LEVEL_1_TOKEN::Dump(FILE *f)
  1068. {
  1069. switch (nTokenType)
  1070. {
  1071. case OP_EXPRESSION:
  1072. fprintf(f, "OP_EXPRESSION ");
  1073. break;
  1074. case TOKEN_AND:
  1075. fprintf(f, "TOKEN_AND ");
  1076. break;
  1077. case TOKEN_OR:
  1078. fprintf(f, "TOKEN_OR ");
  1079. break;
  1080. case TOKEN_NOT:
  1081. fprintf(f, "TOKEN_NOT ");
  1082. break;
  1083. default:
  1084. fprintf(f, "Error: no token type specified\n");
  1085. }
  1086. if (nTokenType == OP_EXPRESSION)
  1087. {
  1088. char *pOp = "<no op>";
  1089. switch (nOperator)
  1090. {
  1091. case OP_EQUAL: pOp = "OP_EQUAL"; break;
  1092. case OP_NOT_EQUAL: pOp = "OP_NOT_EQUAL"; break;
  1093. case OP_EQUALorGREATERTHAN: pOp = "OP_EQUALorGREATERTHAN"; break;
  1094. case OP_EQUALorLESSTHAN: pOp = "OP_EQUALorLESSTHAN"; break;
  1095. case OP_LESSTHAN: pOp = "OP_LESSTHAN"; break;
  1096. case OP_GREATERTHAN: pOp = "OP_GREATERTHAN"; break;
  1097. case OP_LIKE: pOp = "OP_LIKE"; break;
  1098. }
  1099. fprintf(f, " Property = %S\n", pPropertyName);
  1100. fprintf(f, " Operator = %s\n", pOp);
  1101. fprintf(f, " Value = ");
  1102. switch (V_VT(&vConstValue))
  1103. {
  1104. case VT_I4:
  1105. fprintf(f, "VT_I4 = %d\n", V_I4(&vConstValue));
  1106. break;
  1107. case VT_BSTR:
  1108. fprintf(f, "VT_BSTR = %S\n", V_BSTR(&vConstValue));
  1109. break;
  1110. case VT_R8:
  1111. fprintf(f, "VT_R8 = %f\n", V_R8(&vConstValue));
  1112. break;
  1113. default:
  1114. fprintf(f, "<unknown>\n");
  1115. }
  1116. switch (dwPropertyFunction)
  1117. {
  1118. case IFUNC_NONE:
  1119. break;
  1120. case IFUNC_LOWER:
  1121. fprintf(f, "Intrinsic function LOWER() applied to property\n");
  1122. break;
  1123. case IFUNC_UPPER:
  1124. fprintf(f, "Intrinsic function UPPER() applied to property\n");
  1125. break;
  1126. }
  1127. switch (dwConstFunction)
  1128. {
  1129. case IFUNC_NONE:
  1130. break;
  1131. case IFUNC_LOWER:
  1132. fprintf(f, "Intrinsic function LOWER() applied to const value\n");
  1133. break;
  1134. case IFUNC_UPPER:
  1135. fprintf(f, "Intrinsic function UPPER() applied to const value\n");
  1136. break;
  1137. }
  1138. }
  1139. fprintf(f, " <end of token>\n");
  1140. }
  1141. /////////////////////////////////////////////////////////////////////////////
  1142. //
  1143. // Algorithm for evaluating the expression, assuming that it has been
  1144. // tokenized and translated to Reverse Polish.
  1145. //
  1146. // Starting point: (a) An array of SQL tokens.
  1147. // (b) An empty boolean token stack.
  1148. //
  1149. // 1. Read Next Token
  1150. //
  1151. // 2. If a SIMPLE EXPRESSION, evaluate it to TRUE or FALSE, and
  1152. // place this boolean result on the stack. Go to 1.
  1153. //
  1154. // 3. If an OR operator, then pop a boolean token into A,
  1155. // pop another boolean token into B. If either A or B are TRUE,
  1156. // stack TRUE. Else stack FALSE.
  1157. // Go to 1.
  1158. //
  1159. // 4. If an AND operator, then pop a boolean token into A,
  1160. // and pop another into B. If both are TRUE, stack TRUE.
  1161. // Else stack FALSE.
  1162. // Go to 1.
  1163. //
  1164. // 5. If a NOT operator, reverse the value of the top-of-stack boolean.
  1165. // Go to 1.
  1166. //
  1167. // At end-of-input, the result is at top-of-stack.
  1168. //
  1169. /////////////////////////////////////////////////////////////////////////////