Skip to content

Commit 9953bba

Browse files
committed
DRY up comma separated list parsing.
1 parent b8586d0 commit 9953bba

File tree

6 files changed

+28
-59
lines changed

6 files changed

+28
-59
lines changed

lib/sql_tree/node.rb

+9
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ def equal_leafs?(other)
8181
def self.parse(tokens)
8282
raise 'Only implemented in subclasses!'
8383
end
84+
85+
def self.parse_list(tokens, item_class = SQLTree::Node::Expression)
86+
items = [item_class.parse(tokens)]
87+
while SQLTree::Token::COMMA === tokens.peek
88+
tokens.consume(SQLTree::Token::COMMA)
89+
items << item_class.parse(tokens)
90+
end
91+
return items
92+
end
8493

8594
# Parses a string, expecting it to be parsable to an instance of
8695
# the current class.

lib/sql_tree/node/expression.rb

+8-10
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,9 @@ def self.parse(tokens)
295295
tokens.consume(SQLTree::Token::LPAREN)
296296
items = []
297297
unless SQLTree::Token::RPAREN === tokens.peek
298-
items << SQLTree::Node::Expression.parse(tokens)
299-
while SQLTree::Token::COMMA === tokens.peek
300-
tokens.consume(SQLTree::Token::COMMA)
301-
items << SQLTree::Node::Expression.parse(tokens)
302-
end
298+
items = self.parse_list(tokens, SQLTree::Node::Expression)
303299
end
304300
tokens.consume(SQLTree::Token::RPAREN)
305-
306301
self.new(items)
307302
end
308303
end
@@ -315,11 +310,11 @@ class FunctionCall < SQLTree::Node::Expression
315310
leaf :function
316311

317312
# The argument list as {SQLTree::Node::Expression::List} instance.
318-
child :argument_list
313+
child :arguments
319314

320315
# Generates an SQL fragment for this function call.
321316
def to_sql(options = {})
322-
"#{function}(" + argument_list.items.map { |e| e.to_sql(options) }.join(', ') + ")"
317+
"#{function}(" + arguments.map { |e| e.to_sql(options) }.join(', ') + ")"
323318
end
324319

325320
# Parses an SQL function call.
@@ -331,8 +326,11 @@ def to_sql(options = {})
331326
# @raise [SQLTree::Parser::UnexpectedToken] if an unexpected token is
332327
# encountered during parsing.
333328
def self.parse(tokens)
334-
return self.new(:function => tokens.next.literal,
335-
:argument_list => SQLTree::Node::Expression::List.parse(tokens))
329+
function_call = self.new(:function => tokens.next.literal, :arguments => [])
330+
tokens.consume(SQLTree::Token::LPAREN)
331+
function_call.arguments = self.parse_list(tokens) unless SQLTree::Token::RPAREN === tokens.peek
332+
tokens.consume(SQLTree::Token::RPAREN)
333+
return function_call
336334
end
337335
end
338336

lib/sql_tree/node/insert_query.rb

+2-10
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,15 @@ def to_sql(options = {})
2121

2222
def self.parse_field_list(tokens)
2323
tokens.consume(SQLTree::Token::LPAREN)
24-
fields = [SQLTree::Node::Expression::Field.parse(tokens)]
25-
while SQLTree::Token::COMMA === tokens.peek
26-
tokens.consume(SQLTree::Token::COMMA)
27-
fields << SQLTree::Node::Expression::Field.parse(tokens)
28-
end
24+
fields = parse_list(tokens, SQLTree::Node::Expression::Field)
2925
tokens.consume(SQLTree::Token::RPAREN)
3026
return fields
3127
end
3228

3329
def self.parse_value_list(tokens)
3430
tokens.consume(SQLTree::Token::VALUES)
3531
tokens.consume(SQLTree::Token::LPAREN)
36-
values = [SQLTree::Node::Expression.parse(tokens)]
37-
while SQLTree::Token::COMMA === tokens.peek
38-
tokens.consume(SQLTree::Token::COMMA)
39-
values << SQLTree::Node::Expression.parse(tokens)
40-
end
32+
values = parse_list(tokens)
4133
tokens.consume(SQLTree::Token::RPAREN)
4234
return values
4335
end

lib/sql_tree/node/select_query.rb

+6-32
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def self.parse(tokens)
3838
select_node.distinct = true
3939
end
4040

