A work-in-progress SQL parser written in TypeScript
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* tslint:disable:no-unused-expression */
  2. import { expect } from "chai";
  3. import * as AST from "../src/ast";
  4. import { isError } from "../src/error";
  5. import Lexer from "../src/lexer";
  6. import Parser from "../src/parser";
  7. const parse = (source: string): AST.Statement[] => {
  8. const tokens = new Lexer(source).scan();
  9. if (isError(tokens)) {
  10. throw tokens.message;
  11. } else {
  12. const tree = new Parser(tokens).parse();
  13. if (isError(tree)) {
  14. throw tree.message;
  15. }
  16. return tree;
  17. }
  18. };
  19. describe("Parser", () => {
  20. it("should parse a number selection", () => {
  21. const tree = parse("select 5");
  22. expect(tree).to.deep.equal([
  23. new AST.SelectStatement({
  24. arguments: [new AST.Number(5)],
  25. }),
  26. ]);
  27. });
  28. it("should parse a multiple number selection", () => {
  29. const tree = parse("select 5, 6");
  30. expect(tree).to.deep.equal([
  31. new AST.SelectStatement({
  32. arguments: [new AST.Number(5), new AST.Number(6)],
  33. }),
  34. ]);
  35. });
  36. it("should parse a selection of identifiers", () => {
  37. const tree = parse("select a, b");
  38. expect(tree).to.deep.equal([
  39. new AST.SelectStatement({
  40. arguments: [new AST.Identifier("a"), new AST.Identifier("b")],
  41. }),
  42. ]);
  43. });
  44. it("should parse a selection of identifiers and numbers", () => {
  45. const tree = parse("select a, 5");
  46. expect(tree).to.deep.equal([
  47. new AST.SelectStatement({
  48. arguments: [new AST.Identifier("a"), new AST.Number(5)],
  49. }),
  50. ]);
  51. });
  52. it("should parse the from of a selection", () => {
  53. const tree = parse("select a from t");
  54. expect(tree).to.deep.equal([
  55. new AST.SelectStatement({
  56. arguments: [new AST.Identifier("a")],
  57. from: new AST.Identifier("t"),
  58. }),
  59. ]);
  60. });
  61. it("should parse aliases", () => {
  62. const tree = parse("select a as b");
  63. expect(tree).to.deep.equal([
  64. new AST.SelectStatement({
  65. arguments: [
  66. new AST.Alias(new AST.Identifier("a"), new AST.Identifier("b")),
  67. ],
  68. }),
  69. ]);
  70. });
  71. it("should parse aliases as from targets", () => {
  72. const tree = parse("select a from t as u");
  73. expect(tree).to.deep.equal([
  74. new AST.SelectStatement({
  75. arguments: [new AST.Identifier("a")],
  76. from: new AST.Alias(new AST.Identifier("t"), new AST.Identifier("u")),
  77. }),
  78. ]);
  79. });
  80. it("should not allow a number as a from target", () => {
  81. const fn = () => parse("select 1 from 2");
  82. expect(fn).to.throw("Unexpected token: { kind: NUMBER, value: 2 }");
  83. });
  84. it("should parse a where with a number", () => {
  85. const tree = parse("select a from b where 1");
  86. expect(tree).to.deep.equal([
  87. new AST.SelectStatement({
  88. arguments: [new AST.Identifier("a")],
  89. from: new AST.Identifier("b"),
  90. where: new AST.Number(1),
  91. }),
  92. ]);
  93. });
  94. it("should parse a where with an identifier", () => {
  95. const tree = parse("select a from b where c");
  96. expect(tree).to.deep.equal([
  97. new AST.SelectStatement({
  98. arguments: [new AST.Identifier("a")],
  99. from: new AST.Identifier("b"),
  100. where: new AST.Identifier("c"),
  101. }),
  102. ]);
  103. });
  104. it("should parse a where with an equality", () => {
  105. const tree = parse("select a from b where c = d");
  106. expect(tree).to.deep.equal([
  107. new AST.SelectStatement({
  108. arguments: [new AST.Identifier("a")],
  109. from: new AST.Identifier("b"),
  110. where: new AST.Binary({
  111. left: new AST.Identifier("c"),
  112. right: new AST.Identifier("d"),
  113. type: AST.BinaryExpressionTypes.EQUALITY,
  114. }),
  115. }),
  116. ]);
  117. });
  118. it("should parse a where with an addition", () => {
  119. const tree = parse("select a from b where c + d");
  120. expect(tree).to.deep.equal([
  121. new AST.SelectStatement({
  122. arguments: [new AST.Identifier("a")],
  123. from: new AST.Identifier("b"),
  124. where: new AST.Binary({
  125. left: new AST.Identifier("c"),
  126. right: new AST.Identifier("d"),
  127. type: AST.BinaryExpressionTypes.ADDITION,
  128. }),
  129. }),
  130. ]);
  131. });
  132. it("should parse a where with a subtraction", () => {
  133. const tree = parse("select a from b where c - d");
  134. expect(tree).to.deep.equal([
  135. new AST.SelectStatement({
  136. arguments: [new AST.Identifier("a")],
  137. from: new AST.Identifier("b"),
  138. where: new AST.Binary({
  139. left: new AST.Identifier("c"),
  140. right: new AST.Identifier("d"),
  141. type: AST.BinaryExpressionTypes.SUBTRACTION,
  142. }),
  143. }),
  144. ]);
  145. });
  146. it("should parse a where with a multiplication", () => {
  147. const tree = parse("select a from b where c * d");
  148. expect(tree).to.deep.equal([
  149. new AST.SelectStatement({
  150. arguments: [new AST.Identifier("a")],
  151. from: new AST.Identifier("b"),
  152. where: new AST.Binary({
  153. left: new AST.Identifier("c"),
  154. right: new AST.Identifier("d"),
  155. type: AST.BinaryExpressionTypes.MULTIPLICATION,
  156. }),
  157. }),
  158. ]);
  159. });
  160. it("should parse a where with a division", () => {
  161. const tree = parse("select a from b where c / d");
  162. expect(tree).to.deep.equal([
  163. new AST.SelectStatement({
  164. arguments: [new AST.Identifier("a")],
  165. from: new AST.Identifier("b"),
  166. where: new AST.Binary({
  167. left: new AST.Identifier("c"),
  168. right: new AST.Identifier("d"),
  169. type: AST.BinaryExpressionTypes.DIVISION,
  170. }),
  171. }),
  172. ]);
  173. });
  174. it("should parse a where with a complex binary expression", () => {
  175. const tree = parse("select a from b where c + d = e");
  176. expect(tree).to.deep.equal([
  177. new AST.SelectStatement({
  178. arguments: [new AST.Identifier("a")],
  179. from: new AST.Identifier("b"),
  180. where: new AST.Binary({
  181. left: new AST.Binary({
  182. left: new AST.Identifier("c"),
  183. right: new AST.Identifier("d"),
  184. type: AST.BinaryExpressionTypes.ADDITION,
  185. }),
  186. right: new AST.Identifier("e"),
  187. type: AST.BinaryExpressionTypes.EQUALITY,
  188. }),
  189. }),
  190. ]);
  191. });
  192. });