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
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
}

View File

@ -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) {

View File

@ -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; }

View File

@ -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> 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 <v> FUNCTION_CALL
%type <expression> EXPRESSION
%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
%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);
}
|

View File

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