fix #1. Queries support an order clause and limit clause.
parent
647d09cbd6
commit
9416b22ff5
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
||||
|
|
|
@ -52,6 +52,7 @@ typedef struct {
|
|||
condition *where_condition;
|
||||
error *error;
|
||||
int limit;
|
||||
char ascending;
|
||||
} query;
|
||||
|
||||
// some funcs for freeing our types
|
||||
|
|
Loading…
Reference in New Issue