lib/sql_tree/node/expression.rb in sql_tree-0.0.2 vs lib/sql_tree/node/expression.rb in sql_tree-0.0.3
- old
+ new
@@ -3,15 +3,15 @@
# Base class for all SQL expressions.
#
# This is an asbtract class and should not be used directly. Use
# one of the subclasses instead.
class Expression < Base
-
+
def self.parse(tokens)
SQLTree::Node::LogicalExpression.parse(tokens)
end
-
+
# Parses a single, atomic SQL expression. This can be either:
# * a full expression (or set of expressions) within parentheses.
# * a logical NOT expression
# * an SQL variable
# * an SQL function
@@ -19,11 +19,11 @@
def self.parse_atomic(tokens)
case tokens.peek
when SQLTree::Token::LPAREN
tokens.consume(SQLTree::Token::LPAREN)
expr = SQLTree::Node::Expression.parse(tokens)
- tokens.consume(SQLTree::Token::RPAREN)
+ tokens.consume(SQLTree::Token::RPAREN)
expr
when SQLTree::Token::NOT
SQLTree::Node::LogicalNotExpression.parse(tokens)
when SQLTree::Token::Variable
if tokens.peek(2) == SQLTree::Token::LPAREN
@@ -34,27 +34,27 @@
else
SQLTree::Node::Value.parse(tokens)
end
end
end
-
+
class LogicalNotExpression < Expression
-
+
attr_accessor :expression
-
+
def initialize(expression)
@expression = expression
end
-
+
def to_sql
"NOT(#{@expression.to_sql})"
end
-
+
def ==(other)
other.kind_of?(self.class) && other.expression == self.expression
end
-
+
def self.parse(tokens)
tokens.consume(SQLTree::Token::NOT)
self.new(SQLTree::Node::Expression.parse(tokens))
end
end
@@ -72,33 +72,33 @@
end
def ==(other)
self.operator == other.operator && self.expressions == other.expressions
end
-
+
def self.parse(tokens)
expr = ComparisonExpression.parse(tokens)
while [SQLTree::Token::AND, SQLTree::Token::OR].include?(tokens.peek)
expr = SQLTree::Node::LogicalExpression.new(tokens.next.literal, [expr, ComparisonExpression.parse(tokens)])
- end
+ end
return expr
end
end
class ComparisonExpression < Expression
attr_accessor :lhs, :rhs, :operator
-
+
def initialize(operator, lhs, rhs)
@lhs = lhs
@rhs = rhs
@operator = operator
end
-
+
def to_sql
"(#{@lhs.to_sql} #{@operator} #{@rhs.to_sql})"
end
-
+
def self.parse_comparison_operator(tokens)
operator_token = tokens.next
if SQLTree::Token::IS === operator_token
if SQLTree::Token::NOT === tokens.peek
tokens.consume(SQLTree::Token::NOT)
@@ -115,97 +115,97 @@
end
else
operator_token.literal
end
end
-
+
def self.parse(tokens)
lhs = SQLTree::Node::ArithmeticExpression.parse(tokens)
while SQLTree::Token::COMPARISON_OPERATORS.include?(tokens.peek)
comparison_operator = parse_comparison_operator(tokens)
rhs = ['IN', 'NOT IN'].include?(comparison_operator) ?
SQLTree::Node::SetExpression.parse(tokens) :
SQLTree::Node::ArithmeticExpression.parse(tokens)
-
+
lhs = self.new(comparison_operator, lhs, rhs)
end
return lhs
end
end
-
+
class SetExpression < Expression
attr_accessor :items
-
+
def initialize(items = [])
@items = items
end
def to_sql
"(#{items.map {|i| i.to_sql}.join(', ')})"
end
-
+
def self.parse(tokens)
tokens.consume(SQLTree::Token::LPAREN)
items = [SQLTree::Node::Expression.parse(tokens)]
while tokens.peek == SQLTree::Token::COMMA
tokens.consume(SQLTree::Token::COMMA)
items << SQLTree::Node::Expression.parse(tokens)
end
tokens.consume(SQLTree::Token::RPAREN)
-
+
self.new(items)
end
end
-
+
class FunctionExpression < Expression
attr_accessor :function, :arguments
-
+
def initialize(function, arguments = [])
@function = function
@arguments = arguments
end
-
+
def to_sql
"#{@function}(" + @arguments.map { |e| e.to_sql }.join(', ') + ")"
end
-
+
def self.parse(tokens)
expr = self.new(tokens.next.literal)
tokens.consume(SQLTree::Token::LPAREN)
until tokens.peek == SQLTree::Token::RPAREN
expr.arguments << SQLTree::Node::Expression.parse(tokens)
tokens.consume(SQLTree::Token::COMMA) if tokens.peek == SQLTree::Token::COMMA
end
tokens.consume(SQLTree::Token::RPAREN)
- return expr
+ return expr
end
end
-
+
class ArithmeticExpression < Expression
attr_accessor :lhs, :rhs, :operator
-
+
def initialize(operator, lhs, rhs)
@lhs = lhs
@rhs = rhs
@operator = operator
end
-
+
def to_sql
"(#{@lhs.to_sql} #{@operator} #{@rhs.to_sql})"
end
-
+
def self.parse(tokens)
self.parse_primary(tokens)
end
-
+
def self.parse_primary(tokens)
expr = self.parse_secondary(tokens)
while [SQLTree::Token::PLUS, SQLTree::Token::MINUS].include?(tokens.peek)
expr = self.new(tokens.next.literal, expr, self.parse_secondary(tokens))
end
return expr
end
-
+
def self.parse_secondary(tokens)
expr = Expression.parse_atomic(tokens)
while [SQLTree::Token::PLUS, SQLTree::Token::MINUS].include?(tokens.peek)
expr = self.new(tokens.next.literal, expr, SQLTree::Node::Expression.parse_atomic(tokens))
end