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.

3789 lines
96 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. WQL.CPP
  5. Abstract:
  6. Implements the LL(1) syntax described in WQL.BNF via a recursive
  7. descent parser.
  8. History:
  9. raymcc 14-Sep-97 Created.
  10. raymcc 18-Oct-97 SMS extensions.
  11. --*/
  12. // TO DO:
  13. /*
  14. 5. SQL 89 joins
  15. 6. destructors & memleak checking
  16. 7. alias/table mismatch usage
  17. 8. allow ORDER BY and GROUP BY to occur in any order
  18. 9. AST-To-Text completion
  19. 11. Query Suite
  20. 11. "a" not a valid col name because it is now a keyword
  21. 18. ISNULL function
  22. 17. SELECT FROM (omission of the * or col-list)
  23. */
  24. #include "precomp.h"
  25. #include <stdio.h>
  26. #include <genlex.h>
  27. #include <flexarry.h>
  28. #include <wqllex.h>
  29. #include <wqlnode.h>
  30. #include <wql.h>
  31. static DWORD FlipOperator(DWORD dwOp);
  32. inline wchar_t *Macro_CloneLPWSTR(LPCWSTR src)
  33. {
  34. if (!src)
  35. return 0;
  36. wchar_t *dest = new wchar_t[wcslen(src) + 1];
  37. if (!dest)
  38. return 0;
  39. return wcscpy(dest, src);
  40. }
  41. #define trace(x) printf x
  42. //***************************************************************************
  43. //
  44. // CWQLParser::CWQLParser
  45. //
  46. // Constructor
  47. //
  48. // Parameters:
  49. // <pSrc> A source from which to lex from.
  50. //
  51. //***************************************************************************
  52. CWQLParser::CWQLParser(CGenLexSource *pSrc)
  53. {
  54. m_pLexer = new CGenLexer(WQL_LexTable, pSrc);
  55. m_nLine = 0;
  56. m_pTokenText = 0;
  57. m_nCurrentToken = 0;
  58. m_dwFeaturesFlags = 0;
  59. m_pQueryRoot = 0;
  60. m_pRootWhere = 0;
  61. m_pRootColList = 0;
  62. m_pRootFrom = 0;
  63. m_pRootWhereOptions = 0;
  64. m_nParseContext = Ctx_Default;
  65. m_bAllowPromptForConstant = false;
  66. }
  67. //***************************************************************************
  68. //
  69. // CWQLParser::~CWQLParser
  70. //
  71. //***************************************************************************
  72. CWQLParser::~CWQLParser()
  73. {
  74. Empty();
  75. delete m_pLexer;
  76. }
  77. //***************************************************************************
  78. //
  79. //***************************************************************************
  80. void CWQLParser::Empty()
  81. {
  82. m_aReferencedTables.Empty();
  83. m_aReferencedAliases.Empty();
  84. m_pTokenText = 0; // We don't delete this, it was never allocated
  85. m_nLine = 0;
  86. m_nCurrentToken = 0;
  87. m_dwFeaturesFlags = 0;
  88. delete m_pQueryRoot;
  89. m_pQueryRoot = 0;
  90. m_pRootWhere = 0;
  91. m_pRootColList = 0;
  92. m_pRootFrom = 0;
  93. m_pRootWhereOptions = 0;
  94. m_nParseContext = Ctx_Default;
  95. // For the next two, we don't delete the pointers since they
  96. // were copies of structs elsewhere in the tree.
  97. // =========================================================
  98. m_aSelAliases.Empty();
  99. m_aSelColumns.Empty();
  100. }
  101. //***************************************************************************
  102. //
  103. // CWQLParser::GetTokenLong
  104. //
  105. // Converts the current token to a long int.
  106. //
  107. //***************************************************************************
  108. LONG CWQLParser::GetTokenLong()
  109. {
  110. char buf[64];
  111. sprintf(buf, "%S", m_pTokenText);
  112. return atol(buf);
  113. }
  114. //***************************************************************************
  115. //
  116. // CWQLParser::GetReferencedTables
  117. //
  118. // Creates an array of the names of the tables referenced in this query
  119. //
  120. //***************************************************************************
  121. BOOL CWQLParser::GetReferencedTables(OUT CWStringArray& Tables)
  122. {
  123. Tables = m_aReferencedTables;
  124. return TRUE;
  125. }
  126. BOOL CWQLParser::GetReferencedAliases(OUT CWStringArray & Aliases)
  127. {
  128. Aliases = m_aReferencedAliases;
  129. return TRUE;
  130. }
  131. //***************************************************************************
  132. //
  133. // Next()
  134. //
  135. // Advances to the next token and recognizes keywords, etc.
  136. //
  137. //***************************************************************************
  138. struct WqlKeyword
  139. {
  140. LPWSTR m_pKeyword;
  141. int m_nTokenCode;
  142. };
  143. static WqlKeyword KeyWords[] = // Keep this alphabetized for binary search
  144. {
  145. L"A", WQL_TOK_A,
  146. L"AGGREGATE",WQL_TOK_AGGREGATE,
  147. L"ALL", WQL_TOK_ALL,
  148. L"AND", WQL_TOK_AND,
  149. L"AS", WQL_TOK_AS,
  150. L"ASC", WQL_TOK_ASC,
  151. L"BETWEEN", WQL_TOK_BETWEEN,
  152. L"BY", WQL_TOK_BY,
  153. L"COUNT", WQL_TOK_COUNT,
  154. L"DATEPART", WQL_TOK_DATEPART,
  155. L"DESC", WQL_TOK_DESC,
  156. L"DISTINCT", WQL_TOK_DISTINCT,
  157. L"FIRSTROW", WQL_TOK_FIRSTROW,
  158. L"FROM", WQL_TOK_FROM,
  159. L"FULL", WQL_TOK_FULL,
  160. L"GROUP", WQL_TOK_GROUP,
  161. L"HAVING", WQL_TOK_HAVING,
  162. L"IN", WQL_TOK_IN,
  163. L"INNER", WQL_TOK_INNER,
  164. L"IS", WQL_TOK_IS,
  165. L"ISA", WQL_TOK_ISA,
  166. L"ISNULL", WQL_TOK_ISNULL,
  167. L"JOIN", WQL_TOK_JOIN,
  168. L"LEFT", WQL_TOK_LEFT,
  169. L"LIKE", WQL_TOK_LIKE,
  170. L"LOWER", WQL_TOK_LOWER,
  171. L"NOT", WQL_TOK_NOT,
  172. L"NULL", WQL_TOK_NULL,
  173. L"ON", WQL_TOK_ON,
  174. L"OR", WQL_TOK_OR,
  175. L"ORDER", WQL_TOK_ORDER,
  176. L"OUTER", WQL_TOK_OUTER,
  177. L"QUALIFIER", WQL_TOK_QUALIFIER,
  178. L"RIGHT", WQL_TOK_RIGHT,
  179. L"SELECT", WQL_TOK_SELECT,
  180. L"UPPER", WQL_TOK_UPPER,
  181. L"WHERE", WQL_TOK_WHERE
  182. };
  183. const int NumKeywords = sizeof(KeyWords)/sizeof(WqlKeyword);
  184. BOOL CWQLParser::Next()
  185. {
  186. m_nCurrentToken = m_pLexer->NextToken();
  187. if (m_nCurrentToken == WQL_TOK_ERROR
  188. || (m_nCurrentToken == WQL_TOK_PROMPT && !m_bAllowPromptForConstant))
  189. return FALSE;
  190. m_nLine = m_pLexer->GetLineNum();
  191. m_pTokenText = m_pLexer->GetTokenText();
  192. if (m_nCurrentToken == WQL_TOK_EOF)
  193. m_pTokenText = L"<end of file>";
  194. // Keyword check. Do a binary search
  195. // on the keyword table.
  196. // =================================
  197. if (m_nCurrentToken == WQL_TOK_IDENT)
  198. {
  199. int l = 0, u = NumKeywords - 1;
  200. while (l <= u)
  201. {
  202. int m = (l + u) / 2;
  203. if (_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) < 0)
  204. u = m - 1;
  205. else if (_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) > 0)
  206. l = m + 1;
  207. else // Match
  208. {
  209. m_nCurrentToken = KeyWords[m].m_nTokenCode;
  210. break;
  211. }
  212. }
  213. }
  214. return TRUE;
  215. }
  216. //***************************************************************************
  217. //
  218. // <parse> ::= SELECT <select_stmt>;
  219. //
  220. //***************************************************************************
  221. int CWQLParser::Parse()
  222. {
  223. Empty();
  224. SWQLNode_Select *pSel = 0;
  225. int nRes = SYNTAX_ERROR;
  226. m_pLexer->Reset();
  227. if (!Next())
  228. return LEXICAL_ERROR;
  229. if (m_nCurrentToken == WQL_TOK_SELECT)
  230. {
  231. if (!Next())
  232. return LEXICAL_ERROR;
  233. nRes = select_stmt(&pSel);
  234. }
  235. // cleanup...
  236. // If here, not a legal starter symbol.
  237. // ====================================
  238. m_pQueryRoot = pSel;
  239. return nRes;
  240. }
  241. //***************************************************************************
  242. //
  243. // <select_stmt> ::=
  244. // <select_type>
  245. // <col_ref_list>
  246. // <from_clause>
  247. // <where_clause>
  248. //
  249. //***************************************************************************
  250. // ...
  251. int CWQLParser::select_stmt(OUT SWQLNode_Select **pSelStmt)
  252. {
  253. int nRes = 0;
  254. int nType = 0;
  255. SWQLNode_FromClause *pFrom = 0;
  256. SWQLNode_Select *pSel = 0;
  257. SWQLNode_TableRefs *pTblRefs = 0;
  258. SWQLNode_WhereClause *pWhere = 0;
  259. *pSelStmt = 0;
  260. // Set up the basic AST.
  261. // =====================
  262. pSel = new SWQLNode_Select;
  263. pTblRefs = new SWQLNode_TableRefs;
  264. pSel->m_pLeft = pTblRefs;
  265. // Get the select type.
  266. // ====================
  267. nRes = select_type(nType);
  268. if (nRes)
  269. goto Exit;
  270. pTblRefs->m_nSelectType = nType; // ALL, DISTINCT
  271. // Get the selected list of columns.
  272. // =================================
  273. nRes = col_ref_list(pTblRefs);
  274. if (nRes)
  275. goto Exit;
  276. m_pRootColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft;
  277. // Get the FROM clause and patch it into the AST.
  278. // ===============================================
  279. nRes = from_clause(&pFrom);
  280. if (nRes)
  281. goto Exit;
  282. m_pRootFrom = pFrom;
  283. pTblRefs->m_pRight = pFrom;
  284. // Get the WHERE clause.
  285. // =====================
  286. nRes = where_clause(&pWhere);
  287. if (nRes)
  288. goto Exit;
  289. m_pRootWhere = pWhere;
  290. pSel->m_pRight = pWhere;
  291. // Verify we are at the end of the query.
  292. // ======================================
  293. if (m_nCurrentToken != WQL_TOK_EOF)
  294. {
  295. nRes = SYNTAX_ERROR;
  296. goto Exit;
  297. }
  298. nRes = NO_ERROR;
  299. Exit:
  300. if (nRes)
  301. delete pSel;
  302. else
  303. {
  304. *pSelStmt = pSel;
  305. }
  306. return nRes;
  307. }
  308. //***************************************************************************
  309. //
  310. // <select_type> ::= ALL;
  311. // <select_type> ::= DISTINCT;
  312. // <select_type> ::= <>;
  313. //
  314. // Returns type through nSelType :
  315. // WQL_TOK_ALL or WQL_TOK_DISTINCT
  316. //
  317. //***************************************************************************
  318. // done
  319. int CWQLParser::select_type(int & nSelType)
  320. {
  321. nSelType = WQL_FLAG_ALL; // Default
  322. if (m_nCurrentToken == WQL_TOK_ALL)
  323. {
  324. nSelType = WQL_FLAG_ALL;
  325. if (!Next())
  326. return LEXICAL_ERROR;
  327. return NO_ERROR;
  328. }
  329. if (m_nCurrentToken == WQL_TOK_DISTINCT)
  330. {
  331. nSelType = WQL_FLAG_DISTINCT;
  332. if (!Next())
  333. return LEXICAL_ERROR;
  334. return NO_ERROR;
  335. }
  336. if (m_nCurrentToken == WQL_TOK_AGGREGATE)
  337. {
  338. nSelType = WQL_FLAG_AGGREGATE;
  339. if (!Next())
  340. return LEXICAL_ERROR;
  341. return NO_ERROR;
  342. }
  343. return NO_ERROR;
  344. }
  345. //***************************************************************************
  346. //
  347. // <col_ref_list> ::= <col_ref> <col_ref_rest>;
  348. // <col_ref_list> ::= ASTERISK;
  349. // <col_ref_list> ::= COUNT <count_clause>;
  350. //
  351. //***************************************************************************
  352. int CWQLParser::col_ref_list(
  353. IN OUT SWQLNode_TableRefs *pTblRefs
  354. )
  355. {
  356. int nRes;
  357. DWORD dwFuncFlags = 0;
  358. // Allocate a new left node of type SWQLNode_ColumnList and patch it in
  359. // if it doesn't already exist.
  360. // =====================================================================
  361. SWQLNode_ColumnList *pColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft;
  362. if (pColList == NULL)
  363. {
  364. pColList = new SWQLNode_ColumnList;
  365. pTblRefs->m_pLeft = pColList;
  366. }
  367. // If here, it is a "select *..." query.
  368. // =====================================
  369. if (m_nCurrentToken == WQL_TOK_ASTERISK)
  370. {
  371. // Allocate a new column list which has a single asterisk.
  372. // =======================================================
  373. SWQLColRef *pColRef = new SWQLColRef;
  374. pColRef->m_pColName = Macro_CloneLPWSTR(L"*");
  375. pColRef->m_dwFlags = WQL_FLAG_ASTERISK;
  376. pColList->m_aColumnRefs.Add(pColRef);
  377. if (!Next())
  378. return LEXICAL_ERROR;
  379. return NO_ERROR;
  380. }
  381. // If here, we have a "select COUNT..." operation.
  382. // ===============================================
  383. if (m_nCurrentToken == WQL_TOK_COUNT)
  384. {
  385. if (!Next())
  386. return LEXICAL_ERROR;
  387. pTblRefs->m_nSelectType |= WQL_FLAG_COUNT;
  388. SWQLQualifiedName *pQN = 0;
  389. nRes = count_clause(&pQN);
  390. // Now build up the column reference.
  391. // ==================================
  392. if (nRes)
  393. return nRes;
  394. SWQLColRef *pCR = 0;
  395. nRes = QNameToSWQLColRef(pQN, &pCR);
  396. pColList->m_aColumnRefs.Add(pCR);
  397. return NO_ERROR;
  398. }
  399. // Make a provision for wrapping the
  400. // column in a function all UPPER or LOWER
  401. // =======================================
  402. if (m_nCurrentToken == WQL_TOK_UPPER)
  403. dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_UPPER;
  404. else if (m_nCurrentToken == WQL_TOK_LOWER)
  405. dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_LOWER;
  406. if (dwFuncFlags)
  407. {
  408. // Common procedure for cases where UPPER or LOWER are used.
  409. if (!Next())
  410. return LEXICAL_ERROR;
  411. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  412. return SYNTAX_ERROR;
  413. if (!Next())
  414. return LEXICAL_ERROR;
  415. }
  416. // If here, must be an identifier.
  417. // ===============================
  418. if (m_nCurrentToken != WQL_TOK_IDENT)
  419. return SYNTAX_ERROR;
  420. SWQLQualifiedName *pInitCol = 0;
  421. nRes = col_ref(&pInitCol);
  422. if (nRes)
  423. return nRes;
  424. SWQLColRef *pCR = 0;
  425. nRes = QNameToSWQLColRef(pInitCol, &pCR);
  426. pCR->m_dwFlags |= dwFuncFlags;
  427. if (dwFuncFlags)
  428. {
  429. // If a function call was invoked, remove the trailing paren.
  430. // ==========================================================
  431. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  432. return SYNTAX_ERROR;
  433. if (!Next())
  434. return LEXICAL_ERROR;
  435. }
  436. pColList->m_aColumnRefs.Add(pCR);
  437. return col_ref_rest(pTblRefs);
  438. }
  439. //***************************************************************************
  440. //
  441. // <count_clause> ::= OPEN_PAREN <count_col> CLOSE_PAREN;
  442. // <count_col> ::= ASTERISK;
  443. // <count_col> ::= IDENT;
  444. //
  445. // On NO_ERROR returns:
  446. // <bAsterisk> set to TRUE if a * occurred in the COUNT clause,
  447. // or <bAsterisk> set to FALSE and <pQualName> set to point to the
  448. // qualified name of the column referenced.
  449. //
  450. //***************************************************************************
  451. // done
  452. int CWQLParser::count_clause(
  453. OUT SWQLQualifiedName **pQualName
  454. )
  455. {
  456. int nRes;
  457. *pQualName = 0;
  458. // Syntax check.
  459. // =============
  460. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  461. return SYNTAX_ERROR;
  462. if (!Next())
  463. return LEXICAL_ERROR;
  464. // Determine whether an asterisk was used COUNT(*) or
  465. // a col-ref COUNT(col-ref)
  466. // ==================================================
  467. if (m_nCurrentToken == WQL_TOK_ASTERISK)
  468. {
  469. SWQLQualifiedName *pQN = new SWQLQualifiedName;
  470. SWQLQualifiedNameField *pQF = new SWQLQualifiedNameField;
  471. pQF->m_pName = Macro_CloneLPWSTR(L"*");
  472. pQN->Add(pQF);
  473. *pQualName = pQN;
  474. if (!Next())
  475. return LEXICAL_ERROR;
  476. }
  477. else if (m_nCurrentToken == WQL_TOK_IDENT)
  478. {
  479. SWQLQualifiedName *pQN = 0;
  480. nRes = col_ref(&pQN);
  481. if (nRes)
  482. return nRes;
  483. *pQualName = pQN;
  484. }
  485. // Check for errors in syntax and clean up
  486. // if so.
  487. // =======================================
  488. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  489. {
  490. if (*pQualName)
  491. delete *pQualName;
  492. *pQualName = 0;
  493. return SYNTAX_ERROR;
  494. }
  495. if (!Next())
  496. {
  497. if (*pQualName)
  498. delete *pQualName;
  499. *pQualName = 0;
  500. return LEXICAL_ERROR;
  501. }
  502. return NO_ERROR;
  503. }
  504. //***************************************************************************
  505. //
  506. // <col_ref_rest> ::= COMMA <col_ref_list>;
  507. // <col_ref_rest> ::= <>;
  508. //
  509. //***************************************************************************
  510. int CWQLParser::col_ref_rest(IN OUT SWQLNode_TableRefs *pTblRefs)
  511. {
  512. int nRes;
  513. if (m_nCurrentToken != WQL_TOK_COMMA)
  514. return NO_ERROR;
  515. if (!Next())
  516. return LEXICAL_ERROR;
  517. nRes = col_ref_list(pTblRefs);
  518. return nRes;
  519. }
  520. //***************************************************************************
  521. //
  522. // <from_clause> ::= <table_list>;
  523. //
  524. // <table_list> ::= <single_table_decl> <optional_join>;
  525. //
  526. // <optional_join> ::= <sql89_join_entry>;
  527. // <optional_join> ::= <sql92_join_entry>;
  528. //
  529. // <optional_join> ::= <>; // Unary query
  530. //
  531. //***************************************************************************
  532. int CWQLParser::from_clause(OUT SWQLNode_FromClause **pFrom)
  533. {
  534. int nRes = 0;
  535. SWQLNode_TableRef *pTbl = 0;
  536. SWQLNode_FromClause *pFC = new SWQLNode_FromClause;
  537. if (m_nCurrentToken != WQL_TOK_FROM)
  538. return SYNTAX_ERROR;
  539. if (!Next())
  540. return LEXICAL_ERROR;
  541. nRes = single_table_decl(&pTbl);
  542. if (nRes)
  543. return nRes;
  544. // Check for joins.
  545. // ===============
  546. if (m_nCurrentToken == WQL_TOK_COMMA)
  547. {
  548. SWQLNode_Sql89Join *pJoin = 0;
  549. nRes = sql89_join_entry(pTbl, &pJoin);
  550. if (nRes)
  551. return nRes;
  552. pFC->m_pLeft = pJoin;
  553. }
  554. else
  555. {
  556. if (m_nCurrentToken == WQL_TOK_INNER ||
  557. m_nCurrentToken == WQL_TOK_FULL ||
  558. m_nCurrentToken == WQL_TOK_LEFT ||
  559. m_nCurrentToken == WQL_TOK_RIGHT ||
  560. m_nCurrentToken == WQL_TOK_JOIN
  561. )
  562. {
  563. SWQLNode_Join *pJoin = 0;
  564. nRes = sql92_join_entry(pTbl, &pJoin);
  565. if (nRes)
  566. return nRes;
  567. pFC->m_pLeft = pJoin;
  568. }
  569. // Single table select (unary query).
  570. // ==================================
  571. else
  572. {
  573. pFC->m_pLeft = pTbl;
  574. }
  575. }
  576. *pFrom = pFC;
  577. return NO_ERROR;
  578. }
  579. //***************************************************************************
  580. //
  581. // <sql89_join_entry> ::= COMMA <sql89_join_list>;
  582. //
  583. //***************************************************************************
  584. int CWQLParser::sql89_join_entry(IN SWQLNode_TableRef *pInitialTblRef,
  585. OUT SWQLNode_Sql89Join **pJoin )
  586. {
  587. if (m_nCurrentToken != WQL_TOK_COMMA)
  588. return SYNTAX_ERROR;
  589. if (!Next())
  590. return LEXICAL_ERROR;
  591. return sql89_join_list(pInitialTblRef, pJoin);
  592. }
  593. //***************************************************************************
  594. //
  595. // <sql89_join_list> ::= <single_table_decl> <sql89_join_rest>;
  596. //
  597. // <sql89_join_rest> ::= COMMA <sql89_join_list>;
  598. // <sql89_join_rest> ::= <>;
  599. //
  600. //***************************************************************************
  601. int CWQLParser::sql89_join_list(IN SWQLNode_TableRef *pInitialTblRef,
  602. OUT SWQLNode_Sql89Join **pJoin )
  603. {
  604. int nRes;
  605. SWQLNode_Sql89Join *p89Join = new SWQLNode_Sql89Join;
  606. p89Join->m_aValues.Add(pInitialTblRef);
  607. while (1)
  608. {
  609. SWQLNode_TableRef *pTR = 0;
  610. nRes = single_table_decl(&pTR);
  611. if (nRes)
  612. return nRes;
  613. p89Join->m_aValues.Add(pTR);
  614. if (m_nCurrentToken != WQL_TOK_COMMA)
  615. break;
  616. if (!Next())
  617. return LEXICAL_ERROR;
  618. }
  619. *pJoin = p89Join;
  620. return NO_ERROR;
  621. }
  622. //***************************************************************************
  623. //
  624. // <where_clause> ::= WQL_TOK_WHERE <rel_expr> <where_options>;
  625. // <where_clause> ::= <>; // 'where' is not required
  626. //
  627. //***************************************************************************
  628. // done
  629. int CWQLParser::where_clause(OUT SWQLNode_WhereClause **pRetWhere)
  630. {
  631. SWQLNode_WhereClause *pWhere = new SWQLNode_WhereClause;
  632. *pRetWhere = pWhere;
  633. SWQLNode_RelExpr *pRelExpr = 0;
  634. int nRes;
  635. // 'where' is optional.
  636. // ====================
  637. if (m_nCurrentToken == WQL_TOK_WHERE)
  638. {
  639. if (!Next())
  640. return LEXICAL_ERROR;
  641. // Get the primary relational expression for the 'where' clause.
  642. // =============================================================
  643. nRes = rel_expr(&pRelExpr);
  644. if (nRes)
  645. {
  646. delete pRelExpr;
  647. return nRes;
  648. }
  649. // Get the options, such as ORDER BY, GROUP BY, etc.
  650. // =================================================
  651. }
  652. SWQLNode_WhereOptions *pWhereOpt = 0;
  653. nRes = where_options(&pWhereOpt);
  654. if (nRes)
  655. {
  656. delete pRelExpr;
  657. delete pWhereOpt;
  658. return nRes;
  659. }
  660. pWhere->m_pLeft = pRelExpr;
  661. pWhere->m_pRight = pWhereOpt;
  662. m_pRootWhereOptions = pWhereOpt;
  663. return NO_ERROR;
  664. }
  665. //***************************************************************************
  666. //
  667. // <where_options> ::=
  668. // <group_by_clause>
  669. // <order_by_clause>
  670. //
  671. //***************************************************************************
  672. // done
  673. int CWQLParser::where_options(OUT SWQLNode_WhereOptions **pRetWhereOpt)
  674. {
  675. int nRes;
  676. *pRetWhereOpt = 0;
  677. SWQLNode_GroupBy *pGroupBy = 0;
  678. nRes = group_by_clause(&pGroupBy);
  679. if (nRes)
  680. {
  681. delete pGroupBy;
  682. return nRes;
  683. }
  684. SWQLNode_OrderBy *pOrderBy = 0;
  685. nRes = order_by_clause(&pOrderBy);
  686. if (nRes)
  687. {
  688. delete pOrderBy;
  689. delete pGroupBy;
  690. return nRes;
  691. }
  692. SWQLNode_WhereOptions *pWhereOpt = 0;
  693. if (pGroupBy || pOrderBy)
  694. {
  695. pWhereOpt = new SWQLNode_WhereOptions;
  696. pWhereOpt->m_pLeft = pGroupBy;
  697. pWhereOpt->m_pRight = pOrderBy;
  698. }
  699. *pRetWhereOpt = pWhereOpt;
  700. return NO_ERROR;
  701. }
  702. //***************************************************************************
  703. //
  704. // <group_by_clause> ::= WQL_TOK_GROUP WQL_TOK_BY <col_list> <having_clause>;
  705. // <group_by_clause> ::= <>;
  706. //
  707. //***************************************************************************
  708. // done
  709. int CWQLParser::group_by_clause(OUT SWQLNode_GroupBy **pRetGroupBy)
  710. {
  711. int nRes;
  712. *pRetGroupBy = 0;
  713. if (m_nCurrentToken != WQL_TOK_GROUP)
  714. return NO_ERROR;
  715. if (!Next())
  716. return LEXICAL_ERROR;
  717. if (m_nCurrentToken != WQL_TOK_BY)
  718. return SYNTAX_ERROR;
  719. if (!Next())
  720. return LEXICAL_ERROR;
  721. // Get the guts of the GROUP BY.
  722. // =============================
  723. SWQLNode_GroupBy *pGroupBy = new SWQLNode_GroupBy;
  724. SWQLNode_ColumnList *pColList = 0;
  725. nRes = col_list(&pColList);
  726. if (nRes)
  727. {
  728. delete pGroupBy;
  729. delete pColList;
  730. return nRes;
  731. }
  732. pGroupBy->m_pLeft = pColList;
  733. // Check for the HAVING clause.
  734. // ============================
  735. SWQLNode_Having *pHaving = 0;
  736. nRes = having_clause(&pHaving);
  737. if (pHaving)
  738. pGroupBy->m_pRight = pHaving;
  739. *pRetGroupBy = pGroupBy;
  740. return NO_ERROR;
  741. }
  742. //***************************************************************************
  743. //
  744. // <having_clause> ::= WQL_TOK_HAVING <rel_expr>;
  745. // <having_clause> ::= <>;
  746. //
  747. //***************************************************************************
  748. // done
  749. int CWQLParser::having_clause(OUT SWQLNode_Having **pRetHaving)
  750. {
  751. int nRes;
  752. *pRetHaving = 0;
  753. if (m_nCurrentToken != WQL_TOK_HAVING)
  754. return NO_ERROR;
  755. if (!Next())
  756. return LEXICAL_ERROR;
  757. // If here, we have a HAVING clause.
  758. // =================================
  759. SWQLNode_RelExpr *pRelExpr = 0;
  760. nRes = rel_expr(&pRelExpr);
  761. if (nRes)
  762. {
  763. delete pRelExpr;
  764. return nRes;
  765. }
  766. SWQLNode_Having *pHaving = new SWQLNode_Having;
  767. pHaving->m_pLeft = pRelExpr;
  768. *pRetHaving = pHaving;
  769. return NO_ERROR;
  770. }
  771. //***************************************************************************
  772. //
  773. // <order_by_clause> ::= WQL_TOK_ORDER WQL_TOK_BY <col_list>;
  774. // <order_by_clause> ::= <>;
  775. //
  776. //***************************************************************************
  777. // done
  778. int CWQLParser::order_by_clause(OUT SWQLNode_OrderBy **pRetOrderBy)
  779. {
  780. int nRes;
  781. if (m_nCurrentToken != WQL_TOK_ORDER)
  782. return NO_ERROR;
  783. if (!Next())
  784. return LEXICAL_ERROR;
  785. if (m_nCurrentToken != WQL_TOK_BY)
  786. return SYNTAX_ERROR;
  787. if (!Next())
  788. return LEXICAL_ERROR;
  789. // If here, we have an ORDER BY clause.
  790. // ====================================
  791. SWQLNode_ColumnList *pColList = 0;
  792. nRes = col_list(&pColList);
  793. if (nRes)
  794. {
  795. delete pColList;
  796. return nRes;
  797. }
  798. SWQLNode_OrderBy *pOrderBy = new SWQLNode_OrderBy;
  799. pOrderBy->m_pLeft = pColList;
  800. *pRetOrderBy = pOrderBy;
  801. return NO_ERROR;
  802. }
  803. //***************************************************************************
  804. //
  805. // <single_table_decl> ::= <unbound_table_ident> <table_decl_rest>;
  806. //
  807. // <unbound_table_ident> ::= IDENT;
  808. // <table_decl_rest> ::= <redundant_as> <table_alias>;
  809. // <table_decl_rest> ::= <>;
  810. // <table_alias> ::= IDENT;
  811. //
  812. // <redundant_as> ::= AS;
  813. // <redundant_as> ::= <>;
  814. //
  815. //***************************************************************************
  816. // done; no cleanup
  817. int CWQLParser::single_table_decl(OUT SWQLNode_TableRef **pTblRef)
  818. {
  819. if (pTblRef == 0)
  820. return INTERNAL_ERROR;
  821. *pTblRef = 0;
  822. if (m_nCurrentToken != WQL_TOK_IDENT)
  823. return SYNTAX_ERROR;
  824. SWQLNode_TableRef *pTR = new SWQLNode_TableRef;
  825. pTR->m_pTableName = Macro_CloneLPWSTR(m_pTokenText);
  826. m_aReferencedTables.Add(m_pTokenText);
  827. if (!Next())
  828. return LEXICAL_ERROR;
  829. if (m_nCurrentToken == WQL_TOK_AS)
  830. {
  831. // Here we have a redundant AS and an alias.
  832. // =========================================
  833. if (!Next())
  834. return LEXICAL_ERROR;
  835. }
  836. if (m_nCurrentToken == WQL_TOK_IDENT &&
  837. _wcsicmp(L"FIRSTROW", m_pTokenText) != 0
  838. )
  839. {
  840. // Alias name
  841. // ==========
  842. pTR->m_pAlias = Macro_CloneLPWSTR(m_pTokenText);
  843. m_aReferencedAliases.Add(m_pTokenText);
  844. if (!Next())
  845. return LEXICAL_ERROR;
  846. }
  847. // If no Alias was used, we simply copy the table name into
  848. // the alias slot.
  849. // ========================================================
  850. else
  851. {
  852. pTR->m_pAlias = Macro_CloneLPWSTR(pTR->m_pTableName);
  853. m_aReferencedAliases.Add(pTR->m_pTableName);
  854. }
  855. // For the primary select, we are keeping a list of tables
  856. // we are selecting from.
  857. // =======================================================
  858. if ((m_nParseContext & Ctx_Subselect) == 0)
  859. m_aSelAliases.Add(pTR);
  860. // Return the pointer to the caller.
  861. // =================================
  862. *pTblRef = pTR;
  863. return NO_ERROR;
  864. }
  865. //***************************************************************************
  866. //
  867. // SQL-92 Joins.
  868. //
  869. // We support:
  870. // 1. [INNER] JOIN
  871. // 2. LEFT [OUTER] JOIN
  872. // 3. RIGHT [OUTER] JOIN
  873. // 4. FULL [OUTER] JOIN
  874. //
  875. //
  876. // <sql92_join_entry> ::= <simple_join_clause>;
  877. // <sql92_join_entry> ::= INNER <simple_join_clause>;
  878. // <sql92_join_entry> ::= FULL <opt_outer> <simple_join_clause>;
  879. // <sql92_join_entry> ::= LEFT <opt_outer> <simple_join_clause>;
  880. // <sql92_join_entry> ::= RIGHT <opt_outer> <simple_join_clause>;
  881. //
  882. // <opt_outer> ::= WQL_TOK_OUTER;
  883. // <opt_outer> ::= <>;
  884. //
  885. // <simple_join_clause> ::=
  886. // JOIN
  887. // <single_table_decl>
  888. // <on_clause>
  889. // <sql92_join_continuator>
  890. //
  891. // <sql92_join_continuator> ::= <sql92_join_entry>;
  892. // <sql92_join_continuator> ::= <>;
  893. //
  894. //***************************************************************************
  895. int CWQLParser::sql92_join_entry(
  896. IN SWQLNode_TableRef *pInitialTblRef, // inherited
  897. OUT SWQLNode_Join **pJoin // synthesized
  898. )
  899. {
  900. int nRes;
  901. /* Build a nested join tree bottom up. Currently, the tree is always left-heavy:
  902. JN = Join Noe
  903. JP = Join Pair
  904. OC = On Clause
  905. TR = Table Ref
  906. JN
  907. / \
  908. JP OC
  909. / \
  910. JN TR
  911. / \
  912. JP OC
  913. / \
  914. TR TR
  915. */
  916. // State 1: Attempting to build a new JOIN node.
  917. // =============================================
  918. SWQLNode *pCurrentLeftNode = pInitialTblRef;
  919. SWQLNode_Join *pJN = 0;
  920. while (1)
  921. {
  922. pJN = new SWQLNode_Join;
  923. // Join-type.
  924. // ==========
  925. pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN; // Default
  926. if (m_nCurrentToken == WQL_TOK_INNER)
  927. {
  928. if (!Next())
  929. return LEXICAL_ERROR;
  930. pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN;
  931. }
  932. else if (m_nCurrentToken == WQL_TOK_FULL)
  933. {
  934. if (!Next())
  935. return LEXICAL_ERROR;
  936. if (m_nCurrentToken == WQL_TOK_OUTER)
  937. if (!Next())
  938. return LEXICAL_ERROR;
  939. pJN->m_dwJoinType = WQL_FLAG_FULL_OUTER_JOIN;
  940. }
  941. else if (m_nCurrentToken == WQL_TOK_LEFT)
  942. {
  943. if (!Next())
  944. return LEXICAL_ERROR;
  945. if (m_nCurrentToken == WQL_TOK_OUTER)
  946. if (!Next())
  947. return LEXICAL_ERROR;
  948. pJN->m_dwJoinType = WQL_FLAG_LEFT_OUTER_JOIN;
  949. }
  950. else if (m_nCurrentToken == WQL_TOK_RIGHT)
  951. {
  952. if (!Next())
  953. return LEXICAL_ERROR;
  954. if (m_nCurrentToken == WQL_TOK_OUTER)
  955. if (!Next())
  956. return LEXICAL_ERROR;
  957. pJN->m_dwJoinType = WQL_FLAG_RIGHT_OUTER_JOIN;
  958. }
  959. // <simple_join_clause>
  960. // =====================
  961. if (m_nCurrentToken != WQL_TOK_JOIN)
  962. {
  963. return SYNTAX_ERROR;
  964. }
  965. if (!Next())
  966. return LEXICAL_ERROR;
  967. SWQLNode_JoinPair *pJP = new SWQLNode_JoinPair;
  968. // Determine the table to which to join.
  969. // =====================================
  970. SWQLNode_TableRef *pTR = 0;
  971. nRes = single_table_decl(&pTR);
  972. if (nRes)
  973. return nRes;
  974. pJP->m_pRight = pTR;
  975. pJP->m_pLeft = pCurrentLeftNode;
  976. pCurrentLeftNode = pJN;
  977. // If FIRSTROW is used, add it in.
  978. // ===============================
  979. if (m_nCurrentToken == WQL_TOK_IDENT)
  980. {
  981. if (_wcsicmp(L"FIRSTROW", m_pTokenText) != 0)
  982. return SYNTAX_ERROR;
  983. pJN->m_dwFlags |= WQL_FLAG_FIRSTROW;
  984. if (!Next())
  985. return LEXICAL_ERROR;
  986. }
  987. // Get the ON clause.
  988. // ==================
  989. SWQLNode_OnClause *pOC = 0;
  990. nRes = on_clause(&pOC);
  991. if (nRes)
  992. return nRes;
  993. pJN->m_pRight = pOC; // On clause
  994. pJN->m_pLeft = pJP;
  995. // sql92_join_continuator();
  996. // =========================
  997. if (m_nCurrentToken == WQL_TOK_INNER ||
  998. m_nCurrentToken == WQL_TOK_FULL ||
  999. m_nCurrentToken == WQL_TOK_LEFT ||
  1000. m_nCurrentToken == WQL_TOK_RIGHT ||
  1001. m_nCurrentToken == WQL_TOK_JOIN
  1002. )
  1003. continue;
  1004. break;
  1005. }
  1006. // Return the join node to the caller.
  1007. // ====================================
  1008. *pJoin = pJN;
  1009. return NO_ERROR;
  1010. }
  1011. //***************************************************************************
  1012. //
  1013. // <on_clause> ::= ON <rel_expr>;
  1014. //
  1015. //***************************************************************************
  1016. int CWQLParser::on_clause(OUT SWQLNode_OnClause **pOC)
  1017. {
  1018. if (m_nCurrentToken != WQL_TOK_ON)
  1019. return SYNTAX_ERROR;
  1020. if (!Next())
  1021. return LEXICAL_ERROR;
  1022. SWQLNode_OnClause *pNewOC = new SWQLNode_OnClause;
  1023. SWQLNode_RelExpr *pRelExpr = 0;
  1024. int nRes = rel_expr(&pRelExpr);
  1025. if (nRes)
  1026. return nRes;
  1027. pNewOC->m_pLeft = pRelExpr;
  1028. *pOC = pNewOC;
  1029. return NO_ERROR;
  1030. }
  1031. //***************************************************************************
  1032. //
  1033. // <rel_expr> ::= <rel_term> <rel_expr2>;
  1034. //
  1035. // We are creating a new expression or subexpression each time
  1036. // we enter this recursively. No inherited attributes are
  1037. // propagated to this production.
  1038. //
  1039. //***************************************************************************
  1040. int CWQLParser::rel_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1041. {
  1042. int nRes;
  1043. *pRelExpr = 0;
  1044. // Get the new node. This becomes a temporary root.
  1045. // =================================================
  1046. SWQLNode_RelExpr *pRE = 0;
  1047. nRes = rel_term(&pRE);
  1048. if (nRes)
  1049. return nRes;
  1050. // At this point, we have a possible root. If
  1051. // there are OR operations, the root will be
  1052. // replaced by the next function. Otherwise,
  1053. // the call will pass through pRE into pNewRoot.
  1054. // =============================================
  1055. SWQLNode_RelExpr *pNewRoot = 0;
  1056. nRes = rel_expr2(pRE, &pNewRoot);
  1057. if (nRes)
  1058. return nRes;
  1059. // Return the expression to the caller.
  1060. // ====================================
  1061. *pRelExpr = pNewRoot;
  1062. return NO_ERROR;
  1063. }
  1064. //***************************************************************************
  1065. //
  1066. // <rel_expr2> ::= OR <rel_term> <rel_expr2>;
  1067. // <rel_expr2> ::= <>;
  1068. //
  1069. //***************************************************************************
  1070. // done!
  1071. int CWQLParser::rel_expr2(
  1072. IN OUT SWQLNode_RelExpr *pLeftSide,
  1073. OUT SWQLNode_RelExpr **pNewRootRE
  1074. )
  1075. {
  1076. int nRes;
  1077. *pNewRootRE = pLeftSide; // Default for the nullable production
  1078. while (1)
  1079. {
  1080. // Build a series of OR subtrees bottom-up. We use iteration
  1081. // and pointer juggling to simulate recursion.
  1082. // ============================================================
  1083. if (m_nCurrentToken == WQL_TOK_OR)
  1084. {
  1085. if (!Next())
  1086. return LEXICAL_ERROR;
  1087. SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr;
  1088. pNewRoot->m_dwExprType = WQL_TOK_OR;
  1089. pNewRoot->m_pLeft = pLeftSide;
  1090. pLeftSide = pNewRoot;
  1091. *pNewRootRE = pNewRoot; // Communicate this fact to the caller
  1092. SWQLNode_RelExpr *pRight = 0;
  1093. if (nRes = rel_term(&pRight))
  1094. return nRes;
  1095. pNewRoot->m_pRight = pRight;
  1096. // Right node becomes the new subexpr
  1097. }
  1098. else break;
  1099. }
  1100. return NO_ERROR;
  1101. }
  1102. //***************************************************************************
  1103. //
  1104. // <rel_term> ::= <rel_simple_expr> <rel_term2>;
  1105. //
  1106. //***************************************************************************
  1107. // done!
  1108. int CWQLParser::rel_term(
  1109. OUT SWQLNode_RelExpr **pNewTerm
  1110. )
  1111. {
  1112. int nRes;
  1113. SWQLNode_RelExpr *pNewSimple = 0;
  1114. if (nRes = rel_simple_expr(&pNewSimple))
  1115. return nRes;
  1116. SWQLNode_RelExpr *pNewRoot = 0;
  1117. if (nRes = rel_term2(pNewSimple, &pNewRoot))
  1118. return nRes;
  1119. *pNewTerm = pNewRoot;
  1120. return NO_ERROR;
  1121. }
  1122. //***************************************************************************
  1123. //
  1124. // <rel_term2> ::= AND <rel_simple_expr> <rel_term2>;
  1125. // <rel_term2> ::= <>;
  1126. //
  1127. //***************************************************************************
  1128. // done!
  1129. int CWQLParser::rel_term2(
  1130. IN SWQLNode_RelExpr *pLeftSide, // Inherited
  1131. OUT SWQLNode_RelExpr **pNewRootRE // Synthesized
  1132. )
  1133. {
  1134. int nRes;
  1135. *pNewRootRE = pLeftSide; // Default for the nullable production
  1136. while (1)
  1137. {
  1138. // Build a series of AND subtrees bottom-up. We use iteration
  1139. // and pointer juggling to simulate recursion.
  1140. // ============================================================
  1141. if (m_nCurrentToken == WQL_TOK_AND)
  1142. {
  1143. if (!Next())
  1144. return LEXICAL_ERROR;
  1145. SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr;
  1146. pNewRoot->m_dwExprType = WQL_TOK_AND;
  1147. pNewRoot->m_pLeft = pLeftSide;
  1148. pLeftSide = pNewRoot;
  1149. *pNewRootRE = pNewRoot; // Communicate this fact to the caller
  1150. SWQLNode_RelExpr *pRight = 0;
  1151. if (nRes = rel_simple_expr(&pRight))
  1152. return nRes;
  1153. pNewRoot->m_pRight = pRight;
  1154. }
  1155. else break;
  1156. }
  1157. return NO_ERROR;
  1158. }
  1159. //***************************************************************************
  1160. //
  1161. // <rel_simple_expr> ::= NOT <rel_expr>;
  1162. // <rel_simple_expr> ::= OPEN_PAREN <rel_expr> CLOSE_PAREN;
  1163. // <rel_simple_expr> ::= <typed_expr>;
  1164. //
  1165. //***************************************************************************
  1166. // done!
  1167. int CWQLParser::rel_simple_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1168. {
  1169. int nRes;
  1170. *pRelExpr = 0; // Default
  1171. // NOT <rel_expr>
  1172. // ==============
  1173. if (m_nCurrentToken == WQL_TOK_NOT)
  1174. {
  1175. if (!Next())
  1176. return LEXICAL_ERROR;
  1177. // Allocate a NOT root and place the NOTed subexpr
  1178. // under it.
  1179. // ===============================================
  1180. SWQLNode_RelExpr *pNotRoot = new SWQLNode_RelExpr;
  1181. pNotRoot->m_dwExprType = WQL_TOK_NOT;
  1182. SWQLNode_RelExpr *pRelSubExpr = 0;
  1183. if (nRes = rel_expr(&pRelSubExpr))
  1184. return nRes;
  1185. pNotRoot->m_pLeft = pRelSubExpr;
  1186. pNotRoot->m_pRight = NULL; // intentional
  1187. *pRelExpr = pNotRoot;
  1188. return NO_ERROR;
  1189. }
  1190. // OPEN_PAREN <rel_expr> CLOSE_PAREN
  1191. // =================================
  1192. else if (m_nCurrentToken == WQL_TOK_OPEN_PAREN)
  1193. {
  1194. if (!Next())
  1195. return LEXICAL_ERROR;
  1196. SWQLNode_RelExpr *pSubExpr = 0;
  1197. if (rel_expr(&pSubExpr))
  1198. return SYNTAX_ERROR;
  1199. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1200. return SYNTAX_ERROR;
  1201. if (!Next())
  1202. return LEXICAL_ERROR;
  1203. *pRelExpr = pSubExpr;
  1204. return NO_ERROR;
  1205. }
  1206. // <typed_expr>
  1207. // ============
  1208. SWQLNode_RelExpr *pSubExpr = 0;
  1209. nRes = typed_expr(&pSubExpr);
  1210. if (nRes)
  1211. return nRes;
  1212. *pRelExpr = pSubExpr;
  1213. return NO_ERROR;
  1214. }
  1215. //***************************************************************************
  1216. //
  1217. // <typed_expr> ::= <typed_subexpr> <rel_op> <typed_subexpr_rh>;
  1218. //
  1219. //***************************************************************************
  1220. // done
  1221. int CWQLParser::typed_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1222. {
  1223. int nRes;
  1224. // Allocate a node for this typed expression.
  1225. // There are no possible child nodes, so <pRelExpr> this becomes
  1226. // a synthesized attribute.
  1227. // =============================================================
  1228. SWQLNode_RelExpr *pRE = new SWQLNode_RelExpr;
  1229. pRE->m_dwExprType = WQL_TOK_TYPED_EXPR;
  1230. *pRelExpr = pRE;
  1231. SWQLTypedExpr *pTE = new SWQLTypedExpr;
  1232. // Look at the left hand side.
  1233. // ===========================
  1234. nRes = typed_subexpr(pTE);
  1235. if (nRes)
  1236. return nRes;
  1237. int nOperator;
  1238. // Get the operator.
  1239. // =================
  1240. nRes = rel_op(nOperator);
  1241. if (nRes)
  1242. return nRes;
  1243. pTE->m_dwRelOperator = DWORD(nOperator);
  1244. if (nOperator == WQL_TOK_ISNULL || nOperator == WQL_TOK_NOT_NULL)
  1245. {
  1246. pRE->m_pTypedExpr = pTE;
  1247. return NO_ERROR;
  1248. }
  1249. // Get the right-hand side.
  1250. // ========================
  1251. nRes = typed_subexpr_rh(pTE);
  1252. if (nRes)
  1253. return nRes;
  1254. // Check for IN, NOT IN and a const-list, to change the operator
  1255. // to a more specific variety.
  1256. // =============================================================
  1257. if (pTE->m_pConstList)
  1258. {
  1259. if (pTE->m_dwRelOperator == WQL_TOK_IN)
  1260. pTE->m_dwRelOperator = WQL_TOK_IN_CONST_LIST;
  1261. if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN)
  1262. pTE->m_dwRelOperator = WQL_TOK_NOT_IN_CONST_LIST;
  1263. }
  1264. // Post-processing. If the left side is a const and the right
  1265. // side is a col-ref, flip the operator and swap so that
  1266. // such expressions are normalized with the constant on the
  1267. // right hand side and the column on the left.
  1268. // ============================================================
  1269. if (pTE->m_pConstValue && pTE->m_pJoinColRef)
  1270. {
  1271. pTE->m_dwRelOperator = FlipOperator(pTE->m_dwRelOperator);
  1272. pTE->m_pColRef = pTE->m_pJoinColRef;
  1273. pTE->m_pTableRef = pTE->m_pJoinTableRef;
  1274. pTE->m_pJoinTableRef = 0;
  1275. pTE->m_pJoinColRef = 0;
  1276. DWORD dwTmp = pTE->m_dwRightFlags;
  1277. pTE->m_dwRightFlags = pTE->m_dwLeftFlags;
  1278. pTE->m_dwLeftFlags = dwTmp;
  1279. // Interchange function references.
  1280. // ================================
  1281. pTE->m_pIntrinsicFuncOnColRef = pTE->m_pIntrinsicFuncOnJoinColRef;
  1282. pTE->m_pIntrinsicFuncOnJoinColRef = 0;
  1283. }
  1284. pRE->m_pTypedExpr = pTE;
  1285. return NO_ERROR;
  1286. }
  1287. //***************************************************************************
  1288. //
  1289. // <typed_subexpr> ::= <col_ref>;
  1290. // <typed_subexpr> ::= <function_call>;
  1291. // <typed_subexpr> ::= <typed_const>;
  1292. //
  1293. //***************************************************************************
  1294. int CWQLParser::typed_subexpr(
  1295. SWQLTypedExpr *pTE
  1296. )
  1297. {
  1298. int nRes;
  1299. BOOL bStripTrailingParen = FALSE;
  1300. SWQLQualifiedName *pColRef = 0;
  1301. LPWSTR pFuncHolder = 0;
  1302. // Check for <function_call>
  1303. // =========================
  1304. if (m_nCurrentToken == WQL_TOK_UPPER)
  1305. {
  1306. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  1307. pFuncHolder = Macro_CloneLPWSTR(L"UPPER");
  1308. if (!Next())
  1309. return LEXICAL_ERROR;
  1310. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1311. return SYNTAX_ERROR;
  1312. if (!Next())
  1313. return LEXICAL_ERROR;
  1314. bStripTrailingParen = TRUE;
  1315. }
  1316. if (m_nCurrentToken == WQL_TOK_LOWER)
  1317. {
  1318. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  1319. pFuncHolder = Macro_CloneLPWSTR(L"LOWER");
  1320. if (!Next())
  1321. return LEXICAL_ERROR;
  1322. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1323. return SYNTAX_ERROR;
  1324. if (!Next())
  1325. return LEXICAL_ERROR;
  1326. bStripTrailingParen = TRUE;
  1327. }
  1328. if (
  1329. m_nCurrentToken == WQL_TOK_DATEPART ||
  1330. m_nCurrentToken == WQL_TOK_QUALIFIER ||
  1331. m_nCurrentToken == WQL_TOK_ISNULL
  1332. )
  1333. {
  1334. nRes = function_call(TRUE, pTE);
  1335. if (nRes)
  1336. return nRes;
  1337. return NO_ERROR;
  1338. }
  1339. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  1340. m_nCurrentToken == WQL_TOK_INT ||
  1341. m_nCurrentToken == WQL_TOK_REAL ||
  1342. m_nCurrentToken == WQL_TOK_CHAR ||
  1343. m_nCurrentToken == WQL_TOK_PROMPT ||
  1344. m_nCurrentToken == WQL_TOK_NULL
  1345. )
  1346. {
  1347. SWQLTypedConst *pTC = 0;
  1348. nRes = typed_const(&pTC);
  1349. if (nRes)
  1350. return nRes;
  1351. pTE->m_pConstValue = pTC;
  1352. pTE->m_dwLeftFlags |= WQL_FLAG_CONST; // Intentional!
  1353. pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder;
  1354. goto Exit;
  1355. }
  1356. // If here, must be a <col_ref>.
  1357. // =============================
  1358. nRes = col_ref(&pColRef); // TBD
  1359. if (nRes)
  1360. return nRes;
  1361. pTE->m_pIntrinsicFuncOnColRef = pFuncHolder;
  1362. // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the
  1363. // qualified name and extract the table and col name.
  1364. // ============================================================================
  1365. if (pColRef->m_aFields.Size() == 1)
  1366. {
  1367. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1368. pTE->m_pColRef = Macro_CloneLPWSTR(pCol->m_pName);
  1369. pTE->m_dwLeftFlags |= WQL_FLAG_COLUMN;
  1370. if (pCol->m_bArrayRef)
  1371. {
  1372. pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF;
  1373. pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex;
  1374. }
  1375. }
  1376. else if (pColRef->m_aFields.Size() == 2)
  1377. {
  1378. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1];
  1379. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1380. pTE->m_pColRef = Macro_CloneLPWSTR(pCol->m_pName);
  1381. pTE->m_pTableRef = Macro_CloneLPWSTR(pTbl->m_pName);
  1382. pTE->m_dwLeftFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  1383. if (pCol->m_bArrayRef)
  1384. {
  1385. pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF;
  1386. pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex;
  1387. }
  1388. }
  1389. // If UPPER or LOWER was used, we have to strip a trailing
  1390. // parenthesis.
  1391. // =======================================================
  1392. Exit:
  1393. delete pColRef;
  1394. if (bStripTrailingParen)
  1395. {
  1396. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1397. return SYNTAX_ERROR;
  1398. if (!Next())
  1399. return LEXICAL_ERROR;
  1400. }
  1401. return NO_ERROR;
  1402. }
  1403. //***************************************************************************
  1404. //
  1405. // <typed_subexpr_rh> ::= <function_call>;
  1406. // <typed_subexpr_rh> ::= <typed_const>;
  1407. // <typed_subexpr_rh> ::= <col_ref>;
  1408. //
  1409. // <typed_subexpr_rh> ::= <in_clause>; // Operator must be _IN or _NOT_IN
  1410. //
  1411. //***************************************************************************
  1412. int CWQLParser::typed_subexpr_rh(IN SWQLTypedExpr *pTE)
  1413. {
  1414. int nRes;
  1415. BOOL bStripTrailingParen = FALSE;
  1416. SWQLQualifiedName *pColRef = 0;
  1417. LPWSTR pFuncHolder = 0;
  1418. // Check for <function_call>
  1419. // =========================
  1420. if (m_nCurrentToken == WQL_TOK_UPPER)
  1421. {
  1422. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  1423. pFuncHolder = Macro_CloneLPWSTR(L"UPPER");
  1424. if (!Next())
  1425. return LEXICAL_ERROR;
  1426. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1427. return SYNTAX_ERROR;
  1428. if (!Next())
  1429. return LEXICAL_ERROR;
  1430. bStripTrailingParen = TRUE;
  1431. }
  1432. if (m_nCurrentToken == WQL_TOK_LOWER)
  1433. {
  1434. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  1435. pFuncHolder = Macro_CloneLPWSTR(L"LOWER");
  1436. if (!Next())
  1437. return LEXICAL_ERROR;
  1438. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1439. return SYNTAX_ERROR;
  1440. if (!Next())
  1441. return LEXICAL_ERROR;
  1442. bStripTrailingParen = TRUE;
  1443. }
  1444. if (m_nCurrentToken == WQL_TOK_DATEPART ||
  1445. m_nCurrentToken == WQL_TOK_QUALIFIER ||
  1446. m_nCurrentToken == WQL_TOK_ISNULL
  1447. )
  1448. {
  1449. nRes = function_call(FALSE, pTE);
  1450. if (nRes)
  1451. return nRes;
  1452. return NO_ERROR;
  1453. }
  1454. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  1455. m_nCurrentToken == WQL_TOK_INT ||
  1456. m_nCurrentToken == WQL_TOK_REAL ||
  1457. m_nCurrentToken == WQL_TOK_CHAR ||
  1458. m_nCurrentToken == WQL_TOK_PROMPT ||
  1459. m_nCurrentToken == WQL_TOK_NULL
  1460. )
  1461. {
  1462. SWQLTypedConst *pTC = 0;
  1463. nRes = typed_const(&pTC);
  1464. if (nRes)
  1465. return nRes;
  1466. pTE->m_pConstValue = pTC;
  1467. pTE->m_dwRightFlags |= WQL_FLAG_CONST;
  1468. pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder;
  1469. // Check for BETWEEN operator, since we have
  1470. // the other end of the range to parse.
  1471. // =========================================
  1472. if (pTE->m_dwRelOperator == WQL_TOK_BETWEEN ||
  1473. pTE->m_dwRelOperator == WQL_TOK_NOT_BETWEEN)
  1474. {
  1475. if (m_nCurrentToken != WQL_TOK_AND)
  1476. return SYNTAX_ERROR;
  1477. if (!Next())
  1478. return LEXICAL_ERROR;
  1479. SWQLTypedConst *pTC = 0;
  1480. nRes = typed_const(&pTC);
  1481. if (nRes)
  1482. return nRes;
  1483. pTE->m_pConstValue2 = pTC;
  1484. pTE->m_dwRightFlags |= WQL_FLAG_CONST_RANGE;
  1485. }
  1486. goto Exit;
  1487. }
  1488. if (m_nCurrentToken == WQL_TOK_OPEN_PAREN)
  1489. {
  1490. // IN clause.
  1491. nRes = in_clause(pTE);
  1492. if (nRes)
  1493. return nRes;
  1494. goto Exit;
  1495. }
  1496. // If here, must be a <col_ref>.
  1497. // =============================
  1498. nRes = col_ref(&pColRef);
  1499. if (nRes)
  1500. return nRes;
  1501. pTE->m_pIntrinsicFuncOnJoinColRef = pFuncHolder;
  1502. // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the
  1503. // qualified name and extract the table and col name.
  1504. // ============================================================================
  1505. if (pColRef->m_aFields.Size() == 1)
  1506. {
  1507. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1508. pTE->m_pJoinColRef = Macro_CloneLPWSTR(pCol->m_pName);
  1509. pTE->m_dwRightFlags |= WQL_FLAG_COLUMN;
  1510. if (pCol->m_bArrayRef)
  1511. {
  1512. pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF;
  1513. pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex;
  1514. }
  1515. }
  1516. else if (pColRef->m_aFields.Size() == 2)
  1517. {
  1518. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1];
  1519. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1520. pTE->m_pJoinColRef = Macro_CloneLPWSTR(pCol->m_pName);
  1521. pTE->m_pJoinTableRef = Macro_CloneLPWSTR(pTbl->m_pName);
  1522. pTE->m_dwRightFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  1523. if (pCol->m_bArrayRef)
  1524. {
  1525. pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF;
  1526. pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex;
  1527. }
  1528. }
  1529. Exit:
  1530. delete pColRef;
  1531. if (bStripTrailingParen)
  1532. {
  1533. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1534. return SYNTAX_ERROR;
  1535. if (!Next())
  1536. return LEXICAL_ERROR;
  1537. }
  1538. return NO_ERROR;
  1539. }
  1540. //*****************************************************************************************
  1541. //
  1542. // <rel_op> ::= WQL_TOK_LE;
  1543. // <rel_op> ::= WQL_TOK_LT;
  1544. // <rel_op> ::= WQL_TOK_GE;
  1545. // <rel_op> ::= WQL_TOK_GT;
  1546. // <rel_op> ::= WQL_TOK_EQ;
  1547. // <rel_op> ::= WQL_TOK_NE;
  1548. // <rel_op> ::= WQL_TOK_LIKE;
  1549. // <rel_op> ::= WQL_TOK_BETWEEN;
  1550. // <rel_op> ::= WQL_TOK_IS <is_continuator>;
  1551. // <rel_op> ::= WQL_TOK_ISA;
  1552. // <rel_op> ::= WQL_TOK_IN;
  1553. // <rel_op> ::= WQL_TOK_NOT <not_continuator>;
  1554. //
  1555. // Operator type is returned via <nReturnedOp>
  1556. //
  1557. //*****************************************************************************************
  1558. // done
  1559. int CWQLParser::rel_op(OUT int & nReturnedOp)
  1560. {
  1561. int nRes;
  1562. nReturnedOp = WQL_TOK_ERROR;
  1563. switch (m_nCurrentToken)
  1564. {
  1565. case WQL_TOK_LE:
  1566. nReturnedOp = WQL_TOK_LE;
  1567. if (!Next())
  1568. return LEXICAL_ERROR;
  1569. return NO_ERROR;
  1570. case WQL_TOK_LT:
  1571. nReturnedOp = WQL_TOK_LT;
  1572. if (!Next())
  1573. return LEXICAL_ERROR;
  1574. return NO_ERROR;
  1575. case WQL_TOK_GE:
  1576. nReturnedOp = WQL_TOK_GE;
  1577. if (!Next())
  1578. return LEXICAL_ERROR;
  1579. return NO_ERROR;
  1580. case WQL_TOK_GT:
  1581. nReturnedOp = WQL_TOK_GT;
  1582. if (!Next())
  1583. return LEXICAL_ERROR;
  1584. return NO_ERROR;
  1585. case WQL_TOK_EQ:
  1586. nReturnedOp = WQL_TOK_EQ;
  1587. if (!Next())
  1588. return LEXICAL_ERROR;
  1589. return NO_ERROR;
  1590. case WQL_TOK_NE:
  1591. nReturnedOp = WQL_TOK_NE;
  1592. if (!Next())
  1593. return LEXICAL_ERROR;
  1594. return NO_ERROR;
  1595. case WQL_TOK_LIKE:
  1596. nReturnedOp = WQL_TOK_LIKE;
  1597. if (!Next())
  1598. return LEXICAL_ERROR;
  1599. return NO_ERROR;
  1600. case WQL_TOK_BETWEEN:
  1601. nReturnedOp = WQL_TOK_BETWEEN;
  1602. if (!Next())
  1603. return LEXICAL_ERROR;
  1604. return NO_ERROR;
  1605. case WQL_TOK_IS:
  1606. if (!Next())
  1607. return LEXICAL_ERROR;
  1608. nRes = is_continuator(nReturnedOp);
  1609. return nRes;
  1610. case WQL_TOK_ISA:
  1611. nReturnedOp = WQL_TOK_ISA;
  1612. if (!Next())
  1613. return LEXICAL_ERROR;
  1614. return NO_ERROR;
  1615. case WQL_TOK_IN:
  1616. nReturnedOp = WQL_TOK_IN;
  1617. if (!Next())
  1618. return LEXICAL_ERROR;
  1619. return NO_ERROR;
  1620. case WQL_TOK_NOT:
  1621. if (!Next())
  1622. return LEXICAL_ERROR;
  1623. nRes = not_continuator(nReturnedOp);
  1624. return nRes;
  1625. }
  1626. return SYNTAX_ERROR;
  1627. }
  1628. //*****************************************************************************************
  1629. //
  1630. // <typed_const> ::= WQL_TOK_QSTRING;
  1631. // <typed_const> ::= WQL_TOK_INT;
  1632. // <typed_const> ::= WQL_TOK_REAL;
  1633. // <typed_const> ::= WQL_TOK_PROMPT;
  1634. // <typed_const> ::= WQL_TOK_NULL;
  1635. //
  1636. //*****************************************************************************************
  1637. // done
  1638. int CWQLParser::typed_const(OUT SWQLTypedConst **pRetVal)
  1639. {
  1640. SWQLTypedConst *pNew = new SWQLTypedConst;
  1641. *pRetVal = pNew;
  1642. if (m_nCurrentToken == WQL_TOK_QSTRING
  1643. || m_nCurrentToken == WQL_TOK_PROMPT)
  1644. {
  1645. pNew->m_dwType = VT_LPWSTR;
  1646. pNew->m_bPrompt = (m_nCurrentToken == WQL_TOK_PROMPT);
  1647. pNew->m_Value.m_pString = Macro_CloneLPWSTR(m_pTokenText);
  1648. if (!Next())
  1649. return LEXICAL_ERROR;
  1650. return NO_ERROR;
  1651. }
  1652. if (m_nCurrentToken == WQL_TOK_INT)
  1653. {
  1654. pNew->m_dwType = VT_I4;
  1655. pNew->m_Value.m_lValue = GetTokenLong();
  1656. if (!Next())
  1657. return LEXICAL_ERROR;
  1658. return NO_ERROR;
  1659. }
  1660. if (m_nCurrentToken == WQL_TOK_REAL)
  1661. {
  1662. pNew->m_dwType = VT_R8;
  1663. char buf[64];
  1664. sprintf(buf, "%S", m_pTokenText);
  1665. pNew->m_Value.m_dblValue = atof(buf);
  1666. if (!Next())
  1667. return LEXICAL_ERROR;
  1668. return NO_ERROR;
  1669. }
  1670. if (m_nCurrentToken == WQL_TOK_NULL)
  1671. {
  1672. pNew->m_dwType = VT_NULL;
  1673. if (!Next())
  1674. return LEXICAL_ERROR;
  1675. return NO_ERROR;
  1676. }
  1677. // Unrecognized constant.
  1678. // ======================
  1679. *pRetVal = 0;
  1680. delete pNew;
  1681. return SYNTAX_ERROR;
  1682. }
  1683. //*****************************************************************************************
  1684. //
  1685. // <datepart_call> ::=
  1686. // WQL_TOK_OPEN_PAREN
  1687. // WQL_TOK_IDENT // yy, mm,dd, hh, mm, ss, year, month, etc.
  1688. // WQL_TOK_COMMA
  1689. // <col_ref>
  1690. // WQL_TOK_CLOSE_PAREN
  1691. //
  1692. //*****************************************************************************************
  1693. static WqlKeyword DateKeyWords[] = // Keep this alphabetized for binary search
  1694. {
  1695. L"DAY", WQL_TOK_DAY,
  1696. L"DD", WQL_TOK_DAY,
  1697. L"HH", WQL_TOK_HOUR,
  1698. L"HOUR", WQL_TOK_HOUR,
  1699. L"MI", WQL_TOK_MINUTE,
  1700. L"MILLISECOND", WQL_TOK_MILLISECOND,
  1701. L"MINUTE", WQL_TOK_MINUTE,
  1702. L"MONTH", WQL_TOK_MONTH,
  1703. L"MM", WQL_TOK_MONTH,
  1704. L"MS", WQL_TOK_MILLISECOND,
  1705. L"YEAR", WQL_TOK_YEAR,
  1706. L"YY", WQL_TOK_YEAR
  1707. };
  1708. const int NumDateKeywords = sizeof(DateKeyWords)/sizeof(WqlKeyword);
  1709. int CWQLParser::datepart_call(OUT SWQLNode_Datepart **pRetDP)
  1710. {
  1711. DWORD dwDatepartTok = 0;
  1712. int nRes;
  1713. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1714. return SYNTAX_ERROR;
  1715. if (!Next())
  1716. return LEXICAL_ERROR;
  1717. if (m_nCurrentToken != WQL_TOK_IDENT)
  1718. return SYNTAX_ERROR;
  1719. // Ident must be one of the DATEPART identifiers.
  1720. // ==============================================
  1721. BOOL bFound = FALSE;
  1722. int l = 0, u = NumDateKeywords - 1;
  1723. while (l <= u)
  1724. {
  1725. int m = (l + u) / 2;
  1726. if (_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) < 0)
  1727. u = m - 1;
  1728. else if (_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) > 0)
  1729. l = m + 1;
  1730. else // Match
  1731. {
  1732. bFound = TRUE;
  1733. dwDatepartTok = DateKeyWords[m].m_nTokenCode;
  1734. break;
  1735. }
  1736. }
  1737. if (!bFound)
  1738. return SYNTAX_ERROR;
  1739. // If here, we know the date part.
  1740. // ===============================
  1741. if (!Next())
  1742. return LEXICAL_ERROR;
  1743. if (m_nCurrentToken != WQL_TOK_COMMA)
  1744. return SYNTAX_ERROR;
  1745. if (!Next())
  1746. return LEXICAL_ERROR;
  1747. SWQLQualifiedName *pQN = 0;
  1748. nRes = col_ref(&pQN);
  1749. if (nRes)
  1750. return nRes;
  1751. SWQLColRef *pCR = 0;
  1752. nRes = QNameToSWQLColRef(pQN, &pCR);
  1753. if (nRes)
  1754. return INVALID_PARAMETER;
  1755. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1756. return SYNTAX_ERROR;
  1757. if (!Next())
  1758. return LEXICAL_ERROR;
  1759. // Return the new node.
  1760. // ====================
  1761. SWQLNode_Datepart *pDP = new SWQLNode_Datepart;
  1762. pDP->m_nDatepart = dwDatepartTok;
  1763. pDP->m_pColRef = pCR;
  1764. *pRetDP = pDP;
  1765. return NO_ERROR;
  1766. }
  1767. //*****************************************************************************************
  1768. //
  1769. // <function_call> ::= WQL_TOK_UPPER <function_call_parms>;
  1770. // <function_call> ::= WQL_TOK_LOWER <function_call_parms>;
  1771. // <function_call> ::= WQL_TOK_DATEPART <datepart_call>;
  1772. // <function_call> ::= WQL_TOK_QUALIFIER <function_call_parms>;
  1773. // <function_call> ::= WQL_TOK_ISNULL <function_call_parms>;
  1774. //
  1775. //*****************************************************************************************
  1776. int CWQLParser::function_call(
  1777. IN BOOL bLeftSide,
  1778. IN SWQLTypedExpr *pTE
  1779. )
  1780. {
  1781. int nRes;
  1782. SWQLNode_Datepart *pDP = 0;
  1783. switch (m_nCurrentToken)
  1784. {
  1785. case WQL_TOK_DATEPART:
  1786. {
  1787. if (!Next())
  1788. return LEXICAL_ERROR;
  1789. nRes = datepart_call(&pDP);
  1790. if (nRes)
  1791. return nRes;
  1792. if (bLeftSide)
  1793. {
  1794. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  1795. pTE->m_pLeftFunction = pDP;
  1796. pTE->m_pIntrinsicFuncOnColRef = Macro_CloneLPWSTR(L"DATEPART");
  1797. }
  1798. else
  1799. {
  1800. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  1801. pTE->m_pRightFunction = pDP;
  1802. pTE->m_pIntrinsicFuncOnJoinColRef = Macro_CloneLPWSTR(L"DATEPART");
  1803. }
  1804. return NO_ERROR;
  1805. }
  1806. case WQL_TOK_QUALIFIER:
  1807. trace(("EMIT: QUALIFIER\n"));
  1808. if (!Next())
  1809. return LEXICAL_ERROR;
  1810. nRes = function_call_parms();
  1811. return nRes;
  1812. case WQL_TOK_ISNULL:
  1813. trace(("EMIT: ISNULL\n"));
  1814. if (!Next())
  1815. return LEXICAL_ERROR;
  1816. nRes = function_call_parms();
  1817. return nRes;
  1818. }
  1819. return SYNTAX_ERROR;
  1820. }
  1821. //*****************************************************************************************
  1822. //
  1823. // <function_call_parms> ::=
  1824. // WQL_TOK_OPEN_PAREN
  1825. // <func_args>
  1826. // WQL_TOK_CLOSE_PAREN
  1827. //
  1828. //*****************************************************************************************
  1829. int CWQLParser::function_call_parms()
  1830. {
  1831. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1832. return SYNTAX_ERROR;
  1833. if (!Next())
  1834. return LEXICAL_ERROR;
  1835. int nRes = func_args();
  1836. if (nRes)
  1837. return nRes;
  1838. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1839. return SYNTAX_ERROR;
  1840. if (!Next())
  1841. return LEXICAL_ERROR;
  1842. return NO_ERROR;
  1843. }
  1844. //*****************************************************************************************
  1845. //
  1846. // <func_args> ::= <func_arg> <func_arg_list>;
  1847. // <func_arg_list> ::= WQL_TOK_COMMA <func_arg> <func_arg_list>;
  1848. // <func_arg_list> ::= <>;
  1849. //
  1850. //*****************************************************************************************
  1851. int CWQLParser::func_args()
  1852. {
  1853. int nRes;
  1854. while (1)
  1855. {
  1856. nRes = func_arg();
  1857. if (nRes)
  1858. return nRes;
  1859. if (m_nCurrentToken != WQL_TOK_COMMA)
  1860. break;
  1861. if (!Next())
  1862. return LEXICAL_ERROR;
  1863. }
  1864. return NO_ERROR;
  1865. }
  1866. //*****************************************************************************************
  1867. //
  1868. // <func_arg> ::= <typed_const>;
  1869. // <func_arg> ::= <col_ref>;
  1870. //
  1871. //*****************************************************************************************
  1872. int CWQLParser::func_arg()
  1873. {
  1874. SWQLQualifiedName *pColRef = 0;
  1875. int nRes;
  1876. if (m_nCurrentToken == WQL_TOK_IDENT)
  1877. {
  1878. nRes = col_ref(&pColRef);
  1879. return nRes;
  1880. }
  1881. SWQLTypedConst *pTC = 0;
  1882. return typed_const(&pTC);
  1883. }
  1884. // Tokens which can follow IS
  1885. // ===========================
  1886. //*****************************************************************************************
  1887. //
  1888. // <is_continuator> ::= WQL_TOK_LIKE;
  1889. // <is_continuator> ::= WQL_TOK_BEFORE;
  1890. // <is_continuator> ::= WQL_TOK_AFTER;
  1891. // <is_continuator> ::= WQL_TOK_BETWEEN;
  1892. // <is_continuator> ::= WQL_TOK_NULL;
  1893. // <is_continuator> ::= WQL_TOK_NOT <not_continuator>;
  1894. // <is_continuator> ::= WQL_TOK_IN;
  1895. // <is_continuator> ::= WQL_TOK_A;
  1896. //
  1897. //*****************************************************************************************
  1898. // done
  1899. int CWQLParser::is_continuator(int & nReturnedOp)
  1900. {
  1901. int nRes;
  1902. nReturnedOp = WQL_TOK_ERROR;
  1903. switch (m_nCurrentToken)
  1904. {
  1905. case WQL_TOK_LIKE:
  1906. nReturnedOp = WQL_TOK_LIKE;
  1907. if (!Next())
  1908. return LEXICAL_ERROR;
  1909. return NO_ERROR;
  1910. case WQL_TOK_BEFORE:
  1911. nReturnedOp = WQL_TOK_BEFORE;
  1912. if (!Next())
  1913. return LEXICAL_ERROR;
  1914. return NO_ERROR;
  1915. case WQL_TOK_AFTER:
  1916. nReturnedOp = WQL_TOK_AFTER;
  1917. if (!Next())
  1918. return LEXICAL_ERROR;
  1919. return NO_ERROR;
  1920. case WQL_TOK_BETWEEN:
  1921. nReturnedOp = WQL_TOK_BETWEEN;
  1922. if (!Next())
  1923. return LEXICAL_ERROR;
  1924. return NO_ERROR;
  1925. case WQL_TOK_NULL:
  1926. nReturnedOp = WQL_TOK_ISNULL;
  1927. if (!Next())
  1928. return LEXICAL_ERROR;
  1929. return NO_ERROR;
  1930. case WQL_TOK_NOT:
  1931. if (!Next())
  1932. return LEXICAL_ERROR;
  1933. nRes = not_continuator(nReturnedOp);
  1934. return nRes;
  1935. case WQL_TOK_IN:
  1936. nReturnedOp = WQL_TOK_IN;
  1937. if (!Next())
  1938. return LEXICAL_ERROR;
  1939. return NO_ERROR;
  1940. case WQL_TOK_A:
  1941. nReturnedOp = WQL_TOK_ISA;
  1942. if (!Next())
  1943. return LEXICAL_ERROR;
  1944. return NO_ERROR;
  1945. }
  1946. return SYNTAX_ERROR;
  1947. }
  1948. //*****************************************************************************************
  1949. //
  1950. // <not_continuator> ::= WQL_TOK_LIKE;
  1951. // <not_continuator> ::= WQL_TOK_BEFORE;
  1952. // <not_continuator> ::= WQL_TOK_AFTER;
  1953. // <not_continuator> ::= WQL_TOK_BETWEEN;
  1954. // <not_continuator> ::= WQL_TOK_NULL;
  1955. // <not_continuator> ::= WQL_TOK_IN;
  1956. //
  1957. // Returns WQL_TOK_NOT_LIKE, WQL_TOK_NOT_BEFORE, WQL_TOK_NOT_AFTER, WQL_TOK_NOT_BETWEEN
  1958. // WQL_TOK_NOT_NULL, WQL_TOK_NOT_IN
  1959. //
  1960. //*****************************************************************************************
  1961. // done
  1962. int CWQLParser::not_continuator(int & nReturnedOp)
  1963. {
  1964. nReturnedOp = WQL_TOK_ERROR;
  1965. switch (m_nCurrentToken)
  1966. {
  1967. case WQL_TOK_LIKE:
  1968. nReturnedOp = WQL_TOK_NOT_LIKE;
  1969. if (!Next())
  1970. return LEXICAL_ERROR;
  1971. return NO_ERROR;
  1972. case WQL_TOK_BEFORE:
  1973. nReturnedOp = WQL_TOK_NOT_BEFORE;
  1974. if (!Next())
  1975. return LEXICAL_ERROR;
  1976. return NO_ERROR;
  1977. case WQL_TOK_AFTER:
  1978. nReturnedOp = WQL_TOK_NOT_AFTER;
  1979. if (!Next())
  1980. return LEXICAL_ERROR;
  1981. return NO_ERROR;
  1982. case WQL_TOK_BETWEEN:
  1983. nReturnedOp = WQL_TOK_NOT_BETWEEN;
  1984. if (!Next())
  1985. return LEXICAL_ERROR;
  1986. return NO_ERROR;
  1987. case WQL_TOK_NULL:
  1988. nReturnedOp = WQL_TOK_NOT_NULL;
  1989. if (!Next())
  1990. return LEXICAL_ERROR;
  1991. return NO_ERROR;
  1992. case WQL_TOK_IN:
  1993. nReturnedOp = WQL_TOK_NOT_IN;
  1994. if (!Next())
  1995. return LEXICAL_ERROR;
  1996. return NO_ERROR;
  1997. case WQL_TOK_A:
  1998. nReturnedOp = WQL_TOK_NOT_A;
  1999. if (!Next())
  2000. return LEXICAL_ERROR;
  2001. return NO_ERROR;
  2002. }
  2003. return SYNTAX_ERROR;
  2004. }
  2005. //*****************************************************************************************
  2006. //
  2007. // <in_clause> ::= WQL_TOK_OPEN_PAREN <in_type> WQL_TOK_CLOSE_PAREN;
  2008. // <in_type> ::= <subselect_stmt>;
  2009. // <in_type> ::= <const_list>;
  2010. // <in_type> ::= <qualified_name>;
  2011. //
  2012. //*****************************************************************************************
  2013. int CWQLParser::in_clause(IN SWQLTypedExpr *pTE)
  2014. {
  2015. int nRes;
  2016. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  2017. return SYNTAX_ERROR;
  2018. int nStPos = m_pLexer->GetCurPos();
  2019. if (!Next())
  2020. return LEXICAL_ERROR;
  2021. if (m_nCurrentToken == WQL_TOK_SELECT)
  2022. {
  2023. SWQLNode_Select *pSel = 0;
  2024. nRes = subselect_stmt(&pSel);
  2025. if (nRes)
  2026. return nRes;
  2027. pSel->m_nStPos = nStPos;
  2028. pSel->m_nEndPos = m_pLexer->GetCurPos() - 1;
  2029. // Translate the IN / NOT IN operator to the specific
  2030. // case of subselects.
  2031. // ==================================================
  2032. if (pTE->m_dwRelOperator == WQL_TOK_IN)
  2033. pTE->m_dwRelOperator = WQL_TOK_IN_SUBSELECT;
  2034. else if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN)
  2035. pTE->m_dwRelOperator = WQL_TOK_NOT_IN_SUBSELECT;
  2036. pTE->m_pSubSelect = pSel;
  2037. }
  2038. else if (m_nCurrentToken == WQL_TOK_IDENT)
  2039. {
  2040. nRes = qualified_name(0);
  2041. if (nRes)
  2042. return nRes;
  2043. }
  2044. // If here, we must have a const-list.
  2045. // ===================================
  2046. else
  2047. {
  2048. SWQLConstList *pCL = 0;
  2049. nRes = const_list(&pCL);
  2050. if (nRes)
  2051. return nRes;
  2052. pTE->m_pConstList = pCL;
  2053. }
  2054. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  2055. return SYNTAX_ERROR;
  2056. if (!Next())
  2057. return LEXICAL_ERROR;
  2058. return NO_ERROR;
  2059. }
  2060. //*****************************************************************************************
  2061. //
  2062. // <const_list> ::= <typed_const> <const_list2>;
  2063. // <const_list2> ::= WQL_TOK_COMMA <typed_const> <const_list2>;
  2064. // <const_list2> ::= <>;
  2065. //
  2066. //*****************************************************************************************
  2067. // done
  2068. int CWQLParser::const_list(SWQLConstList **pRetVal)
  2069. {
  2070. int nRes;
  2071. SWQLConstList *pCL = new SWQLConstList;
  2072. *pRetVal = 0;
  2073. while (1)
  2074. {
  2075. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  2076. m_nCurrentToken == WQL_TOK_INT ||
  2077. m_nCurrentToken == WQL_TOK_REAL ||
  2078. m_nCurrentToken == WQL_TOK_CHAR ||
  2079. m_nCurrentToken == WQL_TOK_PROMPT ||
  2080. m_nCurrentToken == WQL_TOK_NULL
  2081. )
  2082. {
  2083. SWQLTypedConst *pTC = 0;
  2084. nRes = typed_const(&pTC);
  2085. if (nRes)
  2086. {
  2087. delete pTC;
  2088. delete pCL;
  2089. return nRes;
  2090. }
  2091. pCL->Add(pTC);
  2092. }
  2093. if (m_nCurrentToken != WQL_TOK_COMMA)
  2094. break;
  2095. // If here, a comma, indicating a following constant.
  2096. // ==================================================
  2097. if (!Next())
  2098. {
  2099. delete pCL;
  2100. return LEXICAL_ERROR;
  2101. }
  2102. }
  2103. *pRetVal = pCL;
  2104. return NO_ERROR;
  2105. }
  2106. //*****************************************************************************************
  2107. //
  2108. // QUALIFIED_NAME
  2109. //
  2110. // This recognizes a name separated by dots, and recognizes any array references which
  2111. // may occur with those names:
  2112. // a
  2113. // a.b
  2114. // a[n].b[n]
  2115. // a.b.c.d
  2116. // a.b[2].c.d.e[3].f
  2117. // ...etc.
  2118. //
  2119. // <qualified_name> ::= WQL_TOK_IDENT <qualified_name2>;
  2120. // <qualified_name2> ::= WQL_TOK_DOT WQL_TOK_IDENT <qualified_name2>;
  2121. //
  2122. // <qualified_name2> ::=
  2123. // WQL_TOK_OPEN_BRACKET
  2124. // WQL_TOK_INT
  2125. // WQL_TOK_CLOSEBRACKET
  2126. // <qname_becomes_array_ref>
  2127. // <qualified_name2>;
  2128. //
  2129. // <qname_becomes_array_ref> ::= <>; // Dummy to enforce array semantics
  2130. //
  2131. // <qualified_name2> ::= <>;
  2132. //
  2133. //*****************************************************************************************
  2134. // done
  2135. int CWQLParser::qualified_name(OUT SWQLQualifiedName **pRetVal)
  2136. {
  2137. if (pRetVal == 0)
  2138. return INVALID_PARAMETER;
  2139. *pRetVal = 0;
  2140. if (m_nCurrentToken != WQL_TOK_IDENT)
  2141. return SYNTAX_ERROR;
  2142. SWQLQualifiedName QN;
  2143. SWQLQualifiedNameField *pQNF;
  2144. pQNF = new SWQLQualifiedNameField;
  2145. pQNF->m_pName = Macro_CloneLPWSTR(m_pTokenText);
  2146. QN.Add(pQNF);
  2147. if (!Next())
  2148. return LEXICAL_ERROR;
  2149. while (1)
  2150. {
  2151. if (m_nCurrentToken == WQL_TOK_DOT)
  2152. {
  2153. // Move past dot
  2154. // ==============
  2155. if (!Next())
  2156. return LEXICAL_ERROR;
  2157. if (!(m_nCurrentToken == WQL_TOK_IDENT || m_nCurrentToken == WQL_TOK_ASTERISK))
  2158. return SYNTAX_ERROR;
  2159. pQNF = new SWQLQualifiedNameField;
  2160. pQNF->m_pName = Macro_CloneLPWSTR(m_pTokenText);
  2161. QN.Add(pQNF);
  2162. if (!Next())
  2163. return LEXICAL_ERROR;
  2164. continue;
  2165. }
  2166. if (m_nCurrentToken == WQL_TOK_OPEN_BRACKET)
  2167. {
  2168. if (!Next())
  2169. return LEXICAL_ERROR;
  2170. if (m_nCurrentToken != WQL_TOK_INT)
  2171. return SYNTAX_ERROR;
  2172. pQNF->m_bArrayRef = TRUE;
  2173. pQNF->m_dwArrayIndex = (DWORD) GetTokenLong();
  2174. if (!Next())
  2175. return LEXICAL_ERROR;
  2176. if (m_nCurrentToken != WQL_TOK_CLOSE_BRACKET)
  2177. return SYNTAX_ERROR;
  2178. if (!Next())
  2179. return LEXICAL_ERROR;
  2180. continue;
  2181. }
  2182. break;
  2183. }
  2184. // Copy the object and return it. We worked with the copy QN
  2185. // throughout to avoid complicated cleanup problems on errors, since
  2186. // we take advantage of the auto destructor of <QN> in cases
  2187. // above where we return errors.
  2188. // ==================================================================
  2189. SWQLQualifiedName *pRetCopy = new SWQLQualifiedName(QN);
  2190. *pRetVal = pRetCopy;
  2191. return NO_ERROR;
  2192. }
  2193. //*****************************************************************************************
  2194. //
  2195. // col_ref
  2196. //
  2197. //*****************************************************************************************
  2198. // done
  2199. int CWQLParser::col_ref(OUT SWQLQualifiedName **pRetVal)
  2200. {
  2201. return qualified_name(pRetVal);
  2202. }
  2203. //*****************************************************************************************
  2204. //
  2205. // <col_list> ::= <col_ref> <col_list_rest>;
  2206. // <col_list_rest> ::= WQL_TOK_COMMA <col_ref> <col_list_rest>;
  2207. // <col_list_rest> ::= <>;
  2208. //
  2209. //*****************************************************************************************
  2210. // <status: SWQLColRef fields to be analyzed and filled in. Testable, though>
  2211. int CWQLParser::col_list(OUT SWQLNode_ColumnList **pRetColList)
  2212. {
  2213. *pRetColList = 0;
  2214. SWQLNode_ColumnList *pColList = new SWQLNode_ColumnList;
  2215. while (1)
  2216. {
  2217. SWQLQualifiedName *pColRef = 0;
  2218. int nRes = col_ref(&pColRef);
  2219. if (nRes)
  2220. {
  2221. delete pColList;
  2222. return nRes;
  2223. }
  2224. // If here, we have a legit column to add to the node.
  2225. // ===================================================
  2226. SWQLColRef *pCRef = 0;
  2227. QNameToSWQLColRef(pColRef, &pCRef);
  2228. pColList->m_aColumnRefs.Add(pCRef);
  2229. // Check for sortation indication
  2230. // ==============================
  2231. if (m_nCurrentToken == WQL_TOK_ASC)
  2232. {
  2233. pCRef->m_dwFlags |= WQL_FLAG_SORT_ASC;
  2234. if (!Next())
  2235. {
  2236. delete pColList;
  2237. return LEXICAL_ERROR;
  2238. }
  2239. }
  2240. else if (m_nCurrentToken == WQL_TOK_DESC)
  2241. {
  2242. pCRef->m_dwFlags |= WQL_FLAG_SORT_DESC;
  2243. if (!Next())
  2244. {
  2245. delete pColList;
  2246. return LEXICAL_ERROR;
  2247. }
  2248. }
  2249. // Check for a continuation.
  2250. // =========================
  2251. if (m_nCurrentToken != WQL_TOK_COMMA)
  2252. break;
  2253. if (!Next())
  2254. {
  2255. delete pColList;
  2256. return LEXICAL_ERROR;
  2257. }
  2258. }
  2259. *pRetColList = pColList;
  2260. return NO_ERROR;
  2261. }
  2262. //*****************************************************************************************
  2263. //
  2264. // <subselect_stmt> ::=
  2265. // WQL_TOK_SELECT
  2266. // <select_type>
  2267. // <col_ref> // Must not be an asterisk
  2268. // <from_clause>
  2269. // <where_clause>
  2270. //
  2271. //*****************************************************************************************
  2272. int CWQLParser::subselect_stmt(OUT SWQLNode_Select **pRetSel)
  2273. {
  2274. int nSelType;
  2275. int nRes = 0;
  2276. SWQLNode_FromClause *pFrom = 0;
  2277. SWQLNode_Select *pSel = 0;
  2278. SWQLNode_TableRefs *pTblRefs = 0;
  2279. SWQLNode_WhereClause *pWhere = 0;
  2280. *pRetSel = 0;
  2281. // Verify that we are in a subselect.
  2282. // ==================================
  2283. if (m_nCurrentToken != WQL_TOK_SELECT)
  2284. return SYNTAX_ERROR;
  2285. if (!Next())
  2286. return LEXICAL_ERROR;
  2287. // This affects some of the productions, since they behave differently
  2288. // in subselects than in primary selects.
  2289. // ===================================================================
  2290. m_nParseContext = Ctx_Subselect;
  2291. // If here, we are definitely in a subselect, so
  2292. // allocate a new node.
  2293. // ==============================================
  2294. pSel = new SWQLNode_Select;
  2295. pTblRefs = new SWQLNode_TableRefs;
  2296. pSel->m_pLeft = pTblRefs;
  2297. // Find the select type.
  2298. // =====================
  2299. nRes = select_type(nSelType);
  2300. if (nRes)
  2301. return nRes;
  2302. pTblRefs->m_nSelectType = nSelType; // ALL, DISTINCT
  2303. // Get the column list. In this case
  2304. // it must be a single column and not
  2305. // an asterisk.
  2306. // ====================================
  2307. nRes = col_ref_list(pTblRefs);
  2308. if (nRes)
  2309. return nRes;
  2310. // Get the FROM clause and patch it in.
  2311. // =====================================
  2312. nRes = from_clause(&pFrom);
  2313. if (nRes)
  2314. return nRes;
  2315. pTblRefs->m_pRight = pFrom;
  2316. // Get the WHERE clause.
  2317. // =====================
  2318. nRes = where_clause(&pWhere);
  2319. if (nRes)
  2320. return nRes;
  2321. pSel->m_pRight = pWhere;
  2322. *pRetSel = pSel;
  2323. m_nParseContext = Ctx_Default; // No longer in a subselect
  2324. return NO_ERROR;
  2325. }
  2326. /////////////////////////////////////////////////////////////////////////////
  2327. //
  2328. // Containers
  2329. //
  2330. /////////////////////////////////////////////////////////////////////////////
  2331. //***************************************************************************
  2332. //
  2333. // SWQLTypedConst constructor
  2334. //
  2335. //***************************************************************************
  2336. // done
  2337. SWQLTypedConst::SWQLTypedConst()
  2338. {
  2339. m_dwType = VT_NULL;
  2340. m_bPrompt = false;
  2341. memset(&m_Value, 0, sizeof(m_Value));
  2342. }
  2343. //***************************************************************************
  2344. //
  2345. // SWQLTypedConst::operator =
  2346. //
  2347. //***************************************************************************
  2348. // done
  2349. SWQLTypedConst & SWQLTypedConst::operator = (SWQLTypedConst &Src)
  2350. {
  2351. Empty();
  2352. if (Src.m_dwType == VT_LPWSTR)
  2353. {
  2354. m_Value.m_pString = Macro_CloneLPWSTR(Src.m_Value.m_pString);
  2355. }
  2356. else
  2357. {
  2358. m_Value = Src.m_Value;
  2359. }
  2360. m_dwType = Src.m_dwType;
  2361. m_bPrompt = Src.m_bPrompt;
  2362. return *this;
  2363. }
  2364. //***************************************************************************
  2365. //
  2366. // SWQLTypedConst::Empty()
  2367. //
  2368. //***************************************************************************
  2369. // done
  2370. void SWQLTypedConst::Empty()
  2371. {
  2372. if (m_dwType == VT_LPWSTR)
  2373. delete [] m_Value.m_pString;
  2374. m_bPrompt = false;
  2375. }
  2376. //***************************************************************************
  2377. //
  2378. // SWQLConstList::operator =
  2379. //
  2380. //***************************************************************************
  2381. // done
  2382. SWQLConstList & SWQLConstList::operator = (SWQLConstList & Src)
  2383. {
  2384. Empty();
  2385. for (int i = 0; i < Src.m_aValues.Size(); i++)
  2386. {
  2387. SWQLTypedConst *pC = (SWQLTypedConst *) Src.m_aValues[i];
  2388. m_aValues.Add(new SWQLTypedConst(*pC));
  2389. }
  2390. return *this;
  2391. }
  2392. //***************************************************************************
  2393. //
  2394. // SWQLConstList::Empty
  2395. //
  2396. //***************************************************************************
  2397. // done
  2398. void SWQLConstList::Empty()
  2399. {
  2400. for (int i = 0; i < m_aValues.Size(); i++)
  2401. delete (SWQLTypedConst *) m_aValues[i];
  2402. m_aValues.Empty();
  2403. }
  2404. //***************************************************************************
  2405. //
  2406. // SWQLQualifiedName::Empty()
  2407. //
  2408. //***************************************************************************
  2409. // done
  2410. void SWQLQualifiedName::Empty()
  2411. {
  2412. for (int i = 0; i < m_aFields.Size(); i++)
  2413. delete (SWQLQualifiedNameField *) m_aFields[i];
  2414. }
  2415. //***************************************************************************
  2416. //
  2417. // SWQLQualifiedName::operator =
  2418. //
  2419. //***************************************************************************
  2420. // done
  2421. SWQLQualifiedName & SWQLQualifiedName::operator = (SWQLQualifiedName &Src)
  2422. {
  2423. Empty();
  2424. for (int i = 0; i < Src.m_aFields.Size(); i++)
  2425. {
  2426. SWQLQualifiedNameField *pQN = new SWQLQualifiedNameField;
  2427. *pQN = *(SWQLQualifiedNameField *) Src.m_aFields[i];
  2428. m_aFields.Add(pQN);
  2429. }
  2430. return *this;
  2431. }
  2432. //***************************************************************************
  2433. //
  2434. // SWQLQualifiedNameField::operator =
  2435. //
  2436. //***************************************************************************
  2437. // done
  2438. SWQLQualifiedNameField &
  2439. SWQLQualifiedNameField::operator =(SWQLQualifiedNameField &Src)
  2440. {
  2441. Empty();
  2442. m_bArrayRef = Src.m_bArrayRef;
  2443. m_pName = Macro_CloneLPWSTR(Src.m_pName);
  2444. m_dwArrayIndex = Src.m_dwArrayIndex;
  2445. return *this;
  2446. }
  2447. //***************************************************************************
  2448. //
  2449. // SWQLNode_ColumnList destructor
  2450. //
  2451. //***************************************************************************
  2452. // tbd
  2453. //***************************************************************************
  2454. //
  2455. // QNameToSWQLColRef
  2456. //
  2457. // Translates a qualified name to a SWQLColRef structure and embeds
  2458. // the q-name into the struct (since that is a field).
  2459. //
  2460. //***************************************************************************
  2461. int CWQLParser::QNameToSWQLColRef(
  2462. IN SWQLQualifiedName *pQName,
  2463. OUT SWQLColRef **pRetVal
  2464. )
  2465. {
  2466. *pRetVal = 0;
  2467. if (pQName == 0 || pRetVal == 0)
  2468. return INVALID_PARAMETER;
  2469. SWQLColRef *pCR = new SWQLColRef;
  2470. // Algorithm: With a two name sequence, assume that the first name is
  2471. // the table and that the second name is the column. If multiple
  2472. // names occur, then we set the SWQLColRef type to WQL_FLAG_COMPLEX
  2473. // and just take the last name for the column.
  2474. // ==================================================================
  2475. if (pQName->m_aFields.Size() == 2)
  2476. {
  2477. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[1];
  2478. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pQName->m_aFields[0];
  2479. pCR->m_pColName = Macro_CloneLPWSTR(pCol->m_pName);
  2480. pCR->m_pTableRef = Macro_CloneLPWSTR(pTbl->m_pName);
  2481. pCR->m_dwFlags = WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  2482. if (_wcsicmp(L"*", pCol->m_pName) == 0)
  2483. pCR->m_dwFlags |= WQL_FLAG_ASTERISK;
  2484. if (pCol->m_bArrayRef)
  2485. {
  2486. pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF;
  2487. pCR->m_dwArrayIndex = pCol->m_dwArrayIndex;
  2488. }
  2489. }
  2490. else if (pQName->m_aFields.Size() == 1)
  2491. {
  2492. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[0];
  2493. pCR->m_pColName = Macro_CloneLPWSTR(pCol->m_pName);
  2494. pCR->m_dwFlags |= WQL_FLAG_COLUMN;
  2495. if (_wcsicmp(L"*", pCol->m_pName) == 0)
  2496. pCR->m_dwFlags |= WQL_FLAG_ASTERISK;
  2497. if (pCol->m_bArrayRef)
  2498. {
  2499. pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF;
  2500. pCR->m_dwArrayIndex = pCol->m_dwArrayIndex;
  2501. }
  2502. }
  2503. // Complex case.
  2504. // =============
  2505. else
  2506. {
  2507. pCR->m_dwFlags = WQL_FLAG_COMPLEX_NAME;
  2508. }
  2509. // Copy the qualified name.
  2510. // ========================
  2511. pCR->m_pQName = pQName;
  2512. *pRetVal = pCR;
  2513. return NO_ERROR;;
  2514. }
  2515. //***************************************************************************
  2516. //
  2517. // SWQLNode_ColumnList::DebugDump
  2518. //
  2519. //***************************************************************************
  2520. void SWQLNode_ColumnList::DebugDump()
  2521. {
  2522. printf("---SWQLNode_ColumnList---\n");
  2523. for (int i = 0; i < m_aColumnRefs.Size(); i++)
  2524. {
  2525. SWQLColRef *pCR = (SWQLColRef *) m_aColumnRefs[i];
  2526. pCR->DebugDump();
  2527. }
  2528. printf("---End SWQLNode_ColumnList---\n");
  2529. }
  2530. //***************************************************************************
  2531. //
  2532. //***************************************************************************
  2533. void SWQLColRef::DebugDump()
  2534. {
  2535. printf(" ---SWQLColRef---\n");
  2536. printf(" Col Name = %S\n", m_pColName);
  2537. printf(" Table = %S\n", m_pTableRef);
  2538. printf(" Array Index = %d\n", m_dwArrayIndex);
  2539. printf(" Flags = 0x%X ", m_dwFlags);
  2540. if (m_dwFlags & WQL_FLAG_TABLE)
  2541. printf("WQL_FLAG_TABLE ");
  2542. if (m_dwFlags & WQL_FLAG_COLUMN)
  2543. printf("WQL_FLAG_COLUMN ");
  2544. if (m_dwFlags & WQL_FLAG_ASTERISK)
  2545. printf("WQL_FLAG_ASTERISK ");
  2546. if (m_dwFlags & WQL_FLAG_NULL)
  2547. printf("WQL_FLAG_NULL ");
  2548. if (m_dwFlags & WQL_FLAG_FUNCTIONIZED)
  2549. printf("WQL_FLAG_FUNCTIONIZED ");
  2550. if (m_dwFlags & WQL_FLAG_COMPLEX_NAME)
  2551. printf("WQL_FLAG_COMPLEX_NAME ");
  2552. if (m_dwFlags & WQL_FLAG_ARRAY_REF)
  2553. printf(" WQL_FLAG_ARRAY_REF");
  2554. if (m_dwFlags & WQL_FLAG_UPPER)
  2555. printf(" WQL_FLAG_UPPER");
  2556. if (m_dwFlags & WQL_FLAG_LOWER)
  2557. printf(" WQL_FLAG_LOWER");
  2558. if (m_dwFlags & WQL_FLAG_SORT_ASC)
  2559. printf(" WQL_FLAG_SORT_ASC");
  2560. if (m_dwFlags & WQL_FLAG_SORT_DESC)
  2561. printf(" WQL_FLAG_SORT_DESC");
  2562. printf("\n");
  2563. printf(" ---\n\n");
  2564. }
  2565. //***************************************************************************
  2566. //
  2567. //***************************************************************************
  2568. void SWQLNode_TableRefs::DebugDump()
  2569. {
  2570. printf("********** BEGIN SWQLNode_TableRefs *************\n");
  2571. printf("Select type = ");
  2572. if (m_nSelectType & WQL_FLAG_COUNT)
  2573. printf("WQL_FLAG_COUNT ");
  2574. if (m_nSelectType & WQL_FLAG_ALL)
  2575. printf("WQL_FLAG_ALL ");
  2576. if (m_nSelectType & WQL_FLAG_DISTINCT)
  2577. printf("WQL_FLAG_DISTINCT ");
  2578. printf("\n");
  2579. m_pLeft->DebugDump();
  2580. m_pRight->DebugDump();
  2581. printf("********** END SWQLNode_TableRefs *************\n\n\n");
  2582. }
  2583. //***************************************************************************
  2584. //
  2585. //***************************************************************************
  2586. void SWQLNode_FromClause::DebugDump()
  2587. {
  2588. printf("---SWQLNode_FromClause---\n");
  2589. if (m_pLeft == 0)
  2590. return;
  2591. m_pLeft->DebugDump();
  2592. printf("---End SWQLNode_FromClause---\n");
  2593. }
  2594. //***************************************************************************
  2595. //
  2596. //***************************************************************************
  2597. void SWQLNode_Select::DebugDump()
  2598. {
  2599. printf("********** BEGIN SWQLNode_Select *************\n");
  2600. m_pLeft->DebugDump();
  2601. m_pRight->DebugDump();
  2602. printf("********** END SWQLNode_Select *************\n");
  2603. }
  2604. //***************************************************************************
  2605. //
  2606. //***************************************************************************
  2607. void SWQLNode_TableRef::DebugDump()
  2608. {
  2609. printf(" ---TableRef---\n");
  2610. printf(" TableName = %S\n", m_pTableName);
  2611. printf(" Alias = %S\n", m_pAlias);
  2612. printf(" ---End TableRef---\n");
  2613. }
  2614. //***************************************************************************
  2615. //
  2616. //***************************************************************************
  2617. void SWQLNode_Join::DebugDump()
  2618. {
  2619. printf("---SWQLNode_Join---\n");
  2620. printf("Join type = ");
  2621. switch (m_dwJoinType)
  2622. {
  2623. case WQL_FLAG_INNER_JOIN : printf("WQL_FLAG_INNER_JOIN "); break;
  2624. case WQL_FLAG_FULL_OUTER_JOIN : printf("WQL_FLAG_FULL_OUTER_JOIN "); break;
  2625. case WQL_FLAG_LEFT_OUTER_JOIN : printf("WQL_FLAG_LEFT_OUTER_JOIN "); break;
  2626. case WQL_FLAG_RIGHT_OUTER_JOIN : printf("WQL_FLAG_RIGHT_OUTER_JOIN "); break;
  2627. default: printf("<error> ");
  2628. }
  2629. if (m_dwFlags & WQL_FLAG_FIRSTROW)
  2630. printf(" (FIRSTROW)");
  2631. printf("\n");
  2632. if (m_pRight)
  2633. m_pRight->DebugDump();
  2634. if (m_pLeft)
  2635. m_pLeft->DebugDump();
  2636. printf("---End SWQLNode_Join---\n");
  2637. }
  2638. //***************************************************************************
  2639. //
  2640. // SWQLNode_Sql89Join::Empty
  2641. //
  2642. //***************************************************************************
  2643. void SWQLNode_Sql89Join::Empty()
  2644. {
  2645. for (int i = 0; i < m_aValues.Size(); i++)
  2646. delete (SWQLNode_TableRef *) m_aValues[i];
  2647. m_aValues.Empty();
  2648. }
  2649. //***************************************************************************
  2650. //
  2651. // SWQLNode_Sql89Join::DebugDump
  2652. //
  2653. //***************************************************************************
  2654. void SWQLNode_Sql89Join::DebugDump()
  2655. {
  2656. printf("\n========== SQL 89 JOIN =================================\n");
  2657. for (int i = 0; i < m_aValues.Size(); i++)
  2658. {
  2659. SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) m_aValues[i];
  2660. pTR->DebugDump();
  2661. }
  2662. printf("\n========== END SQL 89 JOIN =============================\n");
  2663. }
  2664. //***************************************************************************
  2665. //
  2666. // SWQLNode_WhereClause::DebugDump
  2667. //
  2668. //***************************************************************************
  2669. void SWQLNode_WhereClause::DebugDump()
  2670. {
  2671. printf("\n========== WHERE CLAUSE ================================\n");
  2672. if (m_pLeft)
  2673. m_pLeft->DebugDump();
  2674. else
  2675. printf(" <no where clause> \n");
  2676. if (m_pRight)
  2677. m_pRight->DebugDump();
  2678. printf("============= END WHERE CLAUSE ============================\n");
  2679. }
  2680. //***************************************************************************
  2681. //
  2682. // SWQLNode_WhereOptions::DebugDump
  2683. //
  2684. //***************************************************************************
  2685. void SWQLNode_WhereOptions::DebugDump()
  2686. {
  2687. printf("---- Where Options ----\n");
  2688. if (m_pLeft)
  2689. m_pLeft->DebugDump();
  2690. if (m_pRight)
  2691. m_pRight->DebugDump();
  2692. printf("---- End Where Options ----\n");
  2693. }
  2694. //***************************************************************************
  2695. //
  2696. // SWQLNode_Having::DebugDump
  2697. //
  2698. //***************************************************************************
  2699. void SWQLNode_Having::DebugDump()
  2700. {
  2701. printf("---- Having ----\n");
  2702. if (m_pLeft)
  2703. m_pLeft->DebugDump();
  2704. if (m_pRight)
  2705. m_pRight->DebugDump();
  2706. printf("---- End Having ----\n");
  2707. }
  2708. //***************************************************************************
  2709. //
  2710. // SWQLNode_GroupBy::DebugDump
  2711. //
  2712. //***************************************************************************
  2713. void SWQLNode_GroupBy::DebugDump()
  2714. {
  2715. printf("---- Group By ----\n");
  2716. if (m_pLeft)
  2717. m_pLeft->DebugDump();
  2718. if (m_pRight)
  2719. m_pRight->DebugDump();
  2720. printf("---- End Group By ----\n");
  2721. }
  2722. //***************************************************************************
  2723. //
  2724. // SWQLNode_RelExpr::DebugDump
  2725. //
  2726. //***************************************************************************
  2727. void SWQLNode_RelExpr::DebugDump()
  2728. {
  2729. if (m_pRight)
  2730. m_pRight->DebugDump();
  2731. printf(" --- SWQLNode_RelExpr ---\n");
  2732. switch (m_dwExprType)
  2733. {
  2734. case WQL_TOK_OR:
  2735. printf(" <WQL_TOK_OR>\n");
  2736. break;
  2737. case WQL_TOK_AND:
  2738. printf(" <WQL_TOK_AND>\n");
  2739. break;
  2740. case WQL_TOK_NOT:
  2741. printf(" <WQL_TOK_NOT>\n");
  2742. break;
  2743. case WQL_TOK_TYPED_EXPR:
  2744. printf(" <WQL_TOK_TYPED_EXPR>\n");
  2745. m_pTypedExpr->DebugDump();
  2746. break;
  2747. default:
  2748. printf(" <invalid>\n");
  2749. }
  2750. printf(" --- END SWQLNode_RelExpr ---\n\n");
  2751. if (m_pLeft)
  2752. m_pLeft->DebugDump();
  2753. }
  2754. //***************************************************************************
  2755. //
  2756. //***************************************************************************
  2757. static LPWSTR OpToStr(DWORD dwOp)
  2758. {
  2759. LPWSTR pRet = 0;
  2760. switch (dwOp)
  2761. {
  2762. case WQL_TOK_EQ: pRet = L" '=' <WQL_TOK_EQ>"; break;
  2763. case WQL_TOK_NE: pRet = L" '!=' <WQL_TOK_NE>"; break;
  2764. case WQL_TOK_GT: pRet = L" '>' <WQL_TOK_GT>"; break;
  2765. case WQL_TOK_LT: pRet = L" '<' <WQL_TOK_LT>"; break;
  2766. case WQL_TOK_GE: pRet = L" '>=' <WQL_TOK_GE>"; break;
  2767. case WQL_TOK_LE: pRet = L" '<=' <WQL_TOK_LE>"; break;
  2768. case WQL_TOK_IN_CONST_LIST : pRet = L" IN <WQL_TOK_IN_CONST_LIST>"; break;
  2769. case WQL_TOK_NOT_IN_CONST_LIST : pRet = L" NOT IN <WQL_TOK_NOT_IN_CONST_LIST>"; break;
  2770. case WQL_TOK_IN_SUBSELECT : pRet = L" IN <WQL_TOK_IN_SUBSELECT>"; break;
  2771. case WQL_TOK_NOT_IN_SUBSELECT : pRet = L" NOT IN <WQL_TOK_NOT_IN_SUBSELECT>"; break;
  2772. case WQL_TOK_ISNULL: pRet = L"<WQL_TOK_ISNULL>"; break;
  2773. case WQL_TOK_NOT_NULL: pRet = L"<WQL_TOK_NOT_NULL>"; break;
  2774. case WQL_TOK_BETWEEN: pRet = L"<WQL_TOK_BETWEEN>"; break;
  2775. case WQL_TOK_NOT_BETWEEN: pRet = L"<WQL_TOK_NOT_BETWEEN>"; break;
  2776. default: pRet = L" <unknown operator>"; break;
  2777. }
  2778. return pRet;
  2779. }
  2780. //***************************************************************************
  2781. //
  2782. //***************************************************************************
  2783. void SWQLTypedExpr::DebugDump()
  2784. {
  2785. printf(" === BEGIN SWQLTypedExpr ===\n");
  2786. printf(" m_pTableRef = %S\n", m_pTableRef);
  2787. printf(" m_pColRef = %S\n", m_pColRef);
  2788. printf(" m_pJoinTableRef = %S\n", m_pJoinTableRef);
  2789. printf(" m_pJoinColRef = %S\n", m_pJoinColRef);
  2790. printf(" m_dwRelOperator = %S\n", OpToStr(m_dwRelOperator));
  2791. printf(" m_pSubSelect = 0x%X\n", m_pSubSelect);
  2792. printf(" m_dwLeftArrayIndex = %d\n", m_dwLeftArrayIndex);
  2793. printf(" m_dwRightArrayIndex = %d\n", m_dwRightArrayIndex);
  2794. printf(" m_pConstValue = ");
  2795. if (m_pConstValue)
  2796. m_pConstValue->DebugDump();
  2797. else
  2798. printf(" NULL ptr \n");
  2799. printf(" m_pConstValue2 = ");
  2800. if (m_pConstValue2)
  2801. m_pConstValue2->DebugDump();
  2802. else
  2803. printf(" NULL ptr \n");
  2804. printf(" m_dwLeftFlags = (0x%X)", m_dwLeftFlags);
  2805. if (m_dwLeftFlags & WQL_FLAG_COLUMN)
  2806. printf(" WQL_FLAG_COLUMN");
  2807. if (m_dwLeftFlags & WQL_FLAG_TABLE)
  2808. printf(" WQL_FLAG_TABLE");
  2809. if (m_dwLeftFlags & WQL_FLAG_CONST)
  2810. printf(" WQL_FLAG_CONST");
  2811. if (m_dwLeftFlags & WQL_FLAG_COMPLEX_NAME)
  2812. printf(" WQL_FLAG_COMPLEX_NAME");
  2813. if (m_dwLeftFlags & WQL_FLAG_SORT_ASC)
  2814. printf(" WQL_FLAG_SORT_ASC");
  2815. if (m_dwLeftFlags & WQL_FLAG_SORT_DESC)
  2816. printf(" WQL_FLAG_SORT_DESC");
  2817. if (m_dwLeftFlags & WQL_FLAG_FUNCTIONIZED)
  2818. printf(" WQL_FLAG_FUNCTIONIZED (Function=%S)", m_pIntrinsicFuncOnColRef);
  2819. if (m_dwLeftFlags & WQL_FLAG_ARRAY_REF)
  2820. printf(" WQL_FLAG_ARRAY_REF");
  2821. printf("\n");
  2822. printf(" m_dwRightFlags = (0x%X)", m_dwRightFlags);
  2823. if (m_dwRightFlags & WQL_FLAG_COLUMN)
  2824. printf(" WQL_FLAG_COLUMN");
  2825. if (m_dwRightFlags & WQL_FLAG_TABLE)
  2826. printf(" WQL_FLAG_TABLE");
  2827. if (m_dwRightFlags & WQL_FLAG_CONST)
  2828. printf(" WQL_FLAG_CONST");
  2829. if (m_dwRightFlags & WQL_FLAG_COMPLEX_NAME)
  2830. printf(" WQL_FLAG_COMPLEX_NAME");
  2831. if (m_dwLeftFlags & WQL_FLAG_SORT_ASC)
  2832. printf(" WQL_FLAG_SORT_ASC");
  2833. if (m_dwLeftFlags & WQL_FLAG_SORT_DESC)
  2834. printf(" WQL_FLAG_SORT_DESC");
  2835. if (m_dwRightFlags & WQL_FLAG_FUNCTIONIZED)
  2836. {
  2837. printf(" WQL_FLAG_FUNCTIONIZED");
  2838. if (m_pIntrinsicFuncOnJoinColRef)
  2839. printf("(On join col: Function=%S)", m_pIntrinsicFuncOnJoinColRef);
  2840. if (m_pIntrinsicFuncOnConstValue)
  2841. printf("(On const: Function=%S)", m_pIntrinsicFuncOnConstValue);
  2842. }
  2843. if (m_dwRightFlags & WQL_FLAG_ARRAY_REF)
  2844. printf(" WQL_FLAG_ARRAY_REF");
  2845. if (m_dwRightFlags & WQL_FLAG_CONST_RANGE)
  2846. printf(" WQL_FLAG_CONST_RANGE");
  2847. printf("\n");
  2848. if (m_pLeftFunction)
  2849. {
  2850. printf("m_pLeftFunction: \n");
  2851. m_pLeftFunction->DebugDump();
  2852. }
  2853. if (m_pRightFunction)
  2854. {
  2855. printf("m_pRightFunction: \n");
  2856. m_pRightFunction->DebugDump();
  2857. }
  2858. if (m_pConstList)
  2859. {
  2860. printf(" ---Const List---\n");
  2861. for (int i = 0; i < m_pConstList->m_aValues.Size(); i++)
  2862. {
  2863. SWQLTypedConst *pConst = (SWQLTypedConst *) m_pConstList->m_aValues.GetAt(i);
  2864. printf(" ");
  2865. pConst->DebugDump();
  2866. }
  2867. printf(" ---End Const List---\n");
  2868. }
  2869. // Subselects
  2870. // ==========
  2871. if (m_pSubSelect)
  2872. {
  2873. printf(" ------- Begin Subselect ------\n");
  2874. m_pSubSelect->DebugDump();
  2875. printf(" ------- End Subselect ------\n");
  2876. }
  2877. printf("\n");
  2878. printf(" === END SWQLTypedExpr ===\n");
  2879. }
  2880. //***************************************************************************
  2881. //
  2882. //***************************************************************************
  2883. SWQLTypedExpr::SWQLTypedExpr()
  2884. {
  2885. m_pTableRef = 0;
  2886. m_pColRef = 0;
  2887. m_dwRelOperator = 0;
  2888. m_pConstValue = 0;
  2889. m_pConstValue2 = 0;
  2890. m_pJoinTableRef = 0;
  2891. m_pJoinColRef = 0;
  2892. m_pIntrinsicFuncOnColRef = 0;
  2893. m_pIntrinsicFuncOnJoinColRef = 0;
  2894. m_pIntrinsicFuncOnConstValue = 0;
  2895. m_pLeftFunction = 0;
  2896. m_pRightFunction = 0;
  2897. m_pQNRight = 0;
  2898. m_pQNLeft = 0;
  2899. m_dwLeftFlags = 0;
  2900. m_dwRightFlags = 0;
  2901. m_pSubSelect = 0;
  2902. m_dwLeftArrayIndex = 0;
  2903. m_dwRightArrayIndex = 0;
  2904. m_pConstList = 0;
  2905. }
  2906. //***************************************************************************
  2907. //
  2908. //***************************************************************************
  2909. void SWQLTypedExpr::Empty()
  2910. {
  2911. delete [] m_pTableRef;
  2912. delete [] m_pColRef;
  2913. delete m_pConstValue;
  2914. delete m_pConstValue2;
  2915. delete m_pConstList;
  2916. delete [] m_pJoinTableRef;
  2917. delete [] m_pJoinColRef;
  2918. delete [] m_pIntrinsicFuncOnColRef;
  2919. delete [] m_pIntrinsicFuncOnJoinColRef;
  2920. delete [] m_pIntrinsicFuncOnConstValue;
  2921. delete m_pLeftFunction;
  2922. delete m_pRightFunction;
  2923. delete m_pQNRight;
  2924. delete m_pQNLeft;
  2925. delete m_pSubSelect;
  2926. }
  2927. //***************************************************************************
  2928. //
  2929. //***************************************************************************
  2930. void SWQLTypedConst::DebugDump()
  2931. {
  2932. printf(" Typed Const <");
  2933. switch (m_dwType)
  2934. {
  2935. case VT_LPWSTR:
  2936. printf("%S", m_Value.m_pString);
  2937. break;
  2938. case VT_I4:
  2939. printf("%d (0x%X)", m_Value.m_lValue, m_Value.m_lValue);
  2940. break;
  2941. case VT_R8:
  2942. printf("%f", m_Value.m_dblValue);
  2943. break;
  2944. case VT_BOOL:
  2945. printf("(bool) %d", m_Value.m_bValue);
  2946. break;
  2947. case VT_NULL:
  2948. printf(" NULL");
  2949. break;
  2950. default:
  2951. printf(" unknown");
  2952. }
  2953. printf(">\n");
  2954. }
  2955. //***************************************************************************
  2956. //
  2957. //***************************************************************************
  2958. static DWORD FlipOperator(DWORD dwOp)
  2959. {
  2960. switch (dwOp)
  2961. {
  2962. case WQL_TOK_LT: return WQL_TOK_GT;
  2963. case WQL_TOK_LE: return WQL_TOK_GE;
  2964. case WQL_TOK_GT: return WQL_TOK_LT;
  2965. case WQL_TOK_GE: return WQL_TOK_LE;
  2966. }
  2967. return dwOp; // Echo original
  2968. }
  2969. //***************************************************************************
  2970. //
  2971. //***************************************************************************
  2972. void SWQLNode_JoinPair::DebugDump()
  2973. {
  2974. printf("---SWQLNode_JoinPair---\n");
  2975. m_pRight->DebugDump();
  2976. m_pLeft->DebugDump();
  2977. printf("---End SWQLNode_JoinPair---\n");
  2978. }
  2979. void SWQLNode_OnClause::DebugDump()
  2980. {
  2981. printf("---SWQLNode_OnClause---\n");
  2982. m_pLeft->DebugDump();
  2983. printf("---END SWQLNode_OnClause---\n");
  2984. }
  2985. //***************************************************************************
  2986. //
  2987. //***************************************************************************
  2988. void SWQLNode_OrderBy::DebugDump()
  2989. {
  2990. printf("\n\n---- 'ORDER BY' Clause ----\n");
  2991. m_pLeft->DebugDump();
  2992. printf("---- End 'ORDER BY' Clause ----\n\n");
  2993. }
  2994. //***************************************************************************
  2995. //
  2996. //***************************************************************************
  2997. const LPWSTR CWQLParser::AliasToTable(IN LPWSTR pAlias)
  2998. {
  2999. const CFlexArray *pAliases = GetSelectedAliases();
  3000. for (int i = 0; i < pAliases->Size(); i++)
  3001. {
  3002. SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) pAliases->GetAt(i);
  3003. if (_wcsicmp(pTR->m_pAlias, pAlias) == 0)
  3004. return pTR->m_pTableName;
  3005. }
  3006. return NULL; // Not found
  3007. }
  3008. void SWQLNode_Datepart::DebugDump()
  3009. {
  3010. printf(" ----Begin SWQLNode_Datepart----\n");
  3011. switch (m_nDatepart)
  3012. {
  3013. case WQL_TOK_YEAR: printf(" WQL_TOK_YEAR"); break;
  3014. case WQL_TOK_MONTH: printf(" WQL_TOK_MONTH"); break;
  3015. case WQL_TOK_DAY: printf(" WQL_TOK_DAY"); break;
  3016. case WQL_TOK_HOUR: printf(" WQL_TOK_HOUR"); break;
  3017. case WQL_TOK_MINUTE: printf(" WQL_TOK_MINUTE"); break;
  3018. case WQL_TOK_SECOND: printf(" WQL_TOK_SECOND"); break;
  3019. case WQL_TOK_MILLISECOND: printf(" WQL_TOK_MILLISECOND"); break;
  3020. default:
  3021. printf(" -> No datepart specified\n");
  3022. }
  3023. printf("\n");
  3024. if (m_pColRef)
  3025. m_pColRef->DebugDump();
  3026. printf(" ----End SWQLNode_Datepart----\n");
  3027. }
  3028. void SWQLNode_ColumnList::Empty()
  3029. {
  3030. for (int i = 0; i < m_aColumnRefs.Size(); i++)
  3031. delete (SWQLColRef *) m_aColumnRefs[i];
  3032. }
  3033.