Skip to content

Commit

Permalink
Fix parsing of multiple queries
Browse files Browse the repository at this point in the history
Fix #885
  • Loading branch information
jvshahid committed Sep 2, 2014
1 parent 083f7ea commit 5025809
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 78 deletions.
14 changes: 7 additions & 7 deletions integration/multiple_servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,29 +650,29 @@ func (self *ServerSuite) TestContinuousQueryManagement(c *C) {
series := collection.GetSeries("continuous queries", c)
c.Assert(series.Points, HasLen, 0)

response := self.serverProcesses[0].VerifyForbiddenQuery("test_cq", "select * from foo into bar;", false, c, "weakpaul", "pass")
response := self.serverProcesses[0].VerifyForbiddenQuery("test_cq", "select * from foo into bar", false, c, "weakpaul", "pass")
c.Assert(response, Equals, "Insufficient permissions to create continuous query")

self.serverProcesses[0].QueryAsRoot("test_cq", "select * from foo into bar;", false, c)
self.serverProcesses[0].QueryAsRoot("test_cq", "select * from foo into bar", false, c)
self.serverProcesses[0].WaitForServerToSync()

collection = self.serverProcesses[0].QueryAsRoot("test_cq", "list continuous queries;", false, c)
series = collection.GetSeries("continuous queries", c)
c.Assert(series.Points, HasLen, 1)
c.Assert(series.GetValueForPointAndColumn(0, "id", c), Equals, 1.0)
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from foo into bar;")
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from foo into bar")

// wait for the continuous query to run
time.Sleep(time.Second)

self.serverProcesses[0].QueryAsRoot("test_cq", "select * from quu into qux;", false, c)
self.serverProcesses[0].QueryAsRoot("test_cq", "select * from quu into qux", false, c)
collection = self.serverProcesses[0].QueryAsRoot("test_cq", "list continuous queries;", false, c)
series = collection.GetSeries("continuous queries", c)
c.Assert(series.Points, HasLen, 2)
c.Assert(series.GetValueForPointAndColumn(0, "id", c), Equals, 1.0)
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from foo into bar;")
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from foo into bar")
c.Assert(series.GetValueForPointAndColumn(1, "id", c), Equals, 2.0)
c.Assert(series.GetValueForPointAndColumn(1, "query", c), Equals, "select * from quu into qux;")
c.Assert(series.GetValueForPointAndColumn(1, "query", c), Equals, "select * from quu into qux")

self.serverProcesses[0].QueryAsRoot("test_cq", "drop continuous query 1;", false, c)
// wait for the continuous query to be dropped
Expand All @@ -682,7 +682,7 @@ func (self *ServerSuite) TestContinuousQueryManagement(c *C) {
series = collection.GetSeries("continuous queries", c)
c.Assert(series.Points, HasLen, 1)
c.Assert(series.GetValueForPointAndColumn(0, "id", c), Equals, 2.0)
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from quu into qux;")
c.Assert(series.GetValueForPointAndColumn(0, "query", c), Equals, "select * from quu into qux")

self.serverProcesses[0].QueryAsRoot("test_cq", "drop continuous query 2;", false, c)
}
Expand Down
18 changes: 15 additions & 3 deletions parser/frees.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,24 @@ free_drop_series_query (drop_series_query *q)
}

void
close_query (query *q)
close_queries (queries *q)
{
if (q->error) {
if (q->error) {
free_error(q->error);
}
}

while (q->size > 0) {
query *query = q->qs[--q->size];
close_query(query);
free(query);
}
free(q->qs);
q->qs = NULL;
}

