fix #1. Queries support an order clause and limit clause.

pull/17/head
John Shahid 2013-10-11 13:45:40 -04:00
parent 647d09cbd6
commit 9416b22ff5
5 changed files with 65 additions and 20 deletions

View File

@ -88,6 +88,7 @@ type Query struct {
Condition *WhereCondition Condition *WhereCondition
groupByClause GroupByClause groupByClause GroupByClause
Limit int Limit int
Ascending bool
} }
func (self *Query) GetColumnNames() []*Value { func (self *Query) GetColumnNames() []*Value {
@ -250,5 +251,5 @@ func ParseQuery(query string) (*Query, error) {
C.close_query(&q) C.close_query(&q)
return nil, err 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
} }

View File

@ -274,16 +274,25 @@ func (self *QueryParserSuite) TestParseWhereClauseParantheses(c *C) {
c.Assert(third.Operation, Equals, "<") c.Assert(third.Operation, Equals, "<")
} }
func (self *QueryParserSuite) TestParseSelectWithLast(c *C) { func (self *QueryParserSuite) TestParseSelectWithOrderByAndLimit(c *C) {
q, err := ParseQuery("select value from t last 10;") q, err := ParseQuery("select value from t order asc limit 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() defer q.Close()
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(q.Limit, Equals, 10) 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) { func (self *QueryParserSuite) TestParseFromWithNestedFunctions2(c *C) {

View File

@ -27,6 +27,10 @@ last { return LAST; }
from { return FROM; } from { return FROM; }
where { return WHERE; } where { return WHERE; }
select { return SELECT; } select { return SELECT; }
limit { return LIMIT; }
order { return ORDER; }
asc { return ASC; }
desc { return DESC; }
group { return GROUP; } group { return GROUP; }
by { return BY; } by { return BY; }
"(" { yylval->character = *yytext; return *yytext; } "(" { yylval->character = *yytext; return *yytext; }

View File

@ -25,6 +25,10 @@ expression *create_expression(expression *left, char op, expression *right) {
expression* expression; expression* expression;
value_array* value_array; value_array* value_array;
value* v; value* v;
struct {
int limit;
char ascending;
} limit_and_order;
} }
// debugging // debugging
@ -41,7 +45,7 @@ expression *create_expression(expression *left, char op, expression *right) {
%lex-param {void *scanner} %lex-param {void *scanner}
// define types of tokens (terminals) // 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> STRING_VALUE INT_VALUE NAME REGEX_OP REGEX_STRING %token <string> STRING_VALUE INT_VALUE NAME REGEX_OP REGEX_STRING
// define the precendence of these operators // define the precendence of these operators
@ -63,7 +67,9 @@ expression *create_expression(expression *left, char op, expression *right) {
%type <v> FUNCTION_CALL %type <v> FUNCTION_CALL
%type <expression> EXPRESSION %type <expression> EXPRESSION
%type <value_array> GROUP_BY_CLAUSE %type <value_array> GROUP_BY_CLAUSE
%type <integer> LIMIT %type <integer> LIMIT_CLAUSE
%type <character> ORDER_CLAUSE
%type <limit_and_order> LIMIT_AND_ORDER_CLAUSES
// the initial token // the initial token
%start QUERY %start QUERY
@ -78,34 +84,58 @@ expression *create_expression(expression *left, char op, expression *right) {
// grammar // grammar
%% %%
QUERY: 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->c = $2;
q->f = $3; q->f = $3;
q->group_by = $4; q->group_by = $4;
q->where_condition = $5; 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->c = $2;
q->f = $3; q->f = $3;
q->where_condition = $4; q->where_condition = $4;
q->group_by = $5; q->group_by = $5;
q->limit = $6; q->limit = $6.limit;
q->ascending = $6.ascending;
} }
LIMIT: LIMIT_AND_ORDER_CLAUSES:
FIRST INT_VALUE ORDER_CLAUSE LIMIT_CLAUSE
{ {
$$ = atoi($2); $$.limit = $2;
free($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); free($2);
} }
| |

View File

@ -52,6 +52,7 @@ typedef struct {
condition *where_condition; condition *where_condition;
error *error; error *error;
int limit; int limit;
char ascending;
} query; } query;
// some funcs for freeing our types // some funcs for freeing our types