// rewriteSelectStatement performs any necessary query re-writing. func (lm *SelectMapper) rewriteSelectStatement(stmt *influxql.SelectStatement) (*influxql.SelectStatement, error) { var err error // Expand regex expressions in the FROM clause. sources, err := expandSources(stmt.Sources, lm.shard.index) if err != nil { return nil, err } stmt.Sources = sources // Expand wildcards in the fields or GROUP BY. stmt, err = lm.expandWildcards(stmt) if err != nil { return nil, err } stmt.RewriteDistinct() return stmt, nil }
// RewriteSelectStatement performs any necessary query re-writing. func (db *DatabaseIndex) RewriteSelectStatement(stmt *influxql.SelectStatement) (*influxql.SelectStatement, error) { // Expand regex expressions in the FROM clause. sources, err := db.ExpandSources(stmt.Sources) if err != nil { return nil, err } stmt.Sources = sources // Expand wildcards in the fields or GROUP BY. stmt, err = db.ExpandWildcards(stmt) if err != nil { return nil, err } stmt.RewriteDistinct() return stmt, nil }
// rewriteSelectStatement performs any necessary query re-writing. func (q *QueryExecutor) rewriteSelectStatement(stmt *influxql.SelectStatement) (*influxql.SelectStatement, error) { var err error // Expand regex expressions in the FROM clause. sources, err := q.expandSources(stmt.Sources) if err != nil { return nil, err } stmt.Sources = sources // Expand wildcards in the fields or GROUP BY. if stmt.HasWildcard() { stmt, err = q.expandWildcards(stmt) if err != nil { return nil, err } } stmt.RewriteDistinct() return stmt, nil }
// Plan creates an execution plan for the given SelectStatement and returns an Executor. func (q *QueryExecutor) PlanSelect(stmt *influxql.SelectStatement, chunkSize int) (Executor, error) { var shardIDs []uint64 shards := map[uint64]meta.ShardInfo{} // Shards requiring mappers. // It is important to "stamp" this time so that everywhere we evaluate `now()` in the statement is EXACTLY the same `now` now := time.Now().UTC() // Replace instances of "now()" with the current time, and check the resultant times. stmt.Condition = influxql.Reduce(stmt.Condition, &influxql.NowValuer{Now: now}) tmin, tmax := influxql.TimeRange(stmt.Condition) if tmax.IsZero() { tmax = now } if tmin.IsZero() { tmin = time.Unix(0, 0) } for _, src := range stmt.Sources { mm, ok := src.(*influxql.Measurement) if !ok { return nil, fmt.Errorf("invalid source type: %#v", src) } // Build the set of target shards. Using shard IDs as keys ensures each shard ID // occurs only once. shardGroups, err := q.MetaClient.ShardGroupsByTimeRange(mm.Database, mm.RetentionPolicy, tmin, tmax) if err != nil { return nil, err } for _, g := range shardGroups { for _, sh := range g.Shards { if _, ok := shards[sh.ID]; !ok { shards[sh.ID] = sh shardIDs = append(shardIDs, sh.ID) } } } } // Sort shard IDs to make testing deterministic. sort.Sort(uint64Slice(shardIDs)) // Build the Mappers, one per shard. mappers := []Mapper{} for _, shardID := range shardIDs { sh := shards[shardID] 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) } // Certain operations on the SELECT statement can be performed by the AggregateExecutor without // assistance from the Mappers. This allows the AggregateExecutor to prepare aggregation functions // and mathematical functions. stmt.RewriteDistinct() if (stmt.IsRawQuery && !stmt.HasDistinct()) || stmt.IsSimpleDerivative() { return NewRawExecutor(stmt, mappers, chunkSize), nil } else { return NewAggregateExecutor(stmt, mappers), nil } }