1+ /**
2+ * Grammar for validating simple SQL selects.
3+ * @author Marcelo Camargo
4+ * @since 2015/08/26
5+ *
6+ * 2021/04/16: Add '>' and '<' operators (github/FSou1)
7+ */
8+
19{
210 var Sql = {
311 listToString: function(x, xs) {
816
917Start
1018 = Stmt
11-
19+
1220Stmt
1321 = SelectStmt
14-
22+
23+ /* Statements */
24+
1525SelectStmt
16- = SelectToken
17- _ x:SelectField xs:SelectFieldRest*
18- _ FromToken
19- _ from:Identifier {
20- return {
21- type: "select",
22- fields: [x].concat(xs),
23- from: from
24- };
25- }
26-
27- SelectToken
28- = "select"
26+ = _ SelectToken
27+ _ x:SelectField xs:SelectFieldRest*
28+ _ FromToken
29+ _ from:Identifier
30+ _ where:WhereExpr? {
31+ return {
32+ type: "SELECT",
33+ fields: [x].concat(xs),
34+ from: from,
35+ where: where
36+ };
37+ }
2938
30- SeparatorToken
31- = ","
32-
33- FromToken
34- = "from"
35-
3639SelectField "select valid field"
37- = "*"
40+ = Identifier
41+ / "*"
3842
3943SelectFieldRest
40- = SeparatorToken _ s:SelectField {
44+ = _ SeparatorToken _ s:SelectField {
4145 return s;
4246 }
4347
48+ WhereExpr "where expression"
49+ = WhereToken x:LogicExpr xs:LogicExprRest* {
50+ return {
51+ conditions: [x].concat(xs)
52+ };
53+ }
54+
55+ LogicExpr
56+ = _ "(" _ x:LogicExpr xs:LogicExprRest* _ ")" _ {
57+ return [x].concat(xs);
58+ }
59+ / _ left:Expr _ op:Operator _ right:Expr _ {
60+ return {
61+ left: left,
62+ op: op,
63+ right: right
64+ };
65+ }
66+
67+ LogicExprRest
68+ = _ j:Joiner _ l:LogicExpr {
69+ return {
70+ joiner: j,
71+ expression: l
72+ };
73+ }
74+
75+ Joiner "joiner"
76+ = OrToken { return "Or"; }
77+ / AndToken { return "And"; }
78+
79+ Operator
80+ = "<>" { return "Different"; }
81+ / ">" { return "GreaterThan"; }
82+ / "<" { return "LessThan"; }
83+ / "=" { return "Equal"; }
84+ / LikeToken { return "Like"; }
85+
86+ /* Expressions */
87+
88+ Expr
89+ = Float
90+ / Integer
91+ / Identifier
92+ / String
93+
94+ Integer "integer"
95+ = n:[0-9]+ {
96+ return parseInt(n.join(""));
97+ }
98+
99+ Float "float"
100+ = left:Integer "." right:Integer {
101+ return parseFloat([
102+ left.toString(),
103+ right.toString()
104+ ].join("."));
105+ }
106+
107+ String "string"
108+ = "'" str:ValidStringChar* "'" {
109+ return str.join("");
110+ }
111+
112+ ValidStringChar
113+ = !"'" c:. {
114+ return c;
115+ }
116+
117+ /* Tokens */
118+
119+ SelectToken
120+ = "SELECT"i !IdentRest
121+
122+ SeparatorToken
123+ = ","
124+
125+ FromToken
126+ = "FROM"i !IdentRest
127+
128+ WhereToken
129+ = "WHERE"i !IdentRest
130+
131+ LikeToken
132+ = "LIKE"i !IdentRest
133+
134+ OrToken
135+ = "OR"i !IdentRest
136+
137+ AndToken
138+ = "AND"i !IdentRest
139+
140+ /* Identifier */
141+
44142Identifier "identifier"
45143 = x:IdentStart xs:IdentRest* {
46144 return Sql.listToString(x, xs);
47145 }
48-
146+
49147IdentStart
50148 = [a-z_./]i
51-
149+
52150IdentRest
53151 = [a-z0-9_/-]i
54152
153+ /* Skip */
55154_
56- = ( WhiteSpace )
57-
155+ = ( WhiteSpace / NewLine )*
156+
157+ NewLine "newline"
158+ = "\r\n"
159+ / "\r"
160+ / "\n"
161+ / "\u2028"
162+ / "\u2029"
163+
58164WhiteSpace "whitespace"
59- = " "
165+ = " "
166+ / "\t"
167+ / "\v"
168+ / "\f"
0 commit comments