From c055531ef7058a79ac958671555cc4c9cefc645d Mon Sep 17 00:00:00 2001
From: Todd Persen <todd.persen@gmail.com>
Date: Tue, 8 Oct 2013 16:02:18 -0400
Subject: [PATCH] fix the associativity of the arithmetic operators

---
 src/query/parser_test.go | 565 ++++++++++++++++++++-------------------
 src/query/query.yacc     |  38 ++-
 src/query/y.tab.c        | 295 +++++++++++---------
 3 files changed, 477 insertions(+), 421 deletions(-)

diff --git a/src/query/parser_test.go b/src/query/parser_test.go
index f6f56957ca..2d91768100 100644
--- a/src/query/parser_test.go
+++ b/src/query/parser_test.go
@@ -3,7 +3,6 @@ package query
 import (
 	. "launchpad.net/gocheck"
 	"testing"
-	"fmt"
 )
 
 // Hook up gocheck into the gotest runner.
@@ -22,335 +21,335 @@ func ToValueArray(strings ...string) (values []*Value) {
 	return
 }
 
-// func (self *QueryParserSuite) TestParseBasicSelectQuery(c *C) {
-// 	q, err := ParseQuery("select value from t where c == '5';")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseBasicSelectQuery(c *C) {
+	q, err := ParseQuery("select value from t where c == '5';")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.Limit, Equals, 0)
+	c.Assert(q.Limit, Equals, 0)
 
-// 	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("value"))
-// 	w := q.GetWhereCondition()
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
+	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("value"))
+	w := q.GetWhereCondition()
+	c.Assert(q.GetFromClause().Name, Equals, "t")
 
-// 	boolExpression, ok := w.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
+	boolExpression, ok := w.GetBoolExpression()
+	c.Assert(ok, Equals, true)
 
-// 	leftExpression := boolExpression.Left
-// 	rightExpression := boolExpression.Right
+	leftExpression := boolExpression.Left
+	rightExpression := boolExpression.Right
 
-// 	leftValue, ok := leftExpression.GetLeftValue() // simple value is an expression with one value, e.g. it doesn't combine value using arithmetic operations
-// 	rightValue, ok := rightExpression.GetLeftValue()
+	leftValue, ok := leftExpression.GetLeftValue() // simple value is an expression with one value, e.g. it doesn't combine value using arithmetic operations
+	rightValue, ok := rightExpression.GetLeftValue()
 
-// 	c.Assert(leftValue.Name, Equals, "c")
-// 	c.Assert(boolExpression.Operation, Equals, "==")
-// 	c.Assert(rightValue.Name, Equals, "5")
-// }
+	c.Assert(leftValue.Name, Equals, "c")
+	c.Assert(boolExpression.Operation, Equals, "==")
+	c.Assert(rightValue.Name, Equals, "5")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithoutWhereClause(c *C) {
-// 	q, err := ParseQuery("select value, time from t;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("value", "time"))
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
-// 	c.Assert(q.GetWhereCondition(), IsNil)
-// }
+func (self *QueryParserSuite) TestParseSelectWithoutWhereClause(c *C) {
+	q, err := ParseQuery("select value, time from t;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("value", "time"))
+	c.Assert(q.GetFromClause().Name, Equals, "t")
+	c.Assert(q.GetWhereCondition(), IsNil)
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithUpperCase(c *C) {
-// 	q, err := ParseQuery("SELECT VALUE, TIME FROM t WHERE C == '5';")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("VALUE", "TIME"))
-// 	w := q.GetWhereCondition()
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
+func (self *QueryParserSuite) TestParseSelectWithUpperCase(c *C) {
+	q, err := ParseQuery("SELECT VALUE, TIME FROM t WHERE C == '5';")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetColumnNames(), DeepEquals, ToValueArray("VALUE", "TIME"))
+	w := q.GetWhereCondition()
+	c.Assert(q.GetFromClause().Name, Equals, "t")
 
-// 	boolExpression, ok := w.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
-// 	leftExpression := boolExpression.Left
-// 	rightExpression := boolExpression.Right
+	boolExpression, ok := w.GetBoolExpression()
+	c.Assert(ok, Equals, true)
+	leftExpression := boolExpression.Left
+	rightExpression := boolExpression.Right
 
-// 	leftValue, ok := leftExpression.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	rightValue, ok := rightExpression.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
+	leftValue, ok := leftExpression.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	rightValue, ok := rightExpression.GetLeftValue()
+	c.Assert(ok, Equals, true)
 
-// 	c.Assert(leftValue.Name, Equals, "C")
-// 	c.Assert(rightValue.Name, Equals, "5")
-// }
+	c.Assert(leftValue.Name, Equals, "C")
+	c.Assert(rightValue.Name, Equals, "5")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithMultipleColumns(c *C) {
-// 	q, err := ParseQuery("select value, time from t;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
-// }
+func (self *QueryParserSuite) TestParseSelectWithMultipleColumns(c *C) {
+	q, err := ParseQuery("select value, time from t;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetFromClause().Name, Equals, "t")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithInequality(c *C) {
-// 	q, err := ParseQuery("select value, time from t where c < 5;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	w := q.GetWhereCondition()
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
+func (self *QueryParserSuite) TestParseSelectWithInequality(c *C) {
+	q, err := ParseQuery("select value, time from t where c < 5;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	w := q.GetWhereCondition()
+	c.Assert(q.GetFromClause().Name, Equals, "t")
 
-// 	boolExpression, ok := w.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
-// 	leftExpression := boolExpression.Left
-// 	rightExpression := boolExpression.Right
-// 	leftValue, ok := leftExpression.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	rightValue, ok := rightExpression.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
+	boolExpression, ok := w.GetBoolExpression()
+	c.Assert(ok, Equals, true)
+	leftExpression := boolExpression.Left
+	rightExpression := boolExpression.Right
+	leftValue, ok := leftExpression.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	rightValue, ok := rightExpression.GetLeftValue()
+	c.Assert(ok, Equals, true)
 
-// 	c.Assert(leftValue.Name, Equals, "c")
-// 	c.Assert(boolExpression.Operation, Equals, "<")
-// 	c.Assert(rightValue.Name, Equals, "5")
-// }
+	c.Assert(leftValue.Name, Equals, "c")
+	c.Assert(boolExpression.Operation, Equals, "<")
+	c.Assert(rightValue.Name, Equals, "5")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithTimeCondition(c *C) {
-// 	q, err := ParseQuery("select value, time from t where time > now() - 1d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	w := q.GetWhereCondition()
+func (self *QueryParserSuite) TestParseSelectWithTimeCondition(c *C) {
+	q, err := ParseQuery("select value, time from t where time > now() - 1d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	w := q.GetWhereCondition()
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "t")
+	c.Assert(q.GetFromClause().Name, Equals, "t")
 
-// 	boolExpression, ok := w.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
+	boolExpression, ok := w.GetBoolExpression()
+	c.Assert(ok, Equals, true)
 
-// 	leftExpression := boolExpression.Left
-// 	leftValue, ok := leftExpression.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(leftValue.Name, Equals, "time")
+	leftExpression := boolExpression.Left
+	leftValue, ok := leftExpression.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(leftValue.Name, Equals, "time")
 
-// 	rightExpression := boolExpression.Right
-// 	funCallExpr, ok := rightExpression.GetLeftExpression()
-// 	c.Assert(ok, Equals, true)
-// 	funCall, ok := funCallExpr.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	oneDay, ok := rightExpression.Right.GetLeftValue()
-//   c.Assert(ok, Equals, true)
+	rightExpression := boolExpression.Right
+	funCallExpr, ok := rightExpression.GetLeftExpression()
+	c.Assert(ok, Equals, true)
+	funCall, ok := funCallExpr.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	oneDay, ok := rightExpression.Right.GetLeftValue()
+  c.Assert(ok, Equals, true)
 
-// 	c.Assert(funCall.IsFunctionCall(), Equals, true)
-// 	c.Assert(funCall.Name, Equals, "now")
-// 	c.Assert(oneDay.IsFunctionCall(), Equals, false)
-// 	c.Assert(oneDay.Name, Equals, "1d")
-// 	c.Assert(rightExpression.Operation, Equals, byte('-'))
-// }
+	c.Assert(funCall.IsFunctionCall(), Equals, true)
+	c.Assert(funCall.Name, Equals, "now")
+	c.Assert(oneDay.IsFunctionCall(), Equals, false)
+	c.Assert(oneDay.Name, Equals, "1d")
+	c.Assert(rightExpression.Operation, Equals, byte('-'))
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithAnd(c *C) {
-// 	q, err := ParseQuery("select value from cpu.idle where time>now()-7d and time<now()-6d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseSelectWithAnd(c *C) {
+	q, err := ParseQuery("select value from cpu.idle where time>now()-7d and time<now()-6d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
+	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
 
-// 	w := q.GetWhereCondition()
-// 	c.Assert(w.Operation, Equals, "AND")
+	w := q.GetWhereCondition()
+	c.Assert(w.Operation, Equals, "AND")
 
-// 	// leftBoolExpression = 'time > now() - 7d'
-// 	leftWhereCondition, ok := w.GetLeftWhereCondition()
-// 	c.Assert(ok, Equals, true)
-// 	leftBoolExpression, ok := leftWhereCondition.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
-// 	// rightBoolExpression = 'time < now() - 6d'
-// 	rightBoolExpression, ok := w.Right.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
+	// leftBoolExpression = 'time > now() - 7d'
+	leftWhereCondition, ok := w.GetLeftWhereCondition()
+	c.Assert(ok, Equals, true)
+	leftBoolExpression, ok := leftWhereCondition.GetBoolExpression()
+	c.Assert(ok, Equals, true)
+	// rightBoolExpression = 'time < now() - 6d'
+	rightBoolExpression, ok := w.Right.GetBoolExpression()
+	c.Assert(ok, Equals, true)
 
-// 	c.Assert(leftBoolExpression.Left.Left, DeepEquals, &Value{"time", nil})
-// 	expr, ok := leftBoolExpression.Right.GetLeftExpression()
-// 	c.Assert(ok, Equals, true)
-// 	value, ok := expr.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
-// 	value, ok = leftBoolExpression.Right.Right.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"7d", nil})
-// 	c.Assert(leftBoolExpression.Operation, Equals, ">")
+	c.Assert(leftBoolExpression.Left.Left, DeepEquals, &Value{"time", nil})
+	expr, ok := leftBoolExpression.Right.GetLeftExpression()
+	c.Assert(ok, Equals, true)
+	value, ok := expr.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
+	value, ok = leftBoolExpression.Right.Right.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"7d", nil})
+	c.Assert(leftBoolExpression.Operation, Equals, ">")
 
-// 	c.Assert(rightBoolExpression.Left.Left, DeepEquals, &Value{"time", nil})
-// 	expr, ok = rightBoolExpression.Right.GetLeftExpression()
-// 	c.Assert(ok, Equals, true)
-// 	value, ok = expr.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
-// 	value, ok = rightBoolExpression.Right.Right.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"6d", nil})
-// 	c.Assert(rightBoolExpression.Operation, Equals, "<")
-// }
+	c.Assert(rightBoolExpression.Left.Left, DeepEquals, &Value{"time", nil})
+	expr, ok = rightBoolExpression.Right.GetLeftExpression()
+	c.Assert(ok, Equals, true)
+	value, ok = expr.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
+	value, ok = rightBoolExpression.Right.Right.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"6d", nil})
+	c.Assert(rightBoolExpression.Operation, Equals, "<")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithGroupBy(c *C) {
-// 	q, err := ParseQuery("select count(*) from users.events group_by user_email,time(1h) where time>now()-1d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseSelectWithGroupBy(c *C) {
+	q, err := ParseQuery("select count(*) from users.events group_by user_email,time(1h) where time>now()-1d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "users.events")
-// 	c.Assert(q.GetColumnNames(), HasLen, 1)
+	c.Assert(q.GetFromClause().Name, Equals, "users.events")
+	c.Assert(q.GetColumnNames(), HasLen, 1)
 
-// 	column := q.GetColumnNames()[0]
-// 	c.Assert(column.IsFunctionCall(), Equals, true)
-// 	c.Assert(column.Name, Equals, "count")
-// 	c.Assert(column.Elems, HasLen, 1)
-// 	c.Assert(column.Elems[0].IsFunctionCall(), Equals, false)
-// 	c.Assert(column.Elems[0].Name, Equals, "*")
+	column := q.GetColumnNames()[0]
+	c.Assert(column.IsFunctionCall(), Equals, true)
+	c.Assert(column.Name, Equals, "count")
+	c.Assert(column.Elems, HasLen, 1)
+	c.Assert(column.Elems[0].IsFunctionCall(), Equals, false)
+	c.Assert(column.Elems[0].Name, Equals, "*")
 
-// 	groupBy := q.GetGroupByClause()
-// 	c.Assert(groupBy, HasLen, 2)
-// 	c.Assert(groupBy[0].IsFunctionCall(), Equals, false)
-// 	c.Assert(groupBy[0].Name, Equals, "user_email")
-// 	c.Assert(groupBy[1].IsFunctionCall(), Equals, true)
-// 	c.Assert(groupBy[1].Name, Equals, "time")
-// 	c.Assert(groupBy[1].Elems, HasLen, 1)
-// 	c.Assert(groupBy[1].Elems[0].Name, Equals, "1h")
-// }
+	groupBy := q.GetGroupByClause()
+	c.Assert(groupBy, HasLen, 2)
+	c.Assert(groupBy[0].IsFunctionCall(), Equals, false)
+	c.Assert(groupBy[0].Name, Equals, "user_email")
+	c.Assert(groupBy[1].IsFunctionCall(), Equals, true)
+	c.Assert(groupBy[1].Name, Equals, "time")
+	c.Assert(groupBy[1].Elems, HasLen, 1)
+	c.Assert(groupBy[1].Elems[0].Name, Equals, "1h")
+}
 
-// func (self *QueryParserSuite) TestParseFromWithNestedFunctions(c *C) {
-// 	q, err := ParseQuery("select top(10, count(*)) from users.events;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetColumnNames(), HasLen, 1)
-// 	column := q.GetColumnNames()[0]
-// 	c.Assert(column.IsFunctionCall(), Equals, true)
-// 	c.Assert(column.Name, Equals, "top")
-// 	c.Assert(column.Elems, HasLen, 2)
-// 	c.Assert(column.Elems[0].IsFunctionCall(), Equals, false)
-// 	c.Assert(column.Elems[0].Name, Equals, "10")
-// 	c.Assert(column.Elems[1].IsFunctionCall(), Equals, true)
-// 	c.Assert(column.Elems[1].Name, Equals, "count")
-// 	c.Assert(column.Elems[1].Elems, HasLen, 1)
-// 	c.Assert(column.Elems[1].Elems[0].IsFunctionCall(), Equals, false)
-// 	c.Assert(column.Elems[1].Elems[0].Name, Equals, "*")
-// }
+func (self *QueryParserSuite) TestParseFromWithNestedFunctions(c *C) {
+	q, err := ParseQuery("select top(10, count(*)) from users.events;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetColumnNames(), HasLen, 1)
+	column := q.GetColumnNames()[0]
+	c.Assert(column.IsFunctionCall(), Equals, true)
+	c.Assert(column.Name, Equals, "top")
+	c.Assert(column.Elems, HasLen, 2)
+	c.Assert(column.Elems[0].IsFunctionCall(), Equals, false)
+	c.Assert(column.Elems[0].Name, Equals, "10")
+	c.Assert(column.Elems[1].IsFunctionCall(), Equals, true)
+	c.Assert(column.Elems[1].Name, Equals, "count")
+	c.Assert(column.Elems[1].Elems, HasLen, 1)
+	c.Assert(column.Elems[1].Elems[0].IsFunctionCall(), Equals, false)
+	c.Assert(column.Elems[1].Elems[0].Name, Equals, "*")
+}
 
-// func (self *QueryParserSuite) TestParseWhereClausePrecedence(c *C) {
-// 	q, err := ParseQuery("select value from cpu.idle where value > 90 and time > now() - 1d or value > 80 and time > now() - 1w;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseWhereClausePrecedence(c *C) {
+	q, err := ParseQuery("select value from cpu.idle where value > 90 and time > now() - 1d or value > 80 and time > now() - 1w;")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
+	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
 
-// 	whereCondition := q.GetWhereCondition()
+	whereCondition := q.GetWhereCondition()
 
-// 	c.Assert(whereCondition.Operation, Equals, "OR")
-// 	leftCondition, ok := whereCondition.Left.(*WhereCondition)
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(leftCondition.Operation, Equals, "AND")
+	c.Assert(whereCondition.Operation, Equals, "OR")
+	leftCondition, ok := whereCondition.Left.(*WhereCondition)
+	c.Assert(ok, Equals, true)
+	c.Assert(leftCondition.Operation, Equals, "AND")
 
-// 	condition, ok := leftCondition.GetLeftWhereCondition()
-// 	c.Assert(ok, Equals, true)
-// 	leftExpression, ok := condition.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(leftExpression.Operation, Equals, ">")
-// 	c.Assert(leftExpression.Left.Left, DeepEquals, &Value{"value", nil})
-// 	c.Assert(leftExpression.Right.Left, DeepEquals, &Value{"90", nil})
+	condition, ok := leftCondition.GetLeftWhereCondition()
+	c.Assert(ok, Equals, true)
+	leftExpression, ok := condition.GetBoolExpression()
+	c.Assert(ok, Equals, true)
+	c.Assert(leftExpression.Operation, Equals, ">")
+	c.Assert(leftExpression.Left.Left, DeepEquals, &Value{"value", nil})
+	c.Assert(leftExpression.Right.Left, DeepEquals, &Value{"90", nil})
 
-// 	rightExpression, ok := leftCondition.Right.GetBoolExpression()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(rightExpression.Operation, Equals, ">")
-// 	c.Assert(rightExpression.Left.Left, DeepEquals, &Value{"time", nil})
-// 	expr, ok := rightExpression.Right.GetLeftExpression()
-// 	value, ok := expr.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
-// 	value, ok = rightExpression.Right.Right.GetLeftValue()
-// 	c.Assert(ok, Equals, true)
-// 	c.Assert(value, DeepEquals, &Value{"1d", nil})
-// }
+	rightExpression, ok := leftCondition.Right.GetBoolExpression()
+	c.Assert(ok, Equals, true)
+	c.Assert(rightExpression.Operation, Equals, ">")
+	c.Assert(rightExpression.Left.Left, DeepEquals, &Value{"time", nil})
+	expr, ok := rightExpression.Right.GetLeftExpression()
+	value, ok := expr.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"now", []*Value{}})
+	value, ok = rightExpression.Right.Right.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value, DeepEquals, &Value{"1d", nil})
+}
 
-// func (self *QueryParserSuite) TestParseWhereClauseParantheses(c *C) {
-// 	q, err := ParseQuery("select value from cpu.idle where value > 90 and (time > now() - 1d or value > 80) and time < now() - 1w;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseWhereClauseParantheses(c *C) {
+	q, err := ParseQuery("select value from cpu.idle where value > 90 and (time > now() - 1d or value > 80) and time < now() - 1w;")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
+	c.Assert(q.GetFromClause().Name, Equals, "cpu.idle")
 
-// 	whereCondition := q.GetWhereCondition()
+	whereCondition := q.GetWhereCondition()
 
-// 	first := whereCondition.Left.(*WhereCondition).Left.(*WhereCondition).Left.(*BoolExpression)
-// 	second := whereCondition.Left.(*WhereCondition).Right
-// 	third := whereCondition.Right.Left.(*BoolExpression)
+	first := whereCondition.Left.(*WhereCondition).Left.(*WhereCondition).Left.(*BoolExpression)
+	second := whereCondition.Left.(*WhereCondition).Right
+	third := whereCondition.Right.Left.(*BoolExpression)
 
-// 	c.Assert(first.Operation, Equals, ">")
-// 	c.Assert(second.Operation, Equals, "OR")
-// 	c.Assert(third.Operation, Equals, "<")
-// }
+	c.Assert(first.Operation, Equals, ">")
+	c.Assert(second.Operation, Equals, "OR")
+	c.Assert(third.Operation, Equals, "<")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithLast(c *C) {
-// 	q, err := ParseQuery("select value from t last 10;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.Limit, Equals, -10)
+func (self *QueryParserSuite) TestParseSelectWithLast(c *C) {
+	q, err := ParseQuery("select value from t last 10;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.Limit, Equals, -10)
 
-// 	q, err = ParseQuery("select value from t first 10;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.Limit, Equals, 10)
-// }
+	q, err = ParseQuery("select value from t first 10;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.Limit, Equals, 10)
+}
 
-// func (self *QueryParserSuite) TestParseFromWithNestedFunctions2(c *C) {
-// 	q, err := ParseQuery("select count(distinct(email)) from user.events where time>now()-1d group_by time(15m);")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetColumnNames(), HasLen, 1)
-// 	column := q.GetColumnNames()[0]
-// 	c.Assert(column.IsFunctionCall(), Equals, true)
-// 	c.Assert(column.Name, Equals, "count")
-// 	c.Assert(column.Elems, HasLen, 1)
-// 	c.Assert(column.Elems[0].IsFunctionCall(), Equals, true)
-// 	c.Assert(column.Elems[0].Name, Equals, "distinct")
-// 	c.Assert(column.Elems[0].Elems, HasLen, 1)
-// 	c.Assert(column.Elems[0].Elems[0].Name, Equals, "email")
+func (self *QueryParserSuite) TestParseFromWithNestedFunctions2(c *C) {
+	q, err := ParseQuery("select count(distinct(email)) from user.events where time>now()-1d group_by time(15m);")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetColumnNames(), HasLen, 1)
+	column := q.GetColumnNames()[0]
+	c.Assert(column.IsFunctionCall(), Equals, true)
+	c.Assert(column.Name, Equals, "count")
+	c.Assert(column.Elems, HasLen, 1)
+	c.Assert(column.Elems[0].IsFunctionCall(), Equals, true)
+	c.Assert(column.Elems[0].Name, Equals, "distinct")
+	c.Assert(column.Elems[0].Elems, HasLen, 1)
+	c.Assert(column.Elems[0].Elems[0].Name, Equals, "email")
 
-// 	c.Assert(q.GetGroupByClause(), HasLen, 1)
-// 	c.Assert(q.GetGroupByClause()[0], DeepEquals, &Value{
-// 		Name:  "time",
-// 		Elems: []*Value{&Value{"15m", nil}},
-// 	})
-// }
+	c.Assert(q.GetGroupByClause(), HasLen, 1)
+	c.Assert(q.GetGroupByClause()[0], DeepEquals, &Value{
+		Name:  "time",
+		Elems: []*Value{&Value{"15m", nil}},
+	})
+}
 
-// func (self *QueryParserSuite) TestParseFromWithMergedTable(c *C) {
-// 	q, err := ParseQuery("select count(*) from merge(newsletter.signups,user.signups) where time>now()-1d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetFromClause().IsFunctionCall(), Equals, true)
-// 	c.Assert(q.GetFromClause().Name, Equals, "merge")
-// 	c.Assert(q.GetFromClause().Elems, HasLen, 2)
-// 	c.Assert(q.GetFromClause().Elems[0].Name, Equals, "newsletter.signups")
-// 	c.Assert(q.GetFromClause().Elems[1].Name, Equals, "user.signups")
-// }
+func (self *QueryParserSuite) TestParseFromWithMergedTable(c *C) {
+	q, err := ParseQuery("select count(*) from merge(newsletter.signups,user.signups) where time>now()-1d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetFromClause().IsFunctionCall(), Equals, true)
+	c.Assert(q.GetFromClause().Name, Equals, "merge")
+	c.Assert(q.GetFromClause().Elems, HasLen, 2)
+	c.Assert(q.GetFromClause().Elems[0].Name, Equals, "newsletter.signups")
+	c.Assert(q.GetFromClause().Elems[1].Name, Equals, "user.signups")
+}
 
-// func (self *QueryParserSuite) TestParseFromWithJoinedTable(c *C) {
-// 	q, err := ParseQuery("select max(t1.value, t2.value) from inner_join(newsletter.signups, t1, user.signups, t2) where time>now()-1d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	c.Assert(q.GetFromClause().IsFunctionCall(), Equals, true)
-// 	c.Assert(q.GetFromClause().Name, Equals, "inner_join")
-// 	c.Assert(q.GetFromClause().Elems, HasLen, 4)
-// 	c.Assert(q.GetFromClause().Elems[0].Name, Equals, "newsletter.signups")
-// 	c.Assert(q.GetFromClause().Elems[1].Name, Equals, "t1")
-// 	c.Assert(q.GetFromClause().Elems[2].Name, Equals, "user.signups")
-// 	c.Assert(q.GetFromClause().Elems[3].Name, Equals, "t2")
-// }
+func (self *QueryParserSuite) TestParseFromWithJoinedTable(c *C) {
+	q, err := ParseQuery("select max(t1.value, t2.value) from inner_join(newsletter.signups, t1, user.signups, t2) where time>now()-1d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	c.Assert(q.GetFromClause().IsFunctionCall(), Equals, true)
+	c.Assert(q.GetFromClause().Name, Equals, "inner_join")
+	c.Assert(q.GetFromClause().Elems, HasLen, 4)
+	c.Assert(q.GetFromClause().Elems[0].Name, Equals, "newsletter.signups")
+	c.Assert(q.GetFromClause().Elems[1].Name, Equals, "t1")
+	c.Assert(q.GetFromClause().Elems[2].Name, Equals, "user.signups")
+	c.Assert(q.GetFromClause().Elems[3].Name, Equals, "t2")
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithRegexCondition(c *C) {
-// 	q, err := ParseQuery("select email from users.events where email ~= /gmail\\.com/i and time>now()-2d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
-// 	w := q.GetWhereCondition()
+func (self *QueryParserSuite) TestParseSelectWithRegexCondition(c *C) {
+	q, err := ParseQuery("select email from users.events where email ~= /gmail\\.com/i and time>now()-2d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
+	w := q.GetWhereCondition()
 
-// 	regexExpression := w.Left.(*WhereCondition).Left.(*BoolExpression)
-// 	c.Assert(regexExpression.Left.Left, DeepEquals, &Value{"email", nil})
-// 	c.Assert(regexExpression.Operation, Equals, "~=")
-// 	c.Assert(regexExpression.Right.Left, DeepEquals, &Value{"/gmail\\.com/i", nil})
-// }
+	regexExpression := w.Left.(*WhereCondition).Left.(*BoolExpression)
+	c.Assert(regexExpression.Left.Left, DeepEquals, &Value{"email", nil})
+	c.Assert(regexExpression.Operation, Equals, "~=")
+	c.Assert(regexExpression.Right.Left, DeepEquals, &Value{"/gmail\\.com/i", nil})
+}
 
-// func (self *QueryParserSuite) TestParseSelectWithRegexTables(c *C) {
-// 	q, err := ParseQuery("select email from users.* where time>now()-2d;")
-// 	defer q.Close()
-// 	c.Assert(err, IsNil)
+func (self *QueryParserSuite) TestParseSelectWithRegexTables(c *C) {
+	q, err := ParseQuery("select email from users.* where time>now()-2d;")
+	defer q.Close()
+	c.Assert(err, IsNil)
 
-// 	c.Assert(q.GetFromClause().Name, Equals, "users.*")
-// }
+	c.Assert(q.GetFromClause().Name, Equals, "users.*")
+}
 
 func (self *QueryParserSuite) TestParseSelectWithComplexArithmeticOperations(c *C) {
 	q, err := ParseQuery("select value from cpu.idle where 30 < value * 1 / 3 ;")
@@ -366,19 +365,23 @@ func (self *QueryParserSuite) TestParseSelectWithComplexArithmeticOperations(c *
 
 
 	// value * 1 / 3
-	rightExpression := boolExpression.Right.Right
+	rightExpression := boolExpression.Right
 
 	// value * 1
 	left, ok := rightExpression.GetLeftExpression()
 	c.Assert(ok, Equals, true)
-	fmt.Printf("left: %#v\n", left.Left)
-	c.Assert(left.Operation, Equals, "*")
+	c.Assert(left.Operation, Equals, byte('*'))
 	_value, _ := left.GetLeftExpression()
 	value, _ := _value.GetLeftValue()
 	c.Assert(value.Name, Equals, "value")
 	one, _ := left.Right.GetLeftValue()
 	c.Assert(one.Name, Equals, "1")
-	// right = '3'
+
+	// '3'
+	c.Assert(rightExpression.Operation, Equals, byte('/'))
+	value, ok = rightExpression.Right.GetLeftValue()
+	c.Assert(ok, Equals, true)
+	c.Assert(value.Name, Equals, "3")
 }
 
 // TODO:
diff --git a/src/query/query.yacc b/src/query/query.yacc
index ab87824dab..87ca9235ca 100644
--- a/src/query/query.yacc
+++ b/src/query/query.yacc
@@ -48,7 +48,6 @@
 %type <condition>       WHERE_CLAUSE
 %type <value_array>     COLUMN_NAMES
 %type <string>          BOOL_OPERATION
-%type <character>       ARITHMETIC_OPERATION
 %type <condition>       CONDITION
 %type <bool_expression> BOOL_EXPRESSION
 %type <value_array>     VALUES
@@ -213,7 +212,34 @@ EXPRESSION:
           $$ = $2;
         }
         |
-        EXPRESSION ARITHMETIC_OPERATION EXPRESSION
+        EXPRESSION '+' EXPRESSION
+        {
+          $$ = malloc(sizeof(expression));
+          printf("operation: %c\n", $2);
+          $$->left = $1;
+          $$->op = $2;
+          $$->right = $3;
+        }
+        |
+        EXPRESSION '-' EXPRESSION
+        {
+          $$ = malloc(sizeof(expression));
+          printf("operation: %c\n", $2);
+          $$->left = $1;
+          $$->op = $2;
+          $$->right = $3;
+        }
+        |
+        EXPRESSION '*' EXPRESSION
+        {
+          $$ = malloc(sizeof(expression));
+          printf("operation: %c\n", $2);
+          $$->left = $1;
+          $$->op = $2;
+          $$->right = $3;
+        }
+        |
+        EXPRESSION '/' EXPRESSION
         {
           $$ = malloc(sizeof(expression));
           printf("operation: %c\n", $2);
@@ -222,14 +248,6 @@ EXPRESSION:
           $$->right = $3;
         }
 
-ARITHMETIC_OPERATION:
-        '+'
-        |
-        '-'
-        |
-        '*'
-        |
-        '/'
 
 BOOL_EXPRESSION:
         EXPRESSION
diff --git a/src/query/y.tab.c b/src/query/y.tab.c
index e445f84d75..1040106585 100644
--- a/src/query/y.tab.c
+++ b/src/query/y.tab.c
@@ -399,16 +399,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   91
+#define YYLAST   96
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  31
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  15
+#define YYNNTS  14
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  41
+#define YYNRULES  40
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  67
+#define YYNSTATES  69
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
@@ -456,11 +456,11 @@ static const yytype_uint8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    74,    74,    83,    93,    99,   105,   110,   118,   128,
-     133,   137,   139,   145,   150,   155,   164,   172,   179,   186,
-     194,   201,   204,   212,   217,   227,   229,   231,   233,   236,
-     244,   252,   267,   276,   281,   290,   300,   302,   304,   306,
-     308,   310
+       0,    73,    73,    82,    92,    98,   104,   109,   117,   127,
+     132,   136,   138,   144,   149,   154,   163,   171,   178,   185,
+     192,   199,   202,   210,   215,   224,   233,   242,   253,   261,
+     269,   284,   293,   298,   307,   317,   319,   321,   323,   325,
+     327
 };
 #endif
 
@@ -476,7 +476,7 @@ static const char *const yytname[] =
   "OPERATION_GE", "'+'", "'-'", "'*'", "'/'", "';'", "','", "'('", "')'",
   "$accept", "QUERY", "LIMIT", "VALUES", "GROUP_BY_CLAUSE", "COLUMN_NAMES",
   "FROM_CLAUSE", "WHERE_CLAUSE", "FUNCTION_CALL", "VALUE", "EXPRESSION",
-  "ARITHMETIC_OPERATION", "BOOL_EXPRESSION", "CONDITION", "BOOL_OPERATION", YY_NULL
+  "BOOL_EXPRESSION", "CONDITION", "BOOL_OPERATION", YY_NULL
 };
 #endif
 
@@ -506,13 +506,13 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.  */
 static const yytype_int8 yypact[] =
 {
-      30,    29,    17,   -26,   -26,    18,   -26,    21,    46,   -26,
-     -26,   -26,    -7,    29,    29,     5,   -26,   -14,   -26,   -26,
-      19,    29,    48,    60,   -26,    19,   -26,    53,   -26,    27,
-      21,    37,    37,    39,     4,    54,   -26,   -26,   -26,   -26,
-     -26,   -26,   -26,   -26,   -26,   -26,    26,    26,    19,    19,
-      73,    74,    59,    61,   -26,   -26,   -26,    26,    57,    57,
-      71,   -26,   -26,   -26,   -26,   -26,   -17
+      -1,    46,    28,   -26,   -26,    38,   -26,    41,    66,   -26,
+     -26,   -26,    -3,    46,    46,    61,   -26,    58,   -26,   -26,
+       1,    46,    68,    67,   -26,     1,   -26,    59,   -26,    19,
+      41,    31,    31,    29,    45,    73,   -26,   -26,   -26,   -26,
+     -26,   -26,     4,     4,     4,     4,     4,     1,     1,    78,
+      79,    64,    65,   -26,   -26,   -26,     4,    18,    18,   -26,
+     -26,    39,    77,   -26,   -26,   -26,   -26,   -26,   -20
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -522,25 +522,25 @@ static const yytype_uint8 yydefact[] =
 {
        0,     0,     0,    17,    18,    20,    19,    11,     0,    21,
        7,     1,     0,     0,     0,    10,    15,     0,     8,    12,
-       0,     0,    14,    10,    16,     0,    22,    29,    32,    13,
-       9,     6,     6,    29,     0,     0,    36,    37,    38,    39,
-      41,    40,    25,    26,    27,    28,     0,     0,     0,     0,
-       0,     0,     0,     0,    23,    33,    31,     0,    24,    30,
-      35,    34,     4,     5,     2,     3,     0
+       0,     0,    14,    10,    16,     0,    22,    28,    31,    13,
+       9,     6,     6,    28,     0,     0,    35,    36,    37,    38,
+      40,    39,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    23,    32,    30,     0,    24,    25,    26,
+      27,    29,    34,    33,     4,     5,     2,     3,     0
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -26,   -26,    58,   -10,    66,   -26,   -26,    69,   -26,    14,
-     -25,   -26,   -26,   -24,   -26
+     -26,   -26,    62,    20,    72,   -26,   -26,    74,   -26,    24,
+     -25,   -26,   -24,   -26
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     2,    52,     7,    22,     8,    15,    23,     9,    26,
-      27,    46,    28,    29,    47
+      -1,     2,    51,     7,    22,     8,    15,    23,     9,    26,
+      27,    28,    29,    46
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -548,30 +548,30 @@ static const yytype_int8 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      33,    34,    17,     3,     4,     5,    42,    43,    44,    45,
-      20,    30,    21,    54,    13,    10,    24,    11,     6,    48,
-      49,    58,    59,    16,    60,    61,    10,    18,    19,     3,
-       4,     5,    66,     1,    55,    10,     3,     4,     5,     3,
-       4,     5,    48,    49,     6,    50,    51,    12,    25,    13,
-      14,     6,    35,    20,     6,    57,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    35,    21,    56,    54,
-      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
-      42,    43,    44,    45,    62,    63,    64,    49,    65,    32,
-      53,    31
+      33,    34,     1,    42,    43,    44,    45,     3,     4,     5,
+      53,     3,     4,     5,     3,     4,     5,    57,    58,    59,
+      60,    61,     6,    62,    63,    10,     6,    16,    11,     6,
+      25,    68,    17,    56,    47,    48,    10,    18,    19,    49,
+      50,    30,    35,    44,    45,    10,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,     3,     4,     5,    53,
+      47,    48,    42,    43,    44,    45,    20,    12,    21,    13,
+      14,     6,    35,    20,    21,    54,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    13,    55,    24,    64,
+      65,    66,    67,    48,    52,    32,    31
 };
 
 static const yytype_uint8 yycheck[] =
 {
-      25,    25,    12,    10,    11,    12,    23,    24,    25,    26,
-       5,    21,     7,    30,    28,     1,    30,     0,    25,    15,
-      16,    46,    47,    30,    48,    49,    12,    13,    14,    10,
-      11,    12,    57,     3,    30,    21,    10,    11,    12,    10,
-      11,    12,    15,    16,    25,     8,     9,    29,    29,    28,
-       4,    25,    13,     5,    25,    29,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    13,     7,    14,    30,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      23,    24,    25,    26,    11,    11,    27,    16,    27,    23,
-      32,    22
+      25,    25,     3,    23,    24,    25,    26,    10,    11,    12,
+      30,    10,    11,    12,    10,    11,    12,    42,    43,    44,
+      45,    46,    25,    47,    48,     1,    25,    30,     0,    25,
+      29,    56,    12,    29,    15,    16,    12,    13,    14,     8,
+       9,    21,    13,    25,    26,    21,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    10,    11,    12,    30,
+      15,    16,    23,    24,    25,    26,     5,    29,     7,    28,
+       4,    25,    13,     5,     7,    30,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    28,    14,    30,    11,
+      11,    27,    27,    16,    32,    23,    22
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -580,11 +580,11 @@ static const yytype_uint8 yystos[] =
 {
        0,     3,    32,    10,    11,    12,    25,    34,    36,    39,
       40,     0,    29,    28,     4,    37,    30,    34,    40,    40,
-       5,     7,    35,    38,    30,    29,    40,    41,    43,    44,
-      34,    38,    35,    41,    44,    13,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    42,    45,    15,    16,
-       8,     9,    33,    33,    30,    30,    14,    29,    41,    41,
-      44,    44,    11,    11,    27,    27,    41
+       5,     7,    35,    38,    30,    29,    40,    41,    42,    43,
+      34,    38,    35,    41,    43,    13,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    44,    15,    16,     8,
+       9,    33,    33,    30,    30,    14,    29,    41,    41,    41,
+      41,    41,    43,    43,    11,    11,    27,    27,    41
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
@@ -592,9 +592,9 @@ static const yytype_uint8 yyr1[] =
 {
        0,    31,    32,    32,    33,    33,    33,    34,    34,    35,
       35,    36,    37,    38,    38,    39,    39,    40,    40,    40,
-      40,    40,    41,    41,    41,    42,    42,    42,    42,    43,
-      43,    43,    44,    44,    44,    44,    45,    45,    45,    45,
-      45,    45
+      40,    40,    41,    41,    41,    41,    41,    41,    42,    42,
+      42,    43,    43,    43,    43,    44,    44,    44,    44,    44,
+      44
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
@@ -602,9 +602,9 @@ static const yytype_uint8 yyr2[] =
 {
        0,     2,     7,     7,     2,     2,     0,     1,     3,     2,
        0,     1,     2,     2,     0,     3,     4,     1,     1,     1,
-       1,     1,     1,     3,     3,     1,     1,     1,     1,     1,
-       3,     3,     1,     3,     3,     3,     1,     1,     1,     1,
-       1,     1
+       1,     1,     1,     3,     3,     3,     3,     3,     1,     3,
+       3,     1,     3,     3,     3,     1,     1,     1,     1,     1,
+       1
 };
 
 
@@ -1101,127 +1101,127 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio
   switch (yytype)
     {
           case 10: /* STRING_VALUE  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1107 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 11: /* INT_VALUE  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1113 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 12: /* NAME  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1119 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 13: /* REGEX_OP  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1125 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 14: /* REGEX_STRING  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1131 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 17: /* OPERATION_EQUAL  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1137 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 18: /* OPERATION_NE  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1143 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 19: /* OPERATION_GT  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1149 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 20: /* OPERATION_LT  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1155 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 21: /* OPERATION_LE  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1161 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 22: /* OPERATION_GE  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1167 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 34: /* VALUES  */
-#line 69 "query.yacc" /* yacc.c:1257  */
+#line 68 "query.yacc" /* yacc.c:1257  */
       { if (((*yyvaluep).value_array)) free_value_array(((*yyvaluep).value_array)); }
 #line 1173 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 35: /* GROUP_BY_CLAUSE  */
-#line 69 "query.yacc" /* yacc.c:1257  */
+#line 68 "query.yacc" /* yacc.c:1257  */
       { if (((*yyvaluep).value_array)) free_value_array(((*yyvaluep).value_array)); }
 #line 1179 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 36: /* COLUMN_NAMES  */
-#line 69 "query.yacc" /* yacc.c:1257  */
+#line 68 "query.yacc" /* yacc.c:1257  */
       { if (((*yyvaluep).value_array)) free_value_array(((*yyvaluep).value_array)); }
 #line 1185 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 37: /* FROM_CLAUSE  */
-#line 65 "query.yacc" /* yacc.c:1257  */
+#line 64 "query.yacc" /* yacc.c:1257  */
       { free_value(((*yyvaluep).v)); }
 #line 1191 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 38: /* WHERE_CLAUSE  */
-#line 66 "query.yacc" /* yacc.c:1257  */
+#line 65 "query.yacc" /* yacc.c:1257  */
       { if (((*yyvaluep).condition)) free_condition(((*yyvaluep).condition)); }
 #line 1197 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 39: /* FUNCTION_CALL  */
-#line 65 "query.yacc" /* yacc.c:1257  */
+#line 64 "query.yacc" /* yacc.c:1257  */
       { free_value(((*yyvaluep).v)); }
 #line 1203 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 40: /* VALUE  */
-#line 65 "query.yacc" /* yacc.c:1257  */
+#line 64 "query.yacc" /* yacc.c:1257  */
       { free_value(((*yyvaluep).v)); }
 #line 1209 "y.tab.c" /* yacc.c:1257  */
         break;
 
     case 41: /* EXPRESSION  */
-#line 68 "query.yacc" /* yacc.c:1257  */
+#line 67 "query.yacc" /* yacc.c:1257  */
       { free_expression(((*yyvaluep).expression)); }
 #line 1215 "y.tab.c" /* yacc.c:1257  */
         break;
 
-    case 44: /* CONDITION  */
-#line 66 "query.yacc" /* yacc.c:1257  */
+    case 43: /* CONDITION  */
+#line 65 "query.yacc" /* yacc.c:1257  */
       { if (((*yyvaluep).condition)) free_condition(((*yyvaluep).condition)); }
 #line 1221 "y.tab.c" /* yacc.c:1257  */
         break;
 
-    case 45: /* BOOL_OPERATION  */
-#line 67 "query.yacc" /* yacc.c:1257  */
+    case 44: /* BOOL_OPERATION  */
+#line 66 "query.yacc" /* yacc.c:1257  */
       { free(((*yyvaluep).string)); }
 #line 1227 "y.tab.c" /* yacc.c:1257  */
         break;
@@ -1515,7 +1515,7 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 75 "query.yacc" /* yacc.c:1661  */
+#line 74 "query.yacc" /* yacc.c:1661  */
     {
           q->c = (yyvsp[-5].value_array);
           q->f = (yyvsp[-4].v);
@@ -1527,7 +1527,7 @@ yyreduce:
     break;
 
   case 3:
-#line 84 "query.yacc" /* yacc.c:1661  */
+#line 83 "query.yacc" /* yacc.c:1661  */
     {
           q->c = (yyvsp[-5].value_array);
           q->f = (yyvsp[-4].v);
@@ -1539,7 +1539,7 @@ yyreduce:
     break;
 
   case 4:
-#line 94 "query.yacc" /* yacc.c:1661  */
+#line 93 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.integer) = atoi((yyvsp[0].string));
           free((yyvsp[0].string));
@@ -1548,7 +1548,7 @@ yyreduce:
     break;
 
   case 5:
-#line 100 "query.yacc" /* yacc.c:1661  */
+#line 99 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.integer) = -atoi((yyvsp[0].string));
           free((yyvsp[0].string));
@@ -1557,7 +1557,7 @@ yyreduce:
     break;
 
   case 6:
-#line 105 "query.yacc" /* yacc.c:1661  */
+#line 104 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.integer) = 0;
         }
@@ -1565,7 +1565,7 @@ yyreduce:
     break;
 
   case 7:
-#line 111 "query.yacc" /* yacc.c:1661  */
+#line 110 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.value_array) = malloc(sizeof(value_array));
           (yyval.value_array)->size = 1;
@@ -1576,7 +1576,7 @@ yyreduce:
     break;
 
   case 8:
-#line 119 "query.yacc" /* yacc.c:1661  */
+#line 118 "query.yacc" /* yacc.c:1661  */
     {
           size_t new_size = (yyvsp[-2].value_array)->size + 1;
           (yyvsp[-2].value_array)->elems = realloc((yyval.value_array)->elems, sizeof(value*) * new_size);
@@ -1588,7 +1588,7 @@ yyreduce:
     break;
 
   case 9:
-#line 129 "query.yacc" /* yacc.c:1661  */
+#line 128 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.value_array) = (yyvsp[0].value_array);
         }
@@ -1596,7 +1596,7 @@ yyreduce:
     break;
 
   case 10:
-#line 133 "query.yacc" /* yacc.c:1661  */
+#line 132 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.value_array) = NULL;
         }
@@ -1604,7 +1604,7 @@ yyreduce:
     break;
 
   case 12:
-#line 140 "query.yacc" /* yacc.c:1661  */
+#line 139 "query.yacc" /* yacc.c:1661  */
     {
   (yyval.v) = (yyvsp[0].v);
 }
@@ -1612,7 +1612,7 @@ yyreduce:
     break;
 
   case 13:
-#line 146 "query.yacc" /* yacc.c:1661  */
+#line 145 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = (yyvsp[0].condition);
         }
@@ -1620,7 +1620,7 @@ yyreduce:
     break;
 
   case 14:
-#line 150 "query.yacc" /* yacc.c:1661  */
+#line 149 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = NULL;
         }
@@ -1628,7 +1628,7 @@ yyreduce:
     break;
 
   case 15:
-#line 156 "query.yacc" /* yacc.c:1661  */
+#line 155 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = (yyvsp[-2].string);
@@ -1640,7 +1640,7 @@ yyreduce:
     break;
 
   case 16:
-#line 165 "query.yacc" /* yacc.c:1661  */
+#line 164 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = (yyvsp[-3].string);
@@ -1650,7 +1650,7 @@ yyreduce:
     break;
 
   case 17:
-#line 173 "query.yacc" /* yacc.c:1661  */
+#line 172 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = (yyvsp[0].string);
@@ -1660,7 +1660,7 @@ yyreduce:
     break;
 
   case 18:
-#line 180 "query.yacc" /* yacc.c:1661  */
+#line 179 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = (yyvsp[0].string);
@@ -1670,47 +1670,46 @@ yyreduce:
     break;
 
   case 19:
-#line 187 "query.yacc" /* yacc.c:1661  */
+#line 186 "query.yacc" /* yacc.c:1661  */
     {
-          printf("****************");
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = strdup("*");
           (yyval.v)->args = NULL;
         }
-#line 1681 "y.tab.c" /* yacc.c:1661  */
+#line 1680 "y.tab.c" /* yacc.c:1661  */
     break;
 
   case 20:
-#line 195 "query.yacc" /* yacc.c:1661  */
+#line 193 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.v) = malloc(sizeof(value));
           (yyval.v)->name = (yyvsp[0].string);
           (yyval.v)->args = NULL;
         }
-#line 1691 "y.tab.c" /* yacc.c:1661  */
+#line 1690 "y.tab.c" /* yacc.c:1661  */
     break;
 
   case 22:
-#line 205 "query.yacc" /* yacc.c:1661  */
+#line 203 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.expression) = malloc(sizeof(expression));
           (yyval.expression)->left = (yyvsp[0].v);
           (yyval.expression)->op = '\0';
           (yyval.expression)->right = NULL;
         }
-#line 1702 "y.tab.c" /* yacc.c:1661  */
+#line 1701 "y.tab.c" /* yacc.c:1661  */
     break;
 
   case 23:
-#line 213 "query.yacc" /* yacc.c:1661  */
+#line 211 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.expression) = (yyvsp[-1].expression);
         }
-#line 1710 "y.tab.c" /* yacc.c:1661  */
+#line 1709 "y.tab.c" /* yacc.c:1661  */
     break;
 
   case 24:
-#line 218 "query.yacc" /* yacc.c:1661  */
+#line 216 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.expression) = malloc(sizeof(expression));
           printf("operation: %c\n", (yyvsp[-1].character));
@@ -1718,33 +1717,69 @@ yyreduce:
           (yyval.expression)->op = (yyvsp[-1].character);
           (yyval.expression)->right = (yyvsp[0].expression);
         }
-#line 1722 "y.tab.c" /* yacc.c:1661  */
+#line 1721 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 29:
-#line 237 "query.yacc" /* yacc.c:1661  */
+  case 25:
+#line 225 "query.yacc" /* yacc.c:1661  */
+    {
+          (yyval.expression) = malloc(sizeof(expression));
+          printf("operation: %c\n", (yyvsp[-1].character));
+          (yyval.expression)->left = (yyvsp[-2].expression);
+          (yyval.expression)->op = (yyvsp[-1].character);
+          (yyval.expression)->right = (yyvsp[0].expression);
+        }
+#line 1733 "y.tab.c" /* yacc.c:1661  */
+    break;
+
+  case 26:
+#line 234 "query.yacc" /* yacc.c:1661  */
+    {
+          (yyval.expression) = malloc(sizeof(expression));
+          printf("operation: %c\n", (yyvsp[-1].character));
+          (yyval.expression)->left = (yyvsp[-2].expression);
+          (yyval.expression)->op = (yyvsp[-1].character);
+          (yyval.expression)->right = (yyvsp[0].expression);
+        }
+#line 1745 "y.tab.c" /* yacc.c:1661  */
+    break;
+
+  case 27:
+#line 243 "query.yacc" /* yacc.c:1661  */
+    {
+          (yyval.expression) = malloc(sizeof(expression));
+          printf("operation: %c\n", (yyvsp[-1].character));
+          (yyval.expression)->left = (yyvsp[-2].expression);
+          (yyval.expression)->op = (yyvsp[-1].character);
+          (yyval.expression)->right = (yyvsp[0].expression);
+        }
+#line 1757 "y.tab.c" /* yacc.c:1661  */
+    break;
+
+  case 28:
+#line 254 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.bool_expression) = malloc(sizeof(bool_expression));
           (yyval.bool_expression)->left = (yyvsp[0].expression);
           (yyval.bool_expression)->op = NULL;
           (yyval.bool_expression)->right = NULL;
         }
-#line 1733 "y.tab.c" /* yacc.c:1661  */
+#line 1768 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 30:
-#line 245 "query.yacc" /* yacc.c:1661  */
+  case 29:
+#line 262 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.bool_expression) = malloc(sizeof(bool_expression));
           (yyval.bool_expression)->left = (yyvsp[-2].expression);
           (yyval.bool_expression)->op = (yyvsp[-1].string);
           (yyval.bool_expression)->right = (yyvsp[0].expression);
         }
-#line 1744 "y.tab.c" /* yacc.c:1661  */
+#line 1779 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 31:
-#line 253 "query.yacc" /* yacc.c:1661  */
+  case 30:
+#line 270 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.bool_expression) = malloc(sizeof(bool_expression));
           (yyval.bool_expression)->left = (yyvsp[-2].expression);
@@ -1757,11 +1792,11 @@ yyreduce:
           (yyval.bool_expression)->right->op = '\0';
           (yyval.bool_expression)->right->right = NULL;
         }
-#line 1761 "y.tab.c" /* yacc.c:1661  */
+#line 1796 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 32:
-#line 268 "query.yacc" /* yacc.c:1661  */
+  case 31:
+#line 285 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = malloc(sizeof(condition));
           (yyval.condition)->is_bool_expression = TRUE;
@@ -1769,19 +1804,19 @@ yyreduce:
           (yyval.condition)->op = NULL;
           (yyval.condition)->right = NULL;
         }
-#line 1773 "y.tab.c" /* yacc.c:1661  */
+#line 1808 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 33:
-#line 277 "query.yacc" /* yacc.c:1661  */
+  case 32:
+#line 294 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = (yyvsp[-1].condition);
         }
-#line 1781 "y.tab.c" /* yacc.c:1661  */
+#line 1816 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 34:
-#line 282 "query.yacc" /* yacc.c:1661  */
+  case 33:
+#line 299 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = malloc(sizeof(condition));
           (yyval.condition)->is_bool_expression = FALSE;
@@ -1789,11 +1824,11 @@ yyreduce:
           (yyval.condition)->op = "AND";
           (yyval.condition)->right = (yyvsp[0].condition);
         }
-#line 1793 "y.tab.c" /* yacc.c:1661  */
+#line 1828 "y.tab.c" /* yacc.c:1661  */
     break;
 
-  case 35:
-#line 291 "query.yacc" /* yacc.c:1661  */
+  case 34:
+#line 308 "query.yacc" /* yacc.c:1661  */
     {
           (yyval.condition) = malloc(sizeof(condition));
           (yyval.condition)->is_bool_expression = FALSE;
@@ -1801,11 +1836,11 @@ yyreduce:
           (yyval.condition)->op = "OR";
           (yyval.condition)->right = (yyvsp[0].condition);
         }
-#line 1805 "y.tab.c" /* yacc.c:1661  */
+#line 1840 "y.tab.c" /* yacc.c:1661  */
     break;
 
 
-#line 1809 "y.tab.c" /* yacc.c:1661  */
+#line 1844 "y.tab.c" /* yacc.c:1661  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2040,7 +2075,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 312 "query.yacc" /* yacc.c:1906  */
+#line 329 "query.yacc" /* yacc.c:1906  */
 
 void *yy_scan_string(char *, void *);
 void yy_delete_buffer(void *, void *);