github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/emitter.go (about)

     1  package query
     2  
     3  import (
     4  	"github.com/influxdata/influxdb/v2/models"
     5  )
     6  
     7  // Emitter reads from a cursor into rows.
     8  type Emitter struct {
     9  	cur       Cursor
    10  	chunkSize int
    11  
    12  	series  Series
    13  	row     *models.Row
    14  	columns []string
    15  }
    16  
    17  // NewEmitter returns a new instance of Emitter that pulls from itrs.
    18  func NewEmitter(cur Cursor, chunkSize int) *Emitter {
    19  	columns := make([]string, len(cur.Columns()))
    20  	for i, col := range cur.Columns() {
    21  		columns[i] = col.Val
    22  	}
    23  	return &Emitter{
    24  		cur:       cur,
    25  		chunkSize: chunkSize,
    26  		columns:   columns,
    27  	}
    28  }
    29  
    30  // Close closes the underlying iterators.
    31  func (e *Emitter) Close() error {
    32  	return e.cur.Close()
    33  }
    34  
    35  // Emit returns the next row from the iterators.
    36  func (e *Emitter) Emit() (*models.Row, bool, error) {
    37  	// Continually read from the cursor until it is exhausted.
    38  	for {
    39  		// Scan the next row. If there are no rows left, return the current row.
    40  		var row Row
    41  		if !e.cur.Scan(&row) {
    42  			if err := e.cur.Err(); err != nil {
    43  				return nil, false, err
    44  			}
    45  			r := e.row
    46  			e.row = nil
    47  			return r, false, nil
    48  		}
    49  
    50  		// If there's no row yet then create one.
    51  		// If the name and tags match the existing row, append to that row if
    52  		// the number of values doesn't exceed the chunk size.
    53  		// Otherwise return existing row and add values to next emitted row.
    54  		if e.row == nil {
    55  			e.createRow(row.Series, row.Values)
    56  		} else if e.series.SameSeries(row.Series) {
    57  			if e.chunkSize > 0 && len(e.row.Values) >= e.chunkSize {
    58  				r := e.row
    59  				r.Partial = true
    60  				e.createRow(row.Series, row.Values)
    61  				return r, true, nil
    62  			}
    63  			e.row.Values = append(e.row.Values, row.Values)
    64  		} else {
    65  			r := e.row
    66  			e.createRow(row.Series, row.Values)
    67  			return r, true, nil
    68  		}
    69  	}
    70  }
    71  
    72  // createRow creates a new row attached to the emitter.
    73  func (e *Emitter) createRow(series Series, values []interface{}) {
    74  	e.series = series
    75  	e.row = &models.Row{
    76  		Name:    series.Name,
    77  		Tags:    series.Tags.KeyValues(),
    78  		Columns: e.columns,
    79  		Values:  [][]interface{}{values},
    80  	}
    81  }