41-
select_node.select = self.parse_select_clause(tokens)
41+
select_node.select = parse_list(tokens, SQLTree::Node::SelectDeclaration)
4242
select_node.from = self.parse_from_clause(tokens) if SQLTree::Token::FROM === tokens.peek
4343
select_node.where = self.parse_where_clause(tokens) if SQLTree::Token::WHERE === tokens.peek
4444
if SQLTree::Token::GROUP === tokens.peek
@@ -49,23 +49,9 @@ def self.parse(tokens)
4949
return select_node
5050
end
5151

52-
def self.parse_select_clause(tokens)
53-
expressions = [SQLTree::Node::SelectDeclaration.parse(tokens)]
54-
while SQLTree::Token::COMMA === tokens.peek
55-
tokens.consume(SQLTree::Token::COMMA)
56-
expressions << SQLTree::Node::SelectDeclaration.parse(tokens)
57-
end
58-
return expressions
59-
end
60-
6152
def self.parse_from_clause(tokens)
6253
tokens.consume(SQLTree::Token::FROM)
63-
sources = [SQLTree::Node::Source.parse(tokens)]
64-
while SQLTree::Token::COMMA === tokens.peek
65-
tokens.consume(SQLTree::Token::COMMA)
66-
sources << SQLTree::Node::Source.parse(tokens)
67-
end
68-
return sources
54+
parse_list(tokens, SQLTree::Node::Source)
6955
end
7056

7157
def self.parse_where_clause(tokens)
@@ -74,14 +60,8 @@ def self.parse_where_clause(tokens)
7460
end
7561

7662
def self.parse_group_clause(tokens)
77-
tokens.consume(SQLTree::Token::GROUP)
78-
tokens.consume(SQLTree::Token::BY)
79-
exprs = [SQLTree::Node::Expression.parse(tokens)]
80-
while SQLTree::Token::COMMA === tokens.peek
81-
tokens.consume(SQLTree::Token::COMMA)
82-
exprs << SQLTree::Node::Expression.parse(tokens)
83-
end
84-
return exprs
63+
tokens.consume(SQLTree::Token::GROUP, SQLTree::Token::BY)
64+
parse_list(tokens)
8565
end
8666

8767
def self.parse_having_clause(tokens)
@@ -90,14 +70,8 @@ def self.parse_having_clause(tokens)
9070
end
9171

9272
def self.parse_order_clause(tokens)
93-
tokens.consume(SQLTree::Token::ORDER)
94-
tokens.consume(SQLTree::Token::BY)
95-
exprs = [SQLTree::Node::Ordering.parse(tokens)]
96-
while SQLTree::Token::COMMA === tokens.peek
97-
tokens.consume(SQLTree::Token::COMMA)
98-
exprs << SQLTree::Node::Ordering.parse(tokens)
99-
end
100-
return exprs
73+
tokens.consume(SQLTree::Token::ORDER, SQLTree::Token::BY)
74+
parse_list(tokens, SQLTree::Node::Ordering)
10175
end
10276

10377
def self.parse_limit_clause(tokens)

lib/sql_tree/node/update_query.rb

+1-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ def self.parse(tokens)
4343
tokens.consume(SQLTree::Token::UPDATE)
4444
update_query = self.new(SQLTree::Node::TableReference.parse(tokens))
4545
tokens.consume(SQLTree::Token::SET)
46-
update_query.updates = [SQLTree::Node::UpdateQuery::Assignment.parse(tokens)]
47-
while SQLTree::Token::COMMA === tokens.peek
48-
tokens.consume(SQLTree::Token::COMMA)
49-
update_query.updates << SQLTree::Node::UpdateQuery::Assignment.parse(tokens)
50-
end
46+
update_query.updates = parse_list(tokens, SQLTree::Node::UpdateQuery::Assignment)
5147

5248
if SQLTree::Token::WHERE === tokens.peek
5349
tokens.consume(SQLTree::Token::WHERE)

spec/unit/expression_node_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
it "shoud parse a function call without arguments correctly" do
1111
function = SQLTree::Node::Expression['NOW()']
1212
function.function.should == 'NOW'
13-
function.argument_list.should be_empty
13+
function.arguments.should be_empty
1414
end
1515

1616
it "shoud parse a function call with arguments correctly" do
1717
function = SQLTree::Node::Expression["MD5('string')"]
1818
function.function.should == 'MD5'
19-
function.argument_list.items.should == [SQLTree::Node::Expression::Value.new('string')]
19+
function.arguments.should == [SQLTree::Node::Expression::Value.new('string')]
2020
end
2121

2222
it "should parse a logical OR expression correctly" do

0 commit comments

Comments
 (0)