code: func (ng *Engine) exec(ctx context.Context, q *query) (Value, storage.Warnings, error) {
  	ng.metrics.currentQueries.Inc()
  	defer ng.metrics.currentQueries.Dec()
  
  	ctx, cancel := context.WithTimeout(ctx, ng.timeout)
  	q.cancel = cancel
  
  	execSpanTimer, ctx := q.stats.GetSpanTimer(ctx, stats.ExecTotalTime)
  	defer execSpanTimer.Finish()
  
  	queueSpanTimer, _ := q.stats.GetSpanTimer(ctx, stats.ExecQueueTime, ng.metrics.queryQueueTime)
  
  	if err := ng.gate.Start(ctx); err != nil {
  		return nil, nil, contextErr(err, "query queue")
  	}
  	defer ng.gate.Done()
  
  	queueSpanTimer.Finish()
  
  	// Cancel when execution is done or an error was raised.
  	defer q.cancel()
  
  	const env = "query execution"
  
  	evalSpanTimer, ctx := q.stats.GetSpanTimer(ctx, stats.EvalTotalTime)
  	defer evalSpanTimer.Finish()
  
  	// The base context might already be canceled on the first iteration (e.g. during shutdown).
  	if err := contextDone(ctx, env); err != nil {
  		return nil, nil, err
  	}
  
  	switch s := q.Statement().(type) {
  	case *EvalStmt:
  		return ng.execEvalStmt(ctx, q, s)
  	case testStmt:
  		return nil, nil, s(ctx)
  	}
  
  	panic(errors.Errorf("promql.Engine.exec: unhandled statement of type %T", q.Statement()))
  }
docs: // exec executes the query.
  //
  // At this point per query only one EvalStmt is evaluated. Alert and record
  // statements are not handled by the Engine.