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.

416 lines
12 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // WQL Version 1.1 for WBEM M6 / SMS Opal.
  4. //
  5. // This file describes a validated LL(1) grammar for top-down
  6. // or recursive descent parsing of WQL.
  7. //
  8. // raymcc 11-Sep-97 Created
  9. //
  10. /////////////////////////////////////////////////////////////////////////////
  11. <parse> ::= WQL_TOK_SELECT <select_stmt>;
  12. /////////////////////////////////////////////////////////////////////////////
  13. //
  14. // SELECT statement
  15. //
  16. /////////////////////////////////////////////////////////////////////////////
  17. <select_stmt> ::=
  18. <select_type>
  19. <col_ref_list>
  20. <from_clause>
  21. <where_clause>
  22. ;
  23. <select_type> ::= WQL_TOK_ALL;
  24. <select_type> ::= WQL_TOK_DISTINCT;
  25. <select_type> ::= <>;
  26. <subselect_stmt> ::=
  27. WQL_TOK_SELECT
  28. <select_type>
  29. <col_ref_list> // Additionally, must be a single col & not an asterisk
  30. <from_clause>
  31. <where_clause>
  32. ;
  33. /////////////////////////////////////////////////////////////////////////////
  34. //
  35. // Column reference list
  36. //
  37. // Supports either simple names, *, or qualified names of the form
  38. // "table.col" where table could be a literal table name or an aliased
  39. // table name. At this point in the parsing, we can't really tell
  40. // which one is being used.
  41. //
  42. // Either * is required, or at least one column reference.
  43. //
  44. /////////////////////////////////////////////////////////////////////////////
  45. <col_ref_list> ::= <col_ref> <col_ref_rest>;
  46. <col_ref_list> ::= WQL_TOK_ASTERISK;
  47. <col_ref_list> ::= WQL_TOK_COUNT <count_clause>;
  48. <col_ref_rest> ::= WQL_TOK_COMMA <col_ref_list>;
  49. <col_ref_rest> ::= <>;
  50. <count_clause> ::= WQL_TOK_OPEN_PAREN <count_col> WQL_TOK_CLOSE_PAREN;
  51. <count_col> ::= WQL_TOK_ASTERISK;
  52. <count_col> ::= <col_ref>;
  53. /////////////////////////////////////////////////////////////////////////////
  54. //
  55. // Column reference
  56. //
  57. // Used both in the WHERE clause and the COUNT clause
  58. //
  59. /////////////////////////////////////////////////////////////////////////////
  60. <col_ref> ::= <qualified_name>;
  61. /////////////////////////////////////////////////////////////////////////////
  62. //
  63. // qualified names
  64. //
  65. // (dot-separated names with optional array references.
  66. //
  67. /////////////////////////////////////////////////////////////////////////////
  68. <qualified_name> ::= WQL_TOK_IDENT <qualified_name2>;
  69. <qualified_name2> ::= WQL_TOK_DOT WQL_TOK_IDENT <qualified_name2>;
  70. <qualified_name2> ::=
  71. WQL_TOK_OPEN_BRACKET
  72. WQL_TOK_INT
  73. WQL_TOK_CLOSEBRACKET
  74. <qname_becomes_array_ref>
  75. <qualified_name2>;
  76. <qname_becomes_array_ref> ::= <>; // Dummy to enforce array semantics
  77. <qualified_name2> ::= <>;
  78. /////////////////////////////////////////////////////////////////////////////
  79. //
  80. // "FROM" clause
  81. //
  82. // Both SQL-89 and SQL-92 join syntax supported.
  83. //
  84. /////////////////////////////////////////////////////////////////////////////
  85. <from_clause> ::= WQL_TOK_FROM <table_list>;
  86. <table_list> ::= <single_table_decl> <optional_join>;
  87. <optional_join> ::= <sql89_join_entry>;
  88. <optional_join> ::= <sql92_join_entry>;
  89. <optional_join> ::= <>; // Unary query
  90. /////////////////////////////////////////////////////////////////////////////
  91. //
  92. // Table reference
  93. //
  94. // This supports a single table reference in a FROM clause, whether
  95. // an isolated name, or alias (with or without AS).
  96. //
  97. /////////////////////////////////////////////////////////////////////////////
  98. <single_table_decl> ::= <unbound_table_ident> <table_decl_rest>;
  99. <unbound_table_ident> ::= WQL_TOK_IDENT;
  100. <table_decl_rest> ::= <redundant_as> <table_alias>;
  101. <table_decl_rest> ::= <>;
  102. <table_alias> ::= WQL_TOK_IDENT;
  103. <redundant_as> ::= WQL_TOK_AS;
  104. <redundant_as> ::= <>;
  105. /////////////////////////////////////////////////////////////////////////////
  106. //
  107. // SQL-89 Joins
  108. //
  109. /////////////////////////////////////////////////////////////////////////////
  110. <sql89_join_entry> ::= WQL_TOK_COMMA <sql89_join_list>;
  111. <sql89_join_list> ::= <single_table_decl> <sql89_join_rest>;
  112. <sql89_join_rest> ::= WQL_TOK_COMMA <sql89_join_list>;
  113. <sql89_join_rest> ::= <>;
  114. /////////////////////////////////////////////////////////////////////////////
  115. //
  116. // SQL-92 Joins.
  117. //
  118. // We support:
  119. // 1. [INNER] JOIN
  120. // 2. LEFT [OUTER] JOIN
  121. // 3. RIGHT [OUTER] JOIN
  122. // 4. FULL [OUTER] JOIN
  123. //
  124. /////////////////////////////////////////////////////////////////////////////
  125. <sql92_join_entry> ::= <simple_join_clause>;
  126. <sql92_join_entry> ::= WQL_TOK_INNER <simple_join_clause>;
  127. <sql92_join_entry> ::= WQL_TOK_FULL <opt_outer> <simple_join_clause>;
  128. <sql92_join_entry> ::= WQL_TOK_LEFT <opt_outer> <simple_join_clause>;
  129. <sql92_join_entry> ::= WQL_TOK_RIGHT <opt_outer> <simple_join_clause>;
  130. <opt_outer> ::= WQL_TOK_OUTER;
  131. <opt_outer> ::= <>;
  132. <simple_join_clause> ::=
  133. WQL_TOK_JOIN
  134. <single_table_decl>
  135. <on_clause>
  136. <sql92_join_continuator>
  137. ;
  138. <on_clause> ::= WQL_TOK_ON <rel_expr>;
  139. <sql92_join_continuator> ::= <sql92_join_entry>;
  140. <sql92_join_continuator> ::= <>;
  141. /////////////////////////////////////////////////////////////////////////////
  142. //
  143. // "WHERE" clause
  144. //
  145. /////////////////////////////////////////////////////////////////////////////
  146. <where_clause> ::= WQL_TOK_WHERE <rel_expr> <where_options>;
  147. <where_clause> ::= <>; // 'where' is not required
  148. /////////////////////////////////////////////////////////////////////////////
  149. //
  150. // WHERE OPTIONS
  151. //
  152. // We currently force the GROUP BY to precede ORDER BY if they are both
  153. // present. If this causes a problem, we can fix it by using an
  154. // iterative construct below and doing the checking in the parser itself
  155. // as a semantic operation.
  156. //
  157. /////////////////////////////////////////////////////////////////////////////
  158. <where_options> ::=
  159. <group_by_clause>
  160. <order_by_clause>
  161. ;
  162. <group_by_clause> ::= WQL_TOK_GROUP WQL_TOK_BY <col_list> <having_clause>;
  163. <group_by_clause> ::= <>;
  164. <having_clause> ::= WQL_TOK_HAVING <rel_expr>;
  165. <having_clause> ::= <>;
  166. <order_by_clause> ::= WQL_TOK_ORDER WQL_TOK_BY <col_list>;
  167. <order_by_clause> ::= <>;
  168. /////////////////////////////////////////////////////////////////////////////
  169. //
  170. // Simple column list with no asterisk
  171. //
  172. /////////////////////////////////////////////////////////////////////////////
  173. <col_list> ::= <col_ref> <col_list_rest>;
  174. <col_list_rest> ::= WQL_TOK_COMMA <col_ref> <col_list_rest>;
  175. <col_list_rest> ::= <>;
  176. /////////////////////////////////////////////////////////////////////////////
  177. //
  178. // Relational expressions
  179. //
  180. // These set out the precedence of typed expressions relative to the
  181. // NOT, AND, OR and parentheses operators.
  182. //
  183. /////////////////////////////////////////////////////////////////////////////
  184. <rel_expr> ::= <rel_term> <rel_expr2>;
  185. <rel_expr2> ::= WQL_TOK_OR <rel_term> <rel_expr2>;
  186. <rel_expr2> ::= <>;
  187. <rel_term> ::= <rel_simple_expr> <rel_term2>;
  188. <rel_term2> ::= WQL_TOK_AND <rel_simple_expr> <rel_term2>;
  189. <rel_term2> ::= <>;
  190. <rel_simple_expr> ::= WQL_TOK_NOT <rel_expr>;
  191. <rel_simple_expr> ::= WQL_TOK_OPEN_PAREN <rel_expr> WQL_TOK_CLOSE_PAREN;
  192. <rel_simple_expr> ::= <typed_expr>;
  193. /////////////////////////////////////////////////////////////////////////////
  194. //
  195. // Typed expression
  196. //
  197. // This is the lower level expression which requires a relational
  198. // operator. Many of these combined constitute a relational expression.
  199. //
  200. /////////////////////////////////////////////////////////////////////////////
  201. <typed_expr> ::= <typed_subexpr> <rel_op> <typed_subexpr_rh>;
  202. <typed_subexpr> ::= <function_call>;
  203. <typed_subexpr> ::= <typed_const>;
  204. <typed_subexpr> ::= <col_ref>;
  205. <typed_subexpr_rh> ::= <function_call>;
  206. <typed_subexpr_rh> ::= <typed_const>;
  207. <typed_subexpr_rh> ::= <col_ref>;
  208. <typed_subexpr_rh> ::= <in_clause>; // Operator must be _IN or _NOT_IN
  209. /////////////////////////////////////////////////////////////////////////////
  210. //
  211. // Function calls
  212. //
  213. // Each of the recognized functions is part of the grammar.
  214. //
  215. /////////////////////////////////////////////////////////////////////////////
  216. <function_call> ::= WQL_TOK_UPPER <function_call_parms>;
  217. <function_call> ::= WQL_TOK_LOWER <function_call_parms>;
  218. <function_call> ::= WQL_TOK_DATEPART <datepart_call>;
  219. <function_call> ::= WQL_TOK_QUALIFIER <function_call_parms>;
  220. <function_call> ::= WQL_TOK_ISNULL <function_call_parms>;
  221. <function_call_parms> ::=
  222. WQL_TOK_OPEN_PAREN
  223. <func_args>
  224. WQL_TOK_CLOSE_PAREN
  225. ;
  226. <func_args> ::= <func_arg> <func_arg_list>;
  227. <func_arg_list> ::= WQL_TOK_COMMA <func_arg> <func_arg_list>;
  228. <func_arg_list> ::= <>;
  229. <func_arg> ::= <typed_const>;
  230. <func_arg> ::= <col_ref>;
  231. /////////////////////////////////////////////////////////////////////////////
  232. //
  233. // IN clause
  234. //
  235. // We support three syntax branches:
  236. // (a) IN with subselect
  237. // (b) IN with const-list
  238. // (c) IN with qualified name which is an array reference
  239. //
  240. /////////////////////////////////////////////////////////////////////////////
  241. <in_clause> ::= WQL_TOK_OPEN_PAREN <in_type> WQL_TOK_CLOSE_PAREN;
  242. <in_type> ::= <subselect_stmt>;
  243. <in_type> ::= <const_list>;
  244. <in_type> ::= <qualified_name>;
  245. /////////////////////////////////////////////////////////////////////////////
  246. //
  247. // Comma-separated list of constants
  248. //
  249. /////////////////////////////////////////////////////////////////////////////
  250. <const_list> ::= <typed_const> <const_list2>;
  251. <const_list2> ::= WQL_TOK_COMMA <typed_const> <const_list2>;
  252. <const_list2> ::= <>;
  253. /////////////////////////////////////////////////////////////////////////////
  254. //
  255. // Primary relational operator terminals
  256. // Some branching with continuators occurs for IS, IN, and NOT.
  257. //
  258. /////////////////////////////////////////////////////////////////////////////
  259. <rel_op> ::= WQL_TOK_LE;
  260. <rel_op> ::= WQL_TOK_LT;
  261. <rel_op> ::= WQL_TOK_GE;
  262. <rel_op> ::= WQL_TOK_GT;
  263. <rel_op> ::= WQL_TOK_EQ;
  264. <rel_op> ::= WQL_TOK_NE;
  265. <rel_op> ::= WQL_TOK_LIKE;
  266. <rel_op> ::= WQL_TOK_BETWEEN;
  267. <rel_op> ::= WQL_TOK_IS <is_continuator>;
  268. <rel_op> ::= WQL_TOK_ISA;
  269. <rel_op> ::= WQL_TOK_IN;
  270. <rel_op> ::= WQL_TOK_NOT <not_continuator>;
  271. /////////////////////////////////////////////////////////////////////////////
  272. //
  273. // Tokens which can follow IS
  274. //
  275. /////////////////////////////////////////////////////////////////////////////
  276. <is_continuator> ::= WQL_TOK_LIKE;
  277. <is_continuator> ::= WQL_TOK_BEFORE;
  278. <is_continuator> ::= WQL_TOK_AFTER;
  279. <is_continuator> ::= WQL_TOK_BETWEEN;
  280. <is_continuator> ::= WQL_TOK_NULL;
  281. <is_continuator> ::= WQL_TOK_NOT <not_continuator>;
  282. <is_continuator> ::= WQL_TOK_IN;
  283. <is_continuator> ::= WQL_TOK_A;
  284. /////////////////////////////////////////////////////////////////////////////
  285. //
  286. // Tokens which can follow NOT
  287. //
  288. /////////////////////////////////////////////////////////////////////////////
  289. <not_continuator> ::= WQL_TOK_LIKE;
  290. <not_continuator> ::= WQL_TOK_BEFORE;
  291. <not_continuator> ::= WQL_TOK_AFTER;
  292. <not_continuator> ::= WQL_TOK_BETWEEN;
  293. <not_continuator> ::= WQL_TOK_NULL;
  294. <not_continuator> ::= WQL_TOK_IN;
  295. <not_continuator> ::= WQL_TOK_A;
  296. /////////////////////////////////////////////////////////////////////////////
  297. //
  298. // Typed constants (literals)
  299. //
  300. /////////////////////////////////////////////////////////////////////////////
  301. <typed_const> ::= WQL_TOK_QSTRING;
  302. <typed_const> ::= WQL_TOK_INT;
  303. <typed_const> ::= WQL_TOK_REAL;
  304. <typed_const> ::= WQL_TOK_NULL;
  305. /////////////////////////////////////////////////////////////////////////////
  306. //
  307. // Transact-SQL plagiarism: Datepart
  308. //
  309. // datepart(ident, col)
  310. //
  311. /////////////////////////////////////////////////////////////////////////////
  312. <datepart_call> ::=
  313. WQL_TOK_OPEN_PAREN
  314. WQL_TOK_IDENT // yy, mm,dd, hh, mm, ss, year, month, etc.
  315. WQL_TOK_COMMA
  316. <col_ref>
  317. WQL_TOK_CLOSE_PAREN
  318. ;
  319. // RAIX xxxx: Ensure that lexer returns single quoted strings as valid, and recognizes escapes
  320. // RAID 3716: Syntax to reference a qualifier; promised to do this
  321. // qualifier(prop, "MyQual") = 'xxx' qualifier("MyQual") = 'const'
  322. // RAID xxxx : Hex constants
  323. //
  324. // Intrinsic function applied to columns in "select a, func(b), c from d where..."
  325. // Use of qualified asterisks "select t1.*, t2.*, t3.x from ..."
  326. //
  327. // BETWEEN needs to be supported *correctly*
  328. // Unexpected Features: (1) subselects in IN, (2) DatePart (required new approach to functions
  329. // because of the keyword problem, (3) functionized col-refs, (4) COUNT(col-name) as opposed
  330. // to COUNT(*), (5)