func readMapItems(c *TagsCursor, field string, seek, tmin, tmax int64) []MapItem { var items []MapItem var seeked bool for { var timestamp int64 var value interface{} if !seeked { timestamp, value = c.SeekTo(seek) seeked = true } else { timestamp, value = c.Next() } // We're done if the point is outside the query's time range [tmin:tmax). if timestamp != tmin && (timestamp < tmin || timestamp >= tmax) { return items } // Convert values to fields map. fields, ok := value.(map[string]interface{}) if !ok { fields = map[string]interface{}{"": value} } // Value didn't match, look for the next one. if value == nil { continue } // Filter value. if c.filter != nil { // Convert value to a map for filter evaluation. m, ok := value.(map[string]interface{}) if !ok { m = map[string]interface{}{field: value} } // If filter fails then skip to the next value. if !influxql.EvalBool(c.filter, m) { continue } } // Filter out single field, if specified. if m, ok := value.(map[string]interface{}); ok { value = m[field] } if value == nil { continue } items = append(items, MapItem{ Timestamp: timestamp, Value: value, Fields: fields, Tags: c.tags, }) } }
// Next returns the next matching series-key, timestamp byte slice and meta tags for the tagset. Filtering // is enforced on the values. If there is no matching value, then a nil result is returned. func (tsc *TagSetCursor) Next(tmin, tmax int64) (int64, interface{}) { for { // If we're out of points, we're done. if tsc.heap.Len() == 0 { return -1, nil } // Grab the next point with the lowest timestamp. p := heap.Pop(tsc.heap).(*pointHeapItem) // We're done if the point is outside the query's time range [tmin:tmax). if p.timestamp != tmin && (p.timestamp < tmin || p.timestamp >= tmax) { return -1, nil } // Save timestamp & value. timestamp, value := p.timestamp, p.value // Keep track of all fields for series cursor so we can // respond with them if asked tsc.currentFields = value // Keep track of the current tags for the series cursor so we can // respond with them if asked tsc.currentTags = p.cursor.tags // Advance the cursor. if nextKey, nextVal := p.cursor.Next(); nextKey != -1 { *p = pointHeapItem{ timestamp: nextKey, value: nextVal, cursor: p.cursor, } heap.Push(tsc.heap, p) } // Value didn't match, look for the next one. if value == nil { continue } // Filter value. if p.cursor.filter != nil { // Convert value to a map for filter evaluation. m, ok := value.(map[string]interface{}) if !ok { m = map[string]interface{}{tsc.SelectFields[0]: value} } // If filter fails then skip to the next value. if !influxql.EvalBool(p.cursor.filter, m) { continue } } // Filter out single field, if specified. if len(tsc.SelectFields) == 1 { if m, ok := value.(map[string]interface{}); ok { value = m[tsc.SelectFields[0]] } if value == nil { continue } } return timestamp, value } }
func readMapInputs(cursors []*TagsCursor, fieldNames []string, seek, tmin, tmax int64) []MapInput { inputs := make([]MapInput, len(fieldNames)) for i := range inputs { inputs[i].TMin = -1 } for _, c := range cursors { for { var timestamp int64 var value interface{} if !c.Seeked() { timestamp, value = c.SeekTo(seek) } else { timestamp, value = c.Next() } // We're done if the point is outside the query's time range [tmin:tmax). if timestamp != tmin && (timestamp < tmin || timestamp >= tmax) { c.Unread(timestamp, value) break } // Convert values to fields map. fields, ok := value.(map[string]interface{}) if !ok { fields = map[string]interface{}{"": value} } // Value didn't match, look for the next one. if value == nil { continue } for i, field := range fieldNames { fieldValue := value // Filter value. if c.filter != nil { // Convert value to a map for filter evaluation. m, ok := fieldValue.(map[string]interface{}) if !ok { m = map[string]interface{}{field: fieldValue} } // If filter fails then skip to the next value. if !influxql.EvalBool(c.filter, m) { continue } } // Filter out single field, if specified. if m, ok := fieldValue.(map[string]interface{}); ok { fieldValue = m[field] } if fieldValue == nil { continue } inputs[i].Items = append(inputs[i].Items, MapItem{ Timestamp: timestamp, Value: fieldValue, Fields: fields, Tags: c.tags, }) } } } for _, input := range inputs { sort.Sort(MapItems(input.Items)) } return inputs }