// 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") } condition := stmt.Condition if len(stmt.Sources) > 0 { if source, ok := stmt.Sources[0].(*influxql.Measurement); ok { var expr influxql.Expr if source.Regex != nil { expr = &influxql.BinaryExpr{ Op: influxql.EQREGEX, LHS: &influxql.VarRef{Val: "name"}, RHS: &influxql.RegexLiteral{Val: source.Regex.Val}, } } else if source.Name != "" { expr = &influxql.BinaryExpr{ Op: influxql.EQ, LHS: &influxql.VarRef{Val: "name"}, RHS: &influxql.StringLiteral{Val: source.Name}, } } // Set condition or "AND" together. if condition == nil { condition = expr } else { condition = &influxql.BinaryExpr{Op: influxql.AND, LHS: expr, RHS: condition} } } } ss := &influxql.SelectStatement{ Fields: []*influxql.Field{ {Expr: &influxql.VarRef{Val: "tagKey"}}, }, Sources: []influxql.Source{ &influxql.Measurement{Name: "_tagKeys"}, }, Condition: condition, Offset: stmt.Offset, Limit: stmt.Limit, SortFields: stmt.SortFields, OmitTime: true, Dedupe: true, } // Normalize the statement. if err := q.normalizeStatement(ss, database); err != nil { return nil, err } return q.PlanSelect(ss, chunkSize) }
func (e *StatementExecutor) executeDropSeriesStatement(stmt *influxql.DropSeriesStatement, database string) error { if dbi := e.MetaClient.Database(database); dbi == nil { return influxql.ErrDatabaseNotFound(database) } // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return errors.New("DROP SERIES doesn't support time in WHERE clause") } // Locally drop the series. return e.TSDBStore.DeleteSeries(database, stmt.Sources, stmt.Condition) }
func (e *QueryExecutor) executeDropSeriesStatement(stmt *influxql.DropSeriesStatement, database string) error { if dbi, err := e.MetaClient.Database(database); err != nil { return err } else if dbi == nil { return influxql.ErrDatabaseNotFound(database) } // Check for time in WHERE clause (not supported). if influxql.HasTimeExpr(stmt.Condition) { return errors.New("DROP SERIES doesn't support time in WHERE clause") } // Locally drop the series. if err := e.TSDBStore.DeleteSeries(database, stmt.Sources, stmt.Condition); err != nil { return err } // Execute the statement on the other data nodes in the cluster. return e.MetaExecutor.ExecuteStatement(stmt, database) }
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 TAG VALUES 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.Store.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.Store.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.Store.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(database, seriesKeys); err != nil { return &influxql.Result{Err: err} } // remove them from the index db.DropSeries(seriesKeys) return &influxql.Result{} }