Skip to content

Commit 67af857

Browse files
committed
large refactor
- add UPDATE - add DELETE FROM - add LIMIT - add FOR UPDATE - add DISTINCT - add COALESCE function - fix selecting literals, e.g. (1 + 1) - refactor racc - fix escaped quotes (both \' and '') - better detection of invalid sql (e.g. SELECT1)
1 parent bb6ec82 commit 67af857

10 files changed

Lines changed: 1416 additions & 989 deletions

File tree

Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ end
2121
task :parser => [GENERATED_LEXER, GENERATED_PARSER]
2222

2323
# Make sure the parser's up-to-date when we test.
24-
Rake::Task['test'].prerequisites << :parser
24+
Rake::Task['test'].prerequisites << :parser

lib/sql-parser/parser.racc

Lines changed: 70 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,56 +9,55 @@ rule
99
direct_sql_data_statement
1010
: direct_select_statement_multiple_rows
1111
| insert_specification
12+
| update_statement
13+
| delete_statement
1214

13-
direct_select_statement_multiple_rows
14-
: query_expression order_by_clause { result = SQLParser::Statement::DirectSelect.new(val[0], val[1]) }
15+
update_statement
16+
: UPDATE table_reference SET assignment_list where_clause order_by_clause limit_clause { result = SQLParser::Statement::Update.new(val[1], val[3], val[4], val[5], val[6]) }
1517

16-
# module contents
17-
order_by_clause
18-
: # no action
19-
| ORDER BY sort_specification_list { result = SQLParser::Statement::OrderBy.new(val[2]) }
18+
assignment_list
19+
: assignment_list comma assignment { result = Array(val[0]) + Array(val[2]) }
20+
| assignment { result = Array(val[0]) }
2021

21-
sort_specification_list
22-
: sort_specification_list comma sort_specification { result = Array(val[0]) + Array(val[2]) }
23-
| sort_specification
22+
assignment
23+
: column_reference equals_operator value_expression { result = SQLParser::Statement::Assignment.new(val[0], val[2]) }
2424

25-
sort_specification
26-
: sort_key ordering_specification { result = val[1].new(val[0]) }
25+
# MySQL seems to support deletes from multiple tables http://dev.mysql.com/doc/refman/5.7/en/delete.html
26+
delete_statement
27+
: DELETE FROM table_reference where_clause order_by_clause limit_clause { result = SQLParser::Statement::Delete.new(val[2], val[3], val[4], val[5]) }
2728

28-
sort_key
29-
: column_name
30-
| unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
29+
direct_select_statement_multiple_rows
30+
: query_expression maybe_for_update { result = SQLParser::Statement::DirectSelect.new(val[0], val[1]) }
3131

32-
ordering_specification
33-
: { result = SQLParser::Statement::Ascending } # default
34-
| ASC { result = SQLParser::Statement::Ascending }
35-
| DESC { result = SQLParser::Statement::Descending }
32+
maybe_for_update
33+
: # no action
34+
| FOR UPDATE
3635

3736
# queries
3837
subquery
3938
# FIXME: shortcut
4039
: left_paren query_expression right_paren { result = SQLParser::Statement::Subquery.new(val[1]) }
4140

4241
query_expression
43-
: query_specification
42+
: SELECT distinct select_list table_expression { result = SQLParser::Statement::Select.new(val[1], val[2], val[3]) }
4443

4544
insert_specification
46-
: INSERT INTO table_reference value_list { result = SQLParser::Statement::Insert.new(val[2], nil, val[3]) }
47-
| INSERT INTO table_reference column_list value_list { result = SQLParser::Statement::Insert.new(val[2], val[3], val[4]) }
45+
: INSERT INTO table_factor column_list value_list { result = SQLParser::Statement::Insert.new(val[2], val[3], val[4]) }
4846

4947
column_list
50-
: left_paren in_column_list right_paren { result = SQLParser::Statement::InColumnList.new(val[1]) }
48+
: # no action
49+
| left_paren in_column_list right_paren { result = SQLParser::Statement::InColumnList.new(val[1]) }
5150

5251
in_column_list
53-
: value_expression comma in_column_list { result = Array(val[0]) + Array(val[2]) }
54-
| value_expression
52+
: column_reference comma in_column_list { result = Array(val[0]) + Array(val[2]) }
53+
| column_reference
5554

5655
value_list
5756
: VALUES left_paren in_value_list right_paren { result = SQLParser::Statement::InValueList.new(val[2]) }
5857

59-
query_specification
60-
: SELECT select_list table_expression { result = SQLParser::Statement::Select.new(val[1], val[2]) }
61-
| SELECT select_list { result = SQLParser::Statement::Select.new(val[1]) }
58+
distinct
59+
: # no action
60+
| DISTINCT
6261

6362
select_list
6463
: asterisk { result = SQLParser::Statement::All.new }
@@ -71,18 +70,23 @@ rule
7170
derived_column
7271
: value_expression AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
7372
| value_expression column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
73+
| search_condition
7474
| value_expression
7575

7676
table_expression
77-
: from_clause where_clause group_by_clause having_clause { result = SQLParser::Statement::TableExpression.new(val[0], val[1], val[2], val[3]) }
77+
: # no action
78+
| from_clause where_clause group_by_clause having_clause order_by_clause limit_clause { result = SQLParser::Statement::TableExpression.new(val[0], val[1], val[2], val[3], val[4], val[5]) }
7879

7980
from_clause
8081
: FROM table_reference { result = SQLParser::Statement::FromClause.new(val[1]) }
8182

82-
table_reference
83+
table_factor
8384
: table_name AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
8485
| table_name column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
8586
| table_name
87+
88+
table_reference
89+
: table_factor
8690
| joined_table
8791

8892
table_subquery
@@ -140,6 +144,30 @@ rule
140144
: # no action
141145
| HAVING search_condition { result = SQLParser::Statement::HavingClause.new(val[1]) }
142146

147+
order_by_clause
148+
: # no action
149+
| ORDER BY sort_specification_list { result = SQLParser::Statement::OrderBy.new(val[2]) }
150+
151+
sort_specification_list
152+
: sort_specification_list comma sort_specification { result = Array(val[0]) + Array(val[2]) }
153+
| sort_specification
154+
155+
sort_specification
156+
: sort_key ordering_specification { result = val[1].new(val[0]) }
157+
158+
sort_key
159+
: column_reference
160+
| value_expression
161+
162+
ordering_specification
163+
: { result = SQLParser::Statement::Ascending } # default
164+
| ASC { result = SQLParser::Statement::Ascending }
165+
| DESC { result = SQLParser::Statement::Descending }
166+
167+
limit_clause
168+
: # no action
169+
| LIMIT unsigned_integer { result = SQLParser::Statement::Limit.new(val[1]) }
170+
143171
# query expression components
144172
row_subquery
145173
: subquery
@@ -196,9 +224,6 @@ rule
196224
| boolean_test
197225

198226
boolean_test
199-
: boolean_primary
200-
201-
boolean_primary
202227
: predicate
203228
| left_paren search_condition right_paren { result = val[1] }
204229

@@ -209,6 +234,7 @@ rule
209234
| like_predicate
210235
| null_predicate
211236
| exists_predicate
237+
| value_expression
212238

213239
comparison_predicate
214240
: row_value_constructor equals_operator row_value_constructor { result = SQLParser::Statement::Equals.new(val[0], val[2]) }
@@ -225,6 +251,10 @@ rule
225251
row_value_constructor_element
226252
: value_expression
227253

254+
value_expression_list
255+
: value_expression_list comma value_expresson { result = Array(val[0]) + Array(val[2]) }
256+
| value_expression
257+
228258
value_expression
229259
: numeric_value_expression
230260
| general_literal
@@ -248,6 +278,7 @@ rule
248278
| column_reference
249279
| set_function_specification
250280
| left_paren value_expression right_paren { result = val[1] }
281+
| NULL { result = SQLParser::Statement::Null.new }
251282

252283
unsigned_value_specification
253284
: unsigned_literal
@@ -261,14 +292,18 @@ rule
261292
: CURRENT_USER { result = SQLParser::Statement::CurrentUser.new }
262293

263294
column_reference
264-
: qualifier period column_name { result = SQLParser::Statement::QualifiedColumn.new(val[0], val[2]) }
295+
: qualifier period column_or_star { result = SQLParser::Statement::QualifiedColumn.new(val[0], val[2]) }
265296
| column_name
266297

298+
column_or_star
299+
: column_name
300+
| asterisk { result = SQLParser::Statement::All.new }
301+
267302
qualifier
268303
: table_name
269304

270305
set_function_specification
271-
: COUNT left_paren asterisk right_paren { result = SQLParser::Statement::Count.new(SQLParser::Statement::All.new) }
306+
: COUNT left_paren distinct asterisk right_paren { result = SQLParser::Statement::Count.new(SQLParser::Statement::All.new) }
272307
| general_set_function
273308

274309
general_set_function
@@ -277,6 +312,7 @@ rule
277312
| MAX left_paren value_expression right_paren { result = SQLParser::Statement::Maximum.new(val[2]) }
278313
| MIN left_paren value_expression right_paren { result = SQLParser::Statement::Minimum.new(val[2]) }
279314
| SUM left_paren value_expression right_paren { result = SQLParser::Statement::Sum.new(val[2]) }
315+
| COALESCE left_paren value_expression_list right_paren { result = SQLParser::Statement::Coalesce.new(val[2]) }
280316

281317
# literal numbers, strings, dates and times
282318
unsigned_numeric_literal

0 commit comments

Comments
 (0)