void
close_query (query *q)
{
if (q->select_query) {
free_select_query(q->select_query);
free(q->select_query);
Expand Down
86 changes: 54 additions & 32 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ type DeleteQuery struct {
}

type Query struct {
QueryString string
SelectQuery *SelectQuery
DeleteQuery *DeleteQuery
ListQuery *ListQuery
Expand Down Expand Up @@ -112,17 +111,25 @@ func (self *Query) GetQueryStringWithTimeCondition() string {
}

func (self *Query) commonGetQueryString(withTime bool) string {
if self.SelectQuery != nil {
switch self.qType {
case Select, Continuous:
if withTime {
return self.SelectQuery.GetQueryStringWithTimeCondition()
}
return self.SelectQuery.GetQueryString()
} else if self.ListQuery != nil {
return "list series"
} else if self.DeleteQuery != nil {
case Delete:
return self.DeleteQuery.GetQueryString(withTime)
case DropContinuousQuery:
return fmt.Sprintf("drop continuous query %d", self.DropQuery.Id)
case ListSeries:
return "list series"
case ListContinuousQueries:
return "list continuous queries"
case DropSeries:
return "drop series " + self.DropSeriesQuery.tableName
default:
panic(fmt.Errorf("Unknown query type %s", self.qType))
}
return self.QueryString
}

func (self *Query) IsListQuery() bool {
Expand Down Expand Up @@ -602,24 +609,7 @@ func ParseSelectQuery(query string) (*SelectQuery, error) {
return selectQuery, nil
}

func ParseQuery(query string) ([]*Query, error) {
queryString := C.CString(query)
defer C.free(unsafe.Pointer(queryString))
q := C.parse_query(queryString)
defer C.close_query(&q)

if q.error != nil {
str := C.GoString(q.error.err)
return nil, &QueryError{
firstLine: int(q.error.first_line),
firstColumn: int(q.error.first_column) - 1,
lastLine: int(q.error.last_line),
lastColumn: int(q.error.last_column) - 1,
errorString: str,
queryString: query,
}
}

func parseSingleQuery(q *C.query) (*Query, error) {
if q.list_series_query != nil {
var value *Value
var err error
Expand All @@ -631,11 +621,11 @@ func ParseQuery(query string) ([]*Query, error) {
return nil, err
}
}
return []*Query{{QueryString: query, ListQuery: &ListQuery{Type: t, value: value}, qType: ListSeries}}, nil
return &Query{ListQuery: &ListQuery{Type: t, value: value}, qType: ListSeries}, nil
}

if q.list_continuous_queries_query != 0 {
return []*Query{{QueryString: query, ListQuery: &ListQuery{Type: ContinuousQueries}, qType: ListContinuousQueries}}, nil
return &Query{ListQuery: &ListQuery{Type: ContinuousQueries}, qType: ListContinuousQueries}, nil
}

if q.select_query != nil {
Expand All @@ -648,26 +638,58 @@ func ParseQuery(query string) ([]*Query, error) {
if selectQuery.IntoClause != nil {
qType = Continuous
}
return []*Query{{QueryString: query, SelectQuery: selectQuery, qType: qType}}, nil
return &Query{SelectQuery: selectQuery, qType: qType}, nil
} else if q.delete_query != nil {
deleteQuery, err := parseDeleteQuery(q.delete_query)
if err != nil {
return nil, err
}
return []*Query{{QueryString: query, DeleteQuery: deleteQuery, qType: Delete}}, nil
return &Query{DeleteQuery: deleteQuery, qType: Delete}, nil
} else if q.drop_series_query != nil {
dropSeriesQuery, err := parseDropSeriesQuery(query, q.drop_series_query)
dropSeriesQuery, err := parseDropSeriesQuery(q.drop_series_query)
if err != nil {
return nil, err
}
return []*Query{{QueryString: query, DropSeriesQuery: dropSeriesQuery, qType: DropSeries}}, nil
return &Query{DropSeriesQuery: dropSeriesQuery, qType: DropSeries}, nil
} else if q.drop_query != nil {
return []*Query{{QueryString: query, DropQuery: &DropQuery{Id: int(q.drop_query.id)}, qType: DropContinuousQuery}}, nil
return &Query{DropQuery: &DropQuery{Id: int(q.drop_query.id)}, qType: DropContinuousQuery}, nil
}
return nil, fmt.Errorf("Unknown query type encountered")
}

func parseDropSeriesQuery(queryStirng string, dropSeriesQuery *C.drop_series_query) (*DropSeriesQuery, error) {
func ParseQuery(queryStr string) ([]*Query, error) {
queryString := C.CString(queryStr)
defer C.free(unsafe.Pointer(queryString))
q := C.parse_query(queryString)
defer C.close_queries(&q)

if q.error != nil {
str := C.GoString(q.error.err)
return nil, &QueryError{
firstLine: int(q.error.first_line),
firstColumn: int(q.error.first_column) - 1,
lastLine: int(q.error.last_line),
lastColumn: int(q.error.last_column) - 1,
errorString: str,
queryString: queryStr,
}
}

var queries []*C.query
setupSlice((*reflect.SliceHeader)((unsafe.Pointer(&queries))), unsafe.Pointer(q.qs), q.size)

parsedQueries := make([]*Query, len(queries))
for i, query := range queries {
query, err := parseSingleQuery(query)
if err != nil {
return nil, err
}
parsedQueries[i] = query
}
return parsedQueries, nil
}

func parseDropSeriesQuery(dropSeriesQuery *C.drop_series_query) (*DropSeriesQuery, error) {
name, err := GetValue(dropSeriesQuery.name)
if err != nil {
return nil, err
Expand Down
3 changes: 1 addition & 2 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ func (self *QueryParserSuite) TestGetQueryString(c *C) {
actualQuery, err := ParseQuery(queryString)
c.Assert(err, IsNil)
c.Assert(actualQuery, HasLen, 1)
expectedQuery[0].QueryString = ""
actualQuery[0].QueryString = ""
if expectedQuery[0].DeleteQuery != nil {
expectedQuery[0].DeleteQuery.startTimeSpecified = false
actualQuery[0].DeleteQuery.startTimeSpecified = false
Expand Down Expand Up @@ -972,6 +970,7 @@ func (self *QueryParserSuite) TestQueryErrorShouldHaveQueryString(c *C) {
query := "select ! from foo;"
_, err := ParseSelectQuery(query)
e, _ := err.(*QueryError)
c.Assert(e, NotNil)
c.Assert(e.queryString, Equals, query)
}

Expand Down
20 changes: 10 additions & 10 deletions parser/query.yacc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ value *create_expression_value(char *operator, size_t size, ...) {

// declare that we want a reentrant parser
%define api.pure
%parse-param {query *q}
%parse-param {queries *q}
%parse-param {void *scanner}
%lex-param {void *scanner}

Expand Down Expand Up @@ -127,20 +127,20 @@ value *create_expression_value(char *operator, size_t size, ...) {
ALL_QUERIES:
QUERY
{
*q = *$1;
free($1);
q->qs = realloc(q->qs, (q->size + 1) * sizeof(query));
q->qs[q->size++] = $1;
}
|
QUERY ';'
{
*q = *$1;
free($1);
q->qs = realloc(q->qs, (q->size + 1) * sizeof(query));
q->qs[q->size++] = $1;
}
|
QUERY ';' ALL_QUERIES
{
*q = *$1;
free($1);
q->qs = realloc(q->qs, (q->size + 1) * sizeof(query));
q->qs[q->size++] = $1;
}

QUERY:
Expand Down Expand Up @@ -702,10 +702,10 @@ BOOL_OPERATION:
void *yy_scan_string(char *, void *);
void yy_delete_buffer(void *, void *);

query
queries
parse_query(char *const query_s)
{
query q = {NULL, NULL, NULL, NULL, FALSE, FALSE, NULL};
queries q = {0, NULL};
void *scanner;
yylex_init(&scanner);
#ifdef DEBUG
Expand All @@ -719,7 +719,7 @@ parse_query(char *const query_s)
return q;
}

int yyerror(YYLTYPE *locp, query *q, void *s, char *err) {
int yyerror(YYLTYPE *locp, queries *q, void *s, char *err) {
q->error = malloc(sizeof(error));
q->error->err = strdup(err);
q->error->first_line = locp->first_line;
Expand Down
11 changes: 9 additions & 2 deletions parser/query_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,15 @@ typedef struct {
drop_query *drop_query;
list_series_query *list_series_query;
char list_continuous_queries_query;
error *error;
} query;

// queries is an array of query
typedef struct {
size_t size;
query **qs;
error *error;
} queries;

// some funcs for freeing our types
void free_array(array *array);
void free_value_array(value_array *array);
Expand All @@ -132,5 +138,6 @@ void free_condition(condition *condition);
void free_error (error *error);

// this is the api that is used in GO
query parse_query(char *const query_s);
queries parse_query(char *const query_s);
void close_query (query *q);
void close_queries (queries *queries);
Loading

0 comments on commit 5025809

Please sign in to comment.