diff --git a/src/engine/engine.go b/src/engine/engine.go index eaa18eedc00..4a3f571eb1b 100644 --- a/src/engine/engine.go +++ b/src/engine/engine.go @@ -49,6 +49,14 @@ func (self *QueryEngine) RunQuery(user common.User, database string, queryString continue } + if query.DropSeriesQuery != nil { + err := self.coordinator.DropSeries(user, database, query.DropSeriesQuery.GetTableName()) + if err != nil { + return err + } + continue + } + selectQuery := query.SelectQuery if isAggregateQuery(selectQuery) { return self.executeCountQueryWithGroupBy(user, database, selectQuery, localOnly, yield) diff --git a/src/integration/server_test.go b/src/integration/server_test.go index 9d1ffa45e84..5877eddc2b4 100644 --- a/src/integration/server_test.go +++ b/src/integration/server_test.go @@ -307,23 +307,31 @@ func (self *ServerSuite) TestDropDatabase(c *C) { } func (self *ServerSuite) TestDropSeries(c *C) { - self.serverProcesses[0].Post("/db?u=root&p=root", `{"name": "drop_series", "replicationFactor": 3}`, c) - self.serverProcesses[0].Post("/db/drop_series/users?u=root&p=root", `{"name": "paul", "password": "pass"}`, c) - data := `[{ + for i := 0; i < 2; i++ { + self.serverProcesses[0].Post("/db?u=root&p=root", `{"name": "drop_series", "replicationFactor": 3}`, c) + self.serverProcesses[0].Post("/db/drop_series/users?u=root&p=root", `{"name": "paul", "password": "pass"}`, c) + data := `[{ "name": "cluster_query", "columns": ["val1"], "points": [[1]] }]` - self.serverProcesses[0].Post("/db/drop_series/series?u=paul&p=pass", data, c) - time.Sleep(time.Second) - resp := self.serverProcesses[0].Request("DELETE", "/db/drop_series/series/cluster_query?u=root&p=root", "", c) - c.Assert(resp.StatusCode, Equals, http.StatusNoContent) - time.Sleep(time.Second) - for _, s := range self.serverProcesses { - fmt.Printf("Running query against: %d\n", s.apiPort) - collection := s.Query("drop_series", "select * from cluster_query", true, c) - c.Assert(collection.GetSeries("cluster_query", c).Points, HasLen, 0) - c.Assert(collection.GetSeries("cluster_query", c).Columns, DeepEquals, []string{"time", "sequence_number"}) + self.serverProcesses[0].Post("/db/drop_series/series?u=paul&p=pass", data, c) + time.Sleep(time.Second) + if i == 0 { + fmt.Printf("Using the http api\n") + resp := self.serverProcesses[0].Request("DELETE", "/db/drop_series/series/cluster_query?u=root&p=root", "", c) + c.Assert(resp.StatusCode, Equals, http.StatusNoContent) + } else { + fmt.Printf("Using the drop series\n") + self.serverProcesses[0].Query("drop_series", "drop series cluster_query", false, c) + } + time.Sleep(time.Second) + for _, s := range self.serverProcesses { + fmt.Printf("Running query against: %d\n", s.apiPort) + collection := s.Query("drop_series", "select * from cluster_query", true, c) + c.Assert(collection.GetSeries("cluster_query", c).Points, HasLen, 0) + c.Assert(collection.GetSeries("cluster_query", c).Columns, DeepEquals, []string{"time", "sequence_number"}) + } } } diff --git a/src/parser/frees.c b/src/parser/frees.c index 71c44121cb2..511202867f2 100644 --- a/src/parser/frees.c +++ b/src/parser/frees.c @@ -115,6 +115,12 @@ free_delete_query (delete_query *q) } } +void +free_drop_series_query (drop_series_query *q) +{ + free_value(q->name); +} + void close_query (query *q) { @@ -127,6 +133,11 @@ close_query (query *q) free(q->select_query); } + if (q->drop_series_query) { + free_drop_series_query(q->drop_series_query); + free(q->drop_series_query); + } + if (q->delete_query) { free_delete_query(q->delete_query); free(q->delete_query); diff --git a/src/parser/parser.go b/src/parser/parser.go index d27cffe835c..ad8bb1bcbda 100644 --- a/src/parser/parser.go +++ b/src/parser/parser.go @@ -146,14 +146,23 @@ type SelectQuery struct { type ListQuery struct{} +type DropSeriesQuery struct { + tableName string +} + +func (self *DropSeriesQuery) GetTableName() string { + return self.tableName +} + type DeleteQuery struct { SelectDeleteCommonQuery } type Query struct { - SelectQuery *SelectQuery - DeleteQuery *DeleteQuery - ListQuery *ListQuery + SelectQuery *SelectQuery + DeleteQuery *DeleteQuery + ListQuery *ListQuery + DropSeriesQuery *DropSeriesQuery } func (self *Query) GetQueryString() string { @@ -426,20 +435,37 @@ func ParseQuery(query string) ([]*Query, error) { if q.list_series_query != 0 { return []*Query{&Query{ListQuery: &ListQuery{}}}, nil - } - - if q.select_query != nil { + } else if q.select_query != nil { selectQuery, err := parseSelectQuery(query, q.select_query) if err != nil { return nil, err } return []*Query{&Query{SelectQuery: selectQuery}}, nil + } else if q.delete_query != nil { + deleteQuery, err := parseDeleteQuery(query, q.delete_query) + if err != nil { + return nil, err + } + return []*Query{&Query{DeleteQuery: deleteQuery}}, nil + } else if q.drop_series_query != nil { + dropSeriesQuery, err := parseDropSeriesQuery(query, q.drop_series_query) + if err != nil { + return nil, err + } + return []*Query{&Query{DropSeriesQuery: dropSeriesQuery}}, nil } - deleteQuery, err := parseDeleteQuery(query, q.delete_query) + return nil, fmt.Errorf("Unknown query type encountered") +} + +func parseDropSeriesQuery(queryStirng string, dropSeriesQuery *C.drop_series_query) (*DropSeriesQuery, error) { + name, err := GetValue(dropSeriesQuery.name) if err != nil { return nil, err } - return []*Query{&Query{DeleteQuery: deleteQuery}}, nil + + return &DropSeriesQuery{ + tableName: name.Name, + }, nil } func parseSelectDeleteCommonQuery(queryString string, fromClause *C.from_clause, whereCondition *C.condition) (SelectDeleteCommonQuery, error) { diff --git a/src/parser/parser_test.go b/src/parser/parser_test.go index b75c6c157b1..84d226649f6 100644 --- a/src/parser/parser_test.go +++ b/src/parser/parser_test.go @@ -73,6 +73,22 @@ func (self *QueryParserSuite) TestParseDeleteQueryWithEndTime(c *C) { c.Assert(q.GetEndTime(), Equals, time.Unix(1389040522, 0).UTC()) } +func (self *QueryParserSuite) TestParseDropSeries(c *C) { + query := "drop series foobar" + queries, err := ParseQuery(query) + c.Assert(err, IsNil) + + c.Assert(queries, HasLen, 1) + + _q := queries[0] + + c.Assert(_q.DropSeriesQuery, NotNil) + + q := _q.DropSeriesQuery + + c.Assert(q.GetTableName(), Equals, "foobar") +} + func (self *QueryParserSuite) TestGetQueryStringWithTimeCondition(c *C) { now := time.Now().Round(time.Minute).UTC() micros := common.TimeToMicroseconds(now) diff --git a/src/parser/query.lex b/src/parser/query.lex index a676f48c591..cfc0ffb4ea5 100644 --- a/src/parser/query.lex +++ b/src/parser/query.lex @@ -57,6 +57,7 @@ static int yycolumn = 1; "as" { return AS; } "select" { return SELECT; } "delete" { return DELETE; } +"drop series" { return DROP_SERIES; } "limit" { BEGIN(INITIAL); return LIMIT; } "order" { BEGIN(INITIAL); return ORDER; } "asc" { return ASC; } diff --git a/src/parser/query.yacc b/src/parser/query.yacc index dd31b6b978e..cebad7acec1 100644 --- a/src/parser/query.yacc +++ b/src/parser/query.yacc @@ -49,6 +49,7 @@ value *create_expression_value(char *operator, size_t size, ...) { query* query; select_query* select_query; delete_query* delete_query; + drop_series_query* drop_series_query; groupby_clause* groupby_clause; struct { int limit; @@ -69,7 +70,7 @@ value *create_expression_value(char *operator, size_t size, ...) { %lex-param {void *scanner} // define types of tokens (terminals) -%token SELECT DELETE FROM WHERE EQUAL GROUP BY LIMIT ORDER ASC DESC MERGE INNER JOIN AS LIST SERIES +%token SELECT DELETE FROM WHERE EQUAL GROUP BY LIMIT ORDER ASC DESC MERGE INNER JOIN AS LIST SERIES DROP_SERIES %token STRING_VALUE INT_VALUE FLOAT_VALUE TABLE_NAME SIMPLE_NAME REGEX_OP %token NEGATION_REGEX_OP REGEX_STRING INSENSITIVE_REGEX_STRING DURATION @@ -96,6 +97,7 @@ value *create_expression_value(char *operator, size_t size, ...) { %type LIMIT_AND_ORDER_CLAUSES %type QUERY %type DELETE_QUERY +%type DROP_SERIES_QUERY %type SELECT_QUERY // the initial token @@ -150,6 +152,12 @@ QUERY: $$ = calloc(1, sizeof(query)); $$->list_series_query = TRUE; } + | + DROP_SERIES_QUERY + { + $$ = calloc(1, sizeof(query)); + $$->drop_series_query = $1; + } DELETE_QUERY: DELETE FROM_CLAUSE WHERE_CLAUSE @@ -159,6 +167,13 @@ DELETE_QUERY: $$->where_condition = $3; } +DROP_SERIES_QUERY: + DROP_SERIES SIMPLE_NAME_VALUE + { + $$ = malloc(sizeof(drop_series_query)); + $$->name = $2; + } + SELECT_QUERY: SELECT COLUMN_NAMES FROM_CLAUSE GROUP_BY_CLAUSE WHERE_CLAUSE LIMIT_AND_ORDER_CLAUSES { @@ -511,7 +526,7 @@ void yy_delete_buffer(void *, void *); query parse_query(char *const query_s) { - query q = {NULL, NULL, FALSE, NULL}; + query q = {NULL, NULL, NULL, FALSE, NULL}; void *scanner; yylex_init(&scanner); #ifdef DEBUG diff --git a/src/parser/query_types.h b/src/parser/query_types.h index 338779fcb02..07e83471203 100644 --- a/src/parser/query_types.h +++ b/src/parser/query_types.h @@ -89,9 +89,14 @@ typedef struct { error *error; } delete_query; +typedef struct { + value *name; +} drop_series_query; + typedef struct { select_query *select_query; delete_query *delete_query; + drop_series_query *drop_series_query; char list_series_query; error *error; } query; diff --git a/src/parser/test_memory_leaks.sh b/src/parser/test_memory_leaks.sh index 86f1440a9bb..0c839b033e6 100755 --- a/src/parser/test_memory_leaks.sh +++ b/src/parser/test_memory_leaks.sh @@ -39,6 +39,9 @@ int main(int argc, char **argv) { q = parse_query("select email from users.events where email in ('jvshahid@gmail.com')"); close_query(&q); + q = parse_query("drop series foobar"); + close_query(&q); + return 0; } EOF