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

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"regexp"
    10  	"time"
    11  
    12  	internal "github.com/influxdata/influxdb/v2/influxql/query/internal"
    13  	"github.com/influxdata/influxdb/v2/kit/platform"
    14  	"github.com/influxdata/influxql"
    15  	"google.golang.org/protobuf/proto"
    16  )
    17  
    18  // ErrUnknownCall is returned when operating on an unknown function call.
    19  var ErrUnknownCall = errors.New("unknown call")
    20  
    21  const (
    22  	// secToNs is the number of nanoseconds in a second.
    23  	secToNs = int64(time.Second)
    24  )
    25  
    26  // Iterator represents a generic interface for all Iterators.
    27  // Most iterator operations are done on the typed sub-interfaces.
    28  type Iterator interface {
    29  	Stats() IteratorStats
    30  	Close() error
    31  }
    32  
    33  // Iterators represents a list of iterators.
    34  type Iterators []Iterator
    35  
    36  // Stats returns the aggregation of all iterator stats.
    37  func (a Iterators) Stats() IteratorStats {
    38  	var stats IteratorStats
    39  	for _, itr := range a {
    40  		stats.Add(itr.Stats())
    41  	}
    42  	return stats
    43  }
    44  
    45  // Close closes all iterators.
    46  // We are seeing an occasional panic in this function
    47  // which looks like a nil reference from one
    48  // itr.Close() call, thus we check for nil elements
    49  // in the slice a.  This is often called as error
    50  // clean-up, so the state of the iterators may be
    51  // unhappy.
    52  func (a Iterators) Close() (err error) {
    53  	err = nil
    54  	for _, itr := range a {
    55  		if itr != nil {
    56  			if e := itr.Close(); e != nil && err == nil {
    57  				err = e
    58  			}
    59  		}
    60  	}
    61  	return err
    62  }
    63  
    64  // filterNonNil returns a slice of iterators that removes all nil iterators.
    65  func (a Iterators) filterNonNil() []Iterator {
    66  	other := make([]Iterator, 0, len(a))
    67  	for _, itr := range a {
    68  		if itr == nil {
    69  			continue
    70  		}
    71  		other = append(other, itr)
    72  	}
    73  	return other
    74  }
    75  
    76  // dataType determines what slice type this set of iterators should be.
    77  // An iterator type is chosen by looking at the first element in the slice
    78  // and then returning the data type for that iterator.
    79  func (a Iterators) dataType() influxql.DataType {
    80  	if len(a) == 0 {
    81  		return influxql.Unknown
    82  	}
    83  
    84  	switch a[0].(type) {
    85  	case FloatIterator:
    86  		return influxql.Float
    87  	case IntegerIterator:
    88  		return influxql.Integer
    89  	case UnsignedIterator:
    90  		return influxql.Unsigned
    91  	case StringIterator:
    92  		return influxql.String
    93  	case BooleanIterator:
    94  		return influxql.Boolean
    95  	default:
    96  		return influxql.Unknown
    97  	}
    98  }
    99  
   100  // coerce forces an array of iterators to be a single type.
   101  // Iterators that are not of the same type as the first element in the slice
   102  // will be closed and dropped.
   103  func (a Iterators) coerce() interface{} {
   104  	typ := a.dataType()
   105  	switch typ {
   106  	case influxql.Float:
   107  		return newFloatIterators(a)
   108  	case influxql.Integer:
   109  		return newIntegerIterators(a)
   110  	case influxql.Unsigned:
   111  		return newUnsignedIterators(a)
   112  	case influxql.String:
   113  		return newStringIterators(a)
   114  	case influxql.Boolean:
   115  		return newBooleanIterators(a)
   116  	}
   117  	return a
   118  }
   119  
   120  // Merge combines all iterators into a single iterator.
   121  // A sorted merge iterator or a merge iterator can be used based on opt.
   122  func (a Iterators) Merge(opt IteratorOptions) (Iterator, error) {
   123  	// Check if this is a call expression.
   124  	call, ok := opt.Expr.(*influxql.Call)
   125  
   126  	// Merge into a single iterator.
   127  	if !ok && opt.MergeSorted() {
   128  		itr := NewSortedMergeIterator(a, opt)
   129  		if itr != nil && opt.InterruptCh != nil {
   130  			itr = NewInterruptIterator(itr, opt.InterruptCh)
   131  		}
   132  		return itr, nil
   133  	}
   134  
   135  	// We do not need an ordered output so use a merge iterator.
   136  	itr := NewMergeIterator(a, opt)
   137  	if itr == nil {
   138  		return nil, nil
   139  	}
   140  
   141  	if opt.InterruptCh != nil {
   142  		itr = NewInterruptIterator(itr, opt.InterruptCh)
   143  	}
   144  
   145  	if !ok {
   146  		// This is not a call expression so do not use a call iterator.
   147  		return itr, nil
   148  	}
   149  
   150  	// When merging the count() function, use sum() to sum the counted points.
   151  	if call.Name == "count" {
   152  		opt.Expr = &influxql.Call{
   153  			Name: "sum",
   154  			Args: call.Args,
   155  		}
   156  	}
   157  	// When merging the sum_hll() function, use merge_hll() to sum the counted points.
   158  	if call.Name == "sum_hll" {
   159  		opt.Expr = &influxql.Call{
   160  			Name: "merge_hll",
   161  			Args: call.Args,
   162  		}
   163  	}
   164  	return NewCallIterator(itr, opt)
   165  }
   166  
   167  // NewMergeIterator returns an iterator to merge itrs into one.
   168  // Inputs must either be merge iterators or only contain a single name/tag in
   169  // sorted order. The iterator will output all points by window, name/tag, then
   170  // time. This iterator is useful when you need all of the points for an
   171  // interval.
   172  func NewMergeIterator(inputs []Iterator, opt IteratorOptions) Iterator {
   173  	inputs = Iterators(inputs).filterNonNil()
   174  	if n := len(inputs); n == 0 {
   175  		return nil
   176  	} else if n == 1 {
   177  		return inputs[0]
   178  	}
   179  
   180  	// Aggregate functions can use a more relaxed sorting so that points
   181  	// within a window are grouped. This is much more efficient.
   182  	switch inputs := Iterators(inputs).coerce().(type) {
   183  	case []FloatIterator:
   184  		return newFloatMergeIterator(inputs, opt)
   185  	case []IntegerIterator:
   186  		return newIntegerMergeIterator(inputs, opt)
   187  	case []UnsignedIterator:
   188  		return newUnsignedMergeIterator(inputs, opt)
   189  	case []StringIterator:
   190  		return newStringMergeIterator(inputs, opt)
   191  	case []BooleanIterator:
   192  		return newBooleanMergeIterator(inputs, opt)
   193  	default:
   194  		panic(fmt.Sprintf("unsupported merge iterator type: %T", inputs))
   195  	}
   196  }
   197  
   198  // NewParallelMergeIterator returns an iterator that breaks input iterators
   199  // into groups and processes them in parallel.
   200  func NewParallelMergeIterator(inputs []Iterator, opt IteratorOptions, parallelism int) Iterator {
   201  	inputs = Iterators(inputs).filterNonNil()
   202  	if len(inputs) == 0 {
   203  		return nil
   204  	} else if len(inputs) == 1 {
   205  		return inputs[0]
   206  	}
   207  
   208  	// Limit parallelism to the number of inputs.
   209  	if len(inputs) < parallelism {
   210  		parallelism = len(inputs)
   211  	}
   212  
   213  	// Determine the number of inputs per output iterator.
   214  	n := len(inputs) / parallelism
   215  
   216  	// Group iterators together.
   217  	outputs := make([]Iterator, parallelism)
   218  	for i := range outputs {
   219  		var slice []Iterator
   220  		if i < len(outputs)-1 {
   221  			slice = inputs[i*n : (i+1)*n]
   222  		} else {
   223  			slice = inputs[i*n:]
   224  		}
   225  
   226  		outputs[i] = newParallelIterator(NewMergeIterator(slice, opt))
   227  	}
   228  
   229  	// Merge all groups together.
   230  	return NewMergeIterator(outputs, opt)
   231  }
   232  
   233  // NewSortedMergeIterator returns an iterator to merge itrs into one.
   234  // Inputs must either be sorted merge iterators or only contain a single
   235  // name/tag in sorted order. The iterator will output all points by name/tag,
   236  // then time. This iterator is useful when you need all points for a name/tag
   237  // to be in order.
   238  func NewSortedMergeIterator(inputs []Iterator, opt IteratorOptions) Iterator {
   239  	inputs = Iterators(inputs).filterNonNil()
   240  	if len(inputs) == 0 {
   241  		return nil
   242  	} else if len(inputs) == 1 {
   243  		return inputs[0]
   244  	}
   245  
   246  	switch inputs := Iterators(inputs).coerce().(type) {
   247  	case []FloatIterator:
   248  		return newFloatSortedMergeIterator(inputs, opt)
   249  	case []IntegerIterator:
   250  		return newIntegerSortedMergeIterator(inputs, opt)
   251  	case []UnsignedIterator:
   252  		return newUnsignedSortedMergeIterator(inputs, opt)
   253  	case []StringIterator:
   254  		return newStringSortedMergeIterator(inputs, opt)
   255  	case []BooleanIterator:
   256  		return newBooleanSortedMergeIterator(inputs, opt)
   257  	default:
   258  		panic(fmt.Sprintf("unsupported sorted merge iterator type: %T", inputs))
   259  	}
   260  }
   261  
   262  // newParallelIterator returns an iterator that runs in a separate goroutine.
   263  func newParallelIterator(input Iterator) Iterator {
   264  	if input == nil {
   265  		return nil
   266  	}
   267  
   268  	switch itr := input.(type) {
   269  	case FloatIterator:
   270  		return newFloatParallelIterator(itr)
   271  	case IntegerIterator:
   272  		return newIntegerParallelIterator(itr)
   273  	case UnsignedIterator:
   274  		return newUnsignedParallelIterator(itr)
   275  	case StringIterator:
   276  		return newStringParallelIterator(itr)
   277  	case BooleanIterator:
   278  		return newBooleanParallelIterator(itr)
   279  	default:
   280  		panic(fmt.Sprintf("unsupported parallel iterator type: %T", itr))
   281  	}
   282  }
   283  
   284  // NewLimitIterator returns an iterator that limits the number of points per grouping.
   285  func NewLimitIterator(input Iterator, opt IteratorOptions) Iterator {
   286  	switch input := input.(type) {
   287  	case FloatIterator:
   288  		return newFloatLimitIterator(input, opt)
   289  	case IntegerIterator:
   290  		return newIntegerLimitIterator(input, opt)
   291  	case UnsignedIterator:
   292  		return newUnsignedLimitIterator(input, opt)
   293  	case StringIterator:
   294  		return newStringLimitIterator(input, opt)
   295  	case BooleanIterator:
   296  		return newBooleanLimitIterator(input, opt)
   297  	default:
   298  		panic(fmt.Sprintf("unsupported limit iterator type: %T", input))
   299  	}
   300  }
   301  
   302  // NewFilterIterator returns an iterator that filters the points based on the
   303  // condition. This iterator is not nearly as efficient as filtering points
   304  // within the query engine and is only used when filtering subqueries.
   305  func NewFilterIterator(input Iterator, cond influxql.Expr, opt IteratorOptions) Iterator {
   306  	if input == nil {
   307  		return nil
   308  	}
   309  
   310  	switch input := input.(type) {
   311  	case FloatIterator:
   312  		return newFloatFilterIterator(input, cond, opt)
   313  	case IntegerIterator:
   314  		return newIntegerFilterIterator(input, cond, opt)
   315  	case UnsignedIterator:
   316  		return newUnsignedFilterIterator(input, cond, opt)
   317  	case StringIterator:
   318  		return newStringFilterIterator(input, cond, opt)
   319  	case BooleanIterator:
   320  		return newBooleanFilterIterator(input, cond, opt)
   321  	default:
   322  		panic(fmt.Sprintf("unsupported filter iterator type: %T", input))
   323  	}
   324  }
   325  
   326  // NewTagSubsetIterator will strip each of the points to a subset of the tag key values
   327  // for each point it processes.
   328  func NewTagSubsetIterator(input Iterator, opt IteratorOptions) Iterator {
   329  	if input == nil {
   330  		return nil
   331  	}
   332  
   333  	switch input := input.(type) {
   334  	case FloatIterator:
   335  		return newFloatTagSubsetIterator(input, opt)
   336  	case IntegerIterator:
   337  		return newIntegerTagSubsetIterator(input, opt)
   338  	case UnsignedIterator:
   339  		return newUnsignedTagSubsetIterator(input, opt)
   340  	case StringIterator:
   341  		return newStringTagSubsetIterator(input, opt)
   342  	case BooleanIterator:
   343  		return newBooleanTagSubsetIterator(input, opt)
   344  	default:
   345  		panic(fmt.Sprintf("unsupported tag subset iterator type: %T", input))
   346  	}
   347  }
   348  
   349  // NewDedupeIterator returns an iterator that only outputs unique points.
   350  // This iterator maintains a serialized copy of each row so it is inefficient
   351  // to use on large datasets. It is intended for small datasets such as meta queries.
   352  func NewDedupeIterator(input Iterator) Iterator {
   353  	if input == nil {
   354  		return nil
   355  	}
   356  
   357  	switch input := input.(type) {
   358  	case FloatIterator:
   359  		return newFloatDedupeIterator(input)
   360  	case IntegerIterator:
   361  		return newIntegerDedupeIterator(input)
   362  	case UnsignedIterator:
   363  		return newUnsignedDedupeIterator(input)
   364  	case StringIterator:
   365  		return newStringDedupeIterator(input)
   366  	case BooleanIterator:
   367  		return newBooleanDedupeIterator(input)
   368  	default:
   369  		panic(fmt.Sprintf("unsupported dedupe iterator type: %T", input))
   370  	}
   371  }
   372  
   373  // NewFillIterator returns an iterator that fills in missing points in an aggregate.
   374  func NewFillIterator(input Iterator, expr influxql.Expr, opt IteratorOptions) Iterator {
   375  	switch input := input.(type) {
   376  	case FloatIterator:
   377  		return newFloatFillIterator(input, expr, opt)
   378  	case IntegerIterator:
   379  		return newIntegerFillIterator(input, expr, opt)
   380  	case UnsignedIterator:
   381  		return newUnsignedFillIterator(input, expr, opt)
   382  	case StringIterator:
   383  		return newStringFillIterator(input, expr, opt)
   384  	case BooleanIterator:
   385  		return newBooleanFillIterator(input, expr, opt)
   386  	default:
   387  		panic(fmt.Sprintf("unsupported fill iterator type: %T", input))
   388  	}
   389  }
   390  
   391  // NewIntervalIterator returns an iterator that sets the time on each point to the interval.
   392  func NewIntervalIterator(input Iterator, opt IteratorOptions) Iterator {
   393  	switch input := input.(type) {
   394  	case FloatIterator:
   395  		return newFloatIntervalIterator(input, opt)
   396  	case IntegerIterator:
   397  		return newIntegerIntervalIterator(input, opt)
   398  	case UnsignedIterator:
   399  		return newUnsignedIntervalIterator(input, opt)
   400  	case StringIterator:
   401  		return newStringIntervalIterator(input, opt)
   402  	case BooleanIterator:
   403  		return newBooleanIntervalIterator(input, opt)
   404  	default:
   405  		panic(fmt.Sprintf("unsupported interval iterator type: %T", input))
   406  	}
   407  }
   408  
   409  // NewInterruptIterator returns an iterator that will stop producing output
   410  // when the passed-in channel is closed.
   411  func NewInterruptIterator(input Iterator, closing <-chan struct{}) Iterator {
   412  	switch input := input.(type) {
   413  	case FloatIterator:
   414  		return newFloatInterruptIterator(input, closing)
   415  	case IntegerIterator:
   416  		return newIntegerInterruptIterator(input, closing)
   417  	case UnsignedIterator:
   418  		return newUnsignedInterruptIterator(input, closing)
   419  	case StringIterator:
   420  		return newStringInterruptIterator(input, closing)
   421  	case BooleanIterator:
   422  		return newBooleanInterruptIterator(input, closing)
   423  	default:
   424  		panic(fmt.Sprintf("unsupported interrupt iterator type: %T", input))
   425  	}
   426  }
   427  
   428  // IteratorScanner is used to scan the results of an iterator into a map.
   429  type IteratorScanner interface {
   430  	// Peek retrieves information about the next point. It returns a timestamp, the name, and the tags.
   431  	Peek() (int64, string, Tags)
   432  
   433  	// ScanAt will take a time, name, and tags and scan the point that matches those into the map.
   434  	ScanAt(ts int64, name string, tags Tags, values map[string]interface{})
   435  
   436  	// Stats returns the IteratorStats from the Iterator.
   437  	Stats() IteratorStats
   438  
   439  	// Err returns an error that was encountered while scanning.
   440  	Err() error
   441  
   442  	io.Closer
   443  }
   444  
   445  // SkipDefault is a sentinel value to tell the IteratorScanner to skip setting the
   446  // default value if none was present. This causes the map to use the previous value
   447  // if it was previously set.
   448  var SkipDefault = interface{}(0)
   449  
   450  // NewIteratorScanner produces an IteratorScanner for the Iterator.
   451  func NewIteratorScanner(input Iterator, keys []influxql.VarRef, defaultValue interface{}) IteratorScanner {
   452  	switch input := input.(type) {
   453  	case FloatIterator:
   454  		return newFloatIteratorScanner(input, keys, defaultValue)
   455  	case IntegerIterator:
   456  		return newIntegerIteratorScanner(input, keys, defaultValue)
   457  	case UnsignedIterator:
   458  		return newUnsignedIteratorScanner(input, keys, defaultValue)
   459  	case StringIterator:
   460  		return newStringIteratorScanner(input, keys, defaultValue)
   461  	case BooleanIterator:
   462  		return newBooleanIteratorScanner(input, keys, defaultValue)
   463  	default:
   464  		panic(fmt.Sprintf("unsupported type for iterator scanner: %T", input))
   465  	}
   466  }
   467  
   468  // DrainIterator reads and discards all points from itr.
   469  func DrainIterator(itr Iterator) {
   470  	defer itr.Close()
   471  	switch itr := itr.(type) {
   472  	case FloatIterator:
   473  		for p, _ := itr.Next(); p != nil; p, _ = itr.Next() {
   474  		}
   475  	case IntegerIterator:
   476  		for p, _ := itr.Next(); p != nil; p, _ = itr.Next() {
   477  		}
   478  	case UnsignedIterator:
   479  		for p, _ := itr.Next(); p != nil; p, _ = itr.Next() {
   480  		}
   481  	case StringIterator:
   482  		for p, _ := itr.Next(); p != nil; p, _ = itr.Next() {
   483  		}
   484  	case BooleanIterator:
   485  		for p, _ := itr.Next(); p != nil; p, _ = itr.Next() {
   486  		}
   487  	default:
   488  		panic(fmt.Sprintf("unsupported iterator type for draining: %T", itr))
   489  	}
   490  }
   491  
   492  // DrainIterators reads and discards all points from itrs.
   493  func DrainIterators(itrs []Iterator) {
   494  	defer Iterators(itrs).Close()
   495  	for {
   496  		var hasData bool
   497  
   498  		for _, itr := range itrs {
   499  			switch itr := itr.(type) {
   500  			case FloatIterator:
   501  				if p, _ := itr.Next(); p != nil {
   502  					hasData = true
   503  				}
   504  			case IntegerIterator:
   505  				if p, _ := itr.Next(); p != nil {
   506  					hasData = true
   507  				}
   508  			case UnsignedIterator:
   509  				if p, _ := itr.Next(); p != nil {
   510  					hasData = true
   511  				}
   512  			case StringIterator:
   513  				if p, _ := itr.Next(); p != nil {
   514  					hasData = true
   515  				}
   516  			case BooleanIterator:
   517  				if p, _ := itr.Next(); p != nil {
   518  					hasData = true
   519  				}
   520  			default:
   521  				panic(fmt.Sprintf("unsupported iterator type for draining: %T", itr))
   522  			}
   523  		}
   524  
   525  		// Exit once all iterators return a nil point.
   526  		if !hasData {
   527  			break
   528  		}
   529  	}
   530  }
   531  
   532  // NewReaderIterator returns an iterator that streams from a reader.
   533  func NewReaderIterator(ctx context.Context, r io.Reader, typ influxql.DataType, stats IteratorStats) Iterator {
   534  	switch typ {
   535  	case influxql.Float:
   536  		return newFloatReaderIterator(ctx, r, stats)
   537  	case influxql.Integer:
   538  		return newIntegerReaderIterator(ctx, r, stats)
   539  	case influxql.Unsigned:
   540  		return newUnsignedReaderIterator(ctx, r, stats)
   541  	case influxql.String:
   542  		return newStringReaderIterator(ctx, r, stats)
   543  	case influxql.Boolean:
   544  		return newBooleanReaderIterator(ctx, r, stats)
   545  	default:
   546  		return &nilFloatReaderIterator{r: r}
   547  	}
   548  }
   549  
   550  // IteratorCreator is an interface to create Iterators.
   551  type IteratorCreator interface {
   552  	// Creates a simple iterator for use in an InfluxQL query.
   553  	CreateIterator(ctx context.Context, source *influxql.Measurement, opt IteratorOptions) (Iterator, error)
   554  
   555  	// Determines the potential cost for creating an iterator.
   556  	IteratorCost(ctx context.Context, source *influxql.Measurement, opt IteratorOptions) (IteratorCost, error)
   557  }
   558  
   559  // IteratorOptions is an object passed to CreateIterator to specify creation options.
   560  type IteratorOptions struct {
   561  	// OrgID is the organization for which this query is being executed.
   562  	OrgID platform.ID
   563  
   564  	// Expression to iterate for.
   565  	// This can be VarRef or a Call.
   566  	Expr influxql.Expr
   567  
   568  	// Auxiliary tags or values to also retrieve for the point.
   569  	Aux []influxql.VarRef
   570  
   571  	// Data sources from which to receive data. This is only used for encoding
   572  	// measurements over RPC and is no longer used in the open source version.
   573  	Sources []influxql.Source
   574  
   575  	// Group by interval and tags.
   576  	Interval   Interval
   577  	Dimensions []string            // The final dimensions of the query (stays the same even in subqueries).
   578  	GroupBy    map[string]struct{} // Dimensions to group points by in intermediate iterators.
   579  	Location   *time.Location
   580  
   581  	// Fill options.
   582  	Fill      influxql.FillOption
   583  	FillValue interface{}
   584  
   585  	// Condition to filter by.
   586  	Condition influxql.Expr
   587  
   588  	// Time range for the iterator.
   589  	StartTime int64
   590  	EndTime   int64
   591  
   592  	// Sorted in time ascending order if true.
   593  	Ascending bool
   594  
   595  	// Limits the number of points per series.
   596  	Limit, Offset int
   597  
   598  	// Limits the number of series.
   599  	SLimit, SOffset int
   600  
   601  	// Removes the measurement name. Useful for meta queries.
   602  	StripName bool
   603  
   604  	// Removes duplicate rows from raw queries.
   605  	Dedupe bool
   606  
   607  	// Determines if this is a query for raw data or an aggregate/selector.
   608  	Ordered bool
   609  
   610  	// Limits on the creation of iterators.
   611  	MaxSeriesN int
   612  
   613  	// If this channel is set and is closed, the iterator should try to exit
   614  	// and close as soon as possible.
   615  	InterruptCh <-chan struct{}
   616  
   617  	// Authorizer can limit access to data
   618  	Authorizer Authorizer
   619  }
   620  
   621  // newIteratorOptionsStmt creates the iterator options from stmt.
   622  func newIteratorOptionsStmt(stmt *influxql.SelectStatement, sopt SelectOptions) (opt IteratorOptions, err error) {
   623  	// Determine time range from the condition.
   624  	valuer := &influxql.NowValuer{Location: stmt.Location}
   625  	condition, timeRange, err := influxql.ConditionExpr(stmt.Condition, valuer)
   626  	if err != nil {
   627  		return IteratorOptions{}, err
   628  	}
   629  
   630  	if !timeRange.Min.IsZero() {
   631  		opt.StartTime = timeRange.Min.UnixNano()
   632  	} else {
   633  		opt.StartTime = influxql.MinTime
   634  	}
   635  	if !timeRange.Max.IsZero() {
   636  		opt.EndTime = timeRange.Max.UnixNano()
   637  	} else {
   638  		opt.EndTime = influxql.MaxTime
   639  	}
   640  	opt.Location = stmt.Location
   641  
   642  	// Determine group by interval.
   643  	interval, err := stmt.GroupByInterval()
   644  	if err != nil {
   645  		return opt, err
   646  	}
   647  	// Set duration to zero if a negative interval has been used.
   648  	if interval < 0 {
   649  		interval = 0
   650  	} else if interval > 0 {
   651  		opt.Interval.Offset, err = stmt.GroupByOffset()
   652  		if err != nil {
   653  			return opt, err
   654  		}
   655  	}
   656  	opt.Interval.Duration = interval
   657  
   658  	// Always request an ordered output for the top level iterators.
   659  	// The emitter will always emit points as ordered.
   660  	opt.Ordered = true
   661  
   662  	// Determine dimensions.
   663  	opt.GroupBy = make(map[string]struct{}, len(opt.Dimensions))
   664  	for _, d := range stmt.Dimensions {
   665  		if d, ok := d.Expr.(*influxql.VarRef); ok {
   666  			opt.Dimensions = append(opt.Dimensions, d.Val)
   667  			opt.GroupBy[d.Val] = struct{}{}
   668  		}
   669  	}
   670  
   671  	opt.Condition = condition
   672  	opt.Ascending = stmt.TimeAscending()
   673  	opt.Dedupe = stmt.Dedupe
   674  	opt.StripName = stmt.StripName
   675  
   676  	opt.Fill, opt.FillValue = stmt.Fill, stmt.FillValue
   677  	if opt.Fill == influxql.NullFill && stmt.Target != nil {
   678  		// Set the fill option to none if a target has been given.
   679  		// Null values will get ignored when being written to the target
   680  		// so fill(null) wouldn't write any null values to begin with.
   681  		opt.Fill = influxql.NoFill
   682  	}
   683  	opt.Limit, opt.Offset = stmt.Limit, stmt.Offset
   684  	opt.SLimit, opt.SOffset = stmt.SLimit, stmt.SOffset
   685  	opt.MaxSeriesN = sopt.MaxSeriesN
   686  	opt.OrgID = sopt.OrgID
   687  
   688  	return opt, nil
   689  }
   690  
   691  func newIteratorOptionsSubstatement(ctx context.Context, stmt *influxql.SelectStatement, opt IteratorOptions) (IteratorOptions, error) {
   692  	subOpt, err := newIteratorOptionsStmt(stmt, SelectOptions{
   693  		OrgID:      opt.OrgID,
   694  		MaxSeriesN: opt.MaxSeriesN,
   695  	})
   696  	if err != nil {
   697  		return IteratorOptions{}, err
   698  	}
   699  
   700  	if subOpt.StartTime < opt.StartTime {
   701  		subOpt.StartTime = opt.StartTime
   702  	}
   703  	if subOpt.EndTime > opt.EndTime {
   704  		subOpt.EndTime = opt.EndTime
   705  	}
   706  	if !subOpt.Interval.IsZero() && subOpt.EndTime == influxql.MaxTime {
   707  		if now := ctx.Value(nowKey); now != nil {
   708  			subOpt.EndTime = now.(time.Time).UnixNano()
   709  		}
   710  	}
   711  	// Propagate the dimensions to the inner subquery.
   712  	subOpt.Dimensions = opt.Dimensions
   713  	for d := range opt.GroupBy {
   714  		subOpt.GroupBy[d] = struct{}{}
   715  	}
   716  	subOpt.InterruptCh = opt.InterruptCh
   717  
   718  	// Extract the time range and condition from the condition.
   719  	valuer := &influxql.NowValuer{Location: stmt.Location}
   720  	cond, t, err := influxql.ConditionExpr(stmt.Condition, valuer)
   721  	if err != nil {
   722  		return IteratorOptions{}, err
   723  	}
   724  	subOpt.Condition = cond
   725  	// If the time range is more constrained, use it instead. A less constrained time
   726  	// range should be ignored.
   727  	if !t.Min.IsZero() && t.MinTimeNano() > opt.StartTime {
   728  		subOpt.StartTime = t.MinTimeNano()
   729  	}
   730  	if !t.Max.IsZero() && t.MaxTimeNano() < opt.EndTime {
   731  		subOpt.EndTime = t.MaxTimeNano()
   732  	}
   733  
   734  	// Propagate the SLIMIT and SOFFSET from the outer query.
   735  	subOpt.SLimit += opt.SLimit
   736  	subOpt.SOffset += opt.SOffset
   737  
   738  	// Propagate the ordering from the parent query.
   739  	subOpt.Ascending = opt.Ascending
   740  
   741  	// If the inner query uses a null fill option and is not a raw query,
   742  	// switch it to none so we don't hit an unnecessary penalty from the
   743  	// fill iterator. Null values will end up getting stripped by an outer
   744  	// query anyway so there's no point in having them here. We still need
   745  	// all other types of fill iterators because they can affect the result
   746  	// of the outer query. We also do not do this for raw queries because
   747  	// there is no fill iterator for them and fill(none) doesn't work with
   748  	// raw queries.
   749  	if !stmt.IsRawQuery && subOpt.Fill == influxql.NullFill {
   750  		subOpt.Fill = influxql.NoFill
   751  	}
   752  
   753  	// Inherit the ordering method from the outer query.
   754  	subOpt.Ordered = opt.Ordered
   755  
   756  	// If there is no interval for this subquery, but the outer query has an
   757  	// interval, inherit the parent interval.
   758  	interval, err := stmt.GroupByInterval()
   759  	if err != nil {
   760  		return IteratorOptions{}, err
   761  	} else if interval == 0 {
   762  		subOpt.Interval = opt.Interval
   763  	}
   764  	return subOpt, nil
   765  }
   766  
   767  // MergeSorted returns true if the options require a sorted merge.
   768  func (opt IteratorOptions) MergeSorted() bool {
   769  	return opt.Ordered
   770  }
   771  
   772  // SeekTime returns the time the iterator should start from.
   773  // For ascending iterators this is the start time, for descending iterators it's the end time.
   774  func (opt IteratorOptions) SeekTime() int64 {
   775  	if opt.Ascending {
   776  		return opt.StartTime
   777  	}
   778  	return opt.EndTime
   779  }
   780  
   781  // StopTime returns the time the iterator should end at.
   782  // For ascending iterators this is the end time, for descending iterators it's the start time.
   783  func (opt IteratorOptions) StopTime() int64 {
   784  	if opt.Ascending {
   785  		return opt.EndTime
   786  	}
   787  	return opt.StartTime
   788  }
   789  
   790  // Window returns the time window [start,end) that t falls within.
   791  func (opt IteratorOptions) Window(t int64) (start, end int64) {
   792  	if opt.Interval.IsZero() {
   793  		return opt.StartTime, opt.EndTime + 1
   794  	}
   795  
   796  	// Subtract the offset to the time so we calculate the correct base interval.
   797  	t -= int64(opt.Interval.Offset)
   798  
   799  	// Retrieve the zone offset for the start time.
   800  	var zone int64
   801  	if opt.Location != nil {
   802  		_, zone = opt.Zone(t)
   803  	}
   804  
   805  	// Truncate time by duration.
   806  	dt := (t + zone) % int64(opt.Interval.Duration)
   807  	if dt < 0 {
   808  		// Negative modulo rounds up instead of down, so offset
   809  		// with the duration.
   810  		dt += int64(opt.Interval.Duration)
   811  	}
   812  
   813  	// Find the start time.
   814  	if influxql.MinTime+dt >= t {
   815  		start = influxql.MinTime
   816  	} else {
   817  		start = t - dt
   818  	}
   819  
   820  	start += int64(opt.Interval.Offset)
   821  
   822  	// Look for the start offset again because the first time may have been
   823  	// after the offset switch. Now that we are at midnight in UTC, we can
   824  	// lookup the zone offset again to get the real starting offset.
   825  	if opt.Location != nil {
   826  		_, startOffset := opt.Zone(start)
   827  		// Do not adjust the offset if the offset change is greater than or
   828  		// equal to the duration.
   829  		if o := zone - startOffset; o != 0 && abs(o) < int64(opt.Interval.Duration) {
   830  			start += o
   831  		}
   832  	}
   833  
   834  	// Find the end time.
   835  	if dt := int64(opt.Interval.Duration) - dt; influxql.MaxTime-dt <= t {
   836  		end = influxql.MaxTime
   837  	} else {
   838  		end = t + dt
   839  	}
   840  
   841  	// Retrieve the zone offset for the end time.
   842  	if opt.Location != nil {
   843  		_, endOffset := opt.Zone(end)
   844  		// Adjust the end time if the offset is different from the start offset.
   845  		// Only apply the offset if it is smaller than the duration.
   846  		// This prevents going back in time and creating time windows
   847  		// that don't make any sense.
   848  		if o := zone - endOffset; o != 0 && abs(o) < int64(opt.Interval.Duration) {
   849  			// If the offset is greater than 0, that means we are adding time.
   850  			// Added time goes into the previous interval because the clocks
   851  			// move backwards. If the offset is less than 0, then we are skipping
   852  			// time. Skipped time comes after the switch so if we have a time
   853  			// interval that lands on the switch, it comes from the next
   854  			// interval and not the current one. For this reason, we need to know
   855  			// when the actual switch happens by seeing if the time switch is within
   856  			// the current interval. We calculate the zone offset with the offset
   857  			// and see if the value is the same. If it is, we apply the
   858  			// offset.
   859  			if o > 0 {
   860  				end += o
   861  			} else if _, z := opt.Zone(end + o); z == endOffset {
   862  				end += o
   863  			}
   864  		}
   865  	}
   866  	end += int64(opt.Interval.Offset)
   867  	return
   868  }
   869  
   870  // DerivativeInterval returns the time interval for the derivative function.
   871  func (opt IteratorOptions) DerivativeInterval() Interval {
   872  	// Use the interval on the derivative() call, if specified.
   873  	if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 {
   874  		return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val}
   875  	}
   876  
   877  	// Otherwise use the group by interval, if specified.
   878  	if opt.Interval.Duration > 0 {
   879  		return Interval{Duration: opt.Interval.Duration}
   880  	}
   881  
   882  	return Interval{Duration: time.Second}
   883  }
   884  
   885  // ElapsedInterval returns the time interval for the elapsed function.
   886  func (opt IteratorOptions) ElapsedInterval() Interval {
   887  	// Use the interval on the elapsed() call, if specified.
   888  	if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 {
   889  		return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val}
   890  	}
   891  
   892  	return Interval{Duration: time.Nanosecond}
   893  }
   894  
   895  // IntegralInterval returns the time interval for the integral function.
   896  func (opt IteratorOptions) IntegralInterval() Interval {
   897  	// Use the interval on the integral() call, if specified.
   898  	if expr, ok := opt.Expr.(*influxql.Call); ok && len(expr.Args) == 2 {
   899  		return Interval{Duration: expr.Args[1].(*influxql.DurationLiteral).Val}
   900  	}
   901  
   902  	return Interval{Duration: time.Second}
   903  }
   904  
   905  // GetDimensions retrieves the dimensions for this query.
   906  func (opt IteratorOptions) GetDimensions() []string {
   907  	if len(opt.GroupBy) > 0 {
   908  		dimensions := make([]string, 0, len(opt.GroupBy))
   909  		for dim := range opt.GroupBy {
   910  			dimensions = append(dimensions, dim)
   911  		}
   912  		return dimensions
   913  	}
   914  	return opt.Dimensions
   915  }
   916  
   917  // Zone returns the zone information for the given time. The offset is in nanoseconds.
   918  func (opt *IteratorOptions) Zone(ns int64) (string, int64) {
   919  	if opt.Location == nil {
   920  		return "", 0
   921  	}
   922  
   923  	t := time.Unix(0, ns).In(opt.Location)
   924  	name, offset := t.Zone()
   925  	return name, secToNs * int64(offset)
   926  }
   927  
   928  // MarshalBinary encodes opt into a binary format.
   929  func (opt *IteratorOptions) MarshalBinary() ([]byte, error) {
   930  	return proto.Marshal(encodeIteratorOptions(opt))
   931  }
   932  
   933  // UnmarshalBinary decodes from a binary format in to opt.
   934  func (opt *IteratorOptions) UnmarshalBinary(buf []byte) error {
   935  	var pb internal.IteratorOptions
   936  	if err := proto.Unmarshal(buf, &pb); err != nil {
   937  		return err
   938  	}
   939  
   940  	other, err := decodeIteratorOptions(&pb)
   941  	if err != nil {
   942  		return err
   943  	}
   944  	*opt = *other
   945  
   946  	return nil
   947  }
   948  
   949  func encodeIteratorOptions(opt *IteratorOptions) *internal.IteratorOptions {
   950  	pb := &internal.IteratorOptions{
   951  		Interval:   encodeInterval(opt.Interval),
   952  		Dimensions: opt.Dimensions,
   953  		Fill:       proto.Int32(int32(opt.Fill)),
   954  		StartTime:  proto.Int64(opt.StartTime),
   955  		EndTime:    proto.Int64(opt.EndTime),
   956  		Ascending:  proto.Bool(opt.Ascending),
   957  		Limit:      proto.Int64(int64(opt.Limit)),
   958  		Offset:     proto.Int64(int64(opt.Offset)),
   959  		SLimit:     proto.Int64(int64(opt.SLimit)),
   960  		SOffset:    proto.Int64(int64(opt.SOffset)),
   961  		StripName:  proto.Bool(opt.StripName),
   962  		Dedupe:     proto.Bool(opt.Dedupe),
   963  		MaxSeriesN: proto.Int64(int64(opt.MaxSeriesN)),
   964  		Ordered:    proto.Bool(opt.Ordered),
   965  	}
   966  
   967  	// Set expression, if set.
   968  	if opt.Expr != nil {
   969  		pb.Expr = proto.String(opt.Expr.String())
   970  	}
   971  
   972  	// Set the location, if set.
   973  	if opt.Location != nil {
   974  		pb.Location = proto.String(opt.Location.String())
   975  	}
   976  
   977  	// Convert and encode aux fields as variable references.
   978  	if opt.Aux != nil {
   979  		pb.Fields = make([]*internal.VarRef, len(opt.Aux))
   980  		pb.Aux = make([]string, len(opt.Aux))
   981  		for i, ref := range opt.Aux {
   982  			pb.Fields[i] = encodeVarRef(ref)
   983  			pb.Aux[i] = ref.Val
   984  		}
   985  	}
   986  
   987  	// Encode group by dimensions from a map.
   988  	if opt.GroupBy != nil {
   989  		dimensions := make([]string, 0, len(opt.GroupBy))
   990  		for dim := range opt.GroupBy {
   991  			dimensions = append(dimensions, dim)
   992  		}
   993  		pb.GroupBy = dimensions
   994  	}
   995  
   996  	// Convert and encode sources to measurements.
   997  	if opt.Sources != nil {
   998  		sources := make([]*internal.Measurement, len(opt.Sources))
   999  		for i, source := range opt.Sources {
  1000  			mm := source.(*influxql.Measurement)
  1001  			sources[i] = encodeMeasurement(mm)
  1002  		}
  1003  		pb.Sources = sources
  1004  	}
  1005  
  1006  	// Fill value can only be a number. Set it if available.
  1007  	if v, ok := opt.FillValue.(float64); ok {
  1008  		pb.FillValue = proto.Float64(v)
  1009  	}
  1010  
  1011  	// Set condition, if set.
  1012  	if opt.Condition != nil {
  1013  		pb.Condition = proto.String(opt.Condition.String())
  1014  	}
  1015  
  1016  	return pb
  1017  }
  1018  
  1019  func decodeIteratorOptions(pb *internal.IteratorOptions) (*IteratorOptions, error) {
  1020  	opt := &IteratorOptions{
  1021  		Interval:   decodeInterval(pb.GetInterval()),
  1022  		Dimensions: pb.GetDimensions(),
  1023  		Fill:       influxql.FillOption(pb.GetFill()),
  1024  		StartTime:  pb.GetStartTime(),
  1025  		EndTime:    pb.GetEndTime(),
  1026  		Ascending:  pb.GetAscending(),
  1027  		Limit:      int(pb.GetLimit()),
  1028  		Offset:     int(pb.GetOffset()),
  1029  		SLimit:     int(pb.GetSLimit()),
  1030  		SOffset:    int(pb.GetSOffset()),
  1031  		StripName:  pb.GetStripName(),
  1032  		Dedupe:     pb.GetDedupe(),
  1033  		MaxSeriesN: int(pb.GetMaxSeriesN()),
  1034  		Ordered:    pb.GetOrdered(),
  1035  	}
  1036  
  1037  	// Set expression, if set.
  1038  	if pb.Expr != nil {
  1039  		expr, err := influxql.ParseExpr(pb.GetExpr())
  1040  		if err != nil {
  1041  			return nil, err
  1042  		}
  1043  		opt.Expr = expr
  1044  	}
  1045  
  1046  	if pb.Location != nil {
  1047  		loc, err := time.LoadLocation(pb.GetLocation())
  1048  		if err != nil {
  1049  			return nil, err
  1050  		}
  1051  		opt.Location = loc
  1052  	}
  1053  
  1054  	// Convert and decode variable references.
  1055  	if fields := pb.GetFields(); fields != nil {
  1056  		opt.Aux = make([]influxql.VarRef, len(fields))
  1057  		for i, ref := range fields {
  1058  			opt.Aux[i] = decodeVarRef(ref)
  1059  		}
  1060  	} else if aux := pb.GetAux(); aux != nil {
  1061  		opt.Aux = make([]influxql.VarRef, len(aux))
  1062  		for i, name := range aux {
  1063  			opt.Aux[i] = influxql.VarRef{Val: name}
  1064  		}
  1065  	}
  1066  
  1067  	// Convert and decode sources to measurements.
  1068  	if pb.Sources != nil {
  1069  		sources := make([]influxql.Source, len(pb.GetSources()))
  1070  		for i, source := range pb.GetSources() {
  1071  			mm, err := decodeMeasurement(source)
  1072  			if err != nil {
  1073  				return nil, err
  1074  			}
  1075  			sources[i] = mm
  1076  		}
  1077  		opt.Sources = sources
  1078  	}
  1079  
  1080  	// Convert group by dimensions to a map.
  1081  	if pb.GroupBy != nil {
  1082  		dimensions := make(map[string]struct{}, len(pb.GroupBy))
  1083  		for _, dim := range pb.GetGroupBy() {
  1084  			dimensions[dim] = struct{}{}
  1085  		}
  1086  		opt.GroupBy = dimensions
  1087  	}
  1088  
  1089  	// Set the fill value, if set.
  1090  	if pb.FillValue != nil {
  1091  		opt.FillValue = pb.GetFillValue()
  1092  	}
  1093  
  1094  	// Set condition, if set.
  1095  	if pb.Condition != nil {
  1096  		expr, err := influxql.ParseExpr(pb.GetCondition())
  1097  		if err != nil {
  1098  			return nil, err
  1099  		}
  1100  		opt.Condition = expr
  1101  	}
  1102  
  1103  	return opt, nil
  1104  }
  1105  
  1106  func encodeMeasurement(mm *influxql.Measurement) *internal.Measurement {
  1107  	pb := &internal.Measurement{
  1108  		Database:        proto.String(mm.Database),
  1109  		RetentionPolicy: proto.String(mm.RetentionPolicy),
  1110  		Name:            proto.String(mm.Name),
  1111  		SystemIterator:  proto.String(mm.SystemIterator),
  1112  		IsTarget:        proto.Bool(mm.IsTarget),
  1113  	}
  1114  	if mm.Regex != nil {
  1115  		pb.Regex = proto.String(mm.Regex.Val.String())
  1116  	}
  1117  	return pb
  1118  }
  1119  
  1120  func decodeMeasurement(pb *internal.Measurement) (*influxql.Measurement, error) {
  1121  	mm := &influxql.Measurement{
  1122  		Database:        pb.GetDatabase(),
  1123  		RetentionPolicy: pb.GetRetentionPolicy(),
  1124  		Name:            pb.GetName(),
  1125  		SystemIterator:  pb.GetSystemIterator(),
  1126  		IsTarget:        pb.GetIsTarget(),
  1127  	}
  1128  
  1129  	if pb.Regex != nil {
  1130  		regex, err := regexp.Compile(pb.GetRegex())
  1131  		if err != nil {
  1132  			return nil, fmt.Errorf("invalid binary measurement regex: value=%q, err=%s", pb.GetRegex(), err)
  1133  		}
  1134  		mm.Regex = &influxql.RegexLiteral{Val: regex}
  1135  	}
  1136  
  1137  	return mm, nil
  1138  }
  1139  
  1140  // Interval represents a repeating interval for a query.
  1141  type Interval struct {
  1142  	Duration time.Duration
  1143  	Offset   time.Duration
  1144  }
  1145  
  1146  // IsZero returns true if the interval has no duration.
  1147  func (i Interval) IsZero() bool { return i.Duration == 0 }
  1148  
  1149  func encodeInterval(i Interval) *internal.Interval {
  1150  	return &internal.Interval{
  1151  		Duration: proto.Int64(i.Duration.Nanoseconds()),
  1152  		Offset:   proto.Int64(i.Offset.Nanoseconds()),
  1153  	}
  1154  }
  1155  
  1156  func decodeInterval(pb *internal.Interval) Interval {
  1157  	return Interval{
  1158  		Duration: time.Duration(pb.GetDuration()),
  1159  		Offset:   time.Duration(pb.GetOffset()),
  1160  	}
  1161  }
  1162  
  1163  func encodeVarRef(ref influxql.VarRef) *internal.VarRef {
  1164  	return &internal.VarRef{
  1165  		Val:  proto.String(ref.Val),
  1166  		Type: proto.Int32(int32(ref.Type)),
  1167  	}
  1168  }
  1169  
  1170  func decodeVarRef(pb *internal.VarRef) influxql.VarRef {
  1171  	return influxql.VarRef{
  1172  		Val:  pb.GetVal(),
  1173  		Type: influxql.DataType(pb.GetType()),
  1174  	}
  1175  }
  1176  
  1177  type nilFloatIterator struct{}
  1178  
  1179  func (*nilFloatIterator) Stats() IteratorStats       { return IteratorStats{} }
  1180  func (*nilFloatIterator) Close() error               { return nil }
  1181  func (*nilFloatIterator) Next() (*FloatPoint, error) { return nil, nil }
  1182  
  1183  type nilFloatReaderIterator struct {
  1184  	r io.Reader
  1185  }
  1186  
  1187  func (*nilFloatReaderIterator) Stats() IteratorStats { return IteratorStats{} }
  1188  func (itr *nilFloatReaderIterator) Close() error {
  1189  	if r, ok := itr.r.(io.ReadCloser); ok {
  1190  		itr.r = nil
  1191  		return r.Close()
  1192  	}
  1193  	return nil
  1194  }
  1195  func (*nilFloatReaderIterator) Next() (*FloatPoint, error) { return nil, nil }
  1196  
  1197  // IteratorStats represents statistics about an iterator.
  1198  // Some statistics are available immediately upon iterator creation while
  1199  // some are derived as the iterator processes data.
  1200  type IteratorStats struct {
  1201  	SeriesN int // series represented
  1202  	PointN  int // points returned
  1203  }
  1204  
  1205  // Add aggregates fields from s and other together. Overwrites s.
  1206  func (s *IteratorStats) Add(other IteratorStats) {
  1207  	s.SeriesN += other.SeriesN
  1208  	s.PointN += other.PointN
  1209  }
  1210  
  1211  func encodeIteratorStats(stats *IteratorStats) *internal.IteratorStats {
  1212  	return &internal.IteratorStats{
  1213  		SeriesN: proto.Int64(int64(stats.SeriesN)),
  1214  		PointN:  proto.Int64(int64(stats.PointN)),
  1215  	}
  1216  }
  1217  
  1218  func decodeIteratorStats(pb *internal.IteratorStats) IteratorStats {
  1219  	return IteratorStats{
  1220  		SeriesN: int(pb.GetSeriesN()),
  1221  		PointN:  int(pb.GetPointN()),
  1222  	}
  1223  }
  1224  
  1225  // IteratorCost contains statistics retrieved for explaining what potential
  1226  // cost may be incurred by instantiating an iterator.
  1227  type IteratorCost struct {
  1228  	// The total number of shards that are touched by this query.
  1229  	NumShards int64
  1230  
  1231  	// The total number of non-unique series that are accessed by this query.
  1232  	// This number matches the number of cursors created by the query since
  1233  	// one cursor is created for every series.
  1234  	NumSeries int64
  1235  
  1236  	// CachedValues returns the number of cached values that may be read by this
  1237  	// query.
  1238  	CachedValues int64
  1239  
  1240  	// The total number of non-unique files that may be accessed by this query.
  1241  	// This will count the number of files accessed by each series so files
  1242  	// will likely be double counted.
  1243  	NumFiles int64
  1244  
  1245  	// The number of blocks that had the potential to be accessed.
  1246  	BlocksRead int64
  1247  
  1248  	// The amount of data that can be potentially read.
  1249  	BlockSize int64
  1250  }
  1251  
  1252  // Combine combines the results of two IteratorCost structures into one.
  1253  func (c IteratorCost) Combine(other IteratorCost) IteratorCost {
  1254  	return IteratorCost{
  1255  		NumShards:    c.NumShards + other.NumShards,
  1256  		NumSeries:    c.NumSeries + other.NumSeries,
  1257  		CachedValues: c.CachedValues + other.CachedValues,
  1258  		NumFiles:     c.NumFiles + other.NumFiles,
  1259  		BlocksRead:   c.BlocksRead + other.BlocksRead,
  1260  		BlockSize:    c.BlockSize + other.BlockSize,
  1261  	}
  1262  }
  1263  
  1264  // floatFastDedupeIterator outputs unique points where the point has a single aux field.
  1265  type floatFastDedupeIterator struct {
  1266  	input FloatIterator
  1267  	m     map[fastDedupeKey]struct{} // lookup of points already sent
  1268  }
  1269  
  1270  // newFloatFastDedupeIterator returns a new instance of floatFastDedupeIterator.
  1271  func newFloatFastDedupeIterator(input FloatIterator) *floatFastDedupeIterator {
  1272  	return &floatFastDedupeIterator{
  1273  		input: input,
  1274  		m:     make(map[fastDedupeKey]struct{}),
  1275  	}
  1276  }
  1277  
  1278  // Stats returns stats from the input iterator.
  1279  func (itr *floatFastDedupeIterator) Stats() IteratorStats { return itr.input.Stats() }
  1280  
  1281  // Close closes the iterator and all child iterators.
  1282  func (itr *floatFastDedupeIterator) Close() error { return itr.input.Close() }
  1283  
  1284  // Next returns the next unique point from the input iterator.
  1285  func (itr *floatFastDedupeIterator) Next() (*FloatPoint, error) {
  1286  	for {
  1287  		// Read next point.
  1288  		// Skip if there are not any aux fields.
  1289  		p, err := itr.input.Next()
  1290  		if p == nil || err != nil {
  1291  			return nil, err
  1292  		} else if len(p.Aux) == 0 {
  1293  			continue
  1294  		}
  1295  
  1296  		// If the point has already been output then move to the next point.
  1297  		key := fastDedupeKey{name: p.Name}
  1298  		key.values[0] = p.Aux[0]
  1299  		if len(p.Aux) > 1 {
  1300  			key.values[1] = p.Aux[1]
  1301  		}
  1302  		if _, ok := itr.m[key]; ok {
  1303  			continue
  1304  		}
  1305  
  1306  		// Otherwise mark it as emitted and return point.
  1307  		itr.m[key] = struct{}{}
  1308  		return p, nil
  1309  	}
  1310  }
  1311  
  1312  type fastDedupeKey struct {
  1313  	name   string
  1314  	values [2]interface{}
  1315  }
  1316  
  1317  func abs(v int64) int64 {
  1318  	sign := v >> 63
  1319  	return (v ^ sign) - sign
  1320  }
  1321  
  1322  // IteratorEncoder is an encoder for encoding an iterator's points to w.
  1323  type IteratorEncoder struct {
  1324  	w io.Writer
  1325  
  1326  	// Frequency with which stats are emitted.
  1327  	StatsInterval time.Duration
  1328  }
  1329  
  1330  // NewIteratorEncoder encodes an iterator's points to w.
  1331  func NewIteratorEncoder(w io.Writer) *IteratorEncoder {
  1332  	return &IteratorEncoder{
  1333  		w: w,
  1334  
  1335  		StatsInterval: DefaultStatsInterval,
  1336  	}
  1337  }
  1338  
  1339  // EncodeIterator encodes and writes all of itr's points to the underlying writer.
  1340  func (enc *IteratorEncoder) EncodeIterator(itr Iterator) error {
  1341  	switch itr := itr.(type) {
  1342  	case FloatIterator:
  1343  		return enc.encodeFloatIterator(itr)
  1344  	case IntegerIterator:
  1345  		return enc.encodeIntegerIterator(itr)
  1346  	case StringIterator:
  1347  		return enc.encodeStringIterator(itr)
  1348  	case BooleanIterator:
  1349  		return enc.encodeBooleanIterator(itr)
  1350  	default:
  1351  		panic(fmt.Sprintf("unsupported iterator for encoder: %T", itr))
  1352  	}
  1353  }
  1354  
  1355  // encode a stats object in the point stream.
  1356  func (enc *IteratorEncoder) encodeStats(stats IteratorStats) error {
  1357  	buf, err := proto.Marshal(&internal.Point{
  1358  		Name: proto.String(""),
  1359  		Tags: proto.String(""),
  1360  		Time: proto.Int64(0),
  1361  		Nil:  proto.Bool(false),
  1362  
  1363  		Stats: encodeIteratorStats(&stats),
  1364  	})
  1365  	if err != nil {
  1366  		return err
  1367  	}
  1368  
  1369  	if err = binary.Write(enc.w, binary.BigEndian, uint32(len(buf))); err != nil {
  1370  		return err
  1371  	}
  1372  	if _, err = enc.w.Write(buf); err != nil {
  1373  		return err
  1374  	}
  1375  	return nil
  1376  }