// executeSelectStatement plans and executes a select statement against a database. func (q *QueryExecutor) executeSelectStatement(statementID int, stmt *influxql.SelectStatement, results chan *influxql.Result, chunkSize int) error { // Perform any necessary query re-writing. stmt, err := q.rewriteSelectStatement(stmt) if err != nil { return err } // Plan statement execution. p := influxql.NewPlanner(q) e, err := p.Plan(stmt, chunkSize) if err != nil { return err } // Execute plan. ch := e.Execute() // Stream results from the channel. We should send an empty result if nothing comes through. resultSent := false for row := range ch { if row.Err != nil { return row.Err } else { resultSent = true results <- &influxql.Result{StatementID: statementID, Series: []*influxql.Row{row}} } } if !resultSent { results <- &influxql.Result{StatementID: statementID, Series: make([]*influxql.Row, 0)} } return nil }
// Ensure the planner sends the correct simplified statements to the iterator creator. func TestPlanner_CreateIterators(t *testing.T) { var flag0, flag1 bool tx := NewTx() tx.CreateIteratorsFunc = func(stmt *influxql.SelectStatement) ([]influxql.Iterator, error) { switch stmt.String() { case `SELECT cpu.0.value FROM cpu.0 GROUP BY time(10s)`: flag0 = true case `SELECT cpu.1.value FROM cpu.1 GROUP BY time(10s)`: flag1 = true default: t.Fatalf("unexpected stmt passed to iterator creator: %s", stmt.String()) } return nil, nil } stmt := MustParseSelectStatement(` SELECT sum(cpu.0.value) + sum(cpu.1.value) AS sum FROM JOIN(cpu.0, cpu.1) WHERE time >= '2000-01-01 00:00:00' AND time < '2000-01-01 00:01:00' GROUP BY time(10s)`) p := influxql.NewPlanner(NewDB(tx)) p.Now = func() time.Time { return mustParseTime("2000-01-01T12:00:00Z") } if _, err := p.Plan(stmt); err != nil { t.Fatalf("unexpected error: %s", err) } // Verify correct statements were passed through. if !flag0 { t.Error("cpu.0 substatement not passed in") } if !flag1 { t.Error("cpu.1 substatement not passed in") } }
// PlanAndExecute plans, executes, and retrieves all rows. func PlanAndExecute(db influxql.DB, now string, querystring string) ([]*influxql.Row, error) { // Plan statement. p := influxql.NewPlanner(db) p.Now = func() time.Time { return mustParseTime(now) } e, err := p.Plan(MustParseSelectStatement(querystring)) if err != nil { return nil, err } // Execute plan. ch, err := e.Execute() if err != nil { return nil, err } // Collect resultset. var rs []*influxql.Row for row := range ch { rs = append(rs, row) } return rs, nil }