func Filter(query *parser.SelectQuery, series *protocol.Series) (*protocol.Series, error) { if query.GetWhereCondition() == nil { return series, nil } columns := map[string]struct{}{} if query.GetFromClause().Type == parser.FromClauseInnerJoin { outer: for t, cs := range query.GetResultColumns() { for _, c := range cs { // if this is a wildcard select, then drop all columns and // just use '*' if c == "*" { columns = make(map[string]struct{}, 1) columns[c] = struct{}{} break outer } columns[t.Name+"."+c] = struct{}{} } } } else { for _, cs := range query.GetResultColumns() { for _, c := range cs { columns[c] = struct{}{} } } } points := series.Points series.Points = nil for _, point := range points { ok, err := matches(query.GetWhereCondition(), series.Fields, point) if err != nil { return nil, err } if ok { filterColumns(columns, series.Fields, point) series.Points = append(series.Points, point) } } if _, ok := columns["*"]; !ok { newFields := []string{} for _, f := range series.Fields { if _, ok := columns[f]; !ok { continue } newFields = append(newFields, f) } series.Fields = newFields } return series, nil }
func NewQueryEngine(query *parser.SelectQuery, responseChan chan *protocol.Response) (*QueryEngine, error) { limit := query.Limit queryEngine := &QueryEngine{ query: query, where: query.GetWhereCondition(), limiter: NewLimiter(limit), responseChan: responseChan, seriesToPoints: make(map[string]*protocol.Series), // stats stuff explain: query.IsExplainQuery(), runStartTime: 0, runEndTime: 0, pointsRead: 0, pointsWritten: 0, shardId: 0, shardLocal: false, //that really doesn't matter if it is not EXPLAIN query duration: nil, seriesStates: make(map[string]*SeriesState), } if queryEngine.explain { queryEngine.runStartTime = float64(time.Now().UnixNano()) / float64(time.Millisecond) } yield := func(series *protocol.Series) error { var response *protocol.Response queryEngine.limiter.calculateLimitAndSlicePoints(series) if len(series.Points) == 0 { return nil } if queryEngine.explain { //TODO: We may not have to send points, just count them queryEngine.pointsWritten += int64(len(series.Points)) } response = &protocol.Response{Type: &queryResponse, Series: series} responseChan <- response return nil } var err error if query.HasAggregates() { err = queryEngine.executeCountQueryWithGroupBy(query, yield) } else if containsArithmeticOperators(query) { err = queryEngine.executeArithmeticQuery(query, yield) } else { err = queryEngine.distributeQuery(query, yield) } if err != nil { return nil, err } return queryEngine, nil }
func NewFilteringEngine(query *parser.SelectQuery, processor Processor) *FilteringEngine { shouldFilter := query.GetWhereCondition() != nil return &FilteringEngine{query, processor, shouldFilter} }