fix #1. Queries support an order clause and limit clause.
parent
647d09cbd6
commit
9416b22ff5
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue