// PlanShowTagKeys creates an execution plan for a SHOW MEASUREMENTS statement and returns an Executor. func (q *QueryExecutor) PlanShowTagKeys(stmt *influxql.ShowTagKeysStatement, database string, chunkSize int) (Executor, error) { // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return nil, errors.New("SHOW TAG KEYS doesn't support time in WHERE clause") } // Get the database info. di, err := q.MetaStore.Database(database) if err != nil { return nil, err } else if di == nil { return nil, ErrDatabaseNotFound(database) } // Get info for all shards in the database. shards := di.ShardInfos() // Build the Mappers, one per shard. mappers := []Mapper{} for _, sh := range shards { m, err := q.ShardMapper.CreateMapper(sh, stmt, chunkSize) if err != nil { return nil, err } if m == nil { // No data for this shard, skip it. continue } mappers = append(mappers, m) } executor := NewShowTagKeysExecutor(stmt, mappers, chunkSize) return executor, nil }
func (q *QueryExecutor) executeShowTagValuesStatement(stmt *influxql.ShowTagValuesStatement, database string) *influxql.Result { // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return &influxql.Result{Err: errors.New("SHOW SERIES doesn't support time in WHERE clause")} } // Find the database. db := q.Store.DatabaseIndex(database) if db == nil { return &influxql.Result{} } // Expand regex expressions in the FROM clause. sources, err := q.expandSources(stmt.Sources) if err != nil { return &influxql.Result{Err: err} } // Get the list of measurements we're interested in. measurements, err := measurementsFromSourcesOrDB(db, sources...) if err != nil { return &influxql.Result{Err: err} } // Make result. result := &influxql.Result{ Series: make(models.Rows, 0), } tagValues := make(map[string]stringSet) for _, m := range measurements { var ids SeriesIDs if stmt.Condition != nil { // Get series IDs that match the WHERE clause. ids, _, err = m.walkWhereForSeriesIds(stmt.Condition) if err != nil { return &influxql.Result{Err: err} } // If no series matched, then go to the next measurement. if len(ids) == 0 { continue } // TODO: check return of walkWhereForSeriesIds for fields } else { // No WHERE clause so get all series IDs for this measurement. ids = m.seriesIDs } for k, v := range m.tagValuesByKeyAndSeriesID(stmt.TagKeys, ids) { _, ok := tagValues[k] if !ok { tagValues[k] = v } tagValues[k] = tagValues[k].union(v) } } for k, v := range tagValues { r := &models.Row{ Name: k + "TagValues", Columns: []string{k}, } vals := v.list() sort.Strings(vals) for _, val := range vals { v := interface{}(val) r.Values = append(r.Values, []interface{}{v}) } result.Series = append(result.Series, r) } sort.Sort(result.Series) return result }
func (q *QueryExecutor) executeShowSeriesStatement(stmt *influxql.ShowSeriesStatement, database string) *influxql.Result { // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return &influxql.Result{Err: errors.New("SHOW SERIES doesn't support time in WHERE clause")} } // Find the database. db := q.Store.DatabaseIndex(database) if db == nil { return &influxql.Result{} } // Expand regex expressions in the FROM clause. sources, err := q.expandSources(stmt.Sources) if err != nil { return &influxql.Result{Err: err} } // Get the list of measurements we're interested in. measurements, err := measurementsFromSourcesOrDB(db, sources...) if err != nil { return &influxql.Result{Err: err} } // Create result struct that will be populated and returned. result := &influxql.Result{ Series: make(models.Rows, 0, len(measurements)), } // Loop through measurements to build result. One result row / measurement. for _, m := range measurements { var ids SeriesIDs var filters FilterExprs if stmt.Condition != nil { // Get series IDs that match the WHERE clause. ids, filters, err = m.walkWhereForSeriesIds(stmt.Condition) if err != nil { return &influxql.Result{Err: err} } // Delete boolean literal true filter expressions. filters.DeleteBoolLiteralTrues() // Check for unsupported field filters. if filters.Len() > 0 { return &influxql.Result{Err: errors.New("SHOW SERIES doesn't support fields in WHERE clause")} } // If no series matched, then go to the next measurement. if len(ids) == 0 { continue } } else { // No WHERE clause so get all series IDs for this measurement. ids = m.seriesIDs } // Make a new row for this measurement. r := &models.Row{ Name: m.Name, Columns: m.TagKeys(), } // Loop through series IDs getting matching tag sets. for _, id := range ids { if s, ok := m.seriesByID[id]; ok { values := make([]interface{}, 0, len(r.Columns)) // make the series key the first value values = append(values, s.Key) for _, column := range r.Columns { values = append(values, s.Tags[column]) } // Add the tag values to the row. r.Values = append(r.Values, values) } } // make the id the first column r.Columns = append([]string{"_key"}, r.Columns...) // Append the row to the result. result.Series = append(result.Series, r) } if stmt.Limit > 0 || stmt.Offset > 0 { result.Series = q.filterShowSeriesResult(stmt.Limit, stmt.Offset, result.Series) } return result }
// executeDropSeriesStatement removes all series from the local store that match the drop query func (q *QueryExecutor) executeDropSeriesStatement(stmt *influxql.DropSeriesStatement, database string) *influxql.Result { // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return &influxql.Result{Err: errors.New("DROP SERIES doesn't support time in WHERE clause")} } // Find the database. db := q.Store.DatabaseIndex(database) if db == nil { return &influxql.Result{} } // Expand regex expressions in the FROM clause. sources, err := q.expandSources(stmt.Sources) if err != nil { return &influxql.Result{Err: err} } else if stmt.Sources != nil && len(stmt.Sources) != 0 && len(sources) == 0 { return &influxql.Result{} } measurements, err := measurementsFromSourcesOrDB(db, sources...) if err != nil { return &influxql.Result{Err: err} } var seriesKeys []string for _, m := range measurements { var ids SeriesIDs var filters FilterExprs if stmt.Condition != nil { // Get series IDs that match the WHERE clause. ids, filters, err = m.walkWhereForSeriesIds(stmt.Condition) if err != nil { return &influxql.Result{Err: err} } // Delete boolean literal true filter expressions. // These are returned for `WHERE tagKey = 'tagVal'` type expressions and are okay. filters.DeleteBoolLiteralTrues() // Check for unsupported field filters. // Any remaining filters means there were fields (e.g., `WHERE value = 1.2`). if filters.Len() > 0 { return &influxql.Result{Err: errors.New("DROP SERIES doesn't support fields in WHERE clause")} } } else { // No WHERE clause so get all series IDs for this measurement. ids = m.seriesIDs } for _, id := range ids { seriesKeys = append(seriesKeys, m.seriesByID[id].Key) } } // delete the raw series data if err := q.Store.deleteSeries(seriesKeys); err != nil { return &influxql.Result{Err: err} } // remove them from the index db.DropSeries(seriesKeys) return &influxql.Result{} }