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

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/influxdata/influxdb/v2/models"
    11  	"github.com/influxdata/influxql"
    12  )
    13  
    14  // CompileOptions are the customization options for the compiler.
    15  type CompileOptions struct {
    16  	Now time.Time
    17  }
    18  
    19  // Statement is a compiled query statement.
    20  type Statement interface {
    21  	// Prepare prepares the statement by mapping shards and finishing the creation
    22  	// of the query plan.
    23  	Prepare(ctx context.Context, shardMapper ShardMapper, opt SelectOptions) (PreparedStatement, error)
    24  }
    25  
    26  // compiledStatement represents a select statement that has undergone some initial processing to
    27  // determine if it is valid and to have some initial modifications done on the AST.
    28  type compiledStatement struct {
    29  	// Condition is the condition used for accessing data.
    30  	Condition influxql.Expr
    31  
    32  	// TimeRange is the TimeRange for selecting data.
    33  	TimeRange influxql.TimeRange
    34  
    35  	// Interval holds the time grouping interval.
    36  	Interval Interval
    37  
    38  	// InheritedInterval marks if the interval was inherited by a parent.
    39  	// If this is set, then an interval that was inherited will not cause
    40  	// a query that shouldn't have an interval to fail.
    41  	InheritedInterval bool
    42  
    43  	// ExtraIntervals is the number of extra intervals that will be read in addition
    44  	// to the TimeRange. It is a multiple of Interval and only applies to queries that
    45  	// have an Interval. It is used to extend the TimeRange of the mapped shards to
    46  	// include additional non-emitted intervals used by derivative and other functions.
    47  	// It will be set to the highest number of extra intervals that need to be read even
    48  	// if it doesn't apply to all functions. The number will always be positive.
    49  	// This value may be set to a non-zero value even if there is no interval for the
    50  	// compiled query.
    51  	ExtraIntervals int
    52  
    53  	// Ascending is true if the time ordering is ascending.
    54  	Ascending bool
    55  
    56  	// FunctionCalls holds a reference to the call expression of every function
    57  	// call that has been encountered.
    58  	FunctionCalls []*influxql.Call
    59  
    60  	// OnlySelectors is set to true when there are no aggregate functions.
    61  	OnlySelectors bool
    62  
    63  	// HasDistinct is set when the distinct() function is encountered.
    64  	HasDistinct bool
    65  
    66  	// FillOption contains the fill option for aggregates.
    67  	FillOption influxql.FillOption
    68  
    69  	// TopBottomFunction is set to top or bottom when one of those functions are
    70  	// used in the statement.
    71  	TopBottomFunction string
    72  
    73  	// HasAuxiliaryFields is true when the function requires auxiliary fields.
    74  	HasAuxiliaryFields bool
    75  
    76  	// Fields holds all of the fields that will be used.
    77  	Fields []*compiledField
    78  
    79  	// TimeFieldName stores the name of the time field's column.
    80  	// The column names generated by the compiler will not conflict with
    81  	// this name.
    82  	TimeFieldName string
    83  
    84  	// Limit is the number of rows per series this query should be limited to.
    85  	Limit int
    86  
    87  	// HasTarget is true if this query is being written into a target.
    88  	HasTarget bool
    89  
    90  	// Options holds the configured compiler options.
    91  	Options CompileOptions
    92  
    93  	stmt *influxql.SelectStatement
    94  }
    95  
    96  func newCompiler(opt CompileOptions) *compiledStatement {
    97  	if opt.Now.IsZero() {
    98  		opt.Now = time.Now().UTC()
    99  	}
   100  	return &compiledStatement{
   101  		OnlySelectors: true,
   102  		TimeFieldName: "time",
   103  		Options:       opt,
   104  	}
   105  }
   106  
   107  func Compile(stmt *influxql.SelectStatement, opt CompileOptions) (_ Statement, err error) {
   108  	c := newCompiler(opt)
   109  	c.stmt = stmt.Clone()
   110  	if err := c.preprocess(c.stmt); err != nil {
   111  		return nil, err
   112  	}
   113  	if err := c.compile(c.stmt); err != nil {
   114  		return nil, err
   115  	}
   116  	c.stmt.TimeAlias = c.TimeFieldName
   117  	c.stmt.Condition = c.Condition
   118  
   119  	defer func() {
   120  		if e := recover(); e != nil && err == nil {
   121  			var ok bool
   122  			err, ok = e.(error)
   123  			if !ok {
   124  				err = fmt.Errorf("panic: %v", e)
   125  			}
   126  			err = fmt.Errorf("likely malformed statement, unable to rewrite: %w", err)
   127  		}
   128  	}()
   129  
   130  	// Convert DISTINCT into a call.
   131  	c.stmt.RewriteDistinct()
   132  
   133  	// Remove "time" from fields list.
   134  	c.stmt.RewriteTimeFields()
   135  
   136  	// Rewrite any regex conditions that could make use of the index.
   137  	c.stmt.RewriteRegexConditions()
   138  	return c, nil
   139  }
   140  
   141  // preprocess retrieves and records the global attributes of the current statement.
   142  func (c *compiledStatement) preprocess(stmt *influxql.SelectStatement) error {
   143  	c.Ascending = stmt.TimeAscending()
   144  	c.Limit = stmt.Limit
   145  	c.HasTarget = stmt.Target != nil
   146  
   147  	valuer := influxql.NowValuer{Now: c.Options.Now, Location: stmt.Location}
   148  	cond, t, err := influxql.ConditionExpr(stmt.Condition, &valuer)
   149  	if err != nil {
   150  		return err
   151  	}
   152  	// Verify that the condition is actually ok to use.
   153  	if err := c.validateCondition(cond); err != nil {
   154  		return err
   155  	}
   156  	c.Condition = cond
   157  	c.TimeRange = t
   158  
   159  	// Read the dimensions of the query, validate them, and retrieve the interval
   160  	// if it exists.
   161  	if err := c.compileDimensions(stmt); err != nil {
   162  		return err
   163  	}
   164  
   165  	// Retrieve the fill option for the statement.
   166  	c.FillOption = stmt.Fill
   167  
   168  	// Resolve the min and max times now that we know if there is an interval or not.
   169  	if c.TimeRange.Min.IsZero() {
   170  		c.TimeRange.Min = time.Unix(0, influxql.MinTime).UTC()
   171  	}
   172  	if c.TimeRange.Max.IsZero() {
   173  		// If the interval is non-zero, then we have an aggregate query and
   174  		// need to limit the maximum time to now() for backwards compatibility
   175  		// and usability.
   176  		if !c.Interval.IsZero() {
   177  			c.TimeRange.Max = c.Options.Now
   178  		} else {
   179  			c.TimeRange.Max = time.Unix(0, influxql.MaxTime).UTC()
   180  		}
   181  	}
   182  	return nil
   183  }
   184  
   185  func (c *compiledStatement) compile(stmt *influxql.SelectStatement) error {
   186  	if err := c.compileFields(stmt); err != nil {
   187  		return err
   188  	}
   189  	if err := c.validateFields(); err != nil {
   190  		return err
   191  	}
   192  
   193  	// Look through the sources and compile each of the subqueries (if they exist).
   194  	// We do this after compiling the outside because subqueries may require
   195  	// inherited state.
   196  	for _, source := range stmt.Sources {
   197  		switch source := source.(type) {
   198  		case *influxql.SubQuery:
   199  			source.Statement.OmitTime = true
   200  			if err := c.subquery(source.Statement); err != nil {
   201  				return err
   202  			}
   203  			source.Statement.RewriteRegexConditions()
   204  		}
   205  	}
   206  	return nil
   207  }
   208  
   209  func (c *compiledStatement) compileFields(stmt *influxql.SelectStatement) error {
   210  	valuer := MathValuer{}
   211  
   212  	c.Fields = make([]*compiledField, 0, len(stmt.Fields))
   213  	for _, f := range stmt.Fields {
   214  		// Remove any time selection (it is automatically selected by default)
   215  		// and set the time column name to the alias of the time field if it exists.
   216  		// Such as SELECT time, max(value) FROM cpu will be SELECT max(value) FROM cpu
   217  		// and SELECT time AS timestamp, max(value) FROM cpu will return "timestamp"
   218  		// as the column name for the time.
   219  		if ref, ok := f.Expr.(*influxql.VarRef); ok && ref.Val == "time" {
   220  			if f.Alias != "" {
   221  				c.TimeFieldName = f.Alias
   222  			}
   223  			continue
   224  		}
   225  
   226  		// Append this field to the list of processed fields and compile it.
   227  		f.Expr = influxql.Reduce(f.Expr, &valuer)
   228  		field := &compiledField{
   229  			global:        c,
   230  			Field:         f,
   231  			AllowWildcard: true,
   232  		}
   233  		c.Fields = append(c.Fields, field)
   234  		if err := field.compileExpr(field.Field.Expr); err != nil {
   235  			return err
   236  		}
   237  	}
   238  	return nil
   239  }
   240  
   241  type compiledField struct {
   242  	// This holds the global state from the compiled statement.
   243  	global *compiledStatement
   244  
   245  	// Field is the top level field that is being compiled.
   246  	Field *influxql.Field
   247  
   248  	// AllowWildcard is set to true if a wildcard or regular expression is allowed.
   249  	AllowWildcard bool
   250  }
   251  
   252  // compileExpr creates the node that executes the expression and connects that
   253  // node to the WriteEdge as the output.
   254  func (c *compiledField) compileExpr(expr influxql.Expr) error {
   255  	switch expr := expr.(type) {
   256  	case *influxql.VarRef:
   257  		// A bare variable reference will require auxiliary fields.
   258  		c.global.HasAuxiliaryFields = true
   259  		return nil
   260  	case *influxql.Wildcard:
   261  		// Wildcards use auxiliary fields. We assume there will be at least one
   262  		// expansion.
   263  		c.global.HasAuxiliaryFields = true
   264  		if !c.AllowWildcard {
   265  			return errors.New("unable to use wildcard in a binary expression")
   266  		}
   267  		return nil
   268  	case *influxql.RegexLiteral:
   269  		if !c.AllowWildcard {
   270  			return errors.New("unable to use regex in a binary expression")
   271  		}
   272  		c.global.HasAuxiliaryFields = true
   273  		return nil
   274  	case *influxql.Call:
   275  		if isMathFunction(expr) {
   276  			return c.compileMathFunction(expr)
   277  		}
   278  
   279  		// Register the function call in the list of function calls.
   280  		c.global.FunctionCalls = append(c.global.FunctionCalls, expr)
   281  
   282  		switch expr.Name {
   283  		case "percentile":
   284  			return c.compilePercentile(expr.Args)
   285  		case "sample":
   286  			return c.compileSample(expr.Args)
   287  		case "distinct":
   288  			return c.compileDistinct(expr.Args, false)
   289  		case "top", "bottom":
   290  			return c.compileTopBottom(expr)
   291  		case "derivative", "non_negative_derivative":
   292  			isNonNegative := expr.Name == "non_negative_derivative"
   293  			return c.compileDerivative(expr.Args, isNonNegative)
   294  		case "difference", "non_negative_difference":
   295  			isNonNegative := expr.Name == "non_negative_difference"
   296  			return c.compileDifference(expr.Args, isNonNegative)
   297  		case "cumulative_sum":
   298  			return c.compileCumulativeSum(expr.Args)
   299  		case "moving_average":
   300  			return c.compileMovingAverage(expr.Args)
   301  		case "exponential_moving_average", "double_exponential_moving_average", "triple_exponential_moving_average", "relative_strength_index", "triple_exponential_derivative":
   302  			return c.compileExponentialMovingAverage(expr.Name, expr.Args)
   303  		case "kaufmans_efficiency_ratio", "kaufmans_adaptive_moving_average":
   304  			return c.compileKaufmans(expr.Name, expr.Args)
   305  		case "chande_momentum_oscillator":
   306  			return c.compileChandeMomentumOscillator(expr.Args)
   307  		case "elapsed":
   308  			return c.compileElapsed(expr.Args)
   309  		case "integral":
   310  			return c.compileIntegral(expr.Args)
   311  		case "count_hll":
   312  			return c.compileCountHll(expr.Args)
   313  		case "holt_winters", "holt_winters_with_fit":
   314  			withFit := expr.Name == "holt_winters_with_fit"
   315  			return c.compileHoltWinters(expr.Args, withFit)
   316  		default:
   317  			return c.compileFunction(expr)
   318  		}
   319  	case *influxql.Distinct:
   320  		call := expr.NewCall()
   321  		c.global.FunctionCalls = append(c.global.FunctionCalls, call)
   322  		return c.compileDistinct(call.Args, false)
   323  	case *influxql.BinaryExpr:
   324  		// Disallow wildcards in binary expressions. RewriteFields, which expands
   325  		// wildcards, is too complicated if we allow wildcards inside of expressions.
   326  		c.AllowWildcard = false
   327  
   328  		// Check if either side is a literal so we only compile one side if it is.
   329  		if _, ok := expr.LHS.(influxql.Literal); ok {
   330  			if _, ok := expr.RHS.(influxql.Literal); ok {
   331  				return errors.New("cannot perform a binary expression on two literals")
   332  			}
   333  			return c.compileExpr(expr.RHS)
   334  		} else if _, ok := expr.RHS.(influxql.Literal); ok {
   335  			return c.compileExpr(expr.LHS)
   336  		} else {
   337  			// Validate both sides of the expression.
   338  			if err := c.compileExpr(expr.LHS); err != nil {
   339  				return err
   340  			}
   341  			if err := c.compileExpr(expr.RHS); err != nil {
   342  				return err
   343  			}
   344  			return nil
   345  		}
   346  	case *influxql.ParenExpr:
   347  		return c.compileExpr(expr.Expr)
   348  	case influxql.Literal:
   349  		return errors.New("field must contain at least one variable")
   350  	}
   351  	return errors.New("unimplemented")
   352  }
   353  
   354  // compileNestedExpr ensures that the expression is compiled as if it were
   355  // a nested expression.
   356  func (c *compiledField) compileNestedExpr(expr influxql.Expr) error {
   357  	// Intercept the distinct call so we can pass nested as true.
   358  	switch expr := expr.(type) {
   359  	case *influxql.Call:
   360  		if expr.Name == "distinct" {
   361  			return c.compileDistinct(expr.Args, true)
   362  		}
   363  	case *influxql.Distinct:
   364  		call := expr.NewCall()
   365  		return c.compileDistinct(call.Args, true)
   366  	}
   367  	return c.compileExpr(expr)
   368  }
   369  
   370  func (c *compiledField) compileSymbol(name string, field influxql.Expr) error {
   371  	// Must be a variable reference, wildcard, or regexp.
   372  	switch field.(type) {
   373  	case *influxql.VarRef:
   374  		return nil
   375  	case *influxql.Wildcard:
   376  		if !c.AllowWildcard {
   377  			return fmt.Errorf("unsupported expression with wildcard: %s()", name)
   378  		}
   379  		c.global.OnlySelectors = false
   380  		return nil
   381  	case *influxql.RegexLiteral:
   382  		if !c.AllowWildcard {
   383  			return fmt.Errorf("unsupported expression with regex field: %s()", name)
   384  		}
   385  		c.global.OnlySelectors = false
   386  		return nil
   387  	default:
   388  		return fmt.Errorf("expected field argument in %s()", name)
   389  	}
   390  }
   391  
   392  func (c *compiledField) compileFunction(expr *influxql.Call) error {
   393  	// Validate the function call and mark down some meta properties
   394  	// related to the function for query validation.
   395  	switch expr.Name {
   396  	case "max", "min", "first", "last":
   397  		// top/bottom are not included here since they are not typical functions.
   398  	case "count", "sum", "mean", "median", "mode", "stddev", "spread", "sum_hll":
   399  		// These functions are not considered selectors.
   400  		c.global.OnlySelectors = false
   401  	default:
   402  		return fmt.Errorf("undefined function %s()", expr.Name)
   403  	}
   404  
   405  	if exp, got := 1, len(expr.Args); exp != got {
   406  		return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, exp, got)
   407  	}
   408  
   409  	// If this is a call to count(), allow distinct() to be used as the function argument.
   410  	if expr.Name == "count" {
   411  		// If we have count(), the argument may be a distinct() call.
   412  		if arg0, ok := expr.Args[0].(*influxql.Call); ok && arg0.Name == "distinct" {
   413  			return c.compileDistinct(arg0.Args, true)
   414  		} else if arg0, ok := expr.Args[0].(*influxql.Distinct); ok {
   415  			call := arg0.NewCall()
   416  			return c.compileDistinct(call.Args, true)
   417  		}
   418  	}
   419  	return c.compileSymbol(expr.Name, expr.Args[0])
   420  }
   421  
   422  func (c *compiledField) compilePercentile(args []influxql.Expr) error {
   423  	if exp, got := 2, len(args); got != exp {
   424  		return fmt.Errorf("invalid number of arguments for percentile, expected %d, got %d", exp, got)
   425  	}
   426  
   427  	switch args[1].(type) {
   428  	case *influxql.IntegerLiteral:
   429  	case *influxql.NumberLiteral:
   430  	default:
   431  		return fmt.Errorf("expected float argument in percentile()")
   432  	}
   433  	return c.compileSymbol("percentile", args[0])
   434  }
   435  
   436  func (c *compiledField) compileSample(args []influxql.Expr) error {
   437  	if exp, got := 2, len(args); got != exp {
   438  		return fmt.Errorf("invalid number of arguments for sample, expected %d, got %d", exp, got)
   439  	}
   440  
   441  	switch arg1 := args[1].(type) {
   442  	case *influxql.IntegerLiteral:
   443  		if arg1.Val <= 0 {
   444  			return fmt.Errorf("sample window must be greater than 1, got %d", arg1.Val)
   445  		}
   446  	default:
   447  		return fmt.Errorf("expected integer argument in sample()")
   448  	}
   449  	return c.compileSymbol("sample", args[0])
   450  }
   451  
   452  func (c *compiledField) compileDerivative(args []influxql.Expr, isNonNegative bool) error {
   453  	name := "derivative"
   454  	if isNonNegative {
   455  		name = "non_negative_derivative"
   456  	}
   457  
   458  	if min, max, got := 1, 2, len(args); got > max || got < min {
   459  		return fmt.Errorf("invalid number of arguments for %s, expected at least %d but no more than %d, got %d", name, min, max, got)
   460  	}
   461  
   462  	// Retrieve the duration from the derivative() call, if specified.
   463  	if len(args) == 2 {
   464  		switch arg1 := args[1].(type) {
   465  		case *influxql.DurationLiteral:
   466  			if arg1.Val <= 0 {
   467  				return fmt.Errorf("duration argument must be positive, got %s", influxql.FormatDuration(arg1.Val))
   468  			}
   469  		default:
   470  			return fmt.Errorf("second argument to %s must be a duration, got %T", name, args[1])
   471  		}
   472  	}
   473  	c.global.OnlySelectors = false
   474  	if c.global.ExtraIntervals < 1 {
   475  		c.global.ExtraIntervals = 1
   476  	}
   477  
   478  	// Must be a variable reference, function, wildcard, or regexp.
   479  	switch arg0 := args[0].(type) {
   480  	case *influxql.Call:
   481  		if c.global.Interval.IsZero() {
   482  			return fmt.Errorf("%s aggregate requires a GROUP BY interval", name)
   483  		}
   484  		return c.compileNestedExpr(arg0)
   485  	default:
   486  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   487  			return fmt.Errorf("aggregate function required inside the call to %s", name)
   488  		}
   489  		return c.compileSymbol(name, arg0)
   490  	}
   491  }
   492  
   493  func (c *compiledField) compileElapsed(args []influxql.Expr) error {
   494  	if min, max, got := 1, 2, len(args); got > max || got < min {
   495  		return fmt.Errorf("invalid number of arguments for elapsed, expected at least %d but no more than %d, got %d", min, max, got)
   496  	}
   497  
   498  	// Retrieve the duration from the elapsed() call, if specified.
   499  	if len(args) == 2 {
   500  		switch arg1 := args[1].(type) {
   501  		case *influxql.DurationLiteral:
   502  			if arg1.Val <= 0 {
   503  				return fmt.Errorf("duration argument must be positive, got %s", influxql.FormatDuration(arg1.Val))
   504  			}
   505  		default:
   506  			return fmt.Errorf("second argument to elapsed must be a duration, got %T", args[1])
   507  		}
   508  	}
   509  	c.global.OnlySelectors = false
   510  	if c.global.ExtraIntervals < 1 {
   511  		c.global.ExtraIntervals = 1
   512  	}
   513  
   514  	// Must be a variable reference, function, wildcard, or regexp.
   515  	switch arg0 := args[0].(type) {
   516  	case *influxql.Call:
   517  		if c.global.Interval.IsZero() {
   518  			return fmt.Errorf("elapsed aggregate requires a GROUP BY interval")
   519  		}
   520  		return c.compileNestedExpr(arg0)
   521  	default:
   522  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   523  			return fmt.Errorf("aggregate function required inside the call to elapsed")
   524  		}
   525  		return c.compileSymbol("elapsed", arg0)
   526  	}
   527  }
   528  
   529  func (c *compiledField) compileDifference(args []influxql.Expr, isNonNegative bool) error {
   530  	name := "difference"
   531  	if isNonNegative {
   532  		name = "non_negative_difference"
   533  	}
   534  
   535  	if got := len(args); got != 1 {
   536  		return fmt.Errorf("invalid number of arguments for %s, expected 1, got %d", name, got)
   537  	}
   538  	c.global.OnlySelectors = false
   539  	if c.global.ExtraIntervals < 1 {
   540  		c.global.ExtraIntervals = 1
   541  	}
   542  
   543  	// Must be a variable reference, function, wildcard, or regexp.
   544  	switch arg0 := args[0].(type) {
   545  	case *influxql.Call:
   546  		if c.global.Interval.IsZero() {
   547  			return fmt.Errorf("%s aggregate requires a GROUP BY interval", name)
   548  		}
   549  		return c.compileNestedExpr(arg0)
   550  	default:
   551  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   552  			return fmt.Errorf("aggregate function required inside the call to %s", name)
   553  		}
   554  		return c.compileSymbol(name, arg0)
   555  	}
   556  }
   557  
   558  func (c *compiledField) compileCumulativeSum(args []influxql.Expr) error {
   559  	if got := len(args); got != 1 {
   560  		return fmt.Errorf("invalid number of arguments for cumulative_sum, expected 1, got %d", got)
   561  	}
   562  	c.global.OnlySelectors = false
   563  	if c.global.ExtraIntervals < 1 {
   564  		c.global.ExtraIntervals = 1
   565  	}
   566  
   567  	// Must be a variable reference, function, wildcard, or regexp.
   568  	switch arg0 := args[0].(type) {
   569  	case *influxql.Call:
   570  		if c.global.Interval.IsZero() {
   571  			return fmt.Errorf("cumulative_sum aggregate requires a GROUP BY interval")
   572  		}
   573  		return c.compileNestedExpr(arg0)
   574  	default:
   575  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   576  			return fmt.Errorf("aggregate function required inside the call to cumulative_sum")
   577  		}
   578  		return c.compileSymbol("cumulative_sum", arg0)
   579  	}
   580  }
   581  
   582  func (c *compiledField) compileMovingAverage(args []influxql.Expr) error {
   583  	if got := len(args); got != 2 {
   584  		return fmt.Errorf("invalid number of arguments for moving_average, expected 2, got %d", got)
   585  	}
   586  
   587  	arg1, ok := args[1].(*influxql.IntegerLiteral)
   588  	if !ok {
   589  		return fmt.Errorf("second argument for moving_average must be an integer, got %T", args[1])
   590  	} else if arg1.Val <= 1 {
   591  		return fmt.Errorf("moving_average window must be greater than 1, got %d", arg1.Val)
   592  	}
   593  	c.global.OnlySelectors = false
   594  	if c.global.ExtraIntervals < int(arg1.Val) {
   595  		c.global.ExtraIntervals = int(arg1.Val)
   596  	}
   597  
   598  	// Must be a variable reference, function, wildcard, or regexp.
   599  	switch arg0 := args[0].(type) {
   600  	case *influxql.Call:
   601  		if c.global.Interval.IsZero() {
   602  			return fmt.Errorf("moving_average aggregate requires a GROUP BY interval")
   603  		}
   604  		return c.compileNestedExpr(arg0)
   605  	default:
   606  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   607  			return fmt.Errorf("aggregate function required inside the call to moving_average")
   608  		}
   609  		return c.compileSymbol("moving_average", arg0)
   610  	}
   611  }
   612  
   613  func (c *compiledField) compileExponentialMovingAverage(name string, args []influxql.Expr) error {
   614  	if got := len(args); got < 2 || got > 4 {
   615  		return fmt.Errorf("invalid number of arguments for %s, expected at least 2 but no more than 4, got %d", name, got)
   616  	}
   617  
   618  	arg1, ok := args[1].(*influxql.IntegerLiteral)
   619  	if !ok {
   620  		return fmt.Errorf("%s period must be an integer", name)
   621  	} else if arg1.Val < 1 {
   622  		return fmt.Errorf("%s period must be greater than or equal to 1", name)
   623  	}
   624  
   625  	if len(args) >= 3 {
   626  		switch arg2 := args[2].(type) {
   627  		case *influxql.IntegerLiteral:
   628  			if name == "triple_exponential_derivative" && arg2.Val < 1 && arg2.Val != -1 {
   629  				return fmt.Errorf("%s hold period must be greater than or equal to 1", name)
   630  			}
   631  			if arg2.Val < 0 && arg2.Val != -1 {
   632  				return fmt.Errorf("%s hold period must be greater than or equal to 0", name)
   633  			}
   634  		default:
   635  			return fmt.Errorf("%s hold period must be an integer", name)
   636  		}
   637  	}
   638  
   639  	if len(args) >= 4 {
   640  		switch arg3 := args[3].(type) {
   641  		case *influxql.StringLiteral:
   642  			switch arg3.Val {
   643  			case "exponential", "simple":
   644  			default:
   645  				return fmt.Errorf("%s warmup type must be one of: 'exponential' 'simple'", name)
   646  			}
   647  		default:
   648  			return fmt.Errorf("%s warmup type must be a string", name)
   649  		}
   650  	}
   651  
   652  	c.global.OnlySelectors = false
   653  	if c.global.ExtraIntervals < int(arg1.Val) {
   654  		c.global.ExtraIntervals = int(arg1.Val)
   655  	}
   656  
   657  	switch arg0 := args[0].(type) {
   658  	case *influxql.Call:
   659  		if c.global.Interval.IsZero() {
   660  			return fmt.Errorf("%s aggregate requires a GROUP BY interval", name)
   661  		}
   662  		return c.compileExpr(arg0)
   663  	default:
   664  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   665  			return fmt.Errorf("aggregate function required inside the call to %s", name)
   666  		}
   667  		return c.compileSymbol(name, arg0)
   668  	}
   669  }
   670  
   671  func (c *compiledField) compileKaufmans(name string, args []influxql.Expr) error {
   672  	if got := len(args); got < 2 || got > 3 {
   673  		return fmt.Errorf("invalid number of arguments for %s, expected at least 2 but no more than 3, got %d", name, got)
   674  	}
   675  
   676  	arg1, ok := args[1].(*influxql.IntegerLiteral)
   677  	if !ok {
   678  		return fmt.Errorf("%s period must be an integer", name)
   679  	} else if arg1.Val < 1 {
   680  		return fmt.Errorf("%s period must be greater than or equal to 1", name)
   681  	}
   682  
   683  	if len(args) >= 3 {
   684  		switch arg2 := args[2].(type) {
   685  		case *influxql.IntegerLiteral:
   686  			if arg2.Val < 0 && arg2.Val != -1 {
   687  				return fmt.Errorf("%s hold period must be greater than or equal to 0", name)
   688  			}
   689  		default:
   690  			return fmt.Errorf("%s hold period must be an integer", name)
   691  		}
   692  	}
   693  
   694  	c.global.OnlySelectors = false
   695  	if c.global.ExtraIntervals < int(arg1.Val) {
   696  		c.global.ExtraIntervals = int(arg1.Val)
   697  	}
   698  
   699  	switch arg0 := args[0].(type) {
   700  	case *influxql.Call:
   701  		if c.global.Interval.IsZero() {
   702  			return fmt.Errorf("%s aggregate requires a GROUP BY interval", name)
   703  		}
   704  		return c.compileExpr(arg0)
   705  	default:
   706  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   707  			return fmt.Errorf("aggregate function required inside the call to %s", name)
   708  		}
   709  		return c.compileSymbol(name, arg0)
   710  	}
   711  }
   712  
   713  func (c *compiledField) compileChandeMomentumOscillator(args []influxql.Expr) error {
   714  	if got := len(args); got < 2 || got > 4 {
   715  		return fmt.Errorf("invalid number of arguments for chande_momentum_oscillator, expected at least 2 but no more than 4, got %d", got)
   716  	}
   717  
   718  	arg1, ok := args[1].(*influxql.IntegerLiteral)
   719  	if !ok {
   720  		return fmt.Errorf("chande_momentum_oscillator period must be an integer")
   721  	} else if arg1.Val < 1 {
   722  		return fmt.Errorf("chande_momentum_oscillator period must be greater than or equal to 1")
   723  	}
   724  
   725  	if len(args) >= 3 {
   726  		switch arg2 := args[2].(type) {
   727  		case *influxql.IntegerLiteral:
   728  			if arg2.Val < 0 && arg2.Val != -1 {
   729  				return fmt.Errorf("chande_momentum_oscillator hold period must be greater than or equal to 0")
   730  			}
   731  		default:
   732  			return fmt.Errorf("chande_momentum_oscillator hold period must be an integer")
   733  		}
   734  	}
   735  
   736  	c.global.OnlySelectors = false
   737  	if c.global.ExtraIntervals < int(arg1.Val) {
   738  		c.global.ExtraIntervals = int(arg1.Val)
   739  	}
   740  
   741  	if len(args) >= 4 {
   742  		switch arg3 := args[3].(type) {
   743  		case *influxql.StringLiteral:
   744  			switch arg3.Val {
   745  			case "none", "exponential", "simple":
   746  			default:
   747  				return fmt.Errorf("chande_momentum_oscillator warmup type must be one of: 'none' 'exponential' 'simple'")
   748  			}
   749  		default:
   750  			return fmt.Errorf("chande_momentum_oscillator warmup type must be a string")
   751  		}
   752  	}
   753  
   754  	switch arg0 := args[0].(type) {
   755  	case *influxql.Call:
   756  		if c.global.Interval.IsZero() {
   757  			return fmt.Errorf("chande_momentum_oscillator aggregate requires a GROUP BY interval")
   758  		}
   759  		return c.compileExpr(arg0)
   760  	default:
   761  		if !c.global.Interval.IsZero() && !c.global.InheritedInterval {
   762  			return fmt.Errorf("aggregate function required inside the call to chande_momentum_oscillator")
   763  		}
   764  		return c.compileSymbol("chande_momentum_oscillator", arg0)
   765  	}
   766  }
   767  
   768  func (c *compiledField) compileIntegral(args []influxql.Expr) error {
   769  	if min, max, got := 1, 2, len(args); got > max || got < min {
   770  		return fmt.Errorf("invalid number of arguments for integral, expected at least %d but no more than %d, got %d", min, max, got)
   771  	}
   772  
   773  	if len(args) == 2 {
   774  		switch arg1 := args[1].(type) {
   775  		case *influxql.DurationLiteral:
   776  			if arg1.Val <= 0 {
   777  				return fmt.Errorf("duration argument must be positive, got %s", influxql.FormatDuration(arg1.Val))
   778  			}
   779  		default:
   780  			return errors.New("second argument must be a duration")
   781  		}
   782  	}
   783  	c.global.OnlySelectors = false
   784  
   785  	// Must be a variable reference, wildcard, or regexp.
   786  	return c.compileSymbol("integral", args[0])
   787  }
   788  
   789  func (c *compiledField) compileCountHll(args []influxql.Expr) error {
   790  	if exp, got := 1, len(args); exp != got {
   791  		return fmt.Errorf("invalid number of arguments for count_hll, expected %d, got %d", exp, got)
   792  	}
   793  	c.global.OnlySelectors = false
   794  	switch arg0 := args[0].(type) {
   795  	case *influxql.Call:
   796  		return c.compileExpr(arg0)
   797  	default:
   798  		return c.compileSymbol("count_hll", arg0)
   799  	}
   800  }
   801  
   802  func (c *compiledField) compileHoltWinters(args []influxql.Expr, withFit bool) error {
   803  	name := "holt_winters"
   804  	if withFit {
   805  		name = "holt_winters_with_fit"
   806  	}
   807  
   808  	if exp, got := 3, len(args); got != exp {
   809  		return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", name, exp, got)
   810  	}
   811  
   812  	n, ok := args[1].(*influxql.IntegerLiteral)
   813  	if !ok {
   814  		return fmt.Errorf("expected integer argument as second arg in %s", name)
   815  	} else if n.Val <= 0 {
   816  		return fmt.Errorf("second arg to %s must be greater than 0, got %d", name, n.Val)
   817  	}
   818  
   819  	s, ok := args[2].(*influxql.IntegerLiteral)
   820  	if !ok {
   821  		return fmt.Errorf("expected integer argument as third arg in %s", name)
   822  	} else if s.Val < 0 {
   823  		return fmt.Errorf("third arg to %s cannot be negative, got %d", name, s.Val)
   824  	}
   825  	c.global.OnlySelectors = false
   826  
   827  	call, ok := args[0].(*influxql.Call)
   828  	if !ok {
   829  		return fmt.Errorf("must use aggregate function with %s", name)
   830  	} else if c.global.Interval.IsZero() {
   831  		return fmt.Errorf("%s aggregate requires a GROUP BY interval", name)
   832  	}
   833  	return c.compileNestedExpr(call)
   834  }
   835  
   836  func (c *compiledField) compileDistinct(args []influxql.Expr, nested bool) error {
   837  	if len(args) == 0 {
   838  		return errors.New("distinct function requires at least one argument")
   839  	} else if len(args) != 1 {
   840  		return errors.New("distinct function can only have one argument")
   841  	}
   842  
   843  	if _, ok := args[0].(*influxql.VarRef); !ok {
   844  		return errors.New("expected field argument in distinct()")
   845  	}
   846  	if !nested {
   847  		c.global.HasDistinct = true
   848  	}
   849  	c.global.OnlySelectors = false
   850  	return nil
   851  }
   852  
   853  func (c *compiledField) compileTopBottom(call *influxql.Call) error {
   854  	if c.global.TopBottomFunction != "" {
   855  		return fmt.Errorf("selector function %s() cannot be combined with other functions", c.global.TopBottomFunction)
   856  	}
   857  
   858  	if exp, got := 2, len(call.Args); got < exp {
   859  		return fmt.Errorf("invalid number of arguments for %s, expected at least %d, got %d", call.Name, exp, got)
   860  	}
   861  
   862  	limit, ok := call.Args[len(call.Args)-1].(*influxql.IntegerLiteral)
   863  	if !ok {
   864  		return fmt.Errorf("expected integer as last argument in %s(), found %s", call.Name, call.Args[len(call.Args)-1])
   865  	} else if limit.Val <= 0 {
   866  		return fmt.Errorf("limit (%d) in %s function must be at least 1", limit.Val, call.Name)
   867  	} else if c.global.Limit > 0 && int(limit.Val) > c.global.Limit {
   868  		return fmt.Errorf("limit (%d) in %s function can not be larger than the LIMIT (%d) in the select statement", limit.Val, call.Name, c.global.Limit)
   869  	}
   870  
   871  	if _, ok := call.Args[0].(*influxql.VarRef); !ok {
   872  		return fmt.Errorf("expected first argument to be a field in %s(), found %s", call.Name, call.Args[0])
   873  	}
   874  
   875  	if len(call.Args) > 2 {
   876  		for _, v := range call.Args[1 : len(call.Args)-1] {
   877  			ref, ok := v.(*influxql.VarRef)
   878  			if !ok {
   879  				return fmt.Errorf("only fields or tags are allowed in %s(), found %s", call.Name, v)
   880  			}
   881  
   882  			// Add a field for each of the listed dimensions when not writing the results.
   883  			if !c.global.HasTarget {
   884  				field := &compiledField{
   885  					global: c.global,
   886  					Field:  &influxql.Field{Expr: ref},
   887  				}
   888  				c.global.Fields = append(c.global.Fields, field)
   889  				if err := field.compileExpr(ref); err != nil {
   890  					return err
   891  				}
   892  			}
   893  		}
   894  	}
   895  	c.global.TopBottomFunction = call.Name
   896  	return nil
   897  }
   898  
   899  func (c *compiledField) compileMathFunction(expr *influxql.Call) error {
   900  	// How many arguments are we expecting?
   901  	nargs := 1
   902  	switch expr.Name {
   903  	case "atan2", "pow", "log":
   904  		nargs = 2
   905  	}
   906  
   907  	// Did we get the expected number of args?
   908  	if got := len(expr.Args); got != nargs {
   909  		return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, nargs, got)
   910  	}
   911  
   912  	// Compile all the argument expressions that are not just literals.
   913  	for _, arg := range expr.Args {
   914  		if _, ok := arg.(influxql.Literal); ok {
   915  			continue
   916  		}
   917  		if err := c.compileExpr(arg); err != nil {
   918  			return err
   919  		}
   920  	}
   921  	return nil
   922  }
   923  
   924  func (c *compiledStatement) compileDimensions(stmt *influxql.SelectStatement) error {
   925  	for _, d := range stmt.Dimensions {
   926  		// Reduce the expression before attempting anything. Do not evaluate the call.
   927  		expr := influxql.Reduce(d.Expr, nil)
   928  
   929  		switch expr := expr.(type) {
   930  		case *influxql.VarRef:
   931  			if strings.EqualFold(expr.Val, "time") {
   932  				return errors.New("time() is a function and expects at least one argument")
   933  			}
   934  		case *influxql.Call:
   935  			// Ensure the call is time() and it has one or two duration arguments.
   936  			// If we already have a duration
   937  			if expr.Name != "time" {
   938  				return errors.New("only time() calls allowed in dimensions")
   939  			} else if got := len(expr.Args); got < 1 || got > 2 {
   940  				return errors.New("time dimension expected 1 or 2 arguments")
   941  			} else if lit, ok := expr.Args[0].(*influxql.DurationLiteral); !ok {
   942  				return errors.New("time dimension must have duration argument")
   943  			} else if c.Interval.Duration != 0 {
   944  				return errors.New("multiple time dimensions not allowed")
   945  			} else {
   946  				c.Interval.Duration = lit.Val
   947  				if len(expr.Args) == 2 {
   948  					switch lit := expr.Args[1].(type) {
   949  					case *influxql.DurationLiteral:
   950  						c.Interval.Offset = lit.Val % c.Interval.Duration
   951  					case *influxql.TimeLiteral:
   952  						c.Interval.Offset = lit.Val.Sub(lit.Val.Truncate(c.Interval.Duration))
   953  					case *influxql.Call:
   954  						if lit.Name != "now" {
   955  							return errors.New("time dimension offset function must be now()")
   956  						} else if len(lit.Args) != 0 {
   957  							return errors.New("time dimension offset now() function requires no arguments")
   958  						}
   959  						now := c.Options.Now
   960  						c.Interval.Offset = now.Sub(now.Truncate(c.Interval.Duration))
   961  
   962  						// Use the evaluated offset to replace the argument. Ideally, we would
   963  						// use the interval assigned above, but the query engine hasn't been changed
   964  						// to use the compiler information yet.
   965  						expr.Args[1] = &influxql.DurationLiteral{Val: c.Interval.Offset}
   966  					case *influxql.StringLiteral:
   967  						// If literal looks like a date time then parse it as a time literal.
   968  						if lit.IsTimeLiteral() {
   969  							t, err := lit.ToTimeLiteral(stmt.Location)
   970  							if err != nil {
   971  								return err
   972  							}
   973  							c.Interval.Offset = t.Val.Sub(t.Val.Truncate(c.Interval.Duration))
   974  						} else {
   975  							return errors.New("time dimension offset must be duration or now()")
   976  						}
   977  					default:
   978  						return errors.New("time dimension offset must be duration or now()")
   979  					}
   980  				}
   981  			}
   982  		case *influxql.Wildcard:
   983  		case *influxql.RegexLiteral:
   984  		default:
   985  			return errors.New("only time and tag dimensions allowed")
   986  		}
   987  
   988  		// Assign the reduced/changed expression to the dimension.
   989  		d.Expr = expr
   990  	}
   991  	return nil
   992  }
   993  
   994  // validateFields validates that the fields are mutually compatible with each other.
   995  // This runs at the end of compilation but before linking.
   996  func (c *compiledStatement) validateFields() error {
   997  	// Validate that at least one field has been selected.
   998  	if len(c.Fields) == 0 {
   999  		return errors.New("at least 1 non-time field must be queried")
  1000  	}
  1001  	// Ensure there are not multiple calls if top/bottom is present.
  1002  	if len(c.FunctionCalls) > 1 && c.TopBottomFunction != "" {
  1003  		return fmt.Errorf("selector function %s() cannot be combined with other functions", c.TopBottomFunction)
  1004  	} else if len(c.FunctionCalls) == 0 {
  1005  		switch c.FillOption {
  1006  		case influxql.NoFill:
  1007  			return errors.New("fill(none) must be used with a function")
  1008  		case influxql.LinearFill:
  1009  			return errors.New("fill(linear) must be used with a function")
  1010  		}
  1011  		if !c.Interval.IsZero() && !c.InheritedInterval {
  1012  			return errors.New("GROUP BY requires at least one aggregate function")
  1013  		}
  1014  	}
  1015  	// If a distinct() call is present, ensure there is exactly one function.
  1016  	if c.HasDistinct && (len(c.FunctionCalls) != 1 || c.HasAuxiliaryFields) {
  1017  		return errors.New("aggregate function distinct() cannot be combined with other functions or fields")
  1018  	}
  1019  	// Validate we are using a selector or raw query if auxiliary fields are required.
  1020  	if c.HasAuxiliaryFields {
  1021  		if !c.OnlySelectors {
  1022  			return fmt.Errorf("mixing aggregate and non-aggregate queries is not supported")
  1023  		} else if len(c.FunctionCalls) > 1 {
  1024  			return fmt.Errorf("mixing multiple selector functions with tags or fields is not supported")
  1025  		}
  1026  	}
  1027  	return nil
  1028  }
  1029  
  1030  // validateCondition verifies that all elements in the condition are appropriate.
  1031  // For example, aggregate calls don't work in the condition and should throw an
  1032  // error as an invalid expression.
  1033  func (c *compiledStatement) validateCondition(expr influxql.Expr) error {
  1034  	switch expr := expr.(type) {
  1035  	case *influxql.BinaryExpr:
  1036  		// Verify each side of the binary expression. We do not need to
  1037  		// verify the binary expression itself since that should have been
  1038  		// done by influxql.ConditionExpr.
  1039  		if err := c.validateCondition(expr.LHS); err != nil {
  1040  			return err
  1041  		}
  1042  		if err := c.validateCondition(expr.RHS); err != nil {
  1043  			return err
  1044  		}
  1045  		return nil
  1046  	case *influxql.Call:
  1047  		if !isMathFunction(expr) {
  1048  			return fmt.Errorf("invalid function call in condition: %s", expr)
  1049  		}
  1050  
  1051  		// How many arguments are we expecting?
  1052  		nargs := 1
  1053  		switch expr.Name {
  1054  		case "atan2", "pow":
  1055  			nargs = 2
  1056  		}
  1057  
  1058  		// Did we get the expected number of args?
  1059  		if got := len(expr.Args); got != nargs {
  1060  			return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, nargs, got)
  1061  		}
  1062  
  1063  		// Are all the args valid?
  1064  		for _, arg := range expr.Args {
  1065  			if err := c.validateCondition(arg); err != nil {
  1066  				return err
  1067  			}
  1068  		}
  1069  		return nil
  1070  	default:
  1071  		return nil
  1072  	}
  1073  }
  1074  
  1075  // subquery compiles and validates a compiled statement for the subquery using
  1076  // this compiledStatement as the parent.
  1077  func (c *compiledStatement) subquery(stmt *influxql.SelectStatement) error {
  1078  	subquery := newCompiler(c.Options)
  1079  	if err := subquery.preprocess(stmt); err != nil {
  1080  		return err
  1081  	}
  1082  
  1083  	// Substitute now() into the subquery condition. Then use ConditionExpr to
  1084  	// validate the expression. Do not store the results. We have no way to store
  1085  	// and read those results at the moment.
  1086  	valuer := influxql.MultiValuer(
  1087  		&influxql.NowValuer{Now: c.Options.Now, Location: stmt.Location},
  1088  		&MathValuer{},
  1089  	)
  1090  	stmt.Condition = influxql.Reduce(stmt.Condition, valuer)
  1091  
  1092  	// If the ordering is different and the sort field was specified for the subquery,
  1093  	// throw an error.
  1094  	if len(stmt.SortFields) != 0 && subquery.Ascending != c.Ascending {
  1095  		return errors.New("subqueries must be ordered in the same direction as the query itself")
  1096  	}
  1097  	subquery.Ascending = c.Ascending
  1098  
  1099  	// Find the intersection between this time range and the parent.
  1100  	// If the subquery doesn't have a time range, this causes it to
  1101  	// inherit the parent's time range.
  1102  	subquery.TimeRange = subquery.TimeRange.Intersect(c.TimeRange)
  1103  
  1104  	// If the fill option is null, set it to none so we don't waste time on
  1105  	// null values with a redundant fill iterator.
  1106  	if !subquery.Interval.IsZero() && subquery.FillOption == influxql.NullFill {
  1107  		subquery.FillOption = influxql.NoFill
  1108  	}
  1109  
  1110  	// Inherit the grouping interval if the subquery has none.
  1111  	if !c.Interval.IsZero() && subquery.Interval.IsZero() {
  1112  		subquery.Interval = c.Interval
  1113  		subquery.InheritedInterval = true
  1114  	}
  1115  	return subquery.compile(stmt)
  1116  }
  1117  
  1118  func (c *compiledStatement) Prepare(ctx context.Context, shardMapper ShardMapper, sopt SelectOptions) (PreparedStatement, error) {
  1119  	// If this is a query with a grouping, there is a bucket limit, and the minimum time has not been specified,
  1120  	// we need to limit the possible time range that can be used when mapping shards but not when actually executing
  1121  	// the select statement. Determine the shard time range here.
  1122  	timeRange := c.TimeRange
  1123  	if sopt.MaxBucketsN > 0 && !c.stmt.IsRawQuery && timeRange.MinTimeNano() == influxql.MinTime {
  1124  		interval, err := c.stmt.GroupByInterval()
  1125  		if err != nil {
  1126  			return nil, err
  1127  		}
  1128  
  1129  		offset, err := c.stmt.GroupByOffset()
  1130  		if err != nil {
  1131  			return nil, err
  1132  		}
  1133  
  1134  		if interval > 0 {
  1135  			// Determine the last bucket using the end time.
  1136  			opt := IteratorOptions{
  1137  				Interval: Interval{
  1138  					Duration: interval,
  1139  					Offset:   offset,
  1140  				},
  1141  			}
  1142  			last, _ := opt.Window(c.TimeRange.MaxTimeNano() - 1)
  1143  
  1144  			// Determine the time difference using the number of buckets.
  1145  			// Determine the maximum difference between the buckets based on the end time.
  1146  			maxDiff := last - models.MinNanoTime
  1147  			if maxDiff/int64(interval) > int64(sopt.MaxBucketsN) {
  1148  				timeRange.Min = time.Unix(0, models.MinNanoTime)
  1149  			} else {
  1150  				timeRange.Min = time.Unix(0, last-int64(interval)*int64(sopt.MaxBucketsN-1))
  1151  			}
  1152  		}
  1153  	}
  1154  
  1155  	// Modify the time range if there are extra intervals and an interval.
  1156  	if !c.Interval.IsZero() && c.ExtraIntervals > 0 {
  1157  		if c.Ascending {
  1158  			newTime := timeRange.Min.Add(time.Duration(-c.ExtraIntervals) * c.Interval.Duration)
  1159  			if !newTime.Before(time.Unix(0, influxql.MinTime).UTC()) {
  1160  				timeRange.Min = newTime
  1161  			} else {
  1162  				timeRange.Min = time.Unix(0, influxql.MinTime).UTC()
  1163  			}
  1164  		} else {
  1165  			newTime := timeRange.Max.Add(time.Duration(c.ExtraIntervals) * c.Interval.Duration)
  1166  			if !newTime.After(time.Unix(0, influxql.MaxTime).UTC()) {
  1167  				timeRange.Max = newTime
  1168  			} else {
  1169  				timeRange.Max = time.Unix(0, influxql.MaxTime).UTC()
  1170  			}
  1171  		}
  1172  	}
  1173  
  1174  	// Create an iterator creator based on the shards in the cluster.
  1175  	shards, err := shardMapper.MapShards(ctx, c.stmt.Sources, timeRange, sopt)
  1176  	if err != nil {
  1177  		return nil, err
  1178  	}
  1179  
  1180  	// Rewrite wildcards, if any exist.
  1181  	mapper := queryFieldMapper{FieldMapper: newFieldMapperAdapter(shards, ctx)}
  1182  	stmt, err := c.stmt.RewriteFields(mapper)
  1183  	if err != nil {
  1184  		shards.Close()
  1185  		return nil, err
  1186  	}
  1187  
  1188  	// Validate if the types are correct now that they have been assigned.
  1189  	if err := validateTypes(stmt); err != nil {
  1190  		shards.Close()
  1191  		return nil, err
  1192  	}
  1193  
  1194  	// Determine base options for iterators.
  1195  	opt, err := newIteratorOptionsStmt(stmt, sopt)
  1196  	if err != nil {
  1197  		shards.Close()
  1198  		return nil, err
  1199  	}
  1200  	opt.StartTime, opt.EndTime = c.TimeRange.MinTimeNano(), c.TimeRange.MaxTimeNano()
  1201  	opt.Ascending = c.Ascending
  1202  
  1203  	if sopt.MaxBucketsN > 0 && !stmt.IsRawQuery && c.TimeRange.MinTimeNano() > influxql.MinTime {
  1204  		interval, err := stmt.GroupByInterval()
  1205  		if err != nil {
  1206  			shards.Close()
  1207  			return nil, err
  1208  		}
  1209  
  1210  		if interval > 0 {
  1211  			// Determine the start and end time matched to the interval (may not match the actual times).
  1212  			first, _ := opt.Window(opt.StartTime)
  1213  			last, _ := opt.Window(opt.EndTime - 1)
  1214  
  1215  			// Determine the number of buckets by finding the time span and dividing by the interval.
  1216  			buckets := (last - first + int64(interval)) / int64(interval)
  1217  			if int(buckets) > sopt.MaxBucketsN {
  1218  				shards.Close()
  1219  				return nil, fmt.Errorf("max-select-buckets limit exceeded: (%d/%d)", buckets, sopt.MaxBucketsN)
  1220  			}
  1221  		}
  1222  	}
  1223  
  1224  	columns := stmt.ColumnNames()
  1225  	return &preparedStatement{
  1226  		stmt:      stmt,
  1227  		opt:       opt,
  1228  		ic:        shards,
  1229  		columns:   columns,
  1230  		maxPointN: sopt.MaxPointN,
  1231  		now:       c.Options.Now,
  1232  	}, nil
  1233  }