From 9416b22ff5b51f6dba33cd3ea09ffe104b132144 Mon Sep 17 00:00:00 2001 From: John Shahid Date: Fri, 11 Oct 2013 13:45:40 -0400 Subject: [PATCH] fix #1. Queries support an order clause and limit clause. --- src/parser/parser.go | 3 ++- src/parser/parser_test.go | 23 ++++++++++++----- src/parser/query.lex | 4 +++ src/parser/query.yacc | 54 ++++++++++++++++++++++++++++++--------- src/parser/query_types.h | 1 + 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/parser/parser.go b/src/parser/parser.go index 1ca79d6349..ffc0f2b41b 100644 --- a/src/parser/parser.go +++ b/src/parser/parser.go @@ -88,6 +88,7 @@ type Query struct { Condition *WhereCondition groupByClause GroupByClause Limit int + Ascending bool } func (self *Query) GetColumnNames() []*Value { @@ -250,5 +251,5 @@ func ParseQuery(query string) (*Query, error) { C.close_query(&q) return nil, err } - return &Query{q, false, nil, nil, nil, int(q.limit)}, err + return &Query{q, false, nil, nil, nil, int(q.limit), q.ascending != 0}, err } diff --git a/src/parser/parser_test.go b/src/parser/parser_test.go index b16f6762b5..829cbfff6f 100644 --- a/src/parser/parser_test.go +++ b/src/parser/parser_test.go @@ -274,16 +274,25 @@ func (self *QueryParserSuite) TestParseWhereClauseParantheses(c *C) { 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) - - q, err = ParseQuery("select value from t first 10;") +func (self *QueryParserSuite) TestParseSelectWithOrderByAndLimit(c *C) { + q, err := ParseQuery("select value from t order asc limit 10;") defer q.Close() c.Assert(err, IsNil) c.Assert(q.Limit, Equals, 10) + c.Assert(q.Ascending, Equals, true) + + q, err = ParseQuery("select value from t order desc;") + defer q.Close() + c.Assert(err, IsNil) + c.Assert(q.Limit, Equals, 0) + c.Assert(q.Ascending, Equals, false) + + q, err = ParseQuery("select value from t limit 20;") + defer q.Close() + c.Assert(err, IsNil) + c.Assert(q.Limit, Equals, 20) + // ascending is the default + c.Assert(q.Ascending, Equals, true) } func (self *QueryParserSuite) TestParseFromWithNestedFunctions2(c *C) { diff --git a/src/parser/query.lex b/src/parser/query.lex index 5e3684557f..b7ce8f3d71 100644 --- a/src/parser/query.lex +++ b/src/parser/query.lex @@ -27,6 +27,10 @@ last { return LAST; } from { return FROM; } where { return WHERE; } select { return SELECT; } +limit { return LIMIT; } +order { return ORDER; } +asc { return ASC; } +desc { return DESC; } group { return GROUP; } by { return BY; } "(" { yylval->character = *yytext; return *yytext; } diff --git a/src/parser/query.yacc b/src/parser/query.yacc index 539d208672..1010de2ed6 100644 --- a/src/parser/query.yacc +++ b/src/parser/query.yacc @@ -25,6 +25,10 @@ expression *create_expression(expression *left, char op, expression *right) { expression* expression; value_array* value_array; value* v; + struct { + int limit; + char ascending; + } limit_and_order; } // debugging @@ -41,7 +45,7 @@ expression *create_expression(expression *left, char op, expression *right) { %lex-param {void *scanner} // define types of tokens (terminals) -%token SELECT FROM WHERE EQUAL GROUP BY FIRST LAST +%token SELECT FROM WHERE EQUAL GROUP BY FIRST LAST LIMIT ORDER ASC DESC %token STRING_VALUE INT_VALUE NAME REGEX_OP REGEX_STRING // define the precendence of these operators @@ -63,7 +67,9 @@ expression *create_expression(expression *left, char op, expression *right) { %type FUNCTION_CALL %type EXPRESSION %type GROUP_BY_CLAUSE -%type LIMIT +%type LIMIT_CLAUSE +%type ORDER_CLAUSE +%type LIMIT_AND_ORDER_CLAUSES // the initial token %start QUERY @@ -78,34 +84,58 @@ expression *create_expression(expression *left, char op, expression *right) { // grammar %% QUERY: - SELECT COLUMN_NAMES FROM_CLAUSE GROUP_BY_CLAUSE WHERE_CLAUSE LIMIT ';' + SELECT COLUMN_NAMES FROM_CLAUSE GROUP_BY_CLAUSE WHERE_CLAUSE LIMIT_AND_ORDER_CLAUSES ';' { q->c = $2; q->f = $3; q->group_by = $4; q->where_condition = $5; - q->limit = $6; + q->limit = $6.limit; + q->ascending = $6.ascending; } | - SELECT COLUMN_NAMES FROM_CLAUSE WHERE_CLAUSE GROUP_BY_CLAUSE LIMIT ';' + SELECT COLUMN_NAMES FROM_CLAUSE WHERE_CLAUSE GROUP_BY_CLAUSE LIMIT_AND_ORDER_CLAUSES ';' { q->c = $2; q->f = $3; q->where_condition = $4; q->group_by = $5; - q->limit = $6; + q->limit = $6.limit; + q->ascending = $6.ascending; } -LIMIT: - FIRST INT_VALUE +LIMIT_AND_ORDER_CLAUSES: + ORDER_CLAUSE LIMIT_CLAUSE { - $$ = atoi($2); - free($2); + $$.limit = $2; + $$.ascending = $1; } | - LAST INT_VALUE + LIMIT_CLAUSE ORDER_CLAUSE { - $$ = -atoi($2); + $$.limit = $1; + $$.ascending = $2; + } + +ORDER_CLAUSE: + ORDER ASC + { + $$ = TRUE; + } + | + ORDER DESC + { + $$ = FALSE; + } + | + { + $$ = TRUE; + } + +LIMIT_CLAUSE: + LIMIT INT_VALUE + { + $$ = atoi($2); free($2); } | diff --git a/src/parser/query_types.h b/src/parser/query_types.h index ad79de85c1..45b04dc4f0 100644 --- a/src/parser/query_types.h +++ b/src/parser/query_types.h @@ -52,6 +52,7 @@ typedef struct { condition *where_condition; error *error; int limit; + char ascending; } query; // some funcs for freeing our types