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.

1488 lines
38 KiB

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