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 (self *Limiter) calculateLimitAndSlicePoints(series *protocol.Series) { if self.shouldLimit { // if the limit is 0, stop returning any points limit := self.limitForSeries(*series.Name) defer func() { self.limits[*series.Name] = limit }() if limit == 0 { series.Points = nil return } limit -= len(series.Points) if limit <= 0 { sliceTo := len(series.Points) + limit series.Points = series.Points[0:sliceTo] limit = 0 } } }
// merges two time series making sure that the resulting series has // the union of the two series columns and the values set // properly. will panic if the two series don't have the same name func MergeSeries(s1, s2 *protocol.Series) *protocol.Series { if s1.GetName() != s2.GetName() { panic("the two series don't have the same name") } // if the two series have the same columns and in the same order // append the points and return. if reflect.DeepEqual(s1.Fields, s2.Fields) { s1.Points = append(s1.Points, s2.Points...) return s1 } columns := map[string]struct{}{} for _, cs := range [][]string{s1.Fields, s2.Fields} { for _, c := range cs { columns[c] = struct{}{} } } points := append(pointMaps(s1), pointMaps(s2)...) fieldsSlice := make([]string, 0, len(columns)) for c := range columns { fieldsSlice = append(fieldsSlice, c) } resultPoints := make([]*protocol.Point, 0, len(points)) for idx, point := range points { resultPoint := &protocol.Point{} for _, field := range fieldsSlice { value := point[field] if value == nil { value = &protocol.FieldValue{ IsNull: &TRUE, } } resultPoint.Values = append(resultPoint.Values, value) if idx < len(s1.Points) { resultPoint.Timestamp = s1.Points[idx].Timestamp resultPoint.SequenceNumber = s1.Points[idx].SequenceNumber } else { resultPoint.Timestamp = s2.Points[idx-len(s1.Points)].Timestamp resultPoint.SequenceNumber = s2.Points[idx-len(s1.Points)].SequenceNumber } } resultPoints = append(resultPoints, resultPoint) } // otherwise, merge the columns result := &protocol.Series{ Name: s1.Name, Fields: fieldsSlice, Points: resultPoints, } return